logo

utils-std

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

cmd/rm: Reset errno before every call which might set it

Otherwise checks against errno, particularly the errno == 0 ones end up failing.
Leading to bugs like not removing an empty directory when prior removal failed.

Diffstat:

Mcmd/rm.c15++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/cmd/rm.c b/cmd/rm.c @@ -35,6 +35,8 @@ consentf(const char *restrict fmt, ...) va_list ap; + errno = 0; + va_start(ap, fmt); int ret = vfprintf(stderr, fmt, ap); va_end(ap); @@ -45,7 +47,8 @@ consentf(const char *restrict fmt, ...) goto end; } - errno = 0; + errno = 0; + ssize_t nread = getline(&line, &len, stdin); if(nread < 0) { @@ -94,6 +97,7 @@ do_unlinkat(int fd, char *name, char *acc_path) struct stat stats; int err = 0; + errno = 0; if(fstatat(fd, name, &stats, AT_SYMLINK_NOFOLLOW) != 0) { if(force && errno == ENOENT) return 0; @@ -115,6 +119,7 @@ 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; int dir = openat(fd, name, O_RDONLY | O_DIRECTORY | O_CLOEXEC); if(dir == -1) { @@ -122,6 +127,8 @@ do_unlinkat(int fd, char *name, char *acc_path) return 1; } + errno = 0; + DIR *dirp = fdopendir(dir); if(dirp == NULL) { @@ -132,6 +139,8 @@ do_unlinkat(int fd, char *name, char *acc_path) while(true) { + errno = 0; + struct dirent *dp = readdir(dirp); if(dp == NULL) { @@ -145,6 +154,8 @@ do_unlinkat(int fd, char *name, char *acc_path) if(strcmp(dp->d_name, ".") == 0) continue; if(strcmp(dp->d_name, "..") == 0) continue; + errno = 0; + char new_path[PATH_MAX] = ""; if(snprintf(new_path, PATH_MAX, "%s/%s", acc_path, dp->d_name) < 0) { @@ -163,6 +174,7 @@ do_unlinkat(int fd, char *name, char *acc_path) } // fdopendir allocates memory for DIR, needs closedir + errno = 0; if(closedir(dirp) != 0) { fprintf(stderr, @@ -180,6 +192,7 @@ do_unlinkat(int fd, char *name, char *acc_path) if(!consentf("rm: Remove '%s' ? [y/N] ", acc_path)) return 0; } + 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));