1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#include "libbb.h"
35#include <linux/fs.h>
36
37enum {
38 ARG_NONE = 0,
39 ARG_INT = 1,
40 ARG_ULONG = 2,
41
42 ARG_U64 = 3,
43 ARG_MASK = 3,
44
45 FL_USRARG = 4,
46 FL_NORESULT = 8,
47 FL_SCALE512 = 16,
48};
49
50struct bdc {
51 uint32_t ioc;
52 const char name[sizeof("flushbufs")];
53 uint8_t flags;
54 int8_t argval;
55};
56
57static const struct bdc bdcommands[] = {
58 {
59 .ioc = BLKROSET,
60 .name = "setro",
61 .flags = ARG_INT + FL_NORESULT,
62 .argval = 1,
63 },{
64 .ioc = BLKROSET,
65 .name = "setrw",
66 .flags = ARG_INT + FL_NORESULT,
67 .argval = 0,
68 },{
69 .ioc = BLKROGET,
70 .name = "getro",
71 .flags = ARG_INT,
72 .argval = -1,
73 },{
74 .ioc = BLKSSZGET,
75 .name = "getss",
76 .flags = ARG_INT,
77 .argval = -1,
78 },{
79 .ioc = BLKBSZGET,
80 .name = "getbsz",
81 .flags = ARG_INT,
82 .argval = -1,
83 },{
84 .ioc = BLKBSZSET,
85 .name = "setbsz",
86 .flags = ARG_INT + FL_NORESULT + FL_USRARG,
87 .argval = 0,
88 },{
89 .ioc = BLKGETSIZE64,
90 .name = "getsz",
91 .flags = ARG_U64 + FL_SCALE512,
92 .argval = -1,
93 },{
94 .ioc = BLKGETSIZE,
95 .name = "getsize",
96 .flags = ARG_ULONG,
97 .argval = -1,
98 },{
99 .ioc = BLKGETSIZE64,
100 .name = "getsize64",
101 .flags = ARG_U64,
102 .argval = -1,
103 },{
104 .ioc = BLKFLSBUF,
105 .name = "flushbufs",
106 .flags = ARG_NONE + FL_NORESULT,
107 .argval = 0,
108 },{
109 .ioc = BLKRRPART,
110 .name = "rereadpt",
111 .flags = ARG_NONE + FL_NORESULT,
112 .argval = 0,
113 }
114};
115
116static const struct bdc *find_cmd(const char *s)
117{
118 const struct bdc *bdcmd = bdcommands;
119 if (s[0] == '-' && s[1] == '-') {
120 s += 2;
121 do {
122 if (strcmp(s, bdcmd->name) == 0)
123 return bdcmd;
124 bdcmd++;
125 } while (bdcmd != bdcommands + ARRAY_SIZE(bdcommands));
126 }
127 bb_show_usage();
128}
129
130int blockdev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
131int blockdev_main(int argc UNUSED_PARAM, char **argv)
132{
133 const struct bdc *bdcmd;
134 int fd;
135 uint64_t u64;
136 union {
137 int i;
138 unsigned long lu;
139 uint64_t u64;
140 } ioctl_val_on_stack;
141
142 argv++;
143 if (!argv[0] || !argv[1])
144 bb_show_usage();
145
146 bdcmd = find_cmd(*argv);
147
148 u64 = (int)bdcmd->argval;
149 if (bdcmd->flags & FL_USRARG)
150 u64 = xatoi_positive(*++argv);
151
152 argv++;
153 if (!argv[0] || argv[1])
154 bb_show_usage();
155 fd = xopen(argv[0], O_RDONLY);
156
157 ioctl_val_on_stack.u64 = u64;
158#if BB_BIG_ENDIAN
159
160
161
162
163
164
165 switch (bdcmd->flags & ARG_MASK) {
166 case ARG_INT:
167 ioctl_val_on_stack.i = (int)u64;
168 break;
169# if 0
170 case ARG_ULONG:
171 ioctl_val_on_stack.lu = (unsigned long)u64;
172 break;
173# endif
174 }
175#endif
176
177 if (ioctl(fd, bdcmd->ioc, &ioctl_val_on_stack.u64) == -1)
178 bb_simple_perror_msg_and_die(*argv);
179
180
181 u64 = ioctl_val_on_stack.u64;
182
183 if (bdcmd->flags & FL_SCALE512)
184 u64 >>= 9;
185
186
187 switch (bdcmd->flags & (ARG_MASK+FL_NORESULT)) {
188 case ARG_INT:
189
190
191
192 printf("%lld\n", (long long)(int)u64);
193 break;
194 case ARG_ULONG:
195 u64 = (unsigned long)u64;
196
197 case ARG_U64:
198 printf("%llu\n", (unsigned long long)u64);
199 break;
200 }
201
202 if (ENABLE_FEATURE_CLEAN_UP)
203 close(fd);
204 return EXIT_SUCCESS;
205}
206