blob: a780d2238e0c5c940a22d0980fad9a7e3e940f05 [file] [log] [blame]
Sergey Naumov289aff82010-09-06 13:35:58 +02001/*
2 * blockdev implementation for busybox
3 *
4 * Copyright (C) 2010 Sergey Naumov <sknaumov@gmail.com>
5 *
Denys Vlasenko3d4a8f82010-09-06 16:22:25 +02006 * Licensed under GPLv2, see file LICENSE in this source tree.
Sergey Naumov289aff82010-09-06 13:35:58 +02007 */
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
Denys Vlasenkob4e6b412010-09-06 14:15:46 +020020//usage: "OPTION BLOCKDEV"
Sergey Naumov289aff82010-09-06 13:35:58 +020021//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
38enum {
39 ARG_NONE = 0,
40 ARG_INT = 1,
41 ARG_ULONG = 2,
42 ARG_ULLONG = 3,
43 ARG_MASK = 3,
44
45 FL_USRARG = 4, /* argument is provided by user */
46 FL_NORESULT = 8,
47};
48
49struct bdc {
50 uint32_t ioc; /* ioctl code */
51 const char name[sizeof("flushbufs")]; /* "--setfoo" wothout "--" */
52 uint8_t flags;
53 int8_t argval; /* default argument value */
54};
55
56static const struct bdc bdcommands[] = {
57 {
58 .ioc = BLKROSET,
59 .name = "setro",
60 .flags = ARG_INT + FL_NORESULT,
61 .argval = 1,
62 },{
63 .ioc = BLKROSET,
64 .name = "setrw",
65 .flags = ARG_INT + FL_NORESULT,
66 .argval = 0,
67 },{
68 .ioc = BLKROGET,
69 .name = "getro",
70 .flags = ARG_INT,
71 .argval = -1,
72 },{
73 .ioc = BLKSSZGET,
74 .name = "getss",
75 .flags = ARG_INT,
76 .argval = -1,
77 },{
78 .ioc = BLKBSZGET,
79 .name = "getbsz",
80 .flags = ARG_INT,
81 .argval = -1,
82 },{
83 .ioc = BLKBSZSET,
84 .name = "setbsz",
85 .flags = ARG_INT + FL_NORESULT + FL_USRARG,
86 .argval = 0,
87 },{
88 .ioc = BLKGETSIZE,
89 .name = "getsize",
90 .flags = ARG_ULONG,
91 .argval = -1,
92 },{
93 .ioc = BLKGETSIZE64,
94 .name = "getsize64",
95 .flags = ARG_ULLONG,
96 .argval = -1,
97 },{
98 .ioc = BLKFLSBUF,
99 .name = "flushbufs",
100 .flags = ARG_NONE + FL_NORESULT,
101 .argval = 0,
102 },{
103 .ioc = BLKRRPART,
104 .name = "rereadpt",
105 .flags = ARG_NONE + FL_NORESULT,
106 .argval = 0,
107 }
108};
109
110static const struct bdc *find_cmd(const char *s)
111{
Denys Vlasenko264bdad2010-09-06 15:34:15 +0200112 const struct bdc *bdcmd = bdcommands;
113 if (s[0] == '-' && s[1] == '-') {
114 s += 2;
115 do {
116 if (strcmp(s, bdcmd->name) == 0)
117 return bdcmd;
118 bdcmd++;
119 } while (bdcmd != bdcommands + ARRAY_SIZE(bdcommands));
120 }
Sergey Naumov289aff82010-09-06 13:35:58 +0200121 bb_show_usage();
122}
123
124int blockdev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
125int blockdev_main(int argc, char **argv)
126{
127 const struct bdc *bdcmd;
128 void *ioctl_ptr;
129 int fd;
130 int iarg;
131 unsigned long lu;
132 unsigned long long llu;
133
134 if ((unsigned)(argc - 3) > 1) /* must have 2 or 3 args */
135 bb_show_usage();
136
137 bdcmd = find_cmd(*++argv);
138
139 llu = (int)bdcmd->argval;
140 if (bdcmd->flags & FL_USRARG)
141 llu = xatoi_positive(*++argv);
142 lu = llu;
143 iarg = llu;
144
Denys Vlasenkoa35dfe62010-09-06 16:31:18 +0200145 if (!*++argv || argv[1])
Sergey Naumov289aff82010-09-06 13:35:58 +0200146 bb_show_usage();
147 fd = xopen(*argv, O_RDONLY);
148
149 ioctl_ptr = NULL;
150 switch (bdcmd->flags & ARG_MASK) {
151 case ARG_INT:
152 ioctl_ptr = &iarg;
153 break;
154 case ARG_ULONG:
155 ioctl_ptr = &lu;
156 break;
157 case ARG_ULLONG:
158 ioctl_ptr = &llu;
159 break;
160 }
161
162 if (ioctl(fd, bdcmd->ioc, ioctl_ptr) == -1)
163 bb_simple_perror_msg_and_die(*argv);
164
165 switch (bdcmd->flags & (ARG_MASK+FL_NORESULT)) {
166 case ARG_INT:
167 /* Smaller code when we use long long
168 * (gcc tail-merges printf call)
169 */
170 printf("%lld\n", (long long)iarg);
171 break;
172 case ARG_ULONG:
173 llu = lu;
174 /* FALLTHROUGH */
175 case ARG_ULLONG:
176 printf("%llu\n", llu);
177 break;
178 }
179
180 if (ENABLE_FEATURE_CLEAN_UP)
181 close(fd);
182 return EXIT_SUCCESS;
183}