2 * blockdev implementation for busybox
4 * Copyright (C) 2010 Sergey Naumov <sknaumov@gmail.com>
6 * Licensed under GPLv2, see file LICENSE in this source tree.
9 //applet:IF_BLOCKDEV(APPLET(blockdev, BB_DIR_SBIN, BB_SUID_DROP))
11 //kbuild:lib-$(CONFIG_BLOCKDEV) += blockdev.o
13 //config:config BLOCKDEV
14 //config: bool "blockdev"
17 //config: Performs some ioctls with block devices.
19 //usage:#define blockdev_trivial_usage
20 //usage: "OPTION BLOCKDEV"
21 //usage:#define blockdev_full_usage "\n\n"
22 //usage: " --setro Set ro"
23 //usage: "\n --setrw Set rw"
24 //usage: "\n --getro Get ro"
25 //usage: "\n --getss Get sector size"
26 //usage: "\n --getbsz Get block size"
27 //usage: "\n --setbsz BYTES Set block size"
28 //usage: "\n --getsz Get device size in 512-byte sectors"
29 /*//usage: "\n --getsize Get device size in sectors (deprecated)"*/
30 //usage: "\n --getsize64 Get device size in bytes"
31 //usage: "\n --flushbufs Flush buffers"
32 //usage: "\n --rereadpt Reread partition table"
42 /* Yes, BLKGETSIZE64 takes pointer to uint64_t, not ullong! */
46 FL_USRARG
= 4, /* argument is provided by user */
52 uint32_t ioc
; /* ioctl code */
53 const char name
[sizeof("flushbufs")]; /* "--setfoo" wothout "--" */
55 int8_t argval
; /* default argument value */
58 static const struct bdc bdcommands
[] = {
62 .flags
= ARG_INT
+ FL_NORESULT
,
67 .flags
= ARG_INT
+ FL_NORESULT
,
87 .flags
= ARG_INT
+ FL_NORESULT
+ FL_USRARG
,
92 .flags
= ARG_U64
+ FL_SCALE512
,
107 .flags
= ARG_NONE
+ FL_NORESULT
,
112 .flags
= ARG_NONE
+ FL_NORESULT
,
117 static const struct bdc
*find_cmd(const char *s
)
119 const struct bdc
*bdcmd
= bdcommands
;
120 if (s
[0] == '-' && s
[1] == '-') {
123 if (strcmp(s
, bdcmd
->name
) == 0)
126 } while (bdcmd
!= bdcommands
+ ARRAY_SIZE(bdcommands
));
131 int blockdev_main(int argc
, char **argv
) MAIN_EXTERNALLY_VISIBLE
;
132 int blockdev_main(int argc UNUSED_PARAM
, char **argv
)
134 const struct bdc
*bdcmd
;
141 } ioctl_val_on_stack
;
144 if (!argv
[0] || !argv
[1]) /* must have at least 2 args */
147 bdcmd
= find_cmd(*argv
);
149 u64
= (int)bdcmd
->argval
;
150 if (bdcmd
->flags
& FL_USRARG
)
151 u64
= xatoi_positive(*++argv
);
154 if (!argv
[0] || argv
[1])
156 fd
= xopen(argv
[0], O_RDONLY
);
158 ioctl_val_on_stack
.u64
= u64
;
160 /* Store data properly wrt data size.
161 * (1) It's no-op for little-endian.
162 * (2) it's no-op for 0 and -1. Only --setro uses arg != 0 and != -1,
163 * and it is ARG_INT. --setbsz USER_VAL is also ARG_INT.
164 * Thus, we don't need to handle ARG_ULONG.
166 switch (bdcmd
->flags
& ARG_MASK
) {
168 ioctl_val_on_stack
.i
= (int)u64
;
172 ioctl_val_on_stack
.lu
= (unsigned long)u64
;
178 if (ioctl(fd
, bdcmd
->ioc
, &ioctl_val_on_stack
.u64
) == -1)
179 bb_simple_perror_msg_and_die(*argv
);
181 /* Fetch it into register(s) */
182 u64
= ioctl_val_on_stack
.u64
;
184 if (bdcmd
->flags
& FL_SCALE512
)
187 /* Zero- or one-extend the value if needed, then print */
188 switch (bdcmd
->flags
& (ARG_MASK
+FL_NORESULT
)) {
190 /* Smaller code when we use long long
191 * (gcc tail-merges printf call)
193 printf("%lld\n", (long long)(int)u64
);
196 u64
= (unsigned long)u64
;
199 printf("%llu\n", (unsigned long long)u64
);
203 if (ENABLE_FEATURE_CLEAN_UP
)