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 18extern int getopt(int argc, char * const argv[], const char *optstring); 19extern char *optarg; 20extern int optind; 21#endif 22 23#define OUTPUT_VALUE_ONLY 0x0001 24#define OUTPUT_DEVICE_ONLY 0x0002 25 26#include "blkid/blkid.h" 27 28const char *progname = "blkid"; 29 30static void print_version(FILE *out) 31{ 32 fprintf(out, "%s %s (%s)\n", progname, BLKID_VERSION, BLKID_DATE); 33} 34 35static 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 */ 60static 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 81static 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 124int 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 266exit: 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} 274