]> git.ipfire.org Git - thirdparty/util-linux.git/blame - disk-utils/blockdev.c
libmount: fix bugs detected by [smatch scan]
[thirdparty/util-linux.git] / disk-utils / blockdev.c
CommitLineData
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
515422fd 14#include "c.h"
eb63b9b8 15#include "nls.h"
bc8b6383 16#include "blkdev.h"
14c76d8b 17#include "pathnames.h"
612721db 18
eb63b9b8 19struct bdc {
c3f62be7
KZ
20 long ioc; /* ioctl code */
21 const char *iocname; /* ioctl name (e.g. BLKROSET) */
22 long argval; /* default argument */
23
24 const char *name; /* --setfoo */
25 const char *argname; /* argument name or NULL */
26
27 const char *help;
28
29 int argtype;
30 int flags;
31};
32
33/* command flags */
34enum {
35 FL_NOPTR = (1 << 1), /* does not assume pointer (ARG_INT only)*/
36 FL_NORESULT = (1 << 2) /* does not return any data */
37};
38
39/* ioctl argument types */
40enum {
41 ARG_NONE,
726fa24e 42 ARG_USHRT,
c3f62be7 43 ARG_INT,
726fa24e 44 ARG_UINT,
c3f62be7
KZ
45 ARG_LONG,
46 ARG_ULONG,
47 ARG_LLONG,
48 ARG_ULLONG
49};
50
51#define IOCTL_ENTRY( io ) .ioc = io, .iocname = # io
52
00239f33 53static const struct bdc bdcms[] =
c3f62be7
KZ
54{
55 {
56 IOCTL_ENTRY(BLKROSET),
57 .name = "--setro",
58 .argtype = ARG_INT,
59 .argval = 1,
60 .flags = FL_NORESULT,
61 .help = N_("set read-only")
62 },{
63 IOCTL_ENTRY(BLKROSET),
64 .name = "--setrw",
65 .argtype = ARG_INT,
66 .argval = 0,
67 .flags = FL_NORESULT,
68 .help = N_("set read-write")
69 },{
70 IOCTL_ENTRY(BLKROGET),
71 .name = "--getro",
72 .argtype = ARG_INT,
73 .argval = -1,
74 .help = N_("get read-only")
1519ab5f
KZ
75 },{
76 IOCTL_ENTRY(BLKDISCARDZEROES),
77 .name = "--getdiscardzeroes",
78 .argtype = ARG_UINT,
79 .argval = -1,
80 .help = N_("get discard zeroes support status")
c3f62be7
KZ
81 },{
82 IOCTL_ENTRY(BLKSSZGET),
83 .name = "--getss",
84 .argtype = ARG_INT,
85 .argval = -1,
d965d63f
KZ
86 .help = N_("get logical block (sector) size")
87 },{
88 IOCTL_ENTRY(BLKPBSZGET),
89 .name = "--getpbsz",
90 .argtype = ARG_UINT,
91 .argval = -1,
92 .help = N_("get physical block (sector) size")
93 },{
94 IOCTL_ENTRY(BLKIOMIN),
95 .name = "--getiomin",
96 .argtype = ARG_UINT,
97 .argval = -1,
98 .help = N_("get minimum I/O size")
99 },{
100 IOCTL_ENTRY(BLKIOOPT),
101 .name = "--getioopt",
102 .argtype = ARG_UINT,
103 .argval = -1,
104 .help = N_("get optimal I/O size")
105 },{
106 IOCTL_ENTRY(BLKALIGNOFF),
107 .name = "--getalignoff",
108 .argtype = ARG_INT,
ed98508a 109 .argval = -1,
455fdf4a 110 .help = N_("get alignment offset in bytes")
d965d63f
KZ
111 },{
112 IOCTL_ENTRY(BLKSECTGET),
113 .name = "--getmaxsect",
114 .argtype = ARG_USHRT,
115 .argval = -1,
116 .help = N_("get max sectors per request")
c3f62be7
KZ
117 },{
118 IOCTL_ENTRY(BLKBSZGET),
119 .name = "--getbsz",
120 .argtype = ARG_INT,
121 .argval = -1,
122 .help = N_("get blocksize")
123 },{
124 IOCTL_ENTRY(BLKBSZSET),
125 .name = "--setbsz",
455fdf4a 126 .argname = "<bytes>",
c3f62be7
KZ
127 .argtype = ARG_INT,
128 .flags = FL_NORESULT,
129 .help = N_("set blocksize")
130 },{
131 IOCTL_ENTRY(BLKGETSIZE),
132 .name = "--getsize",
133 .argtype = ARG_ULONG,
134 .argval = -1,
455fdf4a 135 .help = N_("get 32-bit sector count (deprecated, use --getsz)")
c3f62be7
KZ
136 },{
137 IOCTL_ENTRY(BLKGETSIZE64),
138 .name = "--getsize64",
139 .argtype = ARG_ULLONG,
140 .argval = -1,
141 .help = N_("get size in bytes")
142 },{
143 IOCTL_ENTRY(BLKRASET),
144 .name = "--setra",
455fdf4a 145 .argname = "<sectors>",
c3f62be7
KZ
146 .argtype = ARG_INT,
147 .flags = FL_NOPTR | FL_NORESULT,
148 .help = N_("set readahead")
149 },{
150 IOCTL_ENTRY(BLKRAGET),
151 .name = "--getra",
152 .argtype = ARG_LONG,
153 .argval = -1,
154 .help = N_("get readahead")
155 },{
156 IOCTL_ENTRY(BLKFRASET),
157 .name = "--setfra",
455fdf4a 158 .argname = "<sectors>",
c3f62be7
KZ
159 .argtype = ARG_INT,
160 .flags = FL_NOPTR | FL_NORESULT,
161 .help = N_("set filesystem readahead")
162 },{
163 IOCTL_ENTRY(BLKFRAGET),
164 .name = "--getfra",
165 .argtype = ARG_LONG,
166 .argval = -1,
167 .help = N_("get filesystem readahead")
168 },{
169 IOCTL_ENTRY(BLKFLSBUF),
170 .name = "--flushbufs",
171 .help = N_("flush buffers")
172 },{
173 IOCTL_ENTRY(BLKRRPART),
174 .name = "--rereadpt",
175 .help = N_("reread partition table")
176 }
eb63b9b8
KZ
177};
178
bded204c
SK
179static void __attribute__ ((__noreturn__)) usage(FILE * out)
180{
75737ad6 181 size_t i;
bded204c 182 fprintf(out, _("\nUsage:\n"
637775c7
KZ
183 " %1$s -V\n"
184 " %1$s --report [devices]\n"
185 " %1$s [-v|-q] commands devices\n\n"
bded204c 186 "Available commands:\n"), program_invocation_short_name);
a424171c 187
637775c7 188 fprintf(out, _(" %-25s get size in 512-byte sectors\n"), "--getsz");
515422fd 189 for (i = 0; i < ARRAY_SIZE(bdcms); i++) {
eb63b9b8 190 if (bdcms[i].argname)
637775c7 191 fprintf(out, " %s %-*s %s\n", bdcms[i].name,
bded204c
SK
192 (int)(24 - strlen(bdcms[i].name)),
193 bdcms[i].argname, _(bdcms[i].help));
a424171c 194 else
637775c7 195 fprintf(out, " %-25s %s\n", bdcms[i].name,
bded204c 196 _(bdcms[i].help));
eb63b9b8 197 }
bded204c
SK
198 fputc('\n', out);
199 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
eb63b9b8
KZ
200}
201
baaa4479
SK
202static int find_cmd(char *s)
203{
75737ad6 204 size_t j;
eb63b9b8 205
515422fd 206 for (j = 0; j < ARRAY_SIZE(bdcms); j++)
eb63b9b8
KZ
207 if (!strcmp(s, bdcms[j].name))
208 return j;
209 return -1;
210}
211
f61a097b
WG
212static void do_commands(int fd, char **argv, int d);
213static void report_header(void);
214static void report_device(char *device, int quiet);
215static void report_all_devices(void);
eb63b9b8 216
baaa4479
SK
217int main(int argc, char **argv)
218{
eb63b9b8 219 int fd, d, j, k;
eb63b9b8 220
eb63b9b8
KZ
221 setlocale(LC_ALL, "");
222 bindtextdomain(PACKAGE, LOCALEDIR);
223 textdomain(PACKAGE);
224
225 if (argc < 2)
bded204c 226 usage(stderr);
eb63b9b8
KZ
227
228 /* -V not together with commands */
229 if (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) {
baaa4479
SK
230 printf(_("%s (%s)\n"), program_invocation_short_name,
231 PACKAGE_STRING);
6b515d0b 232 return EXIT_SUCCESS;
eb63b9b8 233 }
bded204c
SK
234 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
235 usage(stdout);
eb63b9b8 236
612721db
KZ
237 /* --report not together with other commands */
238 if (!strcmp(argv[1], "--report")) {
239 report_header();
240 if (argc > 2) {
241 for (d = 2; d < argc; d++)
242 report_device(argv[d], 0);
243 } else {
244 report_all_devices();
245 }
6b515d0b 246 return EXIT_SUCCESS;
612721db
KZ
247 }
248
eb63b9b8
KZ
249 /* do each of the commands on each of the devices */
250 /* devices start after last command */
251 for (d = 1; d < argc; d++) {
252 j = find_cmd(argv[d]);
253 if (j >= 0) {
c3f62be7 254 if (bdcms[j].argname)
eb63b9b8
KZ
255 d++;
256 continue;
257 }
c129767e
KZ
258 if (!strcmp(argv[d], "--getsz"))
259 continue;
eb63b9b8
KZ
260 if (!strcmp(argv[d], "--")) {
261 d++;
262 break;
263 }
264 if (argv[d][0] != '-')
265 break;
266 }
267
268 if (d >= argc)
bded204c 269 usage(stderr);
eb63b9b8
KZ
270
271 for (k = d; k < argc; k++) {
272 fd = open(argv[k], O_RDONLY, 0);
6b515d0b
SK
273 if (fd < 0)
274 err(EXIT_FAILURE, _("cannot open %s"), argv[k]);
eb63b9b8 275 do_commands(fd, argv, d);
e8f26419 276 close(fd);
eb63b9b8 277 }
6b515d0b 278 return EXIT_SUCCESS;
eb63b9b8
KZ
279}
280
f61a097b 281static void do_commands(int fd, char **argv, int d)
baaa4479 282{
eb63b9b8
KZ
283 int res, i, j;
284 int iarg;
726fa24e
KZ
285 unsigned int uarg;
286 unsigned short huarg;
eb63b9b8 287 long larg;
c129767e 288 long long llarg;
1dea05a8
KZ
289 unsigned long lu;
290 unsigned long long llu;
eb63b9b8
KZ
291 int verbose = 0;
292
293 for (i = 1; i < d; i++) {
294 if (!strcmp(argv[i], "-v")) {
295 verbose = 1;
296 continue;
baaa4479 297 }
eb63b9b8
KZ
298 if (!strcmp(argv[i], "-q")) {
299 verbose = 0;
300 continue;
301 }
302
c129767e 303 if (!strcmp(argv[i], "--getsz")) {
bc8b6383 304 res = blkdev_get_sectors(fd, &llu);
c129767e 305 if (res == 0)
bc8b6383 306 printf("%lld\n", llu);
c129767e 307 else
baaa4479
SK
308 errx(EXIT_FAILURE,
309 _("could not get device size"));
c129767e
KZ
310 continue;
311 }
312
eb63b9b8
KZ
313 j = find_cmd(argv[i]);
314 if (j == -1) {
cc4d8d72 315 warnx(_("Unknown command: %s"), argv[i]);
bded204c 316 usage(stderr);
eb63b9b8
KZ
317 }
318
baaa4479 319 switch (bdcms[j].argtype) {
eb63b9b8 320 default:
c3f62be7 321 case ARG_NONE:
eb63b9b8
KZ
322 res = ioctl(fd, bdcms[j].ioc, 0);
323 break;
726fa24e
KZ
324 case ARG_USHRT:
325 huarg = bdcms[j].argval;
326 res = ioctl(fd, bdcms[j].ioc, &huarg);
327 break;
c3f62be7
KZ
328 case ARG_INT:
329 if (bdcms[j].argname) {
baaa4479 330 if (i == d - 1) {
cc4d8d72 331 warnx(_("%s requires an argument"),
baaa4479 332 bdcms[j].name);
bded204c 333 usage(stderr);
c3f62be7
KZ
334 }
335 iarg = atoi(argv[++i]);
336 } else
337 iarg = bdcms[j].argval;
338
339 res = bdcms[j].flags & FL_NOPTR ?
baaa4479
SK
340 ioctl(fd, bdcms[j].ioc, iarg) :
341 ioctl(fd, bdcms[j].ioc, &iarg);
eb63b9b8 342 break;
726fa24e
KZ
343 case ARG_UINT:
344 uarg = bdcms[j].argval;
345 res = ioctl(fd, bdcms[j].ioc, &uarg);
346 break;
c3f62be7 347 case ARG_LONG:
eb63b9b8
KZ
348 larg = bdcms[j].argval;
349 res = ioctl(fd, bdcms[j].ioc, &larg);
350 break;
c3f62be7 351 case ARG_LLONG:
c129767e
KZ
352 llarg = bdcms[j].argval;
353 res = ioctl(fd, bdcms[j].ioc, &llarg);
354 break;
c3f62be7 355 case ARG_ULONG:
1dea05a8
KZ
356 lu = bdcms[j].argval;
357 res = ioctl(fd, bdcms[j].ioc, &lu);
358 break;
c3f62be7 359 case ARG_ULLONG:
1dea05a8
KZ
360 llu = bdcms[j].argval;
361 res = ioctl(fd, bdcms[j].ioc, &llu);
362 break;
eb63b9b8 363 }
c3f62be7 364
eb63b9b8
KZ
365 if (res == -1) {
366 perror(bdcms[j].iocname);
367 if (verbose)
65b27d36 368 printf(_("%s failed.\n"), _(bdcms[j].help));
6b515d0b 369 exit(EXIT_FAILURE);
eb63b9b8 370 }
c3f62be7
KZ
371
372 if (bdcms[j].argtype == ARG_NONE ||
373 (bdcms[j].flags & FL_NORESULT)) {
eb63b9b8 374 if (verbose)
c3f62be7
KZ
375 printf(_("%s succeeded.\n"), _(bdcms[j].help));
376 continue;
377 }
378
379 if (verbose)
380 printf("%s: ", _(bdcms[j].help));
381
baaa4479 382 switch (bdcms[j].argtype) {
726fa24e
KZ
383 case ARG_USHRT:
384 printf("%hu\n", huarg);
385 break;
c3f62be7
KZ
386 case ARG_INT:
387 printf("%d\n", iarg);
eb63b9b8 388 break;
726fa24e
KZ
389 case ARG_UINT:
390 printf("%u\n", uarg);
391 break;
c3f62be7
KZ
392 case ARG_LONG:
393 printf("%ld\n", larg);
c129767e 394 break;
c3f62be7
KZ
395 case ARG_LLONG:
396 printf("%lld\n", llarg);
1dea05a8 397 break;
c3f62be7
KZ
398 case ARG_ULONG:
399 printf("%lu\n", lu);
1dea05a8 400 break;
c3f62be7
KZ
401 case ARG_ULLONG:
402 printf("%llu\n", llu);
eb63b9b8
KZ
403 break;
404 }
405 }
406}
612721db 407
f61a097b 408static void report_all_devices(void)
baaa4479 409{
612721db
KZ
410 FILE *procpt;
411 char line[200];
412 char ptname[200];
413 char device[210];
414 int ma, mi, sz;
415
14c76d8b 416 procpt = fopen(_PATH_PROC_PARTITIONS, "r");
cc4d8d72 417 if (!procpt)
14c76d8b 418 err(EXIT_FAILURE, _("cannot open %s"), _PATH_PROC_PARTITIONS);
612721db
KZ
419
420 while (fgets(line, sizeof(line), procpt)) {
baaa4479
SK
421 if (sscanf(line, " %d %d %d %200[^\n ]",
422 &ma, &mi, &sz, ptname) != 4)
612721db
KZ
423 continue;
424
425 sprintf(device, "/dev/%s", ptname);
426 report_device(device, 1);
427 }
122db55d 428
429 fclose(procpt);
612721db
KZ
430}
431
f61a097b 432static void report_device(char *device, int quiet)
baaa4479 433{
612721db
KZ
434 int fd;
435 int ro, ssz, bsz;
bc8b6383
KZ
436 long ra;
437 unsigned long long bytes;
612721db
KZ
438 struct hd_geometry g;
439
440 fd = open(device, O_RDONLY | O_NONBLOCK);
441 if (fd < 0) {
442 if (!quiet)
6b515d0b 443 warn(_("cannot open %s"), device);
612721db
KZ
444 return;
445 }
446
447 ro = ssz = bsz = 0;
bc8b6383 448 g.start = ra = 0;
baaa4479
SK
449 if (ioctl(fd, BLKROGET, &ro) == 0 &&
450 ioctl(fd, BLKRAGET, &ra) == 0 &&
451 ioctl(fd, BLKSSZGET, &ssz) == 0 &&
452 ioctl(fd, BLKBSZGET, &bsz) == 0 &&
453 ioctl(fd, HDIO_GETGEO, &g) == 0 &&
454 blkdev_get_size(fd, &bytes) == 0) {
bc8b6383 455 printf("%s %5ld %5d %5d %10ld %15lld %s\n",
c129767e 456 ro ? "ro" : "rw", ra, ssz, bsz, g.start, bytes, device);
612721db
KZ
457 } else {
458 if (!quiet)
cc4d8d72 459 warnx(_("ioctl error on %s"), device);
612721db 460 }
122db55d 461
462 close(fd);
612721db
KZ
463}
464
f61a097b 465static void report_header()
baaa4479 466{
bc8b6383 467 printf(_("RO RA SSZ BSZ StartSec Size Device\n"));
612721db 468}