Minor changes.
[idzebra-moved-to-github.git] / index / main.c
1 /*
2  * Copyright (C) 1994, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: main.c,v $
7  * Revision 1.3  1995-09-01 10:57:07  adam
8  * Minor changes.
9  *
10  * Revision 1.2  1995/09/01  10:30:24  adam
11  * More work on indexing. Not working yet.
12  *
13  * Revision 1.1  1995/08/31  14:50:24  adam
14  * New simple file index tool.
15  *
16  */
17 #include <stdio.h>
18 #include <assert.h>
19 #include <unistd.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <fcntl.h>
23 #include <ctype.h>
24
25 #include <util.h>
26 #include "index.h"
27
28 char *prog;
29
30 static int key_fd = -1;
31 #define KEY_BUF_SIZE 100000
32 static char *key_buf;
33 int key_offset;
34 SYSNO sysno_next;
35 Dict file_idx;
36 static char *base_path = NULL;
37
38 void key_open (const char *fname)
39 {
40     void *file_key;
41     if (key_fd != -1)
42         return;
43     if ((key_fd = open (fname, O_RDWR|O_CREAT, 0666)) == -1)
44     {
45         log (LOG_FATAL|LOG_ERRNO, "Creat %s", fname);
46         exit (1);
47     }
48     if (!(key_buf = malloc (KEY_BUF_SIZE)))
49     {
50         log (LOG_FATAL|LOG_ERRNO, "malloc");
51         exit (1);
52     }
53     key_offset = 0;
54     if (!(file_idx = dict_open ("fileidx", 10, 1)))
55     {
56         log (LOG_FATAL, "dict_open fail of %s", "fileidx");
57         exit (1);
58     }
59     file_key = dict_lookup (file_idx, ".");
60     if (file_key)
61         memcpy (&sysno_next, (char*)file_key+1, sizeof(sysno_next));
62     else
63         sysno_next = 1;
64 }
65
66 void key_close (void)
67 {
68     if (key_fd == -1)
69         return;
70     close (key_fd);
71     dict_insert (file_idx, ".", sizeof(sysno_next), &sysno_next);
72     dict_close (file_idx);
73     key_fd = -1;
74 }
75
76 void key_flush (void)
77 {
78     size_t i = 0;
79     int w;
80     
81     while (i < key_offset)
82     {
83         w = write (key_fd, key_buf + i, key_offset - i);
84         if (w == -1)
85         {
86             log (LOG_FATAL|LOG_ERRNO, "Write key fail");
87             exit (1);
88         }
89         i += w;
90     }
91     key_offset = 0;
92 }
93
94 void key_write (int cmd, struct it_key *k, const char *str)
95 {
96     char x = cmd;
97     size_t slen = strlen(str);
98
99     if (key_offset + sizeof(*k) + slen >= KEY_BUF_SIZE - 2)
100         key_flush ();
101     memcpy (key_buf + key_offset, &x, 1);
102     key_offset++;
103     memcpy (key_buf + key_offset, k, sizeof(*k));
104     key_offset += sizeof(*k);
105     memcpy (key_buf + key_offset, str, slen+1);
106     key_offset += slen+1;
107 }
108
109 void text_extract (SYSNO sysno, int cmd, const char *fname)
110 {
111     FILE *inf;
112     struct it_key k;
113     int seqno = 1;
114     int c;
115     char w[256];
116
117     log (LOG_DEBUG, "Text extract of %d", sysno);
118     k.sysno = sysno;
119     inf = fopen (fname, "r");
120     if (!inf)
121     {
122         log (LOG_WARN|LOG_ERRNO, "open %s", fname);
123         return;
124     }
125     while ((c=getc (inf)) != EOF)
126     {
127         int i = 0;
128         while (i < 254 && c != EOF && isalnum(c))
129         {
130             w[i++] = c;
131             c = getc (inf);
132         }
133         if (i)
134         {
135             w[i] = 0;
136             
137             k.seqno = seqno++;
138             k.field = 0;
139             key_write (cmd, &k, w);
140         }
141         if (c == EOF)
142             break;
143     }
144     fclose (inf);
145 }
146
147 void file_extract (int cmd, struct stat *fs, const char *fname,
148                    const char *kname)
149 {
150     int i;
151     char ext[128];
152     SYSNO sysno;
153     char ext_res[128];
154     const char *file_type;
155     void *file_info;
156
157     log (LOG_DEBUG, "%c %s k=%s", cmd, fname, kname);
158     return;
159     for (i = strlen(fname); --i >= 0; )
160         if (fname[i] == '/')
161         {
162             strcpy (ext, "");
163             break;
164         }
165         else if (fname[i] == '.')
166         {
167             strcpy (ext, fname+i+1);
168             break;
169         }
170     sprintf (ext_res, "fileExtension.%s", ext);
171     if (!(file_type = res_get (common_resource, ext_res)))
172         return;
173     
174     file_info = dict_lookup (file_idx, fname);
175     if (!file_info)
176     {
177         sysno = sysno_next++;
178         dict_insert (file_idx, fname, sizeof(sysno), &sysno);
179     }
180     else
181         memcpy (&sysno, (char*) file_info+1, sizeof(sysno));
182     if (!strcmp (file_type, "text"))
183         text_extract (sysno, cmd, fname);
184 }
185
186 static void repository_extract_r (int cmd, char *rep)
187 {
188     struct dir_entry *e;
189     int i;
190     struct stat fs;
191     size_t rep_len = strlen (rep);
192
193     e = dir_open (rep);
194     if (!e)
195         return;
196     if (rep[rep_len-1] != '/')
197         rep[rep_len] = '/';
198     else
199         --rep_len;
200     for (i=0; e[i].name; i++)
201     {
202         if (!strcmp (e[i].name, ".") || !strcmp (e[i].name, ".."))
203             continue;
204         strcpy (rep +rep_len+1, e[i].name);
205         stat (rep, &fs);
206         switch (fs.st_mode & S_IFMT)
207         {
208         case S_IFREG:
209             file_extract (cmd, &fs, rep, rep);
210             break;
211         case S_IFDIR:
212             repository_extract_r (cmd, rep);
213             break;
214         }
215     }
216     dir_free (&e);
217 }
218
219 void repository_update_r (int cmd, char *dst, char *src);
220
221 void repository_add_tree (int cmd, char *dst, char *src)
222 {
223     mkdir (dst, 0755);
224     repository_update_r (cmd, dst, src);
225 }
226
227 void repository_del_tree (int cmd, char *dst, char *src)
228 {
229     log (LOG_DEBUG, "rmdir of %s", dst);
230 }
231
232 void repository_update_r (int cmd, char *dst, char *src)
233 {
234     struct dir_entry *e_dst, *e_src;
235     int i_dst = 0, i_src = 0;
236     struct stat fs_dst, fs_src;
237     size_t dst_len = strlen (dst);
238     size_t src_len = strlen (src);
239
240     e_dst = dir_open (dst);
241     e_src = dir_open (src);
242
243     if (!e_dst && !e_src)
244         return;
245     if (!e_dst)
246         repository_add_tree (cmd, dst, src);
247     else if (!e_src)
248         repository_del_tree (cmd, dst, src);
249
250     dir_sort (e_src);
251     dir_sort (e_dst);
252
253     if (src[src_len-1] != '/')
254         src[src_len] = '/';
255     else
256         --src_len;
257     if (dst[dst_len-1] != '/')
258         dst[dst_len] = '/';
259     else
260         --dst_len;
261     while (e_dst[i_dst].name || e_src[i_src].name)
262     {
263         int sd;
264
265         if (e_dst[i_dst].name && e_src[i_src].name)
266             sd = strcmp (e_dst[i_dst].name, e_src[i_src].name);
267         else if (e_src[i_src].name)
268             sd = 1;
269         else
270             sd = -1;
271                 
272         if (sd == 0)
273         {
274             strcpy (dst +dst_len+1, e_dst[i_dst].name);
275             strcpy (src +src_len+1, e_src[i_src].name);
276             
277             /* check type, date, length */
278
279             if (strcmp (e_dst[i_dst].name, ".") &&
280                 strcmp (e_dst[i_dst].name, ".."))
281             {
282                 stat (dst, &fs_dst);
283                 stat (src, &fs_src);
284                 
285                 switch (fs_dst.st_mode & S_IFMT)
286                 {
287                 case S_IFREG:
288                     if (fs_src.st_mtime != fs_dst.st_mtime)
289                     {
290                         file_extract ('d', &fs_dst, dst, dst);
291                         file_extract ('a', &fs_src, src, dst);
292                     }
293                     break;
294                 case S_IFDIR:
295                     repository_update_r (cmd, dst, src);
296                     break;
297                 }
298             }
299             i_src++;
300             i_dst++;
301         }
302         else if (sd > 0)
303         {
304             strcpy (dst +dst_len+1, e_src[i_src].name);
305             strcpy (src +src_len+1, e_src[i_src].name);
306             
307             stat (src, &fs_src);
308             switch (fs_src.st_mode & S_IFMT)
309             {
310             case S_IFREG:
311                 file_extract ('a', &fs_src, src, dst);
312                 break;
313             case S_IFDIR:
314                 repository_add_tree (cmd, dst, src);
315                 break;
316             }
317             i_src++;
318         }
319         else 
320         {
321             strcpy (dst +dst_len+1, e_dst[i_dst].name);
322             strcpy (src +src_len+1, e_dst[i_dst].name);
323             
324             stat (dst, &fs_dst);
325             switch (fs_dst.st_mode & S_IFMT)
326             {
327             case S_IFREG:
328                 file_extract ('d', &fs_dst, dst, dst);
329                 break;
330             case S_IFDIR:
331                 repository_del_tree (cmd, dst, src);
332                 break;
333             }
334             i_dst++;
335         }
336     }
337     dir_free (&e_dst);
338     dir_free (&e_src);
339 }
340
341 void repository_traverse (int cmd, const char *rep)
342 {
343     char rep_tmp1[2048];
344     char rep_tmp2[2048];
345
346     strcpy (rep_tmp1, rep);
347     if (base_path)
348     {
349         strcpy (rep_tmp2, base_path);
350         repository_update_r (cmd, rep_tmp2, rep_tmp1);
351     }
352     else
353         repository_extract_r (cmd, rep_tmp1);
354 }
355
356
357 int main (int argc, char **argv)
358 {
359     int ret;
360     int cmd = 0;
361     char *arg;
362     char *base_name;
363
364     prog = *argv;
365     while ((ret = options ("r:v:", argv, argc, &arg)) != -2)
366     {
367         if (ret == 0)
368         {
369             if (!base_name)
370             {
371                 base_name = arg;
372
373                 common_resource = res_open (base_name);
374                 if (!common_resource)
375                 {
376                     log (LOG_FATAL, "Cannot open resource `%s'", base_name);
377                     exit (1);
378                 }
379             }
380             else if(cmd == 0) /* command */
381             {
382                 if (!strcmp (arg, "add"))
383                 {
384                     cmd = 'a';
385                 }
386                 else if (!strcmp (arg, "del"))
387                 {
388                     cmd = 'd';
389                 }
390                 else
391                 {
392                     log (LOG_FATAL, "Unknown command: %s", arg);
393                     exit (1);
394                 }
395             }
396             else
397             {
398                 key_open ("keys.tmp");
399                 repository_traverse (cmd, arg);
400                 cmd = 0;
401             }
402         }
403         else if (ret == 'v')
404         {
405             log_init (log_mask_str(arg), prog, NULL);
406         }
407         else if (ret == 'r')
408         {
409             base_path = arg;
410         }
411         else
412         {
413             log (LOG_FATAL, "Unknown option '-%s'", arg);
414             exit (1);
415         }
416     }
417     key_flush ();
418     key_close ();
419     exit (0);
420 }