tweak blockdev's help text
[oweals/busybox.git] / util-linux / blockdev.c
1 /*
2  * blockdev implementation for busybox
3  *
4  * Copyright (C) 2010 Sergey Naumov <sknaumov@gmail.com>
5  *
6  * Licensed under GPLv2, see file License in this tarball for details.
7  */
8
9 //applet:IF_BLOCKDEV(APPLET(blockdev, _BB_DIR_SBIN, _BB_SUID_DROP))
10
11 //kbuild:lib-$(CONFIG_BLOCKDEV) += blockdev.o
12
13 //config:config BLOCKDEV
14 //config:       bool "blockdev"
15 //config:       default y
16 //config:       help
17 //config:         Performs some ioctls with block devices.
18
19 //usage:#define blockdev_trivial_usage
20 //usage:        "OPTION BLOCKDEV"
21 //usage:#define blockdev_full_usage "\n\n"
22 //usage:       "Options:"
23 //usage:     "\n        --setro         Set ro"
24 //usage:     "\n        --setrw         Set rw"
25 //usage:     "\n        --getro         Get ro"
26 //usage:     "\n        --getss         Get sector size"
27 //usage:     "\n        --getbsz        Get block size"
28 //usage:     "\n        --setbsz BYTES  Set block size"
29 //usage:     "\n        --getsize       Get device size in 512-byte sectors"
30 //usage:     "\n        --getsize64     Get device size in bytes"
31 //usage:     "\n        --flushbufs     Flush buffers"
32 //usage:     "\n        --rereadpt      Reread partition table"
33
34
35 #include "libbb.h"
36 #include <linux/fs.h>
37
38 enum {
39         ARG_NONE   = 0,
40         ARG_INT    = 1,
41         ARG_ULONG  = 2,
42         ARG_ULLONG = 3,
43         ARG_MASK   = 3,
44
45         FL_USRARG   = 4, /* argument is provided by user */
46         FL_NORESULT = 8,
47 };
48
49 struct bdc {
50         uint32_t   ioc;                       /* ioctl code */
51         const char name[sizeof("flushbufs")]; /* "--setfoo" wothout "--" */
52         uint8_t    flags;
53         int8_t     argval;                    /* default argument value */
54 };
55
56 static const struct bdc bdcommands[] = {
57         {
58                 .ioc = BLKROSET,
59                 .name = "setro",
60                 .flags = ARG_INT + FL_NORESULT,
61                 .argval = 1,
62         },{
63                 .ioc = BLKROSET,
64                 .name = "setrw",
65                 .flags = ARG_INT + FL_NORESULT,
66                 .argval = 0,
67         },{
68                 .ioc = BLKROGET,
69                 .name = "getro",
70                 .flags = ARG_INT,
71                 .argval = -1,
72         },{
73                 .ioc = BLKSSZGET,
74                 .name = "getss",
75                 .flags = ARG_INT,
76                 .argval = -1,
77         },{
78                 .ioc = BLKBSZGET,
79                 .name = "getbsz",
80                 .flags = ARG_INT,
81                 .argval = -1,
82         },{
83                 .ioc = BLKBSZSET,
84                 .name = "setbsz",
85                 .flags = ARG_INT + FL_NORESULT + FL_USRARG,
86                 .argval = 0,
87         },{
88                 .ioc = BLKGETSIZE,
89                 .name = "getsize",
90                 .flags = ARG_ULONG,
91                 .argval = -1,
92         },{
93                 .ioc = BLKGETSIZE64,
94                 .name = "getsize64",
95                 .flags = ARG_ULLONG,
96                 .argval = -1,
97         },{
98                 .ioc = BLKFLSBUF,
99                 .name = "flushbufs",
100                 .flags = ARG_NONE + FL_NORESULT,
101                 .argval = 0,
102         },{
103                 .ioc = BLKRRPART,
104                 .name = "rereadpt",
105                 .flags = ARG_NONE + FL_NORESULT,
106                 .argval = 0,
107         }
108 };
109
110 static const struct bdc *find_cmd(const char *s)
111 {
112         int j;
113         if (*s++ == '-')
114                 if (*s++ == '-')
115                         for (j = 0; j < ARRAY_SIZE(bdcommands); j++)
116                                 if (strcmp(s, bdcommands[j].name) == 0)
117                                         return &bdcommands[j];
118         bb_show_usage();
119 }
120
121 int blockdev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
122 int blockdev_main(int argc, char **argv)
123 {
124         const struct bdc *bdcmd;
125         void *ioctl_ptr;
126         int fd;
127         int iarg;
128         unsigned long lu;
129         unsigned long long llu;
130
131         if ((unsigned)(argc - 3) > 1) /* must have 2 or 3 args */
132                 bb_show_usage();
133
134         bdcmd = find_cmd(*++argv);
135
136         llu = (int)bdcmd->argval;
137         if (bdcmd->flags & FL_USRARG)
138                 llu = xatoi_positive(*++argv);
139         lu = llu;
140         iarg = llu;
141
142         if (!*++argv)
143                 bb_show_usage();
144         fd = xopen(*argv, O_RDONLY);
145
146         ioctl_ptr = NULL;
147         switch (bdcmd->flags & ARG_MASK) {
148         case ARG_INT:
149                 ioctl_ptr =  &iarg;
150                 break;
151         case ARG_ULONG:
152                 ioctl_ptr = &lu;
153                 break;
154         case ARG_ULLONG:
155                 ioctl_ptr = &llu;
156                 break;
157         }
158
159         if (ioctl(fd, bdcmd->ioc, ioctl_ptr) == -1)
160                 bb_simple_perror_msg_and_die(*argv);
161
162         switch (bdcmd->flags & (ARG_MASK+FL_NORESULT)) {
163         case ARG_INT:
164                 /* Smaller code when we use long long
165                  * (gcc tail-merges printf call)
166                  */
167                 printf("%lld\n", (long long)iarg);
168                 break;
169         case ARG_ULONG:
170                 llu = lu;
171                 /* FALLTHROUGH */
172         case ARG_ULLONG:
173                 printf("%llu\n", llu);
174                 break;
175         }
176
177         if (ENABLE_FEATURE_CLEAN_UP)
178                 close(fd);
179         return EXIT_SUCCESS;
180 }