source: branches/3.0/mindi-busybox/util-linux/blockdev.c @ 3085

Last change on this file since 3085 was 3085, checked in by bruno, 6 years ago
  • Patches to render this mindi-busybox version compatible with RHEL3 at least, potentially all older Linux 2.4 based distros.
  • Property svn:eol-style set to native
File size: 4.4 KB
Line 
1/*
2 * blockdev implementation for busybox
3 *
4 * Copyright (C) 2010 Sergey Naumov <sknaumov@gmail.com>
5 *
6 * Licensed under GPLv2, see file LICENSE in this source tree.
7 */
8
9//applet:IF_BLOCKDEV(APPLET(blockdev, _BB_DIR_SBIN, _BB_SUID_DROP))
10
11//kbuild:lib-$(CONFIG_BLOCKDEV) += blockdev.o
12
13//config:config BLOCKDEV
14//config:   bool "blockdev"
15//config:   default y
16//config:   help
17//config:     Performs some ioctls with block devices.
18
19//usage:#define blockdev_trivial_usage
20//usage:    "OPTION BLOCKDEV"
21//usage:#define blockdev_full_usage "\n\n"
22//usage:       "Options:"
23//usage:     "\n    --setro     Set ro"
24//usage:     "\n    --setrw     Set rw"
25//usage:     "\n    --getro     Get ro"
26//usage:     "\n    --getss     Get sector size"
27//usage:     "\n    --getbsz    Get block size"
28//usage:     "\n    --setbsz BYTES  Set block size"
29//usage:     "\n    --getsize   Get device size in 512-byte sectors"
30//usage:     "\n    --getsize64 Get device size in bytes"
31//usage:     "\n    --flushbufs Flush buffers"
32//usage:     "\n    --rereadpt  Reread partition table"
33
34
35#include "libbb.h"
36#include <linux/fs.h>
37
38/*  Patch bco to compile this busybox on rhel3  */
39#ifndef BLKGETSIZE64
40#define BLKGETSIZE64 _IOR(0x12,114,size_t)
41#endif
42
43enum {
44    ARG_NONE   = 0,
45    ARG_INT    = 1,
46    ARG_ULONG  = 2,
47    /* Yes, BLKGETSIZE64 takes pointer to uint64_t, not ullong! */
48    ARG_U64    = 3,
49    ARG_MASK   = 3,
50
51    FL_USRARG   = 4, /* argument is provided by user */
52    FL_NORESULT = 8,
53};
54
55struct bdc {
56    uint32_t   ioc;                       /* ioctl code */
57    const char name[sizeof("flushbufs")]; /* "--setfoo" wothout "--" */
58    uint8_t    flags;
59    int8_t     argval;                    /* default argument value */
60};
61
62static const struct bdc bdcommands[] = {
63    {
64        .ioc = BLKROSET,
65        .name = "setro",
66        .flags = ARG_INT + FL_NORESULT,
67        .argval = 1,
68    },{
69        .ioc = BLKROSET,
70        .name = "setrw",
71        .flags = ARG_INT + FL_NORESULT,
72        .argval = 0,
73    },{
74        .ioc = BLKROGET,
75        .name = "getro",
76        .flags = ARG_INT,
77        .argval = -1,
78    },{
79        .ioc = BLKSSZGET,
80        .name = "getss",
81        .flags = ARG_INT,
82        .argval = -1,
83    },{
84        .ioc = BLKBSZGET,
85        .name = "getbsz",
86        .flags = ARG_INT,
87        .argval = -1,
88    },{
89        .ioc = BLKBSZSET,
90        .name = "setbsz",
91        .flags = ARG_INT + FL_NORESULT + FL_USRARG,
92        .argval = 0,
93    },{
94        .ioc = BLKGETSIZE,
95        .name = "getsize",
96        .flags = ARG_ULONG,
97        .argval = -1,
98    },{
99        .ioc = BLKGETSIZE64,
100        .name = "getsize64",
101        .flags = ARG_U64,
102        .argval = -1,
103    },{
104        .ioc = BLKFLSBUF,
105        .name = "flushbufs",
106        .flags = ARG_NONE + FL_NORESULT,
107        .argval = 0,
108    },{
109        .ioc = BLKRRPART,
110        .name = "rereadpt",
111        .flags = ARG_NONE + FL_NORESULT,
112        .argval = 0,
113    }
114};
115
116static const struct bdc *find_cmd(const char *s)
117{
118    const struct bdc *bdcmd = bdcommands;
119    if (s[0] == '-' && s[1] == '-') {
120        s += 2;
121        do {
122            if (strcmp(s, bdcmd->name) == 0)
123                return bdcmd;
124            bdcmd++;
125        } while (bdcmd != bdcommands + ARRAY_SIZE(bdcommands));
126    }
127    bb_show_usage();
128}
129
130int blockdev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
131int blockdev_main(int argc, char **argv)
132{
133    const struct bdc *bdcmd;
134    int fd;
135    uint64_t u64;
136    union {
137        int i;
138        unsigned long lu;
139        uint64_t u64;
140    } ioctl_val_on_stack;
141
142    if ((unsigned)(argc - 3) > 1) /* must have 2 or 3 args */
143        bb_show_usage();
144
145    bdcmd = find_cmd(*++argv);
146
147    u64 = (int)bdcmd->argval;
148    if (bdcmd->flags & FL_USRARG)
149        u64 = xatoi_positive(*++argv);
150
151    if (!*++argv || argv[1])
152        bb_show_usage();
153    fd = xopen(*argv, O_RDONLY);
154
155    ioctl_val_on_stack.u64 = u64;
156#if BB_BIG_ENDIAN
157    /* Store data properly wrt data size.
158     * (1) It's no-op for little-endian.
159     * (2) it's no-op for 0 and -1. Only --setro uses arg != 0 and != -1,
160     * and it is ARG_INT. --setbsz USER_VAL is also ARG_INT.
161     * Thus, we don't need to handle ARG_ULONG.
162     */
163    switch (bdcmd->flags & ARG_MASK) {
164    case ARG_INT:
165        ioctl_val_on_stack.i = (int)u64;
166        break;
167# if 0 /* unused */
168    case ARG_ULONG:
169        ioctl_val_on_stack.lu = (unsigned long)u64;
170        break;
171# endif
172    }
173#endif
174
175    if (ioctl(fd, bdcmd->ioc, &ioctl_val_on_stack.u64) == -1)
176        bb_simple_perror_msg_and_die(*argv);
177
178    /* Fetch it into register(s) */
179    u64 = ioctl_val_on_stack.u64;
180
181    /* Zero- or one-extend the value if needed, then print */
182    switch (bdcmd->flags & (ARG_MASK+FL_NORESULT)) {
183    case ARG_INT:
184        /* Smaller code when we use long long
185         * (gcc tail-merges printf call)
186         */
187        printf("%lld\n", (long long)(int)u64);
188        break;
189    case ARG_ULONG:
190        u64 = (unsigned long)u64;
191        /* FALLTHROUGH */
192    case ARG_U64:
193        printf("%llu\n", (unsigned long long)u64);
194        break;
195    }
196
197    if (ENABLE_FEATURE_CLEAN_UP)
198        close(fd);
199    return EXIT_SUCCESS;
200}
Note: See TracBrowser for help on using the repository browser.