Wed Apr 24 14:02:39 2024 UTC (15d)
make a separate sorting function and KNF (thanks rillig)


(christos)
diff -r1.36 -r1.37 src/usr.sbin/makefs/walk.c

cvs diff -r1.36 -r1.37 src/usr.sbin/makefs/walk.c (expand / switch to unified diff)

--- src/usr.sbin/makefs/walk.c 2024/04/23 22:18:56 1.36
+++ src/usr.sbin/makefs/walk.c 2024/04/24 14:02:39 1.37
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: walk.c,v 1.36 2024/04/23 22:18:56 christos Exp $ */ 1/* $NetBSD: walk.c,v 1.37 2024/04/24 14:02:39 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.36 2024/04/23 22:18:56 christos Exp $"); 44__RCSID("$NetBSD: walk.c,v 1.37 2024/04/24 14:02:39 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>
@@ -76,54 +76,82 @@ static int @@ -76,54 +76,82 @@ static int
76fsnode_cmp(const void *vleft, const void *vright) 76fsnode_cmp(const void *vleft, const void *vright)
77{ 77{
78 const fsnode * const *left = vleft; 78 const fsnode * const *left = vleft;
79 const fsnode * const *right = vright; 79 const fsnode * const *right = vright;
80 const char *lname = (*left)->name, *rname = (*right)->name; 80 const char *lname = (*left)->name, *rname = (*right)->name;
81 81
82 if (strcmp(lname, ".") == 0) 82 if (strcmp(lname, ".") == 0)
83 return -1; 83 return -1;
84 if (strcmp(rname, ".") == 0) 84 if (strcmp(rname, ".") == 0)
85 return 1; 85 return 1;
86 return strcmp(lname, rname); 86 return strcmp(lname, rname);
87} 87}
88 88
 89static fsnode *
 90fsnode_sort(fsnode *first, const char *root, const char *dir)
 91{
 92 fsnode **list, **listptr;
 93 size_t num = 0;
 94
 95 for (fsnode *tmp = first; tmp; tmp = tmp->next, num++) {
 96 num++;
 97 if (debug & DEBUG_DUMP_FSNODES_VERBOSE)
 98 printf ("pre sort: %s %s %s\n", root, dir, tmp->name);
 99 }
 100
 101 list = listptr = ecalloc(num, sizeof(*list));
 102 for (fsnode *tmp = first; tmp; tmp = tmp->next)
 103 *listptr++ = tmp;
 104
 105 qsort (list, num, sizeof(*list), fsnode_cmp);
 106
 107 for (size_t i = 0; i < num - 1; ++i)
 108 list[i]->next = list[i + 1];
 109 list[num - 1]->next = NULL;
 110 first = list[0];
 111 assert(strcmp(first->name, ".") == 0);
 112 free(list);
 113 if (debug & DEBUG_DUMP_FSNODES_VERBOSE)
 114 for (fsnode *tmp = first; tmp; tmp = tmp->next)
 115 printf("post sort: %s %s %s\n", root, dir, tmp->name);
 116
 117 return first;
 118}
 119
89/* 120/*
90 * walk_dir -- 121 * walk_dir --
91 * build a tree of fsnodes from `root' and `dir', with a parent 122 * build a tree of fsnodes from `root' and `dir', with a parent
92 * fsnode of `parent' (which may be NULL for the root of the tree). 123 * fsnode of `parent' (which may be NULL for the root of the tree).
93 * append the tree to a fsnode of `join' if it is not NULL. 124 * append the tree to a fsnode of `join' if it is not NULL.
94 * each "level" is a directory, with the "." entry guaranteed to be 125 * each "level" is a directory, with the "." entry guaranteed to be
95 * at the start of the list, and without ".." entries. 126 * at the start of the list, and without ".." entries.
96 */ 127 */
97fsnode * 128fsnode *
98walk_dir(const char *root, const char *dir, fsnode *parent, fsnode *join, 129walk_dir(const char *root, const char *dir, fsnode *parent, fsnode *join,
99 int replace, int follow) 130 int replace, int follow)
100{ 131{
101 fsnode *first, *cur, *prev, *last; 132 fsnode *first, *cur, *prev, *last;
102 DIR *dirp; 133 DIR *dirp;
103 struct dirent *dent; 134 struct dirent *dent;
104 char path[MAXPATHLEN + 1]; 135 char path[MAXPATHLEN + 1];
105 struct stat stbuf; 136 struct stat stbuf;
106 char *name, *rp; 137 char *name, *rp;
107 int dot, len; 138 int dot, len;
108 139
109 fsnode **list, **listptr; 
110 int num = 0; 
111 
112 assert(root != NULL); 140 assert(root != NULL);
113 assert(dir != NULL); 141 assert(dir != NULL);
114 142
115 len = snprintf(path, sizeof(path), "%s/%s", root, dir); 143 len = snprintf(path, sizeof(path), "%s/%s", root, dir);
116 if (len >= (int)sizeof(path)) 144 if ((size_t)len >= sizeof(path))
117 errx(EXIT_FAILURE, "Pathname too long."); 145 errx(EXIT_FAILURE, "Pathname too long.");
118 if (debug & DEBUG_WALK_DIR) 146 if (debug & DEBUG_WALK_DIR)
119 printf("walk_dir: %s %p\n", path, parent); 147 printf("walk_dir: %s %p\n", path, parent);
120 if ((dirp = opendir(path)) == NULL) 148 if ((dirp = opendir(path)) == NULL)
121 err(EXIT_FAILURE, "Can't opendir `%s'", path); 149 err(EXIT_FAILURE, "Can't opendir `%s'", path);
122 rp = path + strlen(root) + 1; 150 rp = path + strlen(root) + 1;
123 if (join != NULL) { 151 if (join != NULL) {
124 first = cur = join; 152 first = cur = join;
125 while (cur->next != NULL) 153 while (cur->next != NULL)
126 cur = cur->next; 154 cur = cur->next;
127 prev = last = cur; 155 prev = last = cur;
128 } else 156 } else
129 last = first = prev = NULL; 157 last = first = prev = NULL;
@@ -145,34 +173,36 @@ walk_dir(const char *root, const char *d @@ -145,34 +173,36 @@ walk_dir(const char *root, const char *d
145 dot = 0; 173 dot = 0;
146 } 174 }
147 if (debug & DEBUG_WALK_DIR_NODE) 175 if (debug & DEBUG_WALK_DIR_NODE)
148 printf("scanning %s/%s/%s\n", root, dir, name); 176 printf("scanning %s/%s/%s\n", root, dir, name);
149 if (snprintf(path + len, sizeof(path) - len, "/%s", name) >= 177 if (snprintf(path + len, sizeof(path) - len, "/%s", name) >=
150 (int)sizeof(path) - len) 178 (int)sizeof(path) - len)
151 errx(EXIT_FAILURE, "Pathname too long."); 179 errx(EXIT_FAILURE, "Pathname too long.");
152 if (follow) { 180 if (follow) {
153 if (stat(path, &stbuf) == -1) 181 if (stat(path, &stbuf) == -1)
154 err(EXIT_FAILURE, "Can't stat `%s'", path); 182 err(EXIT_FAILURE, "Can't stat `%s'", path);
155 } else { 183 } else {
156 if (lstat(path, &stbuf) == -1) 184 if (lstat(path, &stbuf) == -1)
157 err(EXIT_FAILURE, "Can't lstat `%s'", path); 185 err(EXIT_FAILURE, "Can't lstat `%s'", path);
158 /* As symlink permission bits vary between filesystems 186 /*
159 (ie. 0755 on FFS/NetBSD, 0777 for ext[234]/Linux), 187 * Symlink permission bits vary between filesystems/OSs
160 force them to 0755. */ 188 * (ie. 0755 on FFS/NetBSD, 0777 for ext[234]/Linux),
 189 * force them to 0755.
 190 */
161 if (S_ISLNK(stbuf.st_mode)) { 191 if (S_ISLNK(stbuf.st_mode)) {
162 stbuf.st_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO); 192 stbuf.st_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO);
163 stbuf.st_mode |= S_IRWXU 193 stbuf.st_mode |= S_IRWXU
164 | S_IRGRP | S_IXGRP 194 | S_IRGRP | S_IXGRP
165 | S_IROTH | S_IXOTH; 195 | S_IROTH | S_IXOTH;
166 } 196 }
167 } 197 }
168#ifdef S_ISSOCK 198#ifdef S_ISSOCK
169 if (S_ISSOCK(stbuf.st_mode & S_IFMT)) { 199 if (S_ISSOCK(stbuf.st_mode & S_IFMT)) {
170 if (debug & DEBUG_WALK_DIR_NODE) 200 if (debug & DEBUG_WALK_DIR_NODE)
171 printf(" skipping socket %s\n", path); 201 printf(" skipping socket %s\n", path);
172 continue; 202 continue;
173 } 203 }
174#endif 204#endif
175 205
176 if (join != NULL) { 206 if (join != NULL) {
177 cur = join->next; 207 cur = join->next;
178 for (;;) { 208 for (;;) {
@@ -263,55 +293,27 @@ walk_dir(const char *root, const char *d @@ -263,55 +293,27 @@ walk_dir(const char *root, const char *d
263 if (llen == -1) 293 if (llen == -1)
264 err(EXIT_FAILURE, "Readlink `%s'", path); 294 err(EXIT_FAILURE, "Readlink `%s'", path);
265 slink[llen] = '\0'; 295 slink[llen] = '\0';
266 cur->symlink = estrdup(slink); 296 cur->symlink = estrdup(slink);
267 } 297 }
268 } 298 }
269 assert(first != NULL); 299 assert(first != NULL);
270 if (join == NULL) 300 if (join == NULL)
271 for (cur = first->next; cur != NULL; cur = cur->next) 301 for (cur = first->next; cur != NULL; cur = cur->next)
272 cur->first = first; 302 cur->first = first;
273 if (closedir(dirp) == -1) 303 if (closedir(dirp) == -1)
274 err(EXIT_FAILURE, "Can't closedir `%s/%s'", root, dir); 304 err(EXIT_FAILURE, "Can't closedir `%s/%s'", root, dir);
275 305
276 /* 306 return fsnode_sort(first, root, dir);
277 * Sort entries. 
278 */ 
279 /* Create a plain list: Count, alloc, add. */ 
280 for (fsnode *tmp = first; tmp; tmp = tmp->next) { 
281 num++; 
282 if (debug & DEBUG_DUMP_FSNODES_VERBOSE) 
283 printf ("pre sort: %s %s %s\n", root, dir, tmp->name); 
284 } 
285 list = listptr = ecalloc (num, sizeof (*list)); 
286 for (fsnode *tmp = first; tmp; tmp = tmp->next) 
287 *listptr++ = tmp; 
288 /* Sort plain list. */ 
289 qsort (list, num, sizeof (*list), &fsnode_cmp); 
290 /* Rewire. */ 
291 for (int i = 0; i < num - 1; ++i) 
292 list[i]->next = list[i+1]; 
293 list[num - 1]->next = NULL; 
294 first = list[0]; 
295 /* Check `first` to be ".". */ 
296 assert (strcmp (first->name, ".") == 0); 
297 /* Free. */ 
298 free (list); 
299 /* Dump sorted state. */ 
300 if (debug & DEBUG_DUMP_FSNODES_VERBOSE) 
301 for (fsnode *tmp = first; tmp; tmp = tmp->next) 
302 printf ("post sort: %s %s %s\n", root, dir, tmp->name); 
303 
304 return first; 
305} 307}
306 308
307static fsnode * 309static fsnode *
308create_fsnode(const char *root, const char *path, const char *name, 310create_fsnode(const char *root, const char *path, const char *name,
309 struct stat *stbuf) 311 struct stat *stbuf)
310{ 312{
311 fsnode *cur; 313 fsnode *cur;
312 314
313 cur = ecalloc(1, sizeof(*cur)); 315 cur = ecalloc(1, sizeof(*cur));
314 cur->path = estrdup(path); 316 cur->path = estrdup(path);
315 cur->name = estrdup(name); 317 cur->name = estrdup(name);
316 cur->inode = ecalloc(1, sizeof(*cur->inode)); 318 cur->inode = ecalloc(1, sizeof(*cur->inode));
317 cur->root = root; 319 cur->root = root;