1 /* libraries.c:
2  *
3  ****************************************************************
4  * Copyright (C) 2003 Tom Lord
5  *
6  * See the file "COPYING" for further information about
7  * the copyright and warranty status of this work.
8  */
9 
10 
11 #include "hackerlab/bugs/panic.h"
12 #include "hackerlab/char/str.h"
13 #include "hackerlab/fs/file-names.h"
14 #include "hackerlab/vu/safe.h"
15 #include "tla/libfsutils/dir-listing.h"
16 #include "tla/libfsutils/same.h"
17 #include "tla/libarch/my.h"
18 #include "tla/libarch/namespace.h"
19 #include "tla/libarch/patch-logs.h"
20 #include "tla/libarch/changeset-utils.h"
21 #include "tla/libarch/libraries.h"
22 #include "tla/libarch/inode-sig.h"
23 
24 
25 /* __STDC__ prototypes for static functions */
26 
27 
28 
29 
30 
31 rel_table
arch_library_archive_dirs(rel_table opt_lib_path,const t_uchar * archive,int for_add)32 arch_library_archive_dirs (rel_table opt_lib_path,
33                            const t_uchar * archive,
34                            int for_add)
35 {
36   rel_table lib_path = rel_table_nil;
37   rel_table answer = rel_table_nil;
38   int x;
39 
40   invariant (arch_valid_archive_name (archive));
41 
42   if (rel_n_records (opt_lib_path))
43     {
44       lib_path = rel_copy_table (opt_lib_path);
45     }
46   else
47     {
48       lib_path = arch_my_library_path (for_add ? arch_library_path_add_order : arch_library_path_search_order);
49       if (!rel_n_records (lib_path))
50         return rel_table_nil;
51     }
52 
53   for (x = 0; x < rel_n_records (lib_path); ++x)
54     {
55       const t_uchar * lib_dir;
56       t_uchar * maybe_archive_dir = 0;
57 
58       lib_dir = rel_peek_str (lib_path, x, 0);
59       maybe_archive_dir = file_name_in_vicinity (0, lib_dir, archive);
60 
61       if (!safe_access (maybe_archive_dir, F_OK))
62         {
63           rel_add_records (&answer, rel_singleton_record_taking (rel_make_field_str (maybe_archive_dir)), rel_record_null);
64         }
65 
66       lim_free (0, maybe_archive_dir);
67     }
68 
69   if (for_add && !rel_n_records (answer))
70     {
71       const t_uchar * priority_lib_dir;
72       t_uchar * archive_dir = 0;
73 
74       priority_lib_dir = rel_peek_str (lib_path, 0, 0);
75       archive_dir = file_name_in_vicinity (0, priority_lib_dir, archive);
76       rel_add_records (&answer, rel_singleton_record_taking (rel_make_field_str (archive_dir)), rel_record_null);
77 
78       lim_free (0, archive_dir);
79     }
80 
81   rel_free_table (lib_path);
82   return answer;
83 }
84 
85 
86 rel_table
arch_library_category_dirs(rel_table opt_lib_path,const t_uchar * archive,const t_uchar * category,int for_add)87 arch_library_category_dirs (rel_table opt_lib_path,
88                             const t_uchar * archive,
89                             const t_uchar * category,
90                             int for_add)
91 {
92   rel_table answer = rel_table_nil;
93   rel_table archive_dirs = rel_table_nil;
94   int x;
95 
96   invariant (arch_valid_package_name (category, arch_no_archive, arch_req_category, 0));
97 
98   archive_dirs = arch_library_archive_dirs (opt_lib_path, archive, for_add);
99   if (!rel_n_records (archive_dirs))
100     return rel_table_nil;
101 
102   for (x = 0; x < rel_n_records (archive_dirs); ++x)
103     {
104       const t_uchar * archive_dir;
105       t_uchar * maybe_category_dir = 0;
106 
107       archive_dir = rel_peek_str (archive_dirs, x, 0);
108       maybe_category_dir = file_name_in_vicinity (0, archive_dir, category);
109 
110       if (!safe_access (maybe_category_dir, F_OK))
111         {
112           rel_add_records (&answer, rel_singleton_record_taking (rel_make_field_str (maybe_category_dir)), rel_record_null);
113         }
114 
115       lim_free (0, maybe_category_dir);
116     }
117 
118   if (for_add && !rel_n_records (answer))
119     {
120       const t_uchar * priority_archive_dir;
121       t_uchar * category_dir = 0;
122 
123       priority_archive_dir = rel_peek_str (archive_dirs, 0, 0);
124       category_dir = file_name_in_vicinity (0, priority_archive_dir, category);
125       rel_add_records (&answer, rel_singleton_record_taking (rel_make_field_str (category_dir)), rel_record_null);
126 
127       lim_free (0, category_dir);
128     }
129 
130   rel_free_table (archive_dirs);
131 
132   return answer;
133 }
134 
135 
136 rel_table
arch_library_branch_dirs(rel_table opt_lib_path,const t_uchar * archive,const t_uchar * branch,int for_add)137 arch_library_branch_dirs (rel_table opt_lib_path,
138                           const t_uchar * archive,
139                           const t_uchar * branch,
140                           int for_add)
141 {
142   rel_table answer = rel_table_nil;
143   t_uchar * category = 0;
144   rel_table category_dirs = rel_table_nil;
145   int x;
146 
147   invariant (arch_valid_package_name (branch, arch_no_archive, arch_req_package, 0));
148 
149   category = arch_parse_package_name (arch_ret_category, 0, branch);
150 
151   category_dirs = arch_library_category_dirs (opt_lib_path, archive, category, for_add);
152   if (!rel_n_records (category_dirs))
153     return rel_table_nil;
154 
155   for (x = 0; x < rel_n_records (category_dirs); ++x)
156     {
157       const t_uchar * category_dir;
158       t_uchar * maybe_branch_dir = 0;
159 
160       category_dir = rel_peek_str (category_dirs, x, 0);
161       maybe_branch_dir = file_name_in_vicinity (0, category_dir, branch);
162 
163       if (!safe_access (maybe_branch_dir, F_OK))
164         {
165           rel_add_records (&answer, rel_singleton_record_taking (rel_make_field_str (maybe_branch_dir)), rel_record_null);
166         }
167 
168       lim_free (0, maybe_branch_dir);
169     }
170 
171   if (for_add && !rel_n_records (answer))
172     {
173       const t_uchar * priority_category_dir;
174       t_uchar * branch_dir = 0;
175 
176       priority_category_dir = rel_peek_str (category_dirs, 0, 0);
177       branch_dir = file_name_in_vicinity (0, priority_category_dir, branch);
178       rel_add_records (&answer, rel_singleton_record_taking (rel_make_field_str (branch_dir)), rel_record_null);
179 
180       lim_free (0, branch_dir);
181     }
182 
183   rel_free_table (category_dirs);
184   lim_free (0, category);
185 
186   return answer;
187 }
188 
189 
190 rel_table
arch_library_version_dirs(rel_table opt_lib_path,const t_uchar * archive,const t_uchar * version,int for_add)191 arch_library_version_dirs (rel_table opt_lib_path,
192                            const t_uchar * archive,
193                            const t_uchar * version,
194                            int for_add)
195 {
196   rel_table answer = rel_table_nil;
197   t_uchar * branch = 0;
198   rel_table branch_dirs = rel_table_nil;
199   int x;
200 
201   invariant (arch_valid_package_name (version, arch_no_archive, arch_req_version, 0));
202 
203   branch = arch_parse_package_name (arch_ret_package, 0, version);
204 
205   branch_dirs = arch_library_branch_dirs (opt_lib_path, archive, branch, for_add);
206   if (!rel_n_records (branch_dirs))
207     return rel_table_nil;
208 
209   for (x = 0; x < rel_n_records (branch_dirs); ++x)
210     {
211       const t_uchar * branch_dir;
212       t_uchar * maybe_version_dir = 0;
213 
214       branch_dir = rel_peek_str (branch_dirs, x, 0);
215       maybe_version_dir = file_name_in_vicinity (0, branch_dir, version);
216 
217       if (!safe_access (maybe_version_dir, F_OK))
218         {
219           rel_add_records (&answer, rel_singleton_record_taking (rel_make_field_str (maybe_version_dir)), rel_record_null);
220         }
221 
222       lim_free (0, maybe_version_dir);
223     }
224 
225   if (for_add && !rel_n_records (answer))
226     {
227       const t_uchar * priority_branch_dir;
228       t_uchar * version_dir = 0;
229 
230       priority_branch_dir = rel_peek_str (branch_dirs, 0, 0);
231       version_dir = file_name_in_vicinity (0, priority_branch_dir, version);
232       rel_add_records (&answer, rel_singleton_record_taking (rel_make_field_str (version_dir)), rel_record_null);
233 
234       lim_free (0, version_dir);
235     }
236 
237   rel_free_table (branch_dirs);
238   lim_free (0, branch);
239 
240   return answer;
241 }
242 
243 
244 rel_table
arch_library_revision_dirs(rel_table opt_lib_path,const t_uchar * archive,const t_uchar * revision,int for_add)245 arch_library_revision_dirs (rel_table opt_lib_path,
246                             const t_uchar * archive,
247                             const t_uchar * revision,
248                             int for_add)
249 {
250   rel_table answer = rel_table_nil;
251   t_uchar * version = 0;
252   rel_table version_dirs = rel_table_nil;
253   int x;
254 
255   invariant (arch_valid_package_name (revision, arch_no_archive, arch_req_patch_level, 0));
256 
257   version = arch_parse_package_name (arch_ret_package_version, 0, revision);
258 
259   version_dirs = arch_library_version_dirs (opt_lib_path, archive, version, for_add);
260   if (!rel_n_records (version_dirs))
261     return rel_table_nil;
262 
263   for (x = 0; x < rel_n_records (version_dirs); ++x)
264     {
265       const t_uchar * version_dir;
266       t_uchar * maybe_revision_dir = 0;
267 
268       version_dir = rel_peek_str (version_dirs, x, 0);
269       maybe_revision_dir = file_name_in_vicinity (0, version_dir, revision);
270 
271       if (!safe_access (maybe_revision_dir, F_OK))
272         {
273           rel_add_records (&answer, rel_singleton_record_taking (rel_make_field_str (maybe_revision_dir)), rel_record_null);
274         }
275 
276       lim_free (0, maybe_revision_dir);
277     }
278 
279   if (for_add && !rel_n_records (answer))
280     {
281       const t_uchar * priority_version_dir;
282       t_uchar * revision_dir = 0;
283 
284       priority_version_dir = rel_peek_str (version_dirs, 0, 0);
285       revision_dir = file_name_in_vicinity (0, priority_version_dir, revision);
286       rel_add_records (&answer, rel_singleton_record_taking (rel_make_field_str (revision_dir)), rel_record_null);
287 
288       lim_free (0, revision_dir);
289     }
290 
291   rel_free_table (version_dirs);
292   lim_free (0, version);
293 
294   return answer;
295 }
296 
297 
298 
299 t_uchar *
arch_library_find(rel_table opt_lib_path,const t_uchar * archive,const t_uchar * revision,int check_inode_sigs)300 arch_library_find (rel_table opt_lib_path,
301                    const t_uchar * archive,
302                    const t_uchar * revision,
303                    int check_inode_sigs)
304 {
305   rel_table revision_dirs = rel_table_nil;
306   t_uchar * answer = 0;
307   int x;
308 
309   revision_dirs = arch_library_revision_dirs (opt_lib_path, archive, revision, 0);
310 
311   for (x = 0; x < rel_n_records (revision_dirs); ++x)
312     {
313       if (!safe_access (rel_peek_str (revision_dirs, x, 0), F_OK))
314         {
315           if (check_inode_sigs) {
316             if (!arch_valid_inode_sig (rel_peek_str (revision_dirs, 0, 0), archive, revision))
317               {
318                 safe_printfmt (2, "corrupt library (failed inode signature validation)\n    archive: %s\n    revision: %s\nYou should remove this revision from your library.\n",
319                                archive, revision);
320                 exit (2);
321               }
322           }
323           answer = str_save (0, rel_peek_str (revision_dirs, 0, 0));
324           break;
325         }
326     }
327 
328   rel_free_table (revision_dirs);
329   return answer;
330 }
331 
332 
333 
334 t_uchar *
arch_library_find_file(const t_uchar * archive,const t_uchar * revision,const t_uchar * loc)335 arch_library_find_file (const t_uchar * archive,
336                         const t_uchar * revision,
337                         const t_uchar * loc)
338 {
339   t_uchar * revision_dir = 0;
340   t_uchar * file_path = 0;
341 
342   revision_dir = arch_library_find (rel_table_nil, archive, revision, 1);
343 
344   if (revision_dir)
345     {
346       file_path = file_name_in_vicinity (0, revision_dir, loc);
347 
348       if (safe_access (file_path, F_OK))
349         {
350           lim_free (0, file_path);
351           file_path = 0;
352         }
353     }
354 
355   lim_free (0, revision_dir);
356 
357   return file_path;
358 }
359 
360 
361 t_uchar *
arch_library_find_file_by_id(const t_uchar * archive,const t_uchar * revision,const t_uchar * id)362 arch_library_find_file_by_id (const t_uchar * archive,
363                               const t_uchar * revision,
364                               const t_uchar * id)
365 {
366   t_uchar * revision_dir = 0;
367   t_uchar * file_path = 0;
368 
369   revision_dir = arch_library_find (rel_table_nil, archive, revision, 1);
370 
371   if (revision_dir)
372     {
373       t_uchar * index_file = 0;
374       rel_table index = rel_table_nil;
375       int x;
376 
377       index_file = arch_library_index_file (archive, revision);
378       index = arch_read_changeset_index (index_file);
379 
380       for (x = 0; x < rel_n_records (index); ++x)
381         {
382           if (!str_cmp (id, rel_peek_str (index, x, 1)))
383             {
384               file_path = file_name_in_vicinity (0, revision_dir, rel_peek_str (index, x, 0));
385               break;
386             }
387         }
388 
389       lim_free (0, index_file);
390       rel_free_table (index);
391     }
392 
393   lim_free (0, revision_dir);
394 
395   return file_path;
396 }
397 
398 
399 
400 rel_table
arch_library_archives(void)401 arch_library_archives (void)
402 {
403   rel_table lib_path = rel_table_nil;
404   rel_table answer = rel_table_nil;
405   int x;
406 
407   lib_path = arch_my_library_path (arch_library_path_search_order);
408 
409   for (x = 0; x < rel_n_records (lib_path); ++x)
410     {
411       rel_table tmp = rel_table_nil;
412       rel_table files = rel_table_nil;
413 
414       files = directory_files (rel_peek_str (lib_path, x, 0));
415       tmp = arch_pick_archives_by_field (files, 0);
416 
417       rel_append_x (&answer, tmp);
418 
419       rel_free_table (tmp);
420       rel_free_table (files);
421     }
422 
423   rel_sort_table_by_field (0, answer, 0);
424   rel_uniq_by_field (&answer, 0);
425 
426   rel_free_table (lib_path);
427   return answer;
428 }
429 
430 
431 rel_table
arch_library_categories(const t_uchar * archive)432 arch_library_categories (const t_uchar * archive)
433 {
434   rel_table answer = rel_table_nil;
435   rel_table archive_dirs = rel_table_nil;
436   int x;
437 
438   archive_dirs = arch_library_archive_dirs (rel_table_nil, archive, 0);
439 
440   for (x = 0; x < rel_n_records (archive_dirs); ++x)
441     {
442       rel_table files = rel_table_nil;
443       rel_table tmp = rel_table_nil;
444 
445       files = directory_files (rel_peek_str (archive_dirs, x, 0));
446       tmp = arch_pick_categories_by_field (files, 0);
447       rel_append_x (&answer, tmp);
448 
449       rel_free_table (files);
450       rel_free_table (tmp);
451     }
452 
453   rel_sort_table_by_field (0, answer, 0);
454   rel_uniq_by_field (&answer, 0);
455 
456   rel_free_table (archive_dirs);
457 
458   return answer;
459 }
460 
461 
462 rel_table
arch_library_branches(const t_uchar * archive,const t_uchar * category)463 arch_library_branches (const t_uchar * archive,
464                        const t_uchar * category)
465 {
466   rel_table answer = rel_table_nil;
467   rel_table category_dirs = rel_table_nil;
468   int x;
469 
470   category_dirs = arch_library_category_dirs (rel_table_nil, archive, category, 0);
471 
472   for (x = 0; x < rel_n_records (category_dirs); ++x)
473     {
474       rel_table files = rel_table_nil;
475       rel_table tmp = rel_table_nil;
476 
477       files = directory_files (rel_peek_str (category_dirs, x, 0));
478       tmp = arch_pick_branches_by_field (files, 0);
479       rel_append_x (&answer, tmp);
480 
481       rel_free_table (files);
482       rel_free_table (tmp);
483     }
484 
485   rel_sort_table_by_field (0, answer, 0);
486   rel_uniq_by_field (&answer, 0);
487 
488   rel_free_table (category_dirs);
489 
490   return answer;
491 }
492 
493 
494 rel_table
arch_library_versions(const t_uchar * archive,const t_uchar * branch)495 arch_library_versions (const t_uchar * archive,
496                        const t_uchar * branch)
497 {
498   rel_table answer = rel_table_nil;
499   rel_table branch_dirs = rel_table_nil;
500   int x;
501 
502   branch_dirs = arch_library_branch_dirs (rel_table_nil, archive, branch, 0);
503 
504   for (x = 0; x < rel_n_records (branch_dirs); ++x)
505     {
506       rel_table files = rel_table_nil;
507       rel_table tmp = rel_table_nil;
508 
509       files = directory_files (rel_peek_str (branch_dirs, x, 0));
510       tmp = arch_pick_versions_by_field (files, 0);
511       rel_append_x (&answer, tmp);
512 
513       rel_free_table (files);
514       rel_free_table (tmp);
515     }
516 
517   rel_sort_table_by_field (0, answer, 0);
518   rel_uniq_by_field (&answer, 0);
519 
520   rel_free_table (branch_dirs);
521 
522   return answer;
523 }
524 
525 
526 rel_table
arch_library_revisions(const t_uchar * archive,const t_uchar * version,int full)527 arch_library_revisions (const t_uchar * archive,
528                         const t_uchar * version,
529                         int full)
530 {
531   rel_table answer = rel_table_nil;
532   rel_table version_dirs = rel_table_nil;
533   int x;
534 
535   version_dirs = arch_library_version_dirs (rel_table_nil, archive, version, 0);
536 
537   for (x = 0; x < rel_n_records (version_dirs); ++x)
538     {
539       rel_table files = rel_table_nil;
540       rel_table tmp = rel_table_nil;
541       int y;
542 
543       files = directory_files (rel_peek_str (version_dirs, x, 0));
544       tmp = arch_pick_revisions_by_field (files, 0);
545 
546       for (y = 0; y < rel_n_records (tmp); ++y)
547         {
548           t_uchar * t = 0;
549 
550           if (full)
551             {
552               t = arch_fully_qualify (archive, rel_peek_str (tmp, y, 0));
553               rel_set_taking (tmp, y, 0, rel_make_field_str (t));
554             }
555           else
556             {
557               t = arch_parse_package_name (arch_ret_patch_level, 0, rel_peek_str (tmp, y, 0));
558               rel_set_taking (tmp, y, 0, rel_make_field_str (t));
559             }
560 
561           lim_free (0, t);
562         }
563 
564       rel_append_x (&answer, tmp);
565 
566       rel_free_table (files);
567       rel_free_table (tmp);
568     }
569 
570   if (full)
571     {
572       arch_sort_table_by_name_field (0, answer, 0);
573     }
574   else
575     {
576       arch_sort_table_by_patch_level_field (0, answer, 0);
577     }
578   rel_uniq_by_field (&answer, 0);
579 
580   rel_free_table (version_dirs);
581 
582   return answer;
583 }
584 
585 
586 
587 t_uchar *
arch_library_log(const t_uchar * archive,const t_uchar * revision)588 arch_library_log (const t_uchar * archive,
589                   const t_uchar * revision)
590 {
591   t_uchar * rev_dir = 0;
592   t_uchar * log_path = 0;
593   int in_fd;
594   t_uchar * answer = 0;
595   size_t len;
596 
597   rev_dir = arch_library_find (rel_table_nil, archive, revision, 1);
598   log_path = arch_log_file (rev_dir, archive, revision);
599   in_fd = safe_open (log_path, O_RDONLY, 0);
600   safe_file_to_string (&answer, &len, in_fd);
601   answer = lim_realloc (0, answer, len + 1);
602   answer[len] = 0;
603   safe_close (in_fd);
604 
605   lim_free (0, rev_dir);
606   lim_free (0, log_path);
607   return answer;
608 }
609 
610 
611 t_uchar *
arch_library_index_file(const t_uchar * archive,const t_uchar * revision)612 arch_library_index_file (const t_uchar * archive,
613                          const t_uchar * revision)
614 {
615   t_uchar * revision_dir = 0;
616   t_uchar * answer = 0;
617 
618   revision_dir = arch_library_find (rel_table_nil, archive, revision, 1);
619   invariant (!!revision_dir);
620 
621   answer = file_name_in_vicinity (0, revision_dir, ",,index");
622 
623   lim_free (0, revision_dir);
624   return answer;
625 }
626 
627 
628 rel_table
arch_library_index(const t_uchar * archive,const t_uchar * revision)629 arch_library_index (const t_uchar * archive,
630                     const t_uchar * revision)
631 {
632   t_uchar * index_path = 0;
633   rel_table answer = rel_table_nil;
634 
635   index_path = arch_library_index_file (archive, revision);
636   answer = arch_read_changeset_index (index_path);
637 
638   lim_free (0, index_path);
639   return answer;
640 }
641 
642 
643 
644 int
arch_library_has_archive(const t_uchar * lib,const t_uchar * archive)645 arch_library_has_archive (const t_uchar * lib,
646                           const t_uchar * archive)
647 {
648   t_uchar * path = file_name_in_vicinity (0, lib, archive);
649   int answer;
650 
651   answer = !safe_access (path, F_OK);
652 
653   lim_free (0, path);
654   return answer;
655 }
656 
657 
658 int
arch_library_has_category(const t_uchar * lib,const t_uchar * archive,const t_uchar * category)659 arch_library_has_category (const t_uchar * lib,
660                            const t_uchar * archive,
661                            const t_uchar * category)
662 {
663   t_uchar * archive_path = file_name_in_vicinity (0, lib, archive);
664   t_uchar * category_path = file_name_in_vicinity (0, archive_path, category);
665   int answer;
666 
667   answer = !safe_access (category_path, F_OK);
668 
669   lim_free (0, archive_path);
670   lim_free (0, category_path);
671   return answer;
672 }
673 
674 
675 int
arch_library_has_branch(const t_uchar * lib,const t_uchar * archive,const t_uchar * branch)676 arch_library_has_branch (const t_uchar * lib,
677                          const t_uchar * archive,
678                          const t_uchar * branch)
679 {
680   t_uchar * category = arch_parse_package_name (arch_ret_category, 0, branch);
681   t_uchar * archive_path = file_name_in_vicinity (0, lib, archive);
682   t_uchar * category_path = file_name_in_vicinity (0, archive_path, category);
683   t_uchar * branch_path = file_name_in_vicinity (0, category_path, branch);
684   int answer;
685 
686   answer = !safe_access (branch_path, F_OK);
687 
688   lim_free (0, category);
689 
690   lim_free (0, archive_path);
691   lim_free (0, category_path);
692   lim_free (0, branch_path);
693   return answer;
694 }
695 
696 
697 int
arch_library_has_version(const t_uchar * lib,const t_uchar * archive,const t_uchar * version)698 arch_library_has_version (const t_uchar * lib,
699                           const t_uchar * archive,
700                           const t_uchar * version)
701 {
702   t_uchar * category = arch_parse_package_name (arch_ret_category, 0, version);
703   t_uchar * branch = arch_parse_package_name (arch_ret_package, 0, version);
704   t_uchar * archive_path = file_name_in_vicinity (0, lib, archive);
705   t_uchar * category_path = file_name_in_vicinity (0, archive_path, category);
706   t_uchar * branch_path = file_name_in_vicinity (0, category_path, branch);
707   t_uchar * version_path = file_name_in_vicinity (0, branch_path, version);
708   int answer;
709 
710   answer = !safe_access (version_path, F_OK);
711 
712   lim_free (0, category);
713   lim_free (0, branch);
714 
715   lim_free (0, archive_path);
716   lim_free (0, category_path);
717   lim_free (0, branch_path);
718   lim_free (0, version_path);
719   return answer;
720 }
721 
722 
723 t_uchar *
arch_library_revision_dir_in_lib(const t_uchar * lib,const t_uchar * archive,const t_uchar * revision)724 arch_library_revision_dir_in_lib (const t_uchar * lib,
725                                   const t_uchar * archive,
726                                   const t_uchar * revision)
727 {
728   t_uchar * category = arch_parse_package_name (arch_ret_category, 0, revision);
729   t_uchar * branch = arch_parse_package_name (arch_ret_package, 0, revision);
730   t_uchar * version = arch_parse_package_name (arch_ret_package_version, 0, revision);
731   t_uchar * archive_path = file_name_in_vicinity (0, lib, archive);
732   t_uchar * category_path = file_name_in_vicinity (0, archive_path, category);
733   t_uchar * branch_path = file_name_in_vicinity (0, category_path, branch);
734   t_uchar * version_path = file_name_in_vicinity (0, branch_path, version);
735   t_uchar * revision_path = file_name_in_vicinity (0, version_path, revision);
736 
737   lim_free (0, category);
738   lim_free (0, branch);
739   lim_free (0, version);
740 
741   lim_free (0, archive_path);
742   lim_free (0, category_path);
743   lim_free (0, branch_path);
744   lim_free (0, version_path);
745 
746   return revision_path;
747 }
748 
749 
750 
751 int
arch_library_is_greedy(const t_uchar * lib)752 arch_library_is_greedy (const t_uchar * lib)
753 {
754   t_uchar * greed_path = file_name_in_vicinity (0, lib, "=greedy");
755   int answer = 0;
756 
757   answer = !safe_access (greed_path, F_OK);
758 
759   lim_free (0, greed_path);
760 
761   return answer;
762 }
763 
764 
765 void
arch_set_library_greediness(const t_uchar * lib,int setting)766 arch_set_library_greediness (const t_uchar * lib,
767                              int setting)
768 {
769   t_uchar * greed_path = file_name_in_vicinity (0, lib, "=greedy");
770 
771   if (setting)
772     {
773       int fd;
774 
775       fd = safe_open (greed_path, O_RDONLY | O_CREAT, 0666);
776       safe_close (fd);
777     }
778   else
779     {
780       if (!safe_access (greed_path, F_OK))
781         safe_unlink (greed_path);
782     }
783 
784   lim_free (0, greed_path);
785 }
786 
787 
788 int
arch_library_is_sparse(const t_uchar * lib)789 arch_library_is_sparse (const t_uchar * lib)
790 {
791   t_uchar * sparse_path = file_name_in_vicinity (0, lib, "=sparse");
792   int answer = 0;
793 
794   answer = !safe_access (sparse_path, F_OK);
795 
796   lim_free (0, sparse_path);
797 
798   return answer;
799 }
800 
801 
802 void
arch_set_library_sparseness(const t_uchar * lib,int setting)803 arch_set_library_sparseness (const t_uchar * lib,
804                              int setting)
805 {
806   t_uchar * sparse_path = file_name_in_vicinity (0, lib, "=sparse");
807 
808   if (setting)
809     {
810       int fd;
811 
812       fd = safe_open (sparse_path, O_RDONLY | O_CREAT, 0666);
813       safe_close (fd);
814     }
815   else
816     {
817       if (!safe_access (sparse_path, F_OK))
818         safe_unlink (sparse_path);
819     }
820 
821   lim_free (0, sparse_path);
822 }
823 
824 
825 
826 
827 void
arch_verify_is_library(const t_uchar * lib)828 arch_verify_is_library (const t_uchar * lib)
829 {
830   rel_table lib_path = rel_table_nil;
831   int x;
832 
833   lib_path = arch_my_library_path (arch_library_path_search_order);
834 
835   for (x = 0; x < rel_n_records (lib_path); ++x)
836     {
837       if (names_same_inode (lib, rel_peek_str (lib_path, x, 0)))
838         return;
839     }
840 
841   safe_printfmt (2, "tla: indicated library is not on library path\n  dir %s\n", lib);
842   exit (2);
843 }
844 
845 
846 
847 /* tag: Tom Lord Wed May 21 13:56:29 2003 (libraries.c)
848  */
849