IDZEBRA  2.2.7
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 #include <yaz/snprintf.h>
38 
39 #include "index.h"
40 
41 static int repComp(const char *a, const char *b, size_t len)
42 {
43  if (!len)
44  return 0;
45  return memcmp(a, b, len);
46 }
47 
48 static void fileDelete_r(ZebraHandle zh,
49  struct dirs_info *di, struct dirs_entry *dst,
50  const char *base, char *src)
51 {
52  char tmppath[1024];
53  size_t src_len = strlen(src);
54 
55  while (dst && !repComp(dst->path, src, src_len+1))
56  {
57  switch (dst->kind)
58  {
59  case dirs_file:
60  yaz_snprintf(tmppath, sizeof(tmppath), "%s%s", base, dst->path);
61  zebra_extract_file(zh, &dst->sysno, tmppath, action_delete);
62  strcpy(tmppath, dst->path);
63  dst = dirs_read(di);
64  dirs_del(di, tmppath);
65  break;
66  case dirs_dir:
67  strcpy(tmppath, dst->path);
68  dst = dirs_read(di);
69  dirs_rmdir(di, tmppath);
70  break;
71  default:
72  dst = dirs_read(di);
73  }
74  }
75 }
76 
77 static void file_update_r(ZebraHandle zh,
78  struct dirs_info *di, struct dirs_entry *dst,
79  const char *base, char *src,
80  int level)
81 {
82  struct dir_entry *e_src;
83  int i_src = 0;
84  static char tmppath[1024];
85  size_t src_len = strlen(src);
86 
87  yaz_snprintf(tmppath, sizeof(tmppath), "%s%s", base, src);
88  e_src = dir_open(tmppath, zh->path_reg, zh->m_follow_links);
89  yaz_log(YLOG_LOG, "dir %s", tmppath);
90 
91  if (!dst || strcmp(dst->path, src))
92  {
93  if (!e_src)
94  return;
95 
96  if (src_len && src[src_len-1] != '/')
97  {
98  src[src_len] = '/';
99  src[++src_len] = '\0';
100  }
101  dirs_mkdir(di, src, 0);
102  if (dst && repComp(dst->path, src, src_len))
103  dst = NULL;
104  }
105  else if (!e_src)
106  {
107  strcpy(src, dst->path);
108  fileDelete_r(zh, di, dst, base, src);
109  return;
110  }
111  else
112  {
113  if (src_len && src[src_len-1] != '/')
114  {
115  src[src_len] = '/';
116  src[++src_len] = '\0';
117  }
118  dst = dirs_read(di);
119  }
120  dir_sort(e_src);
121 
122  while (1)
123  {
124  int sd;
125 
126  if (dst && !repComp(dst->path, src, src_len))
127  {
128  if (e_src[i_src].name)
129  {
130  yaz_log(YLOG_DEBUG, "dst=%s src=%s", dst->path + src_len,
131  e_src[i_src].name);
132  sd = strcmp(dst->path + src_len, e_src[i_src].name);
133  }
134  else
135  sd = -1;
136  }
137  else if (e_src[i_src].name)
138  sd = 1;
139  else
140  break;
141  yaz_log(YLOG_DEBUG, "trav sd=%d", sd);
142 
143  if (sd == 0)
144  {
145  strcpy(src + src_len, e_src[i_src].name);
146  yaz_snprintf(tmppath, sizeof(tmppath), "%s%s", base, src);
147 
148  switch(e_src[i_src].kind)
149  {
150  case dirs_file:
151  if (e_src[i_src].mtime > dst->mtime)
152  {
153  if (zebra_extract_file(zh, &dst->sysno, tmppath, action_update) == ZEBRA_OK)
154  {
155  dirs_add(di, src, dst->sysno, e_src[i_src].mtime);
156  }
157  yaz_log(YLOG_DEBUG, "old: %s", ctime(&dst->mtime));
158  yaz_log(YLOG_DEBUG, "new: %s", ctime(&e_src[i_src].mtime));
159  }
160  dst = dirs_read(di);
161  break;
162  case dirs_dir:
163  file_update_r(zh, di, dst, base, src, level+1);
164  dst = dirs_last(di);
165  yaz_log(YLOG_DEBUG, "last is %s", dst ? dst->path : "null");
166  break;
167  default:
168  dst = dirs_read(di);
169  }
170  i_src++;
171  }
172  else if (sd > 0)
173  {
174  zint sysno = 0;
175  strcpy(src + src_len, e_src[i_src].name);
176  yaz_snprintf(tmppath, sizeof(tmppath), "%s%s", base, src);
177 
178  switch (e_src[i_src].kind)
179  {
180  case dirs_file:
181  if (zebra_extract_file(zh, &sysno, tmppath, action_update) == ZEBRA_OK)
182  dirs_add(di, src, sysno, e_src[i_src].mtime);
183  break;
184  case dirs_dir:
185  file_update_r(zh, di, dst, base, src, level+1);
186  if (dst)
187  dst = dirs_last(di);
188  break;
189  }
190  i_src++;
191  }
192  else /* sd < 0 */
193  {
194  strcpy(src, dst->path);
195  yaz_snprintf(tmppath, sizeof(tmppath), "%s%s", base, dst->path);
196 
197  switch (dst->kind)
198  {
199  case dirs_file:
200  zebra_extract_file(zh, &dst->sysno, tmppath, action_delete);
201  dirs_del(di, dst->path);
202  dst = dirs_read(di);
203  break;
204  case dirs_dir:
205  fileDelete_r(zh, di, dst, base, src);
206  dst = dirs_last(di);
207  }
208  }
209  }
210  dir_free(&e_src);
211 }
212 
213 static void file_update_top(ZebraHandle zh, Dict dict, const char *path)
214 {
215  struct dirs_info *di;
216  struct stat sbuf;
217  char src[1024];
218  char dst[1024];
219  int src_len, ret;
220 
221  assert(path);
222 
223  if (zh->path_reg && !yaz_is_abspath(path))
224  {
225  strcpy(src, zh->path_reg);
226  strcat(src, "/");
227  }
228  else
229  *src = '\0';
230  strcat(src, path);
231  ret = zebra_file_stat(src, &sbuf, zh->m_follow_links);
232 
233  strcpy(src, path);
234  src_len = strlen(src);
235 
236  if (ret == -1)
237  {
238  yaz_log(YLOG_WARN|YLOG_ERRNO, "Cannot access path %s", src);
239  }
240  else if (S_ISREG(sbuf.st_mode))
241  {
242  struct dirs_entry *e_dst;
243  di = dirs_fopen(dict, src, zh->m_flag_rw);
244 
245  e_dst = dirs_read(di);
246  if (e_dst)
247  {
248  if (sbuf.st_mtime > e_dst->mtime)
249  if (zebra_extract_file(zh, &e_dst->sysno, src, action_update) == ZEBRA_OK)
250  dirs_add(di, src, e_dst->sysno, sbuf.st_mtime);
251  }
252  else
253  {
254  zint sysno = 0;
255  if (zebra_extract_file(zh, &sysno, src, action_update) == ZEBRA_OK)
256  dirs_add(di, src, sysno, sbuf.st_mtime);
257  }
258  dirs_free(&di);
259  }
260  else if (S_ISDIR(sbuf.st_mode))
261  {
262  if (src_len && src[src_len-1] != '/')
263  {
264  src[src_len] = '/';
265  src[++src_len] = '\0';
266  }
267  di = dirs_open(dict, src, zh->m_flag_rw);
268  *dst = '\0';
269  file_update_r(zh, di, dirs_read(di), src, dst, 0);
270  dirs_free (&di);
271  }
272  else
273  {
274  yaz_log(YLOG_WARN, "Skipping path %s", src);
275  }
276 }
277 
279 {
280  char fmatch_fname[1024];
281  int ord;
282 
284  yaz_snprintf(fmatch_fname, sizeof(fmatch_fname), FMATCH_DICT, ord);
285  if (!(*dictp = dict_open_res(zh->reg->bfs, fmatch_fname, 50,
286  zh->m_flag_rw, 0, zh->res)))
287  {
288  yaz_log(YLOG_FATAL, "dict_open fail of %s", fmatch_fname);
289  return ZEBRA_FAIL;
290  }
291  return ZEBRA_OK;
292 }
293 
295 {
296  Dict dict;
297 
298  if (zebra_open_fmatch(zh, &dict) != ZEBRA_OK)
299  return ZEBRA_FAIL;
300 
301  dict_clean(dict);
302  dict_close(dict);
303 
304  return ZEBRA_OK;
305 }
306 
308 {
309  Dict dict;
310 
311  if (zebraExplain_curDatabase(zh->reg->zei, zh->basenames[0]))
312  {
313  if (zebraExplain_newDatabase(zh->reg->zei, zh->basenames[0], 0))
314  return ZEBRA_FAIL;
315  }
316  if (zebra_open_fmatch(zh, &dict) != ZEBRA_OK)
317  return ZEBRA_FAIL;
318 
319  if (!strcmp(path, "") || !strcmp(path, "-"))
320  {
321  char src[1024];
322  while (scanf("%s", src) == 1)
323  file_update_top(zh, dict, src);
324  }
325  else
326  file_update_top(zh, dict, path);
327 #if 0
328  dump_file_dict(dict);
329 #endif
330  dict_close(dict);
331  return ZEBRA_OK;
332 }
333 
334 
335 /*
336  * Local variables:
337  * c-basic-offset: 4
338  * c-file-style: "Stroustrup"
339  * indent-tabs-mode: nil
340  * End:
341  * vim: shiftwidth=4 tabstop=8 expandtab
342  */
343 
void dict_clean(Dict dict)
reset Dictionary (makes it empty)
Definition: open.c:31
int dict_close(Dict dict)
closes dictionary
Definition: close.c:32
static Dict dict
Definition: dicttest.c:35
struct dir_entry * dir_open(const char *rep, const char *base, int follow_links)
Definition: dir.c:48
void dir_sort(struct dir_entry *e)
Definition: dir.c:138
int zebra_file_stat(const char *file_name, struct stat *buf, int follow_links)
Definition: dir.c:38
void dir_free(struct dir_entry **e_p)
Definition: dir.c:146
struct dirs_info * dirs_fopen(Dict dict, const char *path, int rw)
Definition: dirs.c:105
void dirs_mkdir(struct dirs_info *p, const char *src, time_t mtime)
Definition: dirs.c:170
void dirs_rmdir(struct dirs_info *p, const char *src)
Definition: dirs.c:180
struct dirs_entry * dirs_last(struct dirs_info *p)
Definition: dirs.c:165
void dirs_add(struct dirs_info *p, const char *src, zint sysno, time_t mtime)
Definition: dirs.c:190
void dirs_free(struct dirs_info **pp)
Definition: dirs.c:217
struct dirs_entry * dirs_read(struct dirs_info *p)
Definition: dirs.c:134
struct dirs_info * dirs_open(Dict dict, const char *rep, int rw)
Definition: dirs.c:83
void dirs_del(struct dirs_info *p, const char *src)
Definition: dirs.c:203
ZEBRA_RES zebra_extract_file(ZebraHandle zh, zint *sysno, const char *fname, enum zebra_recctrl_action_t action)
Definition: extract.c:609
Dict dict_open_res(BFiles bfs, const char *name, int cache, int rw, int compact_flag, Res res)
Definition: zebraapi.c:321
#define FMATCH_DICT
Definition: index.h:105
@ dirs_file
Definition: index.h:55
@ dirs_dir
Definition: index.h:55
@ action_delete
Definition: recctrl.h:93
@ action_update
Definition: recctrl.h:95
Definition: index.h:57
time_t mtime
Definition: index.h:60
enum dirsKind kind
Definition: index.h:58
char * name
Definition: index.h:59
Definition: index.h:63
zint sysno
Definition: index.h:66
enum dirsKind kind
Definition: index.h:64
char path[256]
Definition: index.h:65
time_t mtime
Definition: index.h:67
Definition: dirs.c:35
ZebraExplainInfo zei
Definition: index.h:139
BFiles bfs
Definition: index.h:137
struct zebra_register * reg
Definition: index.h:174
char ** basenames
Definition: index.h:178
int m_flag_rw
Definition: index.h:225
char * path_reg
Definition: index.h:182
int m_follow_links
Definition: index.h:218
static ZEBRA_RES zebra_open_fmatch(ZebraHandle zh, Dict *dictp)
Definition: update_file.c:278
static void fileDelete_r(ZebraHandle zh, struct dirs_info *di, struct dirs_entry *dst, const char *base, char *src)
Definition: update_file.c:48
ZEBRA_RES zebra_remove_file_match(ZebraHandle zh)
Definition: update_file.c:294
ZEBRA_RES zebra_update_file_match(ZebraHandle zh, const char *path)
Definition: update_file.c:307
static void file_update_top(ZebraHandle zh, Dict dict, const char *path)
Definition: update_file.c:213
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:77
static int repComp(const char *a, const char *b, size_t len)
Definition: update_file.c:41
long zint
Zebra integer.
Definition: util.h:66
#define ZEBRA_FAIL
Definition: util.h:81
#define ZEBRA_OK
Definition: util.h:82
short ZEBRA_RES
Common return type for Zebra API.
Definition: util.h:80
int zebraExplain_curDatabase(ZebraExplainInfo zei, const char *database)
Definition: zinfo.c:790
int zebraExplain_get_database_ord(ZebraExplainInfo zei)
Definition: zinfo.c:1620
int zebraExplain_newDatabase(ZebraExplainInfo zei, const char *database, int explain_database)
Definition: zinfo.c:882