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