logo

utils-std

Collection of commonly available Unix tools
commit: 7a0e72cddb82b17da2b1355405199387c10b646b
parent 48f6992741d06ac8701d39ccbf44cd0553271041
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Tue, 12 Mar 2024 13:02:03 +0100

cmd/chmod: Add -c option

Diffstat:

MMakefile4++--
Mcmd/chmod.c49++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/Makefile b/Makefile @@ -80,6 +80,6 @@ cmd/df: cmd/df.c lib/humanize.c Makefile rm -f ${<:=.gcov} ${@:=.gcda} ${@:=.gcno} $(CC) -std=c99 $(CFLAGS) -o $@ cmd/df.c lib/humanize.c $(LDFLAGS) $(LDSTATIC) -cmd/chmod: cmd/chmod.c lib/mode.c Makefile +cmd/chmod: cmd/chmod.c lib/mode.c lib/symbolize_mode.c Makefile rm -f ${<:=.gcov} ${@:=.gcda} ${@:=.gcno} - $(CC) -std=c99 $(CFLAGS) -o $@ cmd/chmod.c lib/mode.c $(LDFLAGS) $(LDSTATIC) + $(CC) -std=c99 $(CFLAGS) -o $@ cmd/chmod.c lib/mode.c lib/symbolize_mode.c $(LDFLAGS) $(LDSTATIC) diff --git a/cmd/chmod.c b/cmd/chmod.c @@ -16,6 +16,8 @@ #include <sys/stat.h> // chmod, fstatat, S_ISDIR #include <unistd.h> // getopt +bool opt_c = false; + static int do_fchmodat(int fd, char *fdname, char *mode_arg, char *path, bool recursive) { @@ -48,6 +50,23 @@ do_fchmodat(int fd, char *fdname, char *mode_arg, char *path, bool recursive) return 1; } + if(opt_c && mode != stats.st_mode) + { + char ori_mode[11] = ""; + symbolize_mode(stats.st_mode, ori_mode); + + char cur_mode[11] = ""; + symbolize_mode(mode, cur_mode); + + printf("chmod: Mode changed from 0%o6/%s to 0%o6/%s for '%s%s'\n", + stats.st_mode & 07777, + ori_mode, + mode & 07777, + cur_mode, + fdname, + path); + } + if(recursive && S_ISDIR(stats.st_mode)) { int dir = openat(fd, path, O_RDONLY | O_DIRECTORY | O_CLOEXEC); @@ -61,7 +80,11 @@ do_fchmodat(int fd, char *fdname, char *mode_arg, char *path, bool recursive) DIR *dirp = fdopendir(dir); if(dirp == NULL) { - fprintf(stderr, "chmod: Couldn't get DIR entry for opened '%s/%s': %s\n", fdname, path, strerror(errno)); + fprintf(stderr, + "chmod: Couldn't get DIR entry for opened '%s/%s': %s\n", + fdname, + path, + strerror(errno)); return 1; } @@ -72,7 +95,8 @@ do_fchmodat(int fd, char *fdname, char *mode_arg, char *path, bool recursive) { if(errno == 0) break; - fprintf(stderr, "chmod: Failed reading directory '%s/%s': %s\n", fdname, path, strerror(errno)); + fprintf( + stderr, "chmod: Failed reading directory '%s/%s': %s\n", fdname, path, strerror(errno)); closedir(dirp); return 1; } @@ -83,7 +107,11 @@ do_fchmodat(int fd, char *fdname, char *mode_arg, char *path, bool recursive) char destdir[PATH_MAX] = ""; if(snprintf(destdir, PATH_MAX, "%s/%s", fdname, path) < 0) { - fprintf(stderr, "chmod: Couldn't concatenate '%s' into parent '%s', skipping to next entry: %s", fdname, path, strerror(errno)); + fprintf(stderr, + "chmod: Couldn't concatenate '%s' into parent '%s', skipping to next entry: %s", + fdname, + path, + strerror(errno)); err++; continue; } @@ -96,7 +124,11 @@ do_fchmodat(int fd, char *fdname, char *mode_arg, char *path, bool recursive) // fdopendir allocates memory for DIR, needs closedir if(closedir(dirp) != 0) { - fprintf(stderr, "chmod: Deallocating directory entry for '%s/%s' failed: %s\n", fdname, path, strerror(errno)); + fprintf(stderr, + "chmod: Deallocating directory entry for '%s/%s' failed: %s\n", + fdname, + path, + strerror(errno)); return 1; } } @@ -116,18 +148,21 @@ main(int argc, char *argv[]) bool opt_R = false; int c = -1; - while((c = getopt(argc, argv, ":R")) != -1) + while((c = getopt(argc, argv, ":cR")) != -1) { switch(c) { - case 'R': + case 'c': // GNU + opt_c = true; + break; + case 'R': // POSIX opt_R = true; break; case ':': fprintf(stderr, "chmod: Error: Missing operand for option: '-%c'\n", optopt); usage(); return 1; - case '?': + case '?': // GNU switch(optopt) { case 'r':