xref: /aosp_15_r20/external/rootdev/main.c (revision 9bcc1fc0ac6cc0ff33916f8e6ce540d24c01bac6)
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