diff options
Diffstat (limited to 'command/chmod.c')
-rw-r--r-- | command/chmod.c | 122 |
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 */ } |