static void blkid_probe_to_tags(blkid_probe pr, blkid_dev dev) { const 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) continue; if (strncmp(name, "PART_ENTRY_", 11) == 0) { if (strcmp(name, "PART_ENTRY_UUID") == 0) blkid_set_tag(dev, "PARTUUID", data, len); else if (strcmp(name, "PART_ENTRY_NAME") == 0) blkid_set_tag(dev, "PARTLABEL", data, len); } else if (!strstr(name, "_ID")) { /* superblock UUID, LABEL, ... * but not {SYSTEM,APPLICATION,..._ID} */ blkid_set_tag(dev, name, data, len); } } }
static void get_ext2_info(blkid_dev dev, struct blkid_magic *id, unsigned char *buf) { struct ext2_super_block *es = (struct ext2_super_block *) buf; const char *label = 0; DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n", blkid_le32(es->s_feature_compat), blkid_le32(es->s_feature_incompat), blkid_le32(es->s_feature_ro_compat))); if (strlen(es->s_volume_name)) label = es->s_volume_name; blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name)); set_uuid(dev, es->s_uuid, 0); if ((es->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) && !uuid_is_null(es->s_journal_uuid)) set_uuid(dev, es->s_journal_uuid, "EXT_JOURNAL"); if (strcmp(id->bim_type, "ext2") && ((blkid_le32(es->s_feature_incompat) & EXT2_FEATURE_INCOMPAT_UNSUPPORTED) == 0)) blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2")); }
/* * Extract a tag from the line. * * Return 1 if a valid tag was found. * Return 0 if no tag found. * Return -ve error code. */ static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp) { char *name = NULL; char *value = NULL; int ret; if (!cache || !dev) return -BLKID_ERR_PARAM; if ((ret = parse_token(&name, &value, cp)) <= 0 /* && (ret = parse_xml(&name, &value, cp)) <= 0 */) return ret; DBG(READ, ul_debug("tag: %s=\"%s\"", name, value)); /* Some tags are stored directly in the device struct */ if (!strcmp(name, "DEVNO")) dev->bid_devno = strtoull(value, NULL, 0); else if (!strcmp(name, "PRI")) dev->bid_pri = strtol(value, NULL, 0); else if (!strcmp(name, "TIME")) { char *end = NULL; dev->bid_time = strtoull(value, &end, 0); if (end && *end == '.') dev->bid_utime = strtoull(end + 1, NULL, 0); } else ret = blkid_set_tag(dev, name, value, strlen(value)); return ret < 0 ? ret : 1; }
static void set_uuid(blkid_dev dev, uuid_t uuid, const char *tag) { char str[37]; if (!uuid_is_null(uuid)) { uuid_unparse(uuid, str); blkid_set_tag(dev, tag ? tag : "UUID", str, sizeof(str)); } }
static void blkid_probe_to_tags(blkid_probe pr, blkid_dev dev) { const 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, data, len); } }
static void get_ext2_info(blkid_dev dev, unsigned char *buf) { struct ext2_super_block *es = (struct ext2_super_block *) buf; const char *label = 0; DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n", blkid_le32(es->s_feature_compat), blkid_le32(es->s_feature_incompat), blkid_le32(es->s_feature_ro_compat))); if (strlen(es->s_volume_name)) label = es->s_volume_name; blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name)); set_uuid(dev, es->s_uuid); }
/* * 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 %m (%d) while " "trying to stat %s\n", 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 && #ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC (st.st_mtime < dev->bid_time || (st.st_mtime == dev->bid_time && st.st_mtim.tv_nsec / 1000 <= dev->bid_utime)) && #else st.st_mtime <= dev->bid_time && #endif (diff < BLKID_PROBE_MIN || (dev->bid_flags & BLKID_BID_FL_VERIFIED && diff < BLKID_PROBE_INTERVAL))) return dev; #ifndef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 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)); #else DBG(DEBUG_PROBE, printf("need to revalidate %s (cache time %lu.%lu, stat time %lu.%lu,\n\t" "time since last check %lu)\n", dev->bid_name, (unsigned long)dev->bid_time, (unsigned long)dev->bid_utime, (unsigned long)st.st_mtime, (unsigned long)st.st_mtim.tv_nsec / 1000, (unsigned long)diff)); #endif if (!cache->probe) { cache->probe = blkid_new_probe(); if (!cache->probe) { blkid_free_dev(dev); return NULL; } } fd = open(dev->bid_name, O_RDONLY|O_CLOEXEC); if (fd < 0) { DBG(DEBUG_PROBE, printf("blkid_verify: error %m (%d) while " "opening %s\n", 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_enable_superblocks(cache->probe, TRUE); blkid_probe_set_superblocks_flags(cache->probe, BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE); blkid_probe_enable_partitions(cache->probe, TRUE); blkid_probe_set_partitions_flags(cache->probe, BLKID_PARTS_ENTRY_DETAILS); /* * 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_superblocks_type(cache->probe, BLKID_FLTR_ONLYIN, fltr); if (!blkid_do_probe(cache->probe)) goto found_type; blkid_probe_invert_superblocks_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_safeprobe(cache->probe)) { /* found nothing or error */ blkid_free_dev(dev); dev = NULL; } found_type: if (dev) { #ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC struct timeval tv; if (!gettimeofday(&tv, NULL)) { dev->bid_time = tv.tv_sec; dev->bid_utime = tv.tv_usec; } else #endif dev->bid_time = time(0); dev->bid_devno = st.st_rdev; 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, dev->bid_type)); } blkid_reset_probe(cache->probe); blkid_probe_reset_superblocks_filter(cache->probe); close(fd); return dev; }