blob: eb3e3680d7fa6d81fb151f082e69d2731c7ac1c9 [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>
7#include <getopt.h>
8#include <time.h>
9#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
Eric Andersencc8ed391999-10-05 16:24:54 +000078/*
Eric Andersen3d925622005-06-09 10:16:02 +000079 * This program is free software; you can redistribute it and/or modify
80 * it under the terms of the GNU General Public License version 2 as
81 * published by the Free Software Foundation.
82 *
83 * This program is distributed in the hope that it will be useful,
84 * but WITHOUT ANY WARRANTY; without even the implied warranty of
85 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
86 * GNU Library General Public License for more details.
87 *
88 * You should have received a copy of the GNU General Public License
89 * along with this program; if not, write to the Free Software
90 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
91 *
92 */
Eric Andersencc8ed391999-10-05 16:24:54 +000093
Eric Andersen3d925622005-06-09 10:16:02 +000094extern int makedevs_main(int argc, char **argv)
95{
Eric Andersen3d925622005-06-09 10:16:02 +000096 int opt;
Eric Andersene8614db2005-07-18 09:28:36 +000097 FILE *table = stdin;
98 char *rootdir = NULL;
99 char *line = NULL;
100 int linenum = 0;
Eric Andersen3d925622005-06-09 10:16:02 +0000101 int ret = EXIT_SUCCESS;
Eric Andersencc8ed391999-10-05 16:24:54 +0000102
Eric Andersene8614db2005-07-18 09:28:36 +0000103 while ((opt = getopt(argc, argv, "d:")) != -1) {
104 switch(opt) {
105 case 'd':
106 table = bb_xfopen((line=optarg), "r");
107 break;
108 default:
109 bb_show_usage();
110 }
Eric Andersen3d925622005-06-09 10:16:02 +0000111 }
112
Eric Andersene8614db2005-07-18 09:28:36 +0000113 if (optind >= argc || (rootdir=argv[optind])==NULL) {
114 bb_error_msg_and_die("root directory not speficied");
115 }
116
117 if (chdir(rootdir) != 0) {
118 bb_perror_msg_and_die("Couldnt chdir to %s", rootdir);
Eric Andersen3d925622005-06-09 10:16:02 +0000119 }
120
121 umask(0);
122
Eric Andersene8614db2005-07-18 09:28:36 +0000123 printf("rootdir=%s\n", rootdir);
124 if (line) {
125 printf("table='%s'\n", line);
126 } else {
127 printf("table=<stdin>\n");
128 }
129
Eric Andersen3d925622005-06-09 10:16:02 +0000130 while ((line = bb_get_chomped_line_from_file(table))) {
131 char type;
132 unsigned int mode = 0755;
133 unsigned int major = 0;
134 unsigned int minor = 0;
135 unsigned int count = 0;
136 unsigned int increment = 0;
137 unsigned int start = 0;
138 char name[41];
139 char user[41];
140 char group[41];
141 char *full_name;
142 uid_t uid;
143 gid_t gid;
144
Eric Andersene8614db2005-07-18 09:28:36 +0000145 linenum++;
146
Eric Andersen3d925622005-06-09 10:16:02 +0000147 if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u", name,
Eric Andersene8614db2005-07-18 09:28:36 +0000148 &type, &mode, user, group, &major,
149 &minor, &start, &increment, &count)) ||
150 ((major | minor | start | count | increment) > 255))
151 {
152 if (*line=='\0' || *line=='#' || isspace(*line))
153 continue;
154 bb_error_msg("line %d invalid: '%s'\n", linenum, line);
Eric Andersen3d925622005-06-09 10:16:02 +0000155 ret = EXIT_FAILURE;
156 continue;
157 }
158 if (name[0] == '#') {
159 continue;
160 }
161 if (group) {
162 gid = get_ug_id(group, my_getgrnam);
163 } else {
164 gid = getgid();
165 }
166 if (user) {
167 uid = get_ug_id(user, my_getpwnam);
168 } else {
169 uid = getuid();
170 }
171 full_name = concat_path_file(rootdir, name);
172
173 if (type == 'd') {
Eric Andersene8614db2005-07-18 09:28:36 +0000174 bb_make_directory(full_name, mode | S_IFDIR, FILEUTILS_RECUR);
Eric Andersen3d925622005-06-09 10:16:02 +0000175 if (chown(full_name, uid, gid) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000176 bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
Eric Andersen3d925622005-06-09 10:16:02 +0000177 ret = EXIT_FAILURE;
178 goto loop;
179 }
180 } else {
181 dev_t rdev;
182
183 if (type == 'p') {
184 mode |= S_IFIFO;
185 }
186 else if (type == 'c') {
187 mode |= S_IFCHR;
188 }
189 else if (type == 'b') {
190 mode |= S_IFBLK;
191 } else {
Eric Andersene8614db2005-07-18 09:28:36 +0000192 bb_error_msg("line %d: Unsupported file type %c", linenum, type);
Eric Andersen3d925622005-06-09 10:16:02 +0000193 ret = EXIT_FAILURE;
194 goto loop;
195 }
196
197 if (count > 0) {
198 int i;
199 char *full_name_inc;
200
201 full_name_inc = xmalloc(strlen(full_name) + 4);
202 for (i = start; i < count; i++) {
203 sprintf(full_name_inc, "%s%d", full_name, i);
204 rdev = (major << 8) + minor + (i * increment - start);
205 if (mknod(full_name_inc, mode, rdev) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000206 bb_perror_msg("line %d: Couldnt create node %s", linenum, full_name_inc);
Eric Andersen3d925622005-06-09 10:16:02 +0000207 ret = EXIT_FAILURE;
208 }
209 else if (chown(full_name_inc, uid, gid) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000210 bb_perror_msg("line %d: chown failed for %s", linenum, full_name_inc);
Eric Andersen3d925622005-06-09 10:16:02 +0000211 ret = EXIT_FAILURE;
212 }
213 }
214 free(full_name_inc);
215 } else {
216 rdev = (major << 8) + minor;
217 if (mknod(full_name, mode, rdev) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000218 bb_perror_msg("line %d: Couldnt 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 }
225 }
226 }
227loop:
228 free(line);
229 free(full_name);
230 }
231 fclose(table);
232
233 return 0;
Eric Andersencc8ed391999-10-05 16:24:54 +0000234}
Eric Andersene8614db2005-07-18 09:28:36 +0000235
Eric Andersen3d925622005-06-09 10:16:02 +0000236#else
237# error makdedevs configuration error, either leaf or table must be selected
238#endif