Move devpath scan to separate file.

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@529 36d66b0a-2a48-0410-832c-cd162a569da5
This commit is contained in:
Milan Broz
2011-05-24 11:19:00 +00:00
parent 4c08eedaca
commit 2755f37266
5 changed files with 174 additions and 136 deletions

View File

@@ -52,6 +52,7 @@ libcryptsetup_la_SOURCES = \
utils_debug.c \
utils_loop.c \
utils_loop.h \
utils_devpath.c \
libdevmapper.c \
volumekey.c \
random.c \

View File

@@ -90,8 +90,13 @@ int dm_suspend_and_wipe_key(const char *name);
int dm_resume_and_reinstate_key(const char *name,
size_t key_size,
const char *key);
char *dm_device_path(const char *dev_id);
int dm_is_dm_device(int major);
char *crypt_lookup_dev(const char *dev_id);
int sector_size_for_device(const char *device);
int device_read_ahead(const char *dev, uint32_t *read_ahead);
ssize_t write_blockwise(int fd, void *buf, size_t count);
ssize_t read_blockwise(int fd, void *_buf, size_t count);
ssize_t write_lseek_blockwise(int fd, char *buf, size_t count, off_t offset);

View File

@@ -19,8 +19,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <dirent.h>
#include <errno.h>
@@ -32,7 +30,6 @@
#include "internal.h"
#include "luks.h"
#define DEVICE_DIR "/dev"
#define DM_UUID_LEN 129
#define DM_UUID_PREFIX "CRYPT-"
#define DM_UUID_PREFIX_LEN 6
@@ -208,90 +205,8 @@ void dm_exit(void)
}
}
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;
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 && !strncmp(entry->d_name, "dm-", 3))
continue;
if (st.st_rdev == dev) {
result = strdup(path);
break;
}
}
}
closedir(dir);
return result;
}
static char *lookup_dev_old(const char *dev_id)
{
uint32_t major, minor;
dev_t dev;
char *result = NULL, buf[PATH_MAX + 1];
if (sscanf(dev_id, "%" PRIu32 ":%" PRIu32, &major, &minor) != 2)
return NULL;
dev = makedev(major, minor);
strncpy(buf, DEVICE_DIR, PATH_MAX);
buf[PATH_MAX] = '\0';
/* First try low level device */
if ((result = __lookup_dev(buf, dev, 0, 0)))
return result;
/* If it is dm, try DM dir */
if (dm_is_dm_major(major)) {
strncpy(buf, dm_dir(), PATH_MAX);
if ((result = __lookup_dev(buf, dev, 0, 0)))
return result;
}
strncpy(buf, DEVICE_DIR, PATH_MAX);
result = __lookup_dev(buf, dev, 0, 4);
/* If not found, return NULL */
return result;
}
/* Return path to DM device */
static char *dm_device_path(const char *dev_id)
char *dm_device_path(const char *dev_id)
{
int major, minor;
struct dm_task *dmt;
@@ -319,54 +234,6 @@ static char *dm_device_path(const char *dev_id)
return strdup(path);
}
static char *lookup_dev(const char *dev_id)
{
char link[PATH_MAX], path[PATH_MAX], *devname;
struct stat st;
ssize_t len;
if (snprintf(path, sizeof(path), "/sys/dev/block/%s", dev_id) < 0)
return NULL;
len = readlink(path, link, sizeof(link));
if (len < 0) {
if (stat("/sys/dev/block", &st) < 0)
return lookup_dev_old(dev_id);
return NULL;
}
link[len] = '\0';
devname = strrchr(link, '/');
if (!devname)
return NULL;
devname++;
if (!strncmp(devname, "dm-", 3))
return dm_device_path(dev_id);
if (snprintf(path, sizeof(path), "/dev/%s", devname) < 0)
return NULL;
return strdup(path);
}
static int _dev_read_ahead(const char *dev, uint32_t *read_ahead)
{
int fd, r = 0;
long read_ahead_long;
if ((fd = open(dev, O_RDONLY)) < 0)
return 0;
r = ioctl(fd, BLKRAGET, &read_ahead_long) ? 0 : 1;
close(fd);
if (r)
*read_ahead = (uint32_t) read_ahead_long;
return r;
}
static void hex_key(char *hexkey, size_t key_size, const char *key)
{
unsigned i;
@@ -593,7 +460,7 @@ int dm_create_device(const char *name,
goto out_no_removal;
#ifdef DM_READ_AHEAD_MINIMUM_FLAG
if (_dev_read_ahead(device, &read_ahead) &&
if (device_read_ahead(device, &read_ahead) &&
!dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG))
goto out_no_removal;
#endif
@@ -757,7 +624,7 @@ int dm_query_device(const char *name,
/* device */
rdevice = strsep(&params, " ");
if (device)
*device = lookup_dev(rdevice);
*device = crypt_lookup_dev(rdevice);
/*offset */
if (!params)
@@ -891,3 +758,8 @@ const char *dm_get_dir(void)
{
return dm_dir();
}
int dm_is_dm_device(int major)
{
return dm_is_dm_major((uint32_t)major);
}

View File

@@ -108,6 +108,24 @@ static void *aligned_malloc(void **base, int size, int alignment)
return ptr;
#endif
}
int device_read_ahead(const char *dev, uint32_t *read_ahead)
{
int fd, r = 0;
long read_ahead_long;
if ((fd = open(dev, O_RDONLY)) < 0)
return 0;
r = ioctl(fd, BLKRAGET, &read_ahead_long) ? 0 : 1;
close(fd);
if (r)
*read_ahead = (uint32_t) read_ahead_long;
return r;
}
static int sector_size(int fd)
{
int bsize;

142
lib/utils_devpath.c Normal file
View File

@@ -0,0 +1,142 @@
/*
* devname - search for device name
*
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2011, Red Hat, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "internal.h"
#define DEVICE_DIR "/dev"
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;
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 && !strncmp(entry->d_name, "dm-", 3))
continue;
if (st.st_rdev == dev) {
result = strdup(path);
break;
}
}
}
closedir(dir);
return result;
}
static char *lookup_dev_old(const char *dev_id)
{
int major, minor;
dev_t dev;
char *result = NULL, buf[PATH_MAX + 1];
if (sscanf(dev_id, "%d:%d", &major, &minor) != 2)
return NULL;
dev = makedev(major, minor);
strncpy(buf, DEVICE_DIR, PATH_MAX);
buf[PATH_MAX] = '\0';
/* First try low level device */
if ((result = __lookup_dev(buf, dev, 0, 0)))
return result;
/* If it is dm, try DM dir */
if (dm_is_dm_device(major)) {
strncpy(buf, dm_get_dir(), PATH_MAX);
if ((result = __lookup_dev(buf, dev, 0, 0)))
return result;
}
strncpy(buf, DEVICE_DIR, PATH_MAX);
result = __lookup_dev(buf, dev, 0, 4);
/* If not found, return NULL */
return result;
}
char *crypt_lookup_dev(const char *dev_id)
{
char link[PATH_MAX], path[PATH_MAX], *devname;
struct stat st;
ssize_t len;
if (snprintf(path, sizeof(path), "/sys/dev/block/%s", dev_id) < 0)
return NULL;
len = readlink(path, link, sizeof(link));
if (len < 0) {
if (stat("/sys/dev/block", &st) < 0)
return lookup_dev_old(dev_id);
return NULL;
}
link[len] = '\0';
devname = strrchr(link, '/');
if (!devname)
return NULL;
devname++;
if (!strncmp(devname, "dm-", 3))
return dm_device_path(dev_id);
if (snprintf(path, sizeof(path), "/dev/%s", devname) < 0)
return NULL;
return strdup(path);
}