Commit 50b380b4 authored by Theodore Ts'o's avatar Theodore Ts'o
Browse files

Wholesale changes to blkid library to simplify the implementation

and shrink its size.  Change library version to be 1.0.
parent 19445ef9
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
......
......@@ -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
......@@ -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);
......
......@@ -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
}
......
......@@ -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;
}
......
......@@ -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,77 +51,10 @@ 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
*/
......@@ -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
......@@ -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
/*
* 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
......@@ -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),
......
This diff is collapsed.
......@@ -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__)))
......
/*
* 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;
}
......
/*
* 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);
}
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -68,11 +68,6 @@ static void print_tags(blkid_dev dev, char *show[], int numtag)
printf("%s: ", blkid_devname_name(dev));
first = 0;
}
if (!strcmp(type, "TYPE")) {
if (printed_type)
return;
printed_type = 1;
}
printf("%s=\"%s\" ", type, value);
}
blkid_tag_iterate_end(iter);
......@@ -156,7 +151,7 @@ int main(int argc, char **argv)
goto exit;
}
if (blkid_read_cache(&cache, read) < 0)
if (blkid_get_cache(&cache, read) < 0)
goto exit;
err = 2;
......@@ -166,7 +161,7 @@ int main(int argc, char **argv)
/* Load any additional devices not in the cache */
for (i = 0; i < numdev; i++)
blkid_get_devname(cache, devices[i]);
blkid_get_devname(cache, devices[i], BLKID_DEV_NORMAL);
if ((dev = blkid_find_dev_with_tag(cache, search_type,
search_value))) {
......@@ -178,7 +173,7 @@ int main(int argc, char **argv)
blkid_dev_iterate iter;
blkid_dev dev;
blkid_probe_all(&cache);
blkid_probe_all(cache);
iter = blkid_dev_iterate_begin(cache);
while (blkid_dev_next(iter, &dev) == 0) {
......@@ -188,7 +183,8 @@ int main(int argc, char **argv)
blkid_dev_iterate_end(iter);
/* Add all specified devices to cache (optionally display tags) */
} else for (i = 0; i < numdev; i++) {
blkid_dev dev = blkid_get_devname(cache, devices[i]);
blkid_dev dev = blkid_get_devname(cache, devices[i],
BLKID_DEV_NORMAL);
if (dev) {
print_tags(dev, show, numtag);
......@@ -201,7 +197,6 @@ exit:
free(search_type);
if (search_value)
free(search_value);
blkid_save_cache(cache, write);
blkid_free_cache(cache);
blkid_put_cache(cache);
return err;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment