static char* get_blkid(char *device) { int fd; blkid_probe pr = NULL; uint64_t size; const char *label; char *ret; char path[PATH_MAX]; if(!device || !strlen(device)) return NULL; snprintf(path, PATH_MAX, "/dev/%s", device); fd = open(path, O_RDONLY); if(fd<0) return NULL; pr = blkid_new_probe (); blkid_probe_set_request (pr, BLKID_PROBREQ_LABEL); ioctl(fd, BLKGETSIZE64, &size); blkid_probe_set_device (pr, fd, 0, size); blkid_do_safeprobe (pr); blkid_probe_lookup_value(pr, "LABEL", &label, NULL); ret = strdup(label); blkid_free_probe (pr); close(fd); return ret; }
/* 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 char* get_uuid(char *device) { char path[PATH_MAX]; int fd; blkid_probe pr = NULL; uint64_t size; const char *uuid; char *ret; if(!device || !strlen(device)) return NULL; fd = open(device, O_RDONLY); if (fd < 0) return NULL; pr = blkid_new_probe(); blkid_probe_set_request (pr, BLKID_PROBREQ_UUID); ioctl(fd, BLKGETSIZE64, &size); blkid_probe_set_device(pr, fd, 0, size); blkid_do_safeprobe(pr); blkid_probe_lookup_value(pr, "UUID", &uuid, NULL); snprintf(path, PATH_MAX, "/dev/disk/by-uuid/%s", uuid); ret = strdup(path); blkid_free_probe(pr); close(fd); 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; }
static blkid_probe new_prober(const struct mkswap_control *ctl) { blkid_probe pr = blkid_new_probe(); if (!pr) errx(EXIT_FAILURE, _("unable to alloc new libblkid probe")); if (blkid_probe_set_device(pr, ctl->fd, 0, 0)) errx(EXIT_FAILURE, _("unable to assign device to libblkid probe")); return pr; }
static blkid_probe new_prober(int fd) { blkid_probe pr = blkid_new_probe(); if (!pr) errx(EXIT_FAILURE, _("unable to alloc new libblkid probe")); if (blkid_probe_set_device(pr, fd, 0, 0)) errx(EXIT_FAILURE, _("unable to assign device to libblkid probe")); return pr; }
int get_device_info(int fd, struct device_info *info) { blkid_probe probe; struct stat stat; int ret; *info = device_info_clueless; ret = fstat(fd, &stat); if (ret < 0) { perror("fstat on target failed"); return -1; } if (S_ISREG(stat.st_mode)) { /* there is nothing more to discover for an image file */ info->type = TYPE_FILE; info->partition = 0; info->size = stat.st_size; return 0; } if (!S_ISBLK(stat.st_mode)) { /* neither regular file nor block device? not usable */ info->type = TYPE_BAD; return 0; } probe = blkid_new_probe(); if (!probe) { return -1; } if (blkid_probe_set_device(probe, fd, 0, 0)) { blkid_free_probe(probe); return -1; } get_block_device_size(info, fd); get_block_geometry(info, fd); info->sector_size = blkid_probe_get_sectorsize(probe); /* use udev information if available, fall back to blkid probing */ if (udev_fill_info(info, &stat)) blkid_fill_info(info, probe); blkid_free_probe(probe); return 0; }
/* * 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 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 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; }
/* * 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 }
/* 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; }
/* * 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; }
static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool test) { const char *root_partition; int64_t offset = 0; bool noraid = false; _cleanup_close_ int fd = -1; blkid_probe pr; const char *data; const char *name; int nvals; int i; int err = 0; bool is_gpt = false; static const struct option options[] = { { "offset", optional_argument, NULL, 'o' }, { "noraid", no_argument, NULL, 'R' }, {} }; for (;;) { int option; option = getopt_long(argc, argv, "oR", options, NULL); if (option == -1) break; switch (option) { case 'o': offset = strtoull(optarg, NULL, 0); break; case 'R': noraid = true; break; } } pr = blkid_new_probe(); if (!pr) return EXIT_FAILURE; blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE | BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION); if (noraid) blkid_probe_filter_superblocks_usage(pr, BLKID_FLTR_NOTIN, BLKID_USAGE_RAID); fd = open(udev_device_get_devnode(dev), O_RDONLY|O_CLOEXEC); if (fd < 0) { fprintf(stderr, "error: %s: %m\n", udev_device_get_devnode(dev)); goto out; } err = blkid_probe_set_device(pr, fd, offset, 0); if (err < 0) goto out; log_debug("probe %s %sraid offset=%llu", udev_device_get_devnode(dev), noraid ? "no" : "", (unsigned long long) offset); err = probe_superblocks(pr); if (err < 0) goto out; /* If we are a partition then our parent passed on the root * partition UUID to us */ root_partition = udev_device_get_property_value(dev, "ID_PART_GPT_AUTO_ROOT_UUID"); nvals = blkid_probe_numof_values(pr); for (i = 0; i < nvals; i++) { if (blkid_probe_get_value(pr, i, &name, &data, NULL)) continue; print_property(dev, test, name, data); /* Is this a disk with GPT partition table? */ if (streq(name, "PTTYPE") && streq(data, "gpt")) is_gpt = true; /* Is this a partition that matches the root partition * property we inherited from our parent? */ if (root_partition && streq(name, "PART_ENTRY_UUID") && streq(data, root_partition)) udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT", "1"); } if (is_gpt) find_gpt_root(dev, pr, test); blkid_free_probe(pr); out: if (err < 0) return EXIT_FAILURE; return EXIT_SUCCESS; }
static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool test) { int64_t offset = 0; bool noraid = false; int fd = -1; blkid_probe pr; const char *data; const char *name; int nvals; int i; size_t len; int err = 0; static const struct option options[] = { { "offset", optional_argument, NULL, 'o' }, { "noraid", no_argument, NULL, 'R' }, {} }; for (;;) { int option; option = getopt_long(argc, argv, "oR", options, NULL); if (option == -1) break; switch (option) { case 'o': offset = strtoull(optarg, NULL, 0); break; case 'R': noraid = true; break; } } pr = blkid_new_probe(); if (!pr) return EXIT_FAILURE; blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE | BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION); if (noraid) blkid_probe_filter_superblocks_usage(pr, BLKID_FLTR_NOTIN, BLKID_USAGE_RAID); fd = open(udev_device_get_devnode(dev), O_RDONLY|O_CLOEXEC); if (fd < 0) { fprintf(stderr, "error: %s: %m\n", udev_device_get_devnode(dev)); goto out; } err = blkid_probe_set_device(pr, fd, offset, 0); if (err < 0) goto out; log_debug("probe %s %sraid offset=%llu\n", udev_device_get_devnode(dev), noraid ? "no" : "", (unsigned long long) offset); err = probe_superblocks(pr); if (err < 0) goto out; nvals = blkid_probe_numof_values(pr); for (i = 0; i < nvals; i++) { if (blkid_probe_get_value(pr, i, &name, &data, &len)) continue; len = strnlen((char *) data, len); print_property(dev, test, name, (char *) data); } blkid_free_probe(pr); out: if (fd > 0) close(fd); if (err < 0) return EXIT_FAILURE; return EXIT_SUCCESS; }
static int lowprobe_device(blkid_probe pr, const char *devname, int chain, 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; static int first = 1; 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 (chain & LOWPROBE_TOPOLOGY) rc = lowprobe_topology(pr); if (rc >= 0 && (chain & LOWPROBE_SUPERBLOCKS)) rc = lowprobe_superblocks(pr); if (rc < 0) goto done; nvals = blkid_probe_numof_values(pr); if (nvals && !first && output & (OUTPUT_UDEV_LIST | OUTPUT_EXPORT_LIST)) /* add extra line between output from devices */ fputc('\n', stdout); 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 (first) first = 0; if (nvals >= 1 && !(output & (OUTPUT_VALUE_ONLY | OUTPUT_UDEV_LIST | OUTPUT_EXPORT_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; }
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 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; }
int main(int argc, char **argv) { bool udev = false; int i, o; extern char *optarg; struct cache_sb sb; char uuid[40]; blkid_probe pr; while ((o = getopt(argc, argv, "o:")) != EOF) switch (o) { case 'o': if (strcmp("udev", optarg)) { printf("Invalid output format %s\n", optarg); exit(EXIT_FAILURE); } udev = true; break; } argv += optind; argc -= optind; for (i = 0; i < argc; i++) { int fd = open(argv[i], O_RDONLY); if (fd == -1) continue; if (!(pr = blkid_new_probe())) continue; if (blkid_probe_set_device(pr, fd, 0, 0)) continue; /* probe partitions too */ if (blkid_probe_enable_partitions(pr, true)) continue; /* bail if anything was found * probe-bcache isn't needed once blkid recognizes bcache */ if (!blkid_do_probe(pr)) { continue; } if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) continue; if (memcmp(sb.magic, bcache_magic, 16)) continue; uuid_unparse(sb.uuid, uuid); if (udev) printf("ID_FS_UUID=%s\n" "ID_FS_UUID_ENC=%s\n" "ID_FS_TYPE=bcache\n", uuid, uuid); else printf("%s: UUID=\"\" TYPE=\"bcache\"\n", uuid); } return 0; }
static void write_sb(char *dev, unsigned block_size, unsigned bucket_size, bool writeback, bool discard, bool wipe_bcache, unsigned cache_replacement_policy, uint64_t data_offset, uuid_t set_uuid, bool bdev) { int fd; char uuid_str[40], set_uuid_str[40], zeroes[SB_START] = {0}; struct cache_sb sb; blkid_probe pr; if ((fd = open(dev, O_RDWR|O_EXCL)) == -1) { fprintf(stderr, "Can't open dev %s: %s\n", dev, strerror(errno)); exit(EXIT_FAILURE); } if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) exit(EXIT_FAILURE); if (!memcmp(sb.magic, bcache_magic, 16) && !wipe_bcache) { fprintf(stderr, "Already a bcache device on %s, " "overwrite with --wipe-bcache\n", dev); exit(EXIT_FAILURE); } if (!(pr = blkid_new_probe())) exit(EXIT_FAILURE); if (blkid_probe_set_device(pr, fd, 0, 0)) exit(EXIT_FAILURE); /* enable ptable probing; superblock probing is enabled by default */ if (blkid_probe_enable_partitions(pr, true)) exit(EXIT_FAILURE); if (!blkid_do_probe(pr)) { /* XXX wipefs doesn't know how to remove partition tables */ fprintf(stderr, "Device %s already has a non-bcache superblock, " "remove it using wipefs and wipefs -a\n", dev); exit(EXIT_FAILURE); } memset(&sb, 0, sizeof(struct cache_sb)); sb.offset = SB_SECTOR; sb.version = bdev ? BCACHE_SB_VERSION_BDEV : BCACHE_SB_VERSION_CDEV; memcpy(sb.magic, bcache_magic, 16); uuid_generate(sb.uuid); memcpy(sb.set_uuid, set_uuid, sizeof(sb.set_uuid)); sb.bucket_size = bucket_size; sb.block_size = block_size; uuid_unparse(sb.uuid, uuid_str); uuid_unparse(sb.set_uuid, set_uuid_str); if (SB_IS_BDEV(&sb)) { SET_BDEV_CACHE_MODE( &sb, writeback ? CACHE_MODE_WRITEBACK : CACHE_MODE_WRITETHROUGH); if (data_offset != BDEV_DATA_START_DEFAULT) { sb.version = BCACHE_SB_VERSION_BDEV_WITH_OFFSET; sb.data_offset = data_offset; } printf("UUID: %s\n" "Set UUID: %s\n" "version: %u\n" "block_size: %u\n" "data_offset: %ju\n", uuid_str, set_uuid_str, (unsigned) sb.version, sb.block_size, data_offset); } else { sb.nbuckets = getblocks(fd) / sb.bucket_size; sb.nr_in_set = 1; sb.first_bucket = (23 / sb.bucket_size) + 1; if (sb.nbuckets < 1 << 7) { fprintf(stderr, "Not enough buckets: %ju, need %u\n", sb.nbuckets, 1 << 7); exit(EXIT_FAILURE); } SET_CACHE_DISCARD(&sb, discard); SET_CACHE_REPLACEMENT(&sb, cache_replacement_policy); printf("UUID: %s\n" "Set UUID: %s\n" "version: %u\n" "nbuckets: %ju\n" "block_size: %u\n" "bucket_size: %u\n" "nr_in_set: %u\n" "nr_this_dev: %u\n" "first_bucket: %u\n", uuid_str, set_uuid_str, (unsigned) sb.version, sb.nbuckets, sb.block_size, sb.bucket_size, sb.nr_in_set, sb.nr_this_dev, sb.first_bucket); } sb.csum = csum_set(&sb); /* Zero start of disk */ if (pwrite(fd, zeroes, SB_START, 0) != SB_START) { perror("write error\n"); exit(EXIT_FAILURE); } /* Write superblock */ if (pwrite(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) { perror("write error\n"); exit(EXIT_FAILURE); } fsync(fd); close(fd); }
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; }
static int lowprobe_device(blkid_probe pr, const char *devname, int chain, 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; static int first = 1; fd = open(devname, O_RDONLY); if (fd < 0) { fprintf(stderr, "error: %s: %m\n", devname); return 2; } if (blkid_probe_set_device(pr, fd, offset, size)) goto done; if (chain & LOWPROBE_TOPOLOGY) rc = lowprobe_topology(pr); if (rc >= 0 && (chain & LOWPROBE_SUPERBLOCKS)) rc = lowprobe_superblocks(pr); if (rc < 0) goto done; if (!rc) nvals = blkid_probe_numof_values(pr); if (nvals && !(chain & LOWPROBE_TOPOLOGY) && !(output & OUTPUT_UDEV_LIST) && !blkid_probe_has_value(pr, "TYPE") && !blkid_probe_has_value(pr, "PTTYPE")) /* * Ignore probing result if there is not any filesystem or * partition table on the device and udev output is not * requested. * * The udev db stores information about partitions, so * PART_ENTRY_* values are alway important. */ nvals = 0; if (nvals && !first && output & (OUTPUT_UDEV_LIST | OUTPUT_EXPORT_LIST)) /* add extra line between output from devices */ fputc('\n', stdout); if (nvals && (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 (first) first = 0; if (nvals >= 1 && !(output & (OUTPUT_VALUE_ONLY | OUTPUT_UDEV_LIST | OUTPUT_EXPORT_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); if (rc == -2) return 8; /* ambivalent probing result */ if (!nvals) return 2; /* nothing detected */ return 0; /* sucess */ }
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) {