1 /* pristines.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/bugs/panic.h"
12 #include "hackerlab/char/char-class.h"
13 #include "hackerlab/char/str.h"
14 #include "hackerlab/fs/file-names.h"
15 #include "hackerlab/vu/safe.h"
16 #include "tla/libfsutils/dir-listing.h"
17 #include "tla/libfsutils/ensure-dir.h"
18 #include "tla/libfsutils/tmp-files.h"
19 #include "tla/libfsutils/rmrf.h"
20 #include "tla/libfsutils/copy-file.h"
21 #include "tla/libarch/project-tree.h"
22 #include "tla/libarch/invent.h"
23 #include "tla/libarch/build-revision.h"
24 #include "tla/libarch/inode-sig.h"
25 #include "tla/libarch/namespace.h"
26 #include "tla/libarch/pristines.h"
27
28
29
30 void
arch_make_pristine(const t_uchar * tree_root,const t_uchar * archive,const t_uchar * revision)31 arch_make_pristine (const t_uchar * tree_root,
32 const t_uchar * archive,
33 const t_uchar * revision)
34 {
35 rel_table inventory = rel_table_nil;
36 t_uchar * tmp_pristine = 0;
37 const int full_meta = arch_tree_has_meta_flag (tree_root);
38
39 inventory = arch_source_inventory (tree_root, 1, 0, 0);
40 tmp_pristine = tmp_file_name (tree_root, ",,pristine");
41 rmrf_file (tmp_pristine);
42 safe_mkdir (tmp_pristine, 0777);
43 copy_file_list (tmp_pristine, tree_root, inventory, full_meta);
44
45 arch_install_pristine (tree_root, archive, revision, tmp_pristine);
46
47 rel_free_table (inventory);
48 lim_free (0, tmp_pristine);
49 }
50
51
52 void
arch_add_pristine(int chatter_fd,const t_uchar * tree_root,struct arch_archive * arch,const t_uchar * archive,const t_uchar * revision)53 arch_add_pristine (int chatter_fd,
54 const t_uchar * tree_root,
55 struct arch_archive * arch,
56 const t_uchar * archive,
57 const t_uchar * revision)
58 {
59 t_uchar * tmp_path = 0;
60 t_uchar * cache_dir = 0;
61
62 tmp_path = tmp_file_name (tree_root, ",,new-pristine");
63 safe_mkdir (tmp_path, 0777);
64
65 cache_dir = file_name_directory_file (0, tree_root);
66 arch_build_revision (chatter_fd, tmp_path, arch, archive, revision, cache_dir);
67 arch_install_pristine (tree_root, archive, revision, tmp_path);
68
69 lim_free (0, tmp_path);
70 lim_free (0, cache_dir);
71 }
72
73
74 t_uchar *
arch_pristine_loc(const t_uchar * archive,const t_uchar * revision,int locked_p)75 arch_pristine_loc (const t_uchar * archive,
76 const t_uchar * revision,
77 int locked_p)
78 {
79 t_uchar * category = 0;
80 t_uchar * branch = 0;
81 t_uchar * version = 0;
82 t_uchar * answer = 0;
83
84 invariant (arch_valid_package_name (revision, arch_no_archive, arch_req_patch_level, 0));
85 invariant (arch_valid_archive_name (archive));
86
87 category = arch_parse_package_name (arch_ret_category, 0, revision);
88 branch = arch_parse_package_name (arch_ret_package, 0, revision);
89 version = arch_parse_package_name (arch_ret_package_version, 0, revision);
90
91 answer = str_alloc_cat_many (0, "{arch}/++pristine-trees/", (locked_p ? "locked" : "unlocked"), "/", category, "/", branch, "/", version, "/", archive, "/", revision, str_end);
92
93 lim_free (0, category);
94 lim_free (0, branch);
95 lim_free (0, version);
96
97 return answer;
98 }
99
100
101 t_uchar *
arch_pristine_path(const t_uchar * tree_root,const t_uchar * archive,const t_uchar * revision,int locked_p)102 arch_pristine_path (const t_uchar * tree_root,
103 const t_uchar * archive,
104 const t_uchar * revision,
105 int locked_p)
106 {
107 t_uchar * loc = 0;
108 t_uchar * answer = 0;
109
110 loc = arch_pristine_loc (archive, revision, locked_p);
111 answer = file_name_in_vicinity (0, tree_root, loc);
112
113 lim_free (0, loc);
114 return answer;
115 }
116
117
118 void
arch_install_pristine(const t_uchar * tree_root,const t_uchar * archive,const t_uchar * revision,const t_uchar * source)119 arch_install_pristine (const t_uchar * tree_root,
120 const t_uchar * archive,
121 const t_uchar * revision,
122 const t_uchar * source)
123 {
124 t_uchar * loc = 0;
125 t_uchar * path = 0;
126
127 arch_snap_inode_sig (source, archive, revision);
128
129 loc = arch_pristine_loc (archive, revision, 0);
130 path = file_name_in_vicinity (0, tree_root, loc);
131
132 ensure_directory_exists (path);
133 rmrf_file (path);
134 safe_rename (source, path);
135
136 lim_free (0, loc);
137 lim_free (0, path);
138 }
139
140
141 void
arch_lock_pristine(const t_uchar * tree_root,const t_uchar * archive,const t_uchar * revision)142 arch_lock_pristine (const t_uchar * tree_root,
143 const t_uchar * archive,
144 const t_uchar * revision)
145 {
146 t_uchar * locked_path = 0;
147 t_uchar * unlocked_path = 0;
148
149 locked_path = arch_pristine_path (tree_root, archive, revision, 1);
150 unlocked_path = arch_pristine_path (tree_root, archive, revision, 0);
151
152 if (safe_access (locked_path, F_OK))
153 {
154 t_uchar * locked_dir = 0;
155
156 if (safe_access (unlocked_path, F_OK))
157 {
158 safe_printfmt (2, "arch_lock_pristine: unlocked pristine tree not found for %s/%s\n", archive, revision);
159 exit (2);
160 }
161
162 locked_dir = file_name_directory_file (0, locked_path);
163 ensure_directory_exists (locked_dir);
164 safe_rename (unlocked_path, locked_path);
165
166 lim_free (0, locked_dir);
167 }
168
169 lim_free (0, locked_path);
170 lim_free (0, unlocked_path);
171 }
172
173
174 void
arch_unlock_pristine(const t_uchar * tree_root,const t_uchar * archive,const t_uchar * revision)175 arch_unlock_pristine (const t_uchar * tree_root,
176 const t_uchar * archive,
177 const t_uchar * revision)
178 {
179 t_uchar * locked_path = 0;
180 t_uchar * unlocked_path = 0;
181
182 locked_path = arch_pristine_path (tree_root, archive, revision, 1);
183 unlocked_path = arch_pristine_path (tree_root, archive, revision, 0);
184
185 if (safe_access (unlocked_path, F_OK))
186 {
187 t_uchar * unlocked_dir = 0;
188
189 if (safe_access (locked_path, F_OK))
190 {
191 safe_printfmt (2, "arch_unlock_pristine: locked pristine tree not found for %s/%s\n", archive, revision);
192 exit (2);
193 }
194
195 unlocked_dir = file_name_directory_file (0, unlocked_path);
196 ensure_directory_exists (unlocked_dir);
197 safe_rename (locked_path, unlocked_path);
198
199 lim_free (0, unlocked_dir);
200 }
201
202 lim_free (0, locked_path);
203 lim_free (0, unlocked_path);
204 }
205
206
207 rel_table
arch_pristines(const t_uchar * tree_root,const t_uchar * archive_limit,const t_uchar * limit,int pristine_types)208 arch_pristines (const t_uchar * tree_root,
209 const t_uchar * archive_limit,
210 const t_uchar * limit,
211 int pristine_types)
212 {
213 int here_fd;
214 int errn;
215 struct stat statb;
216 t_uchar * category = 0;
217 t_uchar * branch = 0;
218 t_uchar * version = 0;
219 const t_uchar * revision = 0;
220 t_uchar * locked_in_this_tree_path = 0;
221 t_uchar * unlocked_in_this_tree_path = 0;
222 rel_table answer = rel_table_nil;
223 int x;
224
225 here_fd = safe_open (".", O_RDONLY, 0);
226
227 if (archive_limit)
228 invariant (arch_valid_archive_name (archive_limit));
229
230 if (limit)
231 {
232 invariant (arch_valid_package_name (limit, arch_no_archive, arch_req_category, 1));
233
234 category = arch_parse_package_name (arch_ret_category, 0, limit);
235
236 if (arch_valid_package_name (limit, arch_no_archive, arch_req_package, 1))
237 {
238 branch = arch_parse_package_name (arch_ret_package, 0, limit);
239
240 if (arch_valid_package_name (limit, arch_no_archive, arch_req_version, 1))
241 {
242 version = arch_parse_package_name (arch_ret_package_version, 0, limit);
243
244 if (arch_valid_package_name (limit, arch_no_archive, arch_req_patch_level, 0))
245 {
246 revision = limit;
247 }
248 }
249 }
250 }
251
252 unlocked_in_this_tree_path = file_name_in_vicinity (0, tree_root, "{arch}/++pristine-trees/unlocked");
253 locked_in_this_tree_path = file_name_in_vicinity (0, tree_root, "{arch}/++pristine-trees/locked");
254
255 for (x = arch_unlocked_pristine; x != 0; (x = ((x == arch_unlocked_pristine) ? arch_locked_pristine : 0)))
256 {
257 if (x & pristine_types)
258 {
259 switch (x)
260 {
261 case arch_unlocked_pristine:
262 {
263 if (vu_chdir (&errn, unlocked_in_this_tree_path))
264 continue;
265 break;
266 }
267 case arch_locked_pristine:
268 {
269 if (vu_chdir (&errn, locked_in_this_tree_path))
270 continue;
271 break;
272 }
273 default:
274 {
275 panic ("not reached in arch_pristines");
276 }
277 }
278
279 {
280 rel_table maybe_categories = rel_table_nil;
281 int c;
282
283 if (category)
284 {
285 rel_add_records (&maybe_categories, rel_singleton_record_taking (rel_make_field_str (category)), rel_record_null);
286 }
287 else
288 {
289 maybe_categories = directory_files (".");
290 }
291
292
293 for (c = 0; c < rel_n_records (maybe_categories); ++c)
294 {
295
296 if (arch_valid_package_name (rel_peek_str (maybe_categories, c, 0), arch_no_archive, arch_req_category, 0)
297 && (!vu_lstat (&errn, rel_peek_str (maybe_categories, c, 0), &statb) && S_ISDIR (statb.st_mode)))
298 {
299 rel_table maybe_branches = rel_table_nil;
300 int b;
301
302 safe_chdir (rel_peek_str (maybe_categories, c, 0));
303
304 if (branch)
305 {
306 rel_add_records (&maybe_branches, rel_singleton_record_taking (rel_make_field_str (branch)), rel_record_null);
307 }
308 else
309 {
310 maybe_branches = directory_files (".");
311 }
312
313 for (b = 0; b < rel_n_records (maybe_branches); ++b)
314 {
315
316 if (arch_valid_package_name (rel_peek_str (maybe_branches, b, 0), arch_no_archive, arch_req_package, 0)
317 && (!vu_lstat (&errn, rel_peek_str (maybe_branches, b, 0), &statb) && S_ISDIR (statb.st_mode)))
318 {
319 rel_table maybe_versions = rel_table_nil;
320 int v;
321
322 safe_chdir (rel_peek_str (maybe_branches, b, 0));
323
324 if (version)
325 {
326 rel_add_records (&maybe_versions, rel_singleton_record_taking (rel_make_field_str (version)), rel_record_null);
327 }
328 else
329 {
330 maybe_versions = directory_files (".");
331 }
332
333 for (v = 0; v < rel_n_records (maybe_versions); ++v)
334 {
335 if (arch_valid_package_name (rel_peek_str (maybe_versions, v, 0), arch_no_archive, arch_req_version, 0)
336 && (!vu_lstat (&errn, rel_peek_str (maybe_versions, v, 0), &statb) && S_ISDIR (statb.st_mode)))
337 {
338 rel_table maybe_archives = rel_table_nil;
339 int a;
340
341 safe_chdir (rel_peek_str (maybe_versions, v, 0));
342
343 if (archive_limit)
344 {
345 rel_add_records (&maybe_archives, rel_singleton_record_taking (rel_make_field_str (archive_limit)), rel_record_null);
346 }
347 else
348 {
349 maybe_archives = directory_files (".");
350 }
351
352 for (a = 0; a < rel_n_records (maybe_archives); ++a)
353 {
354 if (arch_valid_archive_name (rel_peek_str (maybe_archives, a, 0)) && (!vu_lstat (&errn, rel_peek_str (maybe_archives, a, 0), &statb) && S_ISDIR (statb.st_mode)))
355 {
356 rel_table maybe_revisions = rel_table_nil;
357 int r;
358
359 safe_chdir (rel_peek_str (maybe_archives, a, 0));
360
361 if (revision)
362 {
363 rel_add_records (&maybe_revisions, rel_singleton_record_taking (rel_make_field_str (revision)), rel_record_null);
364 }
365 else
366 {
367 maybe_revisions = directory_files (".");
368 }
369
370 for (r = 0; r < rel_n_records (maybe_revisions); ++r)
371 {
372 if (arch_valid_package_name (rel_peek_str (maybe_revisions, r, 0), arch_no_archive, arch_req_patch_level, 0)
373 && (!vu_lstat (&errn, rel_peek_str (maybe_revisions, r, 0), &statb) && S_ISDIR (statb.st_mode)))
374 {
375 t_uchar * fqr = 0;
376
377 fqr = arch_fully_qualify (rel_peek_str (maybe_archives, a, 0), rel_peek_str (maybe_revisions, r, 0));
378 rel_add_records (&answer, rel_singleton_record_taking (rel_make_field_str (fqr)), rel_record_null);
379 lim_free (0, fqr);
380 }
381 }
382
383 safe_chdir ("..");
384 rel_free_table (maybe_revisions);
385 }
386 }
387
388 safe_chdir ("..");
389 rel_free_table (maybe_archives);
390 }
391 }
392
393 safe_chdir ("..");
394 rel_free_table (maybe_versions);
395 }
396 }
397
398 safe_chdir ("..");
399 rel_free_table (maybe_branches);
400 }
401 }
402
403 safe_fchdir (here_fd);
404 rel_free_table (maybe_categories);
405 }
406 }
407 }
408
409 arch_sort_table_by_name_field (0, answer, 0);
410
411 safe_close (here_fd);
412
413 lim_free (0, category);
414 lim_free (0, branch);
415 lim_free (0, version);
416 lim_free (0, locked_in_this_tree_path);
417 lim_free (0, unlocked_in_this_tree_path);
418
419 return answer;
420 }
421
422
423 t_uchar *
arch_find_pristine(int * is_locked,const t_uchar * tree_root_or_root_dir,const t_uchar * archive,const t_uchar * revision,int pristine_types,enum arch_pristine_search_scope scope)424 arch_find_pristine (int * is_locked,
425 const t_uchar * tree_root_or_root_dir,
426 const t_uchar * archive,
427 const t_uchar * revision,
428 int pristine_types,
429 enum arch_pristine_search_scope scope)
430 {
431 const t_uchar * locked_pristine_stem = "{arch}/++pristine-trees/locked";
432 const t_uchar * unlocked_pristine_stem = "{arch}/++pristine-trees/unlocked";
433 t_uchar * category = 0;
434 t_uchar * branch = 0;
435 t_uchar * version = 0;
436 t_uchar * locked_relpath = 0;
437 t_uchar * unlocked_relpath = 0;
438 t_uchar * locked_in_this_tree_path = 0;
439 t_uchar * unlocked_in_this_tree_path = 0;
440 t_uchar * answer = 0;
441
442 invariant (arch_valid_archive_name (archive));
443 invariant (arch_valid_package_name (revision, arch_no_archive, arch_req_patch_level, 0));
444
445 category = arch_parse_package_name (arch_ret_category, 0, revision);
446 branch = arch_parse_package_name (arch_ret_package, 0, revision);
447 version = arch_parse_package_name (arch_ret_package_version, 0, revision);
448
449 locked_relpath = str_alloc_cat_many (0, locked_pristine_stem, "/", category, "/", branch, "/", version, "/", archive, "/", revision, str_end);
450 unlocked_relpath = str_alloc_cat_many (0, unlocked_pristine_stem, "/", category, "/", branch, "/", version, "/", archive, "/", revision, str_end);
451
452 locked_in_this_tree_path = file_name_in_vicinity (0, tree_root_or_root_dir, locked_relpath);
453 unlocked_in_this_tree_path = file_name_in_vicinity (0, tree_root_or_root_dir, unlocked_relpath);
454
455 if (((scope == arch_tree_pristine_search) || (scope == arch_tree_and_sibling_pristine_search))
456 && (pristine_types & arch_unlocked_pristine) && !safe_access (unlocked_in_this_tree_path, F_OK))
457 {
458 answer = str_save (0, unlocked_in_this_tree_path);
459 if (is_locked)
460 *is_locked = 0;
461 }
462 else
463 {
464 t_uchar * tree_root_dir = 0;
465 rel_table sibling_files = rel_table_nil;
466 rel_table sibling_paths = rel_table_nil;
467 int x;
468
469 if (scope == arch_cache_dir_pristine_search)
470 tree_root_dir = str_save (0, tree_root_or_root_dir);
471 else
472 {
473 tree_root_dir = file_name_directory_file (0, tree_root_or_root_dir);
474 if (!tree_root_dir)
475 tree_root_dir = str_save (0, ".");
476 }
477 sibling_files = directory_files (tree_root_dir);
478
479 if (scope != arch_tree_pristine_search)
480 {
481 for (x = 0; x < rel_n_records (sibling_files); ++x)
482 {
483 if (char_is_alnum (rel_peek_str (sibling_files, x, 0)[0]))
484 {
485 int ign;
486 struct stat stat_buf;
487 t_uchar * path = 0;
488
489 path = file_name_in_vicinity (0, tree_root_dir, rel_peek_str (sibling_files, x, 0));
490
491 if (!vu_lstat (&ign, path, &stat_buf) && S_ISDIR (stat_buf.st_mode))
492 {
493 rel_add_records (&sibling_paths, rel_singleton_record_taking (rel_make_field_str (path)), rel_record_null);
494 }
495 lim_free (0, path);
496 }
497 }
498
499 if (pristine_types & arch_unlocked_pristine)
500 {
501 for (x = 0; !answer && (x < rel_n_records (sibling_paths)); ++x)
502 {
503 t_uchar * unlocked_sibling_path = 0;
504 int errno = 0;
505
506 unlocked_sibling_path = file_name_in_vicinity (0, rel_peek_str (sibling_paths, x, 0), unlocked_relpath);
507
508 if (!vu_access (&errno, unlocked_sibling_path, F_OK))
509 {
510 answer = str_save (0, unlocked_sibling_path);
511 if (is_locked)
512 *is_locked = 0;
513 }
514
515 lim_free (0, unlocked_sibling_path);
516 }
517 }
518 }
519
520 if (pristine_types & arch_locked_pristine)
521 {
522 if ((scope != arch_cache_dir_pristine_search) && !answer && (!safe_access (locked_in_this_tree_path, F_OK)))
523 {
524 answer = str_save (0, locked_in_this_tree_path);
525 if (is_locked)
526 *is_locked = 1;
527 }
528
529 if (scope != arch_tree_pristine_search)
530 {
531 for (x = 0; !answer && (x < rel_n_records (sibling_paths)); ++x)
532 {
533 t_uchar * locked_sibling_path = 0;
534 int errno = 0;
535
536 locked_sibling_path = file_name_in_vicinity (0, rel_peek_str (sibling_paths, x, 0), locked_relpath);
537
538 if (!vu_access (&errno, locked_sibling_path, F_OK))
539 {
540 answer = str_save (0, locked_sibling_path);
541 if (is_locked)
542 *is_locked = 1;
543 }
544
545 lim_free (0, locked_sibling_path);
546 }
547 }
548 }
549
550 lim_free (0, tree_root_dir);
551 rel_free_table (sibling_files);
552 rel_free_table (sibling_paths);
553 }
554
555 lim_free (0, category);
556 lim_free (0, branch);
557 lim_free (0, version);
558 lim_free (0, locked_relpath);
559 lim_free (0, unlocked_relpath);
560 lim_free (0, locked_in_this_tree_path);
561 lim_free (0, unlocked_in_this_tree_path);
562
563
564 if (answer && !arch_valid_inode_sig (answer, archive, revision))
565 {
566 safe_printfmt (2, "corrupt pristine (failed inode signature validation)\n archive: %s\n revision: %s\n directory %s\nYou should remove this pristine from your tree.\n",
567 archive, revision, answer);
568 exit (2);
569 }
570
571 return answer;
572 }
573
574
575
576
577 /* tag: Tom Lord Wed May 21 18:53:22 2003 (pristines.c)
578 */
579