X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Futils_loop.c;h=6a4e11f4380b8e49d2d5210d7e4c2bbd7d7b4ed8;hb=911ffe81f04e3da033a429061e17b54fa9214503;hp=d628470db0886387d1909583215a600327f50070;hpb=01e03f7002ab0f0b8f576e8e4282d9f428ed9c4c;p=platform%2Fupstream%2Fcryptsetup.git diff --git a/lib/utils_loop.c b/lib/utils_loop.c index d628470..6a4e11f 100644 --- a/lib/utils_loop.c +++ b/lib/utils_loop.c @@ -1,7 +1,7 @@ /* * loopback block device utilities * - * Copyright (C) 2011, Red Hat, Inc. All rights reserved. + * Copyright (C) 2011-2012, 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 @@ -14,7 +14,7 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include @@ -22,13 +22,24 @@ #include #include #include +#include #include #include #include #include "utils_loop.h" -char *crypt_loop_get_device(void) +#define LOOP_DEV_MAJOR 7 + +#ifndef LO_FLAGS_AUTOCLEAR +#define LO_FLAGS_AUTOCLEAR 4 +#endif + +#ifndef LOOP_CTL_GET_FREE +#define LOOP_CTL_GET_FREE 0x4C82 +#endif + +static char *crypt_loop_get_device_old(void) { char dev[20]; int i, loop_fd; @@ -55,6 +66,32 @@ char *crypt_loop_get_device(void) return NULL; } +char *crypt_loop_get_device(void) +{ + char dev[64]; + int i, loop_fd; + struct stat st; + + loop_fd = open("/dev/loop-control", O_RDONLY); + if (loop_fd < 0) + return crypt_loop_get_device_old(); + + i = ioctl(loop_fd, LOOP_CTL_GET_FREE); + if (i < 0) { + close(loop_fd); + return NULL; + } + close(loop_fd); + + if (sprintf(dev, "/dev/loop%d", i) < 0) + return NULL; + + if (stat(dev, &st) || !S_ISBLK(st.st_mode)) + return NULL; + + return strdup(dev); +} + int crypt_loop_attach(const char *loop, const char *file, int offset, int autoclear, int *readonly) { @@ -62,7 +99,7 @@ int crypt_loop_attach(const char *loop, const char *file, int offset, int loop_fd = -1, file_fd = -1, r = 1; file_fd = open(file, (*readonly ? O_RDONLY : O_RDWR) | O_EXCL); - if (file_fd < 0 && errno == EROFS && !*readonly) { + if (file_fd < 0 && (errno == EROFS || errno == EACCES) && !*readonly) { *readonly = 1; file_fd = open(file, O_RDONLY | O_EXCL); } @@ -120,7 +157,7 @@ int crypt_loop_detach(const char *loop) return r; } -char *crypt_loop_backing_file(const char *loop) +static char *_ioctl_backing_file(const char *loop) { struct loop_info64 lo64 = {0}; int loop_fd; @@ -142,6 +179,38 @@ char *crypt_loop_backing_file(const char *loop) return strdup((char*)lo64.lo_file_name); } +static char *_sysfs_backing_file(const char *loop) +{ + struct stat st; + char buf[PATH_MAX]; + size_t len; + int fd; + + if (stat(loop, &st) || !S_ISBLK(st.st_mode)) + return NULL; + + snprintf(buf, sizeof(buf), "/sys/dev/block/%d:%d/loop/backing_file", + major(st.st_rdev), minor(st.st_rdev)); + + fd = open(buf, O_RDONLY); + if (fd < 0) + return NULL; + + len = read(fd, buf, PATH_MAX); + close(fd); + if (len < 2) + return NULL; + + buf[len - 1] = '\0'; + return strdup(buf); +} + +char *crypt_loop_backing_file(const char *loop) +{ + char *bf = _sysfs_backing_file(loop); + return bf ?: _ioctl_backing_file(loop); +} + int crypt_loop_device(const char *loop) { struct stat st;