File indexing completed on 2025-05-11 08:24:19
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #ifdef HAVE_CONFIG_H
0033 #include "config.h"
0034 #endif
0035
0036 #if HAVE_NBTOOL_CONFIG_H
0037 #include "nbtool_config.h"
0038 #endif
0039
0040 #if 0
0041 #ifndef lint
0042 __COPYRIGHT("@(#) Copyright (c) 1998\
0043 The NetBSD Foundation, Inc. All rights reserved.");
0044 __RCSID("$NetBSD: mknod.c,v 1.39 2009/02/13 01:37:23 lukem Exp $");
0045 #endif
0046 #endif
0047
0048 #include <rtems.h>
0049 #include <rtems/shell.h>
0050 #include <rtems/shellconfig.h>
0051 #define __need_getopt_newlib
0052 #include <getopt.h>
0053
0054 #include <sys/cdefs.h>
0055
0056 #include <sys/types.h>
0057 #include <sys/stat.h>
0058 #include <sys/param.h>
0059 #if !HAVE_NBTOOL_CONFIG_H && defined(KERN_DRIVERS)
0060 #include <sys/sysctl.h>
0061 #endif
0062
0063 #include "err.h"
0064 #include <errno.h>
0065 #include <limits.h>
0066 #include <stdio.h>
0067 #include <stdlib.h>
0068 #include <unistd.h>
0069 #include <pwd.h>
0070 #include <grp.h>
0071 #include <string.h>
0072 #include <ctype.h>
0073
0074 #include "mknod-pack_dev.h"
0075
0076 #include <setjmp.h>
0077
0078 typedef struct {
0079 int exit_code;
0080 jmp_buf exit_jmp;
0081 } rtems_shell_mknod_globals;
0082
0083 #define exit_jump &(globals->exit_jmp)
0084
0085 #define exit(ec) rtems_shell_mknod_exit(globals, ec)
0086
0087 static int gid_name(const char *, gid_t *);
0088 static portdev_t callPack(rtems_shell_mknod_globals* globals,
0089 pack_t *, int, u_long *);
0090
0091 static int main_mknod(rtems_shell_mknod_globals*, int, char *[]);
0092 static void usage(rtems_shell_mknod_globals* );
0093
0094 static void
0095 rtems_shell_mknod_exit (rtems_shell_mknod_globals* globals, int code)
0096 {
0097 globals->exit_code = code;
0098 longjmp (globals->exit_jmp, 1);
0099 }
0100
0101 #include "mknod-pack_dev.c"
0102
0103 static int
0104 rtems_shell_main_mknod(int argc, char *argv[])
0105 {
0106 rtems_shell_mknod_globals mknod_globals;
0107 rtems_shell_mknod_globals* globals = &mknod_globals;
0108 memset (globals, 0, sizeof (mknod_globals));
0109 mknod_globals.exit_code = 1;
0110 if (setjmp (mknod_globals.exit_jmp) == 0)
0111 return main_mknod (globals, argc, argv);
0112 return mknod_globals.exit_code;
0113 }
0114
0115 #define getprogname() "mknod"
0116
0117 #ifdef KERN_DRIVERS
0118 #error invalid for RTEMS
0119 static struct kinfo_drivers *kern_drivers;
0120 static int num_drivers;
0121
0122 static void get_device_info(void);
0123 static void print_device_info(char **);
0124 static int major_from_name(const char *, mode_t);
0125 #endif
0126
0127 #define MAXARGS 3
0128
0129 int
0130 main_mknod(rtems_shell_mknod_globals* globals, int argc, char **argv)
0131 {
0132 char *name, *p;
0133 mode_t mode;
0134 portdev_t dev;
0135 pack_t *pack;
0136 u_long numbers[MAXARGS];
0137 int n, ch, fifo, hasformat;
0138 int r_flag = 0;
0139 #ifdef KERN_DRIVERS
0140 int l_flag = 0;
0141 int major;
0142 #endif
0143 #if RTEMS_REMOVED
0144 void *modes = 0;
0145 #endif
0146 uid_t uid = -1;
0147 gid_t gid = -1;
0148 int rval;
0149
0150 struct getopt_data getopt_reent;
0151 memset(&getopt_reent, 0, sizeof(getopt_data));
0152
0153 dev = 0;
0154 fifo = hasformat = 0;
0155 pack = pack_native;
0156
0157 #ifdef KERN_DRIVERS
0158 while ((ch = getopt(argc, argv, "lrRF:g:m:u:")) != -1) {
0159 #else
0160 while ((ch = getopt_r(argc, argv, "rRF:g:m:u:", &getopt_reent)) != -1) {
0161 #endif
0162 switch (ch) {
0163
0164 #ifdef KERN_DRIVERS
0165 case 'l':
0166 l_flag = 1;
0167 break;
0168 #endif
0169
0170 case 'r':
0171 r_flag = 1;
0172 break;
0173
0174 case 'R':
0175 r_flag = 2;
0176 break;
0177
0178 case 'F':
0179 pack = pack_find(getopt_reent.optarg);
0180 if (pack == NULL)
0181 errx(exit_jump, 1, "invalid format: %s", getopt_reent.optarg);
0182 hasformat++;
0183 break;
0184
0185 case 'g':
0186 if (getopt_reent.optarg[0] == '#') {
0187 gid = strtol(getopt_reent.optarg + 1, &p, 10);
0188 if (*p == 0)
0189 break;
0190 }
0191 if (gid_name(getopt_reent.optarg, &gid) == 0)
0192 break;
0193 gid = strtol(getopt_reent.optarg, &p, 10);
0194 if (*p == 0)
0195 break;
0196 errx(exit_jump, 1, "%s: invalid group name", getopt_reent.optarg);
0197
0198 case 'm':
0199 #if RTEMS_REMOVED
0200 modes = setmode(getopt_reent.optarg);
0201 if (modes == NULL)
0202 #endif
0203 err(exit_jump, 1, "Cannot set file mode `%s'", getopt_reent.optarg);
0204 break;
0205
0206 case 'u':
0207 if (getopt_reent.optarg[0] == '#') {
0208 uid = strtol(getopt_reent.optarg + 1, &p, 10);
0209 if (*p == 0)
0210 break;
0211 }
0212 #if RTEMS_REMOVED
0213 if (uid_from_user(getopt_reent.optarg, &uid) == 0)
0214 break;
0215 #endif
0216 uid = strtol(getopt_reent.optarg, &p, 10);
0217 if (*p == 0)
0218 break;
0219 errx(exit_jump, 1, "%s: invalid user name", getopt_reent.optarg);
0220
0221 default:
0222 case '?':
0223 usage(globals);
0224 }
0225 }
0226 argc -= getopt_reent.optind;
0227 argv += getopt_reent.optind;
0228
0229 #ifdef KERN_DRIVERS
0230 if (l_flag) {
0231 print_device_info(argv);
0232 return 0;
0233 }
0234 #endif
0235
0236 if (argc < 2 || argc > 10)
0237 usage(globals);
0238
0239 name = *argv;
0240 argc--;
0241 argv++;
0242
0243 umask(mode = umask(0));
0244 mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) & ~mode;
0245
0246 if (argv[0][1] != '\0')
0247 goto badtype;
0248 switch (*argv[0]) {
0249 case 'c':
0250 mode |= S_IFCHR;
0251 break;
0252
0253 case 'b':
0254 mode |= S_IFBLK;
0255 break;
0256
0257 case 'p':
0258 if (hasformat)
0259 errx(exit_jump, 1, "format is meaningless for fifos");
0260 mode |= S_IFIFO;
0261 fifo = 1;
0262 break;
0263
0264 default:
0265 badtype:
0266 errx(exit_jump, 1, "node type must be 'b', 'c' or 'p'.");
0267 }
0268 argc--;
0269 argv++;
0270
0271 if (fifo) {
0272 if (argc != 0)
0273 usage(globals);
0274 } else {
0275 if (argc < 1 || argc > MAXARGS)
0276 usage(globals);
0277 }
0278
0279 for (n = 0; n < argc; n++) {
0280 errno = 0;
0281 numbers[n] = strtoul(argv[n], &p, 0);
0282 if (*p == 0 && errno == 0)
0283 continue;
0284 #ifdef KERN_DRIVERS
0285 if (n == 0) {
0286 major = major_from_name(argv[0], mode);
0287 if (major != -1) {
0288 numbers[0] = major;
0289 continue;
0290 }
0291 if (!isdigit(*(unsigned char *)argv[0]))
0292 errx(1, "unknown driver: %s", argv[0]);
0293 }
0294 #endif
0295 errx(exit_jump, 1, "invalid number: %s", argv[n]);
0296 }
0297
0298 switch (argc) {
0299 case 0:
0300 dev = 0;
0301 break;
0302
0303 case 1:
0304 dev = numbers[0];
0305 break;
0306
0307 default:
0308 dev = callPack(globals, pack, argc, numbers);
0309 break;
0310 }
0311
0312 #if RTEMS_REMOVED
0313 if (modes != NULL)
0314 mode = getmode(modes, mode);
0315 #endif
0316 umask(0);
0317 rval = fifo ? mkfifo(name, mode) : mknod(name, mode, dev);
0318 if (rval < 0 && errno == EEXIST && r_flag) {
0319 struct stat sb;
0320 if (lstat(name, &sb) != 0 || (!fifo && sb.st_rdev != dev))
0321 sb.st_mode = 0;
0322
0323 if ((sb.st_mode & S_IFMT) == (mode & S_IFMT)) {
0324 if (r_flag == 1)
0325
0326 return 0;
0327 if (sb.st_mode != mode)
0328 rval = chmod(name, mode);
0329 else
0330 rval = 0;
0331 } else {
0332 unlink(name);
0333 rval = fifo ? mkfifo(name, mode)
0334 : mknod(name, mode, dev);
0335 }
0336 }
0337 if (rval < 0)
0338 err(exit_jump, 1, "%s", name);
0339 if ((uid != (uid_t)-1 || gid != (uid_t)-1) && chown(name, uid, gid) == -1)
0340
0341 warn("%s: uid/gid not changed", name);
0342
0343 return 0;
0344 }
0345
0346 static void
0347 usage(rtems_shell_mknod_globals* globals)
0348 {
0349 const char *progname = getprogname();
0350
0351 (void)fprintf(stderr,
0352 "usage: %s [-rR] [-F format] [-m mode] [-u user] [-g group]\n",
0353 progname);
0354 (void)fprintf(stderr,
0355 #ifdef KERN_DRIVERS
0356 " [ name [b | c] [major | driver] minor\n"
0357 #else
0358 " [ name [b | c] major minor\n"
0359 #endif
0360 " | name [b | c] major unit subunit\n"
0361 " | name [b | c] number\n"
0362 " | name p ]\n");
0363 #ifdef KERN_DRIVERS
0364 (void)fprintf(stderr, " %s -l [driver] ...\n", progname);
0365 #endif
0366 exit(1);
0367 }
0368
0369 static int
0370 gid_name(const char *name, gid_t *gid)
0371 {
0372 struct group *g;
0373
0374 g = getgrnam(name);
0375 if (!g)
0376 return -1;
0377 *gid = g->gr_gid;
0378 return 0;
0379 }
0380
0381 static portdev_t
0382 callPack(rtems_shell_mknod_globals* globals, pack_t *f, int n, u_long *numbers)
0383 {
0384 portdev_t d;
0385 const char *error = NULL;
0386
0387 d = (*f)(n, numbers, &error);
0388 if (error != NULL)
0389 errx(exit_jump, 1, "%s", error);
0390 return d;
0391 }
0392
0393 #ifdef KERN_DRIVERS
0394 static void
0395 get_device_info(void)
0396 {
0397 static int mib[2] = {CTL_KERN, KERN_DRIVERS};
0398 size_t len;
0399
0400 if (sysctl(mib, 2, NULL, &len, NULL, 0) != 0)
0401 err(1, "kern.drivers" );
0402 kern_drivers = malloc(len);
0403 if (kern_drivers == NULL)
0404 err(1, "malloc");
0405 if (sysctl(mib, 2, kern_drivers, &len, NULL, 0) != 0)
0406 err(1, "kern.drivers" );
0407
0408 num_drivers = len / sizeof *kern_drivers;
0409 }
0410
0411 static void
0412 print_device_info(char **names)
0413 {
0414 int i;
0415 struct kinfo_drivers *kd;
0416
0417 if (kern_drivers == NULL)
0418 get_device_info();
0419
0420 do {
0421 kd = kern_drivers;
0422 for (i = 0; i < num_drivers; kd++, i++) {
0423 if (*names && strcmp(*names, kd->d_name))
0424 continue;
0425 printf("%s", kd->d_name);
0426 if (kd->d_cmajor != -1)
0427 printf(" character major %d", kd->d_cmajor);
0428 if (kd->d_bmajor != -1)
0429 printf(" block major %d", kd->d_bmajor);
0430 printf("\n");
0431 }
0432 } while (*names && *++names);
0433 }
0434
0435 static int
0436 major_from_name(const char *name, mode_t mode)
0437 {
0438 int i;
0439 struct kinfo_drivers *kd;
0440
0441 if (kern_drivers == NULL)
0442 get_device_info();
0443
0444 kd = kern_drivers;
0445 for (i = 0; i < num_drivers; kd++, i++) {
0446 if (strcmp(name, kd->d_name))
0447 continue;
0448 if (S_ISCHR(mode))
0449 return kd->d_cmajor;
0450 return kd->d_bmajor;
0451 }
0452 return -1;
0453 }
0454 #endif
0455
0456 rtems_shell_cmd_t rtems_shell_MKNOD_Command = {
0457 "mknod",
0458 "mknod mknod [-rR] [-F fmt] [-m mode] name [c | b] minor",
0459 "files",
0460 rtems_shell_main_mknod,
0461 NULL,
0462 NULL
0463 };