blob: e988400eb13cfc608d81a21c863115613e898112 [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) {
Eric Andersen2ada89b2005-07-18 09:45:35 +0000115 bb_error_msg_and_die("root directory not specified");
Eric Andersene8614db2005-07-18 09:28:36 +0000116 }
117
118 if (chdir(rootdir) != 0) {
Eric Andersen2ada89b2005-07-18 09:45:35 +0000119 bb_perror_msg_and_die("could not 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) {
Bernhard Reutner-Fischerd5bd1372005-09-20 21:06:17 +0000163 gid = get_ug_id(group, bb_xgetgrnam);
Eric Andersen3d925622005-06-09 10:16:02 +0000164 } else {
165 gid = getgid();
166 }
167 if (user) {
Bernhard Reutner-Fischerd5bd1372005-09-20 21:06:17 +0000168 uid = get_ug_id(user, bb_xgetpwnam);
Eric Andersen3d925622005-06-09 10:16:02 +0000169 } 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 }
Eric Andersen90161c92005-07-18 22:40:59 +0000181 if ((mode != -1) && (chmod(full_name, mode) < 0)){
182 bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
183 ret = EXIT_FAILURE;
184 goto loop;
185 }
186 } else if (type == 'f') {
187 struct stat st;
188 if ((stat(full_name, &st) < 0 || !S_ISREG(st.st_mode))) {
189 bb_perror_msg("line %d: regular file '%s' does not exist", linenum, full_name);
190 ret = EXIT_FAILURE;
191 goto loop;
192 }
193 if (chown(full_name, uid, gid) == -1) {
194 bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
195 ret = EXIT_FAILURE;
196 goto loop;
197 }
198 if ((mode != -1) && (chmod(full_name, mode) < 0)){
199 bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
200 ret = EXIT_FAILURE;
201 goto loop;
202 }
203 } else
204 {
Eric Andersen3d925622005-06-09 10:16:02 +0000205 dev_t rdev;
206
207 if (type == 'p') {
208 mode |= S_IFIFO;
209 }
210 else if (type == 'c') {
211 mode |= S_IFCHR;
212 }
213 else if (type == 'b') {
214 mode |= S_IFBLK;
215 } else {
Eric Andersen2ada89b2005-07-18 09:45:35 +0000216 bb_error_msg("line %d: unsupported file type %c", linenum, type);
Eric Andersen3d925622005-06-09 10:16:02 +0000217 ret = EXIT_FAILURE;
218 goto loop;
219 }
220
221 if (count > 0) {
222 int i;
223 char *full_name_inc;
224
225 full_name_inc = xmalloc(strlen(full_name) + 4);
226 for (i = start; i < count; i++) {
227 sprintf(full_name_inc, "%s%d", full_name, i);
228 rdev = (major << 8) + minor + (i * increment - start);
229 if (mknod(full_name_inc, mode, rdev) == -1) {
Eric Andersen2ada89b2005-07-18 09:45:35 +0000230 bb_perror_msg("line %d: could not create node %s", linenum, full_name_inc);
Eric Andersen3d925622005-06-09 10:16:02 +0000231 ret = EXIT_FAILURE;
232 }
233 else if (chown(full_name_inc, uid, gid) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000234 bb_perror_msg("line %d: chown failed for %s", linenum, full_name_inc);
Eric Andersen3d925622005-06-09 10:16:02 +0000235 ret = EXIT_FAILURE;
236 }
Eric Andersen90161c92005-07-18 22:40:59 +0000237 if ((mode != -1) && (chmod(full_name_inc, mode) < 0)){
238 bb_perror_msg("line %d: chmod failed for %s", linenum, full_name_inc);
239 ret = EXIT_FAILURE;
240 }
Eric Andersen3d925622005-06-09 10:16:02 +0000241 }
242 free(full_name_inc);
243 } else {
244 rdev = (major << 8) + minor;
245 if (mknod(full_name, mode, rdev) == -1) {
Eric Andersen2ada89b2005-07-18 09:45:35 +0000246 bb_perror_msg("line %d: could not create node %s", linenum, full_name);
Eric Andersen3d925622005-06-09 10:16:02 +0000247 ret = EXIT_FAILURE;
248 }
249 else if (chown(full_name, uid, gid) == -1) {
Eric Andersene8614db2005-07-18 09:28:36 +0000250 bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
Eric Andersen3d925622005-06-09 10:16:02 +0000251 ret = EXIT_FAILURE;
252 }
Eric Andersen90161c92005-07-18 22:40:59 +0000253 if ((mode != -1) && (chmod(full_name, mode) < 0)){
254 bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
255 ret = EXIT_FAILURE;
256 }
Eric Andersen3d925622005-06-09 10:16:02 +0000257 }
258 }
259loop:
260 free(line);
261 free(full_name);
262 }
263 fclose(table);
264
265 return 0;
Eric Andersencc8ed391999-10-05 16:24:54 +0000266}
Eric Andersene8614db2005-07-18 09:28:36 +0000267
Eric Andersen3d925622005-06-09 10:16:02 +0000268#else
269# error makdedevs configuration error, either leaf or table must be selected
270#endif