1 /* archive.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 "config-options.h"
12 #include "hackerlab/bugs/panic.h"
13 #include "hackerlab/os/errno.h"
14 #include "hackerlab/os/errno-to-string.h"
15 #include "hackerlab/os/sys/types.h"
16 #include "hackerlab/os/sys/wait.h"
17 #include "hackerlab/os/signal.h"
18 #include "hackerlab/os/time.h"
19 #include "hackerlab/os/unistd.h"
20 #include "hackerlab/os/stdlib.h"
21 #include "hackerlab/fmt/cvt.h"
22 #include "hackerlab/mem/alloc-limits.h"
23 #include "hackerlab/mem/mem.h"
24 #include "hackerlab/hash/hash-utils.h"
25 #include "hackerlab/arrays/ar.h"
26 #include "hackerlab/char/str.h"
27 #include "hackerlab/char/char-class.h"
28 #include "hackerlab/vu/safe.h"
29 #include "hackerlab/fs/cwd.h"
30 #include "hackerlab/fs/file-names.h"
31 #include "tla/libfsutils/tmp-files.h"
32 #include "tla/libfsutils/rmrf.h"
33 #include "tla/libarch/namespace.h"
34 #include "tla/libarch/my.h"
35 #include "tla/libarch/exec.h"
36 #include "tla/libarch/archives.h"
37 #include "tla/libarch/archive-version.h"
38 #include "tla/libarch/pfs.h"
39 #include "tla/libarch/archive-pfs.h"
40 #include "tla/libarch/archive.h"
41 
42 
43 /* __STDC__ prototypes for static functions */
44 static int invoke_tar_extract (int * pid_ret);
45 static int wait_for_tar (int pid);
46 static void ensure_writable (struct arch_archive * arch,
47                              int mirror_ok);
48 
49 
50 
51 static struct arch_archive * connected_by_name = 0;
52 
53 
54 
55 void
arch_make_archive(const t_uchar * name,const t_uchar * location,const t_uchar * mirror_of,int dot_listing_lossage,int signed_archive,int tla_archive)56 arch_make_archive (const t_uchar * name,
57                    const t_uchar * location,
58                    const t_uchar * mirror_of,
59                    int dot_listing_lossage,
60                    int signed_archive,
61                    int tla_archive)
62 {
63   t_uchar * current_loc = 0;
64   t_uchar * version;
65 
66   invariant (arch_valid_archive_name (name));
67 
68   current_loc = arch_archive_location (name, 1);
69 
70   if (current_loc)
71     {
72       safe_printfmt (2, "arch_make_archive: archive already registered\n  name: %s\n", name);
73       exit (2);
74     }
75 
76   version = arch_archive_version_for_new_archive (tla_archive);
77 
78   arch_pfs_make_archive (name, location, version, mirror_of, dot_listing_lossage, signed_archive);
79 
80   arch_run_hook ("make-archive", "ARCH_ARCHIVE", name, "ARCH_LOCATION", location, (t_uchar*)0);
81 
82   lim_free (0, version);
83 }
84 
85 
86 struct arch_archive *
arch_archive_connect_location(const t_uchar * name,const t_uchar * location,const t_uchar * want_mirror_of)87 arch_archive_connect_location (const t_uchar * name,
88                                const t_uchar * location,
89                                const t_uchar * want_mirror_of)
90 {
91   struct arch_archive * answer = 0;
92 
93   answer = lim_malloc (0, sizeof (*answer));
94   mem_set0 ((t_uchar *)answer, sizeof (*answer));
95 
96   answer->name = str_save (0, name);
97   answer->location = str_save (0, location);
98 
99   answer->client_anticipates_mirror = (want_mirror_of ? str_save (0, want_mirror_of) : 0);
100 
101   arch_pfs_archive_connect (&answer);
102 
103   answer->version = answer->vtable->archive_version (answer);
104   answer->access = arch_archive_access (answer->version);
105   answer->type = arch_archive_type (answer->version);
106 
107   if (answer->access == arch_archive_incompatible)
108     {
109       safe_printfmt (2, "arch_archive_connect: attempt to connect to incompatible archive\n  archive: %s\n", (name ? name : location));
110       exit (2);
111     }
112 
113   answer->mirror_of = arch_get_meta_info_trimming (answer, "mirror");
114   answer->official_name = arch_get_meta_info_trimming (answer, "name");
115   if (!answer->official_name)
116     {
117       int ign;
118 
119       printfmt (&ign, 2, "Unable to read the official name of archive %s\n  Archive damaged?\n", name);
120       exit (2);
121     }
122   lim_free (0, answer->name);
123   answer->name = str_save (0, answer->official_name);
124   answer->http_blows = arch_get_meta_int_info (answer, "http-blows");
125   answer->signed_archive = arch_get_meta_int_info (answer, "signed-archive");
126 
127   if (want_mirror_of && str_cmp (want_mirror_of, answer->mirror_of))
128     {
129       safe_printfmt (2, "arch_archive_connect: attempt to connect to wrong mirror\n  archive: %s\n  wanted mirror of: %s\n  got mirror of: %s\n",
130                      (name ? name : location), want_mirror_of, (answer->mirror_of ? answer->mirror_of : (t_uchar *)"(not a mirror)"));
131       exit (2);
132     }
133 
134   return answer;
135 }
136 
137 
138 struct arch_archive *
arch_archive_connect(const t_uchar * name,const t_uchar * want_mirror_of)139 arch_archive_connect (const t_uchar * name,
140                       const t_uchar * want_mirror_of)
141 {
142   struct arch_archive * answer = 0;
143 
144   for (answer = connected_by_name;
145        answer && str_cmp (answer->name, name);
146        answer = answer->next)
147     ;
148 
149   if (answer)
150     {
151       if (want_mirror_of && str_cmp (want_mirror_of, answer->mirror_of))
152         {
153           safe_printfmt (2, "arch_archive_connect: attempt to connect to wrong mirror\n  archive: %s\n  wanted mirror of: %s\n  got mirror of: %s\n",
154                          name, want_mirror_of, (answer->mirror_of ? answer->mirror_of : (t_uchar *)"(not a mirror)"));
155           exit (2);
156         }
157 
158       ++answer->refs;
159       return answer;
160     }
161   else
162     {
163       t_uchar * location = 0;
164 
165       location = arch_archive_location (name, 0);
166 
167       answer = arch_archive_connect_location (name, location, want_mirror_of);
168       lim_free (0, answer->name);
169       answer->name = str_save (0, name);
170       answer->refs = 1;
171       answer->next = connected_by_name;
172       connected_by_name = answer;
173 
174       lim_free(0, location);
175       return answer;
176     }
177 }
178 
179 
180 void
arch_archive_close(struct arch_archive * arch)181 arch_archive_close (struct arch_archive * arch)
182 {
183   if (!arch)
184     return;
185 
186   if (arch->refs)
187     --arch->refs;
188 
189   if (!arch->refs)
190     {
191       struct arch_archive ** handle = &connected_by_name;
192 
193       while (*handle)
194         {
195           if (*handle != arch)
196             handle = &((*handle)->next);
197           else
198             {
199               *handle = (*handle)->next;
200             }
201         }
202 
203       arch->vtable->close (arch);
204       lim_free (0, arch->name);
205       lim_free (0, arch->official_name);
206       lim_free (0, arch->location);
207       lim_free (0, arch->version);
208       lim_free (0, arch);
209     }
210 }
211 
212 
213 t_uchar *
arch_archive_version(struct arch_archive * arch)214 arch_archive_version (struct arch_archive * arch)
215 {
216   return arch->vtable->archive_version (arch);
217 }
218 
219 
220 rel_table
arch_archive_categories(struct arch_archive * arch)221 arch_archive_categories (struct arch_archive * arch)
222 {
223   rel_table answer  = rel_table_nil;
224 
225   answer = arch->vtable->categories (arch);
226   rel_sort_table_by_field (0, answer, 0);
227 
228   return answer;
229 }
230 
231 
232 rel_table
arch_archive_branches(struct arch_archive * arch,const t_uchar * category)233 arch_archive_branches (struct arch_archive * arch,
234                        const t_uchar * category)
235 {
236   rel_table answer  = rel_table_nil;
237 
238   answer = arch->vtable->branches (arch, category);
239   rel_sort_table_by_field (0, answer, 0);
240 
241   return answer;
242 }
243 
244 
245 rel_table
arch_archive_versions(struct arch_archive * arch,const t_uchar * package)246 arch_archive_versions (struct arch_archive * arch,
247                        const t_uchar * package)
248 {
249   rel_table answer  = rel_table_nil;
250 
251   answer = arch->vtable->versions (arch, package);
252   arch_sort_table_by_name_field (0, answer, 0);
253 
254   return answer;
255 }
256 
257 t_uchar *
arch_archive_latest_revision(struct arch_archive * arch,const t_uchar * version,int full)258 arch_archive_latest_revision (struct arch_archive * arch,
259                               const t_uchar * version,
260                               int full)
261 {
262   rel_table revs  = rel_table_nil;
263   t_uchar * answer = 0;
264 
265   revs = arch_archive_revisions (arch, version, full);
266 
267   if (rel_n_records (revs))
268     answer = str_save (0, rel_peek_str (revs, rel_n_records (revs) - 1, 0));
269 
270   rel_free_table (revs);
271   return answer;
272 }
273 
274 
275 rel_table
arch_archive_revisions(struct arch_archive * arch,const t_uchar * version,int full)276 arch_archive_revisions (struct arch_archive * arch,
277                         const t_uchar * version,
278                         int full)
279 {
280   rel_table answer  = rel_table_nil;
281 
282   answer = arch->vtable->revisions (arch, version);
283   arch_sort_table_by_patch_level_field (0, answer, 0);
284 
285   if (full)
286     {
287       t_uchar * fqv = 0;
288       int x;
289 
290       if (full == 1)
291         fqv = arch_fully_qualify (arch->name, version);
292       else
293         fqv = str_save (0, version);
294 
295       for (x = 0; x < rel_n_records (answer); ++x)
296         {
297           const t_uchar * t;
298           t_uchar * new_t;
299 
300           t = rel_peek_str (answer, x, 0);
301           new_t = str_alloc_cat_many (0, fqv, "--", t, str_end);
302           rel_set_taking (answer, x, 0, rel_make_field_str (new_t));
303           lim_free (0, new_t);
304         }
305 
306       lim_free (0, fqv);
307     }
308 
309   return answer;
310 }
311 
312 t_uchar *
arch_archive_log(struct arch_archive * arch,const t_uchar * revision)313 arch_archive_log (struct arch_archive * arch,
314                   const t_uchar * revision)
315 {
316   t_uchar * answer = 0;
317 
318   answer = arch->vtable->archive_log (arch, revision);
319 
320   return answer;
321 }
322 
323 
324 void
arch_revision_type(enum arch_revision_type * type,int * is_cached,struct arch_archive * arch,const t_uchar * revision)325 arch_revision_type (enum arch_revision_type * type,
326                     int * is_cached,
327                     struct arch_archive * arch,
328                     const t_uchar * revision)
329 {
330   if (arch->vtable->revision_type (type, is_cached, arch, revision) < 0)
331     {
332       safe_printfmt (2, "corrupt archive\n  name: %s\n  location: %s\n  revision: %s\n", arch->name, arch->location, revision);
333       exit (2);
334     }
335 }
336 
337 
338 int
arch_revision_exists(struct arch_archive * arch,const t_uchar * revision)339 arch_revision_exists (struct arch_archive * arch,
340                       const t_uchar * revision)
341 {
342   enum arch_revision_type type;
343   int is_cached;
344   return (arch->vtable->revision_type (&type, &is_cached, arch, revision) >= 0);
345 }
346 
347 
348 void
arch_get_patch_targz(int out_fd,struct arch_archive * arch,const t_uchar * revision)349 arch_get_patch_targz (int out_fd,
350                       struct arch_archive * arch,
351                       const t_uchar * revision)
352 {
353   arch->vtable->get_patch (out_fd, arch, revision);
354 }
355 
356 
357 void
arch_get_patch(struct arch_archive * arch,const t_uchar * revision,const t_uchar * dest_dir)358 arch_get_patch (struct arch_archive * arch,
359                 const t_uchar * revision,
360                 const t_uchar * dest_dir)
361 {
362   int here_fd;
363   t_uchar * dest_dir_dir = 0;
364   t_uchar * dest_dir_dir_path = 0;
365   t_uchar * dest_dir_tail = 0;
366   t_uchar * dest_dir_path = 0;
367   t_uchar * tmpdir_path = 0;
368   int out_fd = 0;
369   int tar_pid = 0;
370   t_uchar * patches_file_name = 0;
371   t_uchar * patches_file_dest = 0;
372 
373   here_fd = safe_open (".", O_RDONLY, 0);
374 
375   dest_dir_dir = file_name_directory_file (0, dest_dir);
376   if (dest_dir_dir)
377     safe_chdir (dest_dir_dir);
378   dest_dir_dir_path = safe_current_working_directory ();
379   dest_dir_tail = file_name_tail (0, dest_dir);
380   dest_dir_path = file_name_in_vicinity (0, dest_dir_dir_path, dest_dir_tail);
381 
382   tmpdir_path = tmp_file_name (dest_dir_dir_path, ",,get-patch");
383   patches_file_name = str_alloc_cat (0, revision, ".patches");
384   patches_file_dest = file_name_in_vicinity (0, "..", dest_dir_tail);
385 
386   safe_mkdir (tmpdir_path, 0777);
387   safe_chdir (tmpdir_path);
388 
389   out_fd = invoke_tar_extract (&tar_pid);
390   arch->vtable->get_patch (out_fd, arch, revision);
391   safe_close (out_fd);
392   if (wait_for_tar (tar_pid))
393     panic ("arch_get_patch: tar exitted with non-0 status");
394   safe_rename (patches_file_name, patches_file_dest);
395 
396   safe_fchdir (here_fd);
397   safe_close (here_fd);
398   rmrf_file (tmpdir_path);
399 
400   lim_free (0, dest_dir_dir);
401   lim_free (0, dest_dir_dir_path);
402   lim_free (0, dest_dir_tail);
403   lim_free (0, dest_dir_path);
404   lim_free (0, tmpdir_path);
405   lim_free (0, patches_file_name);
406   lim_free (0, patches_file_dest);
407 }
408 
409 
410 void
arch_get_cached_revision_targz(int out_fd,struct arch_archive * arch,const t_uchar * revision)411 arch_get_cached_revision_targz (int out_fd,
412                                 struct arch_archive * arch,
413                                 const t_uchar * revision)
414 {
415   arch->vtable->get_cached (out_fd, arch, revision);
416 }
417 
418 
419 void
arch_get_cached_revision(struct arch_archive * arch,const t_uchar * revision,const t_uchar * dest_dir)420 arch_get_cached_revision (struct arch_archive * arch,
421                           const t_uchar * revision,
422                           const t_uchar * dest_dir)
423 {
424   int here_fd;
425   t_uchar * dest_dir_dir = 0;
426   t_uchar * dest_dir_dir_path = 0;
427   t_uchar * dest_dir_tail = 0;
428   t_uchar * dest_dir_path = 0;
429   t_uchar * tmpdir_path = 0;
430   int out_fd = 0;
431   int tar_pid = 0;
432   t_uchar * patches_file_dest = 0;
433 
434   here_fd = safe_open (".", O_RDONLY, 0);
435 
436   dest_dir_dir = file_name_directory_file (0, dest_dir);
437   if (dest_dir_dir)
438     safe_chdir (dest_dir_dir);
439   dest_dir_dir_path = safe_current_working_directory ();
440   dest_dir_tail = file_name_tail (0, dest_dir);
441   dest_dir_path = file_name_in_vicinity (0, dest_dir_dir_path, dest_dir_tail);
442 
443   tmpdir_path = tmp_file_name (dest_dir_dir_path, ",,get-patch");
444   patches_file_dest = file_name_in_vicinity (0, "..", dest_dir_tail);
445 
446   safe_mkdir (tmpdir_path, 0777);
447   safe_chdir (tmpdir_path);
448 
449   out_fd = invoke_tar_extract (&tar_pid);
450   arch->vtable->get_cached (out_fd, arch, revision);
451   safe_close (out_fd);
452   if (wait_for_tar (tar_pid))
453     panic ("arch_get_patch: tar exitted with non-0 status");
454   safe_rename (revision, patches_file_dest);
455 
456   safe_fchdir (here_fd);
457   safe_close (here_fd);
458   rmrf_file (tmpdir_path);
459 
460   lim_free (0, dest_dir_dir);
461   lim_free (0, dest_dir_dir_path);
462   lim_free (0, dest_dir_tail);
463   lim_free (0, dest_dir_path);
464   lim_free (0, tmpdir_path);
465   lim_free (0, patches_file_dest);
466 }
467 
468 
469 void
arch_get_import_targz(int out_fd,struct arch_archive * arch,const t_uchar * revision)470 arch_get_import_targz (int out_fd,
471                        struct arch_archive * arch,
472                        const t_uchar * revision)
473 {
474   arch->vtable->get_import (out_fd, arch, revision);
475 }
476 
477 
478 void
arch_get_import_revision(struct arch_archive * arch,const t_uchar * revision,const t_uchar * dest_dir)479 arch_get_import_revision (struct arch_archive * arch,
480                           const t_uchar * revision,
481                           const t_uchar * dest_dir)
482 {
483   int here_fd;
484   t_uchar * dest_dir_dir = 0;
485   t_uchar * dest_dir_dir_path = 0;
486   t_uchar * dest_dir_tail = 0;
487   t_uchar * dest_dir_path = 0;
488   t_uchar * tmpdir_path = 0;
489   int out_fd = 0;
490   int tar_pid = 0;
491   t_uchar * patches_file_dest = 0;
492 
493   here_fd = safe_open (".", O_RDONLY, 0);
494 
495   dest_dir_dir = file_name_directory_file (0, dest_dir);
496   if (dest_dir_dir)
497     safe_chdir (dest_dir_dir);
498   dest_dir_dir_path = safe_current_working_directory ();
499   dest_dir_tail = file_name_tail (0, dest_dir);
500   dest_dir_path = file_name_in_vicinity (0, dest_dir_dir_path, dest_dir_tail);
501 
502   tmpdir_path = tmp_file_name (dest_dir_dir_path, ",,get-patch");
503   patches_file_dest = file_name_in_vicinity (0, "..", dest_dir_tail);
504 
505   safe_mkdir (tmpdir_path, 0777);
506   safe_chdir (tmpdir_path);
507 
508   out_fd = invoke_tar_extract (&tar_pid);
509   arch->vtable->get_import (out_fd, arch, revision);
510   safe_close (out_fd);
511   if (wait_for_tar (tar_pid))
512     panic ("arch_get_patch: tar exitted with non-0 status");
513   safe_rename (revision, patches_file_dest);
514 
515   safe_fchdir (here_fd);
516   safe_close (here_fd);
517   rmrf_file (tmpdir_path);
518 
519   lim_free (0, dest_dir_dir);
520   lim_free (0, dest_dir_dir_path);
521   lim_free (0, dest_dir_tail);
522   lim_free (0, dest_dir_path);
523   lim_free (0, tmpdir_path);
524   lim_free (0, patches_file_dest);
525 }
526 
527 
528 t_uchar *
arch_get_continuation(struct arch_archive * arch,const t_uchar * revision)529 arch_get_continuation (struct arch_archive * arch,
530                        const t_uchar * revision)
531 {
532   t_uchar * raw_data = 0;
533   t_uchar * start;
534   t_uchar * end;
535   t_uchar * answer = 0;
536 
537   raw_data = arch->vtable->get_continuation (arch, revision);
538 
539   start = raw_data;
540   while (*start && char_is_space (*start))
541     ++start;
542 
543   end = start;
544   while (*end && !char_is_space (*end))
545     ++end;
546 
547   answer = str_save_n (0, start, end - start);
548 
549   lim_free (0, raw_data);
550 
551   return answer;
552 }
553 
554 t_uchar *
arch_get_meta_info(struct arch_archive * arch,const t_uchar * meta_info_name)555 arch_get_meta_info (struct arch_archive * arch,
556                     const t_uchar * meta_info_name)
557 {
558   t_uchar * answer = 0;
559 
560   answer = arch->vtable->get_meta_info (arch, meta_info_name);
561 
562   return answer;
563 }
564 
565 
566 t_uchar *
arch_get_meta_info_trimming(struct arch_archive * arch,const t_uchar * meta_info_name)567 arch_get_meta_info_trimming (struct arch_archive * arch,
568                              const t_uchar * meta_info_name)
569 {
570   t_uchar * intermediate = 0;
571   t_uchar * answer = 0;
572 
573   intermediate = arch_get_meta_info (arch, meta_info_name);
574   if (!intermediate)
575     return 0;
576 
577   answer = str_save_trimming (0, intermediate);
578 
579   lim_free (0, intermediate);
580 
581   return answer;
582 }
583 
584 
585 int
arch_make_category(t_uchar ** errstr,struct arch_archive * arch,const t_uchar * category)586 arch_make_category (t_uchar ** errstr,
587                     struct arch_archive * arch,
588                     const t_uchar * category)
589 {
590   int answer;
591 
592   ensure_writable (arch, 0);
593   answer = arch->vtable->make_category (errstr, arch, category);
594   arch_run_hook ("make-category", "ARCH_ARCHIVE", arch->name, "ARCH_CATEGORY", category, (t_uchar*)0);
595   return answer;
596 }
597 
598 int
arch_make_branch(t_uchar ** errstr,struct arch_archive * arch,const t_uchar * branch)599 arch_make_branch (t_uchar ** errstr,
600                   struct arch_archive * arch,
601                   const t_uchar * branch)
602 {
603   int answer;
604 
605   ensure_writable (arch, 0);
606   answer = arch->vtable->make_branch (errstr, arch, branch);
607   arch_run_hook ("make-branch", "ARCH_ARCHIVE", arch->name, "ARCH_BRANCH", branch, (t_uchar*)0);
608   return answer;
609 }
610 
611 int
arch_make_version(t_uchar ** errstr,struct arch_archive * arch,const t_uchar * version)612 arch_make_version (t_uchar ** errstr,
613                    struct arch_archive * arch,
614                    const t_uchar * version)
615 {
616   int answer;
617 
618   ensure_writable (arch, 0);
619   answer = arch->vtable->make_version (errstr, arch, version);
620   arch_run_hook ("make-version", "ARCH_ARCHIVE", arch->name, "ARCH_VERSION", version, (t_uchar*)0);
621   return answer;
622 }
623 
624 
625 
626 
627 int
arch_archive_lock_revision(t_uchar ** errstr,struct arch_archive * a,const t_uchar * version,const t_uchar * prev_level,const t_uchar * uid,const t_uchar * txn_id,const t_uchar * new_level)628 arch_archive_lock_revision (t_uchar ** errstr,
629                             struct arch_archive * a,
630                             const t_uchar * version,
631                             const t_uchar * prev_level,
632                             const t_uchar * uid,
633                             const t_uchar * txn_id,
634                             const t_uchar * new_level)
635 {
636   ensure_writable (a, 1);
637   return a->vtable->lock_revision (errstr, a, version, prev_level, uid, txn_id, new_level);
638 }
639 
640 
641 int
arch_revision_ready(t_uchar ** errstr,struct arch_archive * a,const t_uchar * version,const t_uchar * prev_level,const t_uchar * uid,const t_uchar * txn_id,const t_uchar * new_level)642 arch_revision_ready (t_uchar ** errstr,
643                      struct arch_archive *a,
644                      const t_uchar * version,
645                      const t_uchar * prev_level,
646                      const t_uchar * uid,
647                      const t_uchar * txn_id,
648                      const t_uchar * new_level)
649 {
650   return a->vtable->revision_ready (errstr, a, version, prev_level, uid, txn_id, new_level);
651 }
652 
653 
654 
655 int
arch_archive_finish_revision(t_uchar ** errstr,struct arch_archive * a,const t_uchar * version,const t_uchar * prev_level,const t_uchar * uid,const t_uchar * txn_id,const t_uchar * new_level)656 arch_archive_finish_revision (t_uchar ** errstr,
657                               struct arch_archive * a,
658                               const t_uchar * version,
659                               const t_uchar * prev_level,
660                               const t_uchar * uid,
661                               const t_uchar * txn_id,
662                               const t_uchar * new_level)
663 {
664   ensure_writable (a, 0);
665   return a->vtable->finish_revision (errstr, a, version, prev_level, uid, txn_id, new_level);
666 }
667 
668 enum arch_revision_lock_state
arch_archive_revision_lock_state(t_uchar ** prev_level_ret,t_uchar ** uid_ret,t_uchar ** txn_id_ret,struct arch_archive * a,const t_uchar * version)669 arch_archive_revision_lock_state (t_uchar ** prev_level_ret,
670                                   t_uchar ** uid_ret,
671                                   t_uchar ** txn_id_ret,
672                                   struct arch_archive * a,
673                                   const t_uchar * version)
674 {
675   ensure_writable (a, 1);
676   return a->vtable->lock_state (prev_level_ret, uid_ret, txn_id_ret, a, version);
677 }
678 
679 int
arch_archive_break_revision_lock(t_uchar ** errstr,struct arch_archive * a,const t_uchar * version,const t_uchar * prev_level,const t_uchar * uid,const t_uchar * txn_id)680 arch_archive_break_revision_lock (t_uchar ** errstr,
681                                   struct arch_archive * a,
682                                   const t_uchar * version,
683                                   const t_uchar * prev_level,
684                                   const t_uchar * uid,
685                                   const t_uchar * txn_id)
686 {
687   ensure_writable (a, 1);
688   return a->vtable->break_revision_lock (errstr, a, version, prev_level, uid, txn_id);
689 }
690 
691 
692 
693 
694 int
arch_archive_put_log(t_uchar ** errstr,struct arch_archive * a,const t_uchar * version,const t_uchar * prev_level,const t_uchar * uid,const t_uchar * txn_id,const t_uchar * log_text)695 arch_archive_put_log (t_uchar ** errstr,
696                       struct arch_archive * a,
697                       const t_uchar * version,
698                       const t_uchar * prev_level,
699                       const t_uchar * uid,
700                       const t_uchar * txn_id,
701                       const t_uchar * log_text)
702 {
703   ensure_writable (a, 0);
704   return a->vtable->put_log (errstr, a, version, prev_level, uid, txn_id, log_text);
705 }
706 
707 
708 
709 int
arch_archive_put_continuation(t_uchar ** errstr,struct arch_archive * a,const t_uchar * version,const t_uchar * prev_level,const t_uchar * uid,const t_uchar * txn_id,const t_uchar * continuation)710 arch_archive_put_continuation (t_uchar ** errstr,
711                                struct arch_archive * a,
712                                const t_uchar * version,
713                                const t_uchar * prev_level,
714                                const t_uchar * uid,
715                                const t_uchar * txn_id,
716                                const t_uchar * continuation)
717 {
718   ensure_writable (a, 0);
719   return a->vtable->put_continuation (errstr, a, version, prev_level, uid, txn_id, continuation);
720 }
721 
722 
723 int
arch_archive_put_changeset_targz(t_uchar ** errstr,struct arch_archive * a,const t_uchar * version,const t_uchar * prev_level,const t_uchar * uid,const t_uchar * txn_id,const t_uchar * level,int in_fd)724 arch_archive_put_changeset_targz (t_uchar ** errstr,
725                                   struct arch_archive * a,
726                                   const t_uchar * version,
727                                   const t_uchar * prev_level,
728                                   const t_uchar * uid,
729                                   const t_uchar * txn_id,
730                                   const t_uchar * level,
731                                   int in_fd)
732 {
733   int answer;
734 
735   answer = a->vtable->put_changeset (errstr, a, version, prev_level, uid, txn_id, level, in_fd);
736 
737   return answer;
738 }
739 
740 
741 int
arch_archive_put_changeset(t_uchar ** errstr,struct arch_archive * a,const t_uchar * version,const t_uchar * prev_level,const t_uchar * uid,const t_uchar * txn_id,const t_uchar * level,const t_uchar * dir)742 arch_archive_put_changeset (t_uchar ** errstr,
743                             struct arch_archive * a,
744                             const t_uchar * version,
745                             const t_uchar * prev_level,
746                             const t_uchar * uid,
747                             const t_uchar * txn_id,
748                             const t_uchar * level,
749                             const t_uchar * dir)
750 {
751   t_uchar * dir_tail = 0;
752   t_uchar * desired_name = 0;
753   t_uchar * tar_file_path = 0;
754   int in_fd;
755   int answer;
756 
757   dir_tail = file_name_tail (0, dir);
758   desired_name = str_alloc_cat_many (0, version, "--", level, ".patches", str_end);
759   invariant (!str_cmp (dir_tail, desired_name));
760 
761 
762   /* GNU tar 1.13 is busted and doesn't output to pipes correctly.
763    */
764 
765   ensure_writable (a, 0);
766 
767   tar_file_path = make_tmp_tar_archive (dir);
768 
769   in_fd = safe_open (tar_file_path, O_RDONLY, 0);
770 
771   answer = a->vtable->put_changeset (errstr, a, version, prev_level, uid, txn_id, level, in_fd);
772 
773   safe_close (in_fd);
774   safe_unlink (tar_file_path);
775 
776   lim_free (0, dir_tail);
777   lim_free (0, desired_name);
778   lim_free (0, tar_file_path);
779 
780   return answer;
781 }
782 
783 
784 int
arch_archive_put_import_targz(t_uchar ** errstr,struct arch_archive * a,const t_uchar * version,const t_uchar * prev_level,const t_uchar * uid,const t_uchar * txn_id,const t_uchar * level,int in_fd)785 arch_archive_put_import_targz (t_uchar ** errstr,
786                                struct arch_archive * a,
787                                const t_uchar * version,
788                                const t_uchar * prev_level,
789                                const t_uchar * uid,
790                                const t_uchar * txn_id,
791                                const t_uchar * level,
792                                int in_fd)
793 {
794   int answer;
795 
796   answer = a->vtable->put_import (errstr, a, version, prev_level, uid, txn_id, level, in_fd);
797 
798   return answer;
799 }
800 
801 
802 int
arch_archive_put_import(t_uchar ** errstr,struct arch_archive * a,const t_uchar * version,const t_uchar * prev_level,const t_uchar * uid,const t_uchar * txn_id,const t_uchar * level,const t_uchar * dir)803 arch_archive_put_import (t_uchar ** errstr,
804                          struct arch_archive * a,
805                          const t_uchar * version,
806                          const t_uchar * prev_level,
807                          const t_uchar * uid,
808                          const t_uchar * txn_id,
809                          const t_uchar * level,
810                          const t_uchar * dir)
811 {
812   t_uchar * dir_tail = 0;
813   t_uchar * desired_name = 0;
814   t_uchar * tar_file_path = 0;
815   int in_fd;
816   int answer;
817 
818   dir_tail = file_name_tail (0, dir);
819   desired_name = str_alloc_cat_many (0, version, "--", level, str_end);
820   invariant (!str_cmp (dir_tail, desired_name));
821 
822 
823   /* GNU tar 1.13 is busted and doesn't output to pipes correctly.
824    */
825 
826   ensure_writable (a, 0);
827 
828   tar_file_path = make_tmp_tar_archive (dir);
829 
830   in_fd = safe_open (tar_file_path, O_RDONLY, 0);
831 
832   answer = a->vtable->put_import (errstr, a, version, prev_level, uid, txn_id, level, in_fd);
833 
834   safe_close (in_fd);
835   safe_unlink (tar_file_path);
836 
837   lim_free (0, dir_tail);
838   lim_free (0, desired_name);
839   lim_free (0, tar_file_path);
840 
841   return answer;
842 }
843 
844 int
arch_archive_put_cached_targz(t_uchar ** errstr,struct arch_archive * a,const t_uchar * revision,int in_fd)845 arch_archive_put_cached_targz (t_uchar ** errstr,
846                                struct arch_archive * a,
847                                const t_uchar * revision,
848                                int in_fd)
849 {
850   int answer;
851 
852   answer = a->vtable->put_cached (errstr, a, revision, in_fd);
853 
854   return answer;
855 }
856 
857 int
arch_archive_put_cached(t_uchar ** errstr,struct arch_archive * a,const t_uchar * revision,const t_uchar * dir)858 arch_archive_put_cached (t_uchar ** errstr,
859                          struct arch_archive * a,
860                          const t_uchar * revision,
861                          const t_uchar * dir)
862 {
863   t_uchar * dir_tail = 0;
864   t_uchar * tar_file_path = 0;
865   int in_fd;
866   int answer;
867 
868   dir_tail = file_name_tail (0, dir);
869   invariant (!str_cmp (dir_tail, revision));
870 
871 
872   /* GNU tar 1.13 is busted and doesn't output to pipes correctly.
873    */
874 
875   ensure_writable (a, 1);
876 
877   tar_file_path = make_tmp_tar_archive (dir);
878 
879   in_fd = safe_open (tar_file_path, O_RDONLY, 0);
880 
881   answer = a->vtable->put_cached (errstr, a, revision, in_fd);
882 
883   safe_close (in_fd);
884   safe_unlink (tar_file_path);
885 
886   lim_free (0, dir_tail);
887   lim_free (0, tar_file_path);
888 
889   return answer;
890 }
891 
892 
893 int
arch_archive_delete_cached(t_uchar ** errstr,struct arch_archive * a,const t_uchar * revision)894 arch_archive_delete_cached (t_uchar ** errstr,
895                             struct arch_archive * a,
896                             const t_uchar * revision)
897 {
898   ensure_writable (a, 1);
899   return a->vtable->delete_cached (errstr, a, revision);
900 }
901 
902 void
arch_archive_repair_non_txnal(int chatter_fd,struct arch_archive * a)903 arch_archive_repair_non_txnal (int chatter_fd, struct arch_archive * a)
904 {
905   ensure_writable (a, 1);
906   a->vtable->repair_non_txnal (chatter_fd, a);
907 }
908 
909 
910 
911 
912 
913 t_uchar *
arch_generate_txn_id(void)914 arch_generate_txn_id (void)
915 {
916   time_t now;
917   pid_t pid;
918   char hostname[64];
919   char number[64];
920   t_uchar * answer;
921 
922   now = time (0);
923   pid = getpid ();
924 
925   mem_set0 ((t_uchar *)hostname, sizeof (hostname));
926   gethostname (hostname, sizeof (hostname));
927 
928   cvt_ulong_to_hex (number, hash_ul((t_ulong)now ^ (t_ulong)pid));
929   answer = str_save (0, number);
930 
931   cvt_ulong_to_hex (number, hash_mem ((t_uchar *)hostname, sizeof (hostname)));
932   answer = str_realloc_cat (0, answer, number);
933 
934   cvt_ulong_to_hex (number, hash_ul ((t_ulong)now ^ ~(t_ulong)pid));
935   answer = str_realloc_cat (0, answer, number);
936 
937   return answer;
938 }
939 
940 
941 t_uchar *
arch_previous_revision(struct arch_archive * arch,const t_uchar * revision)942 arch_previous_revision (struct arch_archive * arch,
943                         const t_uchar * revision)
944 {
945   t_uchar * version = 0;
946   t_uchar * patch_level = 0;
947   enum arch_patch_level_type current_type;
948   enum arch_patch_level_type next_type;
949   t_ulong current_n;
950   t_ulong next_n;
951   t_uchar * next_patch_level = 0;
952   t_uchar * answer = 0;
953 
954 
955   version = arch_parse_package_name (arch_ret_package_version, 0, revision);
956   patch_level = arch_parse_package_name (arch_ret_patch_level, 0, revision);
957 
958   current_type = arch_analyze_patch_level (&current_n, patch_level);
959 
960   if (current_type == arch_is_base0_level)
961     {
962       answer = 0;
963     }
964   else
965     {
966       if (((current_type == arch_is_patch_level) || (current_type == arch_is_versionfix_level)) && (current_n > 1))
967         {
968           next_type = current_type;
969           next_n = current_n - 1;
970         }
971       else if (current_n == 1)
972         {
973           next_n = 0;
974           if (current_type == arch_is_patch_level)
975             next_type = arch_is_base0_level;
976           else
977             next_type = arch_is_version_level;
978         }
979       else
980         {
981           rel_table revisions  = rel_table_nil;
982           int x;
983 
984           revisions = arch_archive_revisions (arch, version, 0);
985 
986           if (!rel_n_records (revisions))
987             {
988               safe_printfmt (2, "version has no revisions (%s/%s)\n", arch->name, version);
989               exit (2);
990             }
991 
992           for (x = 0; x < rel_n_records (revisions); ++x)
993             if (rel_peek_str (revisions, x, 0)[0] == 'v')
994               break;
995 
996           invariant (x);
997 
998           if (x == rel_n_records (revisions))
999             x = rel_n_records (revisions);
1000 
1001           if (x == 1)
1002             {
1003               next_type = arch_is_base0_level;
1004               next_n = 0;
1005             }
1006           else
1007             {
1008               next_type = arch_is_patch_level;
1009               next_n = x - 1;
1010             }
1011 
1012           rel_free_table (revisions);
1013         }
1014 
1015       next_patch_level = arch_form_patch_level (next_type, next_n);
1016       answer = str_alloc_cat_many (0, version, "--", next_patch_level, str_end);
1017     }
1018 
1019   lim_free (0, version);
1020   lim_free (0, patch_level);
1021   lim_free (0, next_patch_level);
1022 
1023   return answer;
1024 }
1025 
1026 
1027 t_uchar *
arch_ancestor_revision(struct arch_archive * arch,const t_uchar * revision)1028 arch_ancestor_revision (struct arch_archive * arch,
1029                         const t_uchar * revision)
1030 {
1031   enum arch_revision_type type;
1032 
1033   arch_revision_type (&type, 0, arch, revision);
1034 
1035   switch (type)
1036     {
1037     default:
1038       {
1039         panic ("arch_ancestor_revision: unrecognized revision type");
1040         return 0;
1041       }
1042     case arch_import_revision:
1043       {
1044         return 0;
1045       }
1046     case arch_simple_revision:
1047       {
1048         t_uchar * prev_revision = 0;
1049         t_uchar * answer = 0;
1050 
1051         prev_revision = arch_previous_revision (arch, revision);
1052         answer = arch_fully_qualify (arch->name, prev_revision);
1053 
1054         lim_free (0, prev_revision);
1055 
1056         return answer;
1057       }
1058     case arch_continuation_revision:
1059       {
1060         return arch_get_continuation (arch, revision);
1061       }
1062     }
1063 }
1064 
1065 
1066 
1067 t_uchar *
archive_tmp_file_name(const t_uchar * dir,const t_uchar * basename)1068 archive_tmp_file_name (const t_uchar * dir,
1069                        const t_uchar * basename)
1070 {
1071   t_uchar * my_uid = 0;
1072   t_uchar * tmp_name = 0;
1073 
1074   my_uid = arch_my_id_uid ();
1075   tmp_name = tmp_file_name (dir, basename);
1076 
1077   tmp_name = str_realloc_cat_many (0, tmp_name, ".", my_uid, str_end);
1078 
1079   lim_free (0, my_uid);
1080 
1081   return tmp_name;
1082 }
1083 
1084 
1085 
1086 
1087 static int
invoke_tar_extract(int * pid_ret)1088 invoke_tar_extract (int * pid_ret)
1089 {
1090   int pipe_fds[2];
1091   int pid;
1092 
1093   if (pipe (pipe_fds))
1094     panic ("unable to create pipe fds for tar");
1095 
1096   pid = fork ();
1097 
1098   if (pid == -1)
1099     panic ("unable to fork for patch");
1100 
1101   if (pid)
1102     {
1103       *pid_ret = pid;
1104       safe_close (pipe_fds[0]);
1105       return pipe_fds[1];
1106     }
1107   else
1108     {
1109       t_uchar ** argv;
1110 
1111       safe_close (pipe_fds[1]);
1112 
1113       argv = 0;
1114 
1115       *(t_uchar **)ar_push ((void **)&argv, 0, sizeof (char *)) = cfg__gnu_tar;
1116       *(t_uchar **)ar_push ((void **)&argv, 0, sizeof (char *)) = "-m";
1117       *(t_uchar **)ar_push ((void **)&argv, 0, sizeof (char *)) = "-p";
1118       *(t_uchar **)ar_push ((void **)&argv, 0, sizeof (char *)) = "-s";
1119       *(t_uchar **)ar_push ((void **)&argv, 0, sizeof (char *)) = "-zxf";
1120       *(t_uchar **)ar_push ((void **)&argv, 0, sizeof (char *)) = "-";
1121       *(t_uchar **)ar_push ((void **)&argv, 0, sizeof (char *)) = 0;
1122 
1123       safe_move_fd (pipe_fds[0], 0);
1124 
1125       arch_util_execvp (cfg__gnu_tar, argv);
1126       panic ("invoke_tar_extract: execvp for patch returned to caller");
1127       exit (2);
1128     }
1129   panic ("invoke_tar_extract: not reached");
1130   return -1;
1131 }
1132 
1133 static int
wait_for_tar(int pid)1134 wait_for_tar (int pid)
1135 {
1136   int status;
1137   int wait_pid;
1138 
1139   wait_pid = waitpid (pid, &status, 0);
1140   if (wait_pid < 0)
1141     {
1142       panic_msg ("error waiting for tar subprocess");
1143       kill (0, SIGKILL);
1144       panic ("error waiting for subprocess");
1145     }
1146   if (WIFSIGNALED (status))
1147     {
1148       safe_printfmt (2, "\n");
1149       safe_printfmt (2, "wait_for_tar: tar subprocess killed by signal %d\n", WTERMSIG (status));
1150       safe_printfmt (2, "\n");
1151       exit (2);
1152       return -1;
1153     }
1154   else if (!WIFEXITED (status))
1155     {
1156       panic_msg ("waitpid returned for a non-exited process");
1157       kill (0, SIGKILL);
1158       panic ("waitpid returned for a non-exited process");
1159       return -1;
1160     }
1161   else
1162     {
1163       int exit_status;
1164 
1165       exit_status = WEXITSTATUS (status);
1166       return exit_status;
1167     }
1168 }
1169 
1170 
1171 t_uchar *
make_tmp_tar_archive(const t_uchar * dir)1172 make_tmp_tar_archive (const t_uchar * dir)
1173 {
1174   t_uchar * dir_dir = 0;
1175   t_uchar * dir_tail = 0;
1176   t_uchar * tmp_stem = 0;
1177   t_uchar * tmp_in_cwd = 0;
1178   t_uchar * tmp_path = 0;
1179 
1180   dir_dir = file_name_directory_file (0, dir);
1181   if (!dir_dir)
1182     dir_dir = str_save (0, ".");
1183 
1184   dir_tail = file_name_tail (0, dir);
1185 
1186   tmp_stem = str_alloc_cat_many (0, ",,", dir_tail, ".tar.gz", str_end);
1187   tmp_in_cwd = tmp_file_name (".", tmp_stem);
1188   tmp_path = file_name_in_vicinity (0, dir_dir, tmp_in_cwd);
1189 
1190   {
1191     int pid;
1192     int dev_null_fd;
1193 
1194     dev_null_fd = safe_open ("/dev/null", O_WRONLY, 0);
1195 
1196     pid = fork ();
1197 
1198     if (pid == -1)
1199       panic ("unable to fork for patch");
1200 
1201     if (!pid)
1202       {
1203         t_uchar ** argv;
1204 
1205         safe_chdir (dir_dir);
1206 
1207         argv = 0;
1208 
1209         *(t_uchar **)ar_push ((void **)&argv, 0, sizeof (char *)) = cfg__gnu_tar;
1210         *(t_uchar **)ar_push ((void **)&argv, 0, sizeof (char *)) = "-zcf";
1211         *(t_uchar **)ar_push ((void **)&argv, 0, sizeof (char *)) = tmp_in_cwd;
1212         *(t_uchar **)ar_push ((void **)&argv, 0, sizeof (char *)) = dir_tail;
1213         *(t_uchar **)ar_push ((void **)&argv, 0, sizeof (char *)) = 0;
1214 
1215         safe_move_fd (dev_null_fd, 1);
1216         safe_dup2 (1, 2);
1217 
1218         arch_util_execvp (cfg__gnu_tar, argv);
1219         panic ("make_tmp_tar_archive: execvp for patch returned to caller");
1220         exit (2);
1221       }
1222     else
1223       {
1224         int status;
1225         int wait_pid;
1226 
1227         safe_close (dev_null_fd);
1228 
1229         wait_pid = waitpid (pid, &status, 0);
1230         if (wait_pid < 0)
1231           {
1232             panic_msg ("error waiting for tar subprocess");
1233             kill (0, SIGKILL);
1234             panic ("error waiting for subprocess");
1235           }
1236         if (WIFSIGNALED (status))
1237           {
1238             safe_printfmt (2, "\n");
1239             safe_printfmt (2, "wait_for_tar: tar subprocess killed by signal %d\n", WTERMSIG (status));
1240             safe_printfmt (2, "\n");
1241             exit (2);
1242             return 0;
1243           }
1244         else if (!WIFEXITED (status))
1245           {
1246             panic_msg ("waitpid returned for a non-exited process");
1247             kill (0, SIGKILL);
1248             panic ("waitpid returned for a non-exited process");
1249             return 0;
1250           }
1251         else
1252           {
1253             int exit_status;
1254 
1255             exit_status = WEXITSTATUS (status);
1256 
1257             if (exit_status)
1258               panic ("make_tmp_tar_archive: tar exitted with non-0 status");
1259           }
1260       }
1261   }
1262 
1263   lim_free (0, dir_dir);
1264   lim_free (0, dir_tail);
1265   lim_free (0, tmp_in_cwd);
1266   lim_free (0, tmp_stem);
1267 
1268   return tmp_path;
1269 }
1270 
1271 
1272 
1273 static void
ensure_writable(struct arch_archive * arch,int mirror_ok)1274 ensure_writable (struct arch_archive * arch,
1275                  int mirror_ok)
1276 {
1277   if (arch->access != arch_archive_writable)
1278     {
1279       safe_printfmt (2, "attempt to modify archive that has only read-compatibility\n    archive: %s\n", arch->name);
1280       exit (2);
1281     }
1282 
1283   if (!mirror_ok)
1284     {
1285       if (!arch->client_anticipates_mirror && !!arch->mirror_of)
1286         {
1287           safe_printfmt (2, "attempt to write directly to mirror\n    archive: %s\n    mirror of: %s\n", arch->name, arch->mirror_of);
1288           exit (2);
1289         }
1290 
1291       if (arch->client_anticipates_mirror && !arch->mirror_of)
1292         {
1293           safe_printfmt (2, "archive is not a mirror of %s\n    archive: %s\n    expected mirror of: %s\n", arch->client_anticipates_mirror, arch->name, arch->client_anticipates_mirror);
1294           exit (2);
1295         }
1296 
1297       if (arch->client_anticipates_mirror && str_cmp (arch->client_anticipates_mirror, arch->mirror_of))
1298         {
1299           safe_printfmt (2, "attempt to write to the wrong mirror\n    archive: %s\n    expected mirror of: %s\n    got mirror of: %s\n",
1300                          arch->name, arch->client_anticipates_mirror, arch->mirror_of);
1301           exit (2);
1302         }
1303     }
1304 }
1305 
1306 
1307 int
arch_get_meta_int_info(struct arch_archive * arch,const t_uchar * key)1308 arch_get_meta_int_info(struct arch_archive * arch,
1309                        const t_uchar * key)
1310 {
1311   t_uchar * key_existence = arch_get_meta_info (arch, key);
1312   int result  = !!key_existence;
1313 
1314   lim_free (0, key_existence);
1315 
1316   return result;
1317 }
1318 
1319 t_uchar *
arch_fs_archive_category_path(const struct arch_archive * arch,const t_uchar * archive_path,const t_uchar * category)1320 arch_fs_archive_category_path (const struct arch_archive * arch,
1321                                const t_uchar * archive_path,
1322                                const t_uchar * category)
1323 {
1324   if (arch->type == arch_archive_baz)
1325     panic ("baz does not support stand alone categories");
1326   return file_name_in_vicinity (0, archive_path, category);
1327 }
1328 
1329 t_uchar *
arch_fs_archive_branch_path(const struct arch_archive * arch,const t_uchar * archive_path,const t_uchar * package)1330 arch_fs_archive_branch_path (const struct arch_archive * arch,
1331                              const t_uchar * archive_path,
1332                              const t_uchar * package)
1333 {
1334   t_uchar * category = 0;
1335   t_uchar * category_path = 0;
1336   t_uchar * branch_path = 0;
1337 
1338   if (arch->type == arch_archive_baz)
1339     panic ("baz does not support stand alone branches");
1340 
1341   invariant (arch_valid_package_name (package, arch_no_archive, arch_req_package, 0));
1342 
1343   category = arch_parse_package_name (arch_ret_category, 0, package);
1344   category_path = arch_fs_archive_category_path (arch, archive_path, category);
1345   branch_path = file_name_in_vicinity (0, category_path, package);
1346 
1347   lim_free (0, category);
1348   lim_free (0, category_path);
1349   return branch_path;
1350 }
1351 
1352 
1353 t_uchar *
arch_fs_archive_version_path(const struct arch_archive * arch,const t_uchar * archive_path,const t_uchar * version)1354 arch_fs_archive_version_path (const struct arch_archive * arch,
1355                               const t_uchar * archive_path,
1356                               const t_uchar * version)
1357 {
1358   t_uchar * package = 0;
1359   t_uchar * package_path = 0;
1360   t_uchar * version_path = 0;
1361 
1362   invariant (arch_valid_package_name (version, arch_no_archive, arch_req_version, 0));
1363 
1364   if (arch->type == arch_archive_baz)
1365     return str_save (0, version);
1366 
1367   package = arch_parse_package_name (arch_ret_package, 0, version);
1368   package_path = arch_fs_archive_branch_path (arch, archive_path, package);
1369   version_path = file_name_in_vicinity (0, package_path, version);
1370 
1371   lim_free (0, package);
1372   lim_free (0, package_path);
1373 
1374   return version_path;
1375 }
1376 
1377 t_uchar *
arch_fs_archive_revision_path(const struct arch_archive * arch,const t_uchar * archive_path,const t_uchar * revision)1378 arch_fs_archive_revision_path (const struct arch_archive * arch,
1379                                const t_uchar * archive_path,
1380                                const t_uchar * revision)
1381 {
1382   t_uchar * version = 0;
1383   t_uchar * version_path = 0;
1384   t_uchar * level = 0;
1385   t_uchar * revision_path = 0;
1386 
1387   invariant (arch_valid_package_name (revision, arch_no_archive, arch_req_patch_level, 0));
1388 
1389   version = arch_parse_package_name (arch_ret_package_version, 0, revision);
1390   version_path = arch_fs_archive_version_path (arch, archive_path, version);
1391   level = arch_parse_package_name (arch_ret_patch_level, 0, revision);
1392   revision_path = file_name_in_vicinity (0, version_path, level);
1393 
1394   lim_free (0, version);
1395   lim_free (0, version_path);
1396   lim_free (0, level);
1397 
1398   return revision_path;
1399 }
1400 
1401 t_uchar *
arch_fs_archive_revision_log_path(const struct arch_archive * arch,const t_uchar * archive_path,const t_uchar * revision)1402 arch_fs_archive_revision_log_path (const struct arch_archive * arch,
1403                                    const t_uchar * archive_path,
1404                                    const t_uchar * revision)
1405 {
1406   t_uchar * revision_path = 0;
1407   t_uchar * log_path = 0;
1408 
1409   revision_path = arch_fs_archive_revision_path (arch, archive_path, revision);
1410   log_path = file_name_in_vicinity (0, revision_path, "log");
1411 
1412   lim_free (0, revision_path);
1413 
1414   return log_path;
1415 }
1416 
1417 t_uchar *
arch_fs_archive_changeset_path(const struct arch_archive * arch,const t_uchar * archive_path,const t_uchar * revision)1418 arch_fs_archive_changeset_path (const struct arch_archive * arch,
1419                                 const t_uchar * archive_path,
1420                                 const t_uchar * revision)
1421 {
1422   t_uchar * revision_path = 0;
1423   t_uchar * changeset_path;
1424 
1425   revision_path = arch_fs_archive_revision_path (arch, archive_path, revision);
1426   changeset_path = file_name_in_vicinity (0, revision_path, revision);
1427   changeset_path = str_realloc_cat (0, changeset_path, ".patches.tar.gz");
1428 
1429   lim_free (0, revision_path);
1430 
1431   return changeset_path;
1432 }
1433 
1434 t_uchar *
arch_fs_archive_import_path(const struct arch_archive * arch,const t_uchar * archive_path,const t_uchar * revision)1435 arch_fs_archive_import_path (const struct arch_archive * arch,
1436                              const t_uchar * archive_path,
1437                              const t_uchar * revision)
1438 {
1439   t_uchar * revision_path = 0;
1440   t_uchar * changeset_path;
1441 
1442   revision_path = arch_fs_archive_revision_path (arch, archive_path, revision);
1443   changeset_path = file_name_in_vicinity (0, revision_path, revision);
1444   changeset_path = str_realloc_cat (0, changeset_path, ".src.tar.gz");
1445 
1446   lim_free (0, revision_path);
1447 
1448   return changeset_path;
1449 }
1450 
1451 
1452 t_uchar *
arch_fs_archive_cached_path(const struct arch_archive * arch,const t_uchar * archive_path,const t_uchar * revision)1453 arch_fs_archive_cached_path (const struct arch_archive * arch,
1454                              const t_uchar * archive_path,
1455                              const t_uchar * revision)
1456 {
1457   t_uchar * revision_path = 0;
1458   t_uchar * changeset_path;
1459 
1460   revision_path = arch_fs_archive_revision_path (arch, archive_path, revision);
1461   changeset_path = file_name_in_vicinity (0, revision_path, revision);
1462   changeset_path = str_realloc_cat (0, changeset_path, ".tar.gz");
1463 
1464   lim_free (0, revision_path);
1465 
1466   return changeset_path;
1467 }
1468 
1469 t_uchar *
arch_fs_archive_cached_checksum_path(const struct arch_archive * arch,const t_uchar * archive_path,const t_uchar * revision)1470 arch_fs_archive_cached_checksum_path (const struct arch_archive * arch,
1471                                       const t_uchar * archive_path,
1472                                       const t_uchar * revision)
1473 {
1474   t_uchar * revision_path = 0;
1475   t_uchar * checksum_path = 0;
1476 
1477   revision_path = arch_fs_archive_revision_path (arch, archive_path, revision);
1478   checksum_path = file_name_in_vicinity (0, revision_path, "checksum.cacherev");
1479 
1480   lim_free (0, revision_path);
1481 
1482   return checksum_path;
1483 }
1484 
1485 
1486 t_uchar *
arch_fs_archive_continuation_path(const struct arch_archive * arch,const t_uchar * archive_path,const t_uchar * revision)1487 arch_fs_archive_continuation_path (const struct arch_archive * arch,
1488                                    const t_uchar * archive_path,
1489                                    const t_uchar * revision)
1490 {
1491   t_uchar * revision_path = 0;
1492   t_uchar * continuation_path;
1493 
1494   revision_path = arch_fs_archive_revision_path (arch, archive_path, revision);
1495   continuation_path = file_name_in_vicinity (0, revision_path, "CONTINUATION");
1496 
1497   lim_free (0, revision_path);
1498 
1499   return continuation_path;
1500 }
1501 
1502 
1503 
1504 t_uchar *
arch_fs_archive_revision_lock_unlocked_path(const struct arch_archive * arch,const t_uchar * archive_path,const t_uchar * version,const t_uchar * prev_level)1505 arch_fs_archive_revision_lock_unlocked_path (const struct arch_archive * arch,
1506 					     const t_uchar * archive_path,
1507                                              const t_uchar * version,
1508                                              const t_uchar * prev_level)
1509 {
1510   t_uchar * answer = 0;
1511 
1512   invariant (arch_valid_package_name (version, arch_no_archive, arch_req_version, 0));
1513 
1514   if (!prev_level)
1515     {
1516       t_uchar * version_path = 0;
1517 
1518       version_path = arch_fs_archive_version_path (arch, archive_path, version);
1519       answer = file_name_in_vicinity (0, version_path, "++revision-lock");
1520 
1521       lim_free (0, version_path);
1522     }
1523   else
1524     {
1525       t_uchar * revision = 0;
1526       t_uchar * revision_path = 0;
1527 
1528       revision = str_alloc_cat_many (0, version, "--", prev_level, str_end);
1529       revision_path = arch_fs_archive_revision_path (arch, archive_path, revision);
1530 
1531       answer = file_name_in_vicinity (0, revision_path, "++revision-lock");
1532 
1533       lim_free (0, revision);
1534       lim_free (0, revision_path);
1535     }
1536 
1537   return answer;
1538 }
1539 
1540 
1541 t_uchar *
arch_fs_archive_revision_lock_locked_path(const struct arch_archive * arch,const t_uchar * archive_path,const t_uchar * version,const t_uchar * prev_level,const t_uchar * arch_user_id,const t_uchar * txn_id)1542 arch_fs_archive_revision_lock_locked_path (const struct arch_archive * arch,
1543 					   const t_uchar * archive_path,
1544                                            const t_uchar * version,
1545                                            const t_uchar * prev_level,
1546                                            const t_uchar * arch_user_id,
1547                                            const t_uchar * txn_id)
1548 {
1549   t_uchar * version_path = 0;
1550   t_uchar * lock_basename = 0;
1551   t_uchar * answer = 0;
1552 
1553   invariant (arch_valid_package_name (version, arch_no_archive, arch_req_version, 0));
1554 
1555   version_path = arch_fs_archive_version_path (arch, archive_path, version);
1556 
1557   lock_basename = str_alloc_cat_many (0,
1558                                       "++revision-lock-held--",
1559                                       (prev_level ? prev_level : (t_uchar *)"absolute-0"),
1560                                       "--",
1561                                       arch_user_id,
1562                                       (txn_id ? "--" : 0),
1563                                       txn_id,
1564                                       str_end);
1565 
1566   answer = file_name_in_vicinity (0, version_path, lock_basename);
1567 
1568   lim_free (0, version_path);
1569   lim_free (0, lock_basename);
1570   return answer;
1571 }
1572 
1573 
1574 t_uchar *
arch_fs_archive_revision_lock_locked_contents_path(const struct arch_archive * arch,const t_uchar * archive_path,const t_uchar * version,const t_uchar * prev_level,const t_uchar * arch_user_id,const t_uchar * txn_id)1575 arch_fs_archive_revision_lock_locked_contents_path (const struct arch_archive * arch,
1576 						    const t_uchar * archive_path,
1577                                                     const t_uchar * version,
1578                                                     const t_uchar * prev_level,
1579                                                     const t_uchar * arch_user_id,
1580                                                     const t_uchar * txn_id)
1581 {
1582   t_uchar * locked_path = 0;
1583   t_uchar * answer = 0;
1584 
1585   locked_path = arch_fs_archive_revision_lock_locked_path (arch, archive_path, version, prev_level, arch_user_id, txn_id);
1586   answer = file_name_in_vicinity (0, locked_path, "+contents");
1587 
1588   lim_free (0, locked_path);
1589   return answer;
1590 }
1591 
1592 
1593 t_uchar *
arch_fs_archive_revision_lock_broken_path(const struct arch_archive * arch,const t_uchar * archive_path,const t_uchar * version,const t_uchar * prev_level)1594 arch_fs_archive_revision_lock_broken_path (const struct arch_archive * arch,
1595 					   const t_uchar * archive_path,
1596                                            const t_uchar * version,
1597                                            const t_uchar * prev_level)
1598 {
1599   t_uchar * version_path = 0;
1600   t_uchar * lock_dir_basename = 0;
1601   t_uchar * lock_basename = 0;
1602   t_uchar * broken_dir = 0;
1603   t_uchar * answer = 0;
1604 
1605   version_path = arch_fs_archive_version_path (arch, archive_path, version);
1606 
1607   lock_dir_basename = str_alloc_cat (0, "++revision-lock-broken--", (prev_level ? prev_level : (t_uchar *)"absolute-0"));
1608   lock_basename = str_alloc_cat (0, ",,remade-lock--", (prev_level ? prev_level : (t_uchar *)"absolute-0"));
1609 
1610   broken_dir = file_name_in_vicinity (0, version_path, lock_dir_basename);
1611   answer = file_name_in_vicinity (0, broken_dir, lock_basename);
1612 
1613   lim_free (0, version_path);
1614   lim_free (0, lock_dir_basename);
1615   lim_free (0, lock_basename);
1616   lim_free (0, broken_dir);
1617   return answer;
1618 }
1619 
1620 
1621 
1622 
1623 
1624 
1625 /* tag: Tom Lord Tue May 20 00:52:06 2003 (archive.c)
1626  */
1627