blockdev: new applet
authorSergey Naumov <sknaumov@gmail.com>
Mon, 6 Sep 2010 11:35:58 +0000 (13:35 +0200)
committerDenys Vlasenko <dvlasenk@redhat.com>
Mon, 6 Sep 2010 11:35:58 +0000 (13:35 +0200)
function                                             old     new   delta
blockdev_main                                          -     287    +287
bdcommands                                             -     160    +160
packed_usage                                       27203   27298     +95
applet_names                                        2297    2306      +9
applet_main                                         1352    1356      +4
applet_nameofs                                       676     678      +2
applet_install_loc                                   169     170      +1
------------------------------------------------------------------------------
(add/remove: 3/0 grow/shrink: 5/0 up/down: 558/0)             Total: 558 bytes

Signed-off-by: Sergey Naumov <sknaumov@gmail.com>
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
util-linux/blockdev.c [new file with mode: 0644]

diff --git a/util-linux/blockdev.c b/util-linux/blockdev.c
new file mode 100644 (file)
index 0000000..eb5914b
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * blockdev implementation for busybox
+ *
+ * Copyright (C) 2010 Sergey Naumov <sknaumov@gmail.com>
+ *
+ * Licensed under GPLv2, see file License in this tarball for details.
+ */
+
+//applet:IF_BLOCKDEV(APPLET(blockdev, _BB_DIR_SBIN, _BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_BLOCKDEV) += blockdev.o
+
+//config:config BLOCKDEV
+//config:      bool "blockdev"
+//config:      default y
+//config:      help
+//config:        Performs some ioctls with block devices.
+
+//usage:#define blockdev_trivial_usage
+//usage:       "OPTION [OPTARG] DEVICE"
+//usage:#define blockdev_full_usage "\n\n"
+//usage:       "Options:"
+//usage:     "\n       --setro         Set ro"
+//usage:     "\n       --setrw         Set rw"
+//usage:     "\n       --getro         Get ro"
+//usage:     "\n       --getss         Get sector size"
+//usage:     "\n       --getbsz        Get block size"
+//usage:     "\n       --setbsz BYTES  Set block size"
+//usage:     "\n       --getsize       Get device size in 512-byte sectors"
+//usage:     "\n       --getsize64     Get device size in bytes"
+//usage:     "\n       --flushbufs     Flush buffers"
+//usage:     "\n       --rereadpt      Reread partition table"
+
+
+#include "libbb.h"
+#include <linux/fs.h>
+
+enum {
+       ARG_NONE   = 0,
+       ARG_INT    = 1,
+       ARG_ULONG  = 2,
+       ARG_ULLONG = 3,
+       ARG_MASK   = 3,
+
+       FL_USRARG   = 4, /* argument is provided by user */
+       FL_NORESULT = 8,
+};
+
+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 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 = BLKGETSIZE,
+               .name = "getsize",
+               .flags = ARG_ULONG,
+               .argval = -1,
+       },{
+               .ioc = BLKGETSIZE64,
+               .name = "getsize64",
+               .flags = ARG_ULLONG,
+               .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)
+{
+       int j;
+       if (*s++ == '-')
+               if (*s++ == '-')
+                       for (j = 0; j < ARRAY_SIZE(bdcommands); j++)
+                               if (strcmp(s, bdcommands[j].name) == 0)
+                                       return &bdcommands[j];
+       bb_show_usage();
+}
+
+int blockdev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int blockdev_main(int argc, char **argv)
+{
+       const struct bdc *bdcmd;
+       void *ioctl_ptr;
+       int fd;
+       int iarg;
+       unsigned long lu;
+       unsigned long long llu;
+
+       if ((unsigned)(argc - 3) > 1) /* must have 2 or 3 args */
+               bb_show_usage();
+
+       bdcmd = find_cmd(*++argv);
+
+       llu = (int)bdcmd->argval;
+       if (bdcmd->flags & FL_USRARG)
+               llu = xatoi_positive(*++argv);
+       lu = llu;
+       iarg = llu;
+
+       if (!*++argv)
+               bb_show_usage();
+       fd = xopen(*argv, O_RDONLY);
+
+       ioctl_ptr = NULL;
+       switch (bdcmd->flags & ARG_MASK) {
+       case ARG_INT:
+               ioctl_ptr =  &iarg;
+               break;
+       case ARG_ULONG:
+               ioctl_ptr = &lu;
+               break;
+       case ARG_ULLONG:
+               ioctl_ptr = &llu;
+               break;
+       }
+
+       if (ioctl(fd, bdcmd->ioc, ioctl_ptr) == -1)
+               bb_simple_perror_msg_and_die(*argv);
+
+       switch (bdcmd->flags & (ARG_MASK+FL_NORESULT)) {
+       case ARG_INT:
+               /* Smaller code when we use long long
+                * (gcc tail-merges printf call)
+                */
+               printf("%lld\n", (long long)iarg);
+               break;
+       case ARG_ULONG:
+               llu = lu;
+               /* FALLTHROUGH */
+       case ARG_ULLONG:
+               printf("%llu\n", llu);
+               break;
+       }
+
+       if (ENABLE_FEATURE_CLEAN_UP)
+               close(fd);
+       return EXIT_SUCCESS;
+}