X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Futils_devpath.c;h=b6c8975dbd08c9e3f78a2ab982f71e81c3fedb73;hb=322b430a2589cdc7985e98a14ec12322b91c9d5e;hp=963785a3c94f185aafe926eb9a40eb9601680469;hpb=ad21d48762fa70838d4ab4fbe8fe2a2e8a4dcef1;p=platform%2Fupstream%2Fcryptsetup.git diff --git a/lib/utils_devpath.c b/lib/utils_devpath.c index 963785a..b6c8975 100644 --- a/lib/utils_devpath.c +++ b/lib/utils_devpath.c @@ -1,10 +1,10 @@ /* * devname - search for device name * - * Copyright (C) 2004, Jana Saout - * Copyright (C) 2004-2007, Clemens Fruhwirth - * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2013, Milan Broz + * Copyright (C) 2004 Jana Saout + * Copyright (C) 2004-2007 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -26,11 +26,13 @@ #include #include #include -#include #include #include #include #include +#ifdef HAVE_SYS_SYSMACROS_H +# include /* for major, minor */ +#endif #include "internal.h" static char *__lookup_dev(char *path, dev_t dev, int dir_level, const int max_level) @@ -108,7 +110,7 @@ static char *lookup_dev_old(int major, int minor) return result; /* If it is dm, try DM dir */ - if (dm_is_dm_device(major, minor)) { + if (dm_is_dm_device(major)) { strncpy(buf, dm_get_dir(), PATH_MAX); if ((result = __lookup_dev(buf, dev, 0, 0))) return result; @@ -276,24 +278,30 @@ char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t major(st.st_rdev), minor(st.st_rdev)) < 0) return NULL; + dir = opendir(path); + if (!dir) + return NULL; + len = readlink(path, link, sizeof(link) - 1); - if (len < 0) + if (len < 0) { + closedir(dir); return NULL; + } /* Get top level disk name for sysfs search */ link[len] = '\0'; devname = strrchr(link, '/'); - if (!devname) + if (!devname) { + closedir(dir); return NULL; + } devname++; /* DM devices do not use kernel partitions. */ - if (dm_is_dm_kernel_name(devname)) - return NULL; - - dir = opendir(path); - if (!dir) + if (dm_is_dm_kernel_name(devname)) { + closedir(dir); return NULL; + } devname_len = strlen(devname); while((entry = readdir(dir))) { @@ -362,3 +370,88 @@ char *crypt_get_base_device(const char *dev_path) snprintf(part_path, sizeof(part_path), "/dev/%s", devname); return strdup(part_path); } + +int lookup_by_disk_id(const char *dm_uuid) +{ + struct dirent *entry; + struct stat st; + int r = 0; /* not found */ + DIR *dir = opendir("/dev/disk/by-id"); + + if (!dir) + /* map ENOTDIR to ENOENT we'll handle both errors same */ + return errno == ENOTDIR ? -ENOENT : -errno; + + while ((entry = readdir(dir))) { + if (entry->d_name[0] == '.' || + !strncmp(entry->d_name, "..", 2)) + continue; + + if (fstatat(dirfd(dir), entry->d_name, &st, AT_SYMLINK_NOFOLLOW)) { + r = -EINVAL; + break; + } + + if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) + continue; + + if (!strncmp(entry->d_name, dm_uuid, strlen(dm_uuid))) { + r = 1; + break; + } + } + + closedir(dir); + + return r; +} + +int lookup_by_sysfs_uuid_field(const char *dm_uuid, size_t max_len) +{ + struct dirent *entry; + char subpath[PATH_MAX], uuid[max_len]; + ssize_t s; + struct stat st; + int fd, len, r = 0; /* not found */ + DIR *dir = opendir("/sys/block/"); + + if (!dir) + /* map ENOTDIR to ENOENT we'll handle both errors same */ + return errno == ENOTDIR ? -ENOENT : -errno; + + while (r != 1 && (entry = readdir(dir))) { + if (entry->d_name[0] == '.' || + !strncmp(entry->d_name, "..", 2)) + continue; + + len = snprintf(subpath, PATH_MAX, "%s/%s", entry->d_name, "dm/uuid"); + if (len < 0 || len >= PATH_MAX) { + r = -EINVAL; + break; + } + + /* looking for dm-X/dm/uuid file, symlinks are fine */ + fd = openat(dirfd(dir), subpath, O_RDONLY | O_CLOEXEC); + if (fd < 0) + continue; + + if (fstat(fd, &st) || !S_ISREG(st.st_mode)) { + close(fd); + continue; + } + + /* reads binary data */ + s = read_buffer(fd, uuid, max_len - 1); + if (s > 0) { + uuid[s] = '\0'; + if (!strncmp(uuid, dm_uuid, strlen(dm_uuid))) + r = 1; + } + + close(fd); + } + + closedir(dir); + + return r; +}