diff --git a/src/chgrp.c b/src/chgrp.c new file mode 100644 index 0000000..8f344ab --- /dev/null +++ b/src/chgrp.c @@ -0,0 +1,242 @@ +/* chgrp.c */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* types */ +#define OPT_h 1 +#define OPT_R 2 +#define OPT_H 4 +#define OPT_L 8 +#define OPT_P 12 + + +/* chgrp */ +static int _chgrp_grp_error(char * group); +static int _chgrp_gid(int opts, gid_t gid, int argc, char * argv[]); +static int _chgrp(int opts, char * group, int argc, char * argv[]) +{ + struct group * grp; + + if((grp = getgrnam(group)) == NULL) + return _chgrp_grp_error(group); + return _chgrp_gid(opts, grp->gr_gid, argc, argv); +} + +static int _chgrp_grp_error(char * group) +{ + fprintf(stderr, "%s", "chgrp: "); + if(errno == 0) + fprintf(stderr, "%s%s", group, ": Unknown group\n"); + else + perror(group); + return 2; +} + +static int _chgrp_do_recursive(int opts, gid_t gid, char * file); +static int _chgrp_do(int opts, gid_t gid, char * file); +static int _chgrp_gid(int opts, gid_t gid, int argc, char * argv[]) +{ + int res = 0; + int i; + + if((opts & OPT_R) == OPT_R) + { + for(i = 0; i < argc; i++) + res +=_chgrp_do_recursive(opts, gid, argv[i]); + return res; + } + for(i = 0; i < argc; i++) + res +=_chgrp_do(opts, gid, argv[i]); + return res; +} + +static int _chgrp_do_recursive_do(int opts, gid_t gid, char * file); +static int _chgrp_do_recursive(int opts, gid_t gid, char * file) +{ + struct stat st; + + if((lstat(file, &st)) != 0) + { + fprintf(stderr, "%s", "chgrp: "); + perror(file); + return 1; + } + if(S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode)) + _chgrp_do_recursive_do(opts, gid, file); + return 0; +} + +static int _chgrp_do_recursive_do(int opts, gid_t gid, char * file) +{ + DIR * dir; + struct dirent * de; + int len; + char * s; + char * p; + + if((dir = opendir(file)) == NULL) + { + fprintf(stderr, "%s", "chgrp: "); + perror(file); + return 1; + } + readdir(dir); + readdir(dir); + len = strlen(file) + 2; + if((s = malloc(len)) == NULL) + { + fprintf(stderr, "%s", "chgrp: "); + perror(file); + return 1; + } + strcpy(s, file); + s[len-2] = '/'; + s[len-1] = '\0'; + while((de = readdir(dir)) != NULL) + { + if((p = realloc(s, len + strlen(de->d_name))) == NULL) + { + fprintf(stderr, "%s", "chgrp: "); + perror("malloc"); + continue; + } + s = p; + strcat(s, de->d_name); + fprintf(stderr, "%s\n", s); + _chgrp_do_recursive(opts, gid, s); + s[len-1] = '\0'; + } + free(s); + closedir(dir); + return 0; +} + +/*{ + struct stat st; + DIR * dir; + struct dirent * de; + unsigned int len; + char * s; + char * p; + + fprintf(stderr, "_chgrp_do_recursive(%d, %d, %s)\n", opts, gid, file); + if(stat(file, &st) != 0) + { + fprintf(stderr, "%s", "chgrp: "); + perror(file); + return 1; + } + if(!S_ISLNK(st.st_mode) && S_ISDIR(st.st_mode)) + { + if((dir = opendir(file)) == NULL) + { + fprintf(stderr, "%s", "chgrp: "); + perror(file); + return 1; + } + len = strlen(file) + 2; + if((s = malloc(len)) == NULL) + { + fprintf(stderr, "%s", "chgrp: "); + perror("alloc"); + return 1; + } + sprintf(s, "%s/", file); + fprintf(stderr, "coucou %s\n", s); + readdir(dir); + readdir(dir); + while((de = readdir(dir)) != NULL) + { + if((p = realloc(s, len + strlen(de->d_name))) == NULL) + { + fprintf(stderr, "%s", "chgrp: "); + perror("alloc"); + continue; + } + s = p; + s[len-1] = '\0'; + strcat(s, de->d_name); + fprintf(stderr, "coucou2 %s\n", s); + _chgrp_do_recursive(opts, gid, s); + } + free(s); + closedir(dir); + } + return 0; +}*/ + +static int _chgrp_do(int opts, gid_t gid, char * file) +{ + struct stat st; + int res; + + if(stat(file, &st) != 0) + { + fprintf(stderr, "%s", "chgrp: "); + perror(file); + return 1; + } + if((opts & OPT_h) == OPT_h) + res = lchown(file, st.st_uid, gid); + else + res = chown(file, st.st_uid, gid); + if(res != 0) + { + fprintf(stderr, "%s", "chgrp: "); + perror(file); + return 1; + } + return 0; +} + + +/* usage */ +static int _usage(void) +{ + fprintf(stderr, "%s", "Usage: chgrp [-hR] group file ...\n\ + chgrp -R [-H | -L | -P] group file ...\n"); + return 1; +} + +/* main */ +int main(int argc, char * argv[]) +{ + int o; + int opts = 0; + + while((o = getopt(argc, argv, "hRHLP")) != -1) + { + switch(o) + { + case 'h': + if((opts & OPT_h) == 0) + opts += OPT_h; + break; + case 'R': + if((opts & OPT_R) == 0) + opts += OPT_R; + break; + case 'H': + case 'L': + case 'P': + fprintf(stderr, "%s%c%s", "chgrp: -", o, + ": Not yet implemented\n"); + default: + return _usage(); + } + } + if(argc - optind < 2) + return _usage(); + return _chgrp(opts, argv[optind], argc - optind - 1, &argv[optind+1]); +}