OSDN Git Service

blkid: Output non-printing characters using ^ and M- notation
[android-x86/external-e2fsprogs.git] / misc / blkid.c
1 /*
2  * blkid.c - User command-line interface for libblkid
3  *
4  * Copyright (C) 2001 Andreas Dilger
5  *
6  * %Begin-Header%
7  * This file may be redistributed under the terms of the
8  * GNU Lesser General Public License.
9  * %End-Header%
10  */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #ifdef HAVE_GETOPT_H
16 #include <getopt.h>
17 #else
18 extern int getopt(int argc, char * const argv[], const char *optstring);
19 extern char *optarg;
20 extern int optind;
21 #endif
22
23 #define OUTPUT_VALUE_ONLY       0x0001
24 #define OUTPUT_DEVICE_ONLY      0x0002
25
26 #include "blkid/blkid.h"
27
28 const char *progname = "blkid";
29
30 static void print_version(FILE *out)
31 {
32         fprintf(out, "%s %s (%s)\n", progname, BLKID_VERSION, BLKID_DATE);
33 }
34
35 static void usage(int error)
36 {
37         FILE *out = error ? stderr : stdout;
38
39         print_version(out);
40         fprintf(out,
41                 "usage:\t%s [-c <file>] [-ghl] [-o format] "
42                 "[-s <tag>] [-t <token>]\n    [-v] [-w <file>] [dev ...]\n"
43                 "\t-c\tcache file (default: /etc/blkid.tab, /dev/null = none)\n"
44                 "\t-h\tprint this usage message and exit\n"
45                 "\t-g\tgarbage collect the blkid cache\n"
46                 "\t-s\tshow specified tag(s) (default show all tags)\n"
47                 "\t-t\tfind device with a specific token (NAME=value pair)\n"
48                 "\t-l\tlookup the the first device with arguments specified by -t\n"
49                 "\t-v\tprint version and exit\n"
50                 "\t-w\twrite cache to different file (/dev/null = no write)\n"
51                 "\tdev\tspecify device(s) to probe (default: all devices)\n",
52                 progname);
53         exit(error);
54 }
55
56 /*
57  * This function does "safe" printing.  It will convert non-printable
58  * ASCII characters using '^' and M- notation.
59  */
60 static void safe_print(const char *cp, int len)
61 {
62         unsigned char   ch;
63
64         if (len < 0)
65                 len = strlen(cp);
66
67         while (len--) {
68                 ch = *cp++;
69                 if (ch > 128) {
70                         fputs("M-", stdout);
71                         ch -= 128;
72                 }
73                 if ((ch < 32) || (ch == 0x7f)) {
74                         fputc('^', stdout);
75                         ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
76                 }
77                 fputc(ch, stdout);
78         }
79 }
80
81 static void print_tags(blkid_dev dev, char *show[], int numtag, int output)
82 {
83         blkid_tag_iterate       iter;
84         const char              *type, *value;
85         int                     i, first = 1;
86
87         if (!dev)
88                 return;
89
90         if (output & OUTPUT_DEVICE_ONLY) {
91                 printf("%s\n", blkid_dev_devname(dev));
92                 return;
93         }
94
95         iter = blkid_tag_iterate_begin(dev);
96         while (blkid_tag_next(iter, &type, &value) == 0) {
97                 if (numtag && show) {
98                         for (i=0; i < numtag; i++)
99                                 if (!strcmp(type, show[i]))
100                                         break;
101                         if (i >= numtag)
102                                 continue;
103                 }
104                 if (output & OUTPUT_VALUE_ONLY) {
105                         fputs(value, stdout);
106                         fputc('\n', stdout);
107                 } else {
108                         if (first) {
109                                 printf("%s: ", blkid_dev_devname(dev));
110                                 first = 0;
111                         }
112                         fputs(type, stdout);
113                         fputs("=\"", stdout);
114                         safe_print(value, -1);
115                         fputs("\" ", stdout);
116                 }
117         }
118         blkid_tag_iterate_end(iter);
119
120         if (!first && !(output & OUTPUT_VALUE_ONLY))
121                 printf("\n");
122 }
123
124 int main(int argc, char **argv)
125 {
126         blkid_cache cache = NULL;
127         char *devices[128] = { NULL, };
128         char *show[128] = { NULL, };
129         char *search_type = NULL, *search_value = NULL;
130         char *read = NULL;
131         char *write = NULL;
132         unsigned int numdev = 0, numtag = 0;
133         int version = 0;
134         int err = 4;
135         unsigned int i;
136         int output_format = 0;
137         int lookup = 0, gc = 0;
138         int c;
139
140         while ((c = getopt (argc, argv, "c:f:ghlo:s:t:w:v")) != EOF)
141                 switch (c) {
142                 case 'c':
143                         if (optarg && !*optarg)
144                                 read = NULL;
145                         else
146                                 read = optarg;
147                         if (!write)
148                                 write = read;
149                         break;
150                 case 'l':
151                         lookup++;
152                         break;
153                 case 'g':
154                         gc = 1;
155                         break;
156                 case 'o':
157                         if (!strcmp(optarg, "value"))
158                                 output_format = OUTPUT_VALUE_ONLY;
159                         else if (!strcmp(optarg, "device"))
160                                 output_format = OUTPUT_DEVICE_ONLY;
161                         else if (!strcmp(optarg, "full"))
162                                 output_format = 0;
163                         else {
164                                 fprintf(stderr, "Invalid output format %s.  Chose from value, device, or full\n", optarg);
165                                 exit(1);
166                         }
167                         break;
168                 case 's':
169                         if (numtag >= sizeof(show) / sizeof(*show)) {
170                                 fprintf(stderr, "Too many tags specified\n");
171                                 usage(err);
172                         }
173                         show[numtag++] = optarg;
174                         break;
175                 case 't':
176                         if (search_type) {
177                                 fprintf(stderr, "Can only search for "
178                                                 "one NAME=value pair\n");
179                                 usage(err);
180                         }
181                         if (blkid_parse_tag_string(optarg,
182                                                    &search_type,
183                                                    &search_value)) {
184                                 fprintf(stderr, "-t needs NAME=value pair\n");
185                                 usage(err);
186                         }
187                         break;
188                 case 'v':
189                         version = 1;
190                         break;
191                 case 'w':
192                         if (optarg && !*optarg)
193                                 write = NULL;
194                         else
195                                 write = optarg;
196                         break;
197                 case 'h':
198                         err = 0;
199                 default:
200                         usage(err);
201                 }
202
203         while (optind < argc)
204                 devices[numdev++] = argv[optind++];
205
206         if (version) {
207                 print_version(stdout);
208                 goto exit;
209         }
210
211         if (blkid_get_cache(&cache, read) < 0)
212                 goto exit;
213
214         err = 2;
215         if (gc) {
216                 blkid_gc_cache(cache);
217         } else if (lookup) {
218                 blkid_dev dev;
219
220                 if (!search_type) {
221                         fprintf(stderr, "The lookup option requires a "
222                                 "search type specified using -t\n");
223                         exit(1);
224                 }
225                 /* Load any additional devices not in the cache */
226                 for (i = 0; i < numdev; i++)
227                         blkid_get_dev(cache, devices[i], BLKID_DEV_NORMAL);
228
229                 if ((dev = blkid_find_dev_with_tag(cache, search_type,
230                                                    search_value))) {
231                         print_tags(dev, show, numtag, output_format);
232                         err = 0;
233                 }
234         /* If we didn't specify a single device, show all available devices */
235         } else if (!numdev) {
236                 blkid_dev_iterate       iter;
237                 blkid_dev               dev;
238
239                 blkid_probe_all(cache);
240
241                 iter = blkid_dev_iterate_begin(cache);
242                 blkid_dev_set_search(iter, search_type, search_value);
243                 while (blkid_dev_next(iter, &dev) == 0) {
244                         dev = blkid_verify(cache, dev);
245                         if (!dev)
246                                 continue;
247                         print_tags(dev, show, numtag, output_format);
248                         err = 0;
249                 }
250                 blkid_dev_iterate_end(iter);
251         /* Add all specified devices to cache (optionally display tags) */
252         } else for (i = 0; i < numdev; i++) {
253                 blkid_dev dev = blkid_get_dev(cache, devices[i],
254                                                   BLKID_DEV_NORMAL);
255
256                 if (dev) {
257                         if (search_type && 
258                             !blkid_dev_has_tag(dev, search_type, 
259                                                search_value))
260                                 continue;
261                         print_tags(dev, show, numtag, output_format);
262                         err = 0;
263                 }
264         }
265
266 exit:
267         if (search_type)
268                 free(search_type);
269         if (search_value)
270                 free(search_value);
271         blkid_put_cache(cache);
272         return err;
273 }