static int probe_superblocks(blkid_probe pr) { struct stat st; int rc; if (fstat(blkid_probe_get_fd(pr), &st)) return -1; blkid_probe_enable_partitions(pr, 1); if (!S_ISCHR(st.st_mode) && blkid_probe_get_size(pr) <= 1024 * 1440 && blkid_probe_is_wholedisk(pr)) { /* * check if the small disk is partitioned, if yes then * don't probe for filesystems. */ blkid_probe_enable_superblocks(pr, 0); rc = blkid_do_fullprobe(pr); if (rc < 0) return rc; /* -1 = error, 1 = nothing, 0 = success */ if (blkid_probe_lookup_value(pr, "PTTYPE", NULL, NULL) == 0) return 0; /* partition table detected */ } blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS); blkid_probe_enable_superblocks(pr, 1); return blkid_do_safeprobe(pr); }
static int _wipe_known_signatures_with_blkid(struct device *dev, const char *name, uint32_t types_to_exclude, uint32_t types_no_prompt, int yes, force_t force, int *wiped) { blkid_probe probe = NULL; int found = 0, left = 0, wiped_tmp; int r_wipe; int r = 0; if (!wiped) wiped = &wiped_tmp; *wiped = 0; /* TODO: Should we check for valid dev - _dev_is_valid(dev)? */ if (!(probe = blkid_new_probe_from_filename(dev_name(dev)))) { log_error("Failed to create a new blkid probe for device %s.", dev_name(dev)); goto out; } blkid_probe_enable_partitions(probe, 1); blkid_probe_set_partitions_flags(probe, BLKID_PARTS_MAGIC); blkid_probe_enable_superblocks(probe, 1); blkid_probe_set_superblocks_flags(probe, BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE | BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION | BLKID_SUBLKS_MAGIC | BLKID_SUBLKS_BADCSUM); while (!blkid_do_probe(probe)) { if ((r_wipe = _blkid_wipe(probe, dev, name, types_to_exclude, types_no_prompt, yes, force)) == 1) { (*wiped)++; if (blkid_probe_step_back(probe)) { log_error("Failed to step back blkid probe to check just wiped signature."); goto out; } } /* do not count excluded types */ if (r_wipe != 2) found++; } if (!found) r = 1; left = found - *wiped; if (!left) r = 1; else log_warn("%d existing signature%s left on the device.", left, left > 1 ? "s" : ""); out: if (probe) blkid_free_probe(probe); return r; }
static int check_partition_table(const char *device) { blkid_probe pr; const char *value; int ret; pr = blkid_new_probe_from_filename(device); if (!pr) return -1; ret = blkid_probe_enable_partitions(pr, 1); if (ret < 0) goto errout; ret = blkid_probe_enable_superblocks(pr, 0); if (ret < 0) goto errout; ret = blkid_do_fullprobe(pr); if (ret < 0) goto errout; ret = blkid_probe_lookup_value(pr, "PTTYPE", &value, NULL); if (ret == 0) fprintf(stderr, _("Found a %s partition table in %s\n"), value, device); else ret = 1; errout: blkid_free_probe(pr); return ret; }
static blkid_probe new_probe(const char *devname, int mode) { blkid_probe pr; if (!devname) return NULL; if (mode) { int fd = open(devname, mode); if (fd < 0) goto error; pr = blkid_new_probe(); if (pr && blkid_probe_set_device(pr, fd, 0, 0)) goto error; } else pr = blkid_new_probe_from_filename(devname); if (!pr) goto error; blkid_probe_enable_superblocks(pr, 1); blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC | BLKID_SUBLKS_TYPE | BLKID_SUBLKS_USAGE | BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID); blkid_probe_enable_partitions(pr, 1); blkid_probe_set_partitions_flags(pr, BLKID_PARTS_MAGIC); return pr; error: err(EXIT_FAILURE, _("error: %s: probing initialization failed"), devname); return NULL; }
/** * mnt_get_fstype: * @devname: device name * @ambi: returns TRUE if probing result is ambivalent (optional argument) * @cache: cache for results or NULL * * Returns: filesystem type or NULL in case of error. The result has to be * deallocated by free() if @cache is NULL. */ char *mnt_get_fstype(const char *devname, int *ambi, struct libmnt_cache *cache) { blkid_probe pr; const char *data; char *type = NULL; int rc; DBG(CACHE, mnt_debug_h(cache, "get %s FS type", devname)); if (cache) return mnt_cache_find_tag_value(cache, devname, "TYPE"); if (cache_get_probe(NULL, devname, &pr)) return NULL; blkid_probe_enable_superblocks(pr, 1); blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_TYPE); rc = blkid_do_safeprobe(pr); if (!rc && !blkid_probe_lookup_value(pr, "TYPE", &data, NULL)) type = strdup(data); if (ambi) *ambi = rc == -2 ? TRUE : FALSE; blkid_free_probe(pr); return type; }
static int probe_and_add_mount( const char *id, const char *what, const char *where, bool rw, const char *description, const char *post) { _cleanup_blkid_free_probe_ blkid_probe b = NULL; const char *fstype; int r; assert(id); assert(what); assert(where); assert(description); if (path_is_mount_point(where, true) <= 0 && dir_is_empty(where) <= 0) { log_debug("%s already populated, ignoring.", where); return 0; } /* Let's check the partition type here, so that we know * whether to do LUKS magic. */ errno = 0; b = blkid_new_probe_from_filename(what); if (!b) { if (errno == 0) return log_oom(); log_error_errno(errno, "Failed to allocate prober: %m"); return -errno; } blkid_probe_enable_superblocks(b, 1); blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE); errno = 0; r = blkid_do_safeprobe(b); if (r == -2 || r == 1) /* no result or uncertain */ return 0; else if (r != 0) { if (errno == 0) errno = EIO; log_error_errno(errno, "Failed to probe %s: %m", what); return -errno; } blkid_probe_lookup_value(b, "TYPE", &fstype, NULL); return add_mount( id, what, where, fstype, rw, description, post); }
/* returns device LABEL, UUID, FSTYPE, ... by low-level * probing interface */ static char * fsprobe_get_value(const char *name, const char *devname) { int fd; const char *data = NULL; if (!devname || !name) return NULL; fd = open_device(devname); if (fd < 0) return NULL; if (!blprobe) blprobe = blkid_new_probe(); if (!blprobe) goto done; if (blkid_probe_set_device(blprobe, fd, 0, 0)) goto done; blkid_probe_enable_superblocks(blprobe, 1); blkid_probe_set_superblocks_flags(blprobe, BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE); if (blkid_do_safeprobe(blprobe)) goto done; if (blkid_probe_lookup_value(blprobe, name, &data, NULL)) goto done; done: close(fd); return data ? strdup((char *) data) : NULL; }
static int lowprobe_topology(blkid_probe pr) { /* enable topology probing only */ blkid_probe_enable_topology(pr, 1); blkid_probe_enable_superblocks(pr, 0); blkid_probe_enable_partitions(pr, 0); return blkid_do_fullprobe(pr); }
static struct wipe_desc * read_offsets(struct wipe_desc *wp, const char *fname, int zap) { blkid_probe pr; int rc; if (!fname) return NULL; pr = blkid_new_probe_from_filename(fname); if (!pr) errx(EXIT_FAILURE, _("error: %s: probing initialization failed"), fname); blkid_probe_enable_superblocks(pr, 0); /* enabled by default ;-( */ blkid_probe_enable_partitions(pr, 1); rc = blkid_do_fullprobe(pr); blkid_probe_enable_partitions(pr, 0); if (rc == 0) { const char *type = NULL; blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL); warnx(_("WARNING: %s: appears to contain '%s' " "partition table"), fname, type); } blkid_probe_enable_superblocks(pr, 1); blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC | BLKID_SUBLKS_TYPE | BLKID_SUBLKS_USAGE | BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID); while (blkid_do_probe(pr) == 0) { wp = get_offset_from_probe(wp, pr, zap); if (!wp) break; } blkid_free_probe(pr); return wp; }
/* * This function prints a warning if the device is not wiped (e.g. wipefs(8). * Please don't call this function if there is already a PT. * * Returns: 0 if nothing found, < 0 on error, 1 if found a signature */ static int warn_wipe(struct fdisk_context *cxt) { #ifdef HAVE_LIBBLKID blkid_probe pr; #endif int rc = 0; assert(cxt); if (fdisk_dev_has_disklabel(cxt) || cxt->dev_fd < 0) return -EINVAL; #ifdef HAVE_LIBBLKID DBG(LABEL, dbgprint("wipe check: initialize libblkid prober")); pr = blkid_new_probe(); if (!pr) return -ENOMEM; rc = blkid_probe_set_device(pr, cxt->dev_fd, 0, 0); if (rc) return rc; blkid_probe_enable_superblocks(pr, 1); blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_TYPE); blkid_probe_enable_partitions(pr, 1); /* we care about the first found FS/raid, so don't call blkid_do_probe() * in loop or don't use blkid_do_fullprobe() ... */ rc = blkid_do_probe(pr); if (rc == 0) { const char *name = NULL; if (blkid_probe_lookup_value(pr, "TYPE", &name, 0) == 0 || blkid_probe_lookup_value(pr, "PTTYPE", &name, 0) == 0) { fdisk_warnx(cxt, _( "%s: device contains a valid '%s' signature, it's " "strongly recommended to wipe the device by command wipefs(8) " "if this setup is unexpected to avoid " "possible collisions."), cxt->dev_path, name); rc = 1; } } blkid_free_probe(pr); #endif return rc; }
static int probe_filesystem(const char *node, char **ret_fstype) { #ifdef HAVE_BLKID _cleanup_blkid_free_probe_ blkid_probe b = NULL; const char *fstype; int r; b = blkid_new_probe_from_filename(node); if (!b) return -ENOMEM; blkid_probe_enable_superblocks(b, 1); blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE); errno = 0; r = blkid_do_safeprobe(b); if (r == -2 || r == 1) { log_debug("Failed to identify any partition type on partition %s", node); goto not_found; } if (r != 0) { if (errno == 0) return -EIO; return -errno; } (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL); if (fstype) { char *t; t = strdup(fstype); if (!t) return -ENOMEM; *ret_fstype = t; return 1; } not_found: *ret_fstype = NULL; return 0; #else return -EOPNOTSUPP; #endif }
static lgfs2_rgrps_t rgrps_init(struct gfs2_sbd *sdp) { int ret; int error; uint64_t al_base = 0; uint64_t al_off = 0; struct stat st; blkid_probe pr = blkid_new_probe(); if (pr == NULL || blkid_probe_set_device(pr, sdp->device_fd, 0, 0) != 0 || blkid_probe_enable_superblocks(pr, TRUE) != 0 || blkid_probe_enable_partitions(pr, TRUE) != 0) { fprintf(stderr, _("Failed to create probe\n")); return NULL; } error = fstat(sdp->device_fd, &st); if (error < 0) { fprintf(stderr, _("fstat failed\n")); return NULL; } if (!S_ISREG(st.st_mode) && blkid_probe_enable_topology(pr, TRUE) != 0) { fprintf(stderr, _("Failed to create probe\n")); return NULL; } ret = blkid_do_fullprobe(pr); if (ret == 0 && !S_ISREG(st.st_mode)) { blkid_topology tp = blkid_probe_get_topology(pr); if (tp != NULL) { unsigned long min_io_sz = blkid_topology_get_minimum_io_size(tp); unsigned long opt_io_sz = blkid_topology_get_optimal_io_size(tp); unsigned long phy_sector_sz = blkid_topology_get_physical_sector_size(tp); if ((min_io_sz > phy_sector_sz) && (opt_io_sz > phy_sector_sz)) { al_base = opt_io_sz / sdp->bsize; al_off = min_io_sz / sdp->bsize; } } } blkid_free_probe(pr); return lgfs2_rgrps_init(sdp, al_base, al_off); }
static inline void probe_filesystem(struct format *target) { blkid_probe probe = 0; static char *filesystems[] = { "ext2", "ext3", "ext4", "reiserfs", "jfs", "xfs", "btrfs", "swap", 0 }; const char *filesystem = "unknown"; const char *result = 0; if((probe = blkid_new_probe_from_filename(target->devicepath)) == 0) goto bail; if(blkid_probe_enable_superblocks(probe,true) == -1) goto bail; if(blkid_probe_filter_superblocks_type(probe,BLKID_FLTR_ONLYIN,filesystems) == -1) goto bail; if(blkid_probe_set_superblocks_flags(probe,BLKID_SUBLKS_TYPE) == -1) goto bail; if(blkid_do_probe(probe) == -1) goto bail; if(blkid_probe_lookup_value(probe,"TYPE",&result,0) == -1) goto bail; filesystem = result; bail: if(probe != 0) blkid_free_probe(probe); target->filesystem = strdup(filesystem); }
static blkid_probe new_probe(const char *devname, int mode) { blkid_probe pr = NULL; if (!devname) return NULL; if (mode) { int fd = open(devname, mode); if (fd < 0) goto error; pr = blkid_new_probe(); if (pr && blkid_probe_set_device(pr, fd, 0, 0)) { close(fd); goto error; } } else pr = blkid_new_probe_from_filename(devname); if (!pr) goto error; blkid_probe_enable_superblocks(pr, 1); blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC | /* return magic string and offset */ BLKID_SUBLKS_TYPE | /* return superblock type */ BLKID_SUBLKS_USAGE | /* return USAGE= */ BLKID_SUBLKS_LABEL | /* return LABEL= */ BLKID_SUBLKS_UUID | /* return UUID= */ BLKID_SUBLKS_BADCSUM); /* accept bad checksums */ blkid_probe_enable_partitions(pr, 1); blkid_probe_set_partitions_flags(pr, BLKID_PARTS_MAGIC); return pr; error: blkid_free_probe(pr); err(EXIT_FAILURE, _("error: %s: probing initialization failed"), devname); return NULL; }
/* returns zero when the device has NAME=value (LABEL/UUID) */ static int verify_tag(const char *devname, const char *name, const char *value) { blkid_probe pr; int fd = -1, rc = -1; size_t len; const char *data; int errsv = 0; pr = blkid_new_probe(); if (!pr) return -1; blkid_probe_enable_superblocks(pr, TRUE); blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID); blkid_probe_enable_partitions(pr, TRUE); blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS); fd = open(devname, O_RDONLY|O_CLOEXEC); if (fd < 0) { errsv = errno; goto done; } if (blkid_probe_set_device(pr, fd, 0, 0)) goto done; rc = blkid_do_safeprobe(pr); if (rc) goto done; rc = blkid_probe_lookup_value(pr, name, &data, &len); if (!rc) rc = memcmp(value, data, len); done: DBG(EVALUATE, ul_debug("%s: %s verification %s", devname, name, rc == 0 ? "PASS" : "FAILED")); if (fd >= 0) close(fd); blkid_free_probe(pr); /* for non-root users we use unverified udev links */ return errsv == EACCES ? 0 : rc; }
/* * Returns new libblkid prober. This function call exit() on error. */ static blkid_probe get_swap_prober(const char *devname) { blkid_probe pr; int rc; const char *version = NULL; char *swap_filter[] = { "swap", NULL }; pr = blkid_new_probe_from_filename(devname); if (!pr) { warn(_("%s: unable to probe device"), devname); return NULL; } blkid_probe_enable_superblocks(pr, TRUE); blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_VERSION); blkid_probe_filter_superblocks_type(pr, BLKID_FLTR_ONLYIN, swap_filter); rc = blkid_do_safeprobe(pr); if (rc == -1) warn(_("%s: unable to probe device"), devname); else if (rc == -2) warnx(_("%s: ambivalent probing result, use wipefs(8)"), devname); else if (rc == 1) warnx(_("%s: not a valid swap partition"), devname); if (rc == 0) { /* supported is SWAPSPACE2 only */ if (blkid_probe_lookup_value(pr, "VERSION", &version, NULL) == 0 && version && strcmp(version, "2")) warnx(_("%s: unsupported swap version '%s'"), devname, version); else return pr; } blkid_free_probe(pr); return NULL; }
/* * This function prints a warning if the device is not wiped (e.g. wipefs(8). * Please don't call this function if there is already a PT. * * Returns: 0 if nothing found, < 0 on error, 1 if found a signature */ static int check_collisions(struct fdisk_context *cxt) { #ifdef HAVE_LIBBLKID int rc = 0; blkid_probe pr; assert(cxt); assert(cxt->dev_fd >= 0); DBG(CXT, ul_debugobj(cxt, "wipe check: initialize libblkid prober")); pr = blkid_new_probe(); if (!pr) return -ENOMEM; rc = blkid_probe_set_device(pr, cxt->dev_fd, 0, 0); if (rc) return rc; blkid_probe_enable_superblocks(pr, 1); blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_TYPE); blkid_probe_enable_partitions(pr, 1); /* we care about the first found FS/raid, so don't call blkid_do_probe() * in loop or don't use blkid_do_fullprobe() ... */ rc = blkid_do_probe(pr); if (rc == 0) { const char *name = NULL; if (blkid_probe_lookup_value(pr, "TYPE", &name, 0) == 0 || blkid_probe_lookup_value(pr, "PTTYPE", &name, 0) == 0) { cxt->collision = strdup(name); if (!cxt->collision) rc = -ENOMEM; } } blkid_free_probe(pr); return rc; #else return 0; #endif }
/** * mnt_get_fstype: * @devname: device name * @ambi: returns TRUE if probing result is ambivalent (optional argument) * @cache: cache for results or NULL * * Returns: filesystem type or NULL in case of error. The result has to be * deallocated by free() if @cache is NULL. */ char *mnt_get_fstype(const char *devname, int *ambi, struct libmnt_cache *cache) { blkid_probe pr; const char *data; char *type = NULL; int rc; DBG(CACHE, ul_debugobj(cache, "get %s FS type", devname)); if (cache) { char *val = NULL; rc = __mnt_cache_find_tag_value(cache, devname, "TYPE", &val); if (ambi) *ambi = rc == -2 ? TRUE : FALSE; return rc ? NULL : val; } /* * no cache, probe directly */ pr = blkid_new_probe_from_filename(devname); if (!pr) return NULL; blkid_probe_enable_superblocks(pr, 1); blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_TYPE); rc = blkid_do_safeprobe(pr); DBG(CACHE, ul_debugobj(cache, "libblkid rc=%d", rc)); if (!rc && !blkid_probe_lookup_value(pr, "TYPE", &data, NULL)) type = strdup(data); if (ambi) *ambi = rc == -2 ? TRUE : FALSE; blkid_free_probe(pr); return type; }
/** * mnt_cache_read_tags * @cache: pointer to struct libmnt_cache instance * @devname: path device * * Reads @devname LABEL and UUID to the @cache. * * Returns: 0 if at least one tag was added, 1 if no tag was added or * negative number in case of error. */ int mnt_cache_read_tags(struct libmnt_cache *cache, const char *devname) { blkid_probe pr; size_t i, ntags = 0; int rc; const char *tags[] = { "LABEL", "UUID", "TYPE", "PARTUUID", "PARTLABEL" }; const char *blktags[] = { "LABEL", "UUID", "TYPE", "PART_ENTRY_UUID", "PART_ENTRY_NAME" }; if (!cache || !devname) return -EINVAL; DBG(CACHE, ul_debugobj(cache, "tags for %s requested", devname)); /* check if device is already cached */ for (i = 0; i < cache->nents; i++) { struct mnt_cache_entry *e = &cache->ents[i]; if (!(e->flag & MNT_CACHE_TAGREAD)) continue; if (strcmp(e->value, devname) == 0) /* tags have already been read */ return 0; } pr = blkid_new_probe_from_filename(devname); if (!pr) return -1; blkid_probe_enable_superblocks(pr, 1); blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE); blkid_probe_enable_partitions(pr, 1); blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS); rc = blkid_do_safeprobe(pr); if (rc) goto error; DBG(CACHE, ul_debugobj(cache, "reading tags for: %s", devname)); for (i = 0; i < ARRAY_SIZE(tags); i++) { const char *data; char *dev; if (cache_find_tag_value(cache, devname, tags[i])) { DBG(CACHE, ul_debugobj(cache, "\ntag %s already cached", tags[i])); continue; } if (blkid_probe_lookup_value(pr, blktags[i], &data, NULL)) continue; dev = strdup(devname); if (!dev) goto error; if (cache_add_tag(cache, tags[i], data, dev, MNT_CACHE_TAGREAD)) { free(dev); goto error; } ntags++; } DBG(CACHE, ul_debugobj(cache, "\tread %zd tags", ntags)); blkid_free_probe(pr); return ntags ? 0 : 1; error: blkid_free_probe(pr); return rc < 0 ? rc : -1; }
/* * 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; }
int main(int argc, char *argv[]) { int rc; char *devname; blkid_probe pr; blkid_topology tp; if (argc < 2) { fprintf(stderr, "usage: %s <device> " "-- prints topology details about the device\n", program_invocation_short_name); return EXIT_FAILURE; } devname = argv[1]; pr = blkid_new_probe_from_filename(devname); if (!pr) err(EXIT_FAILURE, "%s: failed to create a new libblkid probe", devname); /* * Binary interface */ tp = blkid_probe_get_topology(pr); if (tp) { printf("----- binary interface:\n"); printf("\talignment offset : %lu\n", blkid_topology_get_alignment_offset(tp)); printf("\tminimum io size : %lu\n", blkid_topology_get_minimum_io_size(tp)); printf("\toptimal io size : %lu\n", blkid_topology_get_optimal_io_size(tp)); printf("\tlogical sector size : %lu\n", blkid_topology_get_logical_sector_size(tp)); printf("\tphysical sector size : %lu\n", blkid_topology_get_physical_sector_size(tp)); } /* * NAME=value interface */ /* enable topology probing */ blkid_probe_enable_topology(pr, TRUE); /* disable superblocks probing (enabled by default) */ blkid_probe_enable_superblocks(pr, FALSE); rc = blkid_do_fullprobe(pr); if (rc == -1) errx(EXIT_FAILURE, "%s: blkid_do_fullprobe() failed", devname); else if (rc == 1) warnx("%s: missing topology information", devname); else { int i, nvals = blkid_probe_numof_values(pr); printf("----- NAME=value interface (values: %d):\n", nvals); for (i = 0; i < nvals; i++) { const char *name, *data; blkid_probe_get_value(pr, i, &name, &data, NULL); printf("\t%s = %s\n", name, data); } } blkid_free_probe(pr); return EXIT_SUCCESS; }
static void zap_bootbits(int fd, const char *devname, int force, int is_blkdev) { char *type = NULL; int whole = 0; int zap = 1; if (!force) { if (lseek(fd, 0, SEEK_SET) != 0) die(_("unable to rewind swap-device")); if (is_blkdev && is_whole_disk_fd(fd, devname)) { /* don't zap bootbits on whole disk -- we know nothing * about bootloaders on the device */ whole = 1; zap = 0; } else { #ifdef HAVE_LIBBLKID_INTERNAL blkid_probe pr = blkid_new_probe(); if (!pr) die(_("unable to alloc new libblkid probe")); if (blkid_probe_set_device(pr, fd, 0, 0)) die(_("unable to assign device to libblkid probe")); blkid_probe_enable_partitions(pr, 1); blkid_probe_enable_superblocks(pr, 0); if (blkid_do_fullprobe(pr) == 0) blkid_probe_lookup_value(pr, "PTTYPE", (const char **) &type, NULL); if (type) { type = strdup(type); zap = 0; } blkid_free_probe(pr); #else /* don't zap if compiled without libblkid */ zap = 0; #endif } } if (zap) { char buf[1024]; if (lseek(fd, 0, SEEK_SET) != 0) die(_("unable to rewind swap-device")); memset(buf, 0, sizeof(buf)); if (write_all(fd, buf, sizeof(buf))) die(_("unable to erase bootbits sectors")); return; } fprintf(stderr, _("%s: %s: warning: don't erase bootbits sectors\n"), program_name, devname); if (type) fprintf(stderr, _(" (%s partition table detected). "), type); else if (whole) fprintf(stderr, _(" on whole disk. ")); else fprintf(stderr, _(" (compiled without libblkid). ")); fprintf(stderr, "Use -f to force.\n"); }
static void wipe_device(int fd, const char *devname, int force) { char *type = NULL; int zap = 1; #ifdef HAVE_LIBBLKID blkid_probe pr = NULL; #endif if (!force) { if (lseek(fd, 0, SEEK_SET) != 0) errx(EXIT_FAILURE, _("unable to rewind swap-device")); #ifdef HAVE_LIBBLKID pr = new_prober(fd); blkid_probe_enable_partitions(pr, 1); blkid_probe_enable_superblocks(pr, 0); if (blkid_do_fullprobe(pr) == 0 && blkid_probe_lookup_value(pr, "PTTYPE", (const char **) &type, NULL) == 0 && type) { type = xstrdup(type); zap = 0; } #else /* don't zap if compiled without libblkid */ zap = 0; #endif } if (zap) { /* * Wipe boodbits */ char buf[1024]; const char *data = NULL; if (lseek(fd, 0, SEEK_SET) != 0) errx(EXIT_FAILURE, _("unable to rewind swap-device")); memset(buf, 0, sizeof(buf)); if (write_all(fd, buf, sizeof(buf))) errx(EXIT_FAILURE, _("unable to erase bootbits sectors")); #ifdef HAVE_LIBBLKID /* * Wipe rest of the device */ if (!pr) pr = new_prober(fd); blkid_probe_enable_superblocks(pr, 1); blkid_probe_enable_partitions(pr, 0); blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC|BLKID_SUBLKS_TYPE); while (blkid_do_probe(pr) == 0) { if (blkid_probe_lookup_value(pr, "TYPE", &data, NULL) == 0 && data) warnx(_("%s: warning: wiping old %s signature."), devname, data); blkid_do_wipe(pr, 0); } #endif } else { warnx(_("%s: warning: don't erase bootbits sectors"), devname); if (type) fprintf(stderr, _(" (%s partition table detected). "), type); else fprintf(stderr, _(" (compiled without libblkid). ")); fprintf(stderr, _("Use -f to force.\n")); } #ifdef HAVE_LIBBLKID blkid_free_probe(pr); #endif }
static int enumerate_partitions(dev_t devnum) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; _cleanup_udev_device_unref_ struct udev_device *d = NULL; _cleanup_blkid_free_probe_ blkid_probe b = NULL; _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_free_ char *home = NULL, *srv = NULL; struct udev_list_entry *first, *item; struct udev_device *parent = NULL; const char *node, *pttype, *devtype; int home_nr = -1, srv_nr = -1; blkid_partlist pl; int r, k; dev_t pn; udev = udev_new(); if (!udev) return log_oom(); d = udev_device_new_from_devnum(udev, 'b', devnum); if (!d) return log_oom(); parent = udev_device_get_parent(d); if (!parent) return log_oom(); /* Does it have a devtype? */ devtype = udev_device_get_devtype(parent); if (!devtype) return 0; /* Is this a disk or a partition? We only care for disks... */ if (!streq(devtype, "disk")) return 0; /* Does it have a device node? */ node = udev_device_get_devnode(parent); if (!node) return 0; log_debug("Root device %s.", node); pn = udev_device_get_devnum(parent); if (major(pn) == 0) return 0; errno = 0; b = blkid_new_probe_from_filename(node); if (!b) { if (errno == 0) return log_oom(); log_error("Failed allocate prober: %m"); return -errno; } blkid_probe_enable_superblocks(b, 1); blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE); blkid_probe_enable_partitions(b, 1); blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); errno = 0; r = blkid_do_safeprobe(b); if (r == -2 || r == 1) /* no result or uncertain */ return 0; else if (r != 0) { if (errno == 0) errno = EIO; log_error("Failed to probe %s: %m", node); return -errno; } errno = 0; r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL); if (r != 0) { if (errno == 0) errno = EIO; log_error("Failed to determine partition table type of %s: %m", node); return -errno; } /* We only do this all for GPT... */ if (!streq_ptr(pttype, "gpt")) return 0; errno = 0; pl = blkid_probe_get_partitions(b); if (!pl) { if (errno == 0) return log_oom(); log_error("Failed to list partitions of %s: %m", node); return -errno; } e = udev_enumerate_new(udev); if (!e) return log_oom(); r = udev_enumerate_add_match_parent(e, parent); if (r < 0) return log_oom(); r = udev_enumerate_add_match_subsystem(e, "block"); if (r < 0) return log_oom(); r = udev_enumerate_scan_devices(e); if (r < 0) { log_error("Failed to enumerate partitions on %s: %s", node, strerror(-r)); return r; } first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *q; const char *stype, *subnode; sd_id128_t type_id; blkid_partition pp; dev_t qn; int nr; q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!q) continue; qn = udev_device_get_devnum(q); if (major(qn) == 0) continue; if (qn == devnum) continue; if (qn == pn) continue; subnode = udev_device_get_devnode(q); if (!subnode) continue; pp = blkid_partlist_devno_to_partition(pl, qn); if (!pp) continue; nr = blkid_partition_get_partno(pp); if (nr < 0) continue; stype = blkid_partition_get_type_string(pp); if (!stype) continue; if (sd_id128_from_string(stype, &type_id) < 0) continue; if (sd_id128_equal(type_id, GPT_SWAP)) { k = add_swap(subnode); if (k < 0) r = k; } else if (sd_id128_equal(type_id, GPT_HOME)) { /* We only care for the first /home partition */ if (home && nr >= home_nr) continue; home_nr = nr; free(home); home = strdup(subnode); if (!home) return log_oom(); } else if (sd_id128_equal(type_id, GPT_SRV)) { /* We only care for the first /srv partition */ if (srv && nr >= srv_nr) continue; srv_nr = nr; free(srv); srv = strdup(node); if (!srv) return log_oom(); } }
static int lxcContainerMountDetectFilesystem(const char *src, char **type) { int fd; int ret = -1; int rc; const char *data = NULL; blkid_probe blkid = NULL; *type = NULL; if ((fd = open(src, O_RDONLY)) < 0) { virReportSystemError(errno, _("Unable to open filesystem %s"), src); return -1; } if (!(blkid = blkid_new_probe())) { virReportSystemError(errno, "%s", _("Unable to create blkid library handle")); goto cleanup; } if (blkid_probe_set_device(blkid, fd, 0, 0) < 0) { virReportSystemError(EINVAL, _("Unable to associate device %s with blkid library"), src); goto cleanup; } blkid_probe_enable_superblocks(blkid, 1); blkid_probe_set_superblocks_flags(blkid, BLKID_SUBLKS_TYPE); rc = blkid_do_safeprobe(blkid); if (rc != 0) { if (rc == 1) /* Nothing found, return success with *type == NULL */ goto done; if (rc == -2) { virReportSystemError(EINVAL, _("Too many filesystems detected for %s"), src); } else { virReportSystemError(errno, _("Unable to detect filesystem for %s"), src); } goto cleanup; } if (blkid_probe_lookup_value(blkid, "TYPE", &data, NULL) < 0) { virReportSystemError(ENOENT, _("Unable to find filesystem type for %s"), src); goto cleanup; } if (!(*type = strdup(data))) { virReportOOMError(); goto cleanup; } done: ret = 0; cleanup: VIR_FORCE_CLOSE(fd); if (blkid) blkid_free_probe(blkid); return ret; }
/** * mnt_cache_read_tags * @cache: pointer to struct libmnt_cache instance * @devname: path device * * Reads @devname LABEL and UUID to the @cache. * * Returns: 0 if at least one tag was added, 1 if no tag was added or * negative number in case of error. */ int mnt_cache_read_tags(struct libmnt_cache *cache, const char *devname) { size_t i, ntags = 0; int rc; const char *tags[] = { "LABEL", "UUID", "TYPE" }; assert(cache); assert(devname); if (!cache || !devname) return -EINVAL; DBG(CACHE, mnt_debug_h(cache, "tags for %s requested", devname)); /* check is device is already cached */ for (i = 0; i < cache->nents; i++) { struct mnt_cache_entry *e = &cache->ents[i]; if (!(e->flag & MNT_CACHE_TAGREAD)) continue; if (strcmp(e->value, devname) == 0) /* tags has been already read */ return 0; } rc = cache_get_probe(cache, devname, NULL); if (rc) return rc; blkid_probe_enable_superblocks(cache->pr, 1); blkid_probe_set_superblocks_flags(cache->pr, BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE); if (blkid_do_safeprobe(cache->pr)) goto error; DBG(CACHE, mnt_debug_h(cache, "reading tags for: %s", devname)); for (i = 0; i < ARRAY_SIZE(tags); i++) { const char *data; char *dev; if (cache_find_tag_value(cache, devname, tags[i])) { DBG(CACHE, mnt_debug_h(cache, "\ntag %s already cached", tags[i])); continue; } if (blkid_probe_lookup_value(cache->pr, tags[i], &data, NULL)) continue; dev = strdup(devname); if (!dev) goto error; if (cache_add_tag(cache, tags[i], data, dev, MNT_CACHE_TAGREAD)) { free(dev); goto error; } ntags++; } DBG(CACHE, mnt_debug_h(cache, "\tread %zd tags", ntags)); return ntags ? 0 : 1; error: return -1; }
static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) { struct statfs sfs; struct stat st, st2; char *t; blkid_probe b = NULL; int r; const char *v; if (statfs(p, &sfs) < 0) { fprintf(stderr, "Failed to check file system type of %s: %m\n", p); return -errno; } if (sfs.f_type != 0x4d44) { fprintf(stderr, "File system %s is not a FAT EFI System Partition (ESP) file system.\n", p); return -ENODEV; } if (stat(p, &st) < 0) { fprintf(stderr, "Failed to determine block device node of %s: %m\n", p); return -errno; } if (major(st.st_dev) == 0) { fprintf(stderr, "Block device node of %p is invalid.\n", p); return -ENODEV; } r = asprintf(&t, "%s/..", p); if (r < 0) { fprintf(stderr, "Out of memory.\n"); return -ENOMEM; } r = stat(t, &st2); free(t); if (r < 0) { fprintf(stderr, "Failed to determine block device node of parent of %s: %m\n", p); return -errno; } if (st.st_dev == st2.st_dev) { fprintf(stderr, "Directory %s is not the root of the EFI System Partition (ESP) file system.\n", p); return -ENODEV; } r = asprintf(&t, "/dev/block/%u:%u", major(st.st_dev), minor(st.st_dev)); if (r < 0) { fprintf(stderr, "Out of memory.\n"); return -ENOMEM; } errno = 0; b = blkid_new_probe_from_filename(t); free(t); if (!b) { if (errno != 0) { fprintf(stderr, "Failed to open file system %s: %m\n", p); return -errno; } fprintf(stderr, "Out of memory.\n"); return -ENOMEM; } blkid_probe_enable_superblocks(b, 1); blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE); blkid_probe_enable_partitions(b, 1); blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); errno = 0; r = blkid_do_safeprobe(b); if (r == -2) { fprintf(stderr, "File system %s is ambigious.\n", p); r = -ENODEV; goto fail; } else if (r == 1) { fprintf(stderr, "File system %s does not contain a label.\n", p); r = -ENODEV; goto fail; } else if (r != 0) { r = errno ? -errno : -EIO; fprintf(stderr, "Failed to probe file system %s: %s\n", p, strerror(-r)); goto fail; } errno = 0; r = blkid_probe_lookup_value(b, "TYPE", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; fprintf(stderr, "Failed to probe file system type %s: %s\n", p, strerror(-r)); goto fail; } if (strcmp(v, "vfat") != 0) { fprintf(stderr, "File system %s is not a FAT EFI System Partition (ESP) file system after all.\n", p); r = -ENODEV; goto fail; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; fprintf(stderr, "Failed to probe partition scheme %s: %s\n", p, strerror(-r)); goto fail; } if (strcmp(v, "gpt") != 0) { fprintf(stderr, "File system %s is not on a GPT partition table.\n", p); r = -ENODEV; goto fail; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; fprintf(stderr, "Failed to probe partition type UUID %s: %s\n", p, strerror(-r)); goto fail; } if (strcmp(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b") != 0) { r = -ENODEV; fprintf(stderr, "File system %s is not an EFI System Partition (ESP).\n", p); goto fail; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; fprintf(stderr, "Failed to probe partition entry UUID %s: %s\n", p, strerror(-r)); goto fail; } r = sd_id128_from_string(v, uuid); if (r < 0) { fprintf(stderr, "Partition %s has invalid UUID: %s\n", p, v); r = -EIO; goto fail; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; fprintf(stderr, "Failed to probe partition number %s: %s\n", p, strerror(-r)); goto fail; } *part = strtoul(v, NULL, 10); errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; fprintf(stderr, "Failed to probe partition offset %s: %s\n", p, strerror(-r)); goto fail; } *pstart = strtoul(v, NULL, 10); errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_SIZE", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; fprintf(stderr, "Failed to probe partition size %s: %s\n", p, strerror(-r)); goto fail; } *psize = strtoul(v, NULL, 10); blkid_free_probe(b); return 0; fail: if (b) blkid_free_probe(b); return r; }
int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectedImage **ret) { #ifdef HAVE_BLKID sd_id128_t root_uuid = SD_ID128_NULL, verity_uuid = SD_ID128_NULL; _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; bool is_gpt, is_mbr, generic_rw, multiple_generic = false; _cleanup_udev_device_unref_ struct udev_device *d = NULL; _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; _cleanup_blkid_free_probe_ blkid_probe b = NULL; _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_free_ char *generic_node = NULL; const char *pttype = NULL, *usage = NULL; struct udev_list_entry *first, *item; blkid_partlist pl; int r, generic_nr; struct stat st; unsigned i; assert(fd >= 0); assert(ret); assert(root_hash || root_hash_size == 0); /* Probes a disk image, and returns information about what it found in *ret. * * Returns -ENOPKG if no suitable partition table or file system could be found. * Returns -EADDRNOTAVAIL if a root hash was specified but no matching root/verity partitions found. */ if (root_hash) { /* If a root hash is supplied, then we use the root partition that has a UUID that match the first * 128bit of the root hash. And we use the verity partition that has a UUID that match the final * 128bit. */ if (root_hash_size < sizeof(sd_id128_t)) return -EINVAL; memcpy(&root_uuid, root_hash, sizeof(sd_id128_t)); memcpy(&verity_uuid, (const uint8_t*) root_hash + root_hash_size - sizeof(sd_id128_t), sizeof(sd_id128_t)); if (sd_id128_is_null(root_uuid)) return -EINVAL; if (sd_id128_is_null(verity_uuid)) return -EINVAL; } if (fstat(fd, &st) < 0) return -errno; if (!S_ISBLK(st.st_mode)) return -ENOTBLK; b = blkid_new_probe(); if (!b) return -ENOMEM; errno = 0; r = blkid_probe_set_device(b, fd, 0, 0); if (r != 0) { if (errno == 0) return -ENOMEM; return -errno; } blkid_probe_enable_superblocks(b, 1); blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE|BLKID_SUBLKS_USAGE); blkid_probe_enable_partitions(b, 1); blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); errno = 0; r = blkid_do_safeprobe(b); if (r == -2 || r == 1) { log_debug("Failed to identify any partition table."); return -ENOPKG; } if (r != 0) { if (errno == 0) return -EIO; return -errno; } m = new0(DissectedImage, 1); if (!m) return -ENOMEM; (void) blkid_probe_lookup_value(b, "USAGE", &usage, NULL); if (STRPTR_IN_SET(usage, "filesystem", "crypto")) { _cleanup_free_ char *t = NULL, *n = NULL; const char *fstype = NULL; /* OK, we have found a file system, that's our root partition then. */ (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL); if (fstype) { t = strdup(fstype); if (!t) return -ENOMEM; } if (asprintf(&n, "/dev/block/%u:%u", major(st.st_rdev), minor(st.st_rdev)) < 0) return -ENOMEM; m->partitions[PARTITION_ROOT] = (DissectedPartition) { .found = true, .rw = true, .partno = -1, .architecture = _ARCHITECTURE_INVALID, .fstype = t, .node = n, }; t = n = NULL; m->encrypted = streq(fstype, "crypto_LUKS"); *ret = m; m = NULL; return 0; } (void) blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL); if (!pttype) return -ENOPKG; is_gpt = streq_ptr(pttype, "gpt"); is_mbr = streq_ptr(pttype, "dos"); if (!is_gpt && !is_mbr) return -ENOPKG; errno = 0; pl = blkid_probe_get_partitions(b); if (!pl) { if (errno == 0) return -ENOMEM; return -errno; } udev = udev_new(); if (!udev) return -errno; d = udev_device_new_from_devnum(udev, 'b', st.st_rdev); if (!d) return -ENOMEM; for (i = 0;; i++) { int n, z; if (i >= 10) { log_debug("Kernel partitions never appeared."); return -ENXIO; } e = udev_enumerate_new(udev); if (!e) return -errno; r = udev_enumerate_add_match_parent(e, d); if (r < 0) return r; r = udev_enumerate_scan_devices(e); if (r < 0) return r; /* Count the partitions enumerated by the kernel */ n = 0; first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) n++; /* Count the partitions enumerated by blkid */ z = blkid_partlist_numof_partitions(pl); if (n == z + 1) break; if (n > z + 1) { log_debug("blkid and kernel partition list do not match."); return -EIO; } if (n < z + 1) { unsigned j; /* The kernel has probed fewer partitions than blkid? Maybe the kernel prober is still running * or it got EBUSY because udev already opened the device. Let's reprobe the device, which is a * synchronous call that waits until probing is complete. */ for (j = 0; j < 20; j++) { r = ioctl(fd, BLKRRPART, 0); if (r < 0) r = -errno; if (r >= 0 || r != -EBUSY) break; /* If something else has the device open, such as an udev rule, the ioctl will return * EBUSY. Since there's no way to wait until it isn't busy anymore, let's just wait a * bit, and try again. * * This is really something they should fix in the kernel! */ usleep(50 * USEC_PER_MSEC); } if (r < 0) return r; } e = udev_enumerate_unref(e); } first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *q; unsigned long long flags; blkid_partition pp; const char *node; dev_t qn; int nr; q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!q) return -errno; qn = udev_device_get_devnum(q); if (major(qn) == 0) continue; if (st.st_rdev == qn) continue; node = udev_device_get_devnode(q); if (!node) continue; pp = blkid_partlist_devno_to_partition(pl, qn); if (!pp) continue; flags = blkid_partition_get_flags(pp); nr = blkid_partition_get_partno(pp); if (nr < 0) continue; if (is_gpt) { int designator = _PARTITION_DESIGNATOR_INVALID, architecture = _ARCHITECTURE_INVALID; const char *stype, *sid, *fstype = NULL; sd_id128_t type_id, id; bool rw = true; if (flags & GPT_FLAG_NO_AUTO) continue; sid = blkid_partition_get_uuid(pp); if (!sid) continue; if (sd_id128_from_string(sid, &id) < 0) continue; stype = blkid_partition_get_type_string(pp); if (!stype) continue; if (sd_id128_from_string(stype, &type_id) < 0) continue; if (sd_id128_equal(type_id, GPT_HOME)) { designator = PARTITION_HOME; rw = !(flags & GPT_FLAG_READ_ONLY); } else if (sd_id128_equal(type_id, GPT_SRV)) { designator = PARTITION_SRV; rw = !(flags & GPT_FLAG_READ_ONLY); } else if (sd_id128_equal(type_id, GPT_ESP)) { designator = PARTITION_ESP; fstype = "vfat"; } #ifdef GPT_ROOT_NATIVE else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE)) { /* If a root ID is specified, ignore everything but the root id */ if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id)) continue; designator = PARTITION_ROOT; architecture = native_architecture(); rw = !(flags & GPT_FLAG_READ_ONLY); } else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE_VERITY)) { m->can_verity = true; /* Ignore verity unless a root hash is specified */ if (sd_id128_is_null(verity_uuid) || !sd_id128_equal(verity_uuid, id)) continue; designator = PARTITION_ROOT_VERITY; fstype = "DM_verity_hash"; architecture = native_architecture(); rw = false; } #endif #ifdef GPT_ROOT_SECONDARY else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY)) { /* If a root ID is specified, ignore everything but the root id */ if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id)) continue; designator = PARTITION_ROOT_SECONDARY; architecture = SECONDARY_ARCHITECTURE; rw = !(flags & GPT_FLAG_READ_ONLY); } else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY_VERITY)) { m->can_verity = true; /* Ignore verity unless root has is specified */ if (sd_id128_is_null(verity_uuid) || !sd_id128_equal(verity_uuid, id)) continue; designator = PARTITION_ROOT_SECONDARY_VERITY; fstype = "DM_verity_hash"; architecture = SECONDARY_ARCHITECTURE; rw = false; } #endif else if (sd_id128_equal(type_id, GPT_SWAP)) { designator = PARTITION_SWAP; fstype = "swap"; } else if (sd_id128_equal(type_id, GPT_LINUX_GENERIC)) { if (generic_node) multiple_generic = true; else { generic_nr = nr; generic_rw = !(flags & GPT_FLAG_READ_ONLY); generic_node = strdup(node); if (!generic_node) return -ENOMEM; } } if (designator != _PARTITION_DESIGNATOR_INVALID) { _cleanup_free_ char *t = NULL, *n = NULL; /* First one wins */ if (m->partitions[designator].found) continue; if (fstype) { t = strdup(fstype); if (!t) return -ENOMEM; } n = strdup(node); if (!n) return -ENOMEM; m->partitions[designator] = (DissectedPartition) { .found = true, .partno = nr, .rw = rw, .architecture = architecture, .node = n, .fstype = t, }; n = t = NULL; } } else if (is_mbr) {
static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) { struct statfs sfs; struct stat st, st2; _cleanup_free_ char *t = NULL; _cleanup_blkid_free_probe_ blkid_probe b = NULL; int r; const char *v, *t2; if (statfs(p, &sfs) < 0) return log_error_errno(errno, "Failed to check file system type of \"%s\": %m", p); if (sfs.f_type != 0x4d44) { log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p); return -ENODEV; } if (stat(p, &st) < 0) return log_error_errno(errno, "Failed to determine block device node of \"%s\": %m", p); if (major(st.st_dev) == 0) { log_error("Block device node of %p is invalid.", p); return -ENODEV; } t2 = strjoina(p, "/.."); r = stat(t2, &st2); if (r < 0) return log_error_errno(errno, "Failed to determine block device node of parent of \"%s\": %m", p); if (st.st_dev == st2.st_dev) { log_error("Directory \"%s\" is not the root of the EFI System Partition (ESP) file system.", p); return -ENODEV; } r = asprintf(&t, "/dev/block/%u:%u", major(st.st_dev), minor(st.st_dev)); if (r < 0) return log_oom(); errno = 0; b = blkid_new_probe_from_filename(t); if (!b) { if (errno == 0) return log_oom(); return log_error_errno(errno, "Failed to open file system \"%s\": %m", p); } blkid_probe_enable_superblocks(b, 1); blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE); blkid_probe_enable_partitions(b, 1); blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); errno = 0; r = blkid_do_safeprobe(b); if (r == -2) { log_error("File system \"%s\" is ambiguous.", p); return -ENODEV; } else if (r == 1) { log_error("File system \"%s\" does not contain a label.", p); return -ENODEV; } else if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe file system \"%s\": %m", p); } errno = 0; r = blkid_probe_lookup_value(b, "TYPE", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe file system type \"%s\": %m", p); } if (!streq(v, "vfat")) { log_error("File system \"%s\" is not FAT.", p); return -ENODEV; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition scheme \"%s\": %m", p); } if (!streq(v, "gpt")) { log_error("File system \"%s\" is not on a GPT partition table.", p); return -ENODEV; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition type UUID \"%s\": %m", p); } if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) { log_error("File system \"%s\" has wrong type for an EFI System Partition (ESP).", p); return -ENODEV; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition entry UUID \"%s\": %m", p); } r = sd_id128_from_string(v, uuid); if (r < 0) { log_error("Partition \"%s\" has invalid UUID \"%s\".", p, v); return -EIO; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition number \"%s\": m", p); } *part = strtoul(v, NULL, 10); errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition offset \"%s\": %m", p); } *pstart = strtoul(v, NULL, 10); errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_SIZE", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition size \"%s\": %m", p); } *psize = strtoul(v, NULL, 10); return 0; }
static int lowprobe_device(blkid_probe pr, const char *devname, char *show[], int output, blkid_loff_t offset, blkid_loff_t size) { const char *data; const char *name; int nvals = 0, n, num = 1; size_t len; int fd; int rc = 0; struct stat st; fd = open(devname, O_RDONLY); if (fd < 0) { fprintf(stderr, "error: %s: %s\n", devname, strerror(errno)); return 2; } if (blkid_probe_set_device(pr, fd, offset, size)) goto done; if (fstat(fd, &st)) goto done; /* * partitions probing */ blkid_probe_enable_superblocks(pr, 0); /* enabled by default ;-( */ blkid_probe_enable_partitions(pr, 1); rc = blkid_do_fullprobe(pr); blkid_probe_enable_partitions(pr, 0); if (rc < 0) goto done; /* -1 = error, 1 = nothing, 0 = succes */ /* * Don't probe for FS/RAIDs on small devices */ if (rc || S_ISCHR(st.st_mode) || blkid_probe_get_size(pr) > 1024 * 1440) { /* * filesystems/RAIDs probing */ blkid_probe_enable_superblocks(pr, 1); rc = blkid_do_safeprobe(pr); if (rc < 0) goto done; } nvals = blkid_probe_numof_values(pr); if (output & OUTPUT_DEVICE_ONLY) { printf("%s\n", devname); goto done; } for (n = 0; n < nvals; n++) { if (blkid_probe_get_value(pr, n, &name, &data, &len)) continue; if (show[0] && !has_item(show, name)) continue; len = strnlen((char *) data, len); print_value(output, num++, devname, (char *) data, name, len); } if (nvals >= 1 && !(output & (OUTPUT_VALUE_ONLY | OUTPUT_UDEV_LIST))) printf("\n"); done: if (rc == -2) { if (output & OUTPUT_UDEV_LIST) print_udev_ambivalent(pr); else fprintf(stderr, "%s: ambivalent result (probably more " "filesystems on the device, use wipefs(8) " "to see more details)\n", devname); } close(fd); return !nvals ? 2 : 0; }