Towards GPL
[idzebra-moved-to-github.git] / index / trav.c
index 49af41e..1143d1e 100644 (file)
-/*
- * Copyright (C) 1994-1998, Index Data I/S 
- * All rights reserved.
- * Sebastian Hammer, Adam Dickmeiss
- *
- * $Log: trav.c,v $
- * Revision 1.33  1998-01-12 15:04:08  adam
- * The test option (-s) only uses read-lock (and not write lock).
- *
- * Revision 1.32  1997/09/25 14:56:51  adam
- * Windows NT interface code to the stat call.
- *
- * Revision 1.31  1997/09/17 12:19:17  adam
- * Zebra version corresponds to YAZ version 1.4.
- * Changed Zebra server so that it doesn't depend on global common_resource.
- *
- * Revision 1.30  1997/09/09 13:38:09  adam
- * Partial port to WIN95/NT.
- *
- * Revision 1.29  1997/02/12 20:39:47  adam
- * Implemented options -f <n> that limits the log to the first <n>
- * records.
- * Changed some log messages also.
- *
- * Revision 1.28  1996/11/01 08:58:44  adam
- * Interface to isamc system now includes update and delete.
- *
- * Revision 1.27  1996/10/29 14:06:56  adam
- * Include zebrautl.h instead of alexutil.h.
- *
- * Revision 1.26  1996/06/04 10:19:01  adam
- * Minor changes - removed include of ctype.h.
- *
- * Revision 1.25  1996/05/01  13:46:37  adam
- * First work on multiple records in one file.
- * New option, -offset, to the "unread" command in the filter module.
- *
- * Revision 1.24  1996/04/26  10:00:23  adam
- * Added option -V to zebraidx to display version information.
- * Removed stupid warnings from file update.
- *
- * Revision 1.23  1996/04/12  07:02:25  adam
- * File update of single files.
- *
- * Revision 1.22  1996/04/09 06:50:50  adam
- * Bug fix: bad reference in function fileUpdateR.
- *
- * Revision 1.21  1996/03/22 15:34:18  quinn
- * Fixed bad reference
- *
- * Revision 1.20  1996/03/21  14:50:10  adam
- * File update uses modify-time instead of change-time.
- *
- * Revision 1.19  1996/03/20  16:16:55  quinn
- * Added diagnostic output
- *
- * Revision 1.18  1996/03/19  12:43:27  adam
- * Bug fix: File update traversal didn't handle trailing slashes correctly.
- * Bug fix: Update of sub directory groups wasn't handled correctly.
- *
- * Revision 1.17  1996/02/12  18:45:17  adam
- * Changed naming of some functions.
- *
- * Revision 1.16  1996/02/05  12:30:02  adam
- * Logging reduced a bit.
- * The remaining running time is estimated during register merge.
- *
- * Revision 1.15  1995/12/07  17:38:48  adam
- * Work locking mechanisms for concurrent updates/commit.
- *
- * Revision 1.14  1995/12/06  12:41:26  adam
- * New command 'stat' for the index program.
- * Filenames can be read from stdin by specifying '-'.
- * Bug fix/enhancement of the transformation from terms to regular
- * expressons in the search engine.
- *
- * Revision 1.13  1995/11/28  09:09:46  adam
- * Zebra config renamed.
- * Use setting 'recordId' to identify record now.
- * Bug fix in recindex.c: rec_release_blocks was invokeded even
- * though the blocks were already released.
- * File traversal properly deletes records when needed.
- *
- * Revision 1.12  1995/11/24  11:31:37  adam
- * Commands add & del read filenames from stdin if source directory is
- * empty.
- * Match criteria supports 'constant' strings.
- *
- * Revision 1.11  1995/11/22  17:19:19  adam
- * Record management uses the bfile system.
- *
- * Revision 1.10  1995/11/21  15:01:16  adam
- * New general match criteria implemented.
- * New feature: document groups.
- *
- * Revision 1.9  1995/11/21  09:20:32  adam
- * Yet more work on record match.
- *
- * Revision 1.8  1995/11/20  16:59:46  adam
- * New update method: the 'old' keys are saved for each records.
- *
- * Revision 1.7  1995/11/20  11:56:28  adam
- * Work on new traversal.
- *
- * Revision 1.6  1995/11/17  15:54:42  adam
- * Started work on virtual directory structure.
- *
- * Revision 1.5  1995/10/17  18:02:09  adam
- * New feature: databases. Implemented as prefix to words in dictionary.
- *
- * Revision 1.4  1995/09/28  09:19:46  adam
- * xfree/xmalloc used everywhere.
- * Extract/retrieve method seems to work for text records.
- *
- * Revision 1.3  1995/09/06  16:11:18  adam
- * Option: only one word key per file.
- *
- * Revision 1.2  1995/09/04  12:33:43  adam
- * Various cleanup. YAZ util used instead.
- *
- * Revision 1.1  1995/09/01  14:06:36  adam
- * Split of work into more files.
- *
- */
+/* $Id: trav.c,v 1.40 2002-08-02 19:26:55 adam Exp $
+   Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
+   Index Data Aps
+
+This file is part of the Zebra server.
+
+Zebra is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Zebra; see the file LICENSE.zebra.  If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+*/
+
+
 
 
 #include <stdio.h>
 #include <assert.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#ifdef WINDOWS
+#ifdef WIN32
 #include <io.h>
 #define S_ISREG(x) (x & _S_IFREG)
 #define S_ISDIR(x) (x & _S_IFDIR)
@@ -148,14 +47,15 @@ static int repComp (const char *a, const char *b, size_t len)
     return memcmp (a, b, len);
 }
 
-static void repositoryExtractR (int deleteFlag, char *rep,
-                                struct recordGroup *rGroup)
+static void repositoryExtractR (ZebraHandle zh, int deleteFlag, char *rep,
+                                struct recordGroup *rGroup,
+                               int level)
 {
     struct dir_entry *e;
     int i;
     size_t rep_len = strlen (rep);
 
-    e = dir_open (rep);
+    e = dir_open (rep, zh->path_reg);
     if (!e)
         return;
     logf (LOG_LOG, "dir %s", rep);
@@ -163,16 +63,23 @@ static void repositoryExtractR (int deleteFlag, char *rep,
         rep[rep_len] = '/';
     else
         --rep_len;
+    
     for (i=0; e[i].name; i++)
     {
+       char *ecp;
         strcpy (rep +rep_len+1, e[i].name);
+       if ((ecp = strrchr (e[i].name, '/')))
+           *ecp = '\0';
+       if (level == 0 && rGroup->databaseNamePath)
+           rGroup->databaseName = e[i].name;
+
         switch (e[i].kind)
         {
         case dirs_file:
-            fileExtract (NULL, rep, rGroup, deleteFlag);
+            fileExtract (zh, NULL, rep, rGroup, deleteFlag);
             break;
         case dirs_dir:
-            repositoryExtractR (deleteFlag, rep, rGroup);
+            repositoryExtractR (zh, deleteFlag, rep, rGroup, level+1);
             break;
         }
     }
@@ -180,9 +87,10 @@ static void repositoryExtractR (int deleteFlag, char *rep,
 
 }
 
-static void fileDeleteR (struct dirs_info *di, struct dirs_entry *dst,
-                              const char *base, char *src,
-                              struct recordGroup *rGroup)
+static void fileDeleteR (ZebraHandle zh,
+                         struct dirs_info *di, struct dirs_entry *dst,
+                         const char *base, char *src,
+                         struct recordGroup *rGroup)
 {
     char tmppath[1024];
     size_t src_len = strlen (src);
@@ -193,7 +101,7 @@ static void fileDeleteR (struct dirs_info *di, struct dirs_entry *dst,
         {
         case dirs_file:
             sprintf (tmppath, "%s%s", base, dst->path);
-            fileExtract (&dst->sysno, tmppath, rGroup, 1);
+            fileExtract (zh, &dst->sysno, tmppath, rGroup, 1);
              
             strcpy (tmppath, dst->path);
             dst = dirs_read (di); 
@@ -210,9 +118,11 @@ static void fileDeleteR (struct dirs_info *di, struct dirs_entry *dst,
     }
 }
 
-static void fileUpdateR (struct dirs_info *di, struct dirs_entry *dst,
-                               const char *base, char *src, 
-                               struct recordGroup *rGroup)
+static void fileUpdateR (ZebraHandle zh,
+                         struct dirs_info *di, struct dirs_entry *dst,
+                        const char *base, char *src, 
+                        struct recordGroup *rGroup,
+                        int level)
 {
     struct dir_entry *e_src;
     int i_src = 0;
@@ -220,7 +130,7 @@ static void fileUpdateR (struct dirs_info *di, struct dirs_entry *dst,
     size_t src_len = strlen (src);
 
     sprintf (tmppath, "%s%s", base, src);
-    e_src = dir_open (tmppath);
+    e_src = dir_open (tmppath, zh->path_reg);
     logf (LOG_LOG, "dir %s", tmppath);
 
 #if 0
@@ -244,7 +154,7 @@ static void fileUpdateR (struct dirs_info *di, struct dirs_entry *dst,
     else if (!e_src)
     {
         strcpy (src, dst->path);
-        fileDeleteR (di, dst, base, src, rGroup);
+        fileDeleteR (zh, di, dst, base, src, rGroup);
         return;
     }
     else
@@ -278,6 +188,9 @@ static void fileUpdateR (struct dirs_info *di, struct dirs_entry *dst,
         else
             break;
         logf (LOG_DEBUG, "trav sd=%d", sd);
+
+       if (level == 0 && rGroup->databaseNamePath)
+           rGroup->databaseName = e_src[i_src].name;
         if (sd == 0)
         {
             strcpy (src + src_len, e_src[i_src].name);
@@ -288,7 +201,7 @@ static void fileUpdateR (struct dirs_info *di, struct dirs_entry *dst,
             case dirs_file:
                 if (e_src[i_src].mtime > dst->mtime)
                 {
-                    if (fileExtract (&dst->sysno, tmppath, rGroup, 0))
+                    if (fileExtract (zh, &dst->sysno, tmppath, rGroup, 0))
                     {
                         dirs_add (di, src, dst->sysno, e_src[i_src].mtime);
                     }
@@ -298,7 +211,7 @@ static void fileUpdateR (struct dirs_info *di, struct dirs_entry *dst,
                 dst = dirs_read (di);
                 break;
             case dirs_dir:
-                fileUpdateR (di, dst, base, src, rGroup);
+                fileUpdateR (zh, di, dst, base, src, rGroup, level+1);
                 dst = dirs_last (di);
                 logf (LOG_DEBUG, "last is %s", dst ? dst->path : "null");
                 break;
@@ -316,11 +229,11 @@ static void fileUpdateR (struct dirs_info *di, struct dirs_entry *dst,
             switch (e_src[i_src].kind)
             {
             case dirs_file:
-                if (fileExtract (&sysno, tmppath, rGroup, 0))
+                if (fileExtract (zh, &sysno, tmppath, rGroup, 0))
                     dirs_add (di, src, sysno, e_src[i_src].mtime);            
                 break;
             case dirs_dir:
-                fileUpdateR (di, dst, base, src, rGroup);
+                fileUpdateR (zh, di, dst, base, src, rGroup, level+1);
                 if (dst)
                     dst = dirs_last (di);
                 break;
@@ -335,12 +248,12 @@ static void fileUpdateR (struct dirs_info *di, struct dirs_entry *dst,
             switch (dst->kind)
             {
             case dirs_file:
-                fileExtract (&dst->sysno, tmppath, rGroup, 1);
+                fileExtract (zh, &dst->sysno, tmppath, rGroup, 1);
                 dirs_del (di, dst->path);
                 dst = dirs_read (di);
                 break;
             case dirs_dir:
-                fileDeleteR (di, dst, base, src, rGroup);
+                fileDeleteR (zh, di, dst, base, src, rGroup);
                 dst = dirs_last (di);
             }
         }
@@ -348,7 +261,7 @@ static void fileUpdateR (struct dirs_info *di, struct dirs_entry *dst,
     dir_free (&e_src);
 }
 
-static void groupRes (struct recordGroup *rGroup)
+static void groupRes (ZebraHandle zh, struct recordGroup *rGroup)
 {
     char resStr[256];
     char gPrefix[256];
@@ -359,18 +272,23 @@ static void groupRes (struct recordGroup *rGroup)
         sprintf (gPrefix, "%s.", rGroup->groupName);
 
     sprintf (resStr, "%srecordId", gPrefix);
-    rGroup->recordId = res_get (common_resource, resStr);
+    rGroup->recordId = res_get (zh->res, resStr);
+    sprintf (resStr, "%sdatabasePath", gPrefix);
+    rGroup->databaseNamePath =
+       atoi (res_get_def (zh->res, resStr, "0"));
 }
 
-void repositoryShow (struct recordGroup *rGroup)
+void repositoryShow (ZebraHandle zh)
+                     
 {
+    struct recordGroup *rGroup = &zh->rGroup;
     char src[1024];
     int src_len;
     struct dirs_entry *dst;
     Dict dict;
     struct dirs_info *di;
     
-    if (!(dict = dict_open (rGroup->bfs, FMATCH_DICT, 50, 0)))
+    if (!(dict = dict_open (zh->reg->bfs, FMATCH_DICT, 50, 0, 0)))
     {
         logf (LOG_FATAL, "dict_open fail of %s", FMATCH_DICT);
        return;
@@ -394,7 +312,8 @@ void repositoryShow (struct recordGroup *rGroup)
     dict_close (dict);
 }
 
-static void fileUpdate (Dict dict, struct recordGroup *rGroup,
+static void fileUpdate (ZebraHandle zh,
+                        Dict dict, struct recordGroup *rGroup,
                         const char *path)
 {
     struct dirs_info *di;
@@ -404,10 +323,20 @@ static void fileUpdate (Dict dict, struct recordGroup *rGroup,
     int src_len;
 
     assert (path);
+
+    if (zh->path_reg && !yaz_is_abspath(path))
+    {
+        strcpy (src, zh->path_reg);
+        strcat (src, "/");
+    }
+    else
+        *src = '\0';
+    strcat (src, path);
+    stat (src, &sbuf);
+
     strcpy (src, path);
     src_len = strlen (src);
 
-    stat (src, &sbuf);
     if (S_ISREG(sbuf.st_mode))
     {
         struct dirs_entry *e_dst;
@@ -417,13 +346,13 @@ static void fileUpdate (Dict dict, struct recordGroup *rGroup,
         if (e_dst)
         {
             if (sbuf.st_mtime > e_dst->mtime)
-                if (fileExtract (&e_dst->sysno, src, rGroup, 0))
+                if (fileExtract (zh, &e_dst->sysno, src, rGroup, 0))
                     dirs_add (di, src, e_dst->sysno, sbuf.st_mtime);
         }
         else
         {
             SYSNO sysno = 0;
-            if (fileExtract (&sysno, src, rGroup, 0))
+            if (fileExtract (zh, &sysno, src, rGroup, 0))
                  dirs_add (di, src, sysno, sbuf.st_mtime);
         }
         dirs_free (&di);
@@ -437,7 +366,7 @@ static void fileUpdate (Dict dict, struct recordGroup *rGroup,
         }
         di = dirs_open (dict, src, rGroup->flagRw);
         *dst = '\0';
-        fileUpdateR (di, dirs_read (di), src, dst, rGroup);
+        fileUpdateR (zh, di, dirs_read (di), src, dst, rGroup, 0);
         dirs_free (&di);
     }
     else
@@ -447,45 +376,59 @@ static void fileUpdate (Dict dict, struct recordGroup *rGroup,
 }
 
 
-static void repositoryExtract (int deleteFlag, struct recordGroup *rGroup,
+static void repositoryExtract (ZebraHandle zh,
+                               int deleteFlag, struct recordGroup *rGroup,
                                const char *path)
 {
     struct stat sbuf;
     char src[1024];
 
     assert (path);
-    strcpy (src, path);
 
+    if (zh->path_reg && !yaz_is_abspath(path))
+    {
+        strcpy (src, zh->path_reg);
+        strcat (src, "/");
+    }
+    else
+        *src = '\0';
+    strcat (src, path);
     stat (src, &sbuf);
+
+    strcpy (src, path);
+
     if (S_ISREG(sbuf.st_mode))
-        fileExtract (NULL, src, rGroup, deleteFlag);
+        fileExtract (zh, NULL, src, rGroup, deleteFlag);
     else if (S_ISDIR(sbuf.st_mode))
-       repositoryExtractR (deleteFlag, src, rGroup);
+       repositoryExtractR (zh, deleteFlag, src, rGroup, 0);
     else
         logf (LOG_WARN, "Ignoring path %s", src);
 }
 
-static void repositoryExtractG (int deleteFlag, struct recordGroup *rGroup)
+static void repositoryExtractG (ZebraHandle zh,
+                                int deleteFlag, struct recordGroup *rGroup)
 {
     if (*rGroup->path == '\0' || !strcmp(rGroup->path, "-"))
     {
         char src[1024];
 
-        while (scanf ("%s", src) == 1)
-            repositoryExtract (deleteFlag, rGroup, src);
+        while (scanf ("%1020s", src) == 1)
+            repositoryExtract (zh, deleteFlag, rGroup, src);
     }
     else
-        repositoryExtract (deleteFlag, rGroup, rGroup->path);
+        repositoryExtract (zh, deleteFlag, rGroup, rGroup->path);
 }
 
-void repositoryUpdate (struct recordGroup *rGroup)
+void repositoryUpdate (ZebraHandle zh)
 {
-    groupRes (rGroup);
+    struct recordGroup *rGroup = &zh->rGroup;
+    groupRes (zh, rGroup);
     assert (rGroup->path);
     if (rGroup->recordId && !strcmp (rGroup->recordId, "file"))
     {
         Dict dict;
-        if (!(dict = dict_open (rGroup->bfs, FMATCH_DICT, 50, rGroup->flagRw)))
+        if (!(dict = dict_open (zh->reg->bfs, FMATCH_DICT, 50,
+                               rGroup->flagRw, 0)))
         {
             logf (LOG_FATAL, "dict_open fail of %s", FMATCH_DICT);
            return ;
@@ -494,18 +437,18 @@ void repositoryUpdate (struct recordGroup *rGroup)
         {
             char src[1024];
             while (scanf ("%s", src) == 1)
-                fileUpdate (dict, rGroup, src);
+                fileUpdate (zh, dict, rGroup, src);
         }
         else
-            fileUpdate (dict, rGroup, rGroup->path);
+            fileUpdate (zh, dict, rGroup, rGroup->path);
         dict_close (dict);
     }
     else 
-        repositoryExtractG (0, rGroup);
+        repositoryExtractG (zh, 0, rGroup);
 }
 
-void repositoryDelete (struct recordGroup *rGroup)
+void repositoryDelete (ZebraHandle zh)
 {
-    repositoryExtractG (1, rGroup);
+    repositoryExtractG (zh, 1, &zh->rGroup);
 }