2003-02-22 Theodore Ts'o <tytso@mit.edu>
+ * 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
/* 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);
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,
};
#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 */
/*
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 */
};
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[];
/* 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);
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
int blkid_debug_mask;
-blkid_cache blkid_new_cache(void)
+int blkid_get_cache(blkid_cache *ret_cache, const char *filename)
{
blkid_cache cache;
}
#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)
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))
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);
cache->bic_time = time(0);
cache->bic_flags |= BLKID_BIC_FL_PROBED;
+ blkid_flush_cache(cache);
return 0;
}
int main(int argc, char **argv)
{
blkid_cache cache = NULL;
+ int ret;
blkid_debug_mask = DEBUG_ALL;
if (argc != 1) {
"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)
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;
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;
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];
--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];
--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;
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;
!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);
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 },
{ NULL, 0, 0, 0, NULL, NULL }
};
-/*
- * 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
{
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;
*/
try_again:
type = 0;
- sec_type = 0;
if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) {
uuid_t uuid;
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;
}
/*
* 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;
}
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));
{
blkid_dev dev;
blkid_cache cache;
+ int ret;
blkid_debug_mask = DEBUG_ALL;
if (argc != 2) {
"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]);
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 */
#include <ctype.h>
#include <string.h>
#include <time.h>
+#include <sys/types.h>
#include <sys/stat.h>
+#include <fcntl.h>
#include <unistd.h>
#if HAVE_ERRNO_H
#include <errno.h>
/* 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));
* 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;
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;
/*
* 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
if (!cache) {
if (blkid_get_cache(&c, NULL) < 0)
- c = blkid_new_cache();
- if (!c)
return NULL;
}
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);
}
printf("device %s, type %s\n", dev->bid_name, dev->bid_type));
fprintf(file,
- "<device TYPE=\"%s\" DEVNO=\"0x%04lx\" TIME=\"%lu\"",
- dev->bid_type, (unsigned long) dev->bid_devno, dev->bid_time);
+ "<device DEVNO=\"0x%04lx\" TIME=\"%lu\"",
+ (unsigned long) dev->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</device>\n", dev->bid_name);
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) {
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));
}
}
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) {
/*
* 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;
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;
const char *type,
const char *value)
{
- blkid_tag head, found;
+ blkid_tag head;
blkid_dev dev;
int pri;
struct list_head *p;
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);
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);