aboutsummaryrefslogtreecommitdiff
path: root/lib/util
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-04-21 21:11:18 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-04-21 21:11:18 +0200
commitb826045d0427db2c18eedda7e02f21acfc2ce62e (patch)
tree94af915f779ecb5c660159349f6bb4b2d423043b /lib/util
parent6c7d1c6e6cb3187218fa180fc87919255928b999 (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>
Diffstat (limited to 'lib/util')
-rw-r--r--lib/util/src/unix_dir_iterator.c53
1 files changed, 19 insertions, 34 deletions
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;
}