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