diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-04-10 17:35:24 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-04-12 20:41:34 +0200 |
commit | 426d2d521ccd44ff8c41d2577fbace6f1726dbd2 (patch) | |
tree | 0ca6bf21fad43d8fad6e8ec1ed85974c01031650 | |
parent | 8059c42315a3ed3726b9b0a4e6293b1cccbaacc0 (diff) |
Copy the dir scan pattern from the Windows implementation
If we look at a sub directory, piece totether the full path and open
that instead. This allows us to move the directory open into the scan
function and get rid of the dirfd trickery. Also pull the recusion
step out into the parent function.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r-- | bin/gensquashfs/src/fstree_from_dir.c | 104 |
1 files changed, 52 insertions, 52 deletions
diff --git a/bin/gensquashfs/src/fstree_from_dir.c b/bin/gensquashfs/src/fstree_from_dir.c index 21c4b78..8923603 100644 --- a/bin/gensquashfs/src/fstree_from_dir.c +++ b/bin/gensquashfs/src/fstree_from_dir.c @@ -220,27 +220,30 @@ static char *read_link(const struct stat *sb, int dir_fd, const char *name) return out; } -static int populate_dir(int dir_fd, fstree_t *fs, tree_node_t *root, - dev_t devstart, scan_node_callback cb, - void *user, unsigned int flags) +static int populate_dir(const char *path, fstree_t *fs, tree_node_t *root, + scan_node_callback cb, void *user, unsigned int flags) { char *extra = NULL; + dev_t devstart = 0; struct dirent *ent; - int ret, childfd; struct stat sb; tree_node_t *n; DIR *dir; + int ret; - dir = fdopendir(dir_fd); + dir = opendir(path); if (dir == NULL) { - perror("fdopendir"); - close(dir_fd); + perror(path); return -1; } - /* XXX: fdopendir can dup and close dir_fd internally - and still be compliant with the spec. */ - dir_fd = dirfd(dir); + if (flags & DIR_SCAN_ONE_FILESYSTEM) { + if (fstat(dirfd(dir), &sb)) { + perror(path); + goto fail; + } + devstart = sb.st_dev; + } for (;;) { errno = 0; @@ -254,7 +257,8 @@ static int populate_dir(int dir_fd, fstree_t *fs, tree_node_t *root, break; } - if (fstatat(dir_fd, ent->d_name, &sb, AT_SYMLINK_NOFOLLOW)) { + if (fstatat(dirfd(dir), ent->d_name, + &sb, AT_SYMLINK_NOFOLLOW)) { perror(ent->d_name); goto fail; } @@ -266,7 +270,7 @@ static int populate_dir(int dir_fd, fstree_t *fs, tree_node_t *root, continue; if (S_ISLNK(sb.st_mode)) { - extra = read_link(&sb, dir_fd, ent->d_name); + extra = read_link(&sb, dirfd(dir), ent->d_name); if (extra == NULL) { perror("readlink"); goto fail; @@ -300,24 +304,8 @@ static int populate_dir(int dir_fd, fstree_t *fs, tree_node_t *root, if (ret < 0) goto fail; - if (ret > 0) { + if (ret > 0) discard_node(root, n); - continue; - } - - if (S_ISDIR(n->mode) && !(flags & DIR_SCAN_NO_RECURSION)) { - childfd = openat(dir_fd, n->name, O_DIRECTORY | - O_RDONLY | O_CLOEXEC); - if (childfd < 0) { - perror(n->name); - goto fail; - } - - if (populate_dir(childfd, fs, n, devstart, - cb, user, flags)) { - goto fail; - } - } } closedir(dir); @@ -333,8 +321,9 @@ int fstree_from_subdir(fstree_t *fs, tree_node_t *root, scan_node_callback cb, void *user, unsigned int flags) { - struct stat sb; - int fd, subfd; + size_t plen, slen; + char *temp = NULL; + tree_node_t *n; if (!S_ISDIR(root->mode)) { fprintf(stderr, @@ -343,35 +332,46 @@ int fstree_from_subdir(fstree_t *fs, tree_node_t *root, return -1; } - fd = open(path, O_DIRECTORY | O_RDONLY | O_CLOEXEC); - if (fd < 0) { - perror(path); - return -1; - } - - if (subdir != NULL) { - subfd = openat(fd, subdir, O_DIRECTORY | O_RDONLY | O_CLOEXEC); + plen = strlen(path); + slen = subdir == NULL ? 0 : strlen(subdir); - if (subfd < 0) { - fprintf(stderr, "%s/%s: %s\n", path, subdir, - strerror(errno)); - close(fd); + if (slen > 0) { + temp = calloc(1, plen + 1 + slen + 1); + if (temp == NULL) { + fprintf(stderr, "%s/%s: allocation failure.\n", + path, subdir); return -1; } - close(fd); - fd = subfd; + memcpy(temp, path, plen); + temp[plen] = '/'; + memcpy(temp + plen + 1, subdir, slen); + temp[plen + 1 + slen] = '\0'; + + path = temp; } - if (fstat(fd, &sb)) { - fprintf(stderr, "%s/%s: %s\n", path, - subdir == NULL ? "" : subdir, - strerror(errno)); - close(fd); - return -1; + if (populate_dir(path, fs, root, cb, user, flags)) + goto fail; + + if (flags & DIR_SCAN_NO_RECURSION) { + free(temp); + return 0; } - return populate_dir(fd, fs, root, sb.st_dev, cb, user, flags); + for (n = root->data.dir.children; n != NULL; n = n->next) { + if (!S_ISDIR(n->mode)) + continue; + + if (fstree_from_subdir(fs, n, path, n->name, cb, user, flags)) + goto fail; + } + + free(temp); + return 0; +fail: + free(temp); + return -1; } #endif |