]> git.ipfire.org Git - thirdparty/util-linux.git/blame - disk-utils/blockdev.c
Imported from util-linux-2.11o tarball.
[thirdparty/util-linux.git] / disk-utils / blockdev.c
CommitLineData
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
34struct 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
42const char *progname;
43
44struct 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
95static void
96usage(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 114static int
eb63b9b8
KZ
115find_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
124void do_commands(int fd, char **argv, int d);
612721db
KZ
125void report_header(void);
126void report_device(char *device, int quiet);
127void report_all_devices(void);
eb63b9b8
KZ
128
129int
130main(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
200void
201do_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
286void
287report_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
311void
312report_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
343void
344report_header() {
345 printf(_("RO RA SSZ BSZ StartSec Size Device\n"));
346}