Ejemplo n.º 1
0
/* 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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
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);
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
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 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
}
Ejemplo n.º 12
0
/* 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;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
int main(int argc, char **argv)
{
	blkid_cache cache = NULL;
	char *devices[128] = { NULL, };
	char *show[128] = { NULL, };
	char *search_type = NULL, *search_value = NULL;
	char *read = NULL;
	char *write = NULL;
	int fltr_usage = 0;
	char **fltr_type = NULL;
	int fltr_flag = BLKID_FLTR_ONLYIN;
	unsigned int numdev = 0, numtag = 0;
	int version = 0;
	int err = 4;
	unsigned int i;
	int output_format = 0;
	int lookup = 0, gc = 0, lowprobe = 0, eval = 0;
	int c;
	uintmax_t offset = 0, size = 0;

	show[0] = NULL;

	while ((c = getopt (argc, argv, "c:f:ghilL:n:o:O:ps:S:t:u:U:w:v")) != EOF)
		switch (c) {
		case 'c':
			if (optarg && !*optarg)
				read = NULL;
			else
				read = optarg;
			if (!write)
				write = read;
			break;
		case 'L':
			eval++;
			search_value = strdup(optarg);
			search_type = strdup("LABEL");
			break;
		case 'n':
			if (fltr_usage) {
				fprintf(stderr, "error: -u and -n options are mutually exclusive\n");
				exit(4);
			}
			fltr_type = list_to_types(optarg, &fltr_flag);
			break;
		case 'u':
			if (fltr_type) {
				fprintf(stderr, "error: -u and -n options are mutually exclusive\n");
				exit(4);
			}
			fltr_usage = list_to_usage(optarg, &fltr_flag);
			break;
		case 'U':
			eval++;
			search_value = strdup(optarg);
			search_type = strdup("UUID");
			break;
		case 'i':
			lowprobe |= LOWPROBE_TOPOLOGY;
			break;
		case 'l':
			lookup++;
			break;
		case 'g':
			gc = 1;
			break;
		case 'o':
			if (!strcmp(optarg, "value"))
				output_format = OUTPUT_VALUE_ONLY;
			else if (!strcmp(optarg, "device"))
				output_format = OUTPUT_DEVICE_ONLY;
			else if (!strcmp(optarg, "list"))
				output_format = OUTPUT_PRETTY_LIST;
			else if (!strcmp(optarg, "udev"))
				output_format = OUTPUT_UDEV_LIST;
			else if (!strcmp(optarg, "export"))
				output_format = OUTPUT_EXPORT_LIST;
			else if (!strcmp(optarg, "full"))
				output_format = 0;
			else {
				fprintf(stderr, "Invalid output format %s. "
					"Choose from value,\n\t"
					"device, list, udev or full\n", optarg);
				exit(4);
			}
			break;
		case 'O':
			if (strtosize(optarg, &offset))
				fprintf(stderr,
					"Invalid offset '%s' specified\n",
					optarg);
			break;
		case 'p':
			lowprobe |= LOWPROBE_SUPERBLOCKS;
			break;
		case 's':
			if (numtag + 1 >= sizeof(show) / sizeof(*show)) {
				fprintf(stderr, "Too many tags specified\n");
				usage(err);
			}
			show[numtag++] = optarg;
			show[numtag] = NULL;
			break;
		case 'S':
			if (strtosize(optarg, &size))
				fprintf(stderr,
					"Invalid size '%s' specified\n",
					optarg);
			break;
		case 't':
			if (search_type) {
				fprintf(stderr, "Can only search for "
						"one NAME=value pair\n");
				usage(err);
			}
			if (blkid_parse_tag_string(optarg,
						   &search_type,
						   &search_value)) {
				fprintf(stderr, "-t needs NAME=value pair\n");
				usage(err);
			}
			break;
		case 'v':
			version = 1;
			break;
		case 'w':
			if (optarg && !*optarg)
				write = NULL;
			else
				write = optarg;
			break;
		case 'h':
			err = 0;
		default:
			usage(err);
		}

	while (optind < argc)
		devices[numdev++] = argv[optind++];

	if (version) {
		print_version(stdout);
		goto exit;
	}

	/* convert LABEL/UUID lookup to evaluate request */
	if (lookup && output_format == OUTPUT_DEVICE_ONLY && search_type &&
	    (!strcmp(search_type, "LABEL") || !strcmp(search_type, "UUID"))) {
		eval++;
		lookup = 0;
	}

	if (!lowprobe && !eval && blkid_get_cache(&cache, read) < 0)
		goto exit;

	if (gc) {
		blkid_gc_cache(cache);
		err = 0;
		goto exit;
	}
	err = 2;

	if (eval == 0 && (output_format & OUTPUT_PRETTY_LIST)) {
		if (lowprobe) {
			fprintf(stderr, "The low-level probing mode does not "
					"support 'list' output format\n");
			exit(4);
		}
		pretty_print_dev(NULL);
	}

	if (lowprobe) {
		/*
		 * Low-level API
		 */
		blkid_probe pr;

		if (!numdev) {
			fprintf(stderr, "The low-level probing mode "
					"requires a device\n");
			exit(4);
		}

		/* automatically enable 'export' format for I/O Limits */
		if (!output_format  && (lowprobe & LOWPROBE_TOPOLOGY))
			output_format = OUTPUT_EXPORT_LIST;

		pr = blkid_new_probe();
		if (!pr)
			goto exit;

		if (lowprobe & LOWPROBE_SUPERBLOCKS) {
			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 (fltr_usage && blkid_probe_filter_superblocks_usage(
						pr, fltr_flag, fltr_usage))
				goto exit;

			else if (fltr_type && blkid_probe_filter_superblocks_type(
						pr, fltr_flag, fltr_type))
				goto exit;
		}

		for (i = 0; i < numdev; i++)
			err = lowprobe_device(pr, devices[i], lowprobe, show,
					output_format,
					(blkid_loff_t) offset,
					(blkid_loff_t) size);
		blkid_free_probe(pr);
	} else if (eval) {
		/*
		 * Evaluate API
		 */
		char *res = blkid_evaluate_tag(search_type, search_value, NULL);
		if (res) {
			err = 0;
			printf("%s\n", res);
		}
	} else if (lookup) {
		/*
		 * Classic (cache based) API
		 */
		blkid_dev dev;

		if (!search_type) {
			fprintf(stderr, "The lookup option requires a "
				"search type specified using -t\n");
			exit(4);
		}
		/* Load any additional devices not in the cache */
		for (i = 0; i < numdev; i++)
			blkid_get_dev(cache, devices[i], BLKID_DEV_NORMAL);

		if ((dev = blkid_find_dev_with_tag(cache, search_type,
						   search_value))) {
			print_tags(dev, show, output_format);
			err = 0;
		}
	/* If we didn't specify a single device, show all available devices */
	} else if (!numdev) {
		blkid_dev_iterate	iter;
		blkid_dev		dev;

		blkid_probe_all(cache);

		iter = blkid_dev_iterate_begin(cache);
		blkid_dev_set_search(iter, search_type, search_value);
		while (blkid_dev_next(iter, &dev) == 0) {
			dev = blkid_verify(cache, dev);
			if (!dev)
				continue;
			print_tags(dev, show, output_format);
			err = 0;
		}
		blkid_dev_iterate_end(iter);
	/* Add all specified devices to cache (optionally display tags) */
	} else for (i = 0; i < numdev; i++) {
		blkid_dev dev = blkid_get_dev(cache, devices[i],
						  BLKID_DEV_NORMAL);

		if (dev) {
			if (search_type &&
			    !blkid_dev_has_tag(dev, search_type,
					       search_value))
				continue;
			print_tags(dev, show, output_format);
			err = 0;
		}
	}

exit:
	free(search_type);
	free(search_value);
	free_types_list(fltr_type);
	if (!lowprobe && !eval)
		blkid_put_cache(cache);
	return err;
}
Ejemplo n.º 15
0
/*
 * 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;
}
Ejemplo n.º 16
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");
}
Ejemplo n.º 17
0
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;
}
Ejemplo n.º 18
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;
}
Ejemplo n.º 19
0
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;
}
Ejemplo n.º 20
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);
}
Ejemplo n.º 21
0
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) {
Ejemplo n.º 22
0
int main(int argc, char **argv)
{
	blkid_cache cache = NULL;
	char **devices = NULL;
	char *show[128] = { NULL, };
	char *search_type = NULL, *search_value = NULL;
	char *read = NULL;
	int fltr_usage = 0;
	char **fltr_type = NULL;
	int fltr_flag = BLKID_FLTR_ONLYIN;
	unsigned int numdev = 0, numtag = 0;
	int version = 0;
	int err = BLKID_EXIT_OTHER;
	unsigned int i;
	int output_format = 0;
	int lookup = 0, gc = 0, lowprobe = 0, eval = 0;
	int c;
	uintmax_t offset = 0, size = 0;

	static const ul_excl_t excl[] = {       /* rows and cols in in ASCII order */
		{ 'n','u' },
		{ 0 }
	};
	int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;

	show[0] = NULL;
	atexit(close_stdout);

	while ((c = getopt (argc, argv,
			    "c:df:ghilL:n:ko:O:ps:S:t:u:U:w:Vv")) != EOF) {

		err_exclusive_options(c, NULL, excl, excl_st);

		switch (c) {
		case 'c':
			if (optarg && !*optarg)
				read = NULL;
			else
				read = optarg;
			break;
		case 'd':
			raw_chars = 1;
			break;
		case 'L':
			eval++;
			search_value = xstrdup(optarg);
			search_type = xstrdup("LABEL");
			break;
		case 'n':
			fltr_type = list_to_types(optarg, &fltr_flag);
			break;
		case 'u':
			fltr_usage = list_to_usage(optarg, &fltr_flag);
			break;
		case 'U':
			eval++;
			search_value = xstrdup(optarg);
			search_type = xstrdup("UUID");
			break;
		case 'i':
			lowprobe |= LOWPROBE_TOPOLOGY;
			break;
		case 'l':
			lookup++;
			break;
		case 'g':
			gc = 1;
			break;
		case 'k':
		{
			size_t idx = 0;
			const char *name = NULL;

			while (blkid_superblocks_get_name(idx++, &name, NULL) == 0)
				printf("%s\n", name);
			exit(EXIT_SUCCESS);
		}
		case 'o':
			if (!strcmp(optarg, "value"))
				output_format = OUTPUT_VALUE_ONLY;
			else if (!strcmp(optarg, "device"))
				output_format = OUTPUT_DEVICE_ONLY;
			else if (!strcmp(optarg, "list"))
				output_format = OUTPUT_PRETTY_LIST;	/* deprecated */
			else if (!strcmp(optarg, "udev"))
				output_format = OUTPUT_UDEV_LIST;
			else if (!strcmp(optarg, "export"))
				output_format = OUTPUT_EXPORT_LIST;
			else if (!strcmp(optarg, "full"))
				output_format = 0;
			else {
				fprintf(stderr, "Invalid output format %s. "
					"Choose from value,\n\t"
					"device, list, udev or full\n", optarg);
				exit(BLKID_EXIT_OTHER);
			}
			break;
		case 'O':
			offset = strtosize_or_err(optarg, "invalid offset argument");
			break;
		case 'p':
			lowprobe |= LOWPROBE_SUPERBLOCKS;
			break;
		case 's':
			if (numtag + 1 >= sizeof(show) / sizeof(*show)) {
				fprintf(stderr, "Too many tags specified\n");
				usage(err);
			}
			show[numtag++] = optarg;
			show[numtag] = NULL;
			break;
		case 'S':
			size = strtosize_or_err(optarg, "invalid size argument");
			break;
		case 't':
			if (search_type) {
				fprintf(stderr, "Can only search for "
						"one NAME=value pair\n");
				usage(err);
			}
			if (blkid_parse_tag_string(optarg,
						   &search_type,
						   &search_value)) {
				fprintf(stderr, "-t needs NAME=value pair\n");
				usage(err);
			}
			break;
		case 'V':
		case 'v':
			version = 1;
			break;
		case 'w':
			/* ignore - backward compatibility */
			break;
		case 'h':
			err = 0;
			/* fallthrough */
		default:
			usage(err);
		}
	}


	/* The rest of the args are device names */
	if (optind < argc) {
		devices = xcalloc(argc - optind, sizeof(char *));
		while (optind < argc)
			devices[numdev++] = argv[optind++];
	}

	if (version) {
		print_version(stdout);
		goto exit;
	}

	/* convert LABEL/UUID lookup to evaluate request */
	if (lookup && output_format == OUTPUT_DEVICE_ONLY && search_type &&
	    (!strcmp(search_type, "LABEL") || !strcmp(search_type, "UUID"))) {
		eval++;
		lookup = 0;
	}

	if (!lowprobe && !eval && blkid_get_cache(&cache, read) < 0)
		goto exit;

	if (gc) {
		blkid_gc_cache(cache);
		err = 0;
		goto exit;
	}
	err = BLKID_EXIT_NOTFOUND;

	if (eval == 0 && (output_format & OUTPUT_PRETTY_LIST)) {
		if (lowprobe) {
			fprintf(stderr, "The low-level probing mode does not "
					"support 'list' output format\n");
			exit(BLKID_EXIT_OTHER);
		}
		pretty_print_dev(NULL);
	}

	if (lowprobe) {
		/*
		 * Low-level API
		 */
		blkid_probe pr;

		if (!numdev) {
			fprintf(stderr, "The low-level probing mode "
					"requires a device\n");
			exit(BLKID_EXIT_OTHER);
		}

		/* automatically enable 'export' format for I/O Limits */
		if (!output_format  && (lowprobe & LOWPROBE_TOPOLOGY))
			output_format = OUTPUT_EXPORT_LIST;

		pr = blkid_new_probe();
		if (!pr)
			goto exit;

		if (lowprobe & LOWPROBE_SUPERBLOCKS) {
			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 (fltr_usage && blkid_probe_filter_superblocks_usage(
						pr, fltr_flag, fltr_usage))
				goto exit;

			else if (fltr_type && blkid_probe_filter_superblocks_type(
						pr, fltr_flag, fltr_type))
				goto exit;
		}

		for (i = 0; i < numdev; i++) {
			err = lowprobe_device(pr, devices[i], lowprobe, show,
					output_format,
					(blkid_loff_t) offset,
					(blkid_loff_t) size);
			if (err)
				break;
		}
		blkid_free_probe(pr);
	} else if (eval) {
		/*
		 * Evaluate API
		 */
		char *res = blkid_evaluate_tag(search_type, search_value, NULL);
		if (res) {
			err = 0;
			printf("%s\n", res);
		}
	} else if (lookup) {
		/*
		 * Classic (cache based) API
		 */
		blkid_dev dev;

		if (!search_type) {
			fprintf(stderr, "The lookup option requires a "
				"search type specified using -t\n");
			exit(BLKID_EXIT_OTHER);
		}
		/* Load any additional devices not in the cache */
		for (i = 0; i < numdev; i++)
			blkid_get_dev(cache, devices[i], BLKID_DEV_NORMAL);

		if ((dev = blkid_find_dev_with_tag(cache, search_type,
						   search_value))) {
			print_tags(dev, show, output_format);
			err = 0;
		}
	/* If we didn't specify a single device, show all available devices */
	} else if (!numdev) {
		blkid_dev_iterate	iter;
		blkid_dev		dev;

		blkid_probe_all(cache);

		iter = blkid_dev_iterate_begin(cache);
		blkid_dev_set_search(iter, search_type, search_value);
		while (blkid_dev_next(iter, &dev) == 0) {
			dev = blkid_verify(cache, dev);
			if (!dev)
				continue;
			print_tags(dev, show, output_format);
			err = 0;
		}
		blkid_dev_iterate_end(iter);
	/* Add all specified devices to cache (optionally display tags) */
	} else for (i = 0; i < numdev; i++) {
		blkid_dev dev = blkid_get_dev(cache, devices[i],
						  BLKID_DEV_NORMAL);

		if (dev) {
			if (search_type &&
			    !blkid_dev_has_tag(dev, search_type,
					       search_value))
				continue;
			print_tags(dev, show, output_format);
			err = 0;
		}
	}

exit:
	free(search_type);
	free(search_value);
	free_types_list(fltr_type);
	if (!lowprobe && !eval)
		blkid_put_cache(cache);
	free(devices);
	return err;
}