| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: walk.c,v 1.37 2024/04/24 14:02:39 christos Exp $ */ | | 1 | /* $NetBSD: walk.c,v 1.38 2024/04/24 14:23:37 christos Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2001 Wasabi Systems, Inc. | | 4 | * Copyright (c) 2001 Wasabi Systems, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Written by Luke Mewburn for Wasabi Systems, Inc. | | 7 | * Written by Luke Mewburn for Wasabi Systems, Inc. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
| @@ -31,27 +31,27 @@ | | | @@ -31,27 +31,27 @@ |
31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
35 | * POSSIBILITY OF SUCH DAMAGE. | | 35 | * POSSIBILITY OF SUCH DAMAGE. |
36 | */ | | 36 | */ |
37 | | | 37 | |
38 | #if HAVE_NBTOOL_CONFIG_H | | 38 | #if HAVE_NBTOOL_CONFIG_H |
39 | #include "nbtool_config.h" | | 39 | #include "nbtool_config.h" |
40 | #endif | | 40 | #endif |
41 | | | 41 | |
42 | #include <sys/cdefs.h> | | 42 | #include <sys/cdefs.h> |
43 | #if defined(__RCSID) && !defined(__lint) | | 43 | #if defined(__RCSID) && !defined(__lint) |
44 | __RCSID("$NetBSD: walk.c,v 1.37 2024/04/24 14:02:39 christos Exp $"); | | 44 | __RCSID("$NetBSD: walk.c,v 1.38 2024/04/24 14:23:37 christos Exp $"); |
45 | #endif /* !__lint */ | | 45 | #endif /* !__lint */ |
46 | | | 46 | |
47 | #include <sys/param.h> | | 47 | #include <sys/param.h> |
48 | #include <sys/stat.h> | | 48 | #include <sys/stat.h> |
49 | | | 49 | |
50 | #include <assert.h> | | 50 | #include <assert.h> |
51 | #include <errno.h> | | 51 | #include <errno.h> |
52 | #include <fcntl.h> | | 52 | #include <fcntl.h> |
53 | #include <stdio.h> | | 53 | #include <stdio.h> |
54 | #include <dirent.h> | | 54 | #include <dirent.h> |
55 | #include <stdlib.h> | | 55 | #include <stdlib.h> |
56 | #include <string.h> | | 56 | #include <string.h> |
57 | #include <unistd.h> | | 57 | #include <unistd.h> |
| @@ -85,44 +85,46 @@ fsnode_cmp(const void *vleft, const void | | | @@ -85,44 +85,46 @@ fsnode_cmp(const void *vleft, const void |
85 | return 1; | | 85 | return 1; |
86 | return strcmp(lname, rname); | | 86 | return strcmp(lname, rname); |
87 | } | | 87 | } |
88 | | | 88 | |
89 | static fsnode * | | 89 | static fsnode * |
90 | fsnode_sort(fsnode *first, const char *root, const char *dir) | | 90 | fsnode_sort(fsnode *first, const char *root, const char *dir) |
91 | { | | 91 | { |
92 | fsnode **list, **listptr; | | 92 | fsnode **list, **listptr; |
93 | size_t num = 0; | | 93 | size_t num = 0; |
94 | | | 94 | |
95 | for (fsnode *tmp = first; tmp; tmp = tmp->next, num++) { | | 95 | for (fsnode *tmp = first; tmp; tmp = tmp->next, num++) { |
96 | num++; | | 96 | num++; |
97 | if (debug & DEBUG_DUMP_FSNODES_VERBOSE) | | 97 | if (debug & DEBUG_DUMP_FSNODES_VERBOSE) |
98 | printf ("pre sort: %s %s %s\n", root, dir, tmp->name); | | 98 | printf("%s: pre sort: %s %s %s\n", |
| | | 99 | __func__, root, dir, tmp->name); |
99 | } | | 100 | } |
100 | | | 101 | |
101 | list = listptr = ecalloc(num, sizeof(*list)); | | 102 | list = listptr = ecalloc(num, sizeof(*list)); |
102 | for (fsnode *tmp = first; tmp; tmp = tmp->next) | | 103 | for (fsnode *tmp = first; tmp; tmp = tmp->next) |
103 | *listptr++ = tmp; | | 104 | *listptr++ = tmp; |
104 | | | 105 | |
105 | qsort (list, num, sizeof(*list), fsnode_cmp); | | 106 | qsort (list, num, sizeof(*list), fsnode_cmp); |
106 | | | 107 | |
107 | for (size_t i = 0; i < num - 1; ++i) | | 108 | for (size_t i = 0; i < num - 1; ++i) |
108 | list[i]->next = list[i + 1]; | | 109 | list[i]->next = list[i + 1]; |
109 | list[num - 1]->next = NULL; | | 110 | list[num - 1]->next = NULL; |
110 | first = list[0]; | | 111 | first = list[0]; |
111 | assert(strcmp(first->name, ".") == 0); | | 112 | assert(strcmp(first->name, ".") == 0); |
112 | free(list); | | 113 | free(list); |
113 | if (debug & DEBUG_DUMP_FSNODES_VERBOSE) | | 114 | if (debug & DEBUG_DUMP_FSNODES_VERBOSE) |
114 | for (fsnode *tmp = first; tmp; tmp = tmp->next) | | 115 | for (fsnode *tmp = first; tmp; tmp = tmp->next) |
115 | printf("post sort: %s %s %s\n", root, dir, tmp->name); | | 116 | printf("%s: post sort: %s %s %s\n", |
| | | 117 | __func__, root, dir, tmp->name); |
116 | | | 118 | |
117 | return first; | | 119 | return first; |
118 | } | | 120 | } |
119 | | | 121 | |
120 | /* | | 122 | /* |
121 | * walk_dir -- | | 123 | * walk_dir -- |
122 | * build a tree of fsnodes from `root' and `dir', with a parent | | 124 | * build a tree of fsnodes from `root' and `dir', with a parent |
123 | * fsnode of `parent' (which may be NULL for the root of the tree). | | 125 | * fsnode of `parent' (which may be NULL for the root of the tree). |
124 | * append the tree to a fsnode of `join' if it is not NULL. | | 126 | * append the tree to a fsnode of `join' if it is not NULL. |
125 | * each "level" is a directory, with the "." entry guaranteed to be | | 127 | * each "level" is a directory, with the "." entry guaranteed to be |
126 | * at the start of the list, and without ".." entries. | | 128 | * at the start of the list, and without ".." entries. |
127 | */ | | 129 | */ |
128 | fsnode * | | 130 | fsnode * |
| @@ -134,27 +136,27 @@ walk_dir(const char *root, const char *d | | | @@ -134,27 +136,27 @@ walk_dir(const char *root, const char *d |
134 | struct dirent *dent; | | 136 | struct dirent *dent; |
135 | char path[MAXPATHLEN + 1]; | | 137 | char path[MAXPATHLEN + 1]; |
136 | struct stat stbuf; | | 138 | struct stat stbuf; |
137 | char *name, *rp; | | 139 | char *name, *rp; |
138 | int dot, len; | | 140 | int dot, len; |
139 | | | 141 | |
140 | assert(root != NULL); | | 142 | assert(root != NULL); |
141 | assert(dir != NULL); | | 143 | assert(dir != NULL); |
142 | | | 144 | |
143 | len = snprintf(path, sizeof(path), "%s/%s", root, dir); | | 145 | len = snprintf(path, sizeof(path), "%s/%s", root, dir); |
144 | if ((size_t)len >= sizeof(path)) | | 146 | if ((size_t)len >= sizeof(path)) |
145 | errx(EXIT_FAILURE, "Pathname too long."); | | 147 | errx(EXIT_FAILURE, "Pathname too long."); |
146 | if (debug & DEBUG_WALK_DIR) | | 148 | if (debug & DEBUG_WALK_DIR) |
147 | printf("walk_dir: %s %p\n", path, parent); | | 149 | printf("%s: %s %p\n", __func__, path, parent); |
148 | if ((dirp = opendir(path)) == NULL) | | 150 | if ((dirp = opendir(path)) == NULL) |
149 | err(EXIT_FAILURE, "Can't opendir `%s'", path); | | 151 | err(EXIT_FAILURE, "Can't opendir `%s'", path); |
150 | rp = path + strlen(root) + 1; | | 152 | rp = path + strlen(root) + 1; |
151 | if (join != NULL) { | | 153 | if (join != NULL) { |
152 | first = cur = join; | | 154 | first = cur = join; |
153 | while (cur->next != NULL) | | 155 | while (cur->next != NULL) |
154 | cur = cur->next; | | 156 | cur = cur->next; |
155 | prev = last = cur; | | 157 | prev = last = cur; |
156 | } else | | 158 | } else |
157 | last = first = prev = NULL; | | 159 | last = first = prev = NULL; |
158 | while ((dent = readdir(dirp)) != NULL) { | | 160 | while ((dent = readdir(dirp)) != NULL) { |
159 | name = dent->d_name; | | 161 | name = dent->d_name; |
160 | dot = 0; | | 162 | dot = 0; |
| @@ -163,86 +165,88 @@ walk_dir(const char *root, const char *d | | | @@ -163,86 +165,88 @@ walk_dir(const char *root, const char *d |
163 | case '\0': /* "." */ | | 165 | case '\0': /* "." */ |
164 | if (join != NULL) | | 166 | if (join != NULL) |
165 | continue; | | 167 | continue; |
166 | dot = 1; | | 168 | dot = 1; |
167 | break; | | 169 | break; |
168 | case '.': /* ".." */ | | 170 | case '.': /* ".." */ |
169 | if (name[2] == '\0') | | 171 | if (name[2] == '\0') |
170 | continue; | | 172 | continue; |
171 | /* FALLTHROUGH */ | | 173 | /* FALLTHROUGH */ |
172 | default: | | 174 | default: |
173 | dot = 0; | | 175 | dot = 0; |
174 | } | | 176 | } |
175 | if (debug & DEBUG_WALK_DIR_NODE) | | 177 | if (debug & DEBUG_WALK_DIR_NODE) |
176 | printf("scanning %s/%s/%s\n", root, dir, name); | | 178 | printf("%s: scanning %s/%s/%s\n", |
| | | 179 | __func__, root, dir, name); |
177 | if (snprintf(path + len, sizeof(path) - len, "/%s", name) >= | | 180 | if (snprintf(path + len, sizeof(path) - len, "/%s", name) >= |
178 | (int)sizeof(path) - len) | | 181 | (int)sizeof(path) - len) |
179 | errx(EXIT_FAILURE, "Pathname too long."); | | 182 | errx(EXIT_FAILURE, "Pathname too long."); |
180 | if (follow) { | | 183 | if (follow) { |
181 | if (stat(path, &stbuf) == -1) | | 184 | if (stat(path, &stbuf) == -1) |
182 | err(EXIT_FAILURE, "Can't stat `%s'", path); | | 185 | err(EXIT_FAILURE, "Can't stat `%s'", path); |
183 | } else { | | 186 | } else { |
184 | if (lstat(path, &stbuf) == -1) | | 187 | if (lstat(path, &stbuf) == -1) |
185 | err(EXIT_FAILURE, "Can't lstat `%s'", path); | | 188 | err(EXIT_FAILURE, "Can't lstat `%s'", path); |
186 | /* | | 189 | /* |
187 | * Symlink permission bits vary between filesystems/OSs | | 190 | * Symlink permission bits vary between filesystems/OSs |
188 | * (ie. 0755 on FFS/NetBSD, 0777 for ext[234]/Linux), | | 191 | * (ie. 0755 on FFS/NetBSD, 0777 for ext[234]/Linux), |
189 | * force them to 0755. | | 192 | * force them to 0755. |
190 | */ | | 193 | */ |
191 | if (S_ISLNK(stbuf.st_mode)) { | | 194 | if (S_ISLNK(stbuf.st_mode)) { |
192 | stbuf.st_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO); | | 195 | stbuf.st_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO); |
193 | stbuf.st_mode |= S_IRWXU | | 196 | stbuf.st_mode |= S_IRWXU |
194 | | S_IRGRP | S_IXGRP | | 197 | | S_IRGRP | S_IXGRP |
195 | | S_IROTH | S_IXOTH; | | 198 | | S_IROTH | S_IXOTH; |
196 | } | | 199 | } |
197 | } | | 200 | } |
198 | #ifdef S_ISSOCK | | 201 | #ifdef S_ISSOCK |
199 | if (S_ISSOCK(stbuf.st_mode & S_IFMT)) { | | 202 | if (S_ISSOCK(stbuf.st_mode & S_IFMT)) { |
200 | if (debug & DEBUG_WALK_DIR_NODE) | | 203 | if (debug & DEBUG_WALK_DIR_NODE) |
201 | printf(" skipping socket %s\n", path); | | 204 | printf("%s: skipping socket %s\n", __func__, path); |
202 | continue; | | 205 | continue; |
203 | } | | 206 | } |
204 | #endif | | 207 | #endif |
205 | | | 208 | |
206 | if (join != NULL) { | | 209 | if (join != NULL) { |
207 | cur = join->next; | | 210 | cur = join->next; |
208 | for (;;) { | | 211 | for (;;) { |
209 | if (cur == NULL || strcmp(cur->name, name) == 0) | | 212 | if (cur == NULL || strcmp(cur->name, name) == 0) |
210 | break; | | 213 | break; |
211 | if (cur == last) { | | 214 | if (cur == last) { |
212 | cur = NULL; | | 215 | cur = NULL; |
213 | break; | | 216 | break; |
214 | } | | 217 | } |
215 | cur = cur->next; | | 218 | cur = cur->next; |
216 | } | | 219 | } |
217 | if (cur != NULL) { | | 220 | if (cur != NULL) { |
218 | if (S_ISDIR(cur->type) && | | 221 | if (S_ISDIR(cur->type) && |
219 | S_ISDIR(stbuf.st_mode)) { | | 222 | S_ISDIR(stbuf.st_mode)) { |
220 | if (debug & DEBUG_WALK_DIR_NODE) | | 223 | if (debug & DEBUG_WALK_DIR_NODE) |
221 | printf("merging %s with %p\n", | | 224 | printf("%s: merging %s with %p\n", |
222 | path, cur->child); | | 225 | __func__, path, cur->child); |
223 | cur->child = walk_dir(root, rp, cur, | | 226 | cur->child = walk_dir(root, rp, cur, |
224 | cur->child, replace, follow); | | 227 | cur->child, replace, follow); |
225 | continue; | | 228 | continue; |
226 | } | | 229 | } |
227 | if (!replace) | | 230 | if (!replace) |
228 | errx(EXIT_FAILURE, | | 231 | errx(EXIT_FAILURE, |
229 | "Can't merge %s `%s' with " | | 232 | "Can't merge %s `%s' with " |
230 | "existing %s", | | 233 | "existing %s", |
231 | inode_type(stbuf.st_mode), path, | | 234 | inode_type(stbuf.st_mode), path, |
232 | inode_type(cur->type)); | | 235 | inode_type(cur->type)); |
233 | else { | | 236 | else { |
234 | if (debug & DEBUG_WALK_DIR_NODE) | | 237 | if (debug & DEBUG_WALK_DIR_NODE) |
235 | printf("replacing %s %s\n", | | 238 | printf("%s: replacing %s %s\n", |
| | | 239 | __func__, |
236 | inode_type(stbuf.st_mode), | | 240 | inode_type(stbuf.st_mode), |
237 | path); | | 241 | path); |
238 | if (cur == join->next) | | 242 | if (cur == join->next) |
239 | join->next = cur->next; | | 243 | join->next = cur->next; |
240 | else { | | 244 | else { |
241 | fsnode *p; | | 245 | fsnode *p; |
242 | for (p = join->next; | | 246 | for (p = join->next; |
243 | p->next != cur; p = p->next) | | 247 | p->next != cur; p = p->next) |
244 | continue; | | 248 | continue; |
245 | p->next = cur->next; | | 249 | p->next = cur->next; |
246 | } | | 250 | } |
247 | free(cur); | | 251 | free(cur); |
248 | } | | 252 | } |
| @@ -270,27 +274,28 @@ walk_dir(const char *root, const char *d | | | @@ -270,27 +274,28 @@ walk_dir(const char *root, const char *d |
270 | replace, follow); | | 274 | replace, follow); |
271 | continue; | | 275 | continue; |
272 | } | | 276 | } |
273 | } | | 277 | } |
274 | if (stbuf.st_nlink > 1) { | | 278 | if (stbuf.st_nlink > 1) { |
275 | fsinode *curino; | | 279 | fsinode *curino; |
276 | | | 280 | |
277 | curino = link_check(cur->inode); | | 281 | curino = link_check(cur->inode); |
278 | if (curino != NULL) { | | 282 | if (curino != NULL) { |
279 | free(cur->inode); | | 283 | free(cur->inode); |
280 | cur->inode = curino; | | 284 | cur->inode = curino; |
281 | cur->inode->nlink++; | | 285 | cur->inode->nlink++; |
282 | if (debug & DEBUG_WALK_DIR_LINKCHECK) | | 286 | if (debug & DEBUG_WALK_DIR_LINKCHECK) |
283 | printf("link_check: found [%ju, %ju]\n", | | 287 | printf("%s: link check found [%ju, %ju]\n", |
| | | 288 | __func__, |
284 | (uintmax_t)curino->st.st_dev, | | 289 | (uintmax_t)curino->st.st_dev, |
285 | (uintmax_t)curino->st.st_ino); | | 290 | (uintmax_t)curino->st.st_ino); |
286 | } | | 291 | } |
287 | } | | 292 | } |
288 | if (S_ISLNK(cur->type)) { | | 293 | if (S_ISLNK(cur->type)) { |
289 | char slink[PATH_MAX+1]; | | 294 | char slink[PATH_MAX+1]; |
290 | ssize_t llen; | | 295 | ssize_t llen; |
291 | | | 296 | |
292 | llen = readlink(path, slink, sizeof(slink) - 1); | | 297 | llen = readlink(path, slink, sizeof(slink) - 1); |
293 | if (llen == -1) | | 298 | if (llen == -1) |
294 | err(EXIT_FAILURE, "Readlink `%s'", path); | | 299 | err(EXIT_FAILURE, "Readlink `%s'", path); |
295 | slink[llen] = '\0'; | | 300 | slink[llen] = '\0'; |
296 | cur->symlink = estrdup(slink); | | 301 | cur->symlink = estrdup(slink); |
| @@ -393,27 +398,27 @@ free_fsnodes(fsnode *node) | | | @@ -393,27 +398,27 @@ free_fsnodes(fsnode *node) |
393 | * entries will be added. | | 398 | * entries will be added. |
394 | */ | | 399 | */ |
395 | void | | 400 | void |
396 | apply_specfile(const char *specfile, const char *dir, fsnode *parent, int speconly) | | 401 | apply_specfile(const char *specfile, const char *dir, fsnode *parent, int speconly) |
397 | { | | 402 | { |
398 | struct timeval start; | | 403 | struct timeval start; |
399 | FILE *fp; | | 404 | FILE *fp; |
400 | NODE *root; | | 405 | NODE *root; |
401 | | | 406 | |
402 | assert(specfile != NULL); | | 407 | assert(specfile != NULL); |
403 | assert(parent != NULL); | | 408 | assert(parent != NULL); |
404 | | | 409 | |
405 | if (debug & DEBUG_APPLY_SPECFILE) | | 410 | if (debug & DEBUG_APPLY_SPECFILE) |
406 | printf("apply_specfile: %s, %s %p\n", specfile, dir, parent); | | 411 | printf("%s: %s, %s %p\n", __func__, specfile, dir, parent); |
407 | | | 412 | |
408 | /* read in the specfile */ | | 413 | /* read in the specfile */ |
409 | if ((fp = fopen(specfile, "r")) == NULL) | | 414 | if ((fp = fopen(specfile, "r")) == NULL) |
410 | err(EXIT_FAILURE, "Can't open `%s'", specfile); | | 415 | err(EXIT_FAILURE, "Can't open `%s'", specfile); |
411 | TIMER_START(start); | | 416 | TIMER_START(start); |
412 | root = spec(fp); | | 417 | root = spec(fp); |
413 | TIMER_RESULTS(start, "spec"); | | 418 | TIMER_RESULTS(start, "spec"); |
414 | if (fclose(fp) == EOF) | | 419 | if (fclose(fp) == EOF) |
415 | err(EXIT_FAILURE, "Can't close `%s'", specfile); | | 420 | err(EXIT_FAILURE, "Can't close `%s'", specfile); |
416 | | | 421 | |
417 | /* perform some sanity checks */ | | 422 | /* perform some sanity checks */ |
418 | if (root == NULL) | | 423 | if (root == NULL) |
419 | errx(EXIT_FAILURE, | | 424 | errx(EXIT_FAILURE, |
| @@ -428,27 +433,27 @@ apply_specfile(const char *specfile, con | | | @@ -428,27 +433,27 @@ apply_specfile(const char *specfile, con |
428 | } | | 433 | } |
429 | | | 434 | |
430 | static void | | 435 | static void |
431 | apply_specdir(const char *dir, NODE *specnode, fsnode *dirnode, int speconly) | | 436 | apply_specdir(const char *dir, NODE *specnode, fsnode *dirnode, int speconly) |
432 | { | | 437 | { |
433 | char path[MAXPATHLEN + 1]; | | 438 | char path[MAXPATHLEN + 1]; |
434 | NODE *curnode; | | 439 | NODE *curnode; |
435 | fsnode *curfsnode; | | 440 | fsnode *curfsnode; |
436 | | | 441 | |
437 | assert(specnode != NULL); | | 442 | assert(specnode != NULL); |
438 | assert(dirnode != NULL); | | 443 | assert(dirnode != NULL); |
439 | | | 444 | |
440 | if (debug & DEBUG_APPLY_SPECFILE) | | 445 | if (debug & DEBUG_APPLY_SPECFILE) |
441 | printf("apply_specdir: %s %p %p\n", dir, specnode, dirnode); | | 446 | printf("%s: %s %p %p\n", __func__, dir, specnode, dirnode); |
442 | | | 447 | |
443 | if (specnode->type != F_DIR) | | 448 | if (specnode->type != F_DIR) |
444 | errx(EXIT_FAILURE, "Specfile node `%s/%s' is not a directory", | | 449 | errx(EXIT_FAILURE, "Specfile node `%s/%s' is not a directory", |
445 | dir, specnode->name); | | 450 | dir, specnode->name); |
446 | if (dirnode->type != S_IFDIR) | | 451 | if (dirnode->type != S_IFDIR) |
447 | errx(EXIT_FAILURE, "Directory node `%s/%s' is not a directory", | | 452 | errx(EXIT_FAILURE, "Directory node `%s/%s' is not a directory", |
448 | dir, dirnode->name); | | 453 | dir, dirnode->name); |
449 | | | 454 | |
450 | apply_specentry(dir, specnode, dirnode); | | 455 | apply_specentry(dir, specnode, dirnode); |
451 | | | 456 | |
452 | /* Remove any filesystem nodes not found in specfile */ | | 457 | /* Remove any filesystem nodes not found in specfile */ |
453 | /* XXX inefficient. This is O^2 in each dir and it would | | 458 | /* XXX inefficient. This is O^2 in each dir and it would |
454 | * have been better never to have walked this part of the tree | | 459 | * have been better never to have walked this part of the tree |
| @@ -456,44 +461,45 @@ apply_specdir(const char *dir, NODE *spe | | | @@ -456,44 +461,45 @@ apply_specdir(const char *dir, NODE *spe |
456 | */ | | 461 | */ |
457 | if (speconly) { | | 462 | if (speconly) { |
458 | fsnode *next; | | 463 | fsnode *next; |
459 | assert(dirnode->name[0] == '.' && dirnode->name[1] == '\0'); | | 464 | assert(dirnode->name[0] == '.' && dirnode->name[1] == '\0'); |
460 | for (curfsnode = dirnode->next; curfsnode != NULL; curfsnode = next) { | | 465 | for (curfsnode = dirnode->next; curfsnode != NULL; curfsnode = next) { |
461 | next = curfsnode->next; | | 466 | next = curfsnode->next; |
462 | for (curnode = specnode->child; curnode != NULL; | | 467 | for (curnode = specnode->child; curnode != NULL; |
463 | curnode = curnode->next) { | | 468 | curnode = curnode->next) { |
464 | if (strcmp(curnode->name, curfsnode->name) == 0) | | 469 | if (strcmp(curnode->name, curfsnode->name) == 0) |
465 | break; | | 470 | break; |
466 | } | | 471 | } |
467 | if (curnode == NULL) { | | 472 | if (curnode == NULL) { |
468 | if (debug & DEBUG_APPLY_SPECONLY) { | | 473 | if (debug & DEBUG_APPLY_SPECONLY) { |
469 | printf("apply_specdir: trimming %s/%s %p\n", dir, curfsnode->name, curfsnode); | | 474 | printf("%s: trimming %s/%s %p\n", |
| | | 475 | __func__, dir, curfsnode->name, |
| | | 476 | curfsnode); |
470 | } | | 477 | } |
471 | free_fsnodes(curfsnode); | | 478 | free_fsnodes(curfsnode); |
472 | } | | 479 | } |
473 | } | | 480 | } |
474 | } | | 481 | } |
475 | | | 482 | |
476 | /* now walk specnode->child matching up with dirnode */ | | 483 | /* now walk specnode->child matching up with dirnode */ |
477 | for (curnode = specnode->child; curnode != NULL; | | 484 | for (curnode = specnode->child; curnode != NULL; |
478 | curnode = curnode->next) { | | 485 | curnode = curnode->next) { |
479 | if (debug & DEBUG_APPLY_SPECENTRY) | | 486 | if (debug & DEBUG_APPLY_SPECENTRY) |
480 | printf("apply_specdir: spec %s\n", | | 487 | printf("%s: spec %s\n", __func__, curnode->name); |
481 | curnode->name); | | | |
482 | for (curfsnode = dirnode->next; curfsnode != NULL; | | 488 | for (curfsnode = dirnode->next; curfsnode != NULL; |
483 | curfsnode = curfsnode->next) { | | 489 | curfsnode = curfsnode->next) { |
484 | #if 0 /* too verbose for now */ | | 490 | #if 0 /* too verbose for now */ |
485 | if (debug & DEBUG_APPLY_SPECENTRY) | | 491 | if (debug & DEBUG_APPLY_SPECENTRY) |
486 | printf("apply_specdir: dirent %s\n", | | 492 | printf("%s: dirent %s\n", __func__, |
487 | curfsnode->name); | | 493 | curfsnode->name); |
488 | #endif | | 494 | #endif |
489 | if (strcmp(curnode->name, curfsnode->name) == 0) | | 495 | if (strcmp(curnode->name, curfsnode->name) == 0) |
490 | break; | | 496 | break; |
491 | } | | 497 | } |
492 | if ((size_t)snprintf(path, sizeof(path), "%s/%s", | | 498 | if ((size_t)snprintf(path, sizeof(path), "%s/%s", |
493 | dir, curnode->name) >= sizeof(path)) | | 499 | dir, curnode->name) >= sizeof(path)) |
494 | errx(EXIT_FAILURE, "Pathname too long."); | | 500 | errx(EXIT_FAILURE, "Pathname too long."); |
495 | if (curfsnode == NULL) { /* need new entry */ | | 501 | if (curfsnode == NULL) { /* need new entry */ |
496 | struct stat stbuf; | | 502 | struct stat stbuf; |
497 | | | 503 | |
498 | /* | | 504 | /* |
499 | * don't add optional spec entries | | 505 | * don't add optional spec entries |
| @@ -511,28 +517,27 @@ apply_specdir(const char *dir, NODE *spe | | | @@ -511,28 +517,27 @@ apply_specdir(const char *dir, NODE *spe |
511 | NODETEST(curnode->flags & F_TYPE, "type"); | | 517 | NODETEST(curnode->flags & F_TYPE, "type"); |
512 | NODETEST(curnode->flags & F_MODE, "mode"); | | 518 | NODETEST(curnode->flags & F_MODE, "mode"); |
513 | /* XXX: require F_TIME ? */ | | 519 | /* XXX: require F_TIME ? */ |
514 | NODETEST(curnode->flags & F_GID || | | 520 | NODETEST(curnode->flags & F_GID || |
515 | curnode->flags & F_GNAME, "group"); | | 521 | curnode->flags & F_GNAME, "group"); |
516 | NODETEST(curnode->flags & F_UID || | | 522 | NODETEST(curnode->flags & F_UID || |
517 | curnode->flags & F_UNAME, "user"); | | 523 | curnode->flags & F_UNAME, "user"); |
518 | if (curnode->type == F_BLOCK || curnode->type == F_CHAR) | | 524 | if (curnode->type == F_BLOCK || curnode->type == F_CHAR) |
519 | NODETEST(curnode->flags & F_DEV, | | 525 | NODETEST(curnode->flags & F_DEV, |
520 | "device number"); | | 526 | "device number"); |
521 | #undef NODETEST | | 527 | #undef NODETEST |
522 | | | 528 | |
523 | if (debug & DEBUG_APPLY_SPECFILE) | | 529 | if (debug & DEBUG_APPLY_SPECFILE) |
524 | printf("apply_specdir: adding %s\n", | | 530 | printf("%s: adding %s\n", __func__, curnode->name); |
525 | curnode->name); | | | |
526 | /* build minimal fsnode */ | | 531 | /* build minimal fsnode */ |
527 | memset(&stbuf, 0, sizeof(stbuf)); | | 532 | memset(&stbuf, 0, sizeof(stbuf)); |
528 | stbuf.st_mode = nodetoino(curnode->type); | | 533 | stbuf.st_mode = nodetoino(curnode->type); |
529 | stbuf.st_nlink = 1; | | 534 | stbuf.st_nlink = 1; |
530 | stbuf.st_mtime = stbuf.st_atime = | | 535 | stbuf.st_mtime = stbuf.st_atime = |
531 | stbuf.st_ctime = start_time.tv_sec; | | 536 | stbuf.st_ctime = start_time.tv_sec; |
532 | #if HAVE_STRUCT_STAT_ST_MTIMENSEC | | 537 | #if HAVE_STRUCT_STAT_ST_MTIMENSEC |
533 | stbuf.st_mtimensec = stbuf.st_atimensec = | | 538 | stbuf.st_mtimensec = stbuf.st_atimensec = |
534 | stbuf.st_ctimensec = start_time.tv_nsec; | | 539 | stbuf.st_ctimensec = start_time.tv_nsec; |
535 | #endif | | 540 | #endif |
536 | curfsnode = create_fsnode(".", ".", curnode->name, | | 541 | curfsnode = create_fsnode(".", ".", curnode->name, |
537 | &stbuf); | | 542 | &stbuf); |
538 | curfsnode->parent = dirnode->parent; | | 543 | curfsnode->parent = dirnode->parent; |
| @@ -567,27 +572,27 @@ static void | | | @@ -567,27 +572,27 @@ static void |
567 | apply_specentry(const char *dir, NODE *specnode, fsnode *dirnode) | | 572 | apply_specentry(const char *dir, NODE *specnode, fsnode *dirnode) |
568 | { | | 573 | { |
569 | | | 574 | |
570 | assert(specnode != NULL); | | 575 | assert(specnode != NULL); |
571 | assert(dirnode != NULL); | | 576 | assert(dirnode != NULL); |
572 | | | 577 | |
573 | if (nodetoino(specnode->type) != dirnode->type) | | 578 | if (nodetoino(specnode->type) != dirnode->type) |
574 | errx(EXIT_FAILURE, | | 579 | errx(EXIT_FAILURE, |
575 | "`%s/%s' type mismatch: specfile %s, tree %s", | | 580 | "`%s/%s' type mismatch: specfile %s, tree %s", |
576 | dir, specnode->name, inode_type(nodetoino(specnode->type)), | | 581 | dir, specnode->name, inode_type(nodetoino(specnode->type)), |
577 | inode_type(dirnode->type)); | | 582 | inode_type(dirnode->type)); |
578 | | | 583 | |
579 | if (debug & DEBUG_APPLY_SPECENTRY) | | 584 | if (debug & DEBUG_APPLY_SPECENTRY) |
580 | printf("apply_specentry: %s/%s\n", dir, dirnode->name); | | 585 | printf("%s: %s/%s\n", dir, __func__, dirnode->name); |
581 | | | 586 | |
582 | #define ASEPRINT(t, b, o, n) \ | | 587 | #define ASEPRINT(t, b, o, n) \ |
583 | if (debug & DEBUG_APPLY_SPECENTRY) \ | | 588 | if (debug & DEBUG_APPLY_SPECENTRY) \ |
584 | printf("\t\t\tchanging %s from " b " to " b "\n", \ | | 589 | printf("\t\t\tchanging %s from " b " to " b "\n", \ |
585 | t, o, n) | | 590 | t, o, n) |
586 | | | 591 | |
587 | if (specnode->flags & (F_GID | F_GNAME)) { | | 592 | if (specnode->flags & (F_GID | F_GNAME)) { |
588 | ASEPRINT("gid", "%d", | | 593 | ASEPRINT("gid", "%d", |
589 | dirnode->inode->st.st_gid, specnode->st_gid); | | 594 | dirnode->inode->st.st_gid, specnode->st_gid); |
590 | dirnode->inode->st.st_gid = specnode->st_gid; | | 595 | dirnode->inode->st.st_gid = specnode->st_gid; |
591 | } | | 596 | } |
592 | if (specnode->flags & F_MODE) { | | 597 | if (specnode->flags & F_MODE) { |
593 | ASEPRINT("mode", "%#o", | | 598 | ASEPRINT("mode", "%#o", |
| @@ -647,52 +652,52 @@ apply_specentry(const char *dir, NODE *s | | | @@ -647,52 +652,52 @@ apply_specentry(const char *dir, NODE *s |
647 | } | | 652 | } |
648 | | | 653 | |
649 | | | 654 | |
650 | /* | | 655 | /* |
651 | * dump_fsnodes -- | | 656 | * dump_fsnodes -- |
652 | * dump the fsnodes from `cur' | | 657 | * dump the fsnodes from `cur' |
653 | */ | | 658 | */ |
654 | void | | 659 | void |
655 | dump_fsnodes(fsnode *root) | | 660 | dump_fsnodes(fsnode *root) |
656 | { | | 661 | { |
657 | fsnode *cur; | | 662 | fsnode *cur; |
658 | char path[MAXPATHLEN + 1]; | | 663 | char path[MAXPATHLEN + 1]; |
659 | | | 664 | |
660 | printf("dump_fsnodes: %s %p\n", root->path, root); | | 665 | printf("%s: %s %p\n", __func__, root->path, root); |
661 | for (cur = root; cur != NULL; cur = cur->next) { | | 666 | for (cur = root; cur != NULL; cur = cur->next) { |
662 | if (snprintf(path, sizeof(path), "%s/%s", cur->path, | | 667 | if (snprintf(path, sizeof(path), "%s/%s", cur->path, |
663 | cur->name) >= (int)sizeof(path)) | | 668 | cur->name) >= (int)sizeof(path)) |
664 | errx(EXIT_FAILURE, "Pathname too long."); | | 669 | errx(EXIT_FAILURE, "Pathname too long."); |
665 | | | 670 | |
666 | if (debug & DEBUG_DUMP_FSNODES_VERBOSE) | | 671 | if (debug & DEBUG_DUMP_FSNODES_VERBOSE) |
667 | printf("cur=%8p parent=%8p first=%8p ", | | 672 | printf("%s: cur=%8p parent=%8p first=%8p ", __func__, |
668 | cur, cur->parent, cur->first); | | 673 | cur, cur->parent, cur->first); |
669 | printf("%7s: %s", inode_type(cur->type), path); | | 674 | printf("%7s: %s", inode_type(cur->type), path); |
670 | if (S_ISLNK(cur->type)) { | | 675 | if (S_ISLNK(cur->type)) { |
671 | assert(cur->symlink != NULL); | | 676 | assert(cur->symlink != NULL); |
672 | printf(" -> %s", cur->symlink); | | 677 | printf(" -> %s", cur->symlink); |
673 | } else { | | 678 | } else { |
674 | assert (cur->symlink == NULL); | | 679 | assert (cur->symlink == NULL); |
675 | } | | 680 | } |
676 | if (cur->inode->nlink > 1) | | 681 | if (cur->inode->nlink > 1) |
677 | printf(", nlinks=%d", cur->inode->nlink); | | 682 | printf(", nlinks=%d", cur->inode->nlink); |
678 | putchar('\n'); | | 683 | putchar('\n'); |
679 | | | 684 | |
680 | if (cur->child) { | | 685 | if (cur->child) { |
681 | assert (cur->type == S_IFDIR); | | 686 | assert (cur->type == S_IFDIR); |
682 | dump_fsnodes(cur->child); | | 687 | dump_fsnodes(cur->child); |
683 | } | | 688 | } |
684 | } | | 689 | } |
685 | printf("dump_fsnodes: finished %s/%s\n", root->path, root->name); | | 690 | printf("%s: finished %s/%s\n", __func__, root->path, root->name); |
686 | } | | 691 | } |
687 | | | 692 | |
688 | | | 693 | |
689 | /* | | 694 | /* |
690 | * inode_type -- | | 695 | * inode_type -- |
691 | * for a given inode type `mode', return a descriptive string. | | 696 | * for a given inode type `mode', return a descriptive string. |
692 | * for most cases, uses inotype() from mtree/misc.c | | 697 | * for most cases, uses inotype() from mtree/misc.c |
693 | */ | | 698 | */ |
694 | const char * | | 699 | const char * |
695 | inode_type(mode_t mode) | | 700 | inode_type(mode_t mode) |
696 | { | | 701 | { |
697 | | | 702 | |
698 | if (S_ISLNK(mode)) | | 703 | if (S_ISLNK(mode)) |