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