]>
Commit | Line | Data |
---|---|---|
eb63b9b8 KZ |
1 | /* |
2 | * blockdev.c --- Do various simple block device ioctls from the command line | |
3 | * aeb, 991028 | |
4 | */ | |
5 | ||
6 | #include <stdio.h> | |
7 | #include <fcntl.h> | |
eb63b9b8 KZ |
8 | #include <stdlib.h> |
9 | #include <string.h> | |
10 | #include <unistd.h> | |
11 | #include <sys/ioctl.h> | |
12 | ||
eb63b9b8 KZ |
13 | #include "nls.h" |
14 | ||
22853e4a KZ |
15 | /* Since it is impossible to include <linux/fs.h>, let us |
16 | give the ioctls explicitly. */ | |
17 | ||
18 | #ifndef BLKROSET | |
19 | #define BLKROSET _IO(0x12,93) | |
20 | #define BLKROGET _IO(0x12,94) | |
21 | #define BLKRRPART _IO(0x12,95) | |
22 | #define BLKGETSIZE _IO(0x12,96) | |
23 | #define BLKFLSBUF _IO(0x12,97) | |
24 | #define BLKRASET _IO(0x12,98) | |
25 | #define BLKRAGET _IO(0x12,99) | |
26 | #define BLKSSZGET _IO(0x12,104) | |
e8f26419 KZ |
27 | #define BLKBSZGET _IOR(0x12,112,sizeof(int)) |
28 | #define BLKBSZSET _IOW(0x12,113,sizeof(int)) | |
22853e4a KZ |
29 | #endif |
30 | ||
612721db KZ |
31 | /* Maybe <linux/hdreg.h> could be included */ |
32 | #ifndef HDIO_GETGEO | |
33 | #define HDIO_GETGEO 0x0301 | |
34 | struct hd_geometry { | |
35 | unsigned char heads; | |
36 | unsigned char sectors; | |
37 | unsigned short cylinders; /* truncated */ | |
38 | unsigned long start; | |
39 | }; | |
40 | #endif | |
41 | ||
eb63b9b8 KZ |
42 | const char *progname; |
43 | ||
44 | struct bdc { | |
45 | char *name; | |
46 | char *iocname; | |
47 | long ioc; | |
48 | int argtype; | |
49 | #define ARGNONE 0 | |
50 | #define ARGINTA 1 | |
e8f26419 KZ |
51 | #define ARGINTAP 2 |
52 | #define ARGINTP 3 | |
53 | #define ARGINTG 4 | |
54 | #define ARGLINTG 5 | |
eb63b9b8 KZ |
55 | long argval; |
56 | char *argname; | |
57 | char *help; | |
58 | } bdcms[] = { | |
59 | #ifdef BLKROSET | |
60 | { "--setro", "BLKROSET", BLKROSET, ARGINTP, 1, NULL, N_("set read-only") }, | |
61 | { "--setrw", "BLKROSET", BLKROSET, ARGINTP, 0, NULL, N_("set read-write") }, | |
62 | #endif | |
63 | #ifdef BLKROGET | |
64 | { "--getro", "BLKROGET", BLKROGET, ARGINTG, -1, NULL, N_("get read-only") }, | |
65 | #endif | |
66 | #ifdef BLKSSZGET | |
67 | { "--getss", "BLKSSZGET", BLKSSZGET, ARGINTG, -1, NULL, N_("get sectorsize") }, | |
68 | #endif | |
e8f26419 KZ |
69 | #ifdef BLKBSZGET |
70 | { "--getbsz", "BLKBSZGET", BLKBSZGET, ARGINTG, -1, NULL, N_("get blocksize") }, | |
71 | #endif | |
72 | #ifdef BLKBSZSET | |
73 | { "--setbsz", "BLKBSZSET", BLKBSZSET, ARGINTAP, 0, "BLOCKSIZE", N_("set blocksize") }, | |
74 | #endif | |
eb63b9b8 KZ |
75 | #ifdef BLKGETSIZE |
76 | { "--getsize", "BLKGETSIZE", BLKGETSIZE, ARGLINTG, -1, NULL, N_("get size") }, | |
77 | #endif | |
78 | #ifdef BLKRASET | |
79 | { "--setra", "BLKRASET", BLKRASET, ARGINTA, 0, "READAHEAD", N_("set readahead") }, | |
80 | #endif | |
81 | #ifdef BLKRAGET | |
82 | { "--getra", "BLKRAGET", BLKRAGET, ARGLINTG, -1, NULL, N_("get readahead") }, | |
83 | #endif | |
84 | #ifdef BLKFLSBUF | |
85 | { "--flushbufs", "BLKFLSBUF", BLKFLSBUF, ARGNONE, 0, NULL, N_("flush buffers") }, | |
86 | #endif | |
87 | #ifdef BLKRRPART | |
88 | { "--rereadpt", "BLKRRPART", BLKRRPART, ARGNONE, 0, NULL, | |
89 | N_("reread partition table") }, | |
90 | #endif | |
91 | }; | |
92 | ||
93 | #define SIZE(a) (sizeof(a)/sizeof((a)[0])) | |
94 | ||
95 | static void | |
96 | usage(void) { | |
97 | int i; | |
612721db KZ |
98 | fprintf(stderr, _("Usage:\n")); |
99 | fprintf(stderr, " %s -V\n", progname); | |
100 | fprintf(stderr, _(" %s --report [devices]\n"), progname); | |
101 | fprintf(stderr, _(" %s [-v|-q] commands devices\n"), progname); | |
eb63b9b8 KZ |
102 | fprintf(stderr, _("Available commands:\n")); |
103 | for (i = 0; i < SIZE(bdcms); i++) { | |
104 | fprintf(stderr, "\t%s", bdcms[i].name); | |
105 | if (bdcms[i].argname) | |
106 | fprintf(stderr, " %s", bdcms[i].argname); | |
107 | if (bdcms[i].help) | |
108 | fprintf(stderr, "\t(%s)", _(bdcms[i].help)); | |
109 | fprintf(stderr, "\n"); | |
110 | } | |
111 | exit(1); | |
112 | } | |
113 | ||
22853e4a | 114 | static int |
eb63b9b8 KZ |
115 | find_cmd(char *s) { |
116 | int j; | |
117 | ||
118 | for (j = 0; j < SIZE(bdcms); j++) | |
119 | if (!strcmp(s, bdcms[j].name)) | |
120 | return j; | |
121 | return -1; | |
122 | } | |
123 | ||
124 | void do_commands(int fd, char **argv, int d); | |
612721db KZ |
125 | void report_header(void); |
126 | void report_device(char *device, int quiet); | |
127 | void report_all_devices(void); | |
eb63b9b8 KZ |
128 | |
129 | int | |
130 | main(int argc, char **argv) { | |
131 | int fd, d, j, k; | |
132 | char *p; | |
133 | ||
134 | /* egcs-2.91.66 is buggy and says: | |
135 | blockdev.c:93: warning: `d' might be used uninitialized */ | |
136 | d = 0; | |
137 | ||
138 | progname = argv[0]; | |
139 | if ((p = strrchr(progname, '/')) != NULL) | |
140 | progname = p+1; | |
141 | ||
142 | setlocale(LC_ALL, ""); | |
143 | bindtextdomain(PACKAGE, LOCALEDIR); | |
144 | textdomain(PACKAGE); | |
145 | ||
146 | if (argc < 2) | |
147 | usage(); | |
148 | ||
149 | /* -V not together with commands */ | |
150 | if (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) { | |
151 | printf("%s from %s\n", progname, util_linux_version); | |
152 | exit(0); | |
153 | } | |
154 | ||
612721db KZ |
155 | /* --report not together with other commands */ |
156 | if (!strcmp(argv[1], "--report")) { | |
157 | report_header(); | |
158 | if (argc > 2) { | |
159 | for (d = 2; d < argc; d++) | |
160 | report_device(argv[d], 0); | |
161 | } else { | |
162 | report_all_devices(); | |
163 | } | |
164 | exit(0); | |
165 | } | |
166 | ||
eb63b9b8 KZ |
167 | /* do each of the commands on each of the devices */ |
168 | /* devices start after last command */ | |
169 | for (d = 1; d < argc; d++) { | |
170 | j = find_cmd(argv[d]); | |
171 | if (j >= 0) { | |
e8f26419 KZ |
172 | if (bdcms[j].argtype == ARGINTA || |
173 | bdcms[j].argtype == ARGINTAP) | |
eb63b9b8 KZ |
174 | d++; |
175 | continue; | |
176 | } | |
177 | if (!strcmp(argv[d], "--")) { | |
178 | d++; | |
179 | break; | |
180 | } | |
181 | if (argv[d][0] != '-') | |
182 | break; | |
183 | } | |
184 | ||
185 | if (d >= argc) | |
186 | usage(); | |
187 | ||
188 | for (k = d; k < argc; k++) { | |
189 | fd = open(argv[k], O_RDONLY, 0); | |
190 | if (fd < 0) { | |
191 | perror(argv[k]); | |
192 | exit(1); | |
193 | } | |
194 | do_commands(fd, argv, d); | |
e8f26419 | 195 | close(fd); |
eb63b9b8 KZ |
196 | } |
197 | return 0; | |
198 | } | |
199 | ||
200 | void | |
201 | do_commands(int fd, char **argv, int d) { | |
202 | int res, i, j; | |
203 | int iarg; | |
204 | long larg; | |
205 | int verbose = 0; | |
206 | ||
207 | for (i = 1; i < d; i++) { | |
208 | if (!strcmp(argv[i], "-v")) { | |
209 | verbose = 1; | |
210 | continue; | |
211 | } | |
212 | if (!strcmp(argv[i], "-q")) { | |
213 | verbose = 0; | |
214 | continue; | |
215 | } | |
216 | ||
217 | j = find_cmd(argv[i]); | |
218 | if (j == -1) { | |
612721db KZ |
219 | fprintf(stderr, _("%s: Unknown command: %s\n"), |
220 | progname, argv[i]); | |
eb63b9b8 KZ |
221 | usage(); |
222 | } | |
223 | ||
224 | switch(bdcms[j].argtype) { | |
225 | default: | |
226 | case ARGNONE: | |
227 | res = ioctl(fd, bdcms[j].ioc, 0); | |
228 | break; | |
229 | case ARGINTA: | |
230 | if (i == d-1) { | |
231 | fprintf(stderr, _("%s requires an argument\n"), | |
232 | bdcms[j].name); | |
233 | usage(); | |
234 | } | |
235 | iarg = atoi(argv[++i]); | |
236 | res = ioctl(fd, bdcms[j].ioc, iarg); | |
237 | break; | |
e8f26419 KZ |
238 | case ARGINTAP: |
239 | if (i == d-1) { | |
240 | fprintf(stderr, _("%s requires an argument\n"), | |
241 | bdcms[j].name); | |
242 | usage(); | |
243 | } | |
244 | iarg = atoi(argv[++i]); | |
245 | res = ioctl(fd, bdcms[j].ioc, &iarg); | |
246 | break; | |
eb63b9b8 KZ |
247 | case ARGINTP: |
248 | case ARGINTG: | |
249 | iarg = bdcms[j].argval; | |
250 | res = ioctl(fd, bdcms[j].ioc, &iarg); | |
251 | break; | |
252 | case ARGLINTG: | |
253 | larg = bdcms[j].argval; | |
254 | res = ioctl(fd, bdcms[j].ioc, &larg); | |
255 | break; | |
256 | } | |
257 | if (res == -1) { | |
258 | perror(bdcms[j].iocname); | |
259 | if (verbose) | |
260 | printf("%s failed.\n", _(bdcms[j].help)); | |
261 | exit(1); | |
262 | } | |
263 | switch(bdcms[j].argtype) { | |
264 | case ARGINTG: | |
265 | if (verbose) | |
266 | printf("%s: %d\n", _(bdcms[j].help), iarg); | |
267 | else | |
268 | printf("%d\n", iarg); | |
269 | break; | |
270 | case ARGLINTG: | |
271 | if (verbose) | |
272 | printf("%s: %ld\n", _(bdcms[j].help), larg); | |
273 | else | |
274 | printf("%ld\n", larg); | |
275 | break; | |
276 | default: | |
277 | if (verbose) | |
612721db | 278 | printf(_("%s succeeded.\n"), _(bdcms[j].help)); |
eb63b9b8 KZ |
279 | break; |
280 | } | |
281 | } | |
282 | } | |
612721db KZ |
283 | |
284 | #define PROC_PARTITIONS "/proc/partitions" | |
285 | ||
286 | void | |
287 | report_all_devices(void) { | |
288 | FILE *procpt; | |
289 | char line[200]; | |
290 | char ptname[200]; | |
291 | char device[210]; | |
292 | int ma, mi, sz; | |
293 | ||
294 | procpt = fopen(PROC_PARTITIONS, "r"); | |
295 | if (!procpt) { | |
296 | fprintf(stderr, _("%s: cannot open %s\n"), | |
297 | progname, PROC_PARTITIONS); | |
298 | exit(1); | |
299 | } | |
300 | ||
301 | while (fgets(line, sizeof(line), procpt)) { | |
302 | if (sscanf (line, " %d %d %d %[^\n ]", | |
303 | &ma, &mi, &sz, ptname) != 4) | |
304 | continue; | |
305 | ||
306 | sprintf(device, "/dev/%s", ptname); | |
307 | report_device(device, 1); | |
308 | } | |
309 | } | |
310 | ||
311 | void | |
312 | report_device(char *device, int quiet) { | |
313 | int fd; | |
314 | int ro, ssz, bsz; | |
315 | long ra, sz, ss; | |
316 | struct hd_geometry g; | |
317 | ||
318 | fd = open(device, O_RDONLY | O_NONBLOCK); | |
319 | if (fd < 0) { | |
320 | if (!quiet) | |
321 | fprintf(stderr, _("%s: cannot open %s\n"), | |
322 | progname, device); | |
323 | return; | |
324 | } | |
325 | ||
326 | ro = ssz = bsz = 0; | |
327 | g.start = ra = sz = ss = 0; | |
328 | if (ioctl (fd, BLKROGET, &ro) == 0 && | |
329 | ioctl (fd, BLKRAGET, &ra) == 0 && | |
330 | ioctl (fd, BLKSSZGET, &ssz) == 0 && | |
331 | ioctl (fd, BLKBSZGET, &bsz) == 0 && | |
332 | ioctl (fd, BLKGETSIZE, &sz) == 0 && | |
333 | ioctl (fd, HDIO_GETGEO, &g) == 0) { | |
334 | printf("%s %5ld %5d %5d %10ld %10ld %s\n", | |
335 | ro ? "ro" : "rw", ra, ssz, bsz, g.start, sz, device); | |
336 | } else { | |
337 | if (!quiet) | |
338 | fprintf(stderr, _("%s: ioctl error on %s\n"), | |
339 | progname, device); | |
340 | } | |
341 | } | |
342 | ||
343 | void | |
344 | report_header() { | |
345 | printf(_("RO RA SSZ BSZ StartSec Size Device\n")); | |
346 | } |