diff options
-rw-r--r-- | util-linux/blockdev.c | 139 |
1 files changed, 58 insertions, 81 deletions
diff --git a/util-linux/blockdev.c b/util-linux/blockdev.c index 5d8e465b4..e9b5b8bf9 100644 --- a/util-linux/blockdev.c +++ b/util-linux/blockdev.c @@ -34,6 +34,35 @@ #include "libbb.h" #include <linux/fs.h> +/* Takes less space is separate arrays than one array of struct */ +static const char bdcmd_names[] ALIGN1 = + "setro" "\0" +#define CMD_SETRO 0 + "setrw" "\0" + "getro" "\0" + "getss" "\0" + "getbsz" "\0" + "setbsz" "\0" +#define CMD_SETBSZ 5 + "getsz" "\0" + "getsize" "\0" + "getsize64" "\0" + "flushbufs" "\0" + "rereadpt" "\0" +; +static const uint32_t bdcmd_ioctl[] = { + BLKROSET, //setro + BLKROSET, //setrw + BLKROGET, //getro + BLKSSZGET, //getss + BLKBSZGET, //getbsz + BLKBSZSET, //setbsz + BLKGETSIZE64, //getsz + BLKGETSIZE, //getsize + BLKGETSIZE64, //getsize64 + BLKFLSBUF, //flushbufs + BLKRRPART, //rereadpt +}; enum { ARG_NONE = 0, ARG_INT = 1, @@ -46,83 +75,26 @@ enum { FL_NORESULT = 8, FL_SCALE512 = 16, }; - -struct bdc { - uint32_t ioc; /* ioctl code */ - const char name[sizeof("flushbufs")]; /* "--setfoo" wothout "--" */ - uint8_t flags; - int8_t argval; /* default argument value */ +static const uint8_t bdcmd_flags[] ALIGN1 = { + ARG_INT + FL_NORESULT, //setro + ARG_INT + FL_NORESULT, //setrw + ARG_INT, //getro + ARG_INT, //getss + ARG_INT, //getbsz + ARG_INT + FL_NORESULT + FL_USRARG, //setbsz + ARG_U64 + FL_SCALE512, //getsz + ARG_ULONG, //getsize + ARG_U64, //getsize64 + ARG_NONE + FL_NORESULT, //flushbufs + ARG_NONE + FL_NORESULT, //rereadpt }; -static const struct bdc bdcommands[] = { - { - .ioc = BLKROSET, - .name = "setro", - .flags = ARG_INT + FL_NORESULT, - .argval = 1, - },{ - .ioc = BLKROSET, - .name = "setrw", - .flags = ARG_INT + FL_NORESULT, - .argval = 0, - },{ - .ioc = BLKROGET, - .name = "getro", - .flags = ARG_INT, - .argval = -1, - },{ - .ioc = BLKSSZGET, - .name = "getss", - .flags = ARG_INT, - .argval = -1, - },{ - .ioc = BLKBSZGET, - .name = "getbsz", - .flags = ARG_INT, - .argval = -1, - },{ - .ioc = BLKBSZSET, - .name = "setbsz", - .flags = ARG_INT + FL_NORESULT + FL_USRARG, - .argval = 0, - },{ - .ioc = BLKGETSIZE64, - .name = "getsz", - .flags = ARG_U64 + FL_SCALE512, - .argval = -1, - },{ - .ioc = BLKGETSIZE, - .name = "getsize", - .flags = ARG_ULONG, - .argval = -1, - },{ - .ioc = BLKGETSIZE64, - .name = "getsize64", - .flags = ARG_U64, - .argval = -1, - },{ - .ioc = BLKFLSBUF, - .name = "flushbufs", - .flags = ARG_NONE + FL_NORESULT, - .argval = 0, - },{ - .ioc = BLKRRPART, - .name = "rereadpt", - .flags = ARG_NONE + FL_NORESULT, - .argval = 0, - } -}; - -static const struct bdc *find_cmd(const char *s) +static unsigned find_cmd(const char *s) { - const struct bdc *bdcmd = bdcommands; if (s[0] == '-' && s[1] == '-') { - s += 2; - do { - if (strcmp(s, bdcmd->name) == 0) - return bdcmd; - bdcmd++; - } while (bdcmd != bdcommands + ARRAY_SIZE(bdcommands)); + int n = index_in_strings(bdcmd_names, s + 2); + if (n >= 0) + return n; } bb_show_usage(); } @@ -130,7 +102,8 @@ static const struct bdc *find_cmd(const char *s) int blockdev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int blockdev_main(int argc UNUSED_PARAM, char **argv) { - const struct bdc *bdcmd; + unsigned bdcmd; + unsigned flags; int fd; uint64_t u64; union { @@ -144,10 +117,13 @@ int blockdev_main(int argc UNUSED_PARAM, char **argv) bb_show_usage(); bdcmd = find_cmd(*argv); - - u64 = (int)bdcmd->argval; - if (bdcmd->flags & FL_USRARG) + /* setrw translates to BLKROSET(0), most other ioctls don't care... */ + /* ...setro will do BLKROSET(1) */ + u64 = (bdcmd == CMD_SETRO); + if (bdcmd == CMD_SETBSZ) { + /* ...setbsz is BLKBSZSET(bytes) */ u64 = xatoi_positive(*++argv); + } argv++; if (!argv[0] || argv[1]) @@ -155,6 +131,7 @@ int blockdev_main(int argc UNUSED_PARAM, char **argv) fd = xopen(argv[0], O_RDONLY); ioctl_val_on_stack.u64 = u64; + flags = bdcmd_flags[bdcmd]; #if BB_BIG_ENDIAN /* Store data properly wrt data size. * (1) It's no-op for little-endian. @@ -162,7 +139,7 @@ int blockdev_main(int argc UNUSED_PARAM, char **argv) * and it is ARG_INT. --setbsz USER_VAL is also ARG_INT. * Thus, we don't need to handle ARG_ULONG. */ - switch (bdcmd->flags & ARG_MASK) { + switch (flags & ARG_MASK) { case ARG_INT: ioctl_val_on_stack.i = (int)u64; break; @@ -174,17 +151,17 @@ int blockdev_main(int argc UNUSED_PARAM, char **argv) } #endif - if (ioctl(fd, bdcmd->ioc, &ioctl_val_on_stack.u64) == -1) + if (ioctl(fd, bdcmd_ioctl[bdcmd], &ioctl_val_on_stack.u64) == -1) bb_simple_perror_msg_and_die(*argv); /* Fetch it into register(s) */ u64 = ioctl_val_on_stack.u64; - if (bdcmd->flags & FL_SCALE512) + if (flags & FL_SCALE512) u64 >>= 9; /* Zero- or one-extend the value if needed, then print */ - switch (bdcmd->flags & (ARG_MASK+FL_NORESULT)) { + switch (flags & (ARG_MASK+FL_NORESULT)) { case ARG_INT: /* Smaller code when we use long long * (gcc tail-merges printf call) |