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