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 (¤t_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