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