Commands add & del read filenames from stdin if source directory is
[idzebra-moved-to-github.git] / index / trav.c
1 /*
2  * Copyright (C) 1994-1995, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: trav.c,v $
7  * Revision 1.12  1995-11-24 11:31:37  adam
8  * Commands add & del read filenames from stdin if source directory is
9  * empty.
10  * Match criteria supports 'constant' strings.
11  *
12  * Revision 1.11  1995/11/22  17:19:19  adam
13  * Record management uses the bfile system.
14  *
15  * Revision 1.10  1995/11/21  15:01:16  adam
16  * New general match criteria implemented.
17  * New feature: document groups.
18  *
19  * Revision 1.9  1995/11/21  09:20:32  adam
20  * Yet more work on record match.
21  *
22  * Revision 1.8  1995/11/20  16:59:46  adam
23  * New update method: the 'old' keys are saved for each records.
24  *
25  * Revision 1.7  1995/11/20  11:56:28  adam
26  * Work on new traversal.
27  *
28  * Revision 1.6  1995/11/17  15:54:42  adam
29  * Started work on virtual directory structure.
30  *
31  * Revision 1.5  1995/10/17  18:02:09  adam
32  * New feature: databases. Implemented as prefix to words in dictionary.
33  *
34  * Revision 1.4  1995/09/28  09:19:46  adam
35  * xfree/xmalloc used everywhere.
36  * Extract/retrieve method seems to work for text records.
37  *
38  * Revision 1.3  1995/09/06  16:11:18  adam
39  * Option: only one word key per file.
40  *
41  * Revision 1.2  1995/09/04  12:33:43  adam
42  * Various cleanup. YAZ util used instead.
43  *
44  * Revision 1.1  1995/09/01  14:06:36  adam
45  * Split of work into more files.
46  *
47  */
48 #include <stdio.h>
49 #include <assert.h>
50 #include <unistd.h>
51 #include <dirent.h>
52 #include <sys/stat.h>
53 #include <sys/types.h>
54 #include <fcntl.h>
55 #include <ctype.h>
56
57 #include <alexutil.h>
58 #include "index.h"
59
60 static int repComp (const char *a, const char *b, size_t len)
61 {
62     if (!len)
63         return 0;
64     return memcmp (a, b, len);
65 }
66
67 static void repositoryExtractR (int deleteFlag, char *rep,
68                                 struct recordGroup *rGroup)
69 {
70     struct dir_entry *e;
71     int i;
72     size_t rep_len = strlen (rep);
73
74     e = dir_open (rep);
75     if (!e)
76         return;
77     if (rep[rep_len-1] != '/')
78         rep[rep_len] = '/';
79     else
80         --rep_len;
81     for (i=0; e[i].name; i++)
82     {
83         strcpy (rep +rep_len+1, e[i].name);
84         switch (e[i].kind)
85         {
86         case dirs_file:
87             fileExtract (NULL, rep, rGroup, deleteFlag);
88             break;
89         case dirs_dir:
90             repositoryExtractR (deleteFlag, rep, rGroup);
91             break;
92         }
93     }
94     dir_free (&e);
95
96 }
97
98 static void stdinExtractR (int deleteFlag, struct recordGroup *rGroup)
99 {
100     char tmppath[256];
101
102     while (scanf ("%s", tmppath) == 1)
103         fileExtract (NULL, tmppath, rGroup, deleteFlag);
104 }
105
106 static void repositoryUpdateR (struct dirs_info *di, struct dirs_entry *dst,
107                                const char *base, char *src, 
108                                struct recordGroup *rGroup)
109 {
110     struct dir_entry *e_src;
111     int i_src = 0;
112     static char tmppath[256];
113     size_t src_len = strlen (src);
114
115     sprintf (tmppath, "%s%s", base, src);
116     e_src = dir_open (tmppath);
117
118 #if 1
119     if (!dst || repComp (dst->path, src, src_len))
120 #else
121     if (!dst || strcmp (dst->path, src))
122 #endif
123     {
124         if (!e_src)
125             return;
126         if (src_len && src[src_len-1] == '/')
127             --src_len;
128         else
129             src[src_len] = '/';
130         src[src_len+1] = '\0';
131         dirs_mkdir (di, src, 0);
132         dst = NULL;
133     }
134     else if (!e_src)
135     {
136         /* delete tree dst */
137         return;
138     }
139     else
140     {
141         if (src_len && src[src_len-1] == '/')
142             --src_len;
143         else
144             src[src_len] = '/';
145         src[src_len+1] = '\0';
146         dst = dirs_read (di); 
147     }
148     dir_sort (e_src);
149
150     while (1)
151     {
152         int sd;
153
154         if (dst && !repComp (dst->path, src, src_len+1))
155         {
156             if (e_src[i_src].name)
157             {
158                 logf (LOG_DEBUG, "dst=%s src=%s", dst->path + src_len+1, 
159                       e_src[i_src].name);
160                 sd = strcmp (dst->path + src_len+1, e_src[i_src].name);
161             }
162             else
163                 sd = -1;
164         }
165         else if (e_src[i_src].name)
166             sd = 1;
167         else
168             break;
169         logf (LOG_DEBUG, "trav sd=%d", sd);
170         if (sd == 0)
171         {
172             strcpy (src + src_len+1, e_src[i_src].name);
173             sprintf (tmppath, "%s%s", base, src);
174             
175             switch (e_src[i_src].kind)
176             {
177             case dirs_file:
178                 if (e_src[i_src].ctime > dst->ctime)
179                 {
180                     if (fileExtract (&dst->sysno, tmppath, rGroup, 0))
181                         dirs_add (di, src, dst->sysno, e_src[i_src].ctime);
182                 }
183                 dst = dirs_read (di);
184                 break;
185             case dirs_dir:
186                 repositoryUpdateR (di, dst, base, src, rGroup);
187                 dst = dirs_last (di);
188                 logf (LOG_DEBUG, "last is %s", dst ? dst->path : "null");
189                 break;
190             default:
191                 dst = dirs_read (di); 
192             }
193             i_src++;
194         }
195         else if (sd > 0)
196         {
197             SYSNO sysno = 0;
198             strcpy (src + src_len+1, e_src[i_src].name);
199             sprintf (tmppath, "%s%s", base, src);
200
201             switch (e_src[i_src].kind)
202             {
203             case dirs_file:
204                 if (fileExtract (&sysno, tmppath, rGroup, 0))
205                     dirs_add (di, src, sysno, e_src[i_src].ctime);            
206                 break;
207             case dirs_dir:
208                 repositoryUpdateR (di, dst, base, src, rGroup);
209                 if (dst)
210                     dst = dirs_last (di);
211                 break;
212             }
213             i_src++;
214         }
215         else  /* sd < 0 */
216         {
217             assert (0);
218         }
219     }
220     dir_free (&e_src);
221 }
222
223 void repositoryUpdate (struct recordGroup *rGroup)
224 {
225     struct dirs_info *di;
226     char src[256];
227     Dict dict;
228
229     dict = dict_open ("repdict", 40, 1);
230
231     assert (rGroup->path);
232     di = dirs_open (dict, rGroup->path);
233     strcpy (src, "");
234     repositoryUpdateR (di, dirs_read (di), rGroup->path, src, rGroup);
235     dirs_free (&di);
236
237     dict_close (dict);
238 }
239
240 void repositoryDelete (struct recordGroup *rGroup)
241 {
242     char src[256];
243
244     assert (rGroup->path);
245     strcpy (src, rGroup->path);
246     if (*src == '\0')
247         stdinExtractR (1, rGroup);
248     else
249         repositoryExtractR (1, src, rGroup);
250 }
251
252 void repositoryAdd (struct recordGroup *rGroup)
253 {
254     char src[256];
255
256     assert (rGroup->path);
257     strcpy (src, rGroup->path);
258     if (*src == '\0')
259         stdinExtractR (0, rGroup);
260     else
261         repositoryExtractR (0, src, rGroup);
262 }
263