1 /* archive-snapshot.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/os/errno.h"
12 #include "hackerlab/os/errno-to-string.h"
13 #include "hackerlab/char/str.h"
14 #include "hackerlab/fs/file-names.h"
15 #include "hackerlab/vu/safe.h"
16 #include "tla/libfsutils/ensure-dir.h"
17 #include "tla/libfsutils/tmp-files.h"
18 #include "tla/libawk/relational.h"
19 #include "tla/libarch/archive.h"
20 #include "tla/libarch/namespace.h"
21 #include "tla/libarch/archive-snapshot.h"
22 
23 
24 /* __STDC__ prototypes for static functions */
25 static void put_file_contents (t_uchar * path, t_uchar * contents);
26 static void ensure_basename (t_uchar * dir, t_uchar * basename);
27 
28 
29 
30 void
archive_snapshot(struct arch_archive * arch,t_uchar * limit,t_uchar * dir)31 archive_snapshot (struct arch_archive * arch, t_uchar * limit, t_uchar * dir)
32 {
33   t_uchar * only_category = 0;
34   t_uchar * only_branch = 0;
35   t_uchar * only_version = 0;
36   t_uchar * only_revision = 0;
37   t_uchar * archive_basename = 0;
38   t_uchar * archive_subdir = 0;
39   rel_table categories  = rel_table_nil;
40   int c;
41 
42   if (limit)
43     {
44       only_category = arch_parse_package_name (arch_ret_category, 0, limit);
45 
46       if (arch_valid_package_name (limit, arch_no_archive, arch_req_package, 1))
47         {
48           only_branch = arch_parse_package_name (arch_ret_package, 0, limit);
49 
50           if (!str_cmp (only_branch, only_category))
51             {
52               lim_free (0, only_branch);
53               only_branch = 0;
54             }
55           else if (arch_valid_package_name (limit, arch_no_archive, arch_req_version, 1))
56             {
57               only_version = arch_parse_package_name (arch_ret_package_version, 0, limit);
58 
59               if (arch_valid_package_name (limit, arch_no_archive, arch_req_patch_level, 1))
60                 {
61                   only_revision = arch_parse_package_name (arch_ret_non_archive, 0, limit);
62                 }
63             }
64         }
65     }
66 
67 
68   archive_basename = str_alloc_cat (0, arch->name, ".added");
69   ensure_basename (dir, archive_basename);
70 
71   archive_subdir = file_name_in_vicinity (0, dir, arch->name);
72   ensure_directory_exists (archive_subdir);
73 
74   categories = arch_archive_categories (arch);
75 
76   for (c = 0; c < rel_n_records (categories); ++c)
77     {
78       t_uchar * category_basename = 0;
79       t_uchar * category_subdir = 0;
80       rel_table branches  = rel_table_nil;
81       int b;
82 
83       if (only_category && str_cmp (only_category, rel_peek_str (categories, c, 0)))
84         continue;
85 
86       category_basename = str_alloc_cat (0, rel_peek_str (categories, c, 0), ".added");
87       category_subdir = file_name_in_vicinity (0, archive_subdir, rel_peek_str (categories, c, 0));
88       branches = arch_archive_branches (arch, rel_peek_str (categories, c, 0));
89 
90       ensure_basename (archive_subdir, category_basename);
91       ensure_directory_exists (category_subdir);
92 
93       for (b = 0; b < rel_n_records (branches); ++b)
94         {
95           t_uchar * branch_basename = 0;
96           t_uchar * branch_subdir = 0;
97           rel_table versions  = rel_table_nil;
98           int v;
99 
100           if (only_branch && str_cmp (only_branch, rel_peek_str (branches, b, 0)))
101             continue;
102 
103           branch_basename = str_alloc_cat (0, rel_peek_str (branches, b, 0), ".added");
104           branch_subdir = file_name_in_vicinity (0, category_subdir, rel_peek_str (branches, b, 0));
105           versions = arch_archive_versions (arch, rel_peek_str (branches, b, 0));
106 
107           ensure_basename (category_subdir, branch_basename);
108           ensure_directory_exists (branch_subdir);
109 
110           for (v = 0; v < rel_n_records (versions); ++v)
111             {
112               t_uchar * version_basename = 0;
113               t_uchar * version_subdir = 0;
114               rel_table revisions  = rel_table_nil;
115               int r;
116 
117               if (only_version && str_cmp (only_version, rel_peek_str (versions, v, 0)))
118                 continue;
119 
120               version_basename = str_alloc_cat (0, rel_peek_str (versions, v, 0), ".added");
121               version_subdir = file_name_in_vicinity (0, branch_subdir, rel_peek_str (versions, v, 0));
122               revisions = arch_archive_revisions (arch, rel_peek_str (versions, v, 0), 2);
123 
124               ensure_basename (branch_subdir, version_basename);
125               ensure_directory_exists (version_subdir);
126 
127               for (r = 0; r < rel_n_records (revisions); ++r)
128                 {
129                   t_uchar * revision_basename = 0;
130                   t_uchar * revision_file = 0;
131                   t_uchar * log = 0;
132 
133                   if (only_revision && str_cmp (only_revision, rel_peek_str (revisions, r, 0)))
134                     continue;
135 
136                   revision_basename = str_alloc_cat (0, rel_peek_str (revisions, r, 0), ".added");
137                   revision_file = file_name_in_vicinity (0, version_subdir, revision_basename);
138                   if (safe_access (revision_file, F_OK))
139                     {
140                       t_uchar * tmp_file = 0;
141 
142                       tmp_file = tmp_file_name (version_subdir, ",,new-log");
143                       log = arch_archive_log (arch, rel_peek_str (revisions, r, 0));
144                       put_file_contents (tmp_file, log);
145                       safe_rename (tmp_file, revision_file);
146 
147                       lim_free (0, tmp_file);
148                     }
149 
150 
151                   lim_free (0, revision_basename);
152                   lim_free (0, revision_file);
153                   lim_free (0, log);
154                 }
155 
156 
157               lim_free (0, version_basename);
158               lim_free (0, version_subdir);
159               rel_free_table (revisions);
160             }
161 
162 
163           lim_free (0, branch_basename);
164           lim_free (0, branch_subdir);
165           rel_free_table (versions);
166         }
167 
168 
169       lim_free (0, category_basename);
170       lim_free (0, category_subdir);
171       rel_free_table (branches);
172     }
173 
174 
175 
176   lim_free (0, only_category);
177   lim_free (0, only_branch);
178   lim_free (0, only_version);
179   lim_free (0, only_revision);
180   lim_free (0, archive_basename);
181   lim_free (0, archive_subdir);
182   rel_free_table (categories);
183 }
184 
185 
186 
187 static void
put_file_contents(t_uchar * path,t_uchar * contents)188 put_file_contents (t_uchar * path, t_uchar * contents)
189 {
190   int out_fd;
191 
192   out_fd = safe_open (path, O_WRONLY | O_CREAT | O_EXCL, 0444);
193   safe_printfmt (out_fd, "%s\n", contents);
194   safe_close (out_fd);
195 }
196 
197 static void
ensure_basename(t_uchar * dir,t_uchar * basename)198 ensure_basename (t_uchar * dir, t_uchar * basename)
199 {
200   int errn;
201   t_uchar * path = 0;
202   int in_fd;
203 
204   path = file_name_in_vicinity (0, dir, basename);
205   in_fd = vu_open (&errn, path, O_WRONLY | O_CREAT | O_EXCL, 0444);
206   if (in_fd >= 0)
207     safe_close (in_fd);
208   else if (errn != EEXIST)
209     {
210       safe_printfmt (2, "archive-snapshot: error creating file %s/%s (%s)\n", dir, basename, errno_to_string (errn));
211       exit (2);
212     }
213 
214   lim_free (0, path);
215 }
216 
217 
218 
219 
220 /* tag: Tom Lord Mon Jun  9 01:03:59 2003 (archive-snapshot.c)
221  */
222