diff options
author | bigbiff bigbiff <bigbiff@teamw.in> | 2013-02-23 02:55:50 +0100 |
---|---|---|
committer | bigbiff bigbiff <bigbiff@teamw.in> | 2013-02-25 15:06:46 +0100 |
commit | e60683a0d553b6488c564863f4e48954944fb0f8 (patch) | |
tree | 9364f97cb88b7c1359f5f06dfb32150a78168c31 /libblkid/cache.c | |
parent | Fix building of updater for 4.2 environment (diff) | |
download | android_bootable_recovery-e60683a0d553b6488c564863f4e48954944fb0f8.tar android_bootable_recovery-e60683a0d553b6488c564863f4e48954944fb0f8.tar.gz android_bootable_recovery-e60683a0d553b6488c564863f4e48954944fb0f8.tar.bz2 android_bootable_recovery-e60683a0d553b6488c564863f4e48954944fb0f8.tar.lz android_bootable_recovery-e60683a0d553b6488c564863f4e48954944fb0f8.tar.xz android_bootable_recovery-e60683a0d553b6488c564863f4e48954944fb0f8.tar.zst android_bootable_recovery-e60683a0d553b6488c564863f4e48954944fb0f8.zip |
Diffstat (limited to 'libblkid/cache.c')
-rw-r--r-- | libblkid/cache.c | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/libblkid/cache.c b/libblkid/cache.c new file mode 100644 index 000000000..cc2cf8e94 --- /dev/null +++ b/libblkid/cache.c @@ -0,0 +1,275 @@ +/* + * cache.c - allocation/initialization/free routines for cache + * + * Copyright (C) 2001 Andreas Dilger + * Copyright (C) 2003 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#include "blkidP.h" +#include "env.h" + +int blkid_debug_mask = 0; + +/** + * SECTION:cache + * @title: Cache + * @short_description: basic routines to work with libblkid cache + * + * Block device information is normally kept in a cache file blkid.tab and is + * verified to still be valid before being returned to the user (if the user has + * read permission on the raw block device, otherwise not). The cache file also + * allows unprivileged users (normally anyone other than root, or those not in the + * "disk" group) to locate devices by label/id. The standard location of the + * cache file can be overridden by the environment variable BLKID_FILE. + * + * In situations where one is getting information about a single known device, it + * does not impact performance whether the cache is used or not (unless you are + * not able to read the block device directly). If you are dealing with multiple + * devices, use of the cache is highly recommended (even if empty) as devices will + * be scanned at most one time and the on-disk cache will be updated if possible. + * There is rarely a reason not to use the cache. + * + * In some cases (modular kernels), block devices are not even visible until after + * they are accessed the first time, so it is critical that there is some way to + * locate these devices without enumerating only visible devices, so the use of + * the cache file is required in this situation. + */ + +#if 0 /* ifdef CONFIG_BLKID_DEBUG */ +static blkid_debug_dump_cache(int mask, blkid_cache cache) +{ + struct list_head *p; + + if (!cache) { + printf("cache: NULL\n"); + return; + } + + printf("cache: time = %lu\n", cache->bic_time); + printf("cache: flags = 0x%08X\n", cache->bic_flags); + + list_for_each(p, &cache->bic_devs) { + blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs); + blkid_debug_dump_dev(dev); + } +} +#endif + +#ifdef CONFIG_BLKID_DEBUG +void blkid_init_debug(int mask) +{ + if (blkid_debug_mask & DEBUG_INIT) + return; + + if (!mask) + { + char *dstr = getenv("LIBBLKID_DEBUG"); + + if (!dstr) + dstr = getenv("BLKID_DEBUG"); /* for backward compatibility */ + if (dstr) + blkid_debug_mask = strtoul(dstr, 0, 0); + } else + blkid_debug_mask = mask; + + if (blkid_debug_mask) + printf("libblkid: debug mask set to 0x%04x.\n", blkid_debug_mask); + + blkid_debug_mask |= DEBUG_INIT; +} +#endif + +static const char *get_default_cache_filename(void) +{ + struct stat st; + + if (stat(BLKID_RUNTIME_TOPDIR, &st) == 0 && S_ISDIR(st.st_mode)) + return BLKID_CACHE_FILE; /* cache in /run */ + + return BLKID_CACHE_FILE_OLD; /* cache in /etc */ +} + +/* returns allocated path to cache */ +char *blkid_get_cache_filename(struct blkid_config *conf) +{ + char *filename; + + filename = safe_getenv("BLKID_FILE"); + if (filename) + filename = strdup(filename); + else if (conf) + filename = conf->cachefile ? strdup(conf->cachefile) : NULL; + else { + struct blkid_config *c = blkid_read_config(NULL); + if (!c) + filename = strdup(get_default_cache_filename()); + else { + filename = c->cachefile; /* already allocated */ + c->cachefile = NULL; + blkid_free_config(c); + } + } + return filename; +} + +/** + * blkid_get_cache: + * @cache: pointer to return cache handler + * @filename: path to the cache file or NULL for the default path + * + * Allocates and initialize librray cache handler. + * + * Returns: 0 on success or number less than zero in case of error. + */ +int blkid_get_cache(blkid_cache *ret_cache, const char *filename) +{ + blkid_cache cache; + + if (!ret_cache) + return -BLKID_ERR_PARAM; + + blkid_init_debug(0); + + DBG(DEBUG_CACHE, printf("creating blkid cache (using %s)\n", + filename ? filename : "default cache")); + + if (!(cache = (blkid_cache) calloc(1, sizeof(struct blkid_struct_cache)))) + return -BLKID_ERR_MEM; + + INIT_LIST_HEAD(&cache->bic_devs); + INIT_LIST_HEAD(&cache->bic_tags); + + if (filename && !*filename) + filename = NULL; + if (filename) + cache->bic_filename = strdup(filename); + else + cache->bic_filename = blkid_get_cache_filename(NULL); + + blkid_read_cache(cache); + *ret_cache = cache; + return 0; +} + +/** + * blkid_put_cache: + * @cache: cache handler + * + * Saves changes to cache file. + */ +void blkid_put_cache(blkid_cache cache) +{ + if (!cache) + return; + + (void) blkid_flush_cache(cache); + + DBG(DEBUG_CACHE, printf("freeing cache struct\n")); + + /* DBG(DEBUG_CACHE, blkid_debug_dump_cache(cache)); */ + + while (!list_empty(&cache->bic_devs)) { + blkid_dev dev = list_entry(cache->bic_devs.next, + struct blkid_struct_dev, + bid_devs); + blkid_free_dev(dev); + } + + while (!list_empty(&cache->bic_tags)) { + blkid_tag tag = list_entry(cache->bic_tags.next, + struct blkid_struct_tag, + bit_tags); + + while (!list_empty(&tag->bit_names)) { + blkid_tag bad = list_entry(tag->bit_names.next, + struct blkid_struct_tag, + bit_names); + + DBG(DEBUG_CACHE, printf("warning: unfreed tag %s=%s\n", + bad->bit_name, bad->bit_val)); + blkid_free_tag(bad); + } + blkid_free_tag(tag); + } + + blkid_free_probe(cache->probe); + + free(cache->bic_filename); + free(cache); +} + +/** + * blkid_gc_cache: + * @cache: cache handler + * + * Removes garbage (non-existing devices) from the cache. + */ +void blkid_gc_cache(blkid_cache cache) +{ + struct list_head *p, *pnext; + struct stat st; + + if (!cache) + return; + + list_for_each_safe(p, pnext, &cache->bic_devs) { + blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs); + if (stat(dev->bid_name, &st) < 0) { + DBG(DEBUG_CACHE, + printf("freeing %s\n", dev->bid_name)); + blkid_free_dev(dev); + cache->bic_flags |= BLKID_BIC_FL_CHANGED; + } else { + DBG(DEBUG_CACHE, + printf("Device %s exists\n", dev->bid_name)); + } + } +} + +#ifdef TEST_PROGRAM +int main(int argc, char** argv) +{ + blkid_cache cache = NULL; + int ret; + + blkid_init_debug(DEBUG_ALL); + + if ((argc > 2)) { + fprintf(stderr, "Usage: %s [filename] \n", argv[0]); + exit(1); + } + + if ((ret = blkid_get_cache(&cache, argv[1])) < 0) { + fprintf(stderr, "error %d parsing cache file %s\n", ret, + argv[1] ? argv[1] : blkid_get_cache_filename(NULL)); + exit(1); + } + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { + fprintf(stderr, "%s: error creating cache (%d)\n", + argv[0], ret); + exit(1); + } + if ((ret = blkid_probe_all(cache)) < 0) + fprintf(stderr, "error probing devices\n"); + + blkid_put_cache(cache); + + return ret; +} +#endif |