--- busybox-cvs-20040623/debian/config-floppy-udeb-linux +++ busybox-cvs-20040623/debian/config-floppy-udeb-linux @@ -344,6 +344,7 @@ CONFIG_MOUNT=y # CONFIG_NFSMOUNT is not set CONFIG_UMOUNT=y +CONFIG_BLOCKDEV=n CONFIG_FEATURE_MOUNT_FORCE=y # --- busybox-cvs-20040623/debian/config-udeb-linux +++ busybox-cvs-20040623/debian/config-udeb-linux @@ -413,6 +413,7 @@ CONFIG_MOUNT=y # CONFIG_NFSMOUNT is not set CONFIG_UMOUNT=y +CONFIG_BLOCKDEV=y CONFIG_FEATURE_MOUNT_FORCE=y # --- busybox-cvs-20040623/debian/config-udeb +++ busybox-cvs-20040623/debian/config-udeb @@ -403,6 +403,7 @@ CONFIG_MOUNT=y # CONFIG_NFSMOUNT is not set CONFIG_UMOUNT=y +CONFIG_BLOCKDEV=y CONFIG_FEATURE_MOUNT_FORCE=y # --- busybox-cvs-20040623/debian/config-deb +++ busybox-cvs-20040623/debian/config-deb @@ -369,6 +369,7 @@ CONFIG_MOUNT=y CONFIG_NFSMOUNT=y CONFIG_UMOUNT=y +CONFIG_BLOCKDEV=n CONFIG_FEATURE_MOUNT_FORCE=y # --- busybox-cvs-20040623/debian/config-static +++ busybox-cvs-20040623/debian/config-static @@ -503,6 +503,7 @@ CONFIG_MOUNT=y CONFIG_NFSMOUNT=y CONFIG_UMOUNT=y +CONFIG_BLOCKDEV=n CONFIG_FEATURE_MOUNT_FORCE=y # --- busybox-cvs-20040623/include/usage.h +++ busybox-cvs-20040623/include/usage.h @@ -89,6 +89,27 @@ "$ basename /foo/bar.txt .txt\n" \ "bar" +#define blockdev_trivial_usage \ + "[OPTION] [DEVICE]" +#define blockdev_full_usage \ + " blockdev --report [devices]" \ +" blockdev [-v|-q] commands devices" \ +"Available commands:" \ +" --getsz (get size in 512-byte sectors)" \ +" --setro (set read-only)" \ +" --setrw (set read-write)" \ +" --getro (get read-only)" \ +" --getss (get sectorsize)" \ +" --getbsz (get blocksize)" \ +" --setbsz BLOCKSIZE (set blocksize)" \ +" --getsize (get 32-bit sector count)" \ +" --getsize64 (get size in bytes)" \ +" --setra READAHEAD (set readahead)" \ +" --getra (get readahead)" \ +" --flushbufs (flush buffers)" \ +" --rereadpt (reread partition table)" \ + + #define bunzip2_trivial_usage \ "[OPTION]... [FILE]" #define bunzip2_full_usage \ --- busybox-cvs-20040623/include/applets.h +++ busybox-cvs-20040623/include/applets.h @@ -75,6 +75,9 @@ #ifdef CONFIG_BASENAME APPLET(basename, basename_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) #endif +#ifdef CONFIG_BLOCKDEV + APPLET(blockdev, blockdev_main, _BB_DIR_SBIN, _BB_SUID_NEVER) +#endif #ifdef CONFIG_BUNZIP2 APPLET(bunzip2, bunzip2_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) #endif --- busybox-cvs-20040623.orig/util-linux/Makefile.in +++ busybox-cvs-20040623/util-linux/Makefile.in @@ -43,6 +43,7 @@ UTILLINUX-$(CONFIG_RDATE) +=rdate.o UTILLINUX-$(CONFIG_SWAPONOFF) +=swaponoff.o UTILLINUX-$(CONFIG_UMOUNT) +=umount.o +UTILLINUX-$(CONFIG_BLOCKDEV) +=blockdev.o libraries-y+=$(UTILLINUX_DIR)$(UTILLINUX_AR) --- busybox-cvs-20040623.orig/util-linux/blockdev.c +++ busybox-cvs-20040623/util-linux/blockdev.c @@ -0,0 +1,393 @@ +/* + * blockdev.c --- Do various simple block device ioctls from the command line + * aeb, 991028 + */ + +#include +#include +#include +#include +#include +#include + +#define N_(s) (s) +#define _(s) (s) + +/* Since it is impossible to include , let us + give the ioctls explicitly. */ + +#ifndef BLKROSET +#define BLKROSET _IO(0x12,93) +#define BLKROGET _IO(0x12,94) +#define BLKRRPART _IO(0x12,95) +#define BLKGETSIZE _IO(0x12,96) +#define BLKFLSBUF _IO(0x12,97) +#define BLKRASET _IO(0x12,98) +#define BLKRAGET _IO(0x12,99) +#define BLKSSZGET _IO(0x12,104) +#define BLKBSZGET _IOR(0x12,112,size_t) +#define BLKBSZSET _IOW(0x12,113,size_t) +#define BLKGETSIZE64 _IOR(0x12,114,size_t) +#endif + +/* Maybe could be included */ +#ifndef HDIO_GETGEO +#define HDIO_GETGEO 0x0301 +struct hd_geometry { + unsigned char heads; + unsigned char sectors; + unsigned short cylinders; /* truncated */ + unsigned long start; +}; +#endif + +const char *progname; + +struct bdc { + char *name; + char *iocname; + long ioc; + int argtype; +#define ARGNONE 0 +#define ARGINTA 1 +#define ARGINTAP 2 +#define ARGINTP 3 +#define ARGINTG 4 +#define ARGLINTG 5 +#define ARGLLINTG 6 + long argval; + char *argname; + char *help; +} bdcms[] = { +#ifdef BLKROSET + { "--setro", "BLKROSET", BLKROSET, ARGINTP, 1, NULL, N_("set read-only") }, + { "--setrw", "BLKROSET", BLKROSET, ARGINTP, 0, NULL, N_("set read-write") }, +#endif +#ifdef BLKROGET + { "--getro", "BLKROGET", BLKROGET, ARGINTG, -1, NULL, N_("get read-only") }, +#endif +#ifdef BLKSSZGET + { "--getss", "BLKSSZGET", BLKSSZGET, ARGINTG, -1, NULL, N_("get sectorsize") }, +#endif +#ifdef BLKBSZGET + { "--getbsz", "BLKBSZGET", BLKBSZGET, ARGINTG, -1, NULL, N_("get blocksize") }, +#endif +#ifdef BLKBSZSET + { "--setbsz", "BLKBSZSET", BLKBSZSET, ARGINTAP, 0, "BLOCKSIZE", N_("set blocksize") }, +#endif +#ifdef BLKGETSIZE + { "--getsize", "BLKGETSIZE", BLKGETSIZE, ARGLINTG, -1, NULL, N_("get 32-bit sector count") }, +#endif +#ifdef BLKGETSIZE64 + { "--getsize64", "BLKGETSIZE64", BLKGETSIZE64, ARGLLINTG, -1, NULL, N_("get size in bytes") }, +#endif +#ifdef BLKRASET + { "--setra", "BLKRASET", BLKRASET, ARGINTA, 0, "READAHEAD", N_("set readahead") }, +#endif +#ifdef BLKRAGET + { "--getra", "BLKRAGET", BLKRAGET, ARGLINTG, -1, NULL, N_("get readahead") }, +#endif +#ifdef BLKFLSBUF + { "--flushbufs", "BLKFLSBUF", BLKFLSBUF, ARGNONE, 0, NULL, N_("flush buffers") }, +#endif +#ifdef BLKRRPART + { "--rereadpt", "BLKRRPART", BLKRRPART, ARGNONE, 0, NULL, + N_("reread partition table") }, +#endif +}; + +#define SIZE(a) (sizeof(a)/sizeof((a)[0])) + +static void +usage(void) { + int i; + fprintf(stderr, _("Usage:\n")); + fprintf(stderr, " %s -V\n", progname); + fprintf(stderr, _(" %s --report [devices]\n"), progname); + fprintf(stderr, _(" %s [-v|-q] commands devices\n"), progname); + fprintf(stderr, _("Available commands:\n")); + fprintf(stderr, "\t--getsz\t(%s)\n", "get size in 512-byte sectors"); + for (i = 0; i < SIZE(bdcms); i++) { + fprintf(stderr, "\t%s", bdcms[i].name); + if (bdcms[i].argname) + fprintf(stderr, " %s", bdcms[i].argname); + if (bdcms[i].help) + fprintf(stderr, "\t(%s)", _(bdcms[i].help)); + fprintf(stderr, "\n"); + } + exit(1); +} + +static int +find_cmd(char *s) { + int j; + + for (j = 0; j < SIZE(bdcms); j++) + if (!strcmp(s, bdcms[j].name)) + return j; + return -1; +} + +static int +getsize(int fd, long long *sectors) { + int err; + long sz; + long long b; + + err = ioctl (fd, BLKGETSIZE, &sz); + if (err) + return err; + err = ioctl(fd, BLKGETSIZE64, &b); + if (err || b == 0 || b == sz) + *sectors = sz; + else + *sectors = (b >> 9); + return 0; +} + +void do_commands(int fd, char **argv, int d); +void report_header(void); +void report_device(char *device, int quiet); +void report_all_devices(void); + +extern int +blockdev_main(int argc, char **argv) { + int fd, d, j, k; + char *p; + + /* egcs-2.91.66 is buggy and says: + blockdev.c:93: warning: `d' might be used uninitialized */ + d = 0; + + progname = argv[0]; + if ((p = strrchr(progname, '/')) != NULL) + progname = p+1; + + /*setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE);*/ + + if (argc < 2) + usage(); + + /* -V not together with commands */ + /*if (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) { + printf("%s from %s\n", progname, util_linux_version); + exit(0); + }*/ + + /* --report not together with other commands */ + if (!strcmp(argv[1], "--report")) { + report_header(); + if (argc > 2) { + for (d = 2; d < argc; d++) + report_device(argv[d], 0); + } else { + report_all_devices(); + } + exit(0); + } + + /* do each of the commands on each of the devices */ + /* devices start after last command */ + for (d = 1; d < argc; d++) { + j = find_cmd(argv[d]); + if (j >= 0) { + if (bdcms[j].argtype == ARGINTA || + bdcms[j].argtype == ARGINTAP) + d++; + continue; + } + if (!strcmp(argv[d], "--getsz")) + continue; + if (!strcmp(argv[d], "--")) { + d++; + break; + } + if (argv[d][0] != '-') + break; + } + + if (d >= argc) + usage(); + + for (k = d; k < argc; k++) { + fd = open(argv[k], O_RDONLY, 0); + if (fd < 0) { + perror(argv[k]); + exit(1); + } + do_commands(fd, argv, d); + close(fd); + } + return 0; +} + +void +do_commands(int fd, char **argv, int d) { + int res, i, j; + int iarg; + long larg; + long long llarg; + int verbose = 0; + + for (i = 1; i < d; i++) { + if (!strcmp(argv[i], "-v")) { + verbose = 1; + continue; + } + if (!strcmp(argv[i], "-q")) { + verbose = 0; + continue; + } + + if (!strcmp(argv[i], "--getsz")) { + res = getsize(fd, &llarg); + if (res == 0) + printf("%lld\n", llarg); + else + exit(1); + continue; + } + + j = find_cmd(argv[i]); + if (j == -1) { + fprintf(stderr, _("%s: Unknown command: %s\n"), + progname, argv[i]); + usage(); + } + + switch(bdcms[j].argtype) { + default: + case ARGNONE: + res = ioctl(fd, bdcms[j].ioc, 0); + break; + case ARGINTA: + if (i == d-1) { + fprintf(stderr, _("%s requires an argument\n"), + bdcms[j].name); + usage(); + } + iarg = atoi(argv[++i]); + res = ioctl(fd, bdcms[j].ioc, iarg); + break; + case ARGINTAP: + if (i == d-1) { + fprintf(stderr, _("%s requires an argument\n"), + bdcms[j].name); + usage(); + } + iarg = atoi(argv[++i]); + res = ioctl(fd, bdcms[j].ioc, &iarg); + break; + case ARGINTP: + case ARGINTG: + iarg = bdcms[j].argval; + res = ioctl(fd, bdcms[j].ioc, &iarg); + break; + case ARGLINTG: + larg = bdcms[j].argval; + res = ioctl(fd, bdcms[j].ioc, &larg); + break; + case ARGLLINTG: + llarg = bdcms[j].argval; + res = ioctl(fd, bdcms[j].ioc, &llarg); + break; + } + if (res == -1) { + perror(bdcms[j].iocname); + if (verbose) + printf("%s failed.\n", _(bdcms[j].help)); + exit(1); + } + switch(bdcms[j].argtype) { + case ARGINTG: + if (verbose) + printf("%s: %d\n", _(bdcms[j].help), iarg); + else + printf("%d\n", iarg); + break; + case ARGLINTG: + if (verbose) + printf("%s: %ld\n", _(bdcms[j].help), larg); + else + printf("%ld\n", larg); + break; + case ARGLLINTG: + if (verbose) + printf("%s: %lld\n", _(bdcms[j].help), llarg); + else + printf("%lld\n", llarg); + break; + default: + if (verbose) + printf(_("%s succeeded.\n"), _(bdcms[j].help)); + break; + } + } +} + +#define PROC_PARTITIONS "/proc/partitions" + +void +report_all_devices(void) { + FILE *procpt; + char line[200]; + char ptname[200]; + char device[210]; + int ma, mi, sz; + + procpt = fopen(PROC_PARTITIONS, "r"); + if (!procpt) { + fprintf(stderr, _("%s: cannot open %s\n"), + progname, PROC_PARTITIONS); + exit(1); + } + + while (fgets(line, sizeof(line), procpt)) { + if (sscanf (line, " %d %d %d %[^\n ]", + &ma, &mi, &sz, ptname) != 4) + continue; + + sprintf(device, "/dev/%s", ptname); + report_device(device, 1); + } +} + +void +report_device(char *device, int quiet) { + int fd; + int ro, ssz, bsz; + long ra, ss; + long long bytes; + struct hd_geometry g; + + fd = open(device, O_RDONLY | O_NONBLOCK); + if (fd < 0) { + if (!quiet) + fprintf(stderr, _("%s: cannot open %s\n"), + progname, device); + return; + } + + ro = ssz = bsz = 0; + g.start = ra = ss = 0; + if (ioctl (fd, BLKROGET, &ro) == 0 && + ioctl (fd, BLKRAGET, &ra) == 0 && + ioctl (fd, BLKSSZGET, &ssz) == 0 && + ioctl (fd, BLKBSZGET, &bsz) == 0 && + ioctl (fd, HDIO_GETGEO, &g) == 0 && + getsize (fd, &bytes) == 0) { + printf("%s %5ld %5d %5d %10ld %10lld %s\n", + ro ? "ro" : "rw", ra, ssz, bsz, g.start, bytes, device); + } else { + if (!quiet) + fprintf(stderr, _("%s: ioctl error on %s\n"), + progname, device); + } +} + +void +report_header() { + printf(_("RO RA SSZ BSZ StartSec Size Device\n")); +} --- busybox-cvs-20040623.orig/util-linux/Config.in +++ busybox-cvs-20040623/util-linux/Config.in @@ -308,6 +308,14 @@ the tool to use. If you enabled the 'mount' utility, you almost certainly also want to enable 'umount'. +config CONFIG_BLOCKDEV + bool "blockdev" + default n + help + Blockdev is a small utility to provide an interface to block devices + from the shell. It allows certain ioctl calls to be made, and their + results printed. + config CONFIG_FEATURE_MOUNT_FORCE bool " Support forced filesystem unmounting" default n