#include #include #include #include #include #include #include "make_path.h" #include "get_stat.h" #include "parse_mode.h" int (*get_stat)(const char *prog_name, const char *path, struct stat *stat_path); unsigned int r_flag; unsigned int s_flag; int change(const char *file, const char *mode_arg) { struct stat old_file; if (get_stat("chmod", file, &old_file)) return 1; mode_t mode = mu_parse_mode(mode_arg, old_file.st_mode); if (chmod(file, mode) != 0) { if (!s_flag) fprintf(stderr, "chmod: unable to chown %s: %s\n", file, strerror(errno)); return 1; } return 0; } int chtree(const char *dst, const char *mode_arg) { int ret = change(dst, mode_arg); struct stat stat_path; if (get_stat("chmod", dst, &stat_path)) return 1; if (!S_ISDIR(stat_path.st_mode) || !r_flag) return ret; DIR *dir = opendir(dst); if (dir == NULL) { if (!s_flag) fprintf(stderr, "chown: %s: Can`t open directory\n", dst); return 1; } struct dirent *ep; while ((ep = readdir(dir)) != NULL) { if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, "..")) continue; char *full_path = mu_make_path("chmod", dst, ep->d_name); if (full_path == NULL) continue; if (chtree(full_path, mode_arg)) ret = 1; free(full_path); } closedir(dir); return ret; } int main(int argc, char **argv) { get_stat = mu_get_lstat; /* Arg hacking */ char *arg, **argp; argp = argv; while ((arg = *++argp)) { if (arg[0] != '-') { arg = NULL; break; } if (arg[1] && (!strchr("-x", arg[1]) || !strchr("-r", arg[1]) || !strchr("-w", arg[1]))) { arg[0] = 'a'; break; } } int opt; while ((opt = getopt(argc, argv, "RfH") != -1)) { switch (opt) { case 'R': r_flag = 1; break; case 'f': s_flag = 1; break; case 'H': get_stat = mu_get_stat; break; default: printf("chmod [ugoa]{+|-}[rwxXst] / [0 - 777] [file1 file2...]\n\t[-H If a command line argument is a symbolic link]\n\t[-R Recursive] [-s Silent]\n"); return 0; } } if (argv[optind] == NULL) { fprintf(stderr, "chmod: missing operand\n"); return 0; } /* Fix arg */ if (arg) arg[0] = '-'; char *mode_arg = argv[optind]; argv += optind; argc -= optind; int ret = 0; for (int i = 1; i < argc; i++) if (chtree(argv[i], mode_arg)) ret = 1; return ret; }