chown.c (2116B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <errno.h> 3 #include <grp.h> 4 #include <limits.h> 5 #include <pwd.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <unistd.h> 9 10 #include "fs.h" 11 #include "util.h" 12 13 static int hflag = 0; 14 static uid_t uid = -1; 15 static gid_t gid = -1; 16 static int ret = 0; 17 18 static void 19 chownpwgr(const char *path, struct stat *st, void *data, struct recursor *r) 20 { 21 char *chownf_name; 22 int (*chownf)(const char *, uid_t, gid_t); 23 24 if ((r->maxdepth == 0 && r->follow == 'P') || (r->follow == 'H' && r->depth) || (hflag && !(r->depth))) { 25 chownf_name = "lchown"; 26 chownf = lchown; 27 } else { 28 chownf_name = "chown"; 29 chownf = chown; 30 } 31 32 if (chownf(path, uid, gid) < 0) { 33 weprintf("%s %s:", chownf_name, path); 34 ret = 1; 35 } else if (S_ISDIR(st->st_mode)) { 36 recurse(path, NULL, r); 37 } 38 } 39 40 static void 41 usage(void) 42 { 43 eprintf("usage: %s [-h] [-R [-H | -L | -P]] owner[:[group]] file ...\n" 44 " %s [-h] [-R [-H | -L | -P]] :group file ...\n", 45 argv0, argv0); 46 } 47 48 int 49 main(int argc, char *argv[]) 50 { 51 struct group *gr; 52 struct passwd *pw; 53 struct recursor r = { .fn = chownpwgr, .hist = NULL, .depth = 0, .maxdepth = 1, 54 .follow = 'P', .flags = 0 }; 55 char *owner, *group; 56 57 ARGBEGIN { 58 case 'h': 59 hflag = 1; 60 break; 61 case 'r': 62 case 'R': 63 r.maxdepth = 0; 64 break; 65 case 'H': 66 case 'L': 67 case 'P': 68 r.follow = ARGC(); 69 break; 70 default: 71 usage(); 72 } ARGEND 73 74 if (argc < 2) 75 usage(); 76 77 owner = argv[0]; 78 if ((group = strchr(owner, ':'))) 79 *group++ = '\0'; 80 81 if (owner && *owner) { 82 errno = 0; 83 pw = getpwnam(owner); 84 if (pw) { 85 uid = pw->pw_uid; 86 } else { 87 if (errno) 88 eprintf("getpwnam %s:", owner); 89 uid = estrtonum(owner, 0, UINT_MAX); 90 } 91 } 92 if (group && *group) { 93 errno = 0; 94 gr = getgrnam(group); 95 if (gr) { 96 gid = gr->gr_gid; 97 } else { 98 if (errno) 99 eprintf("getgrnam %s:", group); 100 gid = estrtonum(group, 0, UINT_MAX); 101 } 102 } 103 if (uid == (uid_t)-1 && gid == (gid_t)-1) 104 usage(); 105 106 for (argc--, argv++; *argv; argc--, argv++) 107 recurse(*argv, NULL, &r); 108 109 return ret || recurse_status; 110 }