1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h> 5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <dirent.h> 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h> 7365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam#include <sys/limits.h> 8365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam#include <sys/stat.h> 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h> 11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <time.h> 12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 13365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnamvoid recurse_chmod(char* path, int mode) 14365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam{ 15365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam struct dirent *dp; 16365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam DIR *dir = opendir(path); 17365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam if (dir == NULL) { 18365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam // not a directory, carry on 19365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam return; 20365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam } 21365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam char *subpath = malloc(sizeof(char)*PATH_MAX); 22365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam int pathlen = strlen(path); 23365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam 24365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam while ((dp = readdir(dir)) != NULL) { 25365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam if (strcmp(dp->d_name, ".") == 0 || 26365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam strcmp(dp->d_name, "..") == 0) continue; 27365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam 28365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam if (strlen(dp->d_name) + pathlen + 2/*NUL and slash*/ > PATH_MAX) { 29365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam fprintf(stderr, "Invalid path specified: too long\n"); 30365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam exit(1); 31365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam } 32365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam 33365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam strcpy(subpath, path); 34365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam strcat(subpath, "/"); 35365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam strcat(subpath, dp->d_name); 36365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam 37365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam if (chmod(subpath, mode) < 0) { 38365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam fprintf(stderr, "Unable to chmod %s: %s\n", subpath, strerror(errno)); 39365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam exit(1); 40365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam } 41365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam 42365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam recurse_chmod(subpath, mode); 43365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam } 44365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam free(subpath); 45365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam closedir(dir); 46365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam} 47365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam 48365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnamstatic int usage() 49365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam{ 50365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam fprintf(stderr, "Usage: chmod [OPTION] <MODE> <FILE>\n"); 51365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam fprintf(stderr, " -R, --recursive change files and directories recursively\n"); 52365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam fprintf(stderr, " --help display this help and exit\n"); 53365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam 54365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam return 10; 55365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam} 56365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint chmod_main(int argc, char **argv) 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int i; 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 61365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam if (argc < 3 || strcmp(argv[1], "--help") == 0) { 62365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam return usage(); 63365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam } 64365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam 65365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam int recursive = (strcmp(argv[1], "-R") == 0 || 66365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam strcmp(argv[1], "--recursive") == 0) ? 1 : 0; 67365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam 68365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam if (recursive && argc < 4) { 69365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam return usage(); 70365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam } 71365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam 72365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam if (recursive) { 73365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam argc--; 74365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam argv++; 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int mode = 0; 78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const char* s = argv[1]; 79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while (*s) { 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (*s >= '0' && *s <= '7') { 81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mode = (mode<<3) | (*s-'0'); 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project else { 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "Bad mode\n"); 85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 10; 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project s++; 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 89365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for (i = 2; i < argc; i++) { 91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (chmod(argv[i], mode) < 0) { 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "Unable to chmod %s: %s\n", argv[i], strerror(errno)); 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 10; 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 95365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam if (recursive) { 96365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam recurse_chmod(argv[i], mode); 97365a09e817e919c491a1e8abce0b734af14d3e5fAnthony Newnam } 98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 102