blob: 999b99331f4a86113b95f288eb4e8add9d5224bd [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Eric Andersen3d925622005-06-09 10:16:02 +00002
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include <fcntl.h>
Eric Andersen3d925622005-06-09 10:16:02 +00007#include <time.h>
Eric Andersen54e57da2005-07-18 09:42:37 +00008#include <ctype.h>
Eric Andersen3d925622005-06-09 10:16:02 +00009#include <unistd.h>
10#include <sys/types.h>
11#include <sys/sysmacros.h> /* major() and minor() */
12#include "busybox.h"
13
14#ifdef CONFIG_FEATURE_MAKEDEVS_LEAF
Eric Andersencc8ed391999-10-05 16:24:54 +000015/*
16 * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
Eric Andersenc7bda1c2004-03-15 08:29:22 +000017 *
Eric Andersencc8ed391999-10-05 16:24:54 +000018 * makedevs
Eric Andersenc7bda1c2004-03-15 08:29:22 +000019 * Make ranges of device files quickly.
Eric Andersencc8ed391999-10-05 16:24:54 +000020 * known bugs: can't deal with alpha ranges
21 */
Erik Andersene49d5ec2000-02-08 19:58:47 +000022int makedevs_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +000023{
Eric Andersen36006022002-06-08 12:44:17 +000024 mode_t mode;
25 char *basedev, *type, *nodname, buf[255];
Eric Andersen4f807a82004-07-26 09:11:12 +000026 int Smajor, Sminor, S, E;
Eric Andersencc8ed391999-10-05 16:24:54 +000027
Erik Andersen5e1189e2000-04-15 16:34:54 +000028 if (argc < 7 || *argv[1]=='-')
Manuel Novoa III cad53642003-03-19 09:13:01 +000029 bb_show_usage();
Erik Andersen5e1189e2000-04-15 16:34:54 +000030
Eric Andersen19732c62002-04-13 14:26:44 +000031 basedev = argv[1];
32 type = argv[2];
Eric Andersencbcdbc42004-07-30 17:48:21 +000033 Smajor = atoi(argv[3]);
34 Sminor = atoi(argv[4]);
Eric Andersen19732c62002-04-13 14:26:44 +000035 S = atoi(argv[5]);
36 E = atoi(argv[6]);
Eric Andersen36006022002-06-08 12:44:17 +000037 nodname = argc == 8 ? basedev : buf;
38
39 mode = 0660;
Eric Andersen19732c62002-04-13 14:26:44 +000040
Eric Andersencc8ed391999-10-05 16:24:54 +000041 switch (type[0]) {
Erik Andersene49d5ec2000-02-08 19:58:47 +000042 case 'c':
Eric Andersen36006022002-06-08 12:44:17 +000043 mode |= S_IFCHR;
Erik Andersene49d5ec2000-02-08 19:58:47 +000044 break;
45 case 'b':
Eric Andersen36006022002-06-08 12:44:17 +000046 mode |= S_IFBLK;
Erik Andersene49d5ec2000-02-08 19:58:47 +000047 break;
48 case 'f':
Eric Andersen36006022002-06-08 12:44:17 +000049 mode |= S_IFIFO;
Erik Andersene49d5ec2000-02-08 19:58:47 +000050 break;
51 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +000052 bb_show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +000053 }
Eric Andersencc8ed391999-10-05 16:24:54 +000054
Erik Andersene49d5ec2000-02-08 19:58:47 +000055 while (S <= E) {
Eric Andersen36006022002-06-08 12:44:17 +000056 int sz;
Erik Andersene49d5ec2000-02-08 19:58:47 +000057
Eric Andersen36006022002-06-08 12:44:17 +000058 sz = snprintf(buf, sizeof(buf), "%s%d", basedev, S);
59 if(sz<0 || sz>=sizeof(buf)) /* libc different */
Manuel Novoa III cad53642003-03-19 09:13:01 +000060 bb_error_msg_and_die("%s too large", basedev);
Erik Andersene49d5ec2000-02-08 19:58:47 +000061
Eric Andersen36006022002-06-08 12:44:17 +000062 /* if mode != S_IFCHR and != S_IFBLK third param in mknod() ignored */
Erik Andersene49d5ec2000-02-08 19:58:47 +000063
Eric Andersene71e7602004-07-30 14:36:37 +000064 if (mknod(nodname, mode, makedev(Smajor, Sminor)))
Manuel Novoa III cad53642003-03-19 09:13:01 +000065 bb_error_msg("Failed to create: %s", nodname);
Erik Andersene49d5ec2000-02-08 19:58:47 +000066
Eric Andersen36006022002-06-08 12:44:17 +000067 if (nodname == basedev) /* ex. /dev/hda - to /dev/hda1 ... */
68 nodname = buf;
Erik Andersene49d5ec2000-02-08 19:58:47 +000069 S++;
70 Sminor++;
Eric Andersencc8ed391999-10-05 16:24:54 +000071 }
72
Erik Andersene49d5ec2000-02-08 19:58:47 +000073 return 0;
Eric Andersencc8ed391999-10-05 16:24:54 +000074}
75
Eric Andersen3d925622005-06-09 10:16:02 +000076#elif defined CONFIG_FEATURE_MAKEDEVS_TABLE
77
Rob Landley1b751c82005-10-28 09:24:33 +000078/* Licensed under the GPL v2 or later, see the file LICENSE in this tarball. */
Eric Andersencc8ed391999-10-05 16:24:54 +000079
Rob Landleydfba7412006-03-06 20:47:33 +000080int makedevs_main(int argc, char **argv)
Eric Andersen3d925622005-06-09 10:16:02 +000081{
Eric Andersene8614db2005-07-18 09:28:36 +000082 FILE *table = stdin;
83 char *rootdir = NULL;
84 char *line = NULL;
85 int linenum = 0;
Eric Andersen3d925622005-06-09 10:16:02 +000086 int ret = EXIT_SUCCESS;
Eric Andersencc8ed391999-10-05 16:24:54 +000087
Rob Landley1b751c82005-10-28 09:24:33 +000088 unsigned long flags;
Bernhard Reutner-Fischer17329742005-12-21 15:07:30 +000089 flags = bb_getopt_ulflags(argc, argv, "d:", &line);
Rob Landley1b751c82005-10-28 09:24:33 +000090 if (line)
91 table = bb_xfopen(line, "r");
Eric Andersen3d925622005-06-09 10:16:02 +000092
Eric Andersene8614db2005-07-18 09:28:36 +000093 if (optind >= argc || (rootdir=argv[optind])==NULL) {
Eric Andersen2ada89b2005-07-18 09:45:35 +000094 bb_error_msg_and_die("root directory not specified");
Eric Andersene8614db2005-07-18 09:28:36 +000095 }
96
97 if (chdir(rootdir) != 0) {
Eric Andersen2ada89b2005-07-18 09:45:35 +000098 bb_perror_msg_and_die("could not chdir to %s", rootdir);
Eric Andersen3d925622005-06-09 10:16:02 +000099 }
100
101 umask(0);
102
Eric Andersene8614db2005-07-18 09:28:36 +0000103 printf("rootdir=%s\n", rootdir);
104 if (line) {
105 printf("table='%s'\n", line);
106 } else {
107 printf("table=<stdin>\n");
108 }
109
Eric Andersen3d925622005-06-09 10:16:02 +0000110 while ((line = bb_get_chomped_line_from_file(table))) {
111 char type;
112 unsigned int mode = 0755;
113 unsigned int major = 0;
114 unsigned int minor = 0;
115 unsigned int count = 0;
116 unsigned int increment = 0;
117 unsigned int start = 0;
118 char name[41];
119 char user[41];
120 char group[41];
121 char *full_name;
122 uid_t uid;
123 gid_t gid;
124
Eric Andersene8614db2005-07-18 09:28:36 +0000125 linenum++;
126
Eric Andersen3d925622005-06-09 10:16:02 +0000127 if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u", name,
Eric Andersene8614db2005-07-18 09:28:36 +0000128 &type, &mode, user, group, &major,
129 &minor, &start, &increment, &count)) ||
130 ((major | minor | start | count | increment) > 255))
131 {
132 if (*line=='\0' || *line=='#' || isspace(*line))
133 continue;
134 bb_error_msg("line %d invalid: '%s'\n", linenum, line);
Eric Andersen3d925622005-06-09 10:16:02 +0000135 ret = EXIT_FAILURE;
136 continue;
137 }
138 if (name[0] == '#') {
139 continue;
140 }
Bernhard Reutner-Fischer17329742005-12-21 15:07:30 +0000141
142 gid = (*group) ? get_ug_id(group, bb_xgetgrnam) : getgid();
143 uid = (*user) ? get_ug_id(user, bb_xgetpwnam) : getuid();
Eric Andersen3d925622005-06-09 10:16:02 +0000144 full_name = concat_path_file(rootdir, name);
145
146 if (type == 'd') {
Eric Andersene8614db2005-07-18 09:28:36 +0000147 bb_make_directory(full_name, mode | S_IFDIR, FILEUTILS_RECUR);
Eric Andersen3d925622005-06-09 10:16:02 +0000148 if (chown(full_name, uid, gid) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000149 bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
Eric Andersen3d925622005-06-09 10:16:02 +0000150 ret = EXIT_FAILURE;
151 goto loop;
152 }
Eric Andersen90161c92005-07-18 22:40:59 +0000153 if ((mode != -1) && (chmod(full_name, mode) < 0)){
154 bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
155 ret = EXIT_FAILURE;
156 goto loop;
157 }
158 } else if (type == 'f') {
159 struct stat st;
160 if ((stat(full_name, &st) < 0 || !S_ISREG(st.st_mode))) {
161 bb_perror_msg("line %d: regular file '%s' does not exist", linenum, full_name);
162 ret = EXIT_FAILURE;
163 goto loop;
164 }
165 if (chown(full_name, uid, gid) == -1) {
166 bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
167 ret = EXIT_FAILURE;
168 goto loop;
169 }
170 if ((mode != -1) && (chmod(full_name, mode) < 0)){
171 bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
172 ret = EXIT_FAILURE;
173 goto loop;
174 }
175 } else
176 {
Eric Andersen3d925622005-06-09 10:16:02 +0000177 dev_t rdev;
178
179 if (type == 'p') {
180 mode |= S_IFIFO;
181 }
182 else if (type == 'c') {
183 mode |= S_IFCHR;
184 }
185 else if (type == 'b') {
186 mode |= S_IFBLK;
187 } else {
Eric Andersen2ada89b2005-07-18 09:45:35 +0000188 bb_error_msg("line %d: unsupported file type %c", linenum, type);
Eric Andersen3d925622005-06-09 10:16:02 +0000189 ret = EXIT_FAILURE;
190 goto loop;
191 }
192
193 if (count > 0) {
194 int i;
195 char *full_name_inc;
196
197 full_name_inc = xmalloc(strlen(full_name) + 4);
198 for (i = start; i < count; i++) {
199 sprintf(full_name_inc, "%s%d", full_name, i);
200 rdev = (major << 8) + minor + (i * increment - start);
201 if (mknod(full_name_inc, mode, rdev) == -1) {
Eric Andersen2ada89b2005-07-18 09:45:35 +0000202 bb_perror_msg("line %d: could not create node %s", linenum, full_name_inc);
Eric Andersen3d925622005-06-09 10:16:02 +0000203 ret = EXIT_FAILURE;
204 }
205 else if (chown(full_name_inc, uid, gid) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000206 bb_perror_msg("line %d: chown failed for %s", linenum, full_name_inc);
Eric Andersen3d925622005-06-09 10:16:02 +0000207 ret = EXIT_FAILURE;
208 }
Eric Andersen90161c92005-07-18 22:40:59 +0000209 if ((mode != -1) && (chmod(full_name_inc, mode) < 0)){
210 bb_perror_msg("line %d: chmod failed for %s", linenum, full_name_inc);
211 ret = EXIT_FAILURE;
212 }
Eric Andersen3d925622005-06-09 10:16:02 +0000213 }
214 free(full_name_inc);
215 } else {
216 rdev = (major << 8) + minor;
217 if (mknod(full_name, mode, rdev) == -1) {
Eric Andersen2ada89b2005-07-18 09:45:35 +0000218 bb_perror_msg("line %d: could not create node %s", linenum, full_name);
Eric Andersen3d925622005-06-09 10:16:02 +0000219 ret = EXIT_FAILURE;
220 }
221 else if (chown(full_name, uid, gid) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000222 bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
Eric Andersen3d925622005-06-09 10:16:02 +0000223 ret = EXIT_FAILURE;
224 }
Eric Andersen90161c92005-07-18 22:40:59 +0000225 if ((mode != -1) && (chmod(full_name, mode) < 0)){
226 bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
227 ret = EXIT_FAILURE;
228 }
Eric Andersen3d925622005-06-09 10:16:02 +0000229 }
230 }
231loop:
232 free(line);
233 free(full_name);
234 }
235 fclose(table);
236
237 return 0;
Eric Andersencc8ed391999-10-05 16:24:54 +0000238}
Eric Andersene8614db2005-07-18 09:28:36 +0000239
Eric Andersen3d925622005-06-09 10:16:02 +0000240#else
Bernhard Reutner-Fischer771b1862006-03-24 14:30:05 +0000241# error makedevs configuration error, either leaf or table must be selected
Eric Andersen3d925622005-06-09 10:16:02 +0000242#endif