1 /* changeset-utils.c:
2  *
3  ****************************************************************
4  * Copyright (C) 2003 Tom Lord
5  *
6  * See the file "COPYING" for further information about
7  * the copyright and warranty status of this work.
8  */
9 
10 
11 #include "hackerlab/os/errno.h"
12 #include "hackerlab/os/errno-to-string.h"
13 #include "hackerlab/fmt/cvt.h"
14 #include "hackerlab/mem/mem.h"
15 #include "hackerlab/char/char-class.h"
16 #include "hackerlab/char/str.h"
17 #include "hackerlab/char/pika-escaping-utils.h"
18 #include "hackerlab/fs/file-names.h"
19 #include "hackerlab/vu/safe.h"
20 #include "tla/libfsutils/read-line.h"
21 #include "tla/libfsutils/safety.h"
22 #include "tla/libarch/invent.h"
23 #include "tla/libarch/changeset-utils.h"
24 
25 
26 /* __STDC__ prototypes for static functions */
27 static void changeset_inv_callback (const t_uchar * path,
28                                     struct stat * stat_buf,
29                                     enum arch_inventory_category category,
30                                     const t_uchar * id,
31                                     int has_source_name,
32                                     void * closure,
33                                     int escape_classes);
34 
35 
36 
37 void
arch_changeset_inventory(struct arch_changeset_inventory * inv_out,const t_uchar * tree_root,const t_uchar * path,enum arch_id_tagging_method method,enum arch_inventory_category untagged_source_category,int escape_classes)38 arch_changeset_inventory (struct arch_changeset_inventory * inv_out,
39                           const t_uchar * tree_root,
40                           const t_uchar * path,
41                           enum arch_id_tagging_method method,
42                           enum arch_inventory_category untagged_source_category,
43                           int escape_classes)
44 {
45   int here_fd;
46   struct arch_inventory_options options;
47 
48   here_fd = safe_open (".", O_RDONLY, 0);
49 
50   mem_set0 ((t_uchar *)&options, sizeof (options));
51   options.categories = arch_inventory_source;
52   options.want_ids = 1;
53   options.treat_unrecognized_source_as_source = 1;
54 
55   if (method != arch_unspecified_id_tagging)
56     {
57       options.method = method;
58       options.untagged_source_category = untagged_source_category;
59       options.override_method = 1;
60     }
61   options.nested = 0;
62   options.include_excluded = 1;
63 
64   arch_get_inventory_naming_conventions (&options, tree_root);
65 
66   inv_out->method = options.method;
67 
68   safe_chdir (path);
69   arch_inventory_traversal (&options, ".", changeset_inv_callback, (void *)inv_out, escape_classes);
70   arch_free_inventory_naming_conventions (&options);
71 
72   rel_sort_table_by_field (0, inv_out->dirs, 1);
73   rel_sort_table_by_field (0, inv_out->files, 1);
74 
75   safe_fchdir (here_fd);
76 
77   safe_close (here_fd);
78 }
79 
80 
81 void
arch_free_changeset_inventory_data(struct arch_changeset_inventory * i)82 arch_free_changeset_inventory_data (struct arch_changeset_inventory * i)
83 {
84   rel_free_table (i->dirs);     i->dirs = rel_table_nil;
85   rel_free_table (i->files);    i->files = rel_table_nil;
86 }
87 
88 
89 rel_table
arch_read_changeset_index(const t_uchar * path)90 arch_read_changeset_index (const t_uchar * path)
91 {
92   int in_fd;
93   rel_table answer = rel_table_nil;
94   t_uchar * line;
95   long len;
96 
97   in_fd = safe_open (path, O_RDONLY, 0);
98 
99   while (1)
100     {
101       t_uchar * loc;
102       t_uchar * id;
103       t_uchar * start;
104 
105       line = 0;
106       len = 0;
107       safe_next_line (&line, &len, in_fd);
108 
109       if (!len)
110         break;
111 
112       while (len && char_is_space (*line))
113         {
114           ++line;
115           --len;
116         }
117 
118       start = line;
119       while (len && !char_is_space (*line))
120         {
121           ++line;
122           --len;
123         }
124 
125       if (line == start)
126         {
127         syntax_error:
128           safe_printfmt (2, "illegally formed changeset index (%s)\n", path);
129           exit (2);
130         }
131 
132       loc = pika_save_unescape_iso8859_1_n (0, 0, start, line - start );
133 
134       while (len && char_is_space (*line))
135         {
136           ++line;
137           --len;
138         }
139 
140       start = line;
141 
142       while (len && !char_is_space (*line))
143         {
144           ++line;
145           --len;
146         }
147 
148       if (line == start)
149         goto syntax_error;
150 
151       id = pika_save_unescape_iso8859_1_n (0, 0, start, line - start );
152 
153       while (len && char_is_space (*line))
154         {
155           ++line;
156           --len;
157         }
158 
159       if (len)
160         goto syntax_error;
161 
162       if (!is_non_upwards_relative_path (loc))
163         {
164           safe_printfmt (2, "illegal path in changeset: %s\n", loc);
165           exit (2);
166         }
167 
168       rel_add_records (&answer, rel_make_record_2_taking (rel_make_field_str (loc), rel_make_field_str (id)), rel_record_null);
169       lim_free (0, loc);
170       lim_free (0, id);
171     }
172 
173   safe_close (in_fd);
174   return answer;
175 }
176 
177 
178 rel_table
arch_read_changeset_dir_metadata(const t_uchar * path)179 arch_read_changeset_dir_metadata (const t_uchar * path)
180 {
181   int errn;
182   int in_fd;
183   rel_table answer = rel_table_nil;
184 
185   in_fd = vu_open (&errn, path, O_RDONLY, 0);
186   if (in_fd < 0)
187     {
188       if (errn == ENOENT)
189         return rel_table_nil;
190       else
191         {
192           safe_printfmt (2, "arch_read_changeset_dir_metadata: unable to open file (%s)\n", path);
193           safe_printfmt (2, "  %s\n", errno_to_string (errn));
194           exit (2);
195         }
196     }
197 
198   while (1)
199     {
200       t_uchar * line;
201       long len;
202       t_uchar * start;
203       t_uchar * perms = 0;
204       t_uchar * loc = 0;
205 
206       line = 0;
207       len = 0;
208       safe_next_line (&line, &len, in_fd);
209       if (!len)
210         break;
211 
212       while (len && char_is_space (*line))
213         {
214           ++line;
215           --len;
216         }
217 
218       if ((len < 13) || str_cmp_prefix ("--permissions", line))
219         {
220         syntax_error:
221           safe_printfmt (2, "illegal dir metadata file: %s\n", path);
222           exit (2);
223         }
224       len -= 13;
225       line += 13;
226 
227       while (len && char_is_space (*line))
228         {
229           ++line;
230           --len;
231         }
232 
233       start = line;
234       while (len && !char_is_space (*line))
235         {
236           ++line;
237           --len;
238         }
239 
240       if (start == line)
241         goto syntax_error;
242 
243       perms = pika_save_unescape_iso8859_1_n (0, 0, start, line - start );
244 
245       while (len && char_is_space (*line))
246         {
247           ++line;
248           --len;
249         }
250 
251       start = line;
252       while (len && !char_is_space (*line))
253         {
254           ++line;
255           --len;
256         }
257 
258       if (start == line)
259         goto syntax_error;
260 
261       loc = pika_save_unescape_iso8859_1_n (0, 0, start, line - start );
262 
263       if (!is_non_upwards_relative_path (loc))
264         {
265           safe_printfmt (2, "illegal path in changeset: %s\n", loc);
266           exit (2);
267         }
268 
269       rel_add_records (&answer, rel_make_record_2_taking (rel_make_field_str (loc), rel_make_field_str (perms)), rel_record_null);
270 
271       lim_free (0, perms);
272       lim_free (0, loc);
273     }
274 
275   safe_close (in_fd);
276 
277   rel_sort_table_by_field (0, answer, 0);
278 
279   return answer;
280 }
281 
282 
283 mode_t
arch_read_permissions_patch(long * uid,long * gid,const t_uchar * file)284 arch_read_permissions_patch (long * uid, long * gid, const t_uchar * file)
285 {
286   int errn;
287   t_uchar * line = 0;
288   t_uchar * s;
289   t_uchar * e;
290   t_ulong answer;
291 
292   line = read_line_from_file (file);
293 
294   s = line;
295 
296   while (char_is_space (*s))
297     ++s;
298   if (str_cmp_prefix ("--permissions", s))
299     {
300     syntax_error:
301       safe_printfmt (2, "illegal metadata patch file: %s\n", file);
302       exit (2);
303     }
304   s += sizeof ("--permissions") - 1;
305   while (char_is_space (*s))
306     ++s;
307 
308   for (e = s; char_is_odigit (*e); ++e)
309     ;
310 
311   if (e == s)
312     goto syntax_error;
313 
314   if (cvt_octal_to_ulong (&errn, &answer, s, e - s))
315     goto syntax_error;
316 
317   if (*e != ',')
318     {
319       if (uid)
320         *uid = -1;
321       if (uid)
322         *uid = -1;
323     }
324   else
325     {
326       s = e + 1;
327       for (e = s; char_is_digit (*e); ++e)
328         ;
329 
330       if (e == s)
331         goto syntax_error;
332 
333       if (uid && cvt_decimal_to_long (&errn, uid, s, e - s))
334         goto syntax_error;
335 
336       if (*e != ',')
337         {
338           if (uid)
339             *uid = -1;
340           if (uid)
341             *uid = -1;
342         }
343       else
344         {
345           s = e + 1;
346           for (e = s; char_is_digit (*e); ++e)
347             ;
348 
349           if (e == s)
350             goto syntax_error;
351 
352           if (gid && cvt_decimal_to_long (&errn, gid, s, e - s))
353             goto syntax_error;
354         }
355     }
356 
357   lim_free (0, line);
358   return (mode_t)answer;
359 }
360 
361 
362 mode_t
arch_parse_permissions_params(long * uid,long * gid,const t_uchar * const line)363 arch_parse_permissions_params (long * uid, long * gid, const t_uchar * const line)
364 {
365   int errn;
366   const t_uchar * s;
367   const t_uchar * e;
368   t_ulong answer;
369 
370   s = line;
371 
372   while (char_is_space (*s))
373     ++s;
374 
375   for (e = s; char_is_odigit (*e); ++e)
376     ;
377 
378   if (e == s)
379     {
380     syntax_error:
381       safe_printfmt (2, "illegal metadata patch param: %s\n", line);
382       exit (2);
383     }
384 
385   if (cvt_octal_to_ulong (&errn, &answer, s, e - s))
386     goto syntax_error;
387 
388   if (*e != ',')
389     {
390       if (uid)
391         *uid = -1;
392       if (uid)
393         *uid = -1;
394     }
395   else
396     {
397       s = e + 1;
398       for (e = s; char_is_digit (*e); ++e)
399         ;
400 
401       if (e == s)
402         goto syntax_error;
403 
404       if (uid && cvt_decimal_to_long (&errn, uid, s, e - s))
405         goto syntax_error;
406 
407       if (*e != ',')
408         {
409           if (uid)
410             *uid = -1;
411           if (uid)
412             *uid = -1;
413         }
414       else
415         {
416           s = e + 1;
417           for (e = s; char_is_digit (*e); ++e)
418             ;
419 
420           if (e == s)
421             goto syntax_error;
422 
423           if (gid && cvt_decimal_to_long (&errn, gid, s, e - s))
424             goto syntax_error;
425         }
426     }
427 
428   return (mode_t)answer;
429 }
430 
431 
432 
433 
434 
435 static void
changeset_inv_callback(const t_uchar * path,struct stat * stat_buf,enum arch_inventory_category category,const t_uchar * id,int has_source_name,void * closure,int escape_classes)436 changeset_inv_callback (const t_uchar * path,
437                         struct stat * stat_buf,
438                         enum arch_inventory_category category,
439                         const t_uchar * id,
440                         int has_source_name,
441                         void * closure,
442                         int escape_classes)
443 {
444   struct arch_changeset_inventory * index;
445 
446   index = (struct arch_changeset_inventory *)closure;
447 
448   if (!id)
449     {
450       t_uchar * dir = 0;
451 
452       dir = file_name_directory_file (0, path);
453       if (!arch_is_dont_care_explicit_dflt_dir (dir))
454         {
455           t_uchar * e_path = 0;
456 
457           e_path = pika_save_escape_iso8859_1 (0, 0, escape_classes, path);
458           safe_printfmt (2, "missing explicit id for file (try tree-lint)\n   file:%s\n", e_path);
459           exit (2);
460         }
461       lim_free (0, dir);
462 
463       return;
464     }
465 
466 
467   if (S_ISDIR (stat_buf->st_mode))
468     rel_add_records (&index->dirs, rel_make_record_2_taking (rel_make_field_str (path), rel_make_field_str (id)), rel_record_null);
469   else
470     rel_add_records (&index->files, rel_make_record_2_taking (rel_make_field_str (path), rel_make_field_str (id)), rel_record_null);
471 }
472 
473 
474 /* tag: Tom Lord Thu May 15 13:00:33 2003 (changeset-utils.c)
475  */
476