Пример #1
0
static char *__lookup_dev(char *path, dev_t dev, int dir_level, const int max_level)
{
	struct dirent *entry;
	struct stat st;
	char *ptr;
	char *result = NULL;
	DIR *dir;
	int space;

	/* Ignore strange nested directories */
	if (dir_level > max_level)
		return NULL;

	path[PATH_MAX - 1] = '\0';
	ptr = path + strlen(path);
	*ptr++ = '/';
	*ptr = '\0';
	space = PATH_MAX - (ptr - path);

	dir = opendir(path);
	if (!dir)
		return NULL;

	while((entry = readdir(dir))) {
		if (entry->d_name[0] == '.' ||
		    !strncmp(entry->d_name, "..", 2))
			continue;

		if (dir_level == 0 &&
		    (!strcmp(entry->d_name, "shm") ||
		     !strcmp(entry->d_name, "fd") ||
		     !strcmp(entry->d_name, "char") ||
		     !strcmp(entry->d_name, "pts")))
			continue;

		strncpy(ptr, entry->d_name, space);
		if (stat(path, &st) < 0)
			continue;

		if (S_ISDIR(st.st_mode)) {
			result = __lookup_dev(path, dev, dir_level + 1, max_level);
			if (result)
				break;
		} else if (S_ISBLK(st.st_mode)) {
			/* workaround: ignore dm-X devices, these are internal kernel names */
			if (dir_level == 0 && dm_is_dm_kernel_name(entry->d_name))
				continue;
			if (st.st_rdev == dev) {
				result = strdup(path);
				break;
			}
		}
	}

	closedir(dir);
	return result;
}
Пример #2
0
/*
 * Returns string pointing to device in /dev according to "major:minor" dev_id
 */
char *crypt_lookup_dev(const char *dev_id)
{
	int major, minor;
	char link[PATH_MAX], path[PATH_MAX], *devname, *devpath = NULL;
	struct stat st;
	ssize_t len;

	if (sscanf(dev_id, "%d:%d", &major, &minor) != 2)
		return NULL;

	if (snprintf(path, sizeof(path), "/sys/dev/block/%s", dev_id) < 0)
		return NULL;

	len = readlink(path, link, sizeof(link));
	if (len < 0) {
		/* Without /sys use old scan */
		if (stat("/sys/dev/block", &st) < 0)
			return lookup_dev_old(major, minor);
		return NULL;
	}

	link[len] = '\0';
	devname = strrchr(link, '/');
	if (!devname)
		return NULL;
	devname++;

	if (dm_is_dm_kernel_name(devname))
		devpath = dm_device_path(major, minor);
	else if (snprintf(path, sizeof(path), "/dev/%s", devname) > 0)
		devpath = strdup(path);

	/*
	 * Check that path is correct.
	 */
	if (devpath && ((stat(devpath, &st) < 0) ||
	    !S_ISBLK(st.st_mode) ||
	    (st.st_rdev != makedev(major, minor)))) {
		free(devpath);
		/* Should never happen unless user mangles with dev nodes. */
		return lookup_dev_old(major, minor);
	}

	return devpath;
}
Пример #3
0
/* Try to find partition which match offset and size on top level device */
char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t size)
{
	char link[PATH_MAX], path[PATH_MAX], part_path[PATH_MAX], *devname;
	char *result = NULL;
	struct stat st;
	size_t devname_len;
	ssize_t len;
	struct dirent *entry;
	DIR *dir;
	uint64_t part_offset, part_size;

	if (stat(dev_path, &st) < 0)
		return NULL;

	if (!S_ISBLK(st.st_mode))
		return NULL;

	if (snprintf(path, sizeof(path), "/sys/dev/block/%d:%d",
		major(st.st_rdev), minor(st.st_rdev)) < 0)
		return NULL;

	len = readlink(path, link, sizeof(link) - 1);
	if (len < 0)
		return NULL;

	/* Get top level disk name for sysfs search */
	link[len] = '\0';
	devname = strrchr(link, '/');
	if (!devname)
		return NULL;
	devname++;

	/* DM devices do not use kernel partitions. */
	if (dm_is_dm_kernel_name(devname))
		return NULL;

	dir = opendir(path);
	if (!dir)
		return NULL;

	devname_len = strlen(devname);
	while((entry = readdir(dir))) {
		if (strncmp(entry->d_name, devname, devname_len))
			continue;

		if (snprintf(part_path, sizeof(part_path), "%s/%s",
		    path, entry->d_name) < 0)
			continue;

		if (stat(part_path, &st) < 0)
			continue;

		if (S_ISDIR(st.st_mode)) {
			if (!_path_get_uint64(part_path, &part_offset, "start") ||
			    !_path_get_uint64(part_path, &part_size, "size"))
				continue;
			if (part_offset == offset && part_size == size &&
			    snprintf(part_path, sizeof(part_path), "/dev/%s",
				     entry->d_name) > 0) {
				result = strdup(part_path);
				break;
			}
		}
	}
	closedir(dir);

	return result;
}