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