Break long lines in debian/control
[idzebra-moved-to-github.git] / index / update_file.c
1 /* This file is part of the Zebra server.
2    Copyright (C) 1994-2011 Index Data
3
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
18 */
19
20 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #include <stdio.h>
24 #include <assert.h>
25 #include <sys/types.h>
26 #ifdef WIN32
27 #include <io.h>
28 #define S_ISREG(x) (x & _S_IFREG)
29 #define S_ISDIR(x) (x & _S_IFDIR)
30 #endif
31 #if HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34 #include <direntz.h>
35 #include <fcntl.h>
36 #include <time.h>
37
38 #include "index.h"
39
40 #if 0
41 static int dump_file_dict_func(char *name, const char *info, int pos,
42                                 void *client)
43 {
44     yaz_log(YLOG_LOG, "%s", name);
45     return 0;
46 }
47 static void dump_file_dict(Dict dict)
48 {
49     int before = 10;
50     int after = 1000;
51     char term[1000];
52     
53     strcpy(term, "0");
54     dict_scan(dict, term, &before, &after, 0, dump_file_dict_func);
55 }
56 #endif
57
58 static int repComp(const char *a, const char *b, size_t len)
59 {
60     if (!len)
61         return 0;
62     return memcmp(a, b, len);
63 }
64
65 static void fileDelete_r(ZebraHandle zh,
66                          struct dirs_info *di, struct dirs_entry *dst,
67                          const char *base, char *src)
68 {
69     char tmppath[1024];
70     size_t src_len = strlen(src);
71
72     while (dst && !repComp(dst->path, src, src_len+1))
73     {
74         switch (dst->kind)
75         {
76         case dirs_file:
77             sprintf(tmppath, "%s%s", base, dst->path);
78             zebra_extract_file(zh, &dst->sysno, tmppath, action_delete);
79             strcpy(tmppath, dst->path);
80             dst = dirs_read(di); 
81             dirs_del(di, tmppath);
82             break;
83         case dirs_dir:
84             strcpy(tmppath, dst->path);
85             dst = dirs_read(di);
86             dirs_rmdir(di, tmppath);
87             break;
88         default:
89             dst = dirs_read(di);
90         }
91     }
92 }
93
94 static void file_update_r(ZebraHandle zh,
95                           struct dirs_info *di, struct dirs_entry *dst,
96                           const char *base, char *src, 
97                           int level)
98 {
99     struct dir_entry *e_src;
100     int i_src = 0;
101     static char tmppath[1024];
102     size_t src_len = strlen(src);
103
104     sprintf(tmppath, "%s%s", base, src);
105     e_src = dir_open(tmppath, zh->path_reg, zh->m_follow_links);
106     yaz_log(YLOG_LOG, "dir %s", tmppath);
107
108 #if 0
109     if (!dst || repComp(dst->path, src, src_len))
110 #else
111     if (!dst || strcmp(dst->path, src))
112 #endif
113     {
114         if (!e_src)
115             return;
116
117         if (src_len && src[src_len-1] != '/')
118         {
119             src[src_len] = '/';
120             src[++src_len] = '\0';
121         }
122         dirs_mkdir(di, src, 0);
123         if (dst && repComp(dst->path, src, src_len))
124             dst = NULL;
125     }
126     else if (!e_src)
127     {
128         strcpy(src, dst->path);
129         fileDelete_r(zh, di, dst, base, src);
130         return;
131     }
132     else
133     {
134         if (src_len && src[src_len-1] != '/')
135         {
136             src[src_len] = '/';
137             src[++src_len] = '\0';
138         }
139         dst = dirs_read(di); 
140     }
141     dir_sort(e_src);
142
143     while (1)
144     {
145         int sd;
146
147         if (dst && !repComp(dst->path, src, src_len))
148         {
149             if (e_src[i_src].name)
150             {
151                 yaz_log(YLOG_DEBUG, "dst=%s src=%s", dst->path + src_len,
152                       e_src[i_src].name);
153                 sd = strcmp(dst->path + src_len, e_src[i_src].name);
154             }
155             else
156                 sd = -1;
157         }
158         else if (e_src[i_src].name)
159             sd = 1;
160         else
161             break;
162         yaz_log(YLOG_DEBUG, "trav sd=%d", sd);
163
164         if (sd == 0)
165         {
166             strcpy(src + src_len, e_src[i_src].name);
167             sprintf(tmppath, "%s%s", base, src);
168             
169             switch(e_src[i_src].kind)
170             {
171             case dirs_file:
172                 if (e_src[i_src].mtime > dst->mtime)
173                 {
174                     if (zebra_extract_file(zh, &dst->sysno, tmppath, action_update) == ZEBRA_OK)
175                     {
176                         dirs_add(di, src, dst->sysno, e_src[i_src].mtime);
177                     }
178                     yaz_log(YLOG_DEBUG, "old: %s", ctime(&dst->mtime));
179                     yaz_log(YLOG_DEBUG, "new: %s", ctime(&e_src[i_src].mtime));
180                 }
181                 dst = dirs_read(di);
182                 break;
183             case dirs_dir:
184                 file_update_r(zh, di, dst, base, src, level+1);
185                 dst = dirs_last(di);
186                 yaz_log(YLOG_DEBUG, "last is %s", dst ? dst->path : "null");
187                 break;
188             default:
189                 dst = dirs_read(di); 
190             }
191             i_src++;
192         }
193         else if (sd > 0)
194         {
195             zint sysno = 0;
196             strcpy(src + src_len, e_src[i_src].name);
197             sprintf(tmppath, "%s%s", base, src);
198
199             switch (e_src[i_src].kind)
200             {
201             case dirs_file:
202                 if (zebra_extract_file(zh, &sysno, tmppath, action_update) == ZEBRA_OK)
203                     dirs_add(di, src, sysno, e_src[i_src].mtime);            
204                 break;
205             case dirs_dir:
206                 file_update_r(zh, di, dst, base, src, level+1);
207                 if (dst)
208                     dst = dirs_last(di);
209                 break;
210             }
211             i_src++;
212         }
213         else  /* sd < 0 */
214         {
215             strcpy(src, dst->path);
216             sprintf(tmppath, "%s%s", base, dst->path);
217
218             switch (dst->kind)
219             {
220             case dirs_file:
221                 zebra_extract_file(zh, &dst->sysno, tmppath, action_delete);
222                 dirs_del(di, dst->path);
223                 dst = dirs_read(di);
224                 break;
225             case dirs_dir:
226                 fileDelete_r(zh, di, dst, base, src);
227                 dst = dirs_last(di);
228             }
229         }
230     }
231     dir_free(&e_src);
232 }
233
234 static void file_update_top(ZebraHandle zh, Dict dict, const char *path)
235 {
236     struct dirs_info *di;
237     struct stat sbuf;
238     char src[1024];
239     char dst[1024];
240     int src_len, ret;
241
242     assert(path);
243
244     if (zh->path_reg && !yaz_is_abspath(path))
245     {
246         strcpy(src, zh->path_reg);
247         strcat(src, "/");
248     }
249     else
250         *src = '\0';
251     strcat(src, path);
252     ret = zebra_file_stat(src, &sbuf, zh->m_follow_links);
253
254     strcpy(src, path);
255     src_len = strlen(src);
256
257     if (ret == -1)
258     {
259         yaz_log(YLOG_WARN|YLOG_ERRNO, "Cannot access path %s", src);
260     } 
261     else if (S_ISREG(sbuf.st_mode))
262     {
263         struct dirs_entry *e_dst;
264         di = dirs_fopen(dict, src, zh->m_flag_rw);
265
266         e_dst = dirs_read(di);
267         if (e_dst)
268         {
269             if (sbuf.st_mtime > e_dst->mtime)
270                 if (zebra_extract_file(zh, &e_dst->sysno, src, action_update) == ZEBRA_OK)
271                     dirs_add(di, src, e_dst->sysno, sbuf.st_mtime);
272         }
273         else
274         {
275             zint sysno = 0;
276             if (zebra_extract_file(zh, &sysno, src, action_update) == ZEBRA_OK)
277                  dirs_add(di, src, sysno, sbuf.st_mtime);
278         }
279         dirs_free(&di);
280     }
281     else if (S_ISDIR(sbuf.st_mode))
282     {
283         if (src_len && src[src_len-1] != '/')
284         {
285             src[src_len] = '/';
286             src[++src_len] = '\0';
287         }
288         di = dirs_open(dict, src, zh->m_flag_rw);
289         *dst = '\0';
290         file_update_r(zh, di, dirs_read(di), src, dst, 0);
291         dirs_free (&di);
292     }
293     else
294     {
295         yaz_log(YLOG_WARN, "Skipping path %s", src);
296     }
297 }
298
299 static ZEBRA_RES zebra_open_fmatch(ZebraHandle zh, Dict *dictp)
300 {
301     char fmatch_fname[1024];
302     int ord;
303
304     ord = zebraExplain_get_database_ord(zh->reg->zei);
305     sprintf(fmatch_fname, FMATCH_DICT, ord);
306     if (!(*dictp = dict_open_res(zh->reg->bfs, fmatch_fname, 50,
307                                 zh->m_flag_rw, 0, zh->res)))
308     {
309         yaz_log(YLOG_FATAL, "dict_open fail of %s", fmatch_fname);
310         return ZEBRA_FAIL;
311     }
312     return ZEBRA_OK;
313 }
314
315 ZEBRA_RES zebra_remove_file_match(ZebraHandle zh)
316 {
317     Dict dict;
318     
319     if (zebra_open_fmatch(zh, &dict) != ZEBRA_OK)
320         return ZEBRA_FAIL;
321
322     dict_clean(dict);
323     dict_close(dict);
324
325     return ZEBRA_OK;
326 }
327
328 ZEBRA_RES zebra_update_file_match(ZebraHandle zh, const char *path)
329 {
330     Dict dict;
331
332     if (zebraExplain_curDatabase(zh->reg->zei, zh->basenames[0]))
333     {
334         if (zebraExplain_newDatabase(zh->reg->zei, zh->basenames[0], 0))
335             return ZEBRA_FAIL;
336     }
337     if (zebra_open_fmatch(zh, &dict) != ZEBRA_OK)
338         return ZEBRA_FAIL;
339     
340     if (!strcmp(path, "") || !strcmp(path, "-"))
341     {
342         char src[1024];
343         while (scanf("%s", src) == 1)
344             file_update_top(zh, dict, src);
345     }
346     else
347         file_update_top(zh, dict, path);
348 #if 0
349     dump_file_dict(dict);
350 #endif
351     dict_close(dict);
352     return ZEBRA_OK;
353 }
354
355
356 /*
357  * Local variables:
358  * c-basic-offset: 4
359  * c-file-style: "Stroustrup"
360  * indent-tabs-mode: nil
361  * End:
362  * vim: shiftwidth=4 tabstop=8 expandtab
363  */
364