paul@181 | 1 | /* |
paul@181 | 2 | * dev.c - allocation/initialization/free routines for dev |
paul@181 | 3 | * |
paul@181 | 4 | * Copyright (C) 2001 Andreas Dilger |
paul@181 | 5 | * Copyright (C) 2003 Theodore Ts'o |
paul@181 | 6 | * |
paul@181 | 7 | * %Begin-Header% |
paul@181 | 8 | * This file may be redistributed under the terms of the |
paul@181 | 9 | * GNU Lesser General Public License. |
paul@181 | 10 | * %End-Header% |
paul@181 | 11 | */ |
paul@181 | 12 | |
paul@181 | 13 | #include "config.h" |
paul@181 | 14 | #include <stdlib.h> |
paul@181 | 15 | #include <string.h> |
paul@181 | 16 | #include <stdint.h> |
paul@181 | 17 | |
paul@181 | 18 | #include "blkidP.h" |
paul@181 | 19 | |
paul@181 | 20 | blkid_dev blkid_new_dev(void) |
paul@181 | 21 | { |
paul@181 | 22 | blkid_dev dev; |
paul@181 | 23 | |
paul@181 | 24 | if (!(dev = (blkid_dev) calloc(1, sizeof(struct blkid_struct_dev)))) |
paul@181 | 25 | return NULL; |
paul@181 | 26 | |
paul@181 | 27 | INIT_LIST_HEAD(&dev->bid_devs); |
paul@181 | 28 | INIT_LIST_HEAD(&dev->bid_tags); |
paul@181 | 29 | |
paul@181 | 30 | return dev; |
paul@181 | 31 | } |
paul@181 | 32 | |
paul@181 | 33 | void blkid_free_dev(blkid_dev dev) |
paul@181 | 34 | { |
paul@181 | 35 | if (!dev) |
paul@181 | 36 | return; |
paul@181 | 37 | |
paul@181 | 38 | DBG(DEBUG_DEV, |
paul@181 | 39 | printf(" freeing dev %s (%s)\n", dev->bid_name, dev->bid_type ? |
paul@181 | 40 | dev->bid_type : "(null)")); |
paul@181 | 41 | DBG(DEBUG_DEV, blkid_debug_dump_dev(dev)); |
paul@181 | 42 | |
paul@181 | 43 | list_del(&dev->bid_devs); |
paul@181 | 44 | while (!list_empty(&dev->bid_tags)) { |
paul@181 | 45 | blkid_tag tag = list_entry(dev->bid_tags.next, |
paul@181 | 46 | struct blkid_struct_tag, |
paul@181 | 47 | bit_tags); |
paul@181 | 48 | blkid_free_tag(tag); |
paul@181 | 49 | } |
paul@181 | 50 | free(dev->bid_name); |
paul@181 | 51 | free(dev); |
paul@181 | 52 | } |
paul@181 | 53 | |
paul@181 | 54 | /* |
paul@181 | 55 | * Given a blkid device, return its name |
paul@181 | 56 | */ |
paul@181 | 57 | extern const char *blkid_dev_devname(blkid_dev dev) |
paul@181 | 58 | { |
paul@181 | 59 | return dev->bid_name; |
paul@181 | 60 | } |
paul@181 | 61 | |
paul@181 | 62 | #ifdef CONFIG_BLKID_DEBUG |
paul@181 | 63 | void blkid_debug_dump_dev(blkid_dev dev) |
paul@181 | 64 | { |
paul@181 | 65 | struct list_head *p; |
paul@181 | 66 | |
paul@181 | 67 | if (!dev) { |
paul@181 | 68 | printf(" dev: NULL\n"); |
paul@181 | 69 | return; |
paul@181 | 70 | } |
paul@181 | 71 | |
paul@181 | 72 | printf(" dev: name = %s\n", dev->bid_name); |
paul@181 | 73 | printf(" dev: DEVNO=\"0x%0llx\"\n", (long long)dev->bid_devno); |
paul@181 | 74 | printf(" dev: TIME=\"%ld\"\n", (long)dev->bid_time); |
paul@181 | 75 | printf(" dev: PRI=\"%d\"\n", dev->bid_pri); |
paul@181 | 76 | printf(" dev: flags = 0x%08X\n", dev->bid_flags); |
paul@181 | 77 | |
paul@181 | 78 | list_for_each(p, &dev->bid_tags) { |
paul@181 | 79 | blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags); |
paul@181 | 80 | if (tag) |
paul@181 | 81 | printf(" tag: %s=\"%s\"\n", tag->bit_name, |
paul@181 | 82 | tag->bit_val); |
paul@181 | 83 | else |
paul@181 | 84 | printf(" tag: NULL\n"); |
paul@181 | 85 | } |
paul@181 | 86 | printf("\n"); |
paul@181 | 87 | } |
paul@181 | 88 | #endif |
paul@181 | 89 | |
paul@181 | 90 | /* |
paul@181 | 91 | * dev iteration routines for the public libblkid interface. |
paul@181 | 92 | * |
paul@181 | 93 | * These routines do not expose the list.h implementation, which are a |
paul@181 | 94 | * contamination of the namespace, and which force us to reveal far, far |
paul@181 | 95 | * too much of our internal implementation. I'm not convinced I want |
paul@181 | 96 | * to keep list.h in the long term, anyway. It's fine for kernel |
paul@181 | 97 | * programming, but performance is not the #1 priority for this |
paul@181 | 98 | * library, and I really don't like the tradeoff of type-safety for |
paul@181 | 99 | * performance for this application. [tytso:20030125.2007EST] |
paul@181 | 100 | */ |
paul@181 | 101 | |
paul@181 | 102 | /* |
paul@181 | 103 | * This series of functions iterate over all devices in a blkid cache |
paul@181 | 104 | */ |
paul@181 | 105 | #define DEV_ITERATE_MAGIC 0x01a5284c |
paul@181 | 106 | |
paul@181 | 107 | struct blkid_struct_dev_iterate { |
paul@181 | 108 | int magic; |
paul@181 | 109 | blkid_cache cache; |
paul@181 | 110 | char *search_type; |
paul@181 | 111 | char *search_value; |
paul@181 | 112 | struct list_head *p; |
paul@181 | 113 | }; |
paul@181 | 114 | |
paul@181 | 115 | extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache) |
paul@181 | 116 | { |
paul@181 | 117 | blkid_dev_iterate iter; |
paul@181 | 118 | |
paul@181 | 119 | iter = malloc(sizeof(struct blkid_struct_dev_iterate)); |
paul@181 | 120 | if (iter) { |
paul@181 | 121 | iter->magic = DEV_ITERATE_MAGIC; |
paul@181 | 122 | iter->cache = cache; |
paul@181 | 123 | iter->p = cache->bic_devs.next; |
paul@181 | 124 | iter->search_type = 0; |
paul@181 | 125 | iter->search_value = 0; |
paul@181 | 126 | } |
paul@181 | 127 | return (iter); |
paul@181 | 128 | } |
paul@181 | 129 | |
paul@181 | 130 | extern int blkid_dev_set_search(blkid_dev_iterate iter, |
paul@181 | 131 | char *search_type, char *search_value) |
paul@181 | 132 | { |
paul@181 | 133 | char *new_type, *new_value; |
paul@181 | 134 | |
paul@181 | 135 | if (!iter || iter->magic != DEV_ITERATE_MAGIC || !search_type || |
paul@181 | 136 | !search_value) |
paul@181 | 137 | return -1; |
paul@181 | 138 | new_type = malloc(strlen(search_type)+1); |
paul@181 | 139 | new_value = malloc(strlen(search_value)+1); |
paul@181 | 140 | if (!new_type || !new_value) { |
paul@181 | 141 | free(new_type); |
paul@181 | 142 | free(new_value); |
paul@181 | 143 | return -1; |
paul@181 | 144 | } |
paul@181 | 145 | strcpy(new_type, search_type); |
paul@181 | 146 | strcpy(new_value, search_value); |
paul@181 | 147 | free(iter->search_type); |
paul@181 | 148 | free(iter->search_value); |
paul@181 | 149 | iter->search_type = new_type; |
paul@181 | 150 | iter->search_value = new_value; |
paul@181 | 151 | return 0; |
paul@181 | 152 | } |
paul@181 | 153 | |
paul@181 | 154 | /* |
paul@181 | 155 | * Return 0 on success, -1 on error |
paul@181 | 156 | */ |
paul@181 | 157 | extern int blkid_dev_next(blkid_dev_iterate iter, |
paul@181 | 158 | blkid_dev *ret_dev) |
paul@181 | 159 | { |
paul@181 | 160 | blkid_dev dev; |
paul@181 | 161 | |
paul@181 | 162 | *ret_dev = 0; |
paul@181 | 163 | if (!iter || iter->magic != DEV_ITERATE_MAGIC) |
paul@181 | 164 | return -1; |
paul@181 | 165 | while (iter->p != &iter->cache->bic_devs) { |
paul@181 | 166 | dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs); |
paul@181 | 167 | iter->p = iter->p->next; |
paul@181 | 168 | if (iter->search_type && |
paul@181 | 169 | !blkid_dev_has_tag(dev, iter->search_type, |
paul@181 | 170 | iter->search_value)) |
paul@181 | 171 | continue; |
paul@181 | 172 | *ret_dev = dev; |
paul@181 | 173 | return 0; |
paul@181 | 174 | } |
paul@181 | 175 | return -1; |
paul@181 | 176 | } |
paul@181 | 177 | |
paul@181 | 178 | extern void blkid_dev_iterate_end(blkid_dev_iterate iter) |
paul@181 | 179 | { |
paul@181 | 180 | if (!iter || iter->magic != DEV_ITERATE_MAGIC) |
paul@181 | 181 | return; |
paul@181 | 182 | iter->magic = 0; |
paul@181 | 183 | free(iter); |
paul@181 | 184 | } |
paul@181 | 185 | |
paul@181 | 186 | #ifdef TEST_PROGRAM |
paul@181 | 187 | #ifdef HAVE_GETOPT_H |
paul@181 | 188 | #include <getopt.h> |
paul@181 | 189 | #else |
paul@181 | 190 | extern char *optarg; |
paul@181 | 191 | extern int optind; |
paul@181 | 192 | #endif |
paul@181 | 193 | |
paul@181 | 194 | void usage(char *prog) |
paul@181 | 195 | { |
paul@181 | 196 | fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask]\n", prog); |
paul@181 | 197 | fprintf(stderr, "\tList all devices and exit\n"); |
paul@181 | 198 | exit(1); |
paul@181 | 199 | } |
paul@181 | 200 | |
paul@181 | 201 | int main(int argc, char **argv) |
paul@181 | 202 | { |
paul@181 | 203 | blkid_dev_iterate iter; |
paul@181 | 204 | blkid_cache cache = NULL; |
paul@181 | 205 | blkid_dev dev; |
paul@181 | 206 | int c, ret; |
paul@181 | 207 | char *tmp; |
paul@181 | 208 | char *file = NULL; |
paul@181 | 209 | char *search_type = NULL; |
paul@181 | 210 | char *search_value = NULL; |
paul@181 | 211 | |
paul@181 | 212 | while ((c = getopt (argc, argv, "m:f:")) != EOF) |
paul@181 | 213 | switch (c) { |
paul@181 | 214 | case 'f': |
paul@181 | 215 | file = optarg; |
paul@181 | 216 | break; |
paul@181 | 217 | case 'm': |
paul@181 | 218 | blkid_debug_mask = strtoul (optarg, &tmp, 0); |
paul@181 | 219 | if (*tmp) { |
paul@181 | 220 | fprintf(stderr, "Invalid debug mask: %s\n", |
paul@181 | 221 | optarg); |
paul@181 | 222 | exit(1); |
paul@181 | 223 | } |
paul@181 | 224 | break; |
paul@181 | 225 | case '?': |
paul@181 | 226 | usage(argv[0]); |
paul@181 | 227 | } |
paul@181 | 228 | if (argc >= optind+2) { |
paul@181 | 229 | search_type = argv[optind]; |
paul@181 | 230 | search_value = argv[optind+1]; |
paul@181 | 231 | optind += 2; |
paul@181 | 232 | } |
paul@181 | 233 | if (argc != optind) |
paul@181 | 234 | usage(argv[0]); |
paul@181 | 235 | |
paul@181 | 236 | if ((ret = blkid_get_cache(&cache, file)) != 0) { |
paul@181 | 237 | fprintf(stderr, "%s: error creating cache (%d)\n", |
paul@181 | 238 | argv[0], ret); |
paul@181 | 239 | exit(1); |
paul@181 | 240 | } |
paul@181 | 241 | |
paul@181 | 242 | iter = blkid_dev_iterate_begin(cache); |
paul@181 | 243 | if (search_type) |
paul@181 | 244 | blkid_dev_set_search(iter, search_type, search_value); |
paul@181 | 245 | while (blkid_dev_next(iter, &dev) == 0) { |
paul@181 | 246 | printf("Device: %s\n", blkid_dev_devname(dev)); |
paul@181 | 247 | } |
paul@181 | 248 | blkid_dev_iterate_end(iter); |
paul@181 | 249 | |
paul@181 | 250 | |
paul@181 | 251 | blkid_put_cache(cache); |
paul@181 | 252 | return (0); |
paul@181 | 253 | } |
paul@181 | 254 | #endif |