summaryrefslogtreecommitdiffstats
path: root/libs/blkid/src/verify.c
diff options
context:
space:
mode:
authorKarel Zak2008-09-06 15:28:40 +0200
committerKarel Zak2009-02-11 23:21:43 +0100
commit51410fc6deb29cae54a2669aafabae6c49f964fc (patch)
tree6117857f4be228ce38b16ba9794c12d7da5641c5 /libs/blkid/src/verify.c
parentblkid: minor changes to library build system (diff)
downloadkernel-qcow2-util-linux-51410fc6deb29cae54a2669aafabae6c49f964fc.tar.gz
kernel-qcow2-util-linux-51410fc6deb29cae54a2669aafabae6c49f964fc.tar.xz
kernel-qcow2-util-linux-51410fc6deb29cae54a2669aafabae6c49f964fc.zip
blkid: add low level probing API
(sorry from the huge patch..) Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libs/blkid/src/verify.c')
-rw-r--r--libs/blkid/src/verify.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/libs/blkid/src/verify.c b/libs/blkid/src/verify.c
new file mode 100644
index 000000000..4db8d7b2c
--- /dev/null
+++ b/libs/blkid/src/verify.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include "blkidP.h"
+
+static void blkid_probe_to_tags(blkid_probe pr, blkid_dev dev)
+{
+ unsigned char *data;
+ const char *name;
+ int nvals, n;
+ size_t len;
+
+ nvals = blkid_probe_numof_values(pr);
+
+ for (n = 0; n < nvals; n++) {
+ if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
+ blkid_set_tag(dev, name, (char *) data, len);
+ }
+}
+
+/*
+ * 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
+ * is also desirable to revalidate an item before use.
+ *
+ * If we are unable to revalidate the data, we return the old data and
+ * do not set the BLKID_BID_FL_VERIFIED flag on it.
+ */
+blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
+{
+ struct stat st;
+ time_t diff, now;
+ char *fltr[2];
+ int fd;
+
+ if (!dev)
+ return NULL;
+
+ now = time(0);
+ diff = now - dev->bid_time;
+
+ if (stat(dev->bid_name, &st) < 0) {
+ DBG(DEBUG_PROBE,
+ printf("blkid_verify: error %s (%d) while "
+ "trying to stat %s\n", strerror(errno), errno,
+ dev->bid_name));
+ open_err:
+ if ((errno == EPERM) || (errno == EACCES) || (errno == ENOENT)) {
+ /* We don't have read permission, just return cache data. */
+ DBG(DEBUG_PROBE, printf("returning unverified data for %s\n",
+ dev->bid_name));
+ return dev;
+ }
+ blkid_free_dev(dev);
+ return NULL;
+ }
+
+ if ((now >= dev->bid_time) &&
+ (st.st_mtime <= dev->bid_time) &&
+ ((diff < BLKID_PROBE_MIN) ||
+ (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
+ diff < BLKID_PROBE_INTERVAL)))
+ return dev;
+
+ DBG(DEBUG_PROBE,
+ printf("need to revalidate %s (cache time %lu, stat time %lu,\n\t"
+ "time since last check %lu)\n",
+ dev->bid_name, (unsigned long)dev->bid_time,
+ (unsigned long)st.st_mtime, (unsigned long)diff));
+
+
+ if (!cache->probe)
+ cache->probe = blkid_new_probe();
+
+ fd = open(dev->bid_name, O_RDONLY);
+ if (fd < 0) {
+ DBG(DEBUG_PROBE, printf("blkid_verify: error %s (%d) while "
+ "opening %s\n", strerror(errno), errno,
+ dev->bid_name));
+ goto open_err;
+ }
+
+ if (blkid_probe_set_device(cache->probe, fd, 0, 0)) {
+ /* failed to read the device */
+ close(fd);
+ blkid_free_dev(dev);
+ return NULL;
+ }
+
+ blkid_probe_set_request(cache->probe,
+ BLKID_PROBREQ_LABEL | BLKID_PROBREQ_UUID |
+ BLKID_PROBREQ_TYPE | BLKID_PROBREQ_SECTYPE);
+
+ /*
+ * If we already know the type, then try that first.
+ */
+ if (dev->bid_type) {
+ blkid_tag_iterate iter;
+ const char *type, *value;
+
+ fltr[0] = dev->bid_type;
+ fltr[1] = NULL;
+
+ blkid_probe_filter_types(cache->probe,
+ BLKID_FLTR_ONLYIN, fltr);
+
+ if (!blkid_do_probe(cache->probe))
+ goto found_type;
+ blkid_probe_invert_filter(cache->probe);
+
+ /*
+ * Zap the device filesystem information and try again
+ */
+ DBG(DEBUG_PROBE,
+ printf("previous fs type %s not valid, "
+ "trying full probe\n", dev->bid_type));
+ iter = blkid_tag_iterate_begin(dev);
+ while (blkid_tag_next(iter, &type, &value) == 0)
+ blkid_set_tag(dev, type, 0, 0);
+ blkid_tag_iterate_end(iter);
+ }
+
+ /*
+ * Probe for all types.
+ */
+ if (blkid_do_probe(cache->probe)) {
+ /* found nothing */
+ blkid_free_dev(dev);
+ dev = NULL;
+ }
+
+found_type:
+ if (dev) {
+ dev->bid_devno = st.st_rdev;
+ dev->bid_time = time(0);
+ dev->bid_flags |= BLKID_BID_FL_VERIFIED;
+ cache->bic_flags |= BLKID_BIC_FL_CHANGED;
+
+ blkid_probe_to_tags(cache->probe, dev);
+
+ DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n",
+ dev->bid_name, (long long)st.st_rdev, type));
+ }
+
+ blkid_reset_probe(cache->probe);
+ blkid_probe_reset_filter(cache->probe);
+ close(fd);
+ return dev;
+}
+
+#ifdef TEST_PROGRAM
+int main(int argc, char **argv)
+{
+ blkid_dev dev;
+ blkid_cache cache;
+ int ret;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s device\n"
+ "Probe a single device to determine type\n", argv[0]);
+ exit(1);
+ }
+ 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]);
+ return (1);
+ }
+ printf("TYPE='%s'\n", dev->bid_type ? dev->bid_type : "(null)");
+ if (dev->bid_label)
+ printf("LABEL='%s'\n", dev->bid_label);
+ if (dev->bid_uuid)
+ printf("UUID='%s'\n", dev->bid_uuid);
+
+ blkid_free_dev(dev);
+ return (0);
+}
+#endif