| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: walk.c,v 1.38 2024/04/24 14:23:37 christos Exp $ */ | | 1 | /* $NetBSD: walk.c,v 1.39 2024/04/24 21:59:39 rillig 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.38 2024/04/24 14:23:37 christos Exp $"); | | 44 | __RCSID("$NetBSD: walk.c,v 1.39 2024/04/24 21:59:39 rillig 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> |
| @@ -83,37 +83,36 @@ fsnode_cmp(const void *vleft, const void | | | @@ -83,37 +83,36 @@ fsnode_cmp(const void *vleft, const void |
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 | |
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++; | | | |
97 | if (debug & DEBUG_DUMP_FSNODES_VERBOSE) | | 96 | if (debug & DEBUG_DUMP_FSNODES_VERBOSE) |
98 | printf("%s: pre sort: %s %s %s\n", | | 97 | printf("%s: pre sort: %s %s %s\n", |
99 | __func__, root, dir, tmp->name); | | 98 | __func__, root, dir, tmp->name); |
100 | } | | 99 | } |
101 | | | 100 | |
102 | list = listptr = ecalloc(num, sizeof(*list)); | | 101 | list = listptr = ecalloc(num, sizeof(*list)); |
103 | for (fsnode *tmp = first; tmp; tmp = tmp->next) | | 102 | for (fsnode *tmp = first; tmp; tmp = tmp->next) |
104 | *listptr++ = tmp; | | 103 | *listptr++ = tmp; |
105 | | | 104 | |
106 | qsort (list, num, sizeof(*list), fsnode_cmp); | | 105 | qsort(list, num, sizeof(*list), fsnode_cmp); |
107 | | | 106 | |
108 | for (size_t i = 0; i < num - 1; ++i) | | 107 | for (size_t i = 0; i < num - 1; ++i) |
109 | list[i]->next = list[i + 1]; | | 108 | list[i]->next = list[i + 1]; |
110 | list[num - 1]->next = NULL; | | 109 | list[num - 1]->next = NULL; |
111 | first = list[0]; | | 110 | first = list[0]; |
112 | assert(strcmp(first->name, ".") == 0); | | 111 | assert(strcmp(first->name, ".") == 0); |
113 | free(list); | | 112 | free(list); |
114 | if (debug & DEBUG_DUMP_FSNODES_VERBOSE) | | 113 | if (debug & DEBUG_DUMP_FSNODES_VERBOSE) |
115 | for (fsnode *tmp = first; tmp; tmp = tmp->next) | | 114 | for (fsnode *tmp = first; tmp; tmp = tmp->next) |
116 | printf("%s: post sort: %s %s %s\n", | | 115 | printf("%s: post sort: %s %s %s\n", |
117 | __func__, root, dir, tmp->name); | | 116 | __func__, root, dir, tmp->name); |
118 | | | 117 | |
119 | return first; | | 118 | return first; |
| @@ -552,27 +551,27 @@ apply_specdir(const char *dir, NODE *spe | | | @@ -552,27 +551,27 @@ apply_specdir(const char *dir, NODE *spe |
552 | curfsnode->child->first = curfsnode->child; | | 551 | curfsnode->child->first = curfsnode->child; |
553 | } | | 552 | } |
554 | if (curfsnode->type == S_IFLNK) { | | 553 | if (curfsnode->type == S_IFLNK) { |
555 | assert(curnode->slink != NULL); | | 554 | assert(curnode->slink != NULL); |
556 | /* for symlinks, copy the target */ | | 555 | /* for symlinks, copy the target */ |
557 | curfsnode->symlink = estrdup(curnode->slink); | | 556 | curfsnode->symlink = estrdup(curnode->slink); |
558 | } | | 557 | } |
559 | } | | 558 | } |
560 | apply_specentry(dir, curnode, curfsnode); | | 559 | apply_specentry(dir, curnode, curfsnode); |
561 | if (curnode->type == F_DIR) { | | 560 | if (curnode->type == F_DIR) { |
562 | if (curfsnode->type != S_IFDIR) | | 561 | if (curfsnode->type != S_IFDIR) |
563 | errx(EXIT_FAILURE, | | 562 | errx(EXIT_FAILURE, |
564 | "`%s' is not a directory", path); | | 563 | "`%s' is not a directory", path); |
565 | assert (curfsnode->child != NULL); | | 564 | assert(curfsnode->child != NULL); |
566 | apply_specdir(path, curnode, curfsnode->child, speconly); | | 565 | apply_specdir(path, curnode, curfsnode->child, speconly); |
567 | } | | 566 | } |
568 | } | | 567 | } |
569 | } | | 568 | } |
570 | | | 569 | |
571 | static void | | 570 | static void |
572 | apply_specentry(const char *dir, NODE *specnode, fsnode *dirnode) | | 571 | apply_specentry(const char *dir, NODE *specnode, fsnode *dirnode) |
573 | { | | 572 | { |
574 | | | 573 | |
575 | assert(specnode != NULL); | | 574 | assert(specnode != NULL); |
576 | assert(dirnode != NULL); | | 575 | assert(dirnode != NULL); |
577 | | | 576 | |
578 | if (nodetoino(specnode->type) != dirnode->type) | | 577 | if (nodetoino(specnode->type) != dirnode->type) |
| @@ -666,34 +665,34 @@ dump_fsnodes(fsnode *root) | | | @@ -666,34 +665,34 @@ dump_fsnodes(fsnode *root) |
666 | for (cur = root; cur != NULL; cur = cur->next) { | | 665 | for (cur = root; cur != NULL; cur = cur->next) { |
667 | if (snprintf(path, sizeof(path), "%s/%s", cur->path, | | 666 | if (snprintf(path, sizeof(path), "%s/%s", cur->path, |
668 | cur->name) >= (int)sizeof(path)) | | 667 | cur->name) >= (int)sizeof(path)) |
669 | errx(EXIT_FAILURE, "Pathname too long."); | | 668 | errx(EXIT_FAILURE, "Pathname too long."); |
670 | | | 669 | |
671 | if (debug & DEBUG_DUMP_FSNODES_VERBOSE) | | 670 | if (debug & DEBUG_DUMP_FSNODES_VERBOSE) |
672 | printf("%s: cur=%8p parent=%8p first=%8p ", __func__, | | 671 | printf("%s: cur=%8p parent=%8p first=%8p ", __func__, |
673 | cur, cur->parent, cur->first); | | 672 | cur, cur->parent, cur->first); |
674 | printf("%7s: %s", inode_type(cur->type), path); | | 673 | printf("%7s: %s", inode_type(cur->type), path); |
675 | if (S_ISLNK(cur->type)) { | | 674 | if (S_ISLNK(cur->type)) { |
676 | assert(cur->symlink != NULL); | | 675 | assert(cur->symlink != NULL); |
677 | printf(" -> %s", cur->symlink); | | 676 | printf(" -> %s", cur->symlink); |
678 | } else { | | 677 | } else { |
679 | assert (cur->symlink == NULL); | | 678 | assert(cur->symlink == NULL); |
680 | } | | 679 | } |
681 | if (cur->inode->nlink > 1) | | 680 | if (cur->inode->nlink > 1) |
682 | printf(", nlinks=%d", cur->inode->nlink); | | 681 | printf(", nlinks=%d", cur->inode->nlink); |
683 | putchar('\n'); | | 682 | putchar('\n'); |
684 | | | 683 | |
685 | if (cur->child) { | | 684 | if (cur->child) { |
686 | assert (cur->type == S_IFDIR); | | 685 | assert(cur->type == S_IFDIR); |
687 | dump_fsnodes(cur->child); | | 686 | dump_fsnodes(cur->child); |
688 | } | | 687 | } |
689 | } | | 688 | } |
690 | printf("%s: finished %s/%s\n", __func__, root->path, root->name); | | 689 | printf("%s: finished %s/%s\n", __func__, root->path, root->name); |
691 | } | | 690 | } |
692 | | | 691 | |
693 | | | 692 | |
694 | /* | | 693 | /* |
695 | * inode_type -- | | 694 | * inode_type -- |
696 | * for a given inode type `mode', return a descriptive string. | | 695 | * for a given inode type `mode', return a descriptive string. |
697 | * for most cases, uses inotype() from mtree/misc.c | | 696 | * for most cases, uses inotype() from mtree/misc.c |
698 | */ | | 697 | */ |
699 | const char * | | 698 | const char * |