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