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