summaryrefslogtreecommitdiff
path: root/command/chmod.c
diff options
context:
space:
mode:
Diffstat (limited to 'command/chmod.c')
-rw-r--r--command/chmod.c122
1 files changed, 86 insertions, 36 deletions
diff --git a/command/chmod.c b/command/chmod.c
index eabb91c..8bf6aab 100644
--- a/command/chmod.c
+++ b/command/chmod.c
@@ -1,3 +1,8 @@
+/**
+ * file: chmod.c
+ * author: Tyler Murphy
+ */
+
#include "command.h"
#include "lslib.h"
@@ -8,21 +13,30 @@
#include <dirent.h>
#include <string.h>
+/**
+ * If to add remove or directly set bits to a file
+ */
enum method {
ADD,
SUB,
SET
};
+/**
+ * Flags to set in chmod
+ */
static struct {
- bool recurse;
- bool list_changed;
- bool verbose;
- bool quiet;
- enum method method;
- mode_t mode;
+ bool recurse; /* if to recurse directorys */
+ bool list_changed; /* if to list what was updated */
+ bool verbose; /* if to list all output */
+ bool quiet; /* if to silence errors */
+ enum method method; /* the method to apply to the mode */
+ mode_t mode; /* the mode to apply with the method */
} flags;
+/**
+ * Help function for chmod
+ */
static void help (void) {
printf("Usage: chmod [-Rcvf] MODE[,MODE]... FILE...\n\n");
printf("MODE is octal number (bit pattern sstrwxrwxrwx) or {+|-|=}[rwxXst]\n\n");
@@ -32,6 +46,12 @@ static void help (void) {
printf("\t-f\tHide errors\n");
}
+/**
+ * Takes in each argument that has a single - and parses it
+ * @param c the character after the -
+ * @param next the next argument in argv that hasnt been parsed
+ * @reutrn if the next arg was used or if the arg was invalid
+ */
static int short_arg(char c, char* next) {
UNUSED(next);
switch (c) {
@@ -60,23 +80,31 @@ static int short_arg(char c, char* next) {
return ARG_UNUSED;
}
+/**
+ * Given a file path, modify its mode, and recurse if set to
+ * @param path the file path to modify
+ */
static void chmod_file(char* path) {
- int save;
- struct stat s;
- DIR* d;
- struct dirent* file;
- mode_t mode = 0;
+ /* allocate arguments on stack */
+ int save; /* path buffer save */
+ struct stat s; /* file info */
+ DIR* d; /* if recursing, open dir */
+ struct dirent* file; /* if recursing, file being read */
+ mode_t mode = 0; /* silence the uninitalized var error */
+ /* add path to path buffer */
save = push_path_buffer(path);
+ /* get file statics, if failed return */
if (lstat(get_path_buffer(), &s) < 0) {
if (!flags.quiet) {
- error_s("cannot stat '%s'", get_path_buffer());
+ error_s("cannot stat '%s'", get_path_buffer()); /* error if failed */
}
pop_path_buffer(save);
return;
}
+ /* get the new mode given the method and proved mode */
if (flags.method == SET) {
mode = flags.mode;;
} else if (flags.method == ADD) {
@@ -85,48 +113,60 @@ static void chmod_file(char* path) {
mode = s.st_mode & ~flags.mode;
}
+ /* attempt to modify the file mode, error and return if failed */
if (chmod(get_path_buffer(), mode) < 0) {
if (!flags.quiet) {
- error_s("cannot chmod '%s'", get_path_buffer());
+ error_s("cannot chmod '%s'", get_path_buffer()); /* error if failed */
}
- pop_path_buffer(save);
+ pop_path_buffer(save); /* clean up */
return;
} else if (flags.list_changed) {
- printf("chmod: changed '%s' to %o\n", get_path_buffer(), mode);
+ output("changed '%s' to %o", get_path_buffer(), mode); /* print if set to be verbose */
}
+ /* if not set to recurse, dont bother to do future checks */
if (!flags.recurse) {
pop_path_buffer(save);
return;
}
+ /* if not a dir, cant recurse and then return */
if (!S_ISDIR(s.st_mode)) {
pop_path_buffer(save);
return;
}
+ /* get the directory, if failed, error and return */
d = opendir(get_path_buffer());
if (d == NULL) {
if (!flags.quiet) {
- error_s("cannot open dir '%s'", get_path_buffer());
+ error_s("cannot open dir '%s'", get_path_buffer()); /* error if failed */
}
- pop_path_buffer(save);
+ pop_path_buffer(save); /* clean up */
return;
}
+ /* chmod each file read */
while ((file = readdir(d)) != NULL) {
- if (is_dot_dir(file->d_name)) continue;
+ if (is_dot_dir(file->d_name)) continue; /* ignore dot dirs */
chmod_file(file->d_name);
}
+ /* clean up */
closedir(d);
pop_path_buffer(save);
}
+/**
+ * Parse a given mode and its method
+ * @param input a pointer to the string to check
+ * @return the mode parsed, mode parsing could not be done if reached , if so call again
+ */
static mode_t parse_mode(char** input) {
- mode_t mode = 00000;
- char* str = *input;
+ mode_t mode = 00000; /* default mode */
+ char* str = *input; /* get the input string */
+ /* check method for mode */
switch (*str) {
case '=':
flags.method = SET;
@@ -139,69 +179,76 @@ static mode_t parse_mode(char** input) {
break;
default:
flags.method = SET;
- mode = get_mode(str);
+ mode = get_mode(str); /* get mode and skip next checks */
goto end;
}
-next:
+next: /* check what bits to update */
str++;
switch (*str) {
- case 'r':
+ case 'r': /* read */
mode |= 00444;
goto next;
- case 'w':
+ case 'w': /* read */
mode |= 00200;
goto next;
- case 'x':
+ case 'x': /* execute */
mode |= 00111;
goto next;
- case 'X':
+ case 'X': /* empty */
mode |= 00000;
goto next;
- case 's':
+ case 's': /* setuid and setgid */
mode |= 06000;
goto next;
- case 't':
+ case 't': /* sticky */
mode |= 01000;
goto next;
case '\0':
- case ',':
+ case ',': /* stop reading args */
goto end;
default:
- error("invalid option: %c", *str);
+ error("invalid option: %c", *str); /* error when invalid */
}
-end:
+end: /* read till next argument and update input string pointer */
+
while (true) {
if (*str == '\0') {
- *input = NULL;
+ *input = NULL; /* no mroe args */
break;
}
if (*str == ',') {
- *input = ++str;
+ *input = ++str; /* another argument found */
break;
}
str++;
}
- return mode;
+ return mode; /* return mode */
}
+/**
+ * Modify a files permission mode
+ */
COMMAND(chmod_main) {
- int start, i;
+ int start, i;
+ /* get default flags */
flags.recurse = false;
flags.list_changed = false;
flags.verbose = false;
flags.quiet = false;
flags.mode = 0;
+ /* parse arguments */
start = parse_args(argc, argv, help, short_arg, NULL);
+ /* if not arguments error and return */
if (argc - start < 1) {
if (!flags.quiet) {
error("no mode provided");
@@ -210,10 +257,12 @@ COMMAND(chmod_main) {
}
}
+ /* parse mode continusally until no more mode arguments found */
do {
flags.mode |= parse_mode(&argv[start]);
} while (argv[start] != NULL);
+ /* if no files found error and return */
if (argc - start < 2) {
if (!flags.quiet) {
error("no files passed");
@@ -222,9 +271,10 @@ COMMAND(chmod_main) {
}
}
+ /* for each file passed, chmod */
for (i = start + 1; i < argc; i++) {
chmod_file(argv[i]);
}
- return EXIT_SUCCESS;
+ return EXIT_SUCCESS; /* return */
}