Example #1
0
static int probe_and_add_mount(
                const char *id,
                const char *what,
                const char *where,
                bool rw,
                const char *description,
                const char *post) {

        _cleanup_blkid_free_probe_ blkid_probe b = NULL;
        const char *fstype;
        int r;

        assert(id);
        assert(what);
        assert(where);
        assert(description);

        if (path_is_mount_point(where, true) <= 0 &&
            dir_is_empty(where) <= 0) {
                log_debug("%s already populated, ignoring.", where);
                return 0;
        }

        /* Let's check the partition type here, so that we know
         * whether to do LUKS magic. */

        errno = 0;
        b = blkid_new_probe_from_filename(what);
        if (!b) {
                if (errno == 0)
                        return log_oom();
                log_error_errno(errno, "Failed to allocate prober: %m");
                return -errno;
        }

        blkid_probe_enable_superblocks(b, 1);
        blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);

        errno = 0;
        r = blkid_do_safeprobe(b);
        if (r == -2 || r == 1) /* no result or uncertain */
                return 0;
        else if (r != 0) {
                if (errno == 0)
                        errno = EIO;
                log_error_errno(errno, "Failed to probe %s: %m", what);
                return -errno;
        }

        blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);

        return add_mount(
                        id,
                        what,
                        where,
                        fstype,
                        rw,
                        description,
                        post);
}
Example #2
0
static int lowprobe_superblocks(blkid_probe pr)
{
	struct stat st;
	int rc, fd = blkid_probe_get_fd(pr);

	if (fd < 0 || fstat(fd, &st))
		return -1;

	blkid_probe_enable_partitions(pr, 1);

	if (!S_ISCHR(st.st_mode) && blkid_probe_get_size(pr) <= 1024 * 1440 &&
	    blkid_probe_is_wholedisk(pr)) {
		/*
		 * check if the small disk is partitioned, if yes then
		 * don't probe for filesystems.
		 */
		blkid_probe_enable_superblocks(pr, 0);

		rc = blkid_do_fullprobe(pr);
		if (rc < 0)
			return rc;	/* -1 = error, 1 = nothing, 0 = succes */

		if (blkid_probe_lookup_value(pr, "PTTYPE", NULL, NULL) == 0)
			return 0;	/* partition table detected */
	}

	blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS);
	blkid_probe_enable_superblocks(pr, 1);

	return blkid_do_safeprobe(pr);
}
Example #3
0
/**
 * mnt_get_fstype:
 * @devname: device name
 * @ambi: returns TRUE if probing result is ambivalent (optional argument)
 * @cache: cache for results or NULL
 *
 * Returns: filesystem type or NULL in case of error. The result has to be
 * deallocated by free() if @cache is NULL.
 */
char *mnt_get_fstype(const char *devname, int *ambi, struct libmnt_cache *cache)
{
	blkid_probe pr;
	const char *data;
	char *type = NULL;
	int rc;

	DBG(CACHE, mnt_debug_h(cache, "get %s FS type", devname));

	if (cache)
		return mnt_cache_find_tag_value(cache, devname, "TYPE");

	if (cache_get_probe(NULL, devname, &pr))
		return NULL;

	blkid_probe_enable_superblocks(pr, 1);

	blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_TYPE);

	rc = blkid_do_safeprobe(pr);

	if (!rc && !blkid_probe_lookup_value(pr, "TYPE", &data, NULL))
		type = strdup(data);

	if (ambi)
		*ambi = rc == -2 ? TRUE : FALSE;

	blkid_free_probe(pr);
	return type;
}
Example #4
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;
}
Example #5
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;
}
Example #6
0
static int probe_filesystem(const char *node, char **ret_fstype) {
#ifdef HAVE_BLKID
        _cleanup_blkid_free_probe_ blkid_probe b = NULL;
        const char *fstype;
        int r;

        b = blkid_new_probe_from_filename(node);
        if (!b)
                return -ENOMEM;

        blkid_probe_enable_superblocks(b, 1);
        blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);

        errno = 0;
        r = blkid_do_safeprobe(b);
        if (r == -2 || r == 1) {
                log_debug("Failed to identify any partition type on partition %s", node);
                goto not_found;
        }
        if (r != 0) {
                if (errno == 0)
                        return -EIO;

                return -errno;
        }

        (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);

        if (fstype) {
                char *t;

                t = strdup(fstype);
                if (!t)
                        return -ENOMEM;

                *ret_fstype = t;
                return 1;
        }

not_found:
        *ret_fstype = NULL;
        return 0;
#else
        return -EOPNOTSUPP;
#endif
}
Example #7
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;
}
Example #8
0
/*
 * Returns new libblkid prober. This function call exit() on error.
 */
static blkid_probe get_swap_prober(const char *devname)
{
	blkid_probe pr;
	int rc;
	const char *version = NULL;
	char *swap_filter[] = { "swap", NULL };

	pr = blkid_new_probe_from_filename(devname);
	if (!pr) {
		warn(_("%s: unable to probe device"), devname);
		return NULL;
	}

	blkid_probe_enable_superblocks(pr, TRUE);
	blkid_probe_set_superblocks_flags(pr,
			BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID |
			BLKID_SUBLKS_VERSION);

	blkid_probe_filter_superblocks_type(pr, BLKID_FLTR_ONLYIN, swap_filter);

	rc = blkid_do_safeprobe(pr);
	if (rc == -1)
		warn(_("%s: unable to probe device"), devname);
	else if (rc == -2)
		warnx(_("%s: ambivalent probing result, use wipefs(8)"), devname);
	else if (rc == 1)
		warnx(_("%s: not a valid swap partition"), devname);

	if (rc == 0) {
		/* supported is SWAPSPACE2 only */
		if (blkid_probe_lookup_value(pr, "VERSION", &version, NULL) == 0
		    && version
		    && strcmp(version, "2"))
			warnx(_("%s: unsupported swap version '%s'"),
						devname, version);
		else
			return pr;
	}

	blkid_free_probe(pr);
	return NULL;
}
Example #9
0
/**
 * mnt_get_fstype:
 * @devname: device name
 * @ambi: returns TRUE if probing result is ambivalent (optional argument)
 * @cache: cache for results or NULL
 *
 * Returns: filesystem type or NULL in case of error. The result has to be
 * deallocated by free() if @cache is NULL.
 */
char *mnt_get_fstype(const char *devname, int *ambi, struct libmnt_cache *cache)
{
	blkid_probe pr;
	const char *data;
	char *type = NULL;
	int rc;

	DBG(CACHE, ul_debugobj(cache, "get %s FS type", devname));

	if (cache) {
		char *val = NULL;
		rc = __mnt_cache_find_tag_value(cache, devname, "TYPE", &val);
		if (ambi)
			*ambi = rc == -2 ? TRUE : FALSE;
		return rc ? NULL : val;
	}

	/*
	 * no cache, probe directly
	 */
	pr =  blkid_new_probe_from_filename(devname);
	if (!pr)
		return NULL;

	blkid_probe_enable_superblocks(pr, 1);
	blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_TYPE);

	rc = blkid_do_safeprobe(pr);

	DBG(CACHE, ul_debugobj(cache, "libblkid rc=%d", rc));

	if (!rc && !blkid_probe_lookup_value(pr, "TYPE", &data, NULL))
		type = strdup(data);

	if (ambi)
		*ambi = rc == -2 ? TRUE : FALSE;

	blkid_free_probe(pr);
	return type;
}
Example #10
0
static int lowprobe_device(blkid_probe pr, const char *devname,	char *show[],
			int output, blkid_loff_t offset, blkid_loff_t size)
{
	const char *data;
	const char *name;
	int nvals = 0, n, num = 1;
	size_t len;
	int fd;
	int rc = 0;
	struct stat st;

	fd = open(devname, O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "error: %s: %s\n", devname, strerror(errno));
		return 2;
	}
	if (blkid_probe_set_device(pr, fd, offset, size))
		goto done;

	if (fstat(fd, &st))
		goto done;
	/*
	 * partitions probing
	 */
	blkid_probe_enable_superblocks(pr, 0);	/* enabled by default ;-( */

	blkid_probe_enable_partitions(pr, 1);
	rc = blkid_do_fullprobe(pr);
	blkid_probe_enable_partitions(pr, 0);

	if (rc < 0)
		goto done;	/* -1 = error, 1 = nothing, 0 = succes */

	/*
	 * Don't probe for FS/RAIDs on small devices
	 */
	if (rc || S_ISCHR(st.st_mode) ||
	    blkid_probe_get_size(pr) > 1024 * 1440) {
		/*
		 * filesystems/RAIDs probing
		 */
		blkid_probe_enable_superblocks(pr, 1);

		rc = blkid_do_safeprobe(pr);
		if (rc < 0)
			goto done;
	}

	nvals = blkid_probe_numof_values(pr);

	if (output & OUTPUT_DEVICE_ONLY) {
		printf("%s\n", devname);
		goto done;
	}

	for (n = 0; n < nvals; n++) {
		if (blkid_probe_get_value(pr, n, &name, &data, &len))
			continue;
		if (show[0] && !has_item(show, name))
			continue;
		len = strnlen((char *) data, len);
		print_value(output, num++, devname, (char *) data, name, len);
	}

	if (nvals >= 1 && !(output & (OUTPUT_VALUE_ONLY | OUTPUT_UDEV_LIST)))
		printf("\n");
done:
	if (rc == -2) {
		if (output & OUTPUT_UDEV_LIST)
			print_udev_ambivalent(pr);
		else
			fprintf(stderr,
				"%s: ambivalent result (probably more "
				"filesystems on the device, use wipefs(8) "
				"to see more details)\n",
				devname);
	}
	close(fd);
	return !nvals ? 2 : 0;
}
Example #11
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;
}
Example #12
0
/**
 * mnt_cache_read_tags
 * @cache: pointer to struct libmnt_cache instance
 * @devname: path device
 *
 * Reads @devname LABEL and UUID to the @cache.
 *
 * Returns: 0 if at least one tag was added, 1 if no tag was added or
 *          negative number in case of error.
 */
int mnt_cache_read_tags(struct libmnt_cache *cache, const char *devname)
{
	blkid_probe pr;
	size_t i, ntags = 0;
	int rc;
	const char *tags[] = { "LABEL", "UUID", "TYPE", "PARTUUID", "PARTLABEL" };
	const char *blktags[] = { "LABEL", "UUID", "TYPE", "PART_ENTRY_UUID", "PART_ENTRY_NAME" };

	if (!cache || !devname)
		return -EINVAL;

	DBG(CACHE, ul_debugobj(cache, "tags for %s requested", devname));

	/* check if device is already cached */
	for (i = 0; i < cache->nents; i++) {
		struct mnt_cache_entry *e = &cache->ents[i];
		if (!(e->flag & MNT_CACHE_TAGREAD))
			continue;
		if (strcmp(e->value, devname) == 0)
			/* tags have already been read */
			return 0;
	}

	pr =  blkid_new_probe_from_filename(devname);
	if (!pr)
		return -1;

	blkid_probe_enable_superblocks(pr, 1);
	blkid_probe_set_superblocks_flags(pr,
			BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID |
			BLKID_SUBLKS_TYPE);

	blkid_probe_enable_partitions(pr, 1);
	blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS);

	rc = blkid_do_safeprobe(pr);
	if (rc)
		goto error;

	DBG(CACHE, ul_debugobj(cache, "reading tags for: %s", devname));

	for (i = 0; i < ARRAY_SIZE(tags); i++) {
		const char *data;
		char *dev;

		if (cache_find_tag_value(cache, devname, tags[i])) {
			DBG(CACHE, ul_debugobj(cache,
					"\ntag %s already cached", tags[i]));
			continue;
		}
		if (blkid_probe_lookup_value(pr, blktags[i], &data, NULL))
			continue;
		dev = strdup(devname);
		if (!dev)
			goto error;
		if (cache_add_tag(cache, tags[i], data, dev,
					MNT_CACHE_TAGREAD)) {
			free(dev);
			goto error;
		}
		ntags++;
	}

	DBG(CACHE, ul_debugobj(cache, "\tread %zd tags", ntags));
	blkid_free_probe(pr);
	return ntags ? 0 : 1;
error:
	blkid_free_probe(pr);
	return rc < 0 ? rc : -1;
}
Example #13
0
/**
 * mnt_cache_read_tags
 * @cache: pointer to struct libmnt_cache instance
 * @devname: path device
 *
 * Reads @devname LABEL and UUID to the @cache.
 *
 * Returns: 0 if at least one tag was added, 1 if no tag was added or
 *          negative number in case of error.
 */
int mnt_cache_read_tags(struct libmnt_cache *cache, const char *devname)
{
	size_t i, ntags = 0;
	int rc;
	const char *tags[] = { "LABEL", "UUID", "TYPE" };

	assert(cache);
	assert(devname);

	if (!cache || !devname)
		return -EINVAL;

	DBG(CACHE, mnt_debug_h(cache, "tags for %s requested", devname));

	/* check is device is already cached */
	for (i = 0; i < cache->nents; i++) {
		struct mnt_cache_entry *e = &cache->ents[i];
		if (!(e->flag & MNT_CACHE_TAGREAD))
			continue;
		if (strcmp(e->value, devname) == 0)
			/* tags has been already read */
			return 0;
	}

	rc = cache_get_probe(cache, devname, NULL);
	if (rc)
		return rc;

	blkid_probe_enable_superblocks(cache->pr, 1);

	blkid_probe_set_superblocks_flags(cache->pr,
			BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID |
			BLKID_SUBLKS_TYPE);

	if (blkid_do_safeprobe(cache->pr))
		goto error;

	DBG(CACHE, mnt_debug_h(cache, "reading tags for: %s", devname));

	for (i = 0; i < ARRAY_SIZE(tags); i++) {
		const char *data;
		char *dev;

		if (cache_find_tag_value(cache, devname, tags[i])) {
			DBG(CACHE, mnt_debug_h(cache,
					"\ntag %s already cached", tags[i]));
			continue;
		}
		if (blkid_probe_lookup_value(cache->pr, tags[i], &data, NULL))
			continue;
		dev = strdup(devname);
		if (!dev)
			goto error;
		if (cache_add_tag(cache, tags[i], data, dev,
					MNT_CACHE_TAGREAD)) {
			free(dev);
			goto error;
		}
		ntags++;
	}

	DBG(CACHE, mnt_debug_h(cache, "\tread %zd tags", ntags));
	return ntags ? 0 : 1;
error:
	return -1;
}
PupCD *pup_cd_new_from_drive(PupCDDrive *drv, PupVMMonitor *monitor)
{
	PupCD *disk;

	pup_vm_monitor_lock(monitor);
	disk = PUP_CD(pup_device_new(PUP_TYPE_CD, PUP_DEVICE(drv)->sysname));
	//Get volume-specific paramaters like label, uuid, ...
	PupVolume *volume = PUP_VOLUME(disk);
	volume->unix_dev = g_strdup(PUP_DRIVE(drv)->unix_dev);
	volume->drv_sysname = g_strdup(PUP_DEVICE(drv)->sysname);
	pup_vm_monitor_unlock(monitor);

	blkid_probe probe = blkid_new_probe_from_filename(volume->unix_dev);
	if (probe)
	{
		blkid_do_safeprobe(probe);
		if (blkid_probe_lookup_value(probe, "TYPE",
			                         (const char **) &(volume->fstype), NULL) == 0)
			volume->fstype = g_strdup(volume->fstype);
		else
			volume->fstype = NULL;
		if (blkid_probe_lookup_value(probe, "LABEL",
			                         (const char **) &(volume->label), NULL) == 0)
			volume->label = g_strdup(volume->label);
		else
			volume->label = NULL;
		if (blkid_probe_lookup_value(probe, "UUID",
			                         (const char **) &(volume->uuid), NULL) == 0)
			volume->uuid = g_strdup(volume->uuid);
		else
			volume->uuid = NULL;

		blkid_free_probe(probe);
	}
	/*
	if (! volume->fstype)
	{
		g_object_unref(disk);
		return NULL;
	}
	*/
	//Check for audio CD
	gint fd = open(volume->unix_dev, O_NONBLOCK | O_RDWR);
	if (fd >= 0)
	{
		if (ioctl(fd, CDROM_DISC_STATUS, 0) == CDS_AUDIO)
		{
			disk->audio_cd = TRUE;
			volume->flags &= (~PUP_VOLUME_IS_MOUNTABLE);
		}
		close (fd);
	}
	//No need to check for mounts, daemon will do it for us
	
	//Display name and icon
	PUP_DEVICE(disk)->display_name = pup_volume_gen_display_name(volume);
	if (disk->audio_cd)
		PUP_DEVICE(disk)->icon_name = g_strdup(PUP_ICON_AUDIOCD);
	else
		PUP_DEVICE(disk)->icon_name = g_strdup(PUP_ICON_CDROM);

	return PUP_CD(pup_overwrite_dev(monitor, PUP_DEVICE(disk)));
}
Example #15
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;
}
static int enumerate_partitions(dev_t devnum) {

        _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
        _cleanup_udev_device_unref_ struct udev_device *d = NULL;
        _cleanup_blkid_free_probe_ blkid_probe b = NULL;
        _cleanup_udev_unref_ struct udev *udev = NULL;
        _cleanup_free_ char *home = NULL, *srv = NULL;
        struct udev_list_entry *first, *item;
        struct udev_device *parent = NULL;
        const char *node, *pttype, *devtype;
        int home_nr = -1, srv_nr = -1;
        blkid_partlist pl;
        int r, k;
        dev_t pn;

        udev = udev_new();
        if (!udev)
                return log_oom();

        d = udev_device_new_from_devnum(udev, 'b', devnum);
        if (!d)
                return log_oom();

        parent = udev_device_get_parent(d);
        if (!parent)
                return log_oom();

        /* Does it have a devtype? */
        devtype = udev_device_get_devtype(parent);
        if (!devtype)
                return 0;

        /* Is this a disk or a partition? We only care for disks... */
        if (!streq(devtype, "disk"))
                return 0;

        /* Does it have a device node? */
        node = udev_device_get_devnode(parent);
        if (!node)
                return 0;

        log_debug("Root device %s.", node);

        pn = udev_device_get_devnum(parent);
        if (major(pn) == 0)
                return 0;

        errno = 0;
        b = blkid_new_probe_from_filename(node);
        if (!b) {
                if (errno == 0)
                        return log_oom();

                log_error("Failed allocate prober: %m");
                return -errno;
        }

        blkid_probe_enable_superblocks(b, 1);
        blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
        blkid_probe_enable_partitions(b, 1);
        blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);

        errno = 0;
        r = blkid_do_safeprobe(b);
        if (r == -2 || r == 1) /* no result or uncertain */
                return 0;
        else if (r != 0) {
                if (errno == 0)
                        errno = EIO;
                log_error("Failed to probe %s: %m", node);
                return -errno;
        }

        errno = 0;
        r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
        if (r != 0) {
                if (errno == 0)
                        errno = EIO;
                log_error("Failed to determine partition table type of %s: %m", node);
                return -errno;
        }

        /* We only do this all for GPT... */
        if (!streq_ptr(pttype, "gpt"))
                return 0;

        errno = 0;
        pl = blkid_probe_get_partitions(b);
        if (!pl) {
                if (errno == 0)
                        return log_oom();

                log_error("Failed to list partitions of %s: %m", node);
                return -errno;
        }

        e = udev_enumerate_new(udev);
        if (!e)
                return log_oom();

        r = udev_enumerate_add_match_parent(e, parent);
        if (r < 0)
                return log_oom();

        r = udev_enumerate_add_match_subsystem(e, "block");
        if (r < 0)
                return log_oom();

        r = udev_enumerate_scan_devices(e);
        if (r < 0) {
                log_error("Failed to enumerate partitions on %s: %s", node, strerror(-r));
                return r;
        }

        first = udev_enumerate_get_list_entry(e);
        udev_list_entry_foreach(item, first) {
                _cleanup_udev_device_unref_ struct udev_device *q;
                const char *stype, *subnode;
                sd_id128_t type_id;
                blkid_partition pp;
                dev_t qn;
                int nr;

                q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
                if (!q)
                        continue;

                qn = udev_device_get_devnum(q);
                if (major(qn) == 0)
                        continue;

                if (qn == devnum)
                        continue;

                if (qn == pn)
                        continue;

                subnode = udev_device_get_devnode(q);
                if (!subnode)
                        continue;

                pp = blkid_partlist_devno_to_partition(pl, qn);
                if (!pp)
                        continue;

                nr = blkid_partition_get_partno(pp);
                if (nr < 0)
                        continue;

                stype = blkid_partition_get_type_string(pp);
                if (!stype)
                        continue;

                if (sd_id128_from_string(stype, &type_id) < 0)
                        continue;

                if (sd_id128_equal(type_id, GPT_SWAP)) {

                        k = add_swap(subnode);
                        if (k < 0)
                                r = k;

                } else if (sd_id128_equal(type_id, GPT_HOME)) {

                        /* We only care for the first /home partition */
                        if (home && nr >= home_nr)
                                continue;

                        home_nr = nr;

                        free(home);
                        home = strdup(subnode);
                        if (!home)
                                return log_oom();

                } else if (sd_id128_equal(type_id, GPT_SRV)) {

                        /* We only care for the first /srv partition */
                        if (srv && nr >= srv_nr)
                                continue;

                        srv_nr = nr;

                        free(srv);
                        srv = strdup(node);
                        if (!srv)
                                return log_oom();
                }
        }
Example #17
0
static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) {
        struct statfs sfs;
        struct stat st, st2;
        _cleanup_free_ char *t = NULL;
        _cleanup_blkid_free_probe_ blkid_probe b = NULL;
        int r;
        const char *v, *t2;

        if (statfs(p, &sfs) < 0)
                return log_error_errno(errno, "Failed to check file system type of \"%s\": %m", p);

        if (sfs.f_type != 0x4d44) {
                log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p);
                return -ENODEV;
        }

        if (stat(p, &st) < 0)
                return log_error_errno(errno, "Failed to determine block device node of \"%s\": %m", p);

        if (major(st.st_dev) == 0) {
                log_error("Block device node of %p is invalid.", p);
                return -ENODEV;
        }

        t2 = strjoina(p, "/..");
        r = stat(t2, &st2);
        if (r < 0)
                return log_error_errno(errno, "Failed to determine block device node of parent of \"%s\": %m", p);

        if (st.st_dev == st2.st_dev) {
                log_error("Directory \"%s\" is not the root of the EFI System Partition (ESP) file system.", p);
                return -ENODEV;
        }

        r = asprintf(&t, "/dev/block/%u:%u", major(st.st_dev), minor(st.st_dev));
        if (r < 0)
                return log_oom();

        errno = 0;
        b = blkid_new_probe_from_filename(t);
        if (!b) {
                if (errno == 0)
                        return log_oom();

                return log_error_errno(errno, "Failed to open file system \"%s\": %m", p);
        }

        blkid_probe_enable_superblocks(b, 1);
        blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
        blkid_probe_enable_partitions(b, 1);
        blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);

        errno = 0;
        r = blkid_do_safeprobe(b);
        if (r == -2) {
                log_error("File system \"%s\" is ambiguous.", p);
                return -ENODEV;
        } else if (r == 1) {
                log_error("File system \"%s\" does not contain a label.", p);
                return -ENODEV;
        } else if (r != 0) {
                r = errno ? -errno : -EIO;
                return log_error_errno(r, "Failed to probe file system \"%s\": %m", p);
        }

        errno = 0;
        r = blkid_probe_lookup_value(b, "TYPE", &v, NULL);
        if (r != 0) {
                r = errno ? -errno : -EIO;
                return log_error_errno(r, "Failed to probe file system type \"%s\": %m", p);
        }

        if (!streq(v, "vfat")) {
                log_error("File system \"%s\" is not FAT.", p);
                return -ENODEV;
        }

        errno = 0;
        r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL);
        if (r != 0) {
                r = errno ? -errno : -EIO;
                return log_error_errno(r, "Failed to probe partition scheme \"%s\": %m", p);
        }

        if (!streq(v, "gpt")) {
                log_error("File system \"%s\" is not on a GPT partition table.", p);
                return -ENODEV;
        }

        errno = 0;
        r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
        if (r != 0) {
                r = errno ? -errno : -EIO;
                return log_error_errno(r, "Failed to probe partition type UUID \"%s\": %m", p);
        }

        if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) {
                log_error("File system \"%s\" has wrong type for an EFI System Partition (ESP).", p);
                return -ENODEV;
        }

        errno = 0;
        r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &v, NULL);
        if (r != 0) {
                r = errno ? -errno : -EIO;
                return log_error_errno(r, "Failed to probe partition entry UUID \"%s\": %m", p);
        }

        r = sd_id128_from_string(v, uuid);
        if (r < 0) {
                log_error("Partition \"%s\" has invalid UUID \"%s\".", p, v);
                return -EIO;
        }

        errno = 0;
        r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL);
        if (r != 0) {
                r = errno ? -errno : -EIO;
                return log_error_errno(r, "Failed to probe partition number \"%s\": m", p);
        }
        *part = strtoul(v, NULL, 10);

        errno = 0;
        r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL);
        if (r != 0) {
                r = errno ? -errno : -EIO;
                return log_error_errno(r, "Failed to probe partition offset \"%s\": %m", p);
        }
        *pstart = strtoul(v, NULL, 10);

        errno = 0;
        r = blkid_probe_lookup_value(b, "PART_ENTRY_SIZE", &v, NULL);
        if (r != 0) {
                r = errno ? -errno : -EIO;
                return log_error_errno(r, "Failed to probe partition size \"%s\": %m", p);
        }
        *psize = strtoul(v, NULL, 10);

        return 0;
}
Example #18
0
static int enumerate_partitions(dev_t devnum) {

        _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
        _cleanup_udev_device_unref_ struct udev_device *d = NULL;
        _cleanup_blkid_free_probe_ blkid_probe b = NULL;
        _cleanup_udev_unref_ struct udev *udev = NULL;
        _cleanup_free_ char *boot = NULL, *home = NULL, *srv = NULL;
        struct udev_list_entry *first, *item;
        struct udev_device *parent = NULL;
        const char *name, *node, *pttype, *devtype;
        int boot_nr = -1, home_nr = -1, srv_nr = -1;
        bool home_rw = true, srv_rw = true;
        blkid_partlist pl;
        int r, k;
        dev_t pn;

        udev = udev_new();
        if (!udev)
                return log_oom();

        d = udev_device_new_from_devnum(udev, 'b', devnum);
        if (!d)
                return log_oom();

        name = udev_device_get_devnode(d);
        if (!name)
                name = udev_device_get_syspath(d);
        if (!name) {
                log_debug("Device %u:%u does not have a name, ignoring.",
                          major(devnum), minor(devnum));
                return 0;
        }

        parent = udev_device_get_parent(d);
        if (!parent) {
                log_debug("%s: not a partitioned device, ignoring.", name);
                return 0;
        }

        /* Does it have a devtype? */
        devtype = udev_device_get_devtype(parent);
        if (!devtype) {
                log_debug("%s: parent doesn't have a device type, ignoring.", name);
                return 0;
        }

        /* Is this a disk or a partition? We only care for disks... */
        if (!streq(devtype, "disk")) {
                log_debug("%s: parent isn't a raw disk, ignoring.", name);
                return 0;
        }

        /* Does it have a device node? */
        node = udev_device_get_devnode(parent);
        if (!node) {
                log_debug("%s: parent device does not have device node, ignoring.", name);
                return 0;
        }

        log_debug("%s: root device %s.", name, node);

        pn = udev_device_get_devnum(parent);
        if (major(pn) == 0)
                return 0;

        errno = 0;
        b = blkid_new_probe_from_filename(node);
        if (!b) {
                if (errno == 0)
                        return log_oom();

                return log_error_errno(errno, "%s: failed to allocate prober: %m", node);
        }

        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 == 1)
                return 0; /* no results */
        else if (r == -2) {
                log_warning("%s: probe gave ambiguous results, ignoring", node);
                return 0;
        } else if (r != 0)
                return log_error_errno(errno ?: EIO, "%s: failed to probe: %m", node);

        errno = 0;
        r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
        if (r != 0)
                return log_error_errno(errno ?: EIO,
                                       "%s: failed to determine partition table type: %m", node);

        /* We only do this all for GPT... */
        if (!streq_ptr(pttype, "gpt")) {
                log_debug("%s: not a GPT partition table, ignoring.", node);
                return 0;
        }

        errno = 0;
        pl = blkid_probe_get_partitions(b);
        if (!pl) {
                if (errno == 0)
                        return log_oom();

                return log_error_errno(errno, "%s: failed to list partitions: %m", node);
        }

        e = udev_enumerate_new(udev);
        if (!e)
                return log_oom();

        r = udev_enumerate_add_match_parent(e, parent);
        if (r < 0)
                return log_oom();

        r = udev_enumerate_add_match_subsystem(e, "block");
        if (r < 0)
                return log_oom();

        r = udev_enumerate_scan_devices(e);
        if (r < 0)
                return log_error_errno(r, "%s: failed to enumerate partitions: %m", node);

        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;
                const char *stype, *subnode;
                sd_id128_t type_id;
                blkid_partition pp;
                dev_t qn;
                int nr;

                q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
                if (!q)
                        continue;

                qn = udev_device_get_devnum(q);
                if (major(qn) == 0)
                        continue;

                if (qn == devnum)
                        continue;

                if (qn == pn)
                        continue;

                subnode = udev_device_get_devnode(q);
                if (!subnode)
                        continue;

                pp = blkid_partlist_devno_to_partition(pl, qn);
                if (!pp)
                        continue;

                nr = blkid_partition_get_partno(pp);
                if (nr < 0)
                        continue;

                stype = blkid_partition_get_type_string(pp);
                if (!stype)
                        continue;

                if (sd_id128_from_string(stype, &type_id) < 0)
                        continue;

                flags = blkid_partition_get_flags(pp);

                if (sd_id128_equal(type_id, GPT_SWAP)) {

                        if (flags & GPT_FLAG_NO_AUTO)
                                continue;

                        if (flags & GPT_FLAG_READ_ONLY) {
                                log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode);
                                continue;
                        }

                        k = add_swap(subnode);
                        if (k < 0)
                                r = k;

                } else if (sd_id128_equal(type_id, GPT_ESP)) {

                        /* We only care for the first /boot partition */
                        if (boot && nr >= boot_nr)
                                continue;

                        /* Note that we do not honour the "no-auto"
                         * flag for the ESP, as it is often unset, to
                         * hide it from Windows. */

                        boot_nr = nr;

                        r = free_and_strdup(&boot, subnode);
                        if (r < 0)
                                return log_oom();

                } else if (sd_id128_equal(type_id, GPT_HOME)) {

                        if (flags & GPT_FLAG_NO_AUTO)
                                continue;

                        /* We only care for the first /home partition */
                        if (home && nr >= home_nr)
                                continue;

                        home_nr = nr;
                        home_rw = !(flags & GPT_FLAG_READ_ONLY),

                        r = free_and_strdup(&home, subnode);
                        if (r < 0)
                                return log_oom();

                } else if (sd_id128_equal(type_id, GPT_SRV)) {

                        if (flags & GPT_FLAG_NO_AUTO)
                                continue;

                        /* We only care for the first /srv partition */
                        if (srv && nr >= srv_nr)
                                continue;

                        srv_nr = nr;
                        srv_rw = !(flags & GPT_FLAG_READ_ONLY),

                        r = free_and_strdup(&srv, subnode);
                        if (r < 0)
                                return log_oom();
                }
        }
Example #19
0
static int add_boot(const char *what) {
        _cleanup_blkid_free_probe_ blkid_probe b = NULL;
        const char *fstype = NULL, *uuid = NULL;
        sd_id128_t id, type_id;
        int r;

        assert(what);

        if (!is_efi_boot()) {
                log_debug("Not an EFI boot, ignoring /boot.");
                return 0;
        }

        if (in_initrd()) {
                log_debug("In initrd, ignoring /boot.");
                return 0;
        }

        if (detect_container() > 0) {
                log_debug("In a container, ignoring /boot.");
                return 0;
        }

        /* We create an .automount which is not overridden by the .mount from the fstab generator. */
        if (fstab_is_mount_point("/boot")) {
                log_debug("/boot specified in fstab, ignoring.");
                return 0;
        }

        if (path_is_busy("/boot")) {
                log_debug("/boot already populated, ignoring.");
                return 0;
        }

        r = efi_loader_get_device_part_uuid(&id);
        if (r == -ENOENT) {
                log_debug("EFI loader partition unknown.");
                return 0;
        }

        if (r < 0) {
                log_error_errno(r, "Failed to read ESP partition UUID: %m");
                return r;
        }

        errno = 0;
        b = blkid_new_probe_from_filename(what);
        if (!b) {
                if (errno == 0)
                        return log_oom();
                return log_error_errno(errno, "Failed to allocate prober: %m");
        }

        blkid_probe_enable_partitions(b, 1);
        blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);

        errno = 0;
        r = blkid_do_safeprobe(b);
        if (r == -2 || r == 1) /* no result or uncertain */
                return 0;
        else if (r != 0)
                return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what);

        (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
        if (!streq(fstype, "vfat")) {
                log_debug("Partition for /boot is not a FAT filesystem, ignoring.");
                return 0;
        }

        r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &uuid, NULL);
        if (r != 0) {
                log_debug_errno(r, "Partition for /boot does not have a UUID, ignoring. %m");
                return 0;
        }

        if (sd_id128_from_string(uuid, &type_id) < 0) {
                log_debug("Partition for /boot does not have a valid UUID, ignoring.");
                return 0;
        }

        if (!sd_id128_equal(type_id, id)) {
                log_debug("Partition for /boot does not appear to be the partition we are booted from.");
                return 0;
        }

        r = add_automount("boot",
                       what,
                       "/boot",
                       "vfat",
                       true,
                       "umask=0077",
                       "EFI System Partition Automount",
                       120 * USEC_PER_SEC);

        return r;
}
Example #20
0
static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) {
        struct statfs sfs;
        struct stat st, st2;
        char *t;
        blkid_probe b = NULL;
        int r;
        const char *v;

        if (statfs(p, &sfs) < 0) {
                fprintf(stderr, "Failed to check file system type of %s: %m\n", p);
                return -errno;
        }

        if (sfs.f_type != 0x4d44) {
                fprintf(stderr, "File system %s is not a FAT EFI System Partition (ESP) file system.\n", p);
                return -ENODEV;
        }

        if (stat(p, &st) < 0) {
                fprintf(stderr, "Failed to determine block device node of %s: %m\n", p);
                return -errno;
        }

        if (major(st.st_dev) == 0) {
                fprintf(stderr, "Block device node of %p is invalid.\n", p);
                return -ENODEV;
        }

        r = asprintf(&t, "%s/..", p);
        if (r < 0) {
                fprintf(stderr, "Out of memory.\n");
                return -ENOMEM;
        }

        r = stat(t, &st2);
        free(t);
        if (r < 0) {
                fprintf(stderr, "Failed to determine block device node of parent of %s: %m\n", p);
                return -errno;
        }

        if (st.st_dev == st2.st_dev) {
                fprintf(stderr, "Directory %s is not the root of the EFI System Partition (ESP) file system.\n", p);
                return -ENODEV;
        }

        r = asprintf(&t, "/dev/block/%u:%u", major(st.st_dev), minor(st.st_dev));
        if (r < 0) {
                fprintf(stderr, "Out of memory.\n");
                return -ENOMEM;
        }

        errno = 0;
        b = blkid_new_probe_from_filename(t);
        free(t);
        if (!b) {
                if (errno != 0) {
                        fprintf(stderr, "Failed to open file system %s: %m\n", p);
                        return -errno;
                }

                fprintf(stderr, "Out of memory.\n");
                return -ENOMEM;
        }

        blkid_probe_enable_superblocks(b, 1);
        blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
        blkid_probe_enable_partitions(b, 1);
        blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);

        errno = 0;
        r = blkid_do_safeprobe(b);
        if (r == -2) {
                fprintf(stderr, "File system %s is ambigious.\n", p);
                r = -ENODEV;
                goto fail;
        } else if (r == 1) {
                fprintf(stderr, "File system %s does not contain a label.\n", p);
                r = -ENODEV;
                goto fail;
        } else if (r != 0) {
                r = errno ? -errno : -EIO;
                fprintf(stderr, "Failed to probe file system %s: %s\n", p, strerror(-r));
                goto fail;
        }

        errno = 0;
        r = blkid_probe_lookup_value(b, "TYPE", &v, NULL);
        if (r != 0) {
                r = errno ? -errno : -EIO;
                fprintf(stderr, "Failed to probe file system type %s: %s\n", p, strerror(-r));
                goto fail;
        }

        if (strcmp(v, "vfat") != 0) {
                fprintf(stderr, "File system %s is not a FAT EFI System Partition (ESP) file system after all.\n", p);
                r = -ENODEV;
                goto fail;
        }

        errno = 0;
        r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL);
        if (r != 0) {
                r = errno ? -errno : -EIO;
                fprintf(stderr, "Failed to probe partition scheme %s: %s\n", p, strerror(-r));
                goto fail;
        }

        if (strcmp(v, "gpt") != 0) {
                fprintf(stderr, "File system %s is not on a GPT partition table.\n", p);
                r = -ENODEV;
                goto fail;
        }

        errno = 0;
        r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
        if (r != 0) {
                r = errno ? -errno : -EIO;
                fprintf(stderr, "Failed to probe partition type UUID %s: %s\n", p, strerror(-r));
                goto fail;
        }

        if (strcmp(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b") != 0) {
                r = -ENODEV;
                fprintf(stderr, "File system %s is not an EFI System Partition (ESP).\n", p);
                goto fail;
        }

        errno = 0;
        r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &v, NULL);
        if (r != 0) {
                r = errno ? -errno : -EIO;
                fprintf(stderr, "Failed to probe partition entry UUID %s: %s\n", p, strerror(-r));
                goto fail;
        }

        r = sd_id128_from_string(v, uuid);
        if (r < 0) {
                fprintf(stderr, "Partition %s has invalid UUID: %s\n", p, v);
                r = -EIO;
                goto fail;
        }

        errno = 0;
        r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL);
        if (r != 0) {
                r = errno ? -errno : -EIO;
                fprintf(stderr, "Failed to probe partition number %s: %s\n", p, strerror(-r));
                goto fail;
        }
        *part = strtoul(v, NULL, 10);

        errno = 0;
        r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL);
        if (r != 0) {
                r = errno ? -errno : -EIO;
                fprintf(stderr, "Failed to probe partition offset %s: %s\n", p, strerror(-r));
                goto fail;
        }
        *pstart = strtoul(v, NULL, 10);

        errno = 0;
        r = blkid_probe_lookup_value(b, "PART_ENTRY_SIZE", &v, NULL);
        if (r != 0) {
                r = errno ? -errno : -EIO;
                fprintf(stderr, "Failed to probe partition size %s: %s\n", p, strerror(-r));
                goto fail;
        }
        *psize = strtoul(v, NULL, 10);

        blkid_free_probe(b);
        return 0;
fail:
        if (b)
                blkid_free_probe(b);
        return r;
}
Example #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) {