diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-04-21 21:11:18 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-04-21 21:11:18 +0200 |
commit | b826045d0427db2c18eedda7e02f21acfc2ce62e (patch) | |
tree | 94af915f779ecb5c660159349f6bb4b2d423043b | |
parent | 6c7d1c6e6cb3187218fa180fc87919255928b999 (diff) |
libutil: unix: simplify/unify directory iterator error handling
Instead of printing out error messages, return an errro ID and match
the behavior with the Windows implementation. Also, don't check first
if the struct stat says it is a link, the readlinkat() system call
will fail if it isn't. Avoid confusing the deputy.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r-- | bin/gensquashfs/src/fstree_from_dir.c | 8 | ||||
-rw-r--r-- | lib/util/src/unix_dir_iterator.c | 53 |
2 files changed, 25 insertions, 36 deletions
diff --git a/bin/gensquashfs/src/fstree_from_dir.c b/bin/gensquashfs/src/fstree_from_dir.c index 85381f9..6200ea3 100644 --- a/bin/gensquashfs/src/fstree_from_dir.c +++ b/bin/gensquashfs/src/fstree_from_dir.c @@ -80,8 +80,10 @@ static int scan_dir(fstree_t *fs, tree_node_t *root, dir_iterator_t *dir, int ret = dir->next(dir, &ent); if (ret > 0) break; - if (ret < 0) + if (ret < 0) { + sqfs_perror("readdir", NULL, ret); return -1; + } if (should_skip(dir, ent, flags)) { free(ent); @@ -89,8 +91,10 @@ static int scan_dir(fstree_t *fs, tree_node_t *root, dir_iterator_t *dir, } if (S_ISLNK(ent->mode)) { - if (dir->read_link(dir, &extra)) { + ret = dir->read_link(dir, &extra); + if (ret) { free(ent); + sqfs_perror("readlink", ent->name, ret); return -1; } } diff --git a/lib/util/src/unix_dir_iterator.c b/lib/util/src/unix_dir_iterator.c index 3f23311..87cf516 100644 --- a/lib/util/src/unix_dir_iterator.c +++ b/lib/util/src/unix_dir_iterator.c @@ -35,54 +35,41 @@ static void dir_destroy(sqfs_object_t *obj) static int dir_read_link(dir_iterator_t *base, char **out) { unix_dir_iterator_t *it = (unix_dir_iterator_t *)base; + ssize_t ret; size_t size; char *str; *out = NULL; - if (it->state != 0 || it->ent == NULL) { - fputs("[BUG] no entry loaded, cannot readlink\n", stderr); - return SQFS_ERROR_INTERNAL; - } + if (it->state < 0) + return it->state; - if (!S_ISLNK(it->sb.st_mode)) { - fprintf(stderr, "[BUG] %s is not a symlink, cannot readlink\n", - it->ent->d_name); - it->state = SQFS_ERROR_INTERNAL; - return SQFS_ERROR_INTERNAL; - } + if (it->state > 0 || it->ent == NULL) + return SQFS_ERROR_NO_ENTRY; if ((sizeof(it->sb.st_size) > sizeof(size_t)) && it->sb.st_size > SIZE_MAX) { - goto fail_ov; + return SQFS_ERROR_ALLOC; } if (SZ_ADD_OV((size_t)it->sb.st_size, 1, &size)) - goto fail_ov; + return SQFS_ERROR_ALLOC; str = calloc(1, size); - if (str == NULL) { - perror(it->ent->d_name); - it->state = SQFS_ERROR_ALLOC; - return it->state; - } + if (str == NULL) + return SQFS_ERROR_ALLOC; - if (readlinkat(dirfd(it->dir), it->ent->d_name, - str, (size_t)it->sb.st_size) < 0) { - fprintf(stderr, "%s: readlink: %s\n", it->ent->d_name, - strerror(errno)); + ret = readlinkat(dirfd(it->dir), it->ent->d_name, + str, (size_t)it->sb.st_size); + if (ret < 0) { free(str); - it->state = SQFS_ERROR_INTERNAL; - return it->state; + return SQFS_ERROR_IO; } - str[it->sb.st_size] = '\0'; + str[ret] = '\0'; *out = str; - return it->state; -fail_ov: - fprintf(stderr, "%s: link target too long\n", it->ent->d_name); - return SQFS_ERROR_OVERFLOW; + return 0; } static int dir_next(dir_iterator_t *base, dir_entry_t **out) @@ -100,8 +87,7 @@ static int dir_next(dir_iterator_t *base, dir_entry_t **out) if (it->ent == NULL) { if (errno != 0) { - perror("readdir"); - it->state = SQFS_ERROR_INTERNAL; + it->state = SQFS_ERROR_IO; } else { it->state = 1; } @@ -109,9 +95,9 @@ static int dir_next(dir_iterator_t *base, dir_entry_t **out) return it->state; } - if (fstatat(dirfd(it->dir), it->ent->d_name, &it->sb, AT_SYMLINK_NOFOLLOW)) { - perror(it->ent->d_name); - it->state = SQFS_ERROR_INTERNAL; + if (fstatat(dirfd(it->dir), it->ent->d_name, + &it->sb, AT_SYMLINK_NOFOLLOW)) { + it->state = SQFS_ERROR_IO; return it->state; } @@ -119,7 +105,6 @@ static int dir_next(dir_iterator_t *base, dir_entry_t **out) decoded = alloc_flex(sizeof(*decoded), 1, len + 1); if (decoded == NULL) { - perror(it->ent->d_name); it->state = SQFS_ERROR_ALLOC; return it->state; } |