blob: 95889506fdb4dc86f22d93409c6d4f9f55532ac3 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Bernhard Reutner-Fischerd9cf7ac2006-04-12 18:39:58 +00002/*
3 * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
4 *
5 * makedevs
6 * Make ranges of device files quickly.
7 * known bugs: can't deal with alpha ranges
8 */
Eric Andersen3d925622005-06-09 10:16:02 +00009
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <fcntl.h>
Eric Andersen3d925622005-06-09 10:16:02 +000014#include <time.h>
Eric Andersen54e57da2005-07-18 09:42:37 +000015#include <ctype.h>
Eric Andersen3d925622005-06-09 10:16:02 +000016#include <unistd.h>
17#include <sys/types.h>
18#include <sys/sysmacros.h> /* major() and minor() */
19#include "busybox.h"
20
21#ifdef CONFIG_FEATURE_MAKEDEVS_LEAF
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
Bernhard Reutner-Fischerd9cf7ac2006-04-12 18:39:58 +000097 bb_xchdir(rootdir);
Eric Andersen3d925622005-06-09 10:16:02 +000098
99 umask(0);
100
Eric Andersene8614db2005-07-18 09:28:36 +0000101 printf("rootdir=%s\n", rootdir);
102 if (line) {
103 printf("table='%s'\n", line);
104 } else {
105 printf("table=<stdin>\n");
106 }
107
Eric Andersen3d925622005-06-09 10:16:02 +0000108 while ((line = bb_get_chomped_line_from_file(table))) {
109 char type;
110 unsigned int mode = 0755;
111 unsigned int major = 0;
112 unsigned int minor = 0;
113 unsigned int count = 0;
114 unsigned int increment = 0;
115 unsigned int start = 0;
116 char name[41];
117 char user[41];
118 char group[41];
119 char *full_name;
120 uid_t uid;
121 gid_t gid;
122
Eric Andersene8614db2005-07-18 09:28:36 +0000123 linenum++;
124
Eric Andersen3d925622005-06-09 10:16:02 +0000125 if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u", name,
Eric Andersene8614db2005-07-18 09:28:36 +0000126 &type, &mode, user, group, &major,
127 &minor, &start, &increment, &count)) ||
128 ((major | minor | start | count | increment) > 255))
129 {
130 if (*line=='\0' || *line=='#' || isspace(*line))
131 continue;
132 bb_error_msg("line %d invalid: '%s'\n", linenum, line);
Eric Andersen3d925622005-06-09 10:16:02 +0000133 ret = EXIT_FAILURE;
134 continue;
135 }
136 if (name[0] == '#') {
137 continue;
138 }
Bernhard Reutner-Fischer17329742005-12-21 15:07:30 +0000139
140 gid = (*group) ? get_ug_id(group, bb_xgetgrnam) : getgid();
141 uid = (*user) ? get_ug_id(user, bb_xgetpwnam) : getuid();
Eric Andersen3d925622005-06-09 10:16:02 +0000142 full_name = concat_path_file(rootdir, name);
143
144 if (type == 'd') {
Eric Andersene8614db2005-07-18 09:28:36 +0000145 bb_make_directory(full_name, mode | S_IFDIR, FILEUTILS_RECUR);
Eric Andersen3d925622005-06-09 10:16:02 +0000146 if (chown(full_name, uid, gid) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000147 bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
Eric Andersen3d925622005-06-09 10:16:02 +0000148 ret = EXIT_FAILURE;
149 goto loop;
150 }
Eric Andersen90161c92005-07-18 22:40:59 +0000151 if ((mode != -1) && (chmod(full_name, mode) < 0)){
152 bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
153 ret = EXIT_FAILURE;
154 goto loop;
155 }
156 } else if (type == 'f') {
157 struct stat st;
158 if ((stat(full_name, &st) < 0 || !S_ISREG(st.st_mode))) {
159 bb_perror_msg("line %d: regular file '%s' does not exist", linenum, full_name);
160 ret = EXIT_FAILURE;
161 goto loop;
162 }
163 if (chown(full_name, uid, gid) == -1) {
164 bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
165 ret = EXIT_FAILURE;
166 goto loop;
167 }
168 if ((mode != -1) && (chmod(full_name, mode) < 0)){
169 bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
170 ret = EXIT_FAILURE;
171 goto loop;
172 }
173 } else
174 {
Eric Andersen3d925622005-06-09 10:16:02 +0000175 dev_t rdev;
176
177 if (type == 'p') {
178 mode |= S_IFIFO;
179 }
180 else if (type == 'c') {
181 mode |= S_IFCHR;
182 }
183 else if (type == 'b') {
184 mode |= S_IFBLK;
185 } else {
Eric Andersen2ada89b2005-07-18 09:45:35 +0000186 bb_error_msg("line %d: unsupported file type %c", linenum, type);
Eric Andersen3d925622005-06-09 10:16:02 +0000187 ret = EXIT_FAILURE;
188 goto loop;
189 }
190
191 if (count > 0) {
192 int i;
193 char *full_name_inc;
194
195 full_name_inc = xmalloc(strlen(full_name) + 4);
196 for (i = start; i < count; i++) {
197 sprintf(full_name_inc, "%s%d", full_name, i);
198 rdev = (major << 8) + minor + (i * increment - start);
199 if (mknod(full_name_inc, mode, rdev) == -1) {
Eric Andersen2ada89b2005-07-18 09:45:35 +0000200 bb_perror_msg("line %d: could not create node %s", linenum, full_name_inc);
Eric Andersen3d925622005-06-09 10:16:02 +0000201 ret = EXIT_FAILURE;
202 }
203 else if (chown(full_name_inc, uid, gid) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000204 bb_perror_msg("line %d: chown failed for %s", linenum, full_name_inc);
Eric Andersen3d925622005-06-09 10:16:02 +0000205 ret = EXIT_FAILURE;
206 }
Eric Andersen90161c92005-07-18 22:40:59 +0000207 if ((mode != -1) && (chmod(full_name_inc, mode) < 0)){
208 bb_perror_msg("line %d: chmod failed for %s", linenum, full_name_inc);
209 ret = EXIT_FAILURE;
210 }
Eric Andersen3d925622005-06-09 10:16:02 +0000211 }
212 free(full_name_inc);
213 } else {
214 rdev = (major << 8) + minor;
215 if (mknod(full_name, mode, rdev) == -1) {
Eric Andersen2ada89b2005-07-18 09:45:35 +0000216 bb_perror_msg("line %d: could not create node %s", linenum, full_name);
Eric Andersen3d925622005-06-09 10:16:02 +0000217 ret = EXIT_FAILURE;
218 }
219 else if (chown(full_name, uid, gid) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000220 bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
Eric Andersen3d925622005-06-09 10:16:02 +0000221 ret = EXIT_FAILURE;
222 }
Eric Andersen90161c92005-07-18 22:40:59 +0000223 if ((mode != -1) && (chmod(full_name, mode) < 0)){
224 bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
225 ret = EXIT_FAILURE;
226 }
Eric Andersen3d925622005-06-09 10:16:02 +0000227 }
228 }
229loop:
230 free(line);
231 free(full_name);
232 }
233 fclose(table);
234
Bernhard Reutner-Fischer56fbd212006-04-24 17:41:29 +0000235 return ret;
Eric Andersencc8ed391999-10-05 16:24:54 +0000236}
Eric Andersene8614db2005-07-18 09:28:36 +0000237
Eric Andersen3d925622005-06-09 10:16:02 +0000238#else
Bernhard Reutner-Fischer771b1862006-03-24 14:30:05 +0000239# error makedevs configuration error, either leaf or table must be selected
Eric Andersen3d925622005-06-09 10:16:02 +0000240#endif