diff --git a/sbin/mknod/mknod.8 b/sbin/mknod/mknod.8 index 8994d091bb98..2232c9a5224b 100644 --- a/sbin/mknod/mknod.8 +++ b/sbin/mknod/mknod.8 @@ -43,6 +43,7 @@ .Ar name .Op Cm c | Cm b .Ar major minor +.Op owner:group .Sh DESCRIPTION The .Nm mknod @@ -90,6 +91,23 @@ The minor device number tells the kernel which subunit the node corresponds to on the device; for example, a subunit may be a filesystem partition or a tty line. +.It Ar "owner \: group" +The +.Ar owner +.Ar group +operand pair is optional, however, if one is specified, they both must be +specified. +The +.Ar owner +may be either a numeric user ID or a user name. +If a user name is also a numeric user ID, the operand is used as a +user name. +The +.Ar group +may be either a numeric group ID or a group name. +Simular to the user name, +if a group name is also a numeric group ID, the operand is used as a +group name. .El .Pp Major and minor device numbers can be given in any format acceptable to @@ -99,10 +117,21 @@ so that a leading indicates a hexadecimal number, and a leading .Ql 0 will cause the number to be interpreted as octal. +.Sh COMPATIBILITY +The +.Xr chown 8 +like functionality is specific to +.Fx +and was added so that +.Pa /dev/MAKEDEV +wound not depend on +.Pa /usr +being mounted. .Sh SEE ALSO .Xr mkfifo 1 , .Xr mknod 2 , -.Xr MAKEDEV 8 +.Xr MAKEDEV 8 , +.Xr chown 8 .Sh HISTORY A .Nm diff --git a/sbin/mknod/mknod.c b/sbin/mknod/mknod.c index 822d5f2cd149..98c0612a4295 100644 --- a/sbin/mknod/mknod.c +++ b/sbin/mknod/mknod.c @@ -56,26 +56,75 @@ static const char rcsid[] = #include #include #include +#include +#include +#include static void usage() { - (void)fprintf(stderr, "usage: mknod name [b | c] major minor\n"); + + (void)fprintf(stderr, + "usage: mknod name [b | c] major minor [owner:group]\n"); exit(1); } +static u_long +id(name, type) + char *name, *type; +{ + u_long val; + char *ep; + + /* + * XXX + * We know that uid_t's and gid_t's are unsigned longs. + */ + errno = 0; + val = strtoul(name, &ep, 10); + if (errno) + err(1, "%s", name); + if (*ep != '\0') + errx(1, "%s: illegal %s name", name, type); + return (val); +} + +static gid_t +a_gid(s) + char *s; +{ + struct group *gr; + + if (*s == '\0') /* Argument was "uid[:.]". */ + errx(1, "group must be specified when the owner is"); + return ((gr = getgrnam(s)) == NULL) ? id(s, "group") : gr->gr_gid; +} + +static uid_t +a_uid(s) + char *s; +{ + struct passwd *pw; + + if (*s == '\0') /* Argument was "[:.]gid". */ + errx(1, "owner must be specified when the group is"); + return ((pw = getpwnam(s)) == NULL) ? id(s, "user") : pw->pw_uid; +} + int main(argc, argv) int argc; char **argv; { - dev_t dev; - char *endp; - long mymajor, myminor; - mode_t mode; int range_error; + uid_t uid; + gid_t gid; + mode_t mode; + dev_t dev; + char *cp, *endp; + long mymajor, myminor; - if (argc != 5) + if (argc != 5 && argc != 6) usage(); mode = 0666; @@ -101,7 +150,21 @@ main(argc, argv) minor(dev) != (u_int) myminor) errx(1, "major or minor number too large"); + uid = gid = -1; + if (6 == argc) { + /* have owner:group */ + if ((cp = strchr(argv[5], ':')) != NULL) { + *cp++ = '\0'; + gid = a_gid(cp); + } else + usage(); + uid = a_uid(argv[5]); + } + if (mknod(argv[1], mode, dev) != 0) err(1, "%s", argv[1]); + if (6 == argc) + if (chown(argv[1], uid, gid)) + err(1, "setting ownership on %s", argv[1]); exit(0); }