1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#include <sys/types.h> 5#include <dirent.h> 6#include <errno.h> 7#include <sys/limits.h> 8#include <sys/stat.h> 9 10#include <unistd.h> 11#include <time.h> 12 13void recurse_chmod(char* path, int mode) 14{ 15 struct dirent *dp; 16 DIR *dir = opendir(path); 17 if (dir == NULL) { 18 // not a directory, carry on 19 return; 20 } 21 char *subpath = malloc(sizeof(char)*PATH_MAX); 22 int pathlen = strlen(path); 23 24 while ((dp = readdir(dir)) != NULL) { 25 if (strcmp(dp->d_name, ".") == 0 || 26 strcmp(dp->d_name, "..") == 0) continue; 27 28 if (strlen(dp->d_name) + pathlen + 2/*NUL and slash*/ > PATH_MAX) { 29 fprintf(stderr, "Invalid path specified: too long\n"); 30 exit(1); 31 } 32 33 strcpy(subpath, path); 34 strcat(subpath, "/"); 35 strcat(subpath, dp->d_name); 36 37 if (chmod(subpath, mode) < 0) { 38 fprintf(stderr, "Unable to chmod %s: %s\n", subpath, strerror(errno)); 39 exit(1); 40 } 41 42 recurse_chmod(subpath, mode); 43 } 44 free(subpath); 45 closedir(dir); 46} 47 48static int usage() 49{ 50 fprintf(stderr, "Usage: chmod [OPTION] <MODE> <FILE>\n"); 51 fprintf(stderr, " -R, --recursive change files and directories recursively\n"); 52 fprintf(stderr, " --help display this help and exit\n"); 53 54 return 10; 55} 56 57int chmod_main(int argc, char **argv) 58{ 59 int i; 60 61 if (argc < 3 || strcmp(argv[1], "--help") == 0) { 62 return usage(); 63 } 64 65 int recursive = (strcmp(argv[1], "-R") == 0 || 66 strcmp(argv[1], "--recursive") == 0) ? 1 : 0; 67 68 if (recursive && argc < 4) { 69 return usage(); 70 } 71 72 if (recursive) { 73 argc--; 74 argv++; 75 } 76 77 int mode = 0; 78 const char* s = argv[1]; 79 while (*s) { 80 if (*s >= '0' && *s <= '7') { 81 mode = (mode<<3) | (*s-'0'); 82 } 83 else { 84 fprintf(stderr, "Bad mode\n"); 85 return 10; 86 } 87 s++; 88 } 89 90 for (i = 2; i < argc; i++) { 91 if (chmod(argv[i], mode) < 0) { 92 fprintf(stderr, "Unable to chmod %s: %s\n", argv[i], strerror(errno)); 93 return 10; 94 } 95 if (recursive) { 96 recurse_chmod(argv[i], mode); 97 } 98 } 99 return 0; 100} 101 102