1*9bcc1fc0SBob Badour /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2*9bcc1fc0SBob Badour * Use of this source code is governed by a BSD-style license that can be
3*9bcc1fc0SBob Badour * found in the LICENSE file.
4*9bcc1fc0SBob Badour *
5*9bcc1fc0SBob Badour * Driver for using rootdev.c from the commandline
6*9bcc1fc0SBob Badour */
7*9bcc1fc0SBob Badour #include <err.h>
8*9bcc1fc0SBob Badour #include <errno.h>
9*9bcc1fc0SBob Badour #include <getopt.h>
10*9bcc1fc0SBob Badour #include <linux/limits.h>
11*9bcc1fc0SBob Badour #include <stdbool.h>
12*9bcc1fc0SBob Badour #include <stdio.h>
13*9bcc1fc0SBob Badour #include <stdlib.h>
14*9bcc1fc0SBob Badour #include <string.h>
15*9bcc1fc0SBob Badour #include <sys/stat.h>
16*9bcc1fc0SBob Badour #include <sys/types.h>
17*9bcc1fc0SBob Badour #include <unistd.h>
18*9bcc1fc0SBob Badour
19*9bcc1fc0SBob Badour #include "rootdev.h"
20*9bcc1fc0SBob Badour
print_help(const char * progname)21*9bcc1fc0SBob Badour static void print_help(const char *progname) {
22*9bcc1fc0SBob Badour fprintf(stderr,
23*9bcc1fc0SBob Badour "%s [OPTIONS] [PATH]\n"
24*9bcc1fc0SBob Badour "Outputs the containing device for the specified PATH.\n"
25*9bcc1fc0SBob Badour "With no arguments, '/' is assumed.\n"
26*9bcc1fc0SBob Badour "\n"
27*9bcc1fc0SBob Badour "Options:\n"
28*9bcc1fc0SBob Badour " -h\tthis message.\n"
29*9bcc1fc0SBob Badour "\n"
30*9bcc1fc0SBob Badour " -c\tcreate the /dev node if it cannot be found\n"
31*9bcc1fc0SBob Badour " -d\treturn the block device only if possible\n"
32*9bcc1fc0SBob Badour " -i\treturn path even if the node doesn't exist\n"
33*9bcc1fc0SBob Badour " -s\tif possible, return the first slave of the root device\n"
34*9bcc1fc0SBob Badour "\n"
35*9bcc1fc0SBob Badour " --block [path]\tset the path to block under the sys mount point\n"
36*9bcc1fc0SBob Badour " --dev [path]\tset the path to dev mount point\n"
37*9bcc1fc0SBob Badour " --major [num]\tset the major number of the rootdev\n"
38*9bcc1fc0SBob Badour " --minor [num]\tset the minor number of the rootdev\n",
39*9bcc1fc0SBob Badour progname);
40*9bcc1fc0SBob Badour }
41*9bcc1fc0SBob Badour
42*9bcc1fc0SBob Badour static int flag_help = 0;
43*9bcc1fc0SBob Badour static int flag_use_slave = 0;
44*9bcc1fc0SBob Badour static int flag_strip_partition = 0;
45*9bcc1fc0SBob Badour static int flag_ignore = 0;
46*9bcc1fc0SBob Badour static int flag_create = 0;
47*9bcc1fc0SBob Badour static int flag_major = 0;
48*9bcc1fc0SBob Badour static int flag_minor = 0;
49*9bcc1fc0SBob Badour static const char *flag_path = "/";
50*9bcc1fc0SBob Badour static char *flag_block_path = NULL;
51*9bcc1fc0SBob Badour static char *flag_dev_path = NULL;
52*9bcc1fc0SBob Badour
parse_args(int argc,char ** argv)53*9bcc1fc0SBob Badour static void parse_args(int argc, char **argv) {
54*9bcc1fc0SBob Badour while (1) {
55*9bcc1fc0SBob Badour int c;
56*9bcc1fc0SBob Badour int option_index = 0;
57*9bcc1fc0SBob Badour static const struct option long_options[] = {
58*9bcc1fc0SBob Badour {"c", no_argument, &flag_create, 1},
59*9bcc1fc0SBob Badour {"d", no_argument, &flag_strip_partition, 1},
60*9bcc1fc0SBob Badour {"h", no_argument, &flag_help, 1},
61*9bcc1fc0SBob Badour {"i", no_argument, &flag_ignore, 1},
62*9bcc1fc0SBob Badour {"s", no_argument, &flag_use_slave, 1},
63*9bcc1fc0SBob Badour /* Long arguments for testing. */
64*9bcc1fc0SBob Badour {"block", required_argument, NULL, 'b'},
65*9bcc1fc0SBob Badour {"dev", required_argument, NULL, 'd'},
66*9bcc1fc0SBob Badour {"major", required_argument, NULL, 'M'},
67*9bcc1fc0SBob Badour {"minor", required_argument, NULL, 'm'},
68*9bcc1fc0SBob Badour {0, 0, 0, 0}
69*9bcc1fc0SBob Badour };
70*9bcc1fc0SBob Badour c = getopt_long_only(argc, argv, "", long_options, &option_index);
71*9bcc1fc0SBob Badour
72*9bcc1fc0SBob Badour if (c == -1)
73*9bcc1fc0SBob Badour break;
74*9bcc1fc0SBob Badour
75*9bcc1fc0SBob Badour if (c == '?') {
76*9bcc1fc0SBob Badour flag_help = 1;
77*9bcc1fc0SBob Badour break;
78*9bcc1fc0SBob Badour }
79*9bcc1fc0SBob Badour
80*9bcc1fc0SBob Badour switch (c) {
81*9bcc1fc0SBob Badour case 'b':
82*9bcc1fc0SBob Badour flag_block_path = optarg;
83*9bcc1fc0SBob Badour break;
84*9bcc1fc0SBob Badour case 'd':
85*9bcc1fc0SBob Badour flag_dev_path = optarg;
86*9bcc1fc0SBob Badour break;
87*9bcc1fc0SBob Badour case 'M':
88*9bcc1fc0SBob Badour flag_major = atoi(optarg);
89*9bcc1fc0SBob Badour break;
90*9bcc1fc0SBob Badour case 'm':
91*9bcc1fc0SBob Badour flag_minor = atoi(optarg);
92*9bcc1fc0SBob Badour break;
93*9bcc1fc0SBob Badour }
94*9bcc1fc0SBob Badour
95*9bcc1fc0SBob Badour }
96*9bcc1fc0SBob Badour
97*9bcc1fc0SBob Badour if (flag_create && flag_strip_partition) {
98*9bcc1fc0SBob Badour flag_help = 1;
99*9bcc1fc0SBob Badour warnx("-c and -d are incompatible at present.");
100*9bcc1fc0SBob Badour return;
101*9bcc1fc0SBob Badour }
102*9bcc1fc0SBob Badour
103*9bcc1fc0SBob Badour if (optind < argc) {
104*9bcc1fc0SBob Badour flag_path = argv[optind++];
105*9bcc1fc0SBob Badour }
106*9bcc1fc0SBob Badour
107*9bcc1fc0SBob Badour if (optind < argc) {
108*9bcc1fc0SBob Badour fprintf(stderr, "Too many free arguments: %d\n", argc - optind);
109*9bcc1fc0SBob Badour flag_help = 1;
110*9bcc1fc0SBob Badour }
111*9bcc1fc0SBob Badour }
112*9bcc1fc0SBob Badour
main(int argc,char ** argv)113*9bcc1fc0SBob Badour int main(int argc, char **argv) {
114*9bcc1fc0SBob Badour struct stat path_stat;
115*9bcc1fc0SBob Badour char path[PATH_MAX];
116*9bcc1fc0SBob Badour int ret;
117*9bcc1fc0SBob Badour dev_t root_dev;
118*9bcc1fc0SBob Badour parse_args(argc, argv);
119*9bcc1fc0SBob Badour
120*9bcc1fc0SBob Badour if (flag_help) {
121*9bcc1fc0SBob Badour print_help(argv[0]);
122*9bcc1fc0SBob Badour return 1;
123*9bcc1fc0SBob Badour }
124*9bcc1fc0SBob Badour
125*9bcc1fc0SBob Badour if (flag_major || flag_minor) {
126*9bcc1fc0SBob Badour root_dev = makedev(flag_major, flag_minor);
127*9bcc1fc0SBob Badour } else {
128*9bcc1fc0SBob Badour /* Yields the containing dev_t in st_dev. */
129*9bcc1fc0SBob Badour if (stat(flag_path, &path_stat) != 0)
130*9bcc1fc0SBob Badour err(1, "Cannot stat(%s)", flag_path);
131*9bcc1fc0SBob Badour root_dev = path_stat.st_dev;
132*9bcc1fc0SBob Badour }
133*9bcc1fc0SBob Badour
134*9bcc1fc0SBob Badour path[0] = '\0';
135*9bcc1fc0SBob Badour ret = rootdev_wrapper(path, sizeof(path),
136*9bcc1fc0SBob Badour flag_use_slave,
137*9bcc1fc0SBob Badour flag_strip_partition,
138*9bcc1fc0SBob Badour &root_dev,
139*9bcc1fc0SBob Badour flag_block_path,
140*9bcc1fc0SBob Badour flag_dev_path);
141*9bcc1fc0SBob Badour
142*9bcc1fc0SBob Badour if (ret == 1 && flag_create) {
143*9bcc1fc0SBob Badour /* TODO(wad) add flag_force to allow replacement */
144*9bcc1fc0SBob Badour ret = 0;
145*9bcc1fc0SBob Badour if (mknod(path, S_IFBLK | S_IRUSR | S_IWUSR, root_dev) && errno != EEXIST) {
146*9bcc1fc0SBob Badour warn("failed to create %s", path);
147*9bcc1fc0SBob Badour ret = 1;
148*9bcc1fc0SBob Badour }
149*9bcc1fc0SBob Badour }
150*9bcc1fc0SBob Badour
151*9bcc1fc0SBob Badour if (flag_ignore && ret > 0)
152*9bcc1fc0SBob Badour ret = 0;
153*9bcc1fc0SBob Badour
154*9bcc1fc0SBob Badour if (path[0] != '\0')
155*9bcc1fc0SBob Badour printf("%s\n", path);
156*9bcc1fc0SBob Badour
157*9bcc1fc0SBob Badour return ret;
158*9bcc1fc0SBob Badour }
159