]>
Commit | Line | Data |
---|---|---|
eb63b9b8 KZ |
1 | /* |
2 | * blockdev.c --- Do various simple block device ioctls from the command line | |
3 | * aeb, 991028 | |
4 | */ | |
5 | ||
6 | #include <stdio.h> | |
7 | #include <fcntl.h> | |
eb63b9b8 KZ |
8 | #include <stdlib.h> |
9 | #include <string.h> | |
10 | #include <unistd.h> | |
11 | #include <sys/ioctl.h> | |
3281d426 | 12 | #include <errno.h> |
eb63b9b8 | 13 | |
eb63b9b8 | 14 | #include "nls.h" |
bc8b6383 | 15 | #include "blkdev.h" |
612721db | 16 | |
eb63b9b8 KZ |
17 | const char *progname; |
18 | ||
19 | struct bdc { | |
20 | char *name; | |
21 | char *iocname; | |
22 | long ioc; | |
23 | int argtype; | |
24 | #define ARGNONE 0 | |
25 | #define ARGINTA 1 | |
e8f26419 KZ |
26 | #define ARGINTAP 2 |
27 | #define ARGINTP 3 | |
28 | #define ARGINTG 4 | |
29 | #define ARGLINTG 5 | |
c129767e | 30 | #define ARGLLINTG 6 |
1dea05a8 KZ |
31 | #define ARGLU 7 |
32 | #define ARGLLU 8 | |
eb63b9b8 KZ |
33 | long argval; |
34 | char *argname; | |
35 | char *help; | |
36 | } bdcms[] = { | |
eb63b9b8 KZ |
37 | { "--setro", "BLKROSET", BLKROSET, ARGINTP, 1, NULL, N_("set read-only") }, |
38 | { "--setrw", "BLKROSET", BLKROSET, ARGINTP, 0, NULL, N_("set read-write") }, | |
eb63b9b8 | 39 | { "--getro", "BLKROGET", BLKROGET, ARGINTG, -1, NULL, N_("get read-only") }, |
eb63b9b8 | 40 | { "--getss", "BLKSSZGET", BLKSSZGET, ARGINTG, -1, NULL, N_("get sectorsize") }, |
e8f26419 | 41 | { "--getbsz", "BLKBSZGET", BLKBSZGET, ARGINTG, -1, NULL, N_("get blocksize") }, |
e8f26419 | 42 | { "--setbsz", "BLKBSZSET", BLKBSZSET, ARGINTAP, 0, "BLOCKSIZE", N_("set blocksize") }, |
1dea05a8 | 43 | { "--getsize", "BLKGETSIZE", BLKGETSIZE, ARGLU, -1, NULL, N_("get 32-bit sector count") }, |
1dea05a8 | 44 | { "--getsize64", "BLKGETSIZE64", BLKGETSIZE64, ARGLLU, -1, NULL, N_("get size in bytes") }, |
eb63b9b8 | 45 | { "--setra", "BLKRASET", BLKRASET, ARGINTA, 0, "READAHEAD", N_("set readahead") }, |
eb63b9b8 | 46 | { "--getra", "BLKRAGET", BLKRAGET, ARGLINTG, -1, NULL, N_("get readahead") }, |
c2a1e788 | 47 | { "--setfra", "BLKFRASET", BLKFRASET, ARGINTA, 0, "FSREADAHEAD", N_("set filesystem readahead") }, |
c2a1e788 | 48 | { "--getfra", "BLKFRAGET", BLKFRAGET, ARGLINTG, -1, NULL, N_("get filesystem readahead") }, |
eb63b9b8 | 49 | { "--flushbufs", "BLKFLSBUF", BLKFLSBUF, ARGNONE, 0, NULL, N_("flush buffers") }, |
eb63b9b8 KZ |
50 | { "--rereadpt", "BLKRRPART", BLKRRPART, ARGNONE, 0, NULL, |
51 | N_("reread partition table") }, | |
eb63b9b8 KZ |
52 | }; |
53 | ||
54 | #define SIZE(a) (sizeof(a)/sizeof((a)[0])) | |
55 | ||
56 | static void | |
57 | usage(void) { | |
58 | int i; | |
a424171c | 59 | fputc('\n', stderr); |
612721db KZ |
60 | fprintf(stderr, _("Usage:\n")); |
61 | fprintf(stderr, " %s -V\n", progname); | |
62 | fprintf(stderr, _(" %s --report [devices]\n"), progname); | |
63 | fprintf(stderr, _(" %s [-v|-q] commands devices\n"), progname); | |
a424171c KZ |
64 | fputc('\n', stderr); |
65 | ||
eb63b9b8 | 66 | fprintf(stderr, _("Available commands:\n")); |
a424171c | 67 | fprintf(stderr, "\t%-30s %s\n", "--getsz", |
65b27d36 | 68 | _("get size in 512-byte sectors")); |
eb63b9b8 | 69 | for (i = 0; i < SIZE(bdcms); i++) { |
eb63b9b8 | 70 | if (bdcms[i].argname) |
a424171c KZ |
71 | fprintf(stderr, "\t%s %-*s %s\n", bdcms[i].name, |
72 | (int) (29 - strlen(bdcms[i].name)), | |
73 | bdcms[i].argname, _(bdcms[i].help)); | |
74 | else | |
75 | fprintf(stderr, "\t%-30s %s\n", bdcms[i].name, | |
76 | _(bdcms[i].help)); | |
eb63b9b8 | 77 | } |
a424171c | 78 | fputc('\n', stderr); |
eb63b9b8 KZ |
79 | exit(1); |
80 | } | |
81 | ||
22853e4a | 82 | static int |
eb63b9b8 KZ |
83 | find_cmd(char *s) { |
84 | int j; | |
85 | ||
86 | for (j = 0; j < SIZE(bdcms); j++) | |
87 | if (!strcmp(s, bdcms[j].name)) | |
88 | return j; | |
89 | return -1; | |
90 | } | |
91 | ||
92 | void do_commands(int fd, char **argv, int d); | |
612721db KZ |
93 | void report_header(void); |
94 | void report_device(char *device, int quiet); | |
95 | void report_all_devices(void); | |
eb63b9b8 KZ |
96 | |
97 | int | |
98 | main(int argc, char **argv) { | |
99 | int fd, d, j, k; | |
100 | char *p; | |
101 | ||
102 | /* egcs-2.91.66 is buggy and says: | |
103 | blockdev.c:93: warning: `d' might be used uninitialized */ | |
104 | d = 0; | |
105 | ||
106 | progname = argv[0]; | |
107 | if ((p = strrchr(progname, '/')) != NULL) | |
108 | progname = p+1; | |
109 | ||
110 | setlocale(LC_ALL, ""); | |
111 | bindtextdomain(PACKAGE, LOCALEDIR); | |
112 | textdomain(PACKAGE); | |
113 | ||
114 | if (argc < 2) | |
115 | usage(); | |
116 | ||
117 | /* -V not together with commands */ | |
118 | if (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) { | |
baf39af1 | 119 | printf("%s (%s)\n", progname, PACKAGE_STRING); |
eb63b9b8 KZ |
120 | exit(0); |
121 | } | |
122 | ||
612721db KZ |
123 | /* --report not together with other commands */ |
124 | if (!strcmp(argv[1], "--report")) { | |
125 | report_header(); | |
126 | if (argc > 2) { | |
127 | for (d = 2; d < argc; d++) | |
128 | report_device(argv[d], 0); | |
129 | } else { | |
130 | report_all_devices(); | |
131 | } | |
132 | exit(0); | |
133 | } | |
134 | ||
eb63b9b8 KZ |
135 | /* do each of the commands on each of the devices */ |
136 | /* devices start after last command */ | |
137 | for (d = 1; d < argc; d++) { | |
138 | j = find_cmd(argv[d]); | |
139 | if (j >= 0) { | |
e8f26419 KZ |
140 | if (bdcms[j].argtype == ARGINTA || |
141 | bdcms[j].argtype == ARGINTAP) | |
eb63b9b8 KZ |
142 | d++; |
143 | continue; | |
144 | } | |
c129767e KZ |
145 | if (!strcmp(argv[d], "--getsz")) |
146 | continue; | |
eb63b9b8 KZ |
147 | if (!strcmp(argv[d], "--")) { |
148 | d++; | |
149 | break; | |
150 | } | |
151 | if (argv[d][0] != '-') | |
152 | break; | |
153 | } | |
154 | ||
155 | if (d >= argc) | |
156 | usage(); | |
157 | ||
158 | for (k = d; k < argc; k++) { | |
159 | fd = open(argv[k], O_RDONLY, 0); | |
160 | if (fd < 0) { | |
161 | perror(argv[k]); | |
162 | exit(1); | |
163 | } | |
164 | do_commands(fd, argv, d); | |
e8f26419 | 165 | close(fd); |
eb63b9b8 KZ |
166 | } |
167 | return 0; | |
168 | } | |
169 | ||
170 | void | |
171 | do_commands(int fd, char **argv, int d) { | |
172 | int res, i, j; | |
173 | int iarg; | |
174 | long larg; | |
c129767e | 175 | long long llarg; |
1dea05a8 KZ |
176 | unsigned long lu; |
177 | unsigned long long llu; | |
eb63b9b8 KZ |
178 | int verbose = 0; |
179 | ||
180 | for (i = 1; i < d; i++) { | |
181 | if (!strcmp(argv[i], "-v")) { | |
182 | verbose = 1; | |
183 | continue; | |
184 | } | |
185 | if (!strcmp(argv[i], "-q")) { | |
186 | verbose = 0; | |
187 | continue; | |
188 | } | |
189 | ||
c129767e | 190 | if (!strcmp(argv[i], "--getsz")) { |
bc8b6383 | 191 | res = blkdev_get_sectors(fd, &llu); |
c129767e | 192 | if (res == 0) |
bc8b6383 | 193 | printf("%lld\n", llu); |
c129767e KZ |
194 | else |
195 | exit(1); | |
196 | continue; | |
197 | } | |
198 | ||
eb63b9b8 KZ |
199 | j = find_cmd(argv[i]); |
200 | if (j == -1) { | |
612721db KZ |
201 | fprintf(stderr, _("%s: Unknown command: %s\n"), |
202 | progname, argv[i]); | |
eb63b9b8 KZ |
203 | usage(); |
204 | } | |
205 | ||
206 | switch(bdcms[j].argtype) { | |
207 | default: | |
208 | case ARGNONE: | |
209 | res = ioctl(fd, bdcms[j].ioc, 0); | |
210 | break; | |
211 | case ARGINTA: | |
212 | if (i == d-1) { | |
213 | fprintf(stderr, _("%s requires an argument\n"), | |
214 | bdcms[j].name); | |
215 | usage(); | |
216 | } | |
217 | iarg = atoi(argv[++i]); | |
218 | res = ioctl(fd, bdcms[j].ioc, iarg); | |
219 | break; | |
e8f26419 KZ |
220 | case ARGINTAP: |
221 | if (i == d-1) { | |
222 | fprintf(stderr, _("%s requires an argument\n"), | |
223 | bdcms[j].name); | |
224 | usage(); | |
225 | } | |
226 | iarg = atoi(argv[++i]); | |
227 | res = ioctl(fd, bdcms[j].ioc, &iarg); | |
228 | break; | |
eb63b9b8 KZ |
229 | case ARGINTP: |
230 | case ARGINTG: | |
231 | iarg = bdcms[j].argval; | |
232 | res = ioctl(fd, bdcms[j].ioc, &iarg); | |
233 | break; | |
234 | case ARGLINTG: | |
235 | larg = bdcms[j].argval; | |
236 | res = ioctl(fd, bdcms[j].ioc, &larg); | |
237 | break; | |
c129767e KZ |
238 | case ARGLLINTG: |
239 | llarg = bdcms[j].argval; | |
240 | res = ioctl(fd, bdcms[j].ioc, &llarg); | |
241 | break; | |
1dea05a8 KZ |
242 | case ARGLU: |
243 | lu = bdcms[j].argval; | |
244 | res = ioctl(fd, bdcms[j].ioc, &lu); | |
245 | break; | |
246 | case ARGLLU: | |
247 | llu = bdcms[j].argval; | |
248 | res = ioctl(fd, bdcms[j].ioc, &llu); | |
249 | break; | |
250 | ||
eb63b9b8 KZ |
251 | } |
252 | if (res == -1) { | |
253 | perror(bdcms[j].iocname); | |
254 | if (verbose) | |
65b27d36 | 255 | printf(_("%s failed.\n"), _(bdcms[j].help)); |
eb63b9b8 KZ |
256 | exit(1); |
257 | } | |
258 | switch(bdcms[j].argtype) { | |
259 | case ARGINTG: | |
260 | if (verbose) | |
261 | printf("%s: %d\n", _(bdcms[j].help), iarg); | |
262 | else | |
263 | printf("%d\n", iarg); | |
264 | break; | |
265 | case ARGLINTG: | |
266 | if (verbose) | |
267 | printf("%s: %ld\n", _(bdcms[j].help), larg); | |
268 | else | |
269 | printf("%ld\n", larg); | |
270 | break; | |
c129767e KZ |
271 | case ARGLLINTG: |
272 | if (verbose) | |
273 | printf("%s: %lld\n", _(bdcms[j].help), llarg); | |
274 | else | |
275 | printf("%lld\n", llarg); | |
276 | break; | |
1dea05a8 KZ |
277 | case ARGLU: |
278 | if (verbose) | |
279 | printf("%s: %lu\n", _(bdcms[j].help), lu); | |
280 | else | |
281 | printf("%lu\n", lu); | |
282 | break; | |
283 | case ARGLLU: | |
284 | if (verbose) | |
285 | printf("%s: %llu\n", _(bdcms[j].help), llu); | |
286 | else | |
287 | printf("%llu\n", llu); | |
288 | break; | |
289 | ||
eb63b9b8 KZ |
290 | default: |
291 | if (verbose) | |
612721db | 292 | printf(_("%s succeeded.\n"), _(bdcms[j].help)); |
eb63b9b8 KZ |
293 | break; |
294 | } | |
295 | } | |
296 | } | |
612721db KZ |
297 | |
298 | #define PROC_PARTITIONS "/proc/partitions" | |
299 | ||
300 | void | |
301 | report_all_devices(void) { | |
302 | FILE *procpt; | |
303 | char line[200]; | |
304 | char ptname[200]; | |
305 | char device[210]; | |
306 | int ma, mi, sz; | |
307 | ||
308 | procpt = fopen(PROC_PARTITIONS, "r"); | |
309 | if (!procpt) { | |
310 | fprintf(stderr, _("%s: cannot open %s\n"), | |
311 | progname, PROC_PARTITIONS); | |
312 | exit(1); | |
313 | } | |
314 | ||
315 | while (fgets(line, sizeof(line), procpt)) { | |
18c3e243 | 316 | if (sscanf (line, " %d %d %d %200[^\n ]", |
612721db KZ |
317 | &ma, &mi, &sz, ptname) != 4) |
318 | continue; | |
319 | ||
320 | sprintf(device, "/dev/%s", ptname); | |
321 | report_device(device, 1); | |
322 | } | |
122db55d | 323 | |
324 | fclose(procpt); | |
612721db KZ |
325 | } |
326 | ||
327 | void | |
328 | report_device(char *device, int quiet) { | |
329 | int fd; | |
330 | int ro, ssz, bsz; | |
bc8b6383 KZ |
331 | long ra; |
332 | unsigned long long bytes; | |
612721db KZ |
333 | struct hd_geometry g; |
334 | ||
335 | fd = open(device, O_RDONLY | O_NONBLOCK); | |
336 | if (fd < 0) { | |
337 | if (!quiet) | |
338 | fprintf(stderr, _("%s: cannot open %s\n"), | |
339 | progname, device); | |
340 | return; | |
341 | } | |
342 | ||
343 | ro = ssz = bsz = 0; | |
bc8b6383 | 344 | g.start = ra = 0; |
612721db KZ |
345 | if (ioctl (fd, BLKROGET, &ro) == 0 && |
346 | ioctl (fd, BLKRAGET, &ra) == 0 && | |
347 | ioctl (fd, BLKSSZGET, &ssz) == 0 && | |
348 | ioctl (fd, BLKBSZGET, &bsz) == 0 && | |
c129767e | 349 | ioctl (fd, HDIO_GETGEO, &g) == 0 && |
bc8b6383 KZ |
350 | blkdev_get_size (fd, &bytes) == 0) { |
351 | printf("%s %5ld %5d %5d %10ld %15lld %s\n", | |
c129767e | 352 | ro ? "ro" : "rw", ra, ssz, bsz, g.start, bytes, device); |
612721db KZ |
353 | } else { |
354 | if (!quiet) | |
355 | fprintf(stderr, _("%s: ioctl error on %s\n"), | |
356 | progname, device); | |
357 | } | |
122db55d | 358 | |
359 | close(fd); | |
612721db KZ |
360 | } |
361 | ||
362 | void | |
363 | report_header() { | |
bc8b6383 | 364 | printf(_("RO RA SSZ BSZ StartSec Size Device\n")); |
612721db | 365 | } |