IDZEBRA  2.1.2
update_file.c
Go to the documentation of this file.
1 /* This file is part of the Zebra server.
2  Copyright (C) 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 
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 
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 
300 {
301  char fmatch_fname[1024];
302  int ord;
303 
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 
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 
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 
char path[256]
Definition: index.h:65
#define ZEBRA_OK
Definition: util.h:82
struct dirs_entry * dirs_last(struct dirs_info *p)
Definition: dirs.c:164
char * path_reg
Definition: index.h:182
static ZEBRA_RES zebra_open_fmatch(ZebraHandle zh, Dict *dictp)
Definition: update_file.c:299
time_t mtime
Definition: index.h:60
Definition: index.h:55
struct zebra_register * reg
Definition: index.h:174
static int repComp(const char *a, const char *b, size_t len)
Definition: update_file.c:58
#define ZEBRA_FAIL
Definition: util.h:81
char ** basenames
Definition: index.h:178
struct dir_entry * dir_open(const char *rep, const char *base, int follow_links)
Definition: dir.c:48
ZebraHandle zh
Definition: zebrash.c:64
struct dirs_info * dirs_open(Dict dict, const char *rep, int rw)
Definition: dirs.c:82
int dict_close(Dict dict)
closes dictionary
Definition: close.c:32
int m_follow_links
Definition: index.h:218
int zebra_file_stat(const char *file_name, struct stat *buf, int follow_links)
Definition: dir.c:38
void dirs_add(struct dirs_info *p, const char *src, zint sysno, time_t mtime)
Definition: dirs.c:189
char * name
Definition: index.h:59
static void file_update_top(ZebraHandle zh, Dict dict, const char *path)
Definition: update_file.c:234
#define FMATCH_DICT
Definition: index.h:105
zint sysno
Definition: index.h:66
void dir_sort(struct dir_entry *e)
Definition: dir.c:138
ZebraExplainInfo zei
Definition: index.h:139
enum dirsKind kind
Definition: index.h:58
Definition: dirs.c:34
int zebraExplain_newDatabase(ZebraExplainInfo zei, const char *database, int explain_database)
Definition: zinfo.c:883
static Dict dict
Definition: dicttest.c:34
int m_flag_rw
Definition: index.h:225
struct dirs_info * dirs_fopen(Dict dict, const char *path, int rw)
Definition: dirs.c:104
time_t mtime
Definition: index.h:67
int dict_scan(Dict dict, char *str, int *before, int *after, void *client, int(*f)(char *name, const char *info, int pos, void *client))
dictionary scan
Definition: scan.c:242
Definition: index.h:63
int zebraExplain_curDatabase(ZebraExplainInfo zei, const char *database)
Definition: zinfo.c:791
void dirs_del(struct dirs_info *p, const char *src)
Definition: dirs.c:202
ZEBRA_RES zebra_update_file_match(ZebraHandle zh, const char *path)
Definition: update_file.c:328
void dirs_free(struct dirs_info **pp)
Definition: dirs.c:216
void dir_free(struct dir_entry **e_p)
Definition: dir.c:146
void dirs_rmdir(struct dirs_info *p, const char *src)
Definition: dirs.c:179
enum dirsKind kind
Definition: index.h:64
void dirs_mkdir(struct dirs_info *p, const char *src, time_t mtime)
Definition: dirs.c:169
ZEBRA_RES zebra_remove_file_match(ZebraHandle zh)
Definition: update_file.c:315
BFiles bfs
Definition: index.h:137
int zebraExplain_get_database_ord(ZebraExplainInfo zei)
Definition: zinfo.c:1621
long zint
Zebra integer.
Definition: util.h:66
struct dirs_entry * dirs_read(struct dirs_info *p)
Definition: dirs.c:133
static void file_update_r(ZebraHandle zh, struct dirs_info *di, struct dirs_entry *dst, const char *base, char *src, int level)
Definition: update_file.c:94
void dict_clean(Dict dict)
reset Dictionary (makes it empty)
Definition: open.c:31
Dict dict_open_res(BFiles bfs, const char *name, int cache, int rw, int compact_flag, Res res)
Definition: zebraapi.c:320
Definition: index.h:57
short ZEBRA_RES
Common return type for Zebra API.
Definition: util.h:80
ZEBRA_RES zebra_extract_file(ZebraHandle zh, zint *sysno, const char *fname, enum zebra_recctrl_action_t action)
Definition: extract.c:620
static void fileDelete_r(ZebraHandle zh, struct dirs_info *di, struct dirs_entry *dst, const char *base, char *src)
Definition: update_file.c:65