diff options
Diffstat (limited to 'lib/blkid')
-rw-r--r-- | lib/blkid/ChangeLog | 7 | ||||
-rw-r--r-- | lib/blkid/Makefile.in | 53 | ||||
-rw-r--r-- | lib/blkid/blkid.h | 49 | ||||
-rw-r--r-- | lib/blkid/blkidP.h | 61 | ||||
-rw-r--r-- | lib/blkid/cache.c | 24 | ||||
-rw-r--r-- | lib/blkid/dev.c | 213 | ||||
-rw-r--r-- | lib/blkid/devname.c | 179 | ||||
-rw-r--r-- | lib/blkid/devno.c | 118 | ||||
-rw-r--r-- | lib/blkid/libblkid.3.in | 6 | ||||
-rw-r--r-- | lib/blkid/probe.c | 818 | ||||
-rw-r--r-- | lib/blkid/probe.h | 12 | ||||
-rw-r--r-- | lib/blkid/read.c | 149 | ||||
-rw-r--r-- | lib/blkid/resolve.c | 17 | ||||
-rw-r--r-- | lib/blkid/save.c | 80 | ||||
-rw-r--r-- | lib/blkid/tag.c | 195 |
15 files changed, 669 insertions, 1312 deletions
diff --git a/lib/blkid/ChangeLog b/lib/blkid/ChangeLog index 827a685c..b73e5aa3 100644 --- a/lib/blkid/ChangeLog +++ b/lib/blkid/ChangeLog @@ -1,3 +1,10 @@ +2003-02-12 Theodore Ts'o <tytso@mit.edu> + + * blkid.h, blkidP.h, cache.c, dev.c, devname.c, devno.c, probe.c, + probe.h, read.c, resolve.c, save.c, tag.c: Wholesale + changes to library to simplify the implementation and + shrink its size. Change library version to be 1.0. + 2003-01-27 Theodore Ts'o <tytso@mit.edu> * read.c (parse_tag): Do not return that blkid_tag when parsing diff --git a/lib/blkid/Makefile.in b/lib/blkid/Makefile.in index 6d8a7767..42528357 100644 --- a/lib/blkid/Makefile.in +++ b/lib/blkid/Makefile.in @@ -31,8 +31,8 @@ HFILES_IN= blkid_types.h LIBRARY= libblkid LIBDIR= blkid -ELF_VERSION = 2.0 -ELF_SO_VERSION = 2 +ELF_VERSION = 1.0 +ELF_SO_VERSION = 1 ELF_IMAGE = libblkid ELF_MYDIR = blkid ELF_INSTALL_DIR = $(root_libdir) @@ -97,7 +97,14 @@ tst_resolve: $(srcdir)/resolve.c $(DEPLIBS_BLKID) tst_save: $(srcdir)/save.c $(DEPLIBS_BLKID) $(CC) -Wall -o tst_save -DTEST_PROGRAM $(srcdir)/save.c $(LIBS_BLKID) $(LIBUUID) $(ALL_CFLAGS) -check:: tst_cache tst_dev tst_devname tst_devno tst_getsize tst_probe \ +../../misc/blkid.o: $(top_srcdir)/misc/blkid.c blkid.h + $(CC) -Wall $(ALL_CFLAGS) -c $(top_srcdir)/misc/blkid.c \ + -o ../../misc/blkid.o + +blkid: ../../misc/blkid.o libblkid.a $(LIBBLKID) $(LIBUUID) + $(CC) -Wall -o blkid ../../misc/blkid.o libblkid.a $(LIBBLKID) $(LIBUUID) + +check:: tst_cache tst_devname tst_devno tst_getsize tst_probe \ tst_read tst_resolve tst_save installdirs:: @@ -129,7 +136,7 @@ uninstall:: clean:: $(RM) -f \#* *.s *.o *.orig *.a *~ *.bak tst_* core profiled/* \ checker/* blkid_types.h ../libblkid.a ../libblkid_p.a \ - $(SMANPAGES) + $(SMANPAGES) blkid mostlyclean:: clean distclean:: clean @@ -140,21 +147,27 @@ distclean:: clean # Makefile dependencies follow. This must be the last section in # the Makefile.in file # -cache.o: $(srcdir)/cache.c $(srcdir)/blkid.h $(srcdir)/list.h \ - $(top_builddir)/lib/blkid/blkid_types.h -dev.o: $(srcdir)/dev.c $(srcdir)/blkid.h $(srcdir)/list.h \ - $(top_builddir)/lib/blkid/blkid_types.h -devname.o: $(srcdir)/devname.c $(srcdir)/blkid.h $(srcdir)/list.h \ - $(top_builddir)/lib/blkid/blkid_types.h -devno.o: $(srcdir)/devno.c $(srcdir)/blkid.h $(srcdir)/list.h \ - $(top_builddir)/lib/blkid/blkid_types.h -getsize.o: $(srcdir)/getsize.c $(srcdir)/blkid.h $(srcdir)/list.h \ - $(top_builddir)/lib/blkid/blkid_types.h -llseek.o: $(srcdir)/llseek.c $(srcdir)/blkid.h $(srcdir)/list.h \ - $(top_builddir)/lib/blkid/blkid_types.h -read.o: $(srcdir)/read.c $(srcdir)/blkid.h $(srcdir)/list.h \ - $(top_builddir)/lib/blkid/blkid_types.h $(top_srcdir)/lib/uuid/uuid.h -save.o: $(srcdir)/save.c $(srcdir)/blkid.h $(srcdir)/list.h \ +cache.o: $(srcdir)/cache.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \ + $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h +dev.o: $(srcdir)/dev.c $(srcdir)/blkidP.h $(srcdir)/blkid.h $(srcdir)/list.h \ $(top_builddir)/lib/blkid/blkid_types.h -tag.o: $(srcdir)/tag.c $(srcdir)/blkid.h $(srcdir)/list.h \ +devname.o: $(srcdir)/devname.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \ + $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h +devno.o: $(srcdir)/devno.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \ + $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h +getsize.o: $(srcdir)/getsize.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \ + $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h +llseek.o: $(srcdir)/llseek.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \ + $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h +probe.o: $(srcdir)/probe.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \ + $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h \ + $(top_srcdir)/lib/uuid/uuid.h $(srcdir)/probe.h +read.o: $(srcdir)/read.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \ + $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h \ + $(top_srcdir)/lib/uuid/uuid.h +resolve.o: $(srcdir)/resolve.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \ + $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h $(srcdir)/probe.h +save.o: $(srcdir)/save.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \ + $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h +tag.o: $(srcdir)/tag.c $(srcdir)/blkidP.h $(srcdir)/blkid.h $(srcdir)/list.h \ $(top_builddir)/lib/blkid/blkid_types.h diff --git a/lib/blkid/blkid.h b/lib/blkid/blkid.h index f8faa0dd..c0ec660e 100644 --- a/lib/blkid/blkid.h +++ b/lib/blkid/blkid.h @@ -13,34 +13,62 @@ #ifndef _BLKID_BLKID_H #define _BLKID_BLKID_H +#include <blkid/blkid_types.h> + #ifdef __cplusplus extern "C" { #endif -#define BLKID_VERSION "1.2.0" -#define BLKID_DATE "22-Nov-2001" +#define BLKID_VERSION "1.0.0" +#define BLKID_DATE "12-Feb-2003" typedef struct blkid_struct_dev *blkid_dev; -typedef struct blkid_struct_tag *blkid_tag; typedef struct blkid_struct_cache *blkid_cache; +typedef __s64 blkid_loff_t; + +typedef struct blkid_struct_tag_iterate *blkid_tag_iterate; +typedef struct blkid_struct_dev_iterate *blkid_dev_iterate; + +/* + * Flags for blkid_get_devname + * + * BLKID_DEV_CREATE Create an empty device structure if not found + * in the cache. + * BLKID_DEV_VERIFY Make sure the device structure corresponds + * with reality. + * BLKID_DEV_FIND Just look up a device entry, and return NULL + * if it is not found. + * BLKID_DEV_NORMAL Get a valid device structure, either from the + * cache or by probing the device. + */ +#define BLKID_DEV_FIND 0x0000 +#define BLKID_DEV_CREATE 0x0001 +#define BLKID_DEV_VERIFY 0x0002 +#define BLKID_DEV_NORMAL (BLKID_DEV_CREATE | BLKID_DEV_VERIFY) /* cache.c */ -extern void blkid_free_cache(blkid_cache cache); +extern void blkid_put_cache(blkid_cache cache); /* dev.c */ extern const char *blkid_devname_name(blkid_dev dev); -typedef struct blkid_struct_dev_iterate *blkid_dev_iterate; extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache); extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev); extern void blkid_dev_iterate_end(blkid_dev_iterate iterate); +/* devno.c */ +extern char *blkid_devno_to_devname(dev_t devno); + /* devname.c */ -extern int blkid_probe_all(blkid_cache *cache); -extern blkid_dev blkid_get_devname(blkid_cache cache, const char *devname); +extern int blkid_probe_all(blkid_cache cache); +extern blkid_dev blkid_get_devname(blkid_cache cache, const char *devname, + int flags); + +/* getsize.c */ +extern blkid_loff_t blkid_get_dev_size(int fd); /* read.c */ -int blkid_read_cache(blkid_cache *cache, const char *filename); +int blkid_get_cache(blkid_cache *cache, const char *filename); /* resolve.c */ extern char *blkid_get_tagname_devname(blkid_cache cache, const char *tagname, @@ -48,15 +76,12 @@ extern char *blkid_get_tagname_devname(blkid_cache cache, const char *tagname, extern char *blkid_get_token(blkid_cache cache, const char *token, const char *value); -/* save.c */ -extern int blkid_save_cache(blkid_cache cache, const char *filename); - /* tag.c */ -typedef struct blkid_struct_tag_iterate *blkid_tag_iterate; extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev); extern int blkid_tag_next(blkid_tag_iterate iterate, const char **type, const char **value); extern void blkid_tag_iterate_end(blkid_tag_iterate iterate); + extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache, const char *type, const char *value); diff --git a/lib/blkid/blkidP.h b/lib/blkid/blkidP.h index 6b300610..5a998029 100644 --- a/lib/blkid/blkidP.h +++ b/lib/blkid/blkidP.h @@ -19,9 +19,6 @@ #include <blkid/blkid.h> #include <blkid/list.h> -#include <blkid/blkid_types.h> - -typedef __s64 blkid_loff_t; /* * This describes the attributes of a specific device. @@ -33,6 +30,7 @@ struct blkid_struct_dev { struct list_head bid_devs; /* All devices in the cache */ struct list_head bid_tags; /* All tags for this device */ + blkid_cache bid_cache; /* Dev belongs to this cache */ char *bid_name; /* Device inode pathname */ char *bid_type; /* Preferred device TYPE */ blkid_loff_t bid_size; /* Filesystem size in bytes */ @@ -47,6 +45,7 @@ struct blkid_struct_dev #define BLKID_BID_FL_VERIFIED 0x0001 /* Device data validated from disk */ #define BLKID_BID_FL_MTYPE 0x0002 /* Device has multiple type matches */ +#define BLKID_BID_FL_INVALID 0x0004 /* Device is invalid */ /* * Each tag defines a NAME=value pair for a particular device. The tags @@ -63,6 +62,7 @@ struct blkid_struct_tag char *bit_val; /* value of tag */ blkid_dev bit_dev; /* pointer to device */ }; +typedef struct blkid_struct_tag *blkid_tag; /* * Minimum number of seconds between device probes, even when reading @@ -91,19 +91,18 @@ struct blkid_struct_cache time_t bic_time; /* Last probe time */ unsigned int bic_idmax; /* Highest ID assigned */ unsigned int bic_flags; /* Status flags of the cache */ + char *bic_filename; /* filename of cache */ }; -#define BLKID_BIC_FL_PARSED 0x0001 /* We parsed a cache file */ #define BLKID_BIC_FL_PROBED 0x0002 /* We probed /proc/partition devices */ #define BLKID_BIC_FL_CHANGED 0x0004 /* Cache has changed from disk */ -extern char *string_copy(const char *s); -extern char *stringn_copy(const char *s, const int length); -extern void string_free(char *s); +extern char *blkid_strdup(const char *s); +extern char *blkid_strndup(const char *s, const int length); extern blkid_cache blkid_new_cache(void); #define BLKID_CACHE_FILE "/etc/blkid.tab" -extern const char *devdirs[]; +extern const char *blkid_devdirs[]; #define BLKID_ERR_IO 5 #define BLKID_ERR_PROC 9 @@ -193,60 +192,28 @@ static inline void DEB_DUMP_CACHE(blkid_cache cache) #define DEB_DUMP_CACHE(cache) do {} while (0) #endif -/* - * Primitive disk functions: llseek.c, getsize.c - */ +/* lseek.c */ extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence); -extern blkid_loff_t blkid_get_dev_size(int fd); - -/* - * Getting data from the cache file: read.c - */ -int blkid_read_cache_line(blkid_cache cache, blkid_dev *dev_p, char *cp); -int blkid_read_cache_file(blkid_cache *cache, FILE *file); - -/* - * Save data to the cache file: save.c - */ -int blkid_save_cache_file(blkid_cache cache, FILE *file); - -/* - * Identify a device by inode name: probe.c - */ -extern blkid_dev blkid_devname_to_dev(const char *devname, - blkid_loff_t size); -/* - * Locate a device by inode name: devname.c - */ -extern blkid_dev blkid_find_devname(blkid_cache cache, const char *devname); +/* probe.c */ extern blkid_dev blkid_verify_devname(blkid_cache cache, blkid_dev dev); -extern blkid_dev blkid_get_devname(blkid_cache cache, const char *devname); -/* - * Locate a device by device major/minor number: devno.c - */ -extern char *blkid_devno_to_devname(dev_t devno); -extern blkid_dev blkid_find_devno(blkid_cache cache, dev_t devno); -extern blkid_dev blkid_get_devno(blkid_cache cache, dev_t devno); +/* save.c */ +extern int blkid_flush_cache(blkid_cache cache); /* * Functions to create and find a specific tag type: tag.c */ -extern blkid_tag blkid_new_tag(void); extern void blkid_free_tag(blkid_tag tag); -extern int blkid_create_tag(blkid_dev dev, const char *name, - const char *value, const int vlength); -extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type, - const char *value); -extern blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type); +extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type); +extern int blkid_set_tag(blkid_dev dev, const char *name, + const char *value, const int vlength, int replace); /* * Functions to create and find a specific tag type: dev.c */ extern blkid_dev blkid_new_dev(void); extern void blkid_free_dev(blkid_dev dev); -extern blkid_dev blkid_add_dev_to_cache(blkid_cache cache, blkid_dev dev); #ifdef __cplusplus } diff --git a/lib/blkid/cache.c b/lib/blkid/cache.c index 188dc82c..0e1fc8e5 100644 --- a/lib/blkid/cache.c +++ b/lib/blkid/cache.c @@ -2,6 +2,7 @@ * 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 @@ -32,12 +33,15 @@ blkid_cache blkid_new_cache(void) return cache; } -void blkid_free_cache(blkid_cache cache) +void blkid_put_cache(blkid_cache cache) { if (!cache) return; + (void) blkid_flush_cache(cache); + DBG(printf("freeing cache struct\n")); + /* DEB_DUMP_CACHE(cache); */ while (!list_empty(&cache->bic_devs)) { @@ -63,6 +67,9 @@ void blkid_free_cache(blkid_cache cache) } blkid_free_tag(tag); } + if (cache->bic_filename) + free(cache->bic_filename); + free(cache); } @@ -77,16 +84,19 @@ int main(int argc, char** argv) exit(1); } - if ((ret = blkid_read_cache(&cache, argv[1])) < 0) + if ((ret = blkid_get_cache(&cache, argv[1])) < 0) { fprintf(stderr, "error %d parsing cache file %s\n", ret, argv[1] ? argv[1] : BLKID_CACHE_FILE); - else if ((ret = blkid_probe_all(&cache) < 0)) + exit(1); + } + if ((cache = blkid_new_cache()) == NULL) { + fprintf(stderr, "%s: error creating cache\n", argv[0]); + exit(1); + } + if ((ret = blkid_probe_all(cache) < 0)) fprintf(stderr, "error probing devices\n"); - else if ((ret = blkid_save_cache(cache, argv[1])) < 0) - fprintf(stderr, "error %d saving cache to %s\n", ret, - argv[1] ? argv[1] : BLKID_CACHE_FILE); - blkid_free_cache(cache); + blkid_put_cache(cache); return ret; } diff --git a/lib/blkid/dev.c b/lib/blkid/dev.c index 2075d451..b6e675ae 100644 --- a/lib/blkid/dev.c +++ b/lib/blkid/dev.c @@ -2,6 +2,7 @@ * dev.c - allocation/initialization/free routines for dev * * Copyright (C) 2001 Andreas Dilger + * Copyright (C) 2003 Theodore Ts'o * * %Begin-Header% * This file may be redistributed under the terms of the @@ -50,78 +51,11 @@ void blkid_free_dev(blkid_dev dev) blkid_free_tag(tag); } if (dev->bid_name) - string_free(dev->bid_name); + free(dev->bid_name); free(dev); } /* - * This is kind of ugly, but I want to be able to compare two strings in - * several different ways. For example, in some cases, if both strings - * are NULL, those would be considered different, but in other cases - * they would be considered the same. Hence the ugliness. - * - * Use as: "ret == SC_SAME" if both strings exist and are equal - * this is equivalent to "!(ret & SC_DIFF)" - * "ret & SC_SAME" if both strings being NULL is also equal - * this is equivalent to "!(ret == SC_DIFF)" - * "ret == SC_DIFF" if both strings exist and are different - * this is equivalent to "!(ret & SC_SAME)" - * "ret & SC_DIFF" if both strings being NULL is also different - * this is equivalent to "!(ret == SC_SAME)" - * "ret == SC_NONE" to see if both strings do not exist - */ -#define SC_DIFF 0x0001 -#define SC_NONE 0x0003 -#define SC_SAME 0x0002 - -static int string_compare(char *s1, char *s2) -{ - if (!s1 && !s2) - return SC_NONE; - - if (!s1 || !s2) - return SC_DIFF; - - if (strcmp(s1, s2)) - return SC_DIFF; - - return SC_SAME; -} - -/* - * Add a tag to the global cache tag list. - */ -static int add_tag_to_cache(blkid_cache cache, blkid_tag tag) -{ - blkid_tag head = NULL; - - if (!cache || !tag) - return 0; - - DBG(printf(" adding tag %s=%s to cache\n", tag->bit_name, tag->bit_val)); - - if (!(head = blkid_find_head_cache(cache, tag->bit_name))) { - head = blkid_new_tag(); - if (!head) - return -BLKID_ERR_MEM; - - DBG(printf(" creating new cache tag head %s\n",tag->bit_name)); - head->bit_name = string_copy(tag->bit_name); - if (!head->bit_name) { - blkid_free_tag(head); - return -BLKID_ERR_MEM; - } - - list_add_tail(&head->bit_tags, &cache->bic_tags); - } - - /* Add this tag to global list */ - list_add_tail(&tag->bit_names, &head->bit_names); - - return 0; -} - -/* * Given a blkid device, return its name */ extern const char *blkid_devname_name(blkid_dev dev) @@ -188,146 +122,3 @@ extern void blkid_dev_iterate_end(blkid_dev_iterate iter) free(iter); } -/* - * Add a device to the global cache list, along with all its tags. - */ -blkid_dev blkid_add_dev_to_cache(blkid_cache cache, blkid_dev dev) -{ - struct list_head *p; - - if (!cache || !dev) - return dev; - - if (!dev->bid_id) - dev->bid_id = ++(cache->bic_idmax); - - list_for_each(p, &cache->bic_devs) { - blkid_dev odev = list_entry(p, struct blkid_struct_dev, bid_devs); - int dup_uuid, dup_label, dup_name, dup_type; - - dup_name = string_compare(odev->bid_name, dev->bid_name); - dup_label = string_compare(odev->bid_label, dev->bid_label); - dup_uuid = string_compare(odev->bid_uuid, dev->bid_uuid); - - if (odev->bid_id == dev->bid_id) - dev->bid_id = ++(cache->bic_idmax); - - /* Fields different, do nothing (check more fields?) */ - if ((dup_name & SC_DIFF) && (dup_uuid & SC_DIFF) && - (dup_label & SC_DIFF)) - continue; - - /* We can't simply allow duplicate fields if the bid_type is - * different, given that a filesystem may change from ext2 - * to ext3 but it will have the same UUID and LABEL fields. - * We need to discard the old cache entry in this case. - */ - - /* If the UUIDs are the same but one is unverified discard it */ - if (dup_uuid == SC_SAME) { - DBG(printf(" duplicate uuid %s\n", dev->bid_uuid)); - if (!(odev->bid_flags & BLKID_BID_FL_VERIFIED)) { - dev->bid_id = odev->bid_id; /* keep old id */ - blkid_free_dev(odev); - goto exit_new; - } else if (!(dev->bid_flags & BLKID_BID_FL_VERIFIED)) { - blkid_free_dev(dev); - dev = odev; - goto exit_old; - } - - /* This shouldn't happen */ - fprintf(stderr, "blkid: same UUID for %s and %s\n", - dev->bid_name, odev->bid_name); - } - - /* If the device name is the same, discard one of them - * (prefer one that has been validated, or the first one). - */ - if (dup_name == SC_SAME) { - DBG(printf(" duplicate devname %s\n", dev->bid_name)); - if (odev->bid_flags & BLKID_BID_FL_VERIFIED || - !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) { - if ((dup_uuid & SC_SAME) && - (dup_label & SC_SAME)) /* use old id */ - dev->bid_id = odev->bid_id; - blkid_free_dev(dev); - dev = odev; - goto exit_old; - } else { - blkid_free_dev(odev); - goto exit_new; - } - } - - dup_type = string_compare(odev->bid_type, dev->bid_type); - - if (dup_label == SC_SAME && dup_type == SC_SAME) { - DBG(printf(" duplicate label %s\n", dev->bid_label)); - if (!(odev->bid_flags & BLKID_BID_FL_VERIFIED)) { - blkid_free_dev(odev); - goto exit_new; - } else if (!(dev->bid_flags & BLKID_BID_FL_VERIFIED)) { - blkid_free_dev(dev); - dev = odev; - goto exit_old; - } - fprintf(stderr, "blkid: same LABEL for %s and %s\n", - dev->bid_name, odev->bid_name); - } - } - -exit_new: - DBG(printf(" adding new devname %s to cache\n", dev->bid_name)); - - cache->bic_flags |= BLKID_BIC_FL_CHANGED; - - list_add_tail(&dev->bid_devs, &cache->bic_devs); - list_for_each(p, &dev->bid_tags) { - blkid_tag tag = list_entry(p, struct blkid_struct_tag, - bit_tags); - add_tag_to_cache(cache, tag); - } - return dev; - -exit_old: - DBG(printf(" using old devname %s from cache\n", dev->bid_name)); - return dev; -} - -#ifdef TEST_PROGRAM -int main(int argc, char** argv) -{ - blkid_cache cache; - blkid_dev dev, newdev; - - if ((argc != 3)) { - fprintf(stderr, "Usage:\t%s dev1 dev2\n" - "Test that adding the same device to the cache fails\n", - argv[0]); - exit(1); - } - - cache = blkid_new_cache(); - if (!cache) { - perror(argv[0]); - return 1; - } - dev = blkid_devname_to_dev(argv[1], 0); - newdev = blkid_add_dev_to_cache(cache, dev); - if (newdev != dev) - printf("devices changed for %s (unexpected)\n", argv[1]); - dev = blkid_devname_to_dev(argv[2], 0); - newdev = blkid_add_dev_to_cache(cache, dev); - if (newdev != dev) - printf("devices changed for %s (unexpected)\n", argv[2]); - dev = blkid_devname_to_dev(argv[2], 0); - newdev = blkid_add_dev_to_cache(cache, dev); - if (newdev != dev) - printf("devices changed for %s (expected)\n", argv[2]); - - blkid_free_cache(cache); - - return 0; -} -#endif diff --git a/lib/blkid/devname.c b/lib/blkid/devname.c index 2c8681df..6cb3a8e8 100644 --- a/lib/blkid/devname.c +++ b/lib/blkid/devname.c @@ -44,57 +44,66 @@ /* * Find a dev struct in the cache by device name, if available. + * + * If there is no entry with the specified device name, and the create + * flag is set, then create an empty device entry. */ -blkid_dev blkid_find_devname(blkid_cache cache, const char *devname) +blkid_dev blkid_get_devname(blkid_cache cache, const char *devname, + int flags) { - blkid_dev dev = NULL; + blkid_dev dev = NULL, tmp; struct list_head *p; if (!cache || !devname) return NULL; list_for_each(p, &cache->bic_devs) { - blkid_dev tmp = list_entry(p, struct blkid_struct_dev, bid_devs); - + tmp = list_entry(p, struct blkid_struct_dev, bid_devs); if (strcmp(tmp->bid_name, devname)) continue; DBG(printf("found devname %s in cache\n", tmp->bid_name)); - dev = blkid_verify_devname(cache, tmp); + dev = tmp; break; } - return dev; -} - -/* - * Return a pointer to an dev struct, either from cache or by probing. - */ -blkid_dev blkid_get_devname(blkid_cache cache, const char *devname) -{ - blkid_dev dev; - - if ((dev = blkid_find_devname(cache, devname))) - return dev; + if (!dev && (flags & BLKID_DEV_CREATE)) { + dev = blkid_new_dev(); + if (!dev) + return NULL; + dev->bid_name = blkid_strdup(devname); + dev->bid_cache = cache; + dev->bid_id = ++(cache->bic_idmax); + list_add_tail(&dev->bid_devs, &cache->bic_devs); + cache->bic_flags |= BLKID_BIC_FL_CHANGED; + } - dev = blkid_devname_to_dev(devname, 0); - return blkid_add_dev_to_cache(cache, dev); + if (flags & BLKID_DEV_VERIFY) + dev = blkid_verify_devname(cache, dev); + return dev; } /* * Probe a single block device to add to the device cache. - * If the size is not specified, it will be found in blkid_devname_to_dev(). */ static blkid_dev probe_one(blkid_cache cache, const char *ptname, - int major, int minor, unsigned long long size) + dev_t devno) { - dev_t devno = makedev(major, minor); - blkid_dev dev; + blkid_dev dev = NULL; + struct list_head *p; const char **dir; char *devname = NULL; /* See if we already have this device number in the cache. */ - if ((dev = blkid_find_devno(cache, devno))) + list_for_each(p, &cache->bic_devs) { + blkid_dev tmp = list_entry(p, struct blkid_struct_dev, + bid_devs); + if (tmp->bid_devno == devno) { + dev = blkid_verify_devname(cache, tmp); + break; + } + } + if (dev && dev->bid_devno == devno) return dev; /* @@ -103,17 +112,17 @@ static blkid_dev probe_one(blkid_cache cache, const char *ptname, * the stat information doesn't check out, use blkid_devno_to_devname() * to find it via an exhaustive search for the device major/minor. */ - for (dir = devdirs; *dir; dir++) { + for (dir = blkid_devdirs; *dir; dir++) { struct stat st; char device[256]; sprintf(device, "%s/%s", *dir, ptname); - if ((dev = blkid_find_devname(cache, device)) && + if ((dev = blkid_get_devname(cache, device, BLKID_DEV_FIND)) && dev->bid_devno == devno) return dev; if (stat(device, &st) == 0 && st.st_rdev == devno) { - devname = string_copy(device); + devname = blkid_strdup(device); break; } } @@ -122,10 +131,10 @@ static blkid_dev probe_one(blkid_cache cache, const char *ptname, if (!devname) return NULL; } - dev = blkid_devname_to_dev(devname, size); - string_free(devname); + dev = blkid_get_devname(cache, devname, BLKID_DEV_NORMAL); + free(devname); - return blkid_add_dev_to_cache(cache, dev); + return dev; } #define PROC_PARTITIONS "/proc/partitions" @@ -139,29 +148,23 @@ static blkid_dev probe_one(blkid_cache cache, const char *ptname, */ #ifdef VG_DIR #include <dirent.h> -static int lvm_get_devno(const char *lvm_device, int *major, int *minor, - blkid_loff_t *size) +static dev_t lvm_get_devno(const char *lvm_device) { FILE *lvf; char buf[1024]; - int ret = 1; - - *major = *minor = 0; - *size = 0; + int ma, mi; + dev_t ret = 0; DBG(printf("opening %s\n", lvm_device)); if ((lvf = fopen(lvm_device, "r")) == NULL) { - ret = errno; - DBG(printf("%s: (%d) %s\n", lvm_device, ret, strerror(ret))); - return -ret; + DBG(printf("%s: (%d) %s\n", lvm_device, errno, + strerror(errno))); + return 0; } while (fgets(buf, sizeof(buf), lvf)) { - if (sscanf(buf, "size: %llu", size) == 1) { /* sectors */ - *size <<= 9; - } - if (sscanf(buf, "device: %d:%d", major, minor) == 2) { - ret = 0; + if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) { + ret = makedev(ma, mi); break; } } @@ -170,11 +173,12 @@ static int lvm_get_devno(const char *lvm_device, int *major, int *minor, return ret; } -static void lvm_probe_all(blkid_cache *cache) +static void lvm_probe_all(blkid_cache cache) { DIR *vg_list; struct dirent *vg_iter; int vg_len = strlen(VG_DIR); + dev_t dev; if ((vg_list = opendir(VG_DIR)) == NULL) return; @@ -202,8 +206,6 @@ static void lvm_probe_all(blkid_cache *cache) while ((lv_iter = readdir(lv_list)) != NULL) { char *lv_name, *lvm_device; - int major, minor; - blkid_loff_t size; lv_name = lv_iter->d_name; if (!strcmp(lv_name, ".") || !strcmp(lv_name, "..")) @@ -217,14 +219,11 @@ static void lvm_probe_all(blkid_cache *cache) } sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name, lv_name); - if (lvm_get_devno(lvm_device, &major, &minor, &size)) { - free(lvm_device); - continue; - } + dev = lvm_get_devno(lvm_device); sprintf(lvm_device, "%s/%s", vg_name, lv_name); - DBG(printf("LVM dev %s: devno 0x%02X%02X, size %Ld\n", - lvm_device, major, minor, size)); - probe_one(*cache, lvm_device, major, minor, size); + DBG(printf("LVM dev %s: devno 0x%04X\n", + lvm_device, dev)); + probe_one(cache, lvm_device, dev); free(lvm_device); } closedir(lv_list); @@ -237,7 +236,7 @@ exit: #define PROC_EVMS_VOLUMES "/proc/evms/volumes" static int -evms_probe_all(blkid_cache *cache) +evms_probe_all(blkid_cache cache) { char line[100]; int ma, mi, sz, num = 0; @@ -255,7 +254,7 @@ evms_probe_all(blkid_cache *cache) DBG(printf("Checking partition %s (%d, %d)\n", device, ma, mi)); - probe_one(*cache, device, ma, mi, sz << 10); + probe_one(cache, device, makedev(ma, mi)); num++; } fclose(procpt); @@ -265,7 +264,7 @@ evms_probe_all(blkid_cache *cache) /* * Read the device data for all available block devices in the system. */ -int blkid_probe_all(blkid_cache *cache) +int blkid_probe_all(blkid_cache cache) { FILE *proc; int firstPass; @@ -273,14 +272,8 @@ int blkid_probe_all(blkid_cache *cache) if (!cache) return -BLKID_ERR_PARAM; - if (!*cache) - *cache = blkid_new_cache(); - - if (!*cache) - return -BLKID_ERR_MEM; - - if ((*cache)->bic_flags & BLKID_BIC_FL_PROBED && - time(0) - (*cache)->bic_time < BLKID_PROBE_INTERVAL) + if (cache->bic_flags & BLKID_BIC_FL_PROBED && + time(0) - cache->bic_time < BLKID_PROBE_INTERVAL) return 0; if (evms_probe_all(cache)) @@ -296,10 +289,11 @@ int blkid_probe_all(blkid_cache *cache) for (firstPass = 1; firstPass >= 0; firstPass--) { char line[1024]; - char ptname0[128], ptname1[128]; + char ptname0[128], ptname1[128], *ptname = 0; char *ptnames[2] = { ptname0, ptname1 }; - int majors[2], minors[2]; - unsigned long long sizes[2]; + dev_t devs[2]; + int ma, mi; + unsigned long long sz; int lens[2] = { 0, 0 }; int handleOnFirst; int which = 0, last = 0; @@ -309,16 +303,17 @@ int blkid_probe_all(blkid_cache *cache) while (fgets(line, sizeof(line), proc)) { last = which; which ^= 1; + ptname = ptnames[which]; if (sscanf(line, " %d %d %lld %128[^\n ]", - &majors[which], &minors[which], - &sizes[which], ptnames[which]) != 4) + &ma, &mi, &sz, ptname) != 4) continue; + devs[which] = makedev(ma, mi); - DBG(printf("read partition name %s\n", ptnames[which])); + DBG(printf("read partition name %s\n", ptname)); /* look only at md devices on first pass */ - handleOnFirst = !strncmp(ptnames[which], "md", 2); + handleOnFirst = !strncmp(ptname, "md", 2); if (firstPass != handleOnFirst) continue; @@ -333,40 +328,34 @@ int blkid_probe_all(blkid_cache *cache) * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs */ - lens[which] = strlen(ptnames[which]); - if (isdigit(ptnames[which][lens[which] - 1])) { - DBG(printf("partition dev %s, devno 0x%02X%02X\n", - ptnames[which], majors[which], - minors[which])); + lens[which] = strlen(ptname); + if (isdigit(ptname[lens[which] - 1])) { + DBG(printf("partition dev %s, devno 0x%04X\n", + ptname, devs[which])); - if (sizes[which] > 1) - probe_one(*cache, ptnames[which], - majors[which], minors[which], - sizes[which] << 10); + if (sz > 1) + probe_one(cache, ptname, devs[which]); lens[which] = 0; lens[last] = 0; } else if (lens[last] && - strncmp(ptnames[last], ptnames[which], + strncmp(ptnames[last], ptname, lens[last])) { - DBG(printf("whole dev %s, devno 0x%02X%02X\n", - ptnames[last], majors[last], - minors[last])); - probe_one(*cache, ptnames[last], majors[last], - minors[last], sizes[last] << 10); + DBG(printf("whole dev %s, devno 0x%04X\n", + ptname, devs[last])); + probe_one(cache, ptname, devs[last]); lens[last] = 0; } } /* Handle the last device if it wasn't partitioned */ if (lens[which]) - probe_one(*cache, ptnames[which], majors[which], - minors[which], sizes[which] << 10); + probe_one(cache, ptname, devs[which]); } fclose(proc); finish: - (*cache)->bic_time = time(0); - (*cache)->bic_flags |= BLKID_BIC_FL_PROBED; + cache->bic_time = time(0); + cache->bic_flags |= BLKID_BIC_FL_PROBED; return 0; } @@ -381,10 +370,14 @@ int main(int argc, char **argv) "Probe all devices and exit\n", argv[0]); exit(1); } - if (blkid_probe_all(&cache) < 0) + if ((cache = blkid_new_cache()) == NULL) { + fprintf(stderr, "%s: error creating cache\n", argv[0]); + exit(1); + } + if (blkid_probe_all(cache) < 0) printf("%s: error probing devices\n", argv[0]); - blkid_free_cache(cache); + blkid_put_cache(cache); return (0); } #endif diff --git a/lib/blkid/devno.c b/lib/blkid/devno.c index 1fe7309d..41fdc3de 100644 --- a/lib/blkid/devno.c +++ b/lib/blkid/devno.c @@ -1,7 +1,7 @@ /* * devno.c - find a particular device by its device number (major/minor) * - * Copyright (C) 2000, 2001 Theodore Ts'o + * Copyright (C) 2000, 2001, 2003 Theodore Ts'o * Copyright (C) 2001 Andreas Dilger * * %Begin-Header% @@ -44,13 +44,16 @@ struct dir_list { struct dir_list *next; }; -char *stringn_copy(const char *s, const int length) +char *blkid_strndup(const char *s, int length) { char *ret; if (!s) return NULL; + if (!length) + length = strlen(s); + ret = malloc(length + 1); if (ret) { strncpy(ret, s, length); @@ -59,18 +62,9 @@ char *stringn_copy(const char *s, const int length) return ret; } -char *string_copy(const char *s) +char *blkid_strdup(const char *s) { - if (!s) - return NULL; - - return stringn_copy(s, strlen(s)); -} - -void string_free(char *s) -{ - if (s) - free(s); + return blkid_strndup(s, 0); } /* @@ -83,7 +77,7 @@ static void add_to_dirlist(const char *name, struct dir_list **list) dp = malloc(sizeof(struct dir_list)); if (!dp) return; - dp->name = string_copy(name); + dp->name = blkid_strdup(name); if (!dp->name) { free(dp); return; @@ -101,58 +95,52 @@ static void free_dirlist(struct dir_list **list) for (dp = *list; dp; dp = next) { next = dp->next; - string_free(dp->name); + free(dp->name); free(dp); } *list = NULL; } -static int scan_dir(char *dirname, dev_t devno, struct dir_list **list, - char **devname) +static void scan_dir(char *dirname, dev_t devno, struct dir_list **list, + char **devname) { DIR *dir; struct dirent *dp; char path[1024]; int dirlen; struct stat st; - int ret = 0; - dirlen = strlen(dirname); if ((dir = opendir(dirname)) == NULL) - return errno; - dp = readdir(dir); - while (dp) { - if (dirlen + strlen(dp->d_name) + 2 >= sizeof(path)) - goto skip_to_next; + return; + dirlen = strlen(dirname) + 2; + while ((dp = readdir(dir)) != 0) { + if (dirlen + strlen(dp->d_name) >= sizeof(path)) + continue; if (dp->d_name[0] == '.' && ((dp->d_name[1] == 0) || ((dp->d_name[1] == '.') && (dp->d_name[2] == 0)))) - goto skip_to_next; + continue; sprintf(path, "%s/%s", dirname, dp->d_name); if (stat(path, &st) < 0) - goto skip_to_next; + continue; if (S_ISDIR(st.st_mode)) add_to_dirlist(path, list); else if (S_ISBLK(st.st_mode) && st.st_rdev == devno) { - *devname = string_copy(path); + *devname = blkid_strdup(path); DBG(printf("found 0x%Lx at %s (%p)\n", devno, - *devname, *devname)); - if (!*devname) - ret = -BLKID_ERR_MEM; + path, *devname)); break; } - skip_to_next: - dp = readdir(dir); } closedir(dir); - return ret; + return; } /* Directories where we will try to search for device numbers */ -const char *devdirs[] = { "/dev", "/devfs", "/devices", NULL }; +const char *blkid_devdirs[] = { "/devices", "/devfs", "/dev", NULL }; /* * This function finds the pathname to a block device with a given @@ -169,13 +157,8 @@ char *blkid_devno_to_devname(dev_t devno) * Add the starting directories to search in reverse order of * importance, since we are using a stack... */ - for (dir = devdirs; *dir; dir++) - /* go to end of list */; - - do { - --dir; + for (dir = blkid_devdirs; *dir; dir++) add_to_dirlist(*dir, &list); - } while (dir != devdirs); while (list) { struct dir_list *current = list; @@ -183,7 +166,7 @@ char *blkid_devno_to_devname(dev_t devno) list = list->next; DBG(printf("directory %s\n", current->name)); scan_dir(current->name, devno, &new_list, &devname); - string_free(current->name); + free(current->name); free(current); if (devname) break; @@ -200,61 +183,14 @@ char *blkid_devno_to_devname(dev_t devno) free_dirlist(&new_list); if (!devname) - fprintf(stderr, "blkid: couldn't find devno 0x%04lx\n", - (unsigned long) devno); + DBG(printf("blkid: couldn't find devno 0x%04lx\n", + (unsigned long) devno)); else DBG(printf("found devno 0x%04Lx as %s\n", devno, devname)); return devname; } -blkid_dev blkid_find_devno(blkid_cache cache, dev_t devno) -{ - blkid_dev dev = NULL; - struct list_head *p, *n; - - if (!cache) - return NULL; - - /* This cannot be a standard list_for_each() because we may be - * deleting the referenced struct in blkid_verify_devname() and - * pointing to another one that was probed from disk, and "p" - * would point to freed memory. - */ - list_for_each_safe(p, n, &cache->bic_devs) { - blkid_dev tmp = list_entry(p, struct blkid_struct_dev, bid_devs); - if (tmp->bid_devno != devno) - continue; - - tmp = blkid_verify_devname(cache, tmp); - if (!tmp || tmp->bid_devno != devno) - continue; - - dev = tmp; - break; - } - - if (dev) - DBG(printf("found devno 0x%04LX in cache as %s\n", - devno, dev->bid_name)); - - return dev; -} - -blkid_dev blkid_get_devno(blkid_cache cache, dev_t devno) -{ - char *devname; - blkid_dev dev; - - if (!(dev = blkid_find_devno(cache, devno)) && - (devname = blkid_devno_to_devname(devno))) { - dev = blkid_get_devname(cache, devname); - string_free(devname); - } - - return dev; -} - #ifdef TEST_PROGRAM int main(int argc, char** argv) { @@ -291,7 +227,7 @@ int main(int argc, char** argv) printf("Looking for device 0x%04Lx\n", devno); devname = blkid_devno_to_devname(devno); if (devname) - string_free(devname); + free(devname); return 0; } #endif diff --git a/lib/blkid/libblkid.3.in b/lib/blkid/libblkid.3.in index 98f487f0..78d17628 100644 --- a/lib/blkid/libblkid.3.in +++ b/lib/blkid/libblkid.3.in @@ -80,11 +80,9 @@ or visit http://www.gnu.org/licenses/licenses.html#LGPL .UE .SH "SEE ALSO" -.BR blkid_read_cache (3), -.BR blkid_save_cache (3), -.BR blkid_free_cache (3), +.BR blkid_get_cache (3), +.BR blkid_put_cache (3), .BR blkid_get_devname (3), -.BR blkid_get_devno (3), .BR blkid_probe_all (3), .BR blkid_free_dev (3), .BR blkid_find_tag_dev (3), diff --git a/lib/blkid/probe.c b/lib/blkid/probe.c index 9969a97c..eeb544c6 100644 --- a/lib/blkid/probe.c +++ b/lib/blkid/probe.c @@ -3,7 +3,7 @@ * struct with the details * * Copyright (C) 1999 by Andries Brouwer - * Copyright (C) 1999, 2000 by Theodore Ts'o + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o * Copyright (C) 2001 by Andreas Dilger * * %Begin-Header% @@ -39,242 +39,149 @@ #endif /* - * Do the required things for instantiating a new device. This is called if - * there is nor a probe handler for a filesystem type, and is also called by - * the filesystem-specific types to do common initialization tasks. - * - * The devname, dev_p, and id fields are required. The buf is - * a buffer to return superblock data in. + * This is a special case code to check for an MDRAID device. We do + * this special since it requires checking for a superblock at the end + * of the device. */ -static int probe_default(int fd, blkid_dev *dev_p, const char *devname, - struct blkid_magic *id, unsigned char *buf, - blkid_loff_t size) +static int check_mdraid(int fd, unsigned char *ret_uuid) { - blkid_loff_t offset; - blkid_dev dev; - struct stat st; - int ret; - - if (!devname || !dev_p || !id || !buf || fd < 0) + struct mdp_superblock_s *md; + blkid_loff_t offset; + char buf[4096]; + + if (fd < 0) return -BLKID_ERR_PARAM; - if (fstat(fd, &st) < 0 || !S_ISBLK(st.st_mode)) - return -BLKID_ERR_DEV; - - offset = (blkid_loff_t)id->bim_kboff << 10; - if (id->bim_kboff < 0) - offset += (size & ~((blkid_loff_t)(id->bim_align - 1))); + offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536; if (blkid_llseek(fd, offset, 0) < 0 || - read(fd, buf, id->bim_kbsize << 10) != id->bim_kbsize << 10) + read(fd, buf, 4096) != 4096) return -BLKID_ERR_IO; - /* Revalidate magic for blkid_validate_devname */ - if (memcmp(id->bim_magic, buf + id->bim_sboff, id->bim_len)) + /* Check for magic number */ + if (memcmp("\251+N\374", buf, 4)) return -BLKID_ERR_PARAM; - dev = blkid_new_dev(); - if (!dev) - return -BLKID_ERR_MEM; + if (!ret_uuid) + return 0; + *ret_uuid = 0; - dev->bid_name = string_copy(devname); - if (!dev->bid_name) { - ret = -BLKID_ERR_MEM; - goto exit_dev; + /* The MD UUID is not contiguous in the superblock, make it so */ + md = (struct mdp_superblock_s *)buf; + if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) { + memcpy(ret_uuid, &md->set_uuid0, 4); + memcpy(ret_uuid, &md->set_uuid1, 12); } + return 0; +} - /* Don't set this until there is no chance of error */ - *dev_p = dev; - dev->bid_devno = st.st_rdev; - dev->bid_devsize = size; - dev->bid_time = time(0); - dev->bid_flags |= BLKID_BID_FL_VERIFIED; - - if (id->bim_type) - blkid_create_tag(dev, "TYPE", id->bim_type, - strlen(id->bim_type)); - - DBG(printf("%s: devno 0x%04Lx, type %s\n", devname, - st.st_rdev, id->bim_type)); +static void set_uuid(blkid_dev dev, uuid_t uuid) +{ + char str[37]; - return 0; -exit_dev: - blkid_free_dev(dev); - return ret; + if (!uuid_is_null(uuid)) { + uuid_unparse(uuid, str); + blkid_set_tag(dev, "UUID", str, sizeof(str), 1); + } } -static int probe_ext2(int fd, blkid_dev *dev_p, const char *devname, +static int probe_ext2(int fd, blkid_cache cache, blkid_dev dev, struct blkid_magic *id, unsigned char *buf, - blkid_loff_t size) + const char **ret_sectype) { - blkid_dev dev; struct ext2_super_block *es; - int ret; - - if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) - return ret; es = (struct ext2_super_block *)buf; - DBG(printf("size = %Ld, ext2_sb.compat = %08X:%08X:%08X\n", size, + DBG(printf("ext2_sb.compat = %08X:%08X:%08X\n", blkid_le32(es->s_feature_compat), blkid_le32(es->s_feature_incompat), blkid_le32(es->s_feature_ro_compat))); /* Make sure we don't keep re-probing as ext2 for a journaled fs */ if (!strcmp(id->bim_type, "ext2") && - (blkid_le32(es->s_feature_compat) & - EXT3_FEATURE_COMPAT_HAS_JOURNAL || - blkid_le32(es->s_feature_incompat) & - EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { - blkid_free_dev(dev); + ((blkid_le32(es->s_feature_compat) & + EXT3_FEATURE_COMPAT_HAS_JOURNAL) || + (blkid_le32(es->s_feature_incompat) & + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))) return -BLKID_ERR_PARAM; - } - - /* Don't set this until there is no chance of error */ - *dev_p = dev; - dev->bid_size = (blkid_loff_t)blkid_le32(es->s_blocks_count) << - (blkid_le32(es->s_log_block_size) + 10); + if (strlen(es->s_volume_name)) + blkid_set_tag(dev, "LABEL", es->s_volume_name, + sizeof(es->s_volume_name), 1); - if (strlen(es->s_volume_name)) { - blkid_create_tag(dev, "LABEL", es->s_volume_name, - sizeof(es->s_volume_name)); - } - - if (!uuid_is_null(es->s_uuid)) { - char uuid[37]; - uuid_unparse(es->s_uuid, uuid); - blkid_create_tag(dev, "UUID", uuid, sizeof(uuid)); - } + set_uuid(dev, es->s_uuid); return 0; } -static int probe_jbd(int fd, blkid_dev *dev_p, const char *devname, +static int probe_jbd(int fd, blkid_cache cache, blkid_dev dev, struct blkid_magic *id, unsigned char *buf, - blkid_loff_t size) + const char **ret_sectype) { - blkid_dev dev; - struct ext2_super_block *es; - int ret; - - if ((ret = probe_ext2(fd, &dev, devname, id, buf, size)) < 0) - return ret; - - es = (struct ext2_super_block *)buf; + struct ext2_super_block *es = (struct ext2_super_block *) buf; if (!(blkid_le32(es->s_feature_incompat) & - EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { - blkid_free_dev(dev); + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) return -BLKID_ERR_PARAM; - } - /* Don't set this until there is no chance of error */ - *dev_p = dev; - return 0; + return (probe_ext2(fd, cache, dev, id, buf, ret_sectype)); } -static int probe_ext3(int fd, blkid_dev *dev_p, const char *devname, - struct blkid_magic *id, unsigned char *buf, - blkid_loff_t size) +static int probe_ext3(int fd, blkid_cache cache, blkid_dev dev, + struct blkid_magic *id, unsigned char *buf, + const char **ret_sectype) { - blkid_dev dev; - struct ext2_super_block *es; + struct ext2_super_block *es = (struct ext2_super_block *) buf; int ret; - if ((ret = probe_ext2(fd, &dev, devname, id, buf, size)) < 0) - return ret; - - es = (struct ext2_super_block *)buf; - if (!(blkid_le32(es->s_feature_compat) & - EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { - blkid_free_dev(dev); - *dev_p = NULL; + EXT3_FEATURE_COMPAT_HAS_JOURNAL)) return -BLKID_ERR_PARAM; - } - /* Don't set this until there is no chance of error */ - *dev_p = dev; + + if ((ret = probe_ext2(fd, cache, dev, id, buf, ret_sectype)) < 0) + return ret; if (!(blkid_le32(es->s_feature_incompat) & - EXT3_FEATURE_INCOMPAT_RECOVER)) { - blkid_create_tag(dev, "TYPE", "ext2", 4); - dev->bid_flags |= BLKID_BID_FL_MTYPE; - } + EXT3_FEATURE_INCOMPAT_RECOVER)) + *ret_sectype = "ext2"; return 0; } -static int probe_vfat(int fd, blkid_dev *dev_p, const char *devname, +static int probe_vfat(int fd, blkid_cache cache, blkid_dev dev, struct blkid_magic *id, unsigned char *buf, - blkid_loff_t size) + const char **ret_sectype) { - blkid_dev dev; struct vfat_super_block *vs; char serno[10]; - blkid_loff_t sectors; - int cluster_size; - int ret; - - if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) - return ret; vs = (struct vfat_super_block *)buf; - /* Don't set this until there is no chance of error */ - *dev_p = dev; - - sectors = ((vs->vs_sectors[1] << 8) | vs->vs_sectors[0]); - if (sectors == 0) - sectors = vs->vs_total_sect; - cluster_size = ((vs->vs_sector_size[1] << 8) | vs->vs_sector_size[0]); - dev->bid_size = sectors * cluster_size; - DBG(printf("%lld %d byte sectors\n", sectors, cluster_size)); - if (strncmp(vs->vs_label, "NO NAME", 7)) { char *end = vs->vs_label + sizeof(vs->vs_label) - 1; while (*end == ' ' && end >= vs->vs_label) --end; if (end >= vs->vs_label) - blkid_create_tag(dev, "LABEL", vs->vs_label, - end - vs->vs_label + 1); + blkid_set_tag(dev, "LABEL", vs->vs_label, + end - vs->vs_label + 1, 1); } /* We can't just print them as %04X, because they are unaligned */ sprintf(serno, "%02X%02X-%02X%02X", vs->vs_serno[3], vs->vs_serno[2], vs->vs_serno[1], vs->vs_serno[0]); - blkid_create_tag(dev, "UUID", serno, sizeof(serno)); + blkid_set_tag(dev, "UUID", serno, sizeof(serno), 1); return 0; } -static int probe_msdos(int fd, blkid_dev *dev_p, const char *devname, +static int probe_msdos(int fd, blkid_cache cache, blkid_dev dev, struct blkid_magic *id, unsigned char *buf, - blkid_loff_t size) + const char **ret_sectype) { - blkid_dev dev; - struct msdos_super_block *ms; + struct msdos_super_block *ms = (struct msdos_super_block *) buf; char serno[10]; - int cluster_size; - blkid_loff_t sectors; - int ret; - - if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) - return ret; - - ms = (struct msdos_super_block *)buf; - - /* Don't set this until there is no chance of error */ - *dev_p = dev; - - sectors = ((ms->ms_sectors[1] << 8) | ms->ms_sectors[0]); - if (sectors == 0) - sectors = ms->ms_total_sect; - cluster_size = ((ms->ms_sector_size[1] << 8) | ms->ms_sector_size[0]); - dev->bid_size = sectors * cluster_size; - DBG(printf("%Ld %d byte sectors\n", sectors, cluster_size)); if (strncmp(ms->ms_label, "NO NAME", 7)) { char *end = ms->ms_label + sizeof(ms->ms_label) - 1; @@ -282,445 +189,133 @@ static int probe_msdos(int fd, blkid_dev *dev_p, const char *devname, while (*end == ' ' && end >= ms->ms_label) --end; if (end >= ms->ms_label) - blkid_create_tag(dev, "LABEL", ms->ms_label, - end - ms->ms_label + 1); + blkid_set_tag(dev, "LABEL", ms->ms_label, + end - ms->ms_label + 1, 1); } /* We can't just print them as %04X, because they are unaligned */ sprintf(serno, "%02X%02X-%02X%02X", ms->ms_serno[3], ms->ms_serno[2], ms->ms_serno[1], ms->ms_serno[0]); - blkid_create_tag(dev, "UUID", serno, sizeof(serno)); + blkid_set_tag(dev, "UUID", serno, 0, 1); return 0; } -static int probe_xfs(int fd, blkid_dev *dev_p, const char *devname, +static int probe_xfs(int fd, blkid_cache cache, blkid_dev dev, struct blkid_magic *id, unsigned char *buf, - blkid_loff_t size) + const char **ret_sectype) { - blkid_dev dev; struct xfs_super_block *xs; - int ret; - - if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) - return ret; xs = (struct xfs_super_block *)buf; - /* Don't set this until there is no chance of error */ - *dev_p = dev; - /* If the filesystem size is larger than the device, this is bad */ - dev->bid_size = blkid_be64(xs->xs_dblocks) * - blkid_be32(xs->xs_blocksize); - if (strlen(xs->xs_fname)) - blkid_create_tag(dev, "LABEL", xs->xs_fname, - sizeof(xs->xs_fname)); - - if (!uuid_is_null(xs->xs_uuid)) { - char uuid[37]; - uuid_unparse(xs->xs_uuid, uuid); - blkid_create_tag(dev, "UUID", uuid, sizeof(uuid)); - } + blkid_set_tag(dev, "LABEL", xs->xs_fname, + sizeof(xs->xs_fname), 1); + set_uuid(dev, xs->xs_uuid); return 0; } -static int probe_reiserfs(int fd, blkid_dev *dev_p, const char *devname, +static int probe_reiserfs(int fd, blkid_cache cache, blkid_dev dev, struct blkid_magic *id, unsigned char *buf, - blkid_loff_t size) + const char **ret_sectype) { - blkid_dev dev; - struct reiserfs_super_block *rs; + struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf; unsigned int blocksize; - int ret; - - if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) - return ret; - - rs = (struct reiserfs_super_block *)buf; blocksize = blkid_le16(rs->rs_blocksize); /* If the superblock is inside the journal, we have the wrong one */ - if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block)) { - blkid_free_dev(dev); + if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block)) return -BLKID_ERR_BIG; - } - - /* Don't set this until there is no chance of error */ - *dev_p = dev; - - /* If the filesystem size is larger than the device, this is bad */ - dev->bid_size = blkid_le32(rs->rs_blocks_count) * blocksize; /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */ if (!strcmp(id->bim_magic, "ReIsEr2Fs") || !strcmp(id->bim_magic, "ReIsEr3Fs")) { if (strlen(rs->rs_label)) { - blkid_create_tag(dev, "LABEL", rs->rs_label, - sizeof(rs->rs_label)); - } - - if (!uuid_is_null(rs->rs_uuid)) { - char uuid[37]; - uuid_unparse(rs->rs_uuid, uuid); - blkid_create_tag(dev, "UUID", uuid, sizeof(uuid)); + blkid_set_tag(dev, "LABEL", rs->rs_label, + sizeof(rs->rs_label), 1); } - } - - return 0; -} -static int probe_minix(int fd, blkid_dev *dev_p, const char *devname, - struct blkid_magic *id, unsigned char *buf, - blkid_loff_t size) -{ - blkid_dev dev; - struct minix_super_block *ms; - int ret; - - if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) - return ret; - - ms = (struct minix_super_block *)buf; - - /* Don't set this until there is no chance of error */ - *dev_p = dev; - dev->bid_size = ms->ms_nzones << ms->ms_log_zone_size; - return 0; -} - -static int probe_swap(int fd, blkid_dev *dev_p, const char *devname, - struct blkid_magic *id, unsigned char *buf, - blkid_loff_t size) -{ - blkid_dev dev; - struct swap_header *sh; - int psize; - int ret; - - if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) - return ret; - - /* PAGE_SIZE can be found by where the magic is located */ - psize = (id->bim_kboff << 10) + (id->bim_sboff + 10); - - /* Don't set this until there is no chance of error */ - *dev_p = dev; - - sh = (struct swap_header *)buf; - /* Is swap data in local endian format? */ - dev->bid_size = (blkid_loff_t)(sh->sh_last_page + 1) * psize; - - /* A label can not exist on the old (128MB max) swap format */ - if (!strcmp(id->bim_magic, "SWAPSPACE2") && sh->sh_label[0]) { - blkid_create_tag(dev, "LABEL", sh->sh_label, - sizeof(sh->sh_label)); + set_uuid(dev, rs->rs_uuid); } return 0; } -static int probe_mdraid(int fd, blkid_dev *dev_p, const char *devname, - struct blkid_magic *id, unsigned char *buf, - blkid_loff_t size) -{ - blkid_dev dev; - struct mdp_superblock_s *md; - int ret; - - if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) - return ret; - - /* Don't set this until there is no chance of error */ - *dev_p = dev; - - md = (struct mdp_superblock_s *)buf; - /* What units is md->size in? Assume 512-byte sectors? */ - dev->bid_size = md->size * 512; - - /* The MD UUID is not contiguous in the superblock, make it so */ - if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) { - unsigned char md_uuid[16]; - char uuid[37]; - - memcpy(md_uuid, &md->set_uuid0, 4); - memcpy(md_uuid + 4, &md->set_uuid1, 12); - - uuid_unparse(md_uuid, uuid); - blkid_create_tag(dev, "UUID", uuid, sizeof(uuid)); - } - return 0; -} - -static int probe_hfs(int fd, blkid_dev *dev_p, const char *devname, - struct blkid_magic *id, unsigned char *buf, - blkid_loff_t size) -{ - blkid_dev dev; - struct hfs_super_block *hfs; - int ret; - - if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) - return ret; - - hfs = (struct hfs_super_block *)buf; - - if (blkid_be32(hfs->h_blksize) != 512) - return -BLKID_ERR_PARAM; - - /* Don't set this until there is no chance of error */ - *dev_p = dev; - - return 0; -} - - /* * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined - * in the type_array table below + bim_kbalign. If we ever start looking for magics - * relative to the end of a device, we can start using negative offsets - * in type_array. + * in the type_array table below + bim_kbalign. + * + * When probing for a lot of magics, we handle everything in 1kB buffers so + * that we don't have to worry about reading each combination of block sizes. */ -#define BLKID_BLK_BITS (10) -#define BLKID_BLK_KBITS (BLKID_BLK_BITS - 10) -#define BLKID_BLK_SIZE (1024 << BLKID_BLK_KBITS) -#define BLKID_BLK_MASK (BLKID_BLK_SIZE - 1) -#define BLKID_BLK_OFFS 128 /* currently MDRAID kboff + align */ +#define BLKID_BLK_OFFS 64 /* currently reiserfs */ /* * Various filesystem magics that we can check for. Note that kboff and * sboff are in kilobytes and bytes respectively. All magics are in * byte strings so we don't worry about endian issues. */ -struct blkid_magic type_array[] = { -/* type kboff sboff len magic align kbsize probe */ - { "MDRAID", -64, 0, 4, "\251+N\374", 65536, 4, probe_mdraid }, -/*{ "LVM", 0, 0, 4, "HM\001\000", 1, 4, probe_lvm },*/ - { "jbd", 1, 0x38, 2, "\123\357", 1, 1, probe_jbd }, - { "ext3", 1, 0x38, 2, "\123\357", 1, 1, probe_ext3 }, - { "ext2", 1, 0x38, 2, "\123\357", 1, 1, probe_ext2 }, - { "reiserfs", 8, 0x34, 8, "ReIsErFs", 1, 1, probe_reiserfs }, - { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", 1, 1, probe_reiserfs }, - { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", 1, 1, probe_reiserfs }, - { "reiserfs", 64, 0x34, 8, "ReIsErFs", 1, 1, probe_reiserfs }, - { "reiserfs", 8, 20, 8, "ReIsErFs", 1, 1, probe_reiserfs }, - { "ntfs", 0, 3, 8, "NTFS ", 1, 1, probe_default }, - { "vfat", 0, 0x52, 5, "MSWIN", 1, 1, probe_vfat }, - { "vfat", 0, 0x52, 8, "FAT32 ", 1, 1, probe_vfat }, - { "msdos", 0, 0x36, 5, "MSDOS", 1, 1, probe_msdos }, - { "msdos", 0, 0x36, 8, "FAT16 ", 1, 1, probe_msdos }, - { "msdos", 0, 0x36, 8, "FAT12 ", 1, 1, probe_msdos }, - { "minix", 1, 0x10, 2, "\177\023", 1, 1, probe_minix }, - { "minix", 1, 0x10, 2, "\217\023", 1, 1, probe_minix }, - { "minix", 1, 0x10, 2, "\150\044", 1, 1, probe_minix }, - { "minix", 1, 0x10, 2, "\170\044", 1, 1, probe_minix }, - { "vxfs", 1, 0, 4, "\365\374\001\245", 1, 1, probe_default }, - { "xfs", 0, 0, 4, "XFSB", 1, 1, probe_xfs }, - { "romfs", 0, 0, 8, "-rom1fs-", 1, 1, probe_default }, - { "bfs", 0, 0, 4, "\316\372\173\033", 1, 1, probe_default }, - { "cramfs", 0, 0, 4, "E=\315\034", 1, 1, probe_default }, - { "qnx4", 0, 4, 6, "QNX4FS", 1, 1, probe_default }, - { "iso9660", 32, 1, 5, "CD001", 1, 1, probe_default }, - { "iso9660", 32, 9, 5, "CDROM", 1, 1, probe_default }, - { "udf", 32, 1, 5, "BEA01", 1, 1, probe_default }, - { "udf", 32, 1, 5, "BOOT2", 1, 1, probe_default }, - { "udf", 32, 1, 5, "CD001", 1, 1, probe_default }, - { "udf", 32, 1, 5, "CDW02", 1, 1, probe_default }, - { "udf", 32, 1, 5, "NSR02", 1, 1, probe_default }, - { "udf", 32, 1, 5, "NSR03", 1, 1, probe_default }, - { "udf", 32, 1, 5, "TEA01", 1, 1, probe_default }, - { "jfs", 32, 0, 4, "JFS1", 1, 1, probe_default }, - { "hfs", 1, 0, 2, "BD", 1, 1, probe_hfs }, - { "ufs", 8, 0x55c, 4, "T\031\001\000", 1, 1, probe_default }, - { "hpfs", 8, 0, 4, "I\350\225\371", 1, 1, probe_default }, - { "sysv", 0, 0x3f8, 4, "\020~\030\375", 1, 1, probe_default }, - { "swap", 0, 0xff6, 10, "SWAP-SPACE", 1, 4, probe_swap }, - { "swap", 0, 0xff6, 10, "SWAPSPACE2", 1, 4, probe_swap }, - { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", 1, 8, probe_swap }, - { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", 1, 8, probe_swap }, - { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", 1, 16, probe_swap }, - { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", 1, 16, probe_swap }, - { NULL, 0, 0, 0, NULL, 1, 0, NULL } +static struct blkid_magic type_array[] = { +/* type kboff sboff len magic probe */ + { "jbd", 1, 0x38, 2, "\123\357", probe_jbd }, + { "ext3", 1, 0x38, 2, "\123\357", probe_ext3 }, + { "ext2", 1, 0x38, 2, "\123\357", probe_ext2 }, + { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs }, + { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs }, + { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs }, + { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs }, + { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs }, + { "ntfs", 0, 3, 8, "NTFS ", 0 }, + { "vfat", 0, 0x52, 5, "MSWIN", probe_vfat }, + { "vfat", 0, 0x52, 8, "FAT32 ", probe_vfat }, + { "msdos", 0, 0x36, 5, "MSDOS", probe_msdos }, + { "msdos", 0, 0x36, 8, "FAT16 ", probe_msdos }, + { "msdos", 0, 0x36, 8, "FAT12 ", probe_msdos }, + { "minix", 1, 0x10, 2, "\177\023", 0 }, + { "minix", 1, 0x10, 2, "\217\023", 0 }, + { "minix", 1, 0x10, 2, "\150\044", 0 }, + { "minix", 1, 0x10, 2, "\170\044", 0 }, + { "vxfs", 1, 0, 4, "\365\374\001\245", 0 }, + { "xfs", 0, 0, 4, "XFSB", probe_xfs }, + { "romfs", 0, 0, 8, "-rom1fs-", 0 }, + { "bfs", 0, 0, 4, "\316\372\173\033", 0 }, + { "cramfs", 0, 0, 4, "E=\315\034", 0 }, + { "qnx4", 0, 4, 6, "QNX4FS", 0 }, + { "iso9660", 32, 1, 5, "CD001", 0 }, + { "iso9660", 32, 9, 5, "CDROM", 0 }, + { "udf", 32, 1, 5, "BEA01", 0 }, + { "udf", 32, 1, 5, "BOOT2", 0 }, + { "udf", 32, 1, 5, "CD001", 0 }, + { "udf", 32, 1, 5, "CDW02", 0 }, + { "udf", 32, 1, 5, "NSR02", 0 }, + { "udf", 32, 1, 5, "NSR03", 0 }, + { "udf", 32, 1, 5, "TEA01", 0 }, + { "jfs", 32, 0, 4, "JFS1", 0 }, + { "hfs", 1, 0, 2, "BD", 0 }, + { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 }, + { "hpfs", 8, 0, 4, "I\350\225\371", 0 }, + { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 }, + { "swap", 0, 0xff6, 10, "SWAP-SPACE", 0 }, + { "swap", 0, 0xff6, 10, "SWAPSPACE2", 0 }, + { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", 0 }, + { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", 0 }, + { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", 0 }, + { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", 0 }, + { NULL, 0, 0, 0, NULL, NULL } }; - -/* - * When probing for a lot of magics, we handle everything in 1kB buffers so - * that we don't have to worry about reading each combination of block sizes. - */ -static unsigned char *read_one_buf(int fd, blkid_loff_t offset) -{ - unsigned char *buf; - - if (lseek(fd, offset, SEEK_SET) < 0) - return NULL; - - if (!(buf = (unsigned char *)malloc(BLKID_BLK_SIZE))) - return NULL; - - if (read(fd, buf, BLKID_BLK_SIZE) != BLKID_BLK_SIZE) { - free(buf); - return NULL; - } - - return buf; -} - -static unsigned char *read_sb_buf(int fd, unsigned char **bufs, int kboff, - blkid_loff_t start) -{ - int idx = kboff >> BLKID_BLK_KBITS; - unsigned char **buf; - - if (idx > BLKID_BLK_OFFS || idx < -BLKID_BLK_OFFS) { - fprintf(stderr, "reading from invalid offset %d (%d)!\n", - kboff, idx); - return NULL; - } - - buf = bufs + idx; - if (!*buf) - *buf = read_one_buf(fd, start); - - return *buf; -} - -static struct blkid_magic *devname_to_magic(const char *devname, int fd, - unsigned char **bufs, - struct blkid_magic *id, - blkid_loff_t size) -{ - struct blkid_magic *ret = NULL; - - if (!bufs || fd < 0) - return NULL; - - if (id >= type_array + sizeof(type_array) / sizeof(*id)) - return NULL; - - for (id = id < type_array ? type_array : id + 1; id->bim_type; ++id) { - unsigned char *buf; - blkid_loff_t start = 0LL; - blkid_loff_t offset = 0LL; - int kboff; - - offset = ((blkid_loff_t)id->bim_kboff << 10) + - (id->bim_sboff & ~0x3ffULL); - /* - * We index negative buffers by their actual offset (including - * superblock offsets > 1kB, not the aligned offset, so that - * we correctly access negative buffers with different - * alignment requirements. - */ - if (id->bim_kboff < 0) { - start = (size & ~((blkid_loff_t)(id->bim_align - 1))) + - offset; - if (start < 0) /* Device too small for alignment */ - continue; - kboff = (start - size) >> 10; - } else { - start = offset; - kboff = offset >> 10; - } - - if ((buf = - read_sb_buf(fd, bufs, kboff, start)) && - !memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ffULL), - id->bim_len)) { - ret = id; - break; - } - } - - return ret; -} - /* - * Get data from a single block special device. - * - * Return a blkid_dev with at least the device type and size set. - * If the passed-in size is zero, then we get the device size here. + * If a device's filesystem no longer checks out, we need to nuke + * information about it from the entry. */ -blkid_dev blkid_devname_to_dev(const char *devname, blkid_loff_t size) +static void blkid_invalidate_fs(blkid_dev dev) { - unsigned char *buf_array[BLKID_BLK_OFFS * 2 + 1]; - unsigned char **bufs = buf_array + BLKID_BLK_OFFS; - blkid_dev dev = NULL, last = NULL; - unsigned char *sb_buf = NULL; - int sb_size = 0; - struct blkid_magic *id = NULL; - blkid_loff_t diff_last = 0xf000000000000000ULL; - int fd; - - if (!devname) - return NULL; - - fd = open(devname, O_RDONLY); - if (fd < 0) - return NULL; - - if (!size) - size = blkid_get_dev_size(fd); - if (size < 1024) - goto exit_fd; - - memset(buf_array, 0, sizeof(buf_array)); - - while ((id = devname_to_magic(devname, fd, bufs, id, size)) && - diff_last) { - int new_sb; - blkid_loff_t diff_dev; - - DBG(printf("found type %s (#%d) on %s, probing\n", - id->bim_type, id - type_array, devname)); - - new_sb = id->bim_kbsize << 10; - if (sb_size < new_sb) { - unsigned char *sav = sb_buf; - if (!(sb_buf = realloc(sb_buf, new_sb))) { - sb_buf = sav; - continue; - } - sb_size = new_sb; - } - - if (id->bim_probe(fd, &dev, devname, id, sb_buf, size) < 0) - continue; - - diff_dev = size - dev->bid_size; - DBG(printf("size = %Lu, fs size = %Lu\n", size, dev->bid_size)); - DBG(printf("checking best match: old %Ld, new %Ld\n", - diff_last, diff_dev)); - /* See which type is a better match by checking size */ - if ((diff_last < 0 && diff_dev > diff_last) || - (diff_last > 0 && diff_dev >= 0 && diff_dev < diff_last)) { - if (last) - blkid_free_dev(last); - last = dev; - diff_last = diff_dev; - } else - blkid_free_dev(dev); - } - - if (!last) - DBG(printf("unknown device type on %s\n", devname)); - else - DBG(printf(last)); - - /* Free up any buffers we allocated */ - for (bufs = buf_array; bufs - buf_array < sizeof(buf_array) / - sizeof(buf_array[0]); bufs++) { - if (*bufs) - free(*bufs); - } - - if (sb_buf) - free(sb_buf); -exit_fd: - close(fd); - return last; -} + blkid_set_tag(dev, "TYPE", 0, 0, 0); + blkid_set_tag(dev, "LABEL", 0, 0, 0); + blkid_set_tag(dev, "UUID", 0, 0, 0); +} /* * Verify that the data in dev is consistent with what is on the actual @@ -733,13 +328,12 @@ exit_fd: */ blkid_dev blkid_verify_devname(blkid_cache cache, blkid_dev dev) { - blkid_loff_t size; struct blkid_magic *id; - blkid_dev new = NULL; - unsigned char *sb_buf = NULL; - int sb_size = 0; + unsigned char *bufs[BLKID_BLK_OFFS + 1], *buf; + const char *sec_type, *type; + struct stat st; time_t diff; - int fd; + int fd, idx; if (!dev) return NULL; @@ -752,10 +346,9 @@ blkid_dev blkid_verify_devname(blkid_cache cache, blkid_dev dev) DBG(printf("need to revalidate %s\n", dev->bid_name)); - if ((fd = open(dev->bid_name, O_RDONLY)) < 0) { + if (((fd = open(dev->bid_name, O_RDONLY)) < 0) || + (fstat(fd, &st) < 0) || !S_ISBLK(st.st_mode)) { if (errno == ENXIO || errno == ENODEV) { - fprintf(stderr, "unable to open %s for revalidation\n", - dev->bid_name); blkid_free_dev(dev); return NULL; } @@ -764,68 +357,117 @@ blkid_dev blkid_verify_devname(blkid_cache cache, blkid_dev dev) return dev; } - size = blkid_get_dev_size(fd); - - /* See if we can probe this device by its existing type directly */ + memset(bufs, 0, sizeof(bufs)); + + /* + * Iterate over the type array. If we already know the type, + * then try that first. If it doesn't work, then blow away + * the type information, and try again. + * + */ +try_again: + type = 0; + sec_type = 0; + if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) { + uuid_t uuid; + + if (check_mdraid(fd, uuid) == 0) { + set_uuid(dev, uuid); + type = "mdraid"; + goto found_type; + } + } for (id = type_array; id->bim_type; id++) { - if (!strcmp(id->bim_type, dev->bid_type)) { - int new_sb = id->bim_kbsize << 10; - /* See if we need to allocate a larger sb buffer */ - if (sb_size < new_sb) { - unsigned char *sav = sb_buf; - - /* We can't revalidate, return old dev */ - if (!(sb_buf = realloc(sb_buf, new_sb))) { - fprintf(stderr, "not enough memory for " - "%s revalidation\n", - dev->bid_name); - free(sav); - goto exit_fd; - } - sb_size = new_sb; + if (dev->bid_type && + strcmp(id->bim_type, dev->bid_type)) + continue; + + idx = id->bim_kboff + (id->bim_sboff >> 10); + if (idx > BLKID_BLK_OFFS || idx < 0) + continue; + buf = bufs[idx]; + if (!buf) { + if (lseek(fd, idx << 10, SEEK_SET) < 0) + continue; + + if (!(buf = (unsigned char *)malloc(1024))) + continue; + + if (read(fd, buf, 1024) != 1024) { + free(buf); + continue; } + bufs[idx] = buf; + } - if (id->bim_probe(fd, &new, dev->bid_name, id, sb_buf, - size) == 0) - break; + if (memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ff), + id->bim_len)) + continue; + + if ((id->bim_probe == NULL) || + (id->bim_probe(fd, cache, dev, id, buf, &sec_type) == 0)) { + type = id->bim_type; + goto found_type; } } - if (sb_buf) - free(sb_buf); + if (!id->bim_type && dev->bid_type) { + /* + * Zap the device filesystem type and try again + */ + blkid_invalidate_fs(dev); + goto try_again; + } - /* Otherwise we need to determine the device type first */ - if (new || (new = blkid_devname_to_dev(dev->bid_name, size))) { - new->bid_id = dev->bid_id; /* save old id for cache */ + if (!dev->bid_type) { blkid_free_dev(dev); - dev = blkid_add_dev_to_cache(cache, new); + return NULL; + } + +found_type: + if (dev && type) { + dev->bid_devno = st.st_rdev; + dev->bid_time = time(0); + dev->bid_flags |= BLKID_BID_FL_VERIFIED; + + blkid_set_tag(dev, "TYPE", type, 0, 1); + if (sec_type) + blkid_set_tag(dev, "TYPE", sec_type, 0, 0); + + DBG(printf("%s: devno 0x%04Lx, type %s\n", + dev->bid_name, st.st_rdev, type)); } -exit_fd: close(fd); - /* In case the cache is missing the device size */ - if (dev->bid_devsize == 0) - dev->bid_devsize = size; return dev; - } #ifdef TEST_PROGRAM int main(int argc, char **argv) { blkid_dev dev; + blkid_cache cache; if (argc != 2) { fprintf(stderr, "Usage: %s device\n" "Probe a single device to determine type\n", argv[0]); exit(1); } - dev = blkid_devname_to_dev(argv[1], 0); - if (dev) - blkid_free_dev(dev); - else + cache = blkid_new_cache(); + dev = blkid_get_devname(cache, argv[1], BLKID_DEV_NORMAL); + if (!dev) { printf("%s: %s has an unsupported type\n", argv[0], argv[1]); + return (1); + } + printf("%s is type %s\n", argv[1], dev->bid_type ? + dev->bid_type : "(null)"); + if (dev->bid_label) + printf("\tlabel is '%s'\n", dev->bid_label); + if (dev->bid_uuid) + printf("\tuuid is %s\n", dev->bid_uuid); + + blkid_free_dev(dev); return (0); } #endif diff --git a/lib/blkid/probe.h b/lib/blkid/probe.h index 23dd07f3..3e02604b 100644 --- a/lib/blkid/probe.h +++ b/lib/blkid/probe.h @@ -2,7 +2,7 @@ * probe.h - constants and on-disk structures for extracting device data * * Copyright (C) 1999 by Andries Brouwer - * Copyright (C) 1999, 2000 by Theodore Ts'o + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o * Copyright (C) 2001 by Andreas Dilger * * %Begin-Header% @@ -18,9 +18,9 @@ struct blkid_magic; -typedef int (*blkid_probe_t)(int fd, blkid_dev *dev_p, const char *devname, +typedef int (*blkid_probe_t)(int fd, blkid_cache cache, blkid_dev dev, struct blkid_magic *id, unsigned char *buf, - blkid_loff_t size); + const char **ret_sectype); struct blkid_magic { const char *bim_type; /* type name for this magic */ @@ -28,8 +28,6 @@ struct blkid_magic { unsigned bim_sboff; /* byte offset within superblock */ unsigned bim_len; /* length of magic */ const char *bim_magic; /* magic string */ - unsigned bim_align; /* byte alignment of superblock */ - unsigned bim_kbsize; /* size of superblock in kilobytes */ blkid_probe_t bim_probe; /* probe function */ }; @@ -202,6 +200,10 @@ struct hfs_super_block { #define _INLINE_ extern inline #endif +extern __u16 blkid_swab16(__u16 val); +extern __u32 blkid_swab32(__u32 val); +extern __u64 blkid_swab64(__u64 val); + #if ((defined __GNUC__) && \ (defined(__i386__) || defined(__i486__) || defined(__i586__))) diff --git a/lib/blkid/read.c b/lib/blkid/read.c index 89a7bfdf..7c9c4d42 100644 --- a/lib/blkid/read.c +++ b/lib/blkid/read.c @@ -1,7 +1,7 @@ /* * read.c - read the blkid cache from disk, to avoid scanning all devices * - * Copyright (C) 2001 Theodore Y. Ts'o + * Copyright (C) 2001, 2003 Theodore Y. Ts'o * Copyright (C) 2001 Andreas Dilger * * %Begin-Header% @@ -179,10 +179,9 @@ static int parse_end(char **cp) * <device foo=bar>devname</device> * <device>devname<foo>bar</foo></device> */ -static int parse_dev(blkid_dev *dev, char **cp) +static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp) { - char **name; - char *start, *tmp, *end; + char *start, *tmp, *end, *name; int ret; if ((ret = parse_start(cp)) <= 0) @@ -190,7 +189,7 @@ static int parse_dev(blkid_dev *dev, char **cp) start = tmp = strchr(*cp, '>'); if (!start) { - fprintf(stderr, "blkid: short line parsing dev: %s\n", *cp); + DBG(printf("blkid: short line parsing dev: %s\n", *cp)); return -BLKID_ERR_CACHE; } start = skip_over_blank(start + 1); @@ -206,30 +205,25 @@ static int parse_dev(blkid_dev *dev, char **cp) *tmp = '\0'; if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0) - fprintf(stderr, "blkid: missing </device> ending: %s\n", end); + DBG(printf("blkid: missing </device> ending: %s\n", end)); else if (tmp) *tmp = '\0'; if (end - start <= 1) { - fprintf(stderr, "blkid: empty device name: %s\n", *cp); + DBG(printf("blkid: empty device name: %s\n", *cp)); return -BLKID_ERR_CACHE; } - if (!(*dev = blkid_new_dev())) + name = blkid_strndup(start, end-start); + if (name == NULL) return -BLKID_ERR_MEM; - name = &(*dev)->bid_name; - *name = (char *)malloc(end - start + 1); - if (*name == NULL) { - blkid_free_dev(*dev); - return -BLKID_ERR_MEM; - } - - memcpy(*name, start, end - start); - (*name)[end - start] = '\0'; + DBG(printf("found dev %s\n", name)); - DBG(printf("found dev %s\n", *name)); + if (!(*dev = blkid_get_devname(cache, name, BLKID_DEV_CREATE))) + return -BLKID_ERR_MEM; + free(name); return 1; } @@ -253,7 +247,7 @@ static int parse_token(char **name, char **value, char **cp) if (**value == '"') { end = strchr(*value + 1, '"'); if (!end) { - fprintf(stderr, "unbalanced quotes at: %s\n", *value); + DBG(printf("unbalanced quotes at: %s\n", *value)); *cp = *value; return -BLKID_ERR_CACHE; } @@ -319,13 +313,11 @@ static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp) cache->bic_idmax = dev->bid_id; } else if (!strcmp(name, "DEVNO")) dev->bid_devno = STRTOULL(value, 0, 0); - else if (!strcmp(name, "DEVSIZE")) - dev->bid_devno = STRTOULL(value, 0, 0); else if (!strcmp(name, "TIME")) /* FIXME: need to parse a long long eventually */ dev->bid_time = strtol(value, 0, 0); else - ret = blkid_create_tag(dev, name, value, strlen(value)); + ret = blkid_set_tag(dev, name, value, strlen(value), 0); DBG(printf(" tag: %s=\"%s\"\n", name, value)); @@ -355,7 +347,7 @@ static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp) DBG(printf("line: %s\n", cp)); - if ((ret = parse_dev(dev_p, &cp)) <= 0) + if ((ret = parse_dev(cache, dev_p, &cp)) <= 0) return ret; dev = *dev_p; @@ -365,37 +357,54 @@ static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp) } if (dev->bid_type == NULL) { - fprintf(stderr, "blkid: device %s has no TYPE\n",dev->bid_name); + DBG(printf("blkid: device %s has no TYPE\n",dev->bid_name)); blkid_free_dev(dev); } DEB_DUMP_DEV(dev); - *dev_p = blkid_add_dev_to_cache(cache, dev); - return ret; } /* - * Read the given file stream for cached device data, and return it - * in a newly allocated cache struct. - * - * Returns 0 on success, or -ve error value. + * Parse the specified filename, and return the data in the supplied or + * a newly allocated cache struct. If the file doesn't exist, return a + * new empty cache struct. */ -int blkid_read_cache_file(blkid_cache *cache, FILE *file) +int blkid_get_cache(blkid_cache *cache, const char *filename) { + FILE *file; char buf[4096]; int lineno = 0; - if (!file || !cache) + if (!cache) return -BLKID_ERR_PARAM; - if (!*cache) - *cache = blkid_new_cache(); - - if (!*cache) + if ((*cache = blkid_new_cache()) == NULL) return -BLKID_ERR_MEM; + if (!filename || !strlen(filename)) + filename = BLKID_CACHE_FILE; + else + (*cache)->bic_filename = blkid_strdup(filename); + + DBG(printf("cache file %s\n", filename)); + + if (!strcmp(filename, "-")) + file = stdin; + else { + /* + * If the file doesn't exist, then we just return an empty + * struct so that the cache can be populated. + */ + if (access(filename, R_OK) < 0) + return 0; + + file = fopen(filename, "r"); + if (!file) + return errno; /* Should never happen */ + } + while (fgets(buf, sizeof(buf), file)) { blkid_dev dev; @@ -410,77 +419,19 @@ int blkid_read_cache_file(blkid_cache *cache, FILE *file) } if (blkid_parse_line(*cache, &dev, buf) < 0) { - fprintf(stderr, "blkid: bad format on line %d\n", - lineno); + DBG(printf("blkid: bad format on line %d\n", lineno)); continue; } } - /* - * Initially assume that we do not need to write out the cache file. - * This would be incorrect if we probed first, and parsed the cache - * afterwards, or parsed two caches and wanted to write it out, but - * the alternative is to force manually marking the cache dirty when - * any device is added, and that is also prone to error. + * Initially we do not need to write out the cache file. */ (*cache)->bic_flags &= ~BLKID_BIC_FL_CHANGED; - return 0; -} - -/* - * Parse the specified filename, and return the data in the supplied or - * a newly allocated cache struct. If the file doesn't exist, return a - * new empty cache struct. - */ -int blkid_read_cache(blkid_cache *cache, const char *filename) -{ - FILE *file; - int ret; - - if (!cache) - return -BLKID_ERR_PARAM; - - if (!filename || !strlen(filename)) - filename = BLKID_CACHE_FILE; - - DBG(printf("cache file %s\n", filename)); - - /* If we read the standard cache file, do not do so again */ - if (!strcmp(filename, BLKID_CACHE_FILE) && (*cache) && - ((*cache)->bic_flags & BLKID_BIC_FL_PARSED)) - return 0; - - if (!strcmp(filename, "-") || !strcmp(filename, "stdin")) - file = stdin; - else { - /* - * If the file doesn't exist, then we just return an empty - * struct so that the cache can be populated. - */ - if (access(filename, R_OK) < 0) { - *cache = blkid_new_cache(); - - return *cache ? 0 : -BLKID_ERR_MEM; - } - - file = fopen(filename, "r"); - if (!file) { - perror(filename); - return errno; - } - } - - ret = blkid_read_cache_file(cache, file); - if (file != stdin) fclose(file); - /* Mark us as having read the standard cache file */ - if (!strcmp(filename, BLKID_CACHE_FILE)) - (*cache)->bic_flags |= BLKID_BIC_FL_PARSED; - - return ret; + return 0; } #ifdef TEST_PROGRAM @@ -494,11 +445,11 @@ int main(int argc, char**argv) "Test parsing of the cache (filename)\n", argv[0]); exit(1); } - if ((ret = blkid_read_cache(&cache, argv[1])) < 0) + if ((ret = blkid_get_cache(&cache, argv[1])) < 0) fprintf(stderr, "error %d reading cache file %s\n", ret, argv[1] ? argv[1] : BLKID_CACHE_FILE); - blkid_free_cache(cache); + blkid_put_cache(cache); return ret; } diff --git a/lib/blkid/resolve.c b/lib/blkid/resolve.c index 04ce1495..19478ed3 100644 --- a/lib/blkid/resolve.c +++ b/lib/blkid/resolve.c @@ -1,7 +1,7 @@ /* * resolve.c - resolve names and tags into specific devices * - * Copyright (C) 2001 Theodore Ts'o. + * Copyright (C) 2001, 2003 Theodore Ts'o. * Copyright (C) 2001 Andreas Dilger * * %Begin-Header% @@ -47,9 +47,9 @@ char *blkid_get_tagname_devname(blkid_cache cache, const char *tagname, if (!cache) DBG(printf("no cache given, direct device probe\n")); - if ((dev = blkid_get_devname(cache, devname)) && - (found = blkid_find_tag_dev(dev, tagname, NULL))) - ret = string_copy(found->bit_val); + if ((dev = blkid_get_devname(cache, devname, BLKID_DEV_NORMAL)) && + (found = blkid_find_tag_dev(dev, tagname))) + ret = blkid_strdup(found->bit_val); if (!cache) blkid_free_dev(dev); @@ -62,8 +62,6 @@ char *blkid_get_tagname_devname(blkid_cache cache, const char *tagname, * pair. In the case of a token, value is ignored. If the "token" is not * of the form "NAME=value" and there is no value given, then it is assumed * to be the actual devname and a copy is returned. - * - * The string returned must be freed with string_free(). */ char *blkid_get_token(blkid_cache cache, const char *token, const char *value) @@ -80,7 +78,7 @@ char *blkid_get_token(blkid_cache cache, const char *token, value ? value : "", cache ? "in cache" : "from disk")); if (!cache) { - if (blkid_read_cache(&c, NULL) < 0) + if (blkid_get_cache(&c, NULL) < 0) c = blkid_new_cache(); if (!c) return NULL; @@ -98,7 +96,7 @@ char *blkid_get_token(blkid_cache cache, const char *token, if (!dev) goto errout; - ret = string_copy(blkid_devname_name(dev)); + ret = blkid_strdup(blkid_devname_name(dev)); errout: if (t) @@ -106,8 +104,7 @@ errout: if (v) free(v); if (!cache) { - blkid_save_cache(c, NULL); - blkid_free_cache(c); + blkid_put_cache(c); } return (ret); } diff --git a/lib/blkid/save.c b/lib/blkid/save.c index e888d0c5..5a8771e7 100644 --- a/lib/blkid/save.c +++ b/lib/blkid/save.c @@ -2,6 +2,7 @@ * save.c - write the cache struct to disk * * Copyright (C) 2001 by Andreas Dilger + * Copyright (C) 2003 Theodore Ts'o * * %Begin-Header% * This file may be redistributed under the terms of the @@ -54,41 +55,17 @@ static int save_dev(blkid_dev dev, FILE *file) return 0; } -int blkid_save_cache_file(blkid_cache cache, FILE *file) -{ - struct list_head *p; - int ret = 0; - - if (!cache || !file) - return -BLKID_ERR_PARAM; - - if (list_empty(&cache->bic_devs) || - !cache->bic_flags & BLKID_BIC_FL_CHANGED) - return 0; - - list_for_each(p, &cache->bic_devs) { - blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs); - if ((ret = save_dev(dev, file)) < 0) - break; - } - - if (ret >= 0) { - cache->bic_flags &= ~BLKID_BIC_FL_CHANGED; - ret = 1; - } - - return ret; -} - /* * Write out the cache struct to the cache file on disk. */ -int blkid_save_cache(blkid_cache cache, const char *filename) +int blkid_flush_cache(blkid_cache cache) { + struct list_head *p; char *tmp = NULL; const char *opened = NULL; + const char *filename; FILE *file = NULL; - int fd, ret; + int fd, ret = 0; if (!cache) return -BLKID_ERR_PARAM; @@ -99,10 +76,9 @@ int blkid_save_cache(blkid_cache cache, const char *filename) return 0; } - if (!filename || !strlen(filename)) - filename = BLKID_CACHE_FILE; + filename = cache->bic_filename ? cache->bic_filename: BLKID_CACHE_FILE; - if (!strcmp(filename, "-") || !strcmp(filename, "stdout")) + if (!strcmp(filename, "-")) file = stdout; else { struct stat st; @@ -142,14 +118,23 @@ int blkid_save_cache(blkid_cache cache, const char *filename) DBG(printf("cache file %s (really %s)\n", filename, opened)); if (!file) { - perror(opened); - if (tmp) - free(tmp); - return errno; + ret = errno; + goto errout; } } - ret = blkid_save_cache_file(cache, file); + list_for_each(p, &cache->bic_devs) { + blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs); + if (!dev->bid_type) + continue; + if ((ret = save_dev(dev, file)) < 0) + break; + } + + if (ret >= 0) { + cache->bic_flags &= ~BLKID_BIC_FL_CHANGED; + ret = 1; + } if (file != stdout) { fclose(file); @@ -173,6 +158,7 @@ int blkid_save_cache(blkid_cache cache, const char *filename) } } +errout: if (tmp) free(tmp); return ret; @@ -189,13 +175,23 @@ int main(int argc, char **argv) "Test loading/saving a cache (filename)\n", argv[0]); exit(1); } - if ((ret = blkid_probe_all(&cache) < 0)) - fprintf(stderr, "error probing devices\n"); - else if ((ret = blkid_save_cache(cache, argv[1])) < 0) - fprintf(stderr, "error %d saving cache to %s\n", ret, - argv[1] ? argv[1] : BLKID_CACHE_FILE); - blkid_free_cache(cache); + if ((cache = blkid_new_cache()) == NULL) { + fprintf(stderr, "%s: error creating cache\n", argv[0]); + exit(1); + } + if ((ret = blkid_probe_all(cache)) < 0) { + fprintf(stderr, "error (%d) probing devices\n", ret); + exit(1); + } + cache->bic_filename = blkid_strdup(argv[1]); + + if ((ret = blkid_flush_cache(cache)) < 0) { + fprintf(stderr, "error (%d) saving cache\n", ret); + exit(1); + } + + blkid_put_cache(cache); return ret; } diff --git a/lib/blkid/tag.c b/lib/blkid/tag.c index d0e1b0a0..9bb99e14 100644 --- a/lib/blkid/tag.c +++ b/lib/blkid/tag.c @@ -2,6 +2,7 @@ * tag.c - allocation/initialization/free routines for tag structs * * Copyright (C) 2001 Andreas Dilger + * Copyright (C) 2003 Theodore Ts'o * * %Begin-Header% * This file may be redistributed under the terms of the @@ -21,7 +22,7 @@ #define DBG(x) #endif -blkid_tag blkid_new_tag(void) +static blkid_tag blkid_new_tag(void) { blkid_tag tag; @@ -39,16 +40,17 @@ void blkid_free_tag(blkid_tag tag) if (!tag) return; - DBG(printf(" freeing tag %s=%s\n", tag->bit_name, tag->bit_val)); + DBG(printf(" freeing tag %s=%s\n", tag->bit_name, + tag->bit_val ? tag->bit_val : "(NULL)")); DEB_DUMP_TAG(tag); list_del(&tag->bit_tags); /* list of tags for this device */ list_del(&tag->bit_names); /* list of tags with this type */ if (tag->bit_name) - string_free(tag->bit_name); + free(tag->bit_name); if (tag->bit_val) - string_free(tag->bit_val); + free(tag->bit_val); free(tag); } @@ -57,122 +59,148 @@ void blkid_free_tag(blkid_tag tag) * Find the desired tag on a device. If value is NULL, then the * first such tag is returned, otherwise return only exact tag if found. */ -blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type, - const char *value) +blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type) { - blkid_tag found = NULL; struct list_head *p; - if (!dev || !type || !value) + if (!dev || !type) return NULL; list_for_each(p, &dev->bid_tags) { blkid_tag tmp = list_entry(p, struct blkid_struct_tag, bit_tags); - if (!strcmp(tmp->bit_name, type) && - (!value || !strcmp(tmp->bit_val, value))){ - found = tmp; - break; - } + if (!strcmp(tmp->bit_name, type)) + return tmp; } - - return found; + return NULL; } /* * Find the desired tag type in the cache. * We return the head tag for this tag type. */ -blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type) +static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type) { - blkid_tag head = NULL; + blkid_tag head = NULL, tmp; struct list_head *p; if (!cache || !type) return NULL; list_for_each(p, &cache->bic_tags) { - blkid_tag tmp = list_entry(p, struct blkid_struct_tag, - bit_tags); - + tmp = list_entry(p, struct blkid_struct_tag, bit_tags); if (!strcmp(tmp->bit_name, type)) { DBG(printf(" found cache tag head %s\n", type)); head = tmp; break; } } - return head; } /* - * Add a single tag to the given device. - * This function is not currently exported because adding arbitrary tags to - * a device will just get lost as soon as we verify the device (which - * uses the dev struct returned from the device probe). At some point in - * the future it may be desirable to allow adding arbitrary tags to a device, - * and ensure that verify keeps all such tags (maybe lower case tag names?) - */ -static void add_tag_to_dev(blkid_dev dev, blkid_tag tag) -{ - if (!dev) - return; - - DBG(printf("adding tag %s=%s\n", tag->bit_name, tag->bit_val)); - - tag->bit_dev = dev; - - list_add_tail(&tag->bit_tags, &dev->bid_tags); - - /* Link common tags directly to the device struct */ - if (!strcmp(tag->bit_name, "TYPE") && !dev->bid_type) - dev->bid_type = tag->bit_val; - else if (!strcmp(tag->bit_name, "LABEL")) - dev->bid_label = tag->bit_val; - else if (!strcmp(tag->bit_name, "UUID")) - dev->bid_uuid = tag->bit_val; -} - -/* - * Allocate and fill out a tag struct. - * If dev is valid, the tag will be added to the tags for this device - * if an identical tag does not already exist. - * If tag is valid, the tag will be returned in this pointer. + * Set a tag on an existing device. + * + * If replace is non-zero, blkid_set_tag() will replace the existing + * tag with the specified value. Otherwise, it will add the specified + * tag to the device. + * + * If value is NULL, then delete all tags with that name from the + * device. */ -int blkid_create_tag(blkid_dev dev, const char *name, - const char *value, const int vlength) +int blkid_set_tag(blkid_dev dev, const char *name, + const char *value, const int vlength, int replace) { - blkid_tag t, found; + blkid_tag t = 0, head = 0; + char *val = 0; - if (!dev) + if (!dev || !name) return -BLKID_ERR_PARAM; - if (!name) - return -BLKID_ERR_PARAM; +repeat: + t = blkid_find_tag_dev(dev, name); + val = blkid_strndup(value, vlength); + if (!value) { + if (t) { + blkid_free_tag(t); + goto repeat; + } else + goto link_tags; + } + if (!val) + goto errout; + if (t) { + if (!strcmp(t->bit_val, val)) { + /* Same thing, exit */ + free(val); + return 0; + } + if (replace) { + free(t->bit_val); + t->bit_val = val; + goto link_tags; + } + dev->bid_flags |= BLKID_BID_FL_MTYPE; + } + /* Existing tag not present, add to device */ t = blkid_new_tag(); if (!t) - return -BLKID_ERR_MEM; - - t->bit_name = string_copy(name); - t->bit_val = stringn_copy(value, vlength); - - if ((found = blkid_find_tag_dev(dev, name, t->bit_val))) { - blkid_free_tag(t); - return 0; + goto errout; + t->bit_name = blkid_strdup(name); + t->bit_val = val; + t->bit_dev = dev; + + list_add_tail(&t->bit_tags, &dev->bid_tags); + + if (dev->bid_cache) { + head = blkid_find_head_cache(dev->bid_cache, t->bit_name); + if (!head) { + head = blkid_new_tag(); + if (!head) + goto errout; + + DBG(printf(" creating new cache tag head %s\n", + name)); + head->bit_name = blkid_strdup(name); + if (!head->bit_name) + goto errout; + list_add_tail(&head->bit_tags, + &dev->bid_cache->bic_tags); + } + list_add_tail(&t->bit_names, &head->bit_names); } - - add_tag_to_dev(dev, t); - + +link_tags: + /* Link common tags directly to the device struct */ + if (!strcmp(name, "TYPE") && (!val || !dev->bid_type)) + dev->bid_type = val; + else if (!strcmp(name, "LABEL")) + dev->bid_label = val; + else if (!strcmp(name, "UUID")) + dev->bid_uuid = val; + + if (dev->bid_cache) + dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED; return 0; + +errout: + if (t) + blkid_free_tag(t); + else if (val) + free(val); + if (head) + blkid_free_tag(head); + return -BLKID_ERR_MEM; } + /* * Parse a "NAME=value" string. This is slightly different than * parse_token, because that will end an unquoted value at a space, while * this will assume that an unquoted value is the rest of the token (e.g. - * if we are passed al alreay quoted string from the command-line we don't + * if we are passed an already quoted string from the command-line we don't * have to both quote and escape quote so that the quotes make it to * us). * @@ -187,7 +215,7 @@ int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val) if (!token || !(cp = strchr(token, '='))) return -1; - name = string_copy(token); + name = blkid_strdup(token); if (!name) return -1; value = name + (cp - token); @@ -198,7 +226,7 @@ int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val) goto errout; /* missing closing quote */ *cp = '\0'; } - value = string_copy(value); + value = blkid_strdup(value); if (!value) goto errout; @@ -208,7 +236,7 @@ int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val) return 0; errout: - string_free(name); + free(name); return -1; } @@ -291,7 +319,7 @@ extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache, const char *type, const char *value) { - blkid_tag head = 0, found; + blkid_tag head = 0, found = 0; struct list_head *p; if (!cache || !type || !value) @@ -303,19 +331,20 @@ try_again: if (!head) head = blkid_find_head_cache(cache, type); - found = 0; - list_for_each(p, &head->bit_names) { - blkid_tag tmp = list_entry(p, struct blkid_struct_tag, - bit_names); + if (head) { + list_for_each(p, &head->bit_names) { + blkid_tag tmp = list_entry(p, struct blkid_struct_tag, + bit_names); - if (!strcmp(tmp->bit_val, value)) { - found = tmp; - break; + if (!strcmp(tmp->bit_val, value)) { + found = tmp; + break; + } } } if ((!head || !found) && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) { - blkid_probe_all(&cache); + blkid_probe_all(cache); goto try_again; } return (found ? found->bit_dev : NULL); |