From 79dd234a799434b6dc8365c49e743f00eb09d2fd Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 22 Feb 2003 17:15:20 -0500 Subject: [PATCH] Internal changes to the blkid library: 1) Only one tag with a particular name can be attached to a device at a time. This significantly simplifies the library, and was needed to allow the cache file to be re-read and changes integrated into the in-core version of the data structure in a simpler fashion than earlier versions of the library. 2) To accomodate this, the ext2/ext3 filesystems are now always tagged as "ext2" type filesystems. Ext3 filesystems are tagged with a SEC_TYPE tag with the value ext3. 3) The new blkid_read_cache() function checks the mod time of the cache file, and if the file has been changed since the last time the cache file was read into memory, it is re-read. This function is now called before probing all of the devices in the system or searching all devices in the cache for a specific tag value. 4) After probing all devices, blkid_flush_cache() is called to write out the cache file. This assures that all of the hard work involved in doing a blkid_probe_all() is saved to disk. --- lib/blkid/ChangeLog | 33 ++++++++++++++ lib/blkid/blkid.h | 2 +- lib/blkid/blkidP.h | 8 ++-- lib/blkid/cache.c | 21 ++++++--- lib/blkid/devname.c | 8 +++- lib/blkid/probe.c | 106 ++++++++++++++++--------------------------- lib/blkid/probe.h | 3 +- lib/blkid/read.c | 68 ++++++++++++++-------------- lib/blkid/resolve.c | 4 +- lib/blkid/save.c | 126 +++++++++++++++++++++++++--------------------------- lib/blkid/tag.c | 103 ++++++++++++++++++------------------------ 11 files changed, 238 insertions(+), 244 deletions(-) diff --git a/lib/blkid/ChangeLog b/lib/blkid/ChangeLog index 4cb7b93..8fcab4e 100644 --- a/lib/blkid/ChangeLog +++ b/lib/blkid/ChangeLog @@ -1,5 +1,38 @@ 2003-02-22 Theodore Ts'o + * devname.c (blkid_probe_all), tag.c (blkid_find_dev_with_tag): + Call blkid_read_cache to make sure the in-core version of + the data structure is the latest. After probing all of + the devices in blkid_probe_all() force the cache file to + be written out, the probe_all represents a lot of effort + that shouldn't be lost. + + * tag.c (blkid_set_tag): Always replace an existing tag with the + new value; we no longer suppor multiple tags with the same + value attached to a device, as this was never really + supported well, and significantly increased the code + complexity. + + * probe.c (probe_ext2): Change handling of ext2/ext3 filesystems. + Ext3 filesystems are now always treated as ext2 + filesystems, with a special SEC_TYPE tag set to ext3. + This was necessary because we now longer support multiple + tags with the same name attached to a device. + + * save.c (save_dev): Don't special case the TYPE tag; just write + it out along with all of the normal tags. + (blkid_flush_cache): Eliminate special case code for stdout. + + * cache.c (blkid_new_cache, blkid_get_cache): Eliminate + blkid_new_cache and fold into blkid_get_cache (moved to + cache.c) + + * read.c (blkid_read_cache): New function created from + blkid_get_cache which used to be in read.c that only + updates the in-core cache data structure from the file. + Uses the file modification time of the cache file to + determine whether the cache file needs to be re-read. + * cache.c, dev.c, devname.c, devno.c, probe.c, read.c, resolve.c, save.c, tag.c, blkidP.h: Add dynamic debugging capabilities, controlled by the environment variable diff --git a/lib/blkid/blkid.h b/lib/blkid/blkid.h index de6a982..75b20ad 100644 --- a/lib/blkid/blkid.h +++ b/lib/blkid/blkid.h @@ -48,6 +48,7 @@ typedef struct blkid_struct_dev_iterate *blkid_dev_iterate; /* cache.c */ extern void blkid_put_cache(blkid_cache cache); +extern int blkid_get_cache(blkid_cache *cache, const char *filename); /* dev.c */ extern const char *blkid_dev_devname(blkid_dev dev); @@ -68,7 +69,6 @@ extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, extern blkid_loff_t blkid_get_dev_size(int fd); /* read.c */ -int blkid_get_cache(blkid_cache *cache, const char *filename); /* resolve.c */ extern char *blkid_get_tagname_devname(blkid_cache cache, const char *tagname, diff --git a/lib/blkid/blkidP.h b/lib/blkid/blkidP.h index db05675..a121106 100644 --- a/lib/blkid/blkidP.h +++ b/lib/blkid/blkidP.h @@ -42,7 +42,6 @@ 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 */ /* @@ -87,6 +86,7 @@ struct blkid_struct_cache struct list_head bic_devs; /* List head of all devices */ struct list_head bic_tags; /* List head of all tag types */ time_t bic_time; /* Last probe time */ + time_t bic_ftime; /* Mod time of the cachefile */ unsigned int bic_flags; /* Status flags of the cache */ char *bic_filename; /* filename of cache */ }; @@ -96,7 +96,6 @@ struct blkid_struct_cache 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 *blkid_devdirs[]; @@ -209,6 +208,9 @@ extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence); /* probe.c */ extern blkid_dev blkid_verify_devname(blkid_cache cache, blkid_dev dev); +/* read.c */ +extern void blkid_read_cache(blkid_cache cache); + /* save.c */ extern int blkid_flush_cache(blkid_cache cache); @@ -218,7 +220,7 @@ extern int blkid_flush_cache(blkid_cache cache); extern void blkid_free_tag(blkid_tag tag); 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); + const char *value, const int vlength); /* * Functions to create and find a specific tag type: dev.c diff --git a/lib/blkid/cache.c b/lib/blkid/cache.c index 9312416..50d52a0 100644 --- a/lib/blkid/cache.c +++ b/lib/blkid/cache.c @@ -15,7 +15,7 @@ int blkid_debug_mask; -blkid_cache blkid_new_cache(void) +int blkid_get_cache(blkid_cache *ret_cache, const char *filename) { blkid_cache cache; @@ -29,15 +29,23 @@ blkid_cache blkid_new_cache(void) } #endif - DBG(DEBUG_CACHE, printf("initializing empty cache\n")); + 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 NULL; + return -BLKID_ERR_MEM; INIT_LIST_HEAD(&cache->bic_devs); INIT_LIST_HEAD(&cache->bic_tags); - return cache; + if (!filename || !strlen(filename)) + filename = BLKID_CACHE_FILE; + cache->bic_filename = blkid_strdup(filename); + + blkid_read_cache(cache); + + *ret_cache = cache; + return 0; } void blkid_put_cache(blkid_cache cache) @@ -97,8 +105,9 @@ int main(int argc, char** argv) argv[1] ? argv[1] : BLKID_CACHE_FILE); exit(1); } - if ((cache = blkid_new_cache()) == NULL) { - fprintf(stderr, "%s: error creating cache\n", argv[0]); + 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)) diff --git a/lib/blkid/devname.c b/lib/blkid/devname.c index 7d88551..27a9d0c 100644 --- a/lib/blkid/devname.c +++ b/lib/blkid/devname.c @@ -280,6 +280,7 @@ int blkid_probe_all(blkid_cache cache) time(0) - cache->bic_time < BLKID_PROBE_INTERVAL) return 0; + blkid_read_cache(cache); evms_probe_all(cache); #ifdef VG_DIR lvm_probe_all(cache); @@ -340,6 +341,7 @@ int blkid_probe_all(blkid_cache cache) cache->bic_time = time(0); cache->bic_flags |= BLKID_BIC_FL_PROBED; + blkid_flush_cache(cache); return 0; } @@ -347,6 +349,7 @@ int blkid_probe_all(blkid_cache cache) int main(int argc, char **argv) { blkid_cache cache = NULL; + int ret; blkid_debug_mask = DEBUG_ALL; if (argc != 1) { @@ -354,8 +357,9 @@ int main(int argc, char **argv) "Probe all devices and exit\n", argv[0]); exit(1); } - if ((cache = blkid_new_cache()) == NULL) { - fprintf(stderr, "%s: error creating cache\n", argv[0]); + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { + fprintf(stderr, "%s: error creating cache (%d)\n", + argv[0], ret); exit(1); } if (blkid_probe_all(cache) < 0) diff --git a/lib/blkid/probe.c b/lib/blkid/probe.c index 4f76ba5..2484a5f 100644 --- a/lib/blkid/probe.c +++ b/lib/blkid/probe.c @@ -74,15 +74,15 @@ static void set_uuid(blkid_dev dev, uuid_t uuid) if (!uuid_is_null(uuid)) { uuid_unparse(uuid, str); - blkid_set_tag(dev, "UUID", str, sizeof(str), 1); + blkid_set_tag(dev, "UUID", str, sizeof(str)); } } static int probe_ext2(int fd, blkid_cache cache, blkid_dev dev, - struct blkid_magic *id, unsigned char *buf, - const char **ret_sectype) + struct blkid_magic *id, unsigned char *buf) { struct ext2_super_block *es; + const char *sec_type = 0; es = (struct ext2_super_block *)buf; @@ -91,26 +91,28 @@ static int probe_ext2(int fd, blkid_cache cache, blkid_dev dev, 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))) + /* Distinguish between jbd and ext2/3 fs */ + if (id && (blkid_le32(es->s_feature_incompat) & + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) return -BLKID_ERR_PARAM; if (strlen(es->s_volume_name)) blkid_set_tag(dev, "LABEL", es->s_volume_name, - sizeof(es->s_volume_name), 1); + sizeof(es->s_volume_name)); set_uuid(dev, es->s_uuid); + if (blkid_le32(es->s_feature_compat) & + EXT3_FEATURE_COMPAT_HAS_JOURNAL) + sec_type = "ext3"; + + blkid_set_tag(dev, "SEC_TYPE", sec_type, 0); + return 0; } static int probe_jbd(int fd, blkid_cache cache, blkid_dev dev, - struct blkid_magic *id, unsigned char *buf, - const char **ret_sectype) + struct blkid_magic *id, unsigned char *buf) { struct ext2_super_block *es = (struct ext2_super_block *) buf; @@ -118,33 +120,11 @@ static int probe_jbd(int fd, blkid_cache cache, blkid_dev dev, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) return -BLKID_ERR_PARAM; - return (probe_ext2(fd, cache, dev, id, buf, ret_sectype)); -} - -static int probe_ext3(int fd, blkid_cache cache, blkid_dev dev, - struct blkid_magic *id, unsigned char *buf, - const char **ret_sectype) -{ - struct ext2_super_block *es = (struct ext2_super_block *) buf; - int ret; - - if (!(blkid_le32(es->s_feature_compat) & - EXT3_FEATURE_COMPAT_HAS_JOURNAL)) - return -BLKID_ERR_PARAM; - - 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)) - *ret_sectype = "ext2"; - - return 0; + return (probe_ext2(fd, cache, dev, 0, buf)); } static int probe_vfat(int fd, blkid_cache cache, blkid_dev dev, - struct blkid_magic *id, unsigned char *buf, - const char **ret_sectype) + struct blkid_magic *id, unsigned char *buf) { struct vfat_super_block *vs; char serno[10]; @@ -158,20 +138,19 @@ static int probe_vfat(int fd, blkid_cache cache, blkid_dev dev, --end; if (end >= vs->vs_label) blkid_set_tag(dev, "LABEL", vs->vs_label, - end - vs->vs_label + 1, 1); + end - vs->vs_label + 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_set_tag(dev, "UUID", serno, sizeof(serno), 1); + blkid_set_tag(dev, "UUID", serno, sizeof(serno)); return 0; } static int probe_msdos(int fd, blkid_cache cache, blkid_dev dev, - struct blkid_magic *id, unsigned char *buf, - const char **ret_sectype) + struct blkid_magic *id, unsigned char *buf) { struct msdos_super_block *ms = (struct msdos_super_block *) buf; char serno[10]; @@ -183,20 +162,19 @@ static int probe_msdos(int fd, blkid_cache cache, blkid_dev dev, --end; if (end >= ms->ms_label) blkid_set_tag(dev, "LABEL", ms->ms_label, - end - ms->ms_label + 1, 1); + end - ms->ms_label + 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_set_tag(dev, "UUID", serno, 0, 1); + blkid_set_tag(dev, "UUID", serno, 0); return 0; } static int probe_xfs(int fd, blkid_cache cache, blkid_dev dev, - struct blkid_magic *id, unsigned char *buf, - const char **ret_sectype) + struct blkid_magic *id, unsigned char *buf) { struct xfs_super_block *xs; @@ -204,14 +182,13 @@ static int probe_xfs(int fd, blkid_cache cache, blkid_dev dev, if (strlen(xs->xs_fname)) blkid_set_tag(dev, "LABEL", xs->xs_fname, - sizeof(xs->xs_fname), 1); + sizeof(xs->xs_fname)); set_uuid(dev, xs->xs_uuid); return 0; } static int probe_reiserfs(int fd, blkid_cache cache, blkid_dev dev, - struct blkid_magic *id, unsigned char *buf, - const char **ret_sectype) + struct blkid_magic *id, unsigned char *buf) { struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf; unsigned int blocksize; @@ -227,7 +204,7 @@ static int probe_reiserfs(int fd, blkid_cache cache, blkid_dev dev, !strcmp(id->bim_magic, "ReIsEr3Fs")) { if (strlen(rs->rs_label)) { blkid_set_tag(dev, "LABEL", rs->rs_label, - sizeof(rs->rs_label), 1); + sizeof(rs->rs_label)); } set_uuid(dev, rs->rs_uuid); @@ -253,7 +230,6 @@ static int probe_reiserfs(int fd, blkid_cache cache, blkid_dev dev, 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 }, @@ -300,17 +276,6 @@ static struct blkid_magic type_array[] = { }; /* - * If a device's filesystem no longer checks out, we need to nuke - * information about it from the entry. - */ -static void blkid_invalidate_fs(blkid_dev dev) -{ - 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 * block device (using the devname field only). Normally this will be * called when finding items in the cache, but for long running processes @@ -323,7 +288,7 @@ blkid_dev blkid_verify_devname(blkid_cache cache, blkid_dev dev) { struct blkid_magic *id; unsigned char *bufs[BLKID_BLK_OFFS + 1], *buf; - const char *sec_type, *type; + const char *type; struct stat st; time_t diff; int fd, idx; @@ -364,7 +329,6 @@ blkid_dev blkid_verify_devname(blkid_cache cache, blkid_dev dev) */ try_again: type = 0; - sec_type = 0; if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) { uuid_t uuid; @@ -402,7 +366,7 @@ try_again: continue; if ((id->bim_probe == NULL) || - (id->bim_probe(fd, cache, dev, id, buf, &sec_type) == 0)) { + (id->bim_probe(fd, cache, dev, id, buf) == 0)) { type = id->bim_type; goto found_type; } @@ -412,7 +376,10 @@ try_again: /* * Zap the device filesystem type and try again */ - blkid_invalidate_fs(dev); + blkid_set_tag(dev, "TYPE", 0, 0); + blkid_set_tag(dev, "SEC_TYPE", 0, 0); + blkid_set_tag(dev, "LABEL", 0, 0); + blkid_set_tag(dev, "UUID", 0, 0); goto try_again; } @@ -428,9 +395,7 @@ found_type: dev->bid_flags |= BLKID_BID_FL_VERIFIED; cache->bic_flags |= BLKID_BIC_FL_CHANGED; - blkid_set_tag(dev, "TYPE", type, 0, 1); - if (sec_type) - blkid_set_tag(dev, "TYPE", sec_type, 0, 0); + blkid_set_tag(dev, "TYPE", type, 0); DBG(DEBUG_PROBE, printf("%s: devno 0x%04Lx, type %s\n", dev->bid_name, st.st_rdev, type)); @@ -446,6 +411,7 @@ int main(int argc, char **argv) { blkid_dev dev; blkid_cache cache; + int ret; blkid_debug_mask = DEBUG_ALL; if (argc != 2) { @@ -453,7 +419,11 @@ int main(int argc, char **argv) "Probe a single device to determine type\n", argv[0]); exit(1); } - cache = blkid_new_cache(); + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { + fprintf(stderr, "%s: error creating cache (%d)\n", + argv[0], ret); + exit(1); + } dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL); if (!dev) { printf("%s: %s has an unsupported type\n", argv[0], argv[1]); diff --git a/lib/blkid/probe.h b/lib/blkid/probe.h index 3e02604..391428c 100644 --- a/lib/blkid/probe.h +++ b/lib/blkid/probe.h @@ -19,8 +19,7 @@ struct blkid_magic; typedef int (*blkid_probe_t)(int fd, blkid_cache cache, blkid_dev dev, - struct blkid_magic *id, unsigned char *buf, - const char **ret_sectype); + struct blkid_magic *id, unsigned char *buf); struct blkid_magic { const char *bim_type; /* type name for this magic */ diff --git a/lib/blkid/read.c b/lib/blkid/read.c index fdee756..71618e3 100644 --- a/lib/blkid/read.c +++ b/lib/blkid/read.c @@ -14,7 +14,9 @@ #include #include #include +#include #include +#include #include #if HAVE_ERRNO_H #include @@ -312,7 +314,7 @@ static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp) /* FIXME: need to parse a long long eventually */ dev->bid_time = strtol(value, 0, 0); else - ret = blkid_set_tag(dev, name, value, strlen(value), 0); + ret = blkid_set_tag(dev, name, value, strlen(value)); DBG(DEBUG_READ, printf(" tag: %s=\"%s\"\n", name, value)); @@ -367,40 +369,37 @@ static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp) * a newly allocated cache struct. If the file doesn't exist, return a * new empty cache struct. */ -int blkid_get_cache(blkid_cache *cache, const char *filename) +void blkid_read_cache(blkid_cache cache) { FILE *file; char buf[4096]; - int lineno = 0; + int fd, lineno = 0; + struct stat st; if (!cache) - return -BLKID_ERR_PARAM; - - if ((*cache = blkid_new_cache()) == NULL) - return -BLKID_ERR_MEM; + return; - if (!filename || !strlen(filename)) - filename = BLKID_CACHE_FILE; - else - (*cache)->bic_filename = blkid_strdup(filename); - - DBG(DEBUG_READ|DEBUG_CACHE, printf("reading 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 */ + /* + * If the file doesn't exist, then we just return an empty + * struct so that the cache can be populated. + */ + if ((fd = open(cache->bic_filename, O_RDONLY)) < 0) + return 0; + if (fstat(fd, &st) < 0) + goto errout; + if ((st.st_mtime == cache->bic_ftime) || + (cache->bic_flags & BLKID_BIC_FL_CHANGED)) { + DBG(DEBUG_CACHE, printf("skipping re-read of %s\n", + cache->bic_filename)); + goto errout; } + + DBG(DEBUG_CACHE, printf("reading cache file %s\n", + cache->bic_filename)); + + file = fdopen(fd, "r"); + if (!file) + goto errout; while (fgets(buf, sizeof(buf), file)) { blkid_dev dev; @@ -410,12 +409,12 @@ int blkid_get_cache(blkid_cache *cache, const char *filename) lineno++; /* Continue reading next line if it ends with a backslash */ while (buf[end] == '\\' && end < sizeof(buf) - 2 && - fgets(buf + end, sizeof(buf) - end, stdin)) { + fgets(buf + end, sizeof(buf) - end, file)) { end = strlen(buf) - 1; lineno++; } - if (blkid_parse_line(*cache, &dev, buf) < 0) { + if (blkid_parse_line(cache, &dev, buf) < 0) { DBG(DEBUG_READ, printf("blkid: bad format on line %d\n", lineno)); continue; @@ -424,12 +423,13 @@ int blkid_get_cache(blkid_cache *cache, const char *filename) /* * Initially we do not need to write out the cache file. */ - (*cache)->bic_flags &= ~BLKID_BIC_FL_CHANGED; - - if (file != stdin) - fclose(file); + cache->bic_flags &= ~BLKID_BIC_FL_CHANGED; + cache->bic_ftime = st.st_mtime; return 0; +errout: + close(fd); + return; } #ifdef TEST_PROGRAM diff --git a/lib/blkid/resolve.c b/lib/blkid/resolve.c index 7e729cb..62764c7 100644 --- a/lib/blkid/resolve.c +++ b/lib/blkid/resolve.c @@ -70,8 +70,6 @@ char *blkid_get_devname(blkid_cache cache, const char *token, if (!cache) { if (blkid_get_cache(&c, NULL) < 0) - c = blkid_new_cache(); - if (!c) return NULL; } @@ -115,7 +113,7 @@ int main(int argc, char **argv) argv[0], argv[0]); exit(1); } - if (blkid_get_cache(&cache, 0) < 0) { + if (blkid_get_cache(&cache, "/dev/null") < 0) { fprintf(stderr, "Couldn't get blkid cache\n"); exit(1); } diff --git a/lib/blkid/save.c b/lib/blkid/save.c index 82b9b77..bed211a 100644 --- a/lib/blkid/save.c +++ b/lib/blkid/save.c @@ -37,14 +37,13 @@ static int save_dev(blkid_dev dev, FILE *file) printf("device %s, type %s\n", dev->bid_name, dev->bid_type)); fprintf(file, - "bid_type, (unsigned long) dev->bid_devno, dev->bid_time); + "bid_devno, dev->bid_time); if (dev->bid_pri) fprintf(file, " PRI=\"%d\"", dev->bid_pri); list_for_each(p, &dev->bid_tags) { blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags); - if (strcmp(tag->bit_name, "TYPE")) - fprintf(file, " %s=\"%s\"", tag->bit_name,tag->bit_val); + fprintf(file, " %s=\"%s\"", tag->bit_name,tag->bit_val); } fprintf(file, ">%s\n", dev->bid_name); @@ -62,63 +61,59 @@ int blkid_flush_cache(blkid_cache cache) const char *filename; FILE *file = NULL; int fd, ret = 0; + struct stat st; if (!cache) return -BLKID_ERR_PARAM; if (list_empty(&cache->bic_devs) || !(cache->bic_flags & BLKID_BIC_FL_CHANGED)) { - DBG(DEBUG_SAVE, printf("empty cache, not saving\n")); + DBG(DEBUG_SAVE, printf("skipping cache file write\n")); return 0; } filename = cache->bic_filename ? cache->bic_filename: BLKID_CACHE_FILE; - if (!strcmp(filename, "-")) - file = stdout; - else { - struct stat st; - - /* If we can't write to the cache file, then don't even try */ - if (((ret = stat(filename, &st)) < 0 && errno != ENOENT) || - (ret == 0 && access(filename, W_OK) < 0)) { - DBG(DEBUG_SAVE, - printf("can't write to cache file %s\n", filename)); - return 0; - } + /* If we can't write to the cache file, then don't even try */ + if (((ret = stat(filename, &st)) < 0 && errno != ENOENT) || + (ret == 0 && access(filename, W_OK) < 0)) { + DBG(DEBUG_SAVE, + printf("can't write to cache file %s\n", filename)); + return 0; + } - /* - * Try and create a temporary file in the same directory so - * that in case of error we don't overwrite the cache file. - * If the cache file doesn't yet exist, it isn't a regular - * file (e.g. /dev/null or a socket), or we couldn't create - * a temporary file then we open it directly. - */ - if (ret == 0 && S_ISREG(st.st_mode)) { - tmp = malloc(strlen(filename) + 8); - if (tmp) { - sprintf(tmp, "%s-XXXXXX", filename); - fd = mkstemp(tmp); - if (fd >= 0) { - file = fdopen(fd, "w"); - opened = tmp; - } - fchmod(fd, 0644); + /* + * Try and create a temporary file in the same directory so + * that in case of error we don't overwrite the cache file. + * If the cache file doesn't yet exist, it isn't a regular + * file (e.g. /dev/null or a socket), or we couldn't create + * a temporary file then we open it directly. + */ + if (ret == 0 && S_ISREG(st.st_mode)) { + tmp = malloc(strlen(filename) + 8); + if (tmp) { + sprintf(tmp, "%s-XXXXXX", filename); + fd = mkstemp(tmp); + if (fd >= 0) { + file = fdopen(fd, "w"); + opened = tmp; } + fchmod(fd, 0644); } + } - if (!file) { - file = fopen(filename, "w"); - opened = filename; - } + if (!file) { + file = fopen(filename, "w"); + opened = filename; + } - DBG(DEBUG_SAVE, - printf("cache file %s (really %s)\n", filename, opened)); + DBG(DEBUG_SAVE, + printf("writing cache file %s (really %s)\n", + filename, opened)); - if (!file) { - ret = errno; - goto errout; - } + if (!file) { + ret = errno; + goto errout; } list_for_each(p, &cache->bic_devs) { @@ -134,27 +129,25 @@ int blkid_flush_cache(blkid_cache cache) ret = 1; } - if (file != stdout) { - fclose(file); - if (opened != filename) { - if (ret < 0) { - unlink(opened); - DBG(DEBUG_SAVE, - printf("unlinked temp cache %s\n", opened)); - } else { - char *backup; - - backup = malloc(strlen(filename) + 5); - if (backup) { - sprintf(backup, "%s.old", filename); - unlink(backup); - link(filename, backup); - free(backup); - } - rename(opened, filename); - DBG(DEBUG_SAVE, - printf("moved temp cache %s\n", opened)); + fclose(file); + if (opened != filename) { + if (ret < 0) { + unlink(opened); + DBG(DEBUG_SAVE, + printf("unlinked temp cache %s\n", opened)); + } else { + char *backup; + + backup = malloc(strlen(filename) + 5); + if (backup) { + sprintf(backup, "%s.old", filename); + unlink(backup); + link(filename, backup); + free(backup); } + rename(opened, filename); + DBG(DEBUG_SAVE, + printf("moved temp cache %s\n", opened)); } } @@ -177,8 +170,9 @@ int main(int argc, char **argv) exit(1); } - if ((cache = blkid_new_cache()) == NULL) { - fprintf(stderr, "%s: error creating cache\n", argv[0]); + 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) { diff --git a/lib/blkid/tag.c b/lib/blkid/tag.c index e8b54f4..d3db41c 100644 --- a/lib/blkid/tag.c +++ b/lib/blkid/tag.c @@ -97,15 +97,10 @@ static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type) /* * 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. + * If value is NULL, then delete the tagsfrom the device. */ int blkid_set_tag(blkid_dev dev, const char *name, - const char *value, const int vlength, int replace) + const char *value, const int vlength) { blkid_tag t = 0, head = 0; char *val = 0; @@ -113,64 +108,52 @@ int blkid_set_tag(blkid_dev dev, const char *name, if (!dev || !name) return -BLKID_ERR_PARAM; -repeat: + if (!(val = blkid_strndup(value, vlength))) + return -BLKID_ERR_MEM; t = blkid_find_tag_dev(dev, name); - val = blkid_strndup(value, vlength); if (!value) { - if (t) { + if (t) blkid_free_tag(t); - goto repeat; - } else - goto link_tags; - } - if (!val) - goto errout; - if (t) { + } else 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) - 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); + free(t->bit_val); + t->bit_val = val; + } else { + /* Existing tag not present, add to device */ + if (!(t = blkid_new_tag())) + 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(DEBUG_TAG, - 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); + 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(DEBUG_TAG, + 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); } - list_add_tail(&t->bit_names, &head->bit_names); } -link_tags: /* Link common tags directly to the device struct */ - if (!strcmp(name, "TYPE") && (!val || !dev->bid_type)) + if (!strcmp(name, "TYPE")) dev->bid_type = val; else if (!strcmp(name, "LABEL")) dev->bid_label = val; @@ -313,7 +296,7 @@ extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache, const char *type, const char *value) { - blkid_tag head, found; + blkid_tag head; blkid_dev dev; int pri; struct list_head *p; @@ -321,11 +304,12 @@ extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache, if (!cache || !type || !value) return NULL; + blkid_read_cache(cache); + DBG(DEBUG_TAG, printf("looking for %s=%s in cache\n", type, value)); try_again: pri = -1; - found = 0; dev = 0; head = blkid_find_head_cache(cache, type); @@ -336,15 +320,16 @@ try_again: if (!strcmp(tmp->bit_val, value) && tmp->bit_dev->bid_pri > pri) { - found = tmp; - dev = found->bit_dev; + dev = tmp->bit_dev; pri = dev->bid_pri; } } } - dev = blkid_verify_devname(cache, dev); - if (dev && strcmp(found->bit_val, value)) - dev = 0; + if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) { + dev = blkid_verify_devname(cache, dev); + if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED)) + goto try_again; + } if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) { blkid_probe_all(cache); -- 1.8.3.1