blob: ffcbe7ac362dd2d7b12d460148d4b33c8316d1cd [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>
Eric Andersen54e57da2005-07-18 09:42:37 +00009#include <ctype.h>
Eric Andersen3d925622005-06-09 10:16:02 +000010#include <unistd.h>
11#include <sys/types.h>
12#include <sys/sysmacros.h> /* major() and minor() */
13#include "busybox.h"
14
15#ifdef CONFIG_FEATURE_MAKEDEVS_LEAF
Eric Andersencc8ed391999-10-05 16:24:54 +000016/*
17 * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
Eric Andersenc7bda1c2004-03-15 08:29:22 +000018 *
Eric Andersencc8ed391999-10-05 16:24:54 +000019 * makedevs
Eric Andersenc7bda1c2004-03-15 08:29:22 +000020 * Make ranges of device files quickly.
Eric Andersencc8ed391999-10-05 16:24:54 +000021 * known bugs: can't deal with alpha ranges
22 */
Erik Andersene49d5ec2000-02-08 19:58:47 +000023int makedevs_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +000024{
Eric Andersen36006022002-06-08 12:44:17 +000025 mode_t mode;
26 char *basedev, *type, *nodname, buf[255];
Eric Andersen4f807a82004-07-26 09:11:12 +000027 int Smajor, Sminor, S, E;
Eric Andersencc8ed391999-10-05 16:24:54 +000028
Erik Andersen5e1189e2000-04-15 16:34:54 +000029 if (argc < 7 || *argv[1]=='-')
Manuel Novoa III cad53642003-03-19 09:13:01 +000030 bb_show_usage();
Erik Andersen5e1189e2000-04-15 16:34:54 +000031
Eric Andersen19732c62002-04-13 14:26:44 +000032 basedev = argv[1];
33 type = argv[2];
Eric Andersencbcdbc42004-07-30 17:48:21 +000034 Smajor = atoi(argv[3]);
35 Sminor = atoi(argv[4]);
Eric Andersen19732c62002-04-13 14:26:44 +000036 S = atoi(argv[5]);
37 E = atoi(argv[6]);
Eric Andersen36006022002-06-08 12:44:17 +000038 nodname = argc == 8 ? basedev : buf;
39
40 mode = 0660;
Eric Andersen19732c62002-04-13 14:26:44 +000041
Eric Andersencc8ed391999-10-05 16:24:54 +000042 switch (type[0]) {
Erik Andersene49d5ec2000-02-08 19:58:47 +000043 case 'c':
Eric Andersen36006022002-06-08 12:44:17 +000044 mode |= S_IFCHR;
Erik Andersene49d5ec2000-02-08 19:58:47 +000045 break;
46 case 'b':
Eric Andersen36006022002-06-08 12:44:17 +000047 mode |= S_IFBLK;
Erik Andersene49d5ec2000-02-08 19:58:47 +000048 break;
49 case 'f':
Eric Andersen36006022002-06-08 12:44:17 +000050 mode |= S_IFIFO;
Erik Andersene49d5ec2000-02-08 19:58:47 +000051 break;
52 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +000053 bb_show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +000054 }
Eric Andersencc8ed391999-10-05 16:24:54 +000055
Erik Andersene49d5ec2000-02-08 19:58:47 +000056 while (S <= E) {
Eric Andersen36006022002-06-08 12:44:17 +000057 int sz;
Erik Andersene49d5ec2000-02-08 19:58:47 +000058
Eric Andersen36006022002-06-08 12:44:17 +000059 sz = snprintf(buf, sizeof(buf), "%s%d", basedev, S);
60 if(sz<0 || sz>=sizeof(buf)) /* libc different */
Manuel Novoa III cad53642003-03-19 09:13:01 +000061 bb_error_msg_and_die("%s too large", basedev);
Erik Andersene49d5ec2000-02-08 19:58:47 +000062
Eric Andersen36006022002-06-08 12:44:17 +000063 /* if mode != S_IFCHR and != S_IFBLK third param in mknod() ignored */
Erik Andersene49d5ec2000-02-08 19:58:47 +000064
Eric Andersene71e7602004-07-30 14:36:37 +000065 if (mknod(nodname, mode, makedev(Smajor, Sminor)))
Manuel Novoa III cad53642003-03-19 09:13:01 +000066 bb_error_msg("Failed to create: %s", nodname);
Erik Andersene49d5ec2000-02-08 19:58:47 +000067
Eric Andersen36006022002-06-08 12:44:17 +000068 if (nodname == basedev) /* ex. /dev/hda - to /dev/hda1 ... */
69 nodname = buf;
Erik Andersene49d5ec2000-02-08 19:58:47 +000070 S++;
71 Sminor++;
Eric Andersencc8ed391999-10-05 16:24:54 +000072 }
73
Erik Andersene49d5ec2000-02-08 19:58:47 +000074 return 0;
Eric Andersencc8ed391999-10-05 16:24:54 +000075}
76
Eric Andersen3d925622005-06-09 10:16:02 +000077#elif defined CONFIG_FEATURE_MAKEDEVS_TABLE
78
Eric Andersencc8ed391999-10-05 16:24:54 +000079/*
Eric Andersen3d925622005-06-09 10:16:02 +000080 * This program is free software; you can redistribute it and/or modify
81 * it under the terms of the GNU General Public License version 2 as
82 * published by the Free Software Foundation.
83 *
84 * This program is distributed in the hope that it will be useful,
85 * but WITHOUT ANY WARRANTY; without even the implied warranty of
86 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
87 * GNU Library General Public License for more details.
88 *
89 * You should have received a copy of the GNU General Public License
90 * along with this program; if not, write to the Free Software
91 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
92 *
93 */
Eric Andersencc8ed391999-10-05 16:24:54 +000094
Eric Andersen3d925622005-06-09 10:16:02 +000095extern int makedevs_main(int argc, char **argv)
96{
Eric Andersen3d925622005-06-09 10:16:02 +000097 int opt;
Eric Andersene8614db2005-07-18 09:28:36 +000098 FILE *table = stdin;
99 char *rootdir = NULL;
100 char *line = NULL;
101 int linenum = 0;
Eric Andersen3d925622005-06-09 10:16:02 +0000102 int ret = EXIT_SUCCESS;
Eric Andersencc8ed391999-10-05 16:24:54 +0000103
Eric Andersene8614db2005-07-18 09:28:36 +0000104 while ((opt = getopt(argc, argv, "d:")) != -1) {
105 switch(opt) {
106 case 'd':
107 table = bb_xfopen((line=optarg), "r");
108 break;
109 default:
110 bb_show_usage();
111 }
Eric Andersen3d925622005-06-09 10:16:02 +0000112 }
113
Eric Andersene8614db2005-07-18 09:28:36 +0000114 if (optind >= argc || (rootdir=argv[optind])==NULL) {
115 bb_error_msg_and_die("root directory not speficied");
116 }
117
118 if (chdir(rootdir) != 0) {
119 bb_perror_msg_and_die("Couldnt chdir to %s", rootdir);
Eric Andersen3d925622005-06-09 10:16:02 +0000120 }
121
122 umask(0);
123
Eric Andersene8614db2005-07-18 09:28:36 +0000124 printf("rootdir=%s\n", rootdir);
125 if (line) {
126 printf("table='%s'\n", line);
127 } else {
128 printf("table=<stdin>\n");
129 }
130
Eric Andersen3d925622005-06-09 10:16:02 +0000131 while ((line = bb_get_chomped_line_from_file(table))) {
132 char type;
133 unsigned int mode = 0755;
134 unsigned int major = 0;
135 unsigned int minor = 0;
136 unsigned int count = 0;
137 unsigned int increment = 0;
138 unsigned int start = 0;
139 char name[41];
140 char user[41];
141 char group[41];
142 char *full_name;
143 uid_t uid;
144 gid_t gid;
145
Eric Andersene8614db2005-07-18 09:28:36 +0000146 linenum++;
147
Eric Andersen3d925622005-06-09 10:16:02 +0000148 if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u", name,
Eric Andersene8614db2005-07-18 09:28:36 +0000149 &type, &mode, user, group, &major,
150 &minor, &start, &increment, &count)) ||
151 ((major | minor | start | count | increment) > 255))
152 {
153 if (*line=='\0' || *line=='#' || isspace(*line))
154 continue;
155 bb_error_msg("line %d invalid: '%s'\n", linenum, line);
Eric Andersen3d925622005-06-09 10:16:02 +0000156 ret = EXIT_FAILURE;
157 continue;
158 }
159 if (name[0] == '#') {
160 continue;
161 }
162 if (group) {
163 gid = get_ug_id(group, my_getgrnam);
164 } else {
165 gid = getgid();
166 }
167 if (user) {
168 uid = get_ug_id(user, my_getpwnam);
169 } else {
170 uid = getuid();
171 }
172 full_name = concat_path_file(rootdir, name);
173
174 if (type == 'd') {
Eric Andersene8614db2005-07-18 09:28:36 +0000175 bb_make_directory(full_name, mode | S_IFDIR, FILEUTILS_RECUR);
Eric Andersen3d925622005-06-09 10:16:02 +0000176 if (chown(full_name, uid, gid) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000177 bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
Eric Andersen3d925622005-06-09 10:16:02 +0000178 ret = EXIT_FAILURE;
179 goto loop;
180 }
181 } else {
182 dev_t rdev;
183
184 if (type == 'p') {
185 mode |= S_IFIFO;
186 }
187 else if (type == 'c') {
188 mode |= S_IFCHR;
189 }
190 else if (type == 'b') {
191 mode |= S_IFBLK;
192 } else {
Eric Andersene8614db2005-07-18 09:28:36 +0000193 bb_error_msg("line %d: Unsupported file type %c", linenum, type);
Eric Andersen3d925622005-06-09 10:16:02 +0000194 ret = EXIT_FAILURE;
195 goto loop;
196 }
197
198 if (count > 0) {
199 int i;
200 char *full_name_inc;
201
202 full_name_inc = xmalloc(strlen(full_name) + 4);
203 for (i = start; i < count; i++) {
204 sprintf(full_name_inc, "%s%d", full_name, i);
205 rdev = (major << 8) + minor + (i * increment - start);
206 if (mknod(full_name_inc, mode, rdev) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000207 bb_perror_msg("line %d: Couldnt create node %s", linenum, full_name_inc);
Eric Andersen3d925622005-06-09 10:16:02 +0000208 ret = EXIT_FAILURE;
209 }
210 else if (chown(full_name_inc, uid, gid) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000211 bb_perror_msg("line %d: chown failed for %s", linenum, full_name_inc);
Eric Andersen3d925622005-06-09 10:16:02 +0000212 ret = EXIT_FAILURE;
213 }
214 }
215 free(full_name_inc);
216 } else {
217 rdev = (major << 8) + minor;
218 if (mknod(full_name, mode, rdev) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000219 bb_perror_msg("line %d: Couldnt create node %s", linenum, full_name);
Eric Andersen3d925622005-06-09 10:16:02 +0000220 ret = EXIT_FAILURE;
221 }
222 else if (chown(full_name, uid, gid) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000223 bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
Eric Andersen3d925622005-06-09 10:16:02 +0000224 ret = EXIT_FAILURE;
225 }
226 }
227 }
228loop:
229 free(line);
230 free(full_name);
231 }
232 fclose(table);
233
234 return 0;
Eric Andersencc8ed391999-10-05 16:24:54 +0000235}
Eric Andersene8614db2005-07-18 09:28:36 +0000236
Eric Andersen3d925622005-06-09 10:16:02 +0000237#else
238# error makdedevs configuration error, either leaf or table must be selected
239#endif