mtree mknod

Change-Id: I887437c7b84839fc644da4c55bd59b6a414408ef
This commit is contained in:
Ben Gras
2012-10-10 17:20:17 +02:00
committed by Lionel Sambuc
parent 7dd6189cc7
commit a8ef09103d
25 changed files with 1580 additions and 291 deletions

View File

@@ -2,6 +2,6 @@
.include <bsd.own.mk>
SUBDIR= fsck fsck_ext2fs newfs_ext2fs
SUBDIR= fsck fsck_ext2fs newfs_ext2fs mknod
.include <bsd.subdir.mk>

8
sbin/mknod/Makefile Normal file
View File

@@ -0,0 +1,8 @@
# $NetBSD: Makefile,v 1.13 2009/04/11 07:58:12 lukem Exp $
# @(#)Makefile 8.1 (Berkeley) 6/5/93
PROG= mknod
SRCS= mknod.c pack_dev.c
MAN= mknod.8
.include <bsd.prog.mk>

229
sbin/mknod/mknod.8 Normal file
View File

@@ -0,0 +1,229 @@
.\" $NetBSD: mknod.8,v 1.28 2004/06/17 21:30:14 dsl Exp $
.\"
.\" Copyright (c) 1980, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)mknod.8 8.2 (Berkeley) 12/11/93
.\"
.Dd June 17, 2004
.Dt MKNOD 8
.Os
.Sh NAME
.Nm mknod
.Nd make device special file
.Sh SYNOPSIS
.Nm
.Op Fl rR
.Op Fl F Ar fmt
.Op Fl g Ar gid
.Op Fl m Ar mode
.Op Fl u Ar uid
.Ar name
.Op Cm c | Cm b
.Op Ar driver | Ar major
.Ar minor
.Nm
.Op Fl rR
.Op Fl F Ar fmt
.Op Fl g Ar gid
.Op Fl m Ar mode
.Op Fl u Ar uid
.Ar name
.Op Cm c | Cm b
.Ar major unit subunit
.Nm
.Op Fl rR
.Op Fl g Ar gid
.Op Fl m Ar mode
.Op Fl u Ar uid
.Ar name
.Op Cm c | Cm b
.Ar number
.Nm
.Op Fl rR
.Op Fl g Ar gid
.Op Fl m Ar mode
.Op Fl u Ar uid
.Ar name
.Cm p
.Nm
.Fl l
.Sh DESCRIPTION
The
.Nm
command creates device special files, or fifos.
Normally the shell script
.Pa /dev/MAKEDEV
is used to create special files for commonly known devices; it executes
.Nm
with the appropriate arguments and can make all the files required for the
device.
.Pp
To make nodes manually, the arguments are:
.Pp
.Bl -tag -width xmxmode
.It Fl r
Replace an existing file if its type is incorrect.
.It Fl R
Replace an existing file if its type is incorrect.
Correct the mode, user and group.
.It Fl F Ar fmt
Create device nodes that may be used by an operating system which
uses device numbers packed in a different format than
.Nx
uses.
This is necessary when
.Nx
is used as an
.Tn NFS
server for netbooted computers running other operating systems.
.Pp
The following values for the
.Ar fmt
are recognized:
.Sy native ,
.Sy 386bsd ,
.Sy 4bsd ,
.Sy bsdos ,
.Sy freebsd ,
.Sy hpux ,
.Sy isc ,
.Sy linux ,
.Sy netbsd ,
.Sy osf1 ,
.Sy sco ,
.Sy solaris ,
.Sy sunos ,
.Sy svr3 ,
.Sy svr4 ,
and
.Sy ultrix .
.It Fl g Ar gid
Specify the group for the device node.
The
.Ar gid
operand may be a numeric group ID or a group name.
If a group name is also a numeric group ID,
the operand is used as a group name.
Precede a numeric group ID with a
.Cm #
to stop it being treated as a name.
.It Fl m Ar mode
Specify the mode for the device node.
The mode may be absolute or symbolic, see
.Xr chmod 1 .
.It Fl u Ar uid
Specify the user for the device node.
The
.Ar uid
operand may be 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.
Precede a numeric user ID with a
.Cm #
to stop it being treated as a name.
.It Ar name
Device name, for example
.Dq sd
for a SCSI disk on an HP300 or a
.Dq pty
for pseudo-devices.
.It Cm b | Cm c | Cm p
Type of device.
If the device is a block type device such as a tape or disk drive
which needs both cooked and raw special files, the type is
.Cm b .
All other devices are character type devices, such as terminal
and pseudo devices, and are type
.Cm c .
Specifying
.Cm p
creates fifo files.
.It Ar driver | Ar major
The major device number is an integer number which tells the kernel
which device driver entry point to use.
If the device driver is configured into the current kernel it may be
specified by driver name or major number.
To find out which major device number to use for a particular device,
use
.Nm
.Fl l ,
check the file
.Pa /dev/MAKEDEV
to see if the device is known, or check
the system dependent device configuration file:
.Bd -filled -offset indent
.Dq Pa /usr/src/sys/arch/\*[Lt]arch\*[Gt]/\*[Lt]arch\*[Gt]/conf.c
.Ed
.Pp
.Po
e.g.
.Pa /usr/src/sys/arch/vax/vax/conf.c
.Pc .
.It Ar minor
The minor device number tells the kernel which one of several similar
devices the node corresponds to; for example, it may be a specific serial
port or pty.
.It Ar unit No and Ar subunit
The unit and subunit numbers select a subset of a device; for example, the
unit may specify a particular SCSI disk, and the subunit a partition on
that disk.
(Currently this form of specification is only supported by the
.Ar bsdos
format, for compatibility with the
.Bsx
.Nm ) .
.It Ar number
A single opaque device number.
Useful for netbooted computers which require device numbers packed
in a format that isn't supported by
.Fl F .
.It Fl l
List the device drivers configured into the current kernel together with their
block and character major numbers.
.El
.Sh SEE ALSO
.Xr chmod 1 ,
.Xr mkfifo 1 ,
.Xr mkfifo 2 ,
.Xr mknod 2 ,
.Xr MAKEDEV 8
.Sh HISTORY
A
.Nm
command appeared in
.At v6 .
The
.Fl F
option appeared in
.Nx 1.4 .
The
.Fl g , l , m , r , R ,
and
.Fl u
options, and the ability to specify a driver by name appeared in
.Nx 2.0 .

393
sbin/mknod/mknod.c Normal file
View File

@@ -0,0 +1,393 @@
/* $NetBSD: mknod.c,v 1.40 2011/08/27 18:37:41 joerg Exp $ */
/*-
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Charles M. Hannum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1998\
The NetBSD Foundation, Inc. All rights reserved.");
__RCSID("$NetBSD: mknod.c,v 1.40 2011/08/27 18:37:41 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#if !HAVE_NBTOOL_CONFIG_H
#include <sys/sysctl.h>
#endif
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <string.h>
#include <ctype.h>
#include "pack_dev.h"
static int gid_name(const char *, gid_t *);
static portdev_t callPack(pack_t *, int, u_long *);
__dead static void usage(void);
#ifdef KERN_DRIVERS
static struct kinfo_drivers *kern_drivers;
static int num_drivers;
static void get_device_info(void);
static void print_device_info(char **);
static int major_from_name(const char *, mode_t);
#endif
#define MAXARGS 3 /* 3 for bsdos, 2 for rest */
int
main(int argc, char **argv)
{
char *name, *p;
mode_t mode;
portdev_t dev;
pack_t *pack;
u_long numbers[MAXARGS];
int n, ch, fifo, hasformat;
int r_flag = 0; /* force: delete existing entry */
#ifdef KERN_DRIVERS
int l_flag = 0; /* list device names and numbers */
int major;
#endif
void *modes = 0;
uid_t uid = -1;
gid_t gid = -1;
int rval;
dev = 0;
fifo = hasformat = 0;
pack = pack_native;
#ifdef KERN_DRIVERS
while ((ch = getopt(argc, argv, "lrRF:g:m:u:")) != -1) {
#else
while ((ch = getopt(argc, argv, "rRF:g:m:u:")) != -1) {
#endif
switch (ch) {
#ifdef KERN_DRIVERS
case 'l':
l_flag = 1;
break;
#endif
case 'r':
r_flag = 1;
break;
case 'R':
r_flag = 2;
break;
case 'F':
pack = pack_find(optarg);
if (pack == NULL)
errx(1, "invalid format: %s", optarg);
hasformat++;
break;
case 'g':
if (optarg[0] == '#') {
gid = strtol(optarg + 1, &p, 10);
if (*p == 0)
break;
}
if (gid_name(optarg, &gid) == 0)
break;
gid = strtol(optarg, &p, 10);
if (*p == 0)
break;
errx(1, "%s: invalid group name", optarg);
case 'm':
modes = setmode(optarg);
if (modes == NULL)
err(1, "Cannot set file mode `%s'", optarg);
break;
case 'u':
if (optarg[0] == '#') {
uid = strtol(optarg + 1, &p, 10);
if (*p == 0)
break;
}
if (uid_from_user(optarg, &uid) == 0)
break;
uid = strtol(optarg, &p, 10);
if (*p == 0)
break;
errx(1, "%s: invalid user name", optarg);
default:
case '?':
usage();
}
}
argc -= optind;
argv += optind;
#ifdef KERN_DRIVERS
if (l_flag) {
print_device_info(argv);
return 0;
}
#endif
if (argc < 2 || argc > 10)
usage();
name = *argv;
argc--;
argv++;
umask(mode = umask(0));
mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) & ~mode;
if (argv[0][1] != '\0')
goto badtype;
switch (*argv[0]) {
case 'c':
mode |= S_IFCHR;
break;
case 'b':
mode |= S_IFBLK;
break;
case 'p':
if (hasformat)
errx(1, "format is meaningless for fifos");
mode |= S_IFIFO;
fifo = 1;
break;
default:
badtype:
errx(1, "node type must be 'b', 'c' or 'p'.");
}
argc--;
argv++;
if (fifo) {
if (argc != 0)
usage();
} else {
if (argc < 1 || argc > MAXARGS)
usage();
}
for (n = 0; n < argc; n++) {
errno = 0;
numbers[n] = strtoul(argv[n], &p, 0);
if (*p == 0 && errno == 0)
continue;
#ifdef KERN_DRIVERS
if (n == 0) {
major = major_from_name(argv[0], mode);
if (major != -1) {
numbers[0] = major;
continue;
}
if (!isdigit(*(unsigned char *)argv[0]))
errx(1, "unknown driver: %s", argv[0]);
}
#endif
errx(1, "invalid number: %s", argv[n]);
}
switch (argc) {
case 0:
dev = 0;
break;
case 1:
dev = numbers[0];
break;
default:
dev = callPack(pack, argc, numbers);
break;
}
if (modes != NULL)
mode = getmode(modes, mode);
umask(0);
rval = fifo ? mkfifo(name, mode) : mknod(name, mode, dev);
if (rval < 0 && errno == EEXIST && r_flag) {
struct stat sb;
if (lstat(name, &sb) != 0 || (!fifo && sb.st_rdev != dev))
sb.st_mode = 0;
if ((sb.st_mode & S_IFMT) == (mode & S_IFMT)) {
if (r_flag == 1)
/* Ignore permissions and user/group */
return 0;
if (sb.st_mode != mode)
rval = chmod(name, mode);
else
rval = 0;
} else {
unlink(name);
rval = fifo ? mkfifo(name, mode)
: mknod(name, mode, dev);
}
}
if (rval < 0)
err(1, "%s", name);
if ((uid != (uid_t)-1 || gid != (uid_t)-1) && chown(name, uid, gid) == -1)
/* XXX Should we unlink the files here? */
warn("%s: uid/gid not changed", name);
return 0;
}
static void
usage(void)
{
const char *progname = getprogname();
(void)fprintf(stderr,
"usage: %s [-rR] [-F format] [-m mode] [-u user] [-g group]\n",
progname);
(void)fprintf(stderr,
#ifdef KERN_DRIVERS
" [ name [b | c] [major | driver] minor\n"
#else
" [ name [b | c] major minor\n"
#endif
" | name [b | c] major unit subunit\n"
" | name [b | c] number\n"
" | name p ]\n");
#ifdef KERN_DRIVERS
(void)fprintf(stderr, " %s -l [driver] ...\n", progname);
#endif
exit(1);
}
static int
gid_name(const char *name, gid_t *gid)
{
struct group *g;
g = getgrnam(name);
if (!g)
return -1;
*gid = g->gr_gid;
return 0;
}
static portdev_t
callPack(pack_t *f, int n, u_long *numbers)
{
portdev_t d;
const char *error = NULL;
d = (*f)(n, numbers, &error);
if (error != NULL)
errx(1, "%s", error);
return d;
}
#ifdef KERN_DRIVERS
static void
get_device_info(void)
{
static int mib[2] = {CTL_KERN, KERN_DRIVERS};
size_t len;
if (sysctl(mib, 2, NULL, &len, NULL, 0) != 0)
err(1, "kern.drivers" );
kern_drivers = malloc(len);
if (kern_drivers == NULL)
err(1, "malloc");
if (sysctl(mib, 2, kern_drivers, &len, NULL, 0) != 0)
err(1, "kern.drivers" );
num_drivers = len / sizeof *kern_drivers;
}
static void
print_device_info(char **names)
{
int i;
struct kinfo_drivers *kd;
if (kern_drivers == NULL)
get_device_info();
do {
kd = kern_drivers;
for (i = 0; i < num_drivers; kd++, i++) {
if (*names && strcmp(*names, kd->d_name))
continue;
printf("%s", kd->d_name);
if (kd->d_cmajor != -1)
printf(" character major %d", kd->d_cmajor);
if (kd->d_bmajor != -1)
printf(" block major %d", kd->d_bmajor);
printf("\n");
}
} while (*names && *++names);
}
static int
major_from_name(const char *name, mode_t mode)
{
int i;
struct kinfo_drivers *kd;
if (kern_drivers == NULL)
get_device_info();
kd = kern_drivers;
for (i = 0; i < num_drivers; kd++, i++) {
if (strcmp(name, kd->d_name))
continue;
if (S_ISCHR(mode))
return kd->d_cmajor;
return kd->d_bmajor;
}
return -1;
}
#endif

290
sbin/mknod/pack_dev.c Normal file
View File

@@ -0,0 +1,290 @@
/* $NetBSD: pack_dev.c,v 1.11 2011/08/27 18:37:41 joerg Exp $ */
/*-
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Charles M. Hannum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: pack_dev.c,v 1.11 2011/08/27 18:37:41 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "pack_dev.h"
static pack_t pack_netbsd;
static pack_t pack_freebsd;
static pack_t pack_8_8;
static pack_t pack_12_20;
static pack_t pack_14_18;
static pack_t pack_8_24;
static pack_t pack_bsdos;
static int compare_format(const void *, const void *);
static const char iMajorError[] = "invalid major number";
static const char iMinorError[] = "invalid minor number";
static const char tooManyFields[] = "too many fields for format";
/* exported */
portdev_t
pack_native(int n, u_long numbers[], const char **error)
{
portdev_t dev = 0;
if (n == 2) {
dev = makedev(numbers[0], numbers[1]);
if ((u_long)major(dev) != numbers[0])
*error = iMajorError;
else if ((u_long)minor(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
static portdev_t
pack_netbsd(int n, u_long numbers[], const char **error)
{
portdev_t dev = 0;
if (n == 2) {
dev = makedev_netbsd(numbers[0], numbers[1]);
if ((u_long)major_netbsd(dev) != numbers[0])
*error = iMajorError;
else if ((u_long)minor_netbsd(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8))
#define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0))
#define makedev_freebsd(x,y) ((portdev_t)((((x) << 8) & 0x0000ff00) | \
(((y) << 0) & 0xffff00ff)))
static portdev_t
pack_freebsd(int n, u_long numbers[], const char **error)
{
portdev_t dev = 0;
if (n == 2) {
dev = makedev_freebsd(numbers[0], numbers[1]);
if ((u_long)major_freebsd(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_freebsd(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8))
#define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0))
#define makedev_8_8(x,y) ((portdev_t)((((x) << 8) & 0x0000ff00) | \
(((y) << 0) & 0x000000ff)))
static portdev_t
pack_8_8(int n, u_long numbers[], const char **error)
{
portdev_t dev = 0;
if (n == 2) {
dev = makedev_8_8(numbers[0], numbers[1]);
if ((u_long)major_8_8(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_8_8(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20))
#define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0))
#define makedev_12_20(x,y) ((portdev_t)((((x) << 20) & 0xfff00000) | \
(((y) << 0) & 0x000fffff)))
static portdev_t
pack_12_20(int n, u_long numbers[], const char **error)
{
portdev_t dev = 0;
if (n == 2) {
dev = makedev_12_20(numbers[0], numbers[1]);
if ((u_long)major_12_20(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_12_20(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18))
#define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0))
#define makedev_14_18(x,y) ((portdev_t)((((x) << 18) & 0xfffc0000) | \
(((y) << 0) & 0x0003ffff)))
static portdev_t
pack_14_18(int n, u_long numbers[], const char **error)
{
portdev_t dev = 0;
if (n == 2) {
dev = makedev_14_18(numbers[0], numbers[1]);
if ((u_long)major_14_18(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_14_18(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24))
#define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0))
#define makedev_8_24(x,y) ((portdev_t)((((x) << 24) & 0xff000000) | \
(((y) << 0) & 0x00ffffff)))
static portdev_t
pack_8_24(int n, u_long numbers[], const char **error)
{
portdev_t dev = 0;
if (n == 2) {
dev = makedev_8_24(numbers[0], numbers[1]);
if ((u_long)major_8_24(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_8_24(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20))
#define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8))
#define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0))
#define makedev_12_12_8(x,y,z) ((portdev_t)((((x) << 20) & 0xfff00000) | \
(((y) << 8) & 0x000fff00) | \
(((z) << 0) & 0x000000ff)))
static portdev_t
pack_bsdos(int n, u_long numbers[], const char **error)
{
portdev_t dev = 0;
if (n == 2) {
dev = makedev_12_20(numbers[0], numbers[1]);
if ((u_long)major_12_20(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_12_20(dev) != numbers[1])
*error = iMinorError;
} else if (n == 3) {
dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]);
if ((u_long)major_12_12_8(dev) != numbers[0])
*error = iMajorError;
if ((u_long)unit_12_12_8(dev) != numbers[1])
*error = "invalid unit number";
if ((u_long)subunit_12_12_8(dev) != numbers[2])
*error = "invalid subunit number";
} else
*error = tooManyFields;
return (dev);
}
/* list of formats and pack functions */
/* this list must be sorted lexically */
static struct format {
const char *name;
pack_t *pack;
} formats[] = {
{"386bsd", pack_8_8},
{"4bsd", pack_8_8},
{"bsdos", pack_bsdos},
{"freebsd", pack_freebsd},
{"hpux", pack_8_24},
{"isc", pack_8_8},
{"linux", pack_8_8},
{"native", pack_native},
{"netbsd", pack_netbsd},
{"osf1", pack_12_20},
{"sco", pack_8_8},
{"solaris", pack_14_18},
{"sunos", pack_8_8},
{"svr3", pack_8_8},
{"svr4", pack_14_18},
{"ultrix", pack_8_8},
};
static int
compare_format(const void *key, const void *element)
{
const char *name;
const struct format *format;
name = key;
format = element;
return (strcmp(name, format->name));
}
pack_t *
pack_find(const char *name)
{
struct format *format;
format = bsearch(name, formats,
sizeof(formats)/sizeof(formats[0]),
sizeof(formats[0]), compare_format);
if (format == 0)
return (NULL);
return (format->pack);
}

52
sbin/mknod/pack_dev.h Normal file
View File

@@ -0,0 +1,52 @@
/* $NetBSD: pack_dev.h,v 1.7 2008/04/28 20:23:09 martin Exp $ */
/*-
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Charles M. Hannum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _PACK_DEV_H
#define _PACK_DEV_H
#ifdef __CYGWIN__
typedef __dev32_t portdev_t;
#else
typedef dev_t portdev_t;
#endif
typedef portdev_t pack_t(int, u_long [], const char **);
pack_t *pack_find(const char *);
pack_t pack_native;
#define major_netbsd(x) ((int32_t)((((x) & 0x000fff00) >> 8)))
#define minor_netbsd(x) ((int32_t)((((x) & 0xfff00000) >> 12) | \
(((x) & 0x000000ff) >> 0)))
#define makedev_netbsd(x,y) ((dev_t)((((x) << 8) & 0x000fff00) | \
(((y) << 12) & 0xfff00000) | \
(((y) << 0) & 0x000000ff)))
#endif /* _PACK_DEV_H */