2 * blockdev.c --- Do various simple block device ioctls from the command line
11 #include <sys/ioctl.h>
17 #include "pathnames.h"
20 long ioc
; /* ioctl code */
21 const char *iocname
; /* ioctl name (e.g. BLKROSET) */
22 long argval
; /* default argument */
24 const char *name
; /* --setfoo */
25 const char *argname
; /* argument name or NULL */
35 FL_NOPTR
= (1 << 1), /* does not assume pointer (ARG_INT only)*/
36 FL_NORESULT
= (1 << 2) /* does not return any data */
39 /* ioctl argument types */
51 #define IOCTL_ENTRY( io ) .ioc = io, .iocname = # io
53 static const struct bdc bdcms
[] =
56 IOCTL_ENTRY(BLKROSET
),
61 .help
= N_("set read-only")
63 IOCTL_ENTRY(BLKROSET
),
68 .help
= N_("set read-write")
70 IOCTL_ENTRY(BLKROGET
),
74 .help
= N_("get read-only")
76 IOCTL_ENTRY(BLKDISCARDZEROES
),
77 .name
= "--getdiscardzeroes",
80 .help
= N_("get discard zeroes support status")
82 IOCTL_ENTRY(BLKSSZGET
),
86 .help
= N_("get logical block (sector) size")
88 IOCTL_ENTRY(BLKPBSZGET
),
92 .help
= N_("get physical block (sector) size")
94 IOCTL_ENTRY(BLKIOMIN
),
98 .help
= N_("get minimum I/O size")
100 IOCTL_ENTRY(BLKIOOPT
),
101 .name
= "--getioopt",
104 .help
= N_("get optimal I/O size")
106 IOCTL_ENTRY(BLKALIGNOFF
),
107 .name
= "--getalignoff",
110 .help
= N_("get alignment offset in bytes")
112 IOCTL_ENTRY(BLKSECTGET
),
113 .name
= "--getmaxsect",
114 .argtype
= ARG_USHRT
,
116 .help
= N_("get max sectors per request")
118 IOCTL_ENTRY(BLKBSZGET
),
122 .help
= N_("get blocksize")
124 IOCTL_ENTRY(BLKBSZSET
),
126 .argname
= "<bytes>",
128 .flags
= FL_NORESULT
,
129 .help
= N_("set blocksize")
131 IOCTL_ENTRY(BLKGETSIZE
),
133 .argtype
= ARG_ULONG
,
135 .help
= N_("get 32-bit sector count (deprecated, use --getsz)")
137 IOCTL_ENTRY(BLKGETSIZE64
),
138 .name
= "--getsize64",
139 .argtype
= ARG_ULLONG
,
141 .help
= N_("get size in bytes")
143 IOCTL_ENTRY(BLKRASET
),
145 .argname
= "<sectors>",
147 .flags
= FL_NOPTR
| FL_NORESULT
,
148 .help
= N_("set readahead")
150 IOCTL_ENTRY(BLKRAGET
),
154 .help
= N_("get readahead")
156 IOCTL_ENTRY(BLKFRASET
),
158 .argname
= "<sectors>",
160 .flags
= FL_NOPTR
| FL_NORESULT
,
161 .help
= N_("set filesystem readahead")
163 IOCTL_ENTRY(BLKFRAGET
),
167 .help
= N_("get filesystem readahead")
169 IOCTL_ENTRY(BLKFLSBUF
),
170 .name
= "--flushbufs",
171 .help
= N_("flush buffers")
173 IOCTL_ENTRY(BLKRRPART
),
174 .name
= "--rereadpt",
175 .help
= N_("reread partition table")
179 static void __attribute__ ((__noreturn__
)) usage(FILE * out
)
182 fprintf(out
, _("\nUsage:\n"
184 " %1$s --report [devices]\n"
185 " %1$s [-v|-q] commands devices\n\n"
186 "Available commands:\n"), program_invocation_short_name
);
188 fprintf(out
, _(" %-25s get size in 512-byte sectors\n"), "--getsz");
189 for (i
= 0; i
< ARRAY_SIZE(bdcms
); i
++) {
190 if (bdcms
[i
].argname
)
191 fprintf(out
, " %s %-*s %s\n", bdcms
[i
].name
,
192 (int)(24 - strlen(bdcms
[i
].name
)),
193 bdcms
[i
].argname
, _(bdcms
[i
].help
));
195 fprintf(out
, " %-25s %s\n", bdcms
[i
].name
,
199 exit(out
== stderr
? EXIT_FAILURE
: EXIT_SUCCESS
);
202 static int find_cmd(char *s
)
206 for (j
= 0; j
< ARRAY_SIZE(bdcms
); j
++)
207 if (!strcmp(s
, bdcms
[j
].name
))
212 void do_commands(int fd
, char **argv
, int d
);
213 void report_header(void);
214 void report_device(char *device
, int quiet
);
215 void report_all_devices(void);
217 int main(int argc
, char **argv
)
221 setlocale(LC_ALL
, "");
222 bindtextdomain(PACKAGE
, LOCALEDIR
);
228 /* -V not together with commands */
229 if (!strcmp(argv
[1], "-V") || !strcmp(argv
[1], "--version")) {
230 printf(_("%s (%s)\n"), program_invocation_short_name
,
234 if (!strcmp(argv
[1], "-h") || !strcmp(argv
[1], "--help"))
237 /* --report not together with other commands */
238 if (!strcmp(argv
[1], "--report")) {
241 for (d
= 2; d
< argc
; d
++)
242 report_device(argv
[d
], 0);
244 report_all_devices();
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
]);
254 if (bdcms
[j
].argname
)
258 if (!strcmp(argv
[d
], "--getsz"))
260 if (!strcmp(argv
[d
], "--")) {
264 if (argv
[d
][0] != '-')
271 for (k
= d
; k
< argc
; k
++) {
272 fd
= open(argv
[k
], O_RDONLY
, 0);
274 err(EXIT_FAILURE
, _("cannot open %s"), argv
[k
]);
275 do_commands(fd
, argv
, d
);
281 void do_commands(int fd
, char **argv
, int d
)
286 unsigned short huarg
;
290 unsigned long long llu
;
293 for (i
= 1; i
< d
; i
++) {
294 if (!strcmp(argv
[i
], "-v")) {
298 if (!strcmp(argv
[i
], "-q")) {
303 if (!strcmp(argv
[i
], "--getsz")) {
304 res
= blkdev_get_sectors(fd
, &llu
);
306 printf("%lld\n", llu
);
309 _("could not get device size"));
313 j
= find_cmd(argv
[i
]);
315 warnx(_("Unknown command: %s"), argv
[i
]);
319 switch (bdcms
[j
].argtype
) {
322 res
= ioctl(fd
, bdcms
[j
].ioc
, 0);
325 huarg
= bdcms
[j
].argval
;
326 res
= ioctl(fd
, bdcms
[j
].ioc
, &huarg
);
329 if (bdcms
[j
].argname
) {
331 warnx(_("%s requires an argument"),
335 iarg
= atoi(argv
[++i
]);
337 iarg
= bdcms
[j
].argval
;
339 res
= bdcms
[j
].flags
& FL_NOPTR
?
340 ioctl(fd
, bdcms
[j
].ioc
, iarg
) :
341 ioctl(fd
, bdcms
[j
].ioc
, &iarg
);
344 uarg
= bdcms
[j
].argval
;
345 res
= ioctl(fd
, bdcms
[j
].ioc
, &uarg
);
348 larg
= bdcms
[j
].argval
;
349 res
= ioctl(fd
, bdcms
[j
].ioc
, &larg
);
352 llarg
= bdcms
[j
].argval
;
353 res
= ioctl(fd
, bdcms
[j
].ioc
, &llarg
);
356 lu
= bdcms
[j
].argval
;
357 res
= ioctl(fd
, bdcms
[j
].ioc
, &lu
);
360 llu
= bdcms
[j
].argval
;
361 res
= ioctl(fd
, bdcms
[j
].ioc
, &llu
);
366 perror(bdcms
[j
].iocname
);
368 printf(_("%s failed.\n"), _(bdcms
[j
].help
));
372 if (bdcms
[j
].argtype
== ARG_NONE
||
373 (bdcms
[j
].flags
& FL_NORESULT
)) {
375 printf(_("%s succeeded.\n"), _(bdcms
[j
].help
));
380 printf("%s: ", _(bdcms
[j
].help
));
382 switch (bdcms
[j
].argtype
) {
384 printf("%hu\n", huarg
);
387 printf("%d\n", iarg
);
390 printf("%u\n", uarg
);
393 printf("%ld\n", larg
);
396 printf("%lld\n", llarg
);
402 printf("%llu\n", llu
);
408 void report_all_devices(void)
416 procpt
= fopen(_PATH_PROC_PARTITIONS
, "r");
418 err(EXIT_FAILURE
, _("cannot open %s"), _PATH_PROC_PARTITIONS
);
420 while (fgets(line
, sizeof(line
), procpt
)) {
421 if (sscanf(line
, " %d %d %d %200[^\n ]",
422 &ma
, &mi
, &sz
, ptname
) != 4)
425 sprintf(device
, "/dev/%s", ptname
);
426 report_device(device
, 1);
432 void report_device(char *device
, int quiet
)
437 unsigned long long bytes
;
438 struct hd_geometry g
;
440 fd
= open(device
, O_RDONLY
| O_NONBLOCK
);
443 warn(_("cannot open %s"), device
);
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) {
455 printf("%s %5ld %5d %5d %10ld %15lld %s\n",
456 ro
? "ro" : "rw", ra
, ssz
, bsz
, g
.start
, bytes
, device
);
459 warnx(_("ioctl error on %s"), device
);
467 printf(_("RO RA SSZ BSZ StartSec Size Device\n"));