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