logo

utils-std

Collection of commonly available Unix tools
commit: 21c374ab77399a99e0e8b5fe1b6f67fdb25cb180
parent 50f9d24bb94d4595555872641eea33f902cebab7
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Thu, 28 Mar 2024 18:17:28 +0100

cmd/rm: Add assert(errno == 0) before functions known to change errno

Risky as different systems could change errno in extra places, but this way
we're sure errno is reset, in fact I forgot to reset it for faccessat(…W_OK…)

Diffstat:

Mcmd/rm.c49+++++++++++++++++++++++++++++++------------------
1 file changed, 31 insertions(+), 18 deletions(-)

diff --git a/cmd/rm.c b/cmd/rm.c @@ -9,6 +9,7 @@ #define _NETBSD_SOURCE #endif +#include <assert.h> #include <ctype.h> // isprint #include <dirent.h> // fdopendir, readdir, closedir #include <errno.h> // errno @@ -35,30 +36,31 @@ consentf(const char *restrict fmt, ...) va_list ap; - errno = 0; - + assert(errno == 0); va_start(ap, fmt); int ret = vfprintf(stderr, fmt, ap); va_end(ap); - if(!ret) + if(ret < 0) { fprintf(stderr, "%s: Failed to print user prompt: %s\n", argv0, strerror(errno)); + errno = 0; goto end; } - errno = 0; - + assert(errno == 0); ssize_t nread = getline(&line, &len, stdin); if(nread < 0) { fprintf(stderr, "\n%s: Failed getting user entry via getline: %s\n", argv0, strerror(errno)); + errno = 0; goto end; } if(nread == 0) { fprintf(stderr, "%s: Got empty response, considering it false\n", argv0); + errno = 0; goto end; } @@ -97,12 +99,17 @@ do_unlinkat(int fd, char *name, char *acc_path) struct stat stats; int err = 0; - errno = 0; + assert(errno == 0); if(fstatat(fd, name, &stats, AT_SYMLINK_NOFOLLOW) != 0) { - if(force && errno == ENOENT) return 0; + if(force && errno == ENOENT) + { + errno = 0; + return 0; + } fprintf(stderr, "rm: Failed getting status for '%s': %s\n", acc_path, strerror(errno)); + errno = 0; return 1; } @@ -119,44 +126,44 @@ do_unlinkat(int fd, char *name, char *acc_path) if(!force && opt_i) if(!consentf("rm: Recurse into '%s' ? [y/N] ", acc_path)) return 0; - errno = 0; + assert(errno == 0); int dir = openat(fd, name, O_RDONLY | O_DIRECTORY | O_CLOEXEC); if(dir == -1) { fprintf(stderr, "rm: Couldn't open '%s' as directory: %s\n", acc_path, strerror(errno)); + errno = 0; return 1; } - errno = 0; - + assert(errno == 0); DIR *dirp = fdopendir(dir); if(dirp == NULL) { fprintf( stderr, "rm: Couldn't get DIR entry for opened '%s': %s\n", acc_path, strerror(errno)); + errno = 0; return 1; } while(true) { - errno = 0; - + assert(errno == 0); struct dirent *dp = readdir(dirp); if(dp == NULL) { if(errno == 0) break; fprintf(stderr, "rm: Failed reading directory '%s': %s\n", acc_path, strerror(errno)); - closedir(dirp); + closedir(dirp); // error ignored + errno = 0; return 1; } if(strcmp(dp->d_name, ".") == 0) continue; if(strcmp(dp->d_name, "..") == 0) continue; - errno = 0; - char new_path[PATH_MAX] = ""; + assert(errno == 0); if(snprintf(new_path, PATH_MAX, "%s/%s", acc_path, dp->d_name) < 0) { fprintf(stderr, @@ -164,7 +171,8 @@ do_unlinkat(int fd, char *name, char *acc_path) name, acc_path, strerror(errno)); - err = 1; + err = 1; + errno = 0; continue; } @@ -174,13 +182,14 @@ do_unlinkat(int fd, char *name, char *acc_path) } // fdopendir allocates memory for DIR, needs closedir - errno = 0; + assert(errno == 0); if(closedir(dirp) != 0) { fprintf(stderr, "rm: Deallocating directory entry for '%s' failed: %s\n", acc_path, strerror(errno)); + errno = 0; return 1; } } @@ -189,13 +198,17 @@ do_unlinkat(int fd, char *name, char *acc_path) { // FIXME: Terminal always considered to be present for tests reason if(faccessat(fd, name, W_OK, AT_SYMLINK_NOFOLLOW) != 0 || opt_i) + { + errno = 0; if(!consentf("rm: Remove '%s' ? [y/N] ", acc_path)) return 0; + } } - errno = 0; + assert(errno == 0); if(unlinkat(fd, name, is_dir ? AT_REMOVEDIR : 0) != 0) { fprintf(stderr, "rm: Couldn't remove '%s': %s\n", acc_path, strerror(errno)); + errno = 0; return 1; } else if(verbose)