2 * cache.c - allocation/initialization/free routines for cache
4 * Copyright (C) 2001 Andreas Dilger
5 * Copyright (C) 2003 Theodore Ts'o
8 * This file may be redistributed under the terms of the
9 * GNU Lesser General Public License.
21 #ifdef HAVE_SYS_STAT_H
27 int blkid_debug_mask = 0;
32 * @short_description: basic routines to work with libblkid cache
34 * Block device information is normally kept in a cache file /etc/blkid.tab and is
35 * verified to still be valid before being returned to the user (if the user has
36 * read permission on the raw block device, otherwise not). The cache file also
37 * allows unprivileged users (normally anyone other than root, or those not in the
38 * "disk" group) to locate devices by label/id. The standard location of the
39 * cache file can be overridden by the environment variable BLKID_FILE.
41 * In situations where one is getting information about a single known device, it
42 * does not impact performance whether the cache is used or not (unless you are
43 * not able to read the block device directly). If you are dealing with multiple
44 * devices, use of the cache is highly recommended (even if empty) as devices will
45 * be scanned at most one time and the on-disk cache will be updated if possible.
46 * There is rarely a reason not to use the cache.
48 * In some cases (modular kernels), block devices are not even visible until after
49 * they are accessed the first time, so it is critical that there is some way to
50 * locate these devices without enumerating only visible devices, so the use of
51 * the cache file is required in this situation.
54 #if 0 /* ifdef CONFIG_BLKID_DEBUG */
55 static blkid_debug_dump_cache(int mask, blkid_cache cache)
60 printf("cache: NULL\n");
64 printf("cache: time = %lu\n", cache->bic_time);
65 printf("cache: flags = 0x%08X\n", cache->bic_flags);
67 list_for_each(p, &cache->bic_devs) {
68 blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
69 blkid_debug_dump_dev(dev);
74 #ifdef CONFIG_BLKID_DEBUG
75 void blkid_init_debug(int mask)
77 if (blkid_debug_mask & DEBUG_INIT)
82 char *dstr = getenv("LIBBLKID_DEBUG");
85 dstr = getenv("BLKID_DEBUG"); /* for backward compatibility */
87 blkid_debug_mask = strtoul(dstr, 0, 0);
89 blkid_debug_mask = mask;
92 printf("libblkid: debug mask set to 0x%04x.\n", blkid_debug_mask);
94 blkid_debug_mask |= DEBUG_INIT;
98 /* returns allocated path to cache */
99 char *blkid_get_cache_filename(struct blkid_config *conf)
103 filename = safe_getenv("BLKID_FILE");
105 filename = blkid_strdup(filename);
107 filename = blkid_strdup(conf->cachefile);
109 struct blkid_config *c = blkid_read_config(NULL);
111 filename = blkid_strdup(BLKID_CACHE_FILE);
113 filename = c->cachefile; /* already allocated */
115 blkid_free_config(c);
123 * @cache: pointer to return cache handler
124 * @filename: path to the cache file or NULL for the default path
126 * Allocates and initialize librray cache handler.
128 * Returns: 0 on success or number less than zero in case of error.
130 int blkid_get_cache(blkid_cache *ret_cache, const char *filename)
136 DBG(DEBUG_CACHE, printf("creating blkid cache (using %s)\n",
137 filename ? filename : "default cache"));
139 if (!(cache = (blkid_cache) calloc(1, sizeof(struct blkid_struct_cache))))
140 return -BLKID_ERR_MEM;
142 INIT_LIST_HEAD(&cache->bic_devs);
143 INIT_LIST_HEAD(&cache->bic_tags);
145 if (filename && !*filename)
148 cache->bic_filename = blkid_strdup(filename);
150 cache->bic_filename = blkid_get_cache_filename(NULL);
152 blkid_read_cache(cache);
159 * @cache: cache handler
161 * Saves changes to cache file.
163 void blkid_put_cache(blkid_cache cache)
168 (void) blkid_flush_cache(cache);
170 DBG(DEBUG_CACHE, printf("freeing cache struct\n"));
172 /* DBG(DEBUG_CACHE, blkid_debug_dump_cache(cache)); */
174 while (!list_empty(&cache->bic_devs)) {
175 blkid_dev dev = list_entry(cache->bic_devs.next,
176 struct blkid_struct_dev,
181 while (!list_empty(&cache->bic_tags)) {
182 blkid_tag tag = list_entry(cache->bic_tags.next,
183 struct blkid_struct_tag,
186 while (!list_empty(&tag->bit_names)) {
187 blkid_tag bad = list_entry(tag->bit_names.next,
188 struct blkid_struct_tag,
191 DBG(DEBUG_CACHE, printf("warning: unfreed tag %s=%s\n",
192 bad->bit_name, bad->bit_val));
198 blkid_free_probe(cache->probe);
200 free(cache->bic_filename);
206 * @cache: cache handler
208 * Removes garbage (non-existing devices) from the cache.
210 void blkid_gc_cache(blkid_cache cache)
212 struct list_head *p, *pnext;
218 list_for_each_safe(p, pnext, &cache->bic_devs) {
219 blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
222 if (stat(dev->bid_name, &st) < 0) {
224 printf("freeing %s\n", dev->bid_name));
226 cache->bic_flags |= BLKID_BIC_FL_CHANGED;
229 printf("Device %s exists\n", dev->bid_name));
235 int main(int argc, char** argv)
237 blkid_cache cache = NULL;
240 blkid_init_debug(DEBUG_ALL);
243 fprintf(stderr, "Usage: %s [filename] \n", argv[0]);
247 if ((ret = blkid_get_cache(&cache, argv[1])) < 0) {
248 fprintf(stderr, "error %d parsing cache file %s\n", ret,
249 argv[1] ? argv[1] : BLKID_CACHE_FILE);
252 if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
253 fprintf(stderr, "%s: error creating cache (%d)\n",
257 if ((ret = blkid_probe_all(cache) < 0))
258 fprintf(stderr, "error probing devices\n");
260 blkid_put_cache(cache);