blob: 9491331abc05911496f33820dcb71c7ff59a5cc0 [file] [log] [blame]
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001/*
2 * dev.c - allocation/initialization/free routines for dev
3 *
4 * Copyright (C) 2001 Andreas Dilger
5 * Copyright (C) 2003 Theodore Ts'o
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the
9 * GNU Lesser General Public License.
10 * %End-Header%
11 */
12
13#include <stdlib.h>
14#include <string.h>
15
16#include "blkidP.h"
17
18/*
19 * NOTE: reference manual is not structured as code. The following section is a generic
20 * section for all high-level cache search+iterate routines.
21 */
22
23/**
24 * SECTION:search
25 * @title: Search and iterate
26 * @short_description: search devices and iterate over devices in the cache.
27 *
28 * Note that high-level probing API provides information about superblocks
29 * (filesystems/raids) only. For partitions and topology is necessary to use
30 * the low-level API.
31 */
32
33blkid_dev blkid_new_dev(void)
34{
35 blkid_dev dev;
36
37 if (!(dev = (blkid_dev) calloc(1, sizeof(struct blkid_struct_dev))))
38 return NULL;
39
40 INIT_LIST_HEAD(&dev->bid_devs);
41 INIT_LIST_HEAD(&dev->bid_tags);
42
43 return dev;
44}
45
46void blkid_free_dev(blkid_dev dev)
47{
48 if (!dev)
49 return;
50
bigbiff7b4c7a62015-01-01 19:44:14 -050051 DBG(DEV,
52 ul_debug(" freeing dev %s (%s)", dev->bid_name, dev->bid_type ?
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050053 dev->bid_type : "(null)"));
bigbiff7b4c7a62015-01-01 19:44:14 -050054 DBG(DEV, blkid_debug_dump_dev(dev));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050055
56 list_del(&dev->bid_devs);
57 while (!list_empty(&dev->bid_tags)) {
58 blkid_tag tag = list_entry(dev->bid_tags.next,
59 struct blkid_struct_tag,
60 bit_tags);
61 blkid_free_tag(tag);
62 }
63 free(dev->bid_name);
64 free(dev);
65}
66
67/*
68 * Given a blkid device, return its name
69 */
bigbiff7b4c7a62015-01-01 19:44:14 -050070const char *blkid_dev_devname(blkid_dev dev)
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050071{
72 return dev ? dev->bid_name : NULL;
73}
74
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050075void blkid_debug_dump_dev(blkid_dev dev)
76{
77 struct list_head *p;
78
79 if (!dev) {
80 printf(" dev: NULL\n");
81 return;
82 }
83
bigbiff7b4c7a62015-01-01 19:44:14 -050084 fprintf(stderr, " dev: name = %s\n", dev->bid_name);
85 fprintf(stderr, " dev: DEVNO=\"0x%0llx\"\n", (long long)dev->bid_devno);
86 fprintf(stderr, " dev: TIME=\"%ld.%ld\"\n", (long)dev->bid_time, (long)dev->bid_utime);
87 fprintf(stderr, " dev: PRI=\"%d\"\n", dev->bid_pri);
88 fprintf(stderr, " dev: flags = 0x%08X\n", dev->bid_flags);
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050089
90 list_for_each(p, &dev->bid_tags) {
91 blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
92 if (tag)
bigbiff7b4c7a62015-01-01 19:44:14 -050093 fprintf(stderr, " tag: %s=\"%s\"\n", tag->bit_name,
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050094 tag->bit_val);
95 else
bigbiff7b4c7a62015-01-01 19:44:14 -050096 fprintf(stderr, " tag: NULL\n");
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050097 }
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050098}
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050099
100/*
101 * dev iteration routines for the public libblkid interface.
102 *
103 * These routines do not expose the list.h implementation, which are a
104 * contamination of the namespace, and which force us to reveal far, far
105 * too much of our internal implemenation. I'm not convinced I want
106 * to keep list.h in the long term, anyway. It's fine for kernel
107 * programming, but performance is not the #1 priority for this
108 * library, and I really don't like the tradeoff of type-safety for
109 * performance for this application. [tytso:20030125.2007EST]
110 */
111
112/*
113 * This series of functions iterate over all devices in a blkid cache
114 */
115#define DEV_ITERATE_MAGIC 0x01a5284c
116
117struct blkid_struct_dev_iterate {
118 int magic;
119 blkid_cache cache;
120 char *search_type;
121 char *search_value;
122 struct list_head *p;
123};
124
bigbiff7b4c7a62015-01-01 19:44:14 -0500125blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache)
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500126{
127 blkid_dev_iterate iter;
128
bigbiff7b4c7a62015-01-01 19:44:14 -0500129 if (!cache) {
130 errno = EINVAL;
131 return NULL;
132 }
133
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500134 iter = malloc(sizeof(struct blkid_struct_dev_iterate));
135 if (iter) {
136 iter->magic = DEV_ITERATE_MAGIC;
137 iter->cache = cache;
138 iter->p = cache->bic_devs.next;
139 iter->search_type = 0;
140 iter->search_value = 0;
141 }
142 return iter;
143}
144
bigbiff7b4c7a62015-01-01 19:44:14 -0500145int blkid_dev_set_search(blkid_dev_iterate iter,
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500146 char *search_type, char *search_value)
147{
148 char *new_type, *new_value;
149
150 if (!iter || iter->magic != DEV_ITERATE_MAGIC || !search_type ||
151 !search_value)
152 return -1;
153 new_type = malloc(strlen(search_type)+1);
154 new_value = malloc(strlen(search_value)+1);
155 if (!new_type || !new_value) {
156 free(new_type);
157 free(new_value);
158 return -1;
159 }
160 strcpy(new_type, search_type);
161 strcpy(new_value, search_value);
162 free(iter->search_type);
163 free(iter->search_value);
164 iter->search_type = new_type;
165 iter->search_value = new_value;
166 return 0;
167}
168
169/*
170 * Return 0 on success, -1 on error
171 */
bigbiff7b4c7a62015-01-01 19:44:14 -0500172int blkid_dev_next(blkid_dev_iterate iter,
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500173 blkid_dev *ret_dev)
174{
175 blkid_dev dev;
176
177 if (!ret_dev || !iter || iter->magic != DEV_ITERATE_MAGIC)
178 return -1;
179 *ret_dev = 0;
180 while (iter->p != &iter->cache->bic_devs) {
181 dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs);
182 iter->p = iter->p->next;
183 if (iter->search_type &&
184 !blkid_dev_has_tag(dev, iter->search_type,
185 iter->search_value))
186 continue;
187 *ret_dev = dev;
188 return 0;
189 }
190 return -1;
191}
192
bigbiff7b4c7a62015-01-01 19:44:14 -0500193void blkid_dev_iterate_end(blkid_dev_iterate iter)
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500194{
195 if (!iter || iter->magic != DEV_ITERATE_MAGIC)
196 return;
197 iter->magic = 0;
198 free(iter->search_type);
199 free(iter->search_value);
200 free(iter);
201}
202
203#ifdef TEST_PROGRAM
204#ifdef HAVE_GETOPT_H
205#include <getopt.h>
206#else
207extern char *optarg;
208extern int optind;
209#endif
210
211void __attribute__((__noreturn__)) usage(char *prog)
212{
213 fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask]\n", prog);
214 fprintf(stderr, "\tList all devices and exit\n");
215 exit(1);
216}
217
218int main(int argc, char **argv)
219{
220 blkid_dev_iterate iter;
221 blkid_cache cache = NULL;
222 blkid_dev dev;
223 int c, ret;
224 char *tmp;
225 char *file = NULL;
226 char *search_type = NULL;
227 char *search_value = NULL;
228
229 while ((c = getopt (argc, argv, "m:f:")) != EOF)
230 switch (c) {
231 case 'f':
232 file = optarg;
233 break;
234 case 'm':
235 {
236 int mask = strtoul (optarg, &tmp, 0);
237 if (*tmp) {
238 fprintf(stderr, "Invalid debug mask: %s\n",
239 optarg);
240 exit(1);
241 }
242 blkid_init_debug(mask);
243 break;
244 }
245 case '?':
246 usage(argv[0]);
247 }
248 if (argc >= optind+2) {
249 search_type = argv[optind];
250 search_value = argv[optind+1];
251 optind += 2;
252 }
253 if (argc != optind)
254 usage(argv[0]);
255
256 if ((ret = blkid_get_cache(&cache, file)) != 0) {
257 fprintf(stderr, "%s: error creating cache (%d)\n",
258 argv[0], ret);
259 exit(1);
260 }
261
262 iter = blkid_dev_iterate_begin(cache);
263 if (search_type)
264 blkid_dev_set_search(iter, search_type, search_value);
265 while (blkid_dev_next(iter, &dev) == 0) {
266 printf("Device: %s\n", blkid_dev_devname(dev));
267 }
268 blkid_dev_iterate_end(iter);
269
270
271 blkid_put_cache(cache);
272 return (0);
273}
274#endif