New feature: databases. Implemented as prefix to words in dictionary.
[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.5  1995-10-17 18:02:09  adam
8  * New feature: databases. Implemented as prefix to words in dictionary.
9  *
10  * Revision 1.4  1995/09/28  09:19:46  adam
11  * xfree/xmalloc used everywhere.
12  * Extract/retrieve method seems to work for text records.
13  *
14  * Revision 1.3  1995/09/06  16:11:18  adam
15  * Option: only one word key per file.
16  *
17  * Revision 1.2  1995/09/04  12:33:43  adam
18  * Various cleanup. YAZ util used instead.
19  *
20  * Revision 1.1  1995/09/01  14:06:36  adam
21  * Split of work into more files.
22  *
23  */
24 #include <stdio.h>
25 #include <assert.h>
26 #include <unistd.h>
27 #include <dirent.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <fcntl.h>
31 #include <ctype.h>
32
33 #include <alexutil.h>
34 #include "index.h"
35
36 static void repository_extract_r (int cmd, char *rep, char *databaseName)
37 {
38     struct dir_entry *e;
39     int i;
40     struct stat fs;
41     size_t rep_len = strlen (rep);
42
43     e = dir_open (rep);
44     if (!e)
45         return;
46     if (rep[rep_len-1] != '/')
47         rep[rep_len] = '/';
48     else
49         --rep_len;
50     for (i=0; e[i].name; i++)
51     {
52         strcpy (rep +rep_len+1, e[i].name);
53         stat (rep, &fs);
54         switch (fs.st_mode & S_IFMT)
55         {
56         case S_IFREG:
57             file_extract (cmd, rep, rep, databaseName);
58             break;
59         case S_IFDIR:
60             repository_extract_r (cmd, rep, databaseName);
61             break;
62         }
63     }
64     dir_free (&e);
65 }
66
67 void copy_file (const char *dst, const char *src)
68 {
69     int d_fd = open (dst, O_WRONLY|O_CREAT, 0666);
70     int s_fd = open (src, O_RDONLY);
71     char *buf;
72     size_t i, r, w;
73
74     if (d_fd == -1)
75     {
76         logf (LOG_FATAL|LOG_ERRNO, "Cannot create %s", dst);
77         exit (1);
78     }
79     if (s_fd == -1)
80     {
81         logf (LOG_FATAL|LOG_ERRNO, "Cannot open %s", src);
82         exit (1);
83     }
84     buf = xmalloc (4096);
85     while ((r=read (s_fd, buf, 4096))>0)
86         for (w = 0; w < r; w += i)
87         {
88             i = write (d_fd, buf + w, r - w);
89             if (i == -1)
90             {
91                 logf (LOG_FATAL|LOG_ERRNO, "write");
92                 exit (1);
93             }
94         }
95     if (r)
96     {
97         logf (LOG_FATAL|LOG_ERRNO, "read");
98         exit (1);
99     }
100     xfree (buf);
101     close (d_fd);
102     close (s_fd);
103 }
104
105 void del_file (const char *dst)
106 {
107     unlink (dst);
108 }
109
110 void del_dir (const char *dst)
111 {
112     logf (LOG_DEBUG, "rmdir of %s", dst);
113     if (rmdir (dst) == -1)
114         logf (LOG_ERRNO|LOG_WARN, "rmdir");
115 }
116
117 void repository_update_r (int cmd, char *dst, char *src, char *databaseName);
118
119 void repository_add_tree (int cmd, char *dst, char *src, char *databaseName)
120 {
121     mkdir (dst, 0755);
122     repository_update_r (cmd, dst, src, databaseName);
123 }
124
125 void repository_del_tree (int cmd, char *dst, char *src, char *databaseName)
126 {
127     size_t dst_len = strlen (dst);
128     size_t src_len = strlen (src);
129     struct dir_entry *e_dst;
130     int i_dst = 0;
131     struct stat fs_dst;
132
133     e_dst = dir_open (dst);
134
135     dir_sort (e_dst);
136
137     if (src[src_len-1] != '/')
138         src[src_len] = '/';
139     else
140         --src_len;
141     if (dst[dst_len-1] != '/')
142         dst[dst_len] = '/';
143     else
144         --dst_len;
145     while (e_dst[i_dst].name)
146     {
147         strcpy (dst +dst_len+1, e_dst[i_dst].name);
148         strcpy (src +src_len+1, e_dst[i_dst].name);
149         
150         stat (dst, &fs_dst);
151         switch (fs_dst.st_mode & S_IFMT)
152         {
153         case S_IFREG:
154             file_extract ('d', dst, dst, databaseName);
155             del_file (dst);
156             break;
157         case S_IFDIR:
158             repository_del_tree (cmd, dst, src, databaseName);
159             break;
160         }
161         i_dst++;
162     }
163     dir_free (&e_dst);
164     if (dst_len > 0)
165     {
166         dst[dst_len] = '\0';
167         del_dir (dst);
168     }
169 }
170
171 void repository_update_r (int cmd, char *dst, char *src, char *databaseName)
172 {
173     struct dir_entry *e_dst, *e_src;
174     int i_dst = 0, i_src = 0;
175     struct stat fs_dst, fs_src;
176     size_t dst_len = strlen (dst);
177     size_t src_len = strlen (src);
178
179     e_dst = dir_open (dst);
180     e_src = dir_open (src);
181
182     if (!e_dst && !e_src)
183         return;
184     if (!e_dst)
185     {
186         dir_free (&e_src);
187         repository_add_tree (cmd, dst, src, databaseName);
188         return;
189     }
190     else if (!e_src)
191     {
192         dir_free (&e_dst);
193         repository_del_tree (cmd, dst, src, databaseName);
194         return;
195     }
196
197     dir_sort (e_src);
198     dir_sort (e_dst);
199
200     if (src[src_len-1] != '/')
201         src[src_len] = '/';
202     else
203         --src_len;
204     if (dst[dst_len-1] != '/')
205         dst[dst_len] = '/';
206     else
207         --dst_len;
208     while (e_dst[i_dst].name || e_src[i_src].name)
209     {
210         int sd;
211
212         if (e_dst[i_dst].name && e_src[i_src].name)
213             sd = strcmp (e_dst[i_dst].name, e_src[i_src].name);
214         else if (e_src[i_src].name)
215             sd = 1;
216         else
217             sd = -1;
218                 
219         if (sd == 0)
220         {
221             strcpy (dst +dst_len+1, e_dst[i_dst].name);
222             strcpy (src +src_len+1, e_src[i_src].name);
223             
224             /* check type, date, length */
225
226             stat (dst, &fs_dst);
227             stat (src, &fs_src);
228                 
229             switch (fs_dst.st_mode & S_IFMT)
230             {
231             case S_IFREG:
232                 if (fs_src.st_ctime > fs_dst.st_ctime)
233                 {
234                     file_extract ('d', dst, dst, databaseName);
235                     file_extract ('a', src, dst, databaseName);
236                     copy_file (dst, src);
237                 }
238                 break;
239             case S_IFDIR:
240                 repository_update_r (cmd, dst, src, databaseName);
241                 break;
242             }
243             i_src++;
244             i_dst++;
245         }
246         else if (sd > 0)
247         {
248             strcpy (dst +dst_len+1, e_src[i_src].name);
249             strcpy (src +src_len+1, e_src[i_src].name);
250             
251             stat (src, &fs_src);
252             switch (fs_src.st_mode & S_IFMT)
253             {
254             case S_IFREG:
255                 file_extract ('a', src, dst, databaseName);
256                 copy_file (dst, src);
257                 break;
258             case S_IFDIR:
259                 repository_add_tree (cmd, dst, src, databaseName);
260                 break;
261             }
262             i_src++;
263         }
264         else 
265         {
266             strcpy (dst +dst_len+1, e_dst[i_dst].name);
267             strcpy (src +src_len+1, e_dst[i_dst].name);
268             
269             stat (dst, &fs_dst);
270             switch (fs_dst.st_mode & S_IFMT)
271             {
272             case S_IFREG:
273                 file_extract ('d', dst, dst, databaseName);
274                 del_file (dst);
275                 break;
276             case S_IFDIR:
277                 repository_del_tree (cmd, dst, src, databaseName);
278                 break;
279             }
280             i_dst++;
281         }
282     }
283     dir_free (&e_dst);
284     dir_free (&e_src);
285 }
286
287 void repository (int cmd, const char *rep, const char *base_path,
288                  char *databaseName)
289 {
290     char rep_tmp1[2048];
291     char rep_tmp2[2048];
292
293     strcpy (rep_tmp1, rep);
294     if (base_path)
295     {
296         strcpy (rep_tmp2, base_path);
297         repository_update_r (cmd, rep_tmp2, rep_tmp1, databaseName);
298     }
299     else
300         repository_extract_r (cmd, rep_tmp1, databaseName);
301 }
302