}
/* Keep the loop open, dettached on last close. */
- h->loop_fd = crypt_loop_attach(h->device, device, 0, &readonly);
+ h->loop_fd = crypt_loop_attach(h->device, device, 0, 1, &readonly);
if (h->loop_fd == -1) {
log_err(NULL, _("Attaching loopback device failed "
"(loop device with autoclear flag is required).\n"));
struct stat st;
struct loop_info64 lo64 = {0};
- for(i = 0; i < 256; i++) {
+ for (i = 0; i < 256; i++) {
sprintf(dev, "/dev/loop%d", i);
if (stat(dev, &st) || !S_ISBLK(st.st_mode))
return NULL;
if (loop_fd < 0)
return NULL;
- if(ioctl(loop_fd, LOOP_GET_STATUS64, &lo64) && errno == ENXIO) {
+ if (ioctl(loop_fd, LOOP_GET_STATUS64, &lo64) &&
+ errno == ENXIO) {
close(loop_fd);
return strdup(dev);
}
return NULL;
}
-int crypt_loop_attach(const char *loop, const char *file,
- int offset, int *readonly)
+int crypt_loop_attach(const char *loop, const char *file, int offset,
+ int autoclear, int *readonly)
{
struct loop_info64 lo64 = {0};
int loop_fd = -1, file_fd = -1, r = 1;
strncpy((char*)lo64.lo_file_name, file, LO_NAME_SIZE);
lo64.lo_offset = offset;
- lo64.lo_flags |= LO_FLAGS_AUTOCLEAR;
+ if (autoclear)
+ lo64.lo_flags |= LO_FLAGS_AUTOCLEAR;
if (ioctl(loop_fd, LOOP_SET_FD, file_fd) < 0)
goto out;
}
/* Verify that autoclear is really set */
- memset(&lo64, 0, sizeof(lo64));
- if (ioctl(loop_fd, LOOP_GET_STATUS64, &lo64) < 0 ||
- !(lo64.lo_flags & LO_FLAGS_AUTOCLEAR)) {
+ if (autoclear) {
+ memset(&lo64, 0, sizeof(lo64));
+ if (ioctl(loop_fd, LOOP_GET_STATUS64, &lo64) < 0 ||
+ !(lo64.lo_flags & LO_FLAGS_AUTOCLEAR)) {
(void)ioctl(loop_fd, LOOP_CLR_FD, 0);
- goto out;
+ goto out;
+ }
}
r = 0;
return r ? -1 : loop_fd;
}
+int crypt_loop_detach(const char *loop)
+{
+ int loop_fd = -1, r = 1;
+
+ loop_fd = open(loop, O_RDONLY);
+ if (loop_fd < 0)
+ return 1;
+
+ if (!ioctl(loop_fd, LOOP_CLR_FD, 0))
+ r = 0;
+
+ close(loop_fd);
+ return r;
+}
+
char *crypt_loop_backing_file(const char *loop)
{
struct loop_info64 lo64 = {0};
{
struct stat st;
+ if (!loop)
+ return 0;
+
if (stat(loop, &st) || !S_ISBLK(st.st_mode) ||
major(st.st_rdev) != LOOP_DEV_MAJOR)
return 0;
char *crypt_loop_get_device(void);
char *crypt_loop_backing_file(const char *loop);
int crypt_loop_device(const char *loop);
-int crypt_loop_attach(const char *loop, const char *file, int offset, int *readonly);
+int crypt_loop_attach(const char *loop, const char *file, int offset,
+ int autoclear, int *readonly);
+int crypt_loop_detach(const char *loop);
-#endif /* _UTILS_CRYPT_H */
+#endif /* _UTILS_LOOP_H */
differ_SOURCES = differ.c
differ_CFLAGS = -Wall -O2
-api_test_SOURCES = api-test.c
+api_test_SOURCES = api-test.c $(top_srcdir)/lib/utils_loop.c
api_test_LDADD = ../lib/libcryptsetup.la
api_test_LDFLAGS = -static
api_test_CFLAGS = -g -Wall -O0 -I$(top_srcdir)/lib/
#include <linux/loop.h>
#include "libcryptsetup.h"
+#include "utils_loop.h"
#define DMDIR "/dev/mapper/"
remove(KEYFILE2);
}
-char *_get_loop_device(void)
-{
- char dev[20];
- int i, loop_fd;
- struct stat st;
- struct loop_info64 lo64 = {0};
-
- for ( i = 0; i < 256; i++ ) {
- sprintf ( dev, "/dev/loop%d", i );
- if ( stat ( dev, &st ) || !S_ISBLK ( st.st_mode ) )
- goto bad;
-
- loop_fd = open ( dev, O_RDONLY );
- if ( loop_fd < 0 )
- goto bad;
-
- if ( ioctl ( loop_fd, LOOP_GET_STATUS64, &lo64 ) && errno == ENXIO ) {
- close ( loop_fd );
- return strdup ( dev );
- }
- close ( loop_fd );
- }
-bad:
- printf("Cannot find free loop device.\n");
- return NULL;
-}
-
// Decode key from its hex representation
static int crypt_decode_key(char *key, char *hex, unsigned int size)
{
static void _cleanup(void)
{
struct stat st;
- char tmp[256];
//_system("udevadm settle", 0);
if (!stat(DEVICE_ERROR, &st))
_system("dmsetup remove " DEVICE_ERROR_name, 0);
- // FIXME: use internel loop lib when available
- if (DEVICE_1 && !strncmp("/dev/loop", DEVICE_1, 9)) {
- snprintf(tmp, sizeof(tmp), "losetup -d %s", DEVICE_1);
- _system(tmp, 0);
- }
+ if (crypt_loop_device(DEVICE_1))
+ crypt_loop_detach(DEVICE_1);
- if (DEVICE_2 && !strncmp("/dev/loop", DEVICE_2, 9)) {
- snprintf(tmp, sizeof(tmp), "losetup -d %s", DEVICE_2);
- _system(tmp, 0);
- }
+ if (crypt_loop_device(DEVICE_2))
+ crypt_loop_detach(DEVICE_2);
_system("rm -f " IMAGE_EMPTY, 0);
_remove_keyfiles();
static int _setup(void)
{
- char tmp[256];
+ int fd, ro = 0;
_system("dmsetup create " DEVICE_EMPTY_name " --table \"0 10000 zero\"", 1);
_system("dmsetup create " DEVICE_ERROR_name " --table \"0 10000 error\"", 1);
if (!DEVICE_1)
- DEVICE_1 = _get_loop_device();
- if (!DEVICE_1)
+ DEVICE_1 = crypt_loop_get_device();
+ if (!DEVICE_1) {
+ printf("Cannot find free loop device.\n");
return 1;
- if (!strncmp("/dev/loop", DEVICE_1, 9)) {
+ }
+ if (crypt_loop_device(DEVICE_1)) {
_system(" [ ! -e " IMAGE1 " ] && bzip2 -dk " IMAGE1 ".bz2", 1);
- snprintf(tmp, sizeof(tmp), "losetup %s %s", DEVICE_1, IMAGE1);
- _system(tmp, 1);
+ fd = crypt_loop_attach(DEVICE_1, IMAGE1, 0, 0, &ro);
+ close(fd);
}
if (!DEVICE_2)
- DEVICE_2 = _get_loop_device();
- if (!DEVICE_2)
+ DEVICE_2 = crypt_loop_get_device();
+ if (!DEVICE_2) {
+ printf("Cannot find free loop device.\n");
return 1;
- if (!strncmp("/dev/loop", DEVICE_2, 9)) {
+ }
+ if (crypt_loop_device(DEVICE_2)) {
_system("dd if=/dev/zero of=" IMAGE_EMPTY " bs=1M count=4", 1);
- snprintf(tmp, sizeof(tmp), "losetup %s %s", DEVICE_2, IMAGE_EMPTY);
- _system(tmp, 1);
+ fd = crypt_loop_attach(DEVICE_2, IMAGE_EMPTY, 0, 0, &ro);
+ close(fd);
}
return 0;
}