From b826045d0427db2c18eedda7e02f21acfc2ce62e Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Fri, 21 Apr 2023 21:11:18 +0200 Subject: 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 --- lib/util/src/unix_dir_iterator.c | 53 ++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 34 deletions(-) (limited to 'lib') 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; } -- cgit v1.2.3