Index: klibc-1.5/usr/utils/losetup.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc-1.5/usr/utils/losetup.c	2008-03-07 23:13:38.635692852 +0100
@@ -0,0 +1,485 @@
+/* Originally from Ted's losetup.c */
+
+#define LOOPMAJOR	7
+
+/*
+ * losetup.c - setup and control loop devices
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/sysmacros.h>
+#include <string.h>
+
+#include "loop.h"
+
+extern int verbose;
+extern char *progname;
+extern char *xstrdup (const char *s);	/* not: #include "sundries.h" */
+extern void error (const char *fmt, ...);	/* idem */
+
+/* caller guarantees n > 0 */
+void
+xstrncpy(char *dest, const char *src, size_t n) {
+        strncpy(dest, src, n-1);
+        dest[n-1] = 0;
+}
+
+
+static int
+loop_info64_to_old(const struct loop_info64 *info64, struct loop_info *info)
+{
+        memset(info, 0, sizeof(*info));
+        info->lo_number = info64->lo_number;
+        info->lo_device = info64->lo_device;
+        info->lo_inode = info64->lo_inode;
+        info->lo_rdevice = info64->lo_rdevice;
+        info->lo_offset = info64->lo_offset;
+        info->lo_encrypt_type = info64->lo_encrypt_type;
+        info->lo_encrypt_key_size = info64->lo_encrypt_key_size;
+        info->lo_flags = info64->lo_flags;
+        info->lo_init[0] = info64->lo_init[0];
+        info->lo_init[1] = info64->lo_init[1];
+        if (info->lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
+                memcpy(info->lo_name, info64->lo_crypt_name, LO_NAME_SIZE);
+        else
+                memcpy(info->lo_name, info64->lo_file_name, LO_NAME_SIZE);
+        memcpy(info->lo_encrypt_key, info64->lo_encrypt_key, LO_KEY_SIZE);
+
+        /* error in case values were truncated */
+        if (info->lo_device != info64->lo_device ||
+            info->lo_rdevice != info64->lo_rdevice ||
+            info->lo_inode != info64->lo_inode ||
+            info->lo_offset != info64->lo_offset)
+                return -EOVERFLOW;
+
+        return 0;
+}
+
+
+static int
+show_loop(char *device) {
+	struct loop_info loopinfo;
+	struct loop_info64 loopinfo64;
+	int fd, errsv;
+
+	if ((fd = open(device, O_RDONLY)) < 0) {
+		int errsv = errno;
+		fprintf(stderr, "loop: can't open device %s: %s\n",
+			device, strerror (errsv));
+		return 2;
+	}
+
+	if (ioctl(fd, LOOP_GET_STATUS64, &loopinfo64) == 0) {
+
+		loopinfo64.lo_file_name[LO_NAME_SIZE-2] = '*';
+		loopinfo64.lo_file_name[LO_NAME_SIZE-1] = 0;
+		loopinfo64.lo_crypt_name[LO_NAME_SIZE-1] = 0;
+
+		printf("%s: [%04llx]:%llu (%s)",
+		       device, loopinfo64.lo_device, loopinfo64.lo_inode,
+		       loopinfo64.lo_file_name);
+
+		if (loopinfo64.lo_offset)
+			printf(", offset %lld", loopinfo64.lo_offset);
+
+		if (loopinfo64.lo_sizelimit)
+			printf(", sizelimit %lld", loopinfo64.lo_sizelimit);
+
+		if (loopinfo64.lo_encrypt_type ||
+		    loopinfo64.lo_crypt_name[0]) {
+			char *e = loopinfo64.lo_crypt_name;
+
+			if (*e == 0 && loopinfo64.lo_encrypt_type == 1)
+				e = "XOR";
+			printf(", encryption %s (type %d)",
+			       e, loopinfo64.lo_encrypt_type);
+		}
+		printf("\n");
+		close (fd);
+		return 0;
+	}
+
+	if (ioctl(fd, LOOP_GET_STATUS, &loopinfo) == 0) {
+		printf ("%s: [%04x]:%ld (%s)",
+			device, loopinfo.lo_device, loopinfo.lo_inode,
+			loopinfo.lo_name);
+
+		if (loopinfo.lo_offset)
+			printf(", offset %d", loopinfo.lo_offset);
+
+		if (loopinfo.lo_encrypt_type)
+			printf(", encryption type %d\n",
+			       loopinfo.lo_encrypt_type);
+
+		printf("\n");
+		close (fd);
+		return 0;
+	}
+
+	errsv = errno;
+	fprintf(stderr, "loop: can't get info on device %s: %s\n",
+		device, strerror (errsv));
+	close (fd);
+	return 1;
+}
+
+int
+is_loop_device (const char *device) {
+	struct stat statbuf;
+
+	return (stat(device, &statbuf) == 0 &&
+		S_ISBLK(statbuf.st_mode) &&
+		major(statbuf.st_rdev) == LOOPMAJOR);
+}
+
+#define SIZE(a) (sizeof(a)/sizeof(a[0]))
+
+char *
+find_unused_loop_device (void) {
+	/* Just creating a device, say in /tmp, is probably a bad idea -
+	   people might have problems with backup or so.
+	   So, we just try /dev/loop[0-7]. */
+	char dev[20];
+	char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" };
+	int i, j, fd, somedev = 0, someloop = 0, permission = 0;
+	struct stat statbuf;
+	struct loop_info loopinfo;
+
+	for (j = 0; j < SIZE(loop_formats); j++) {
+	    for(i = 0; i < 256; i++) {
+		sprintf(dev, loop_formats[j], i);
+		if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
+			somedev++;
+			fd = open (dev, O_RDONLY);
+			if (fd >= 0) {
+				if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0)
+					someloop++;		/* in use */
+				else if (errno == ENXIO) {
+					close (fd);
+					return xstrdup(dev);/* probably free */
+				}
+				close (fd);
+			} else if (errno == EACCES)
+				permission++;
+
+			continue;/* continue trying as long as devices exist */
+		}
+		break;
+	    }
+	}
+
+	if (!somedev)
+		error("%s: could not find any device /dev/loop#", progname);
+	else if (!someloop && permission)
+		error("%s: no permission to look at /dev/loop#", progname);
+	else if (!someloop)
+		error(
+		    "%s: Could not find any loop device. Maybe this kernel "
+		    "does not know\n"
+		    "       about the loop device? (If so, recompile or "
+		    "`modprobe loop'.)", progname);
+	else
+		error("%s: could not find any free loop device", progname);
+	return 0;
+}
+
+/*
+ * A function to read the passphrase either from the terminal or from
+ * an open file descriptor.
+ */
+static char *
+xgetpass(int pfd, const char *prompt) {
+	char *pass;
+	int buflen, i;
+
+	pass = NULL;
+	buflen = 0;
+	for (i=0; ; i++) {
+		if (i >= buflen-1) {
+				/* we're running out of space in the buffer.
+				 * Make it bigger: */
+			char *tmppass = pass;
+			buflen += 128;
+			pass = realloc(tmppass, buflen);
+			if (pass == NULL) {
+				/* realloc failed. Stop reading. */
+				error("Out of memory while reading passphrase");
+				pass = tmppass; /* the old buffer hasn't changed */
+				break;
+			}
+		}
+		if (read(pfd, pass+i, 1) != 1 ||
+		    pass[i] == '\n' || pass[i] == 0)
+			break;
+	}
+
+	if (pass == NULL)
+		return "";
+
+	pass[i] = 0;
+	return pass;
+}
+
+static int
+digits_only(const char *s) {
+	while (*s)
+		if (!isdigit(*s++))
+			return 0;
+	return 1;
+}
+
+int
+set_loop(const char *device, const char *file, unsigned long long offset,
+	 const char *encryption, int pfd, int *loopro) {
+	struct loop_info64 loopinfo64;
+	int fd, ffd, mode, i;
+	char *pass;
+
+	mode = (*loopro ? O_RDONLY : O_RDWR);
+	if ((ffd = open(file, mode)) < 0) {
+		if (!*loopro && errno == EROFS)
+			ffd = open(file, mode = O_RDONLY);
+		if (ffd < 0) {
+			perror(file);
+			return 1;
+		}
+	}
+	if ((fd = open(device, mode)) < 0) {
+		perror (device);
+		return 1;
+	}
+	*loopro = (mode == O_RDONLY);
+
+	memset(&loopinfo64, 0, sizeof(loopinfo64));
+
+	xstrncpy(loopinfo64.lo_file_name, file, LO_NAME_SIZE);
+
+	if (encryption && *encryption) {
+		if (digits_only(encryption)) {
+			loopinfo64.lo_encrypt_type = atoi(encryption);
+		} else {
+			loopinfo64.lo_encrypt_type = LO_CRYPT_CRYPTOAPI;
+			snprintf(loopinfo64.lo_crypt_name, LO_NAME_SIZE,
+				 "%s", encryption);
+		}
+	}
+
+	loopinfo64.lo_offset = offset;
+
+
+	switch (loopinfo64.lo_encrypt_type) {
+	case LO_CRYPT_NONE:
+		loopinfo64.lo_encrypt_key_size = 0;
+		break;
+	case LO_CRYPT_XOR:
+		pass = xgetpass(pfd, "Password: ");
+		goto gotpass;
+	default:
+		pass = xgetpass(pfd, "Password: ");
+	gotpass:
+		memset(loopinfo64.lo_encrypt_key, 0, LO_KEY_SIZE);
+		xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE);
+		memset(pass, 0, strlen(pass));
+		loopinfo64.lo_encrypt_key_size = LO_KEY_SIZE;
+	}
+
+	if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
+		perror("ioctl: LOOP_SET_FD");
+		return 1;
+	}
+	close (ffd);
+
+	i = ioctl(fd, LOOP_SET_STATUS64, &loopinfo64);
+	if (i) {
+		struct loop_info loopinfo;
+		int errsv = errno;
+
+		i = loop_info64_to_old(&loopinfo64, &loopinfo);
+		if (i) {
+			errno = errsv;
+			perror("ioctl: LOOP_SET_STATUS64");
+		} else {
+			i = ioctl(fd, LOOP_SET_STATUS, &loopinfo);
+			if (i)
+				perror("ioctl: LOOP_SET_STATUS");
+		}
+		memset(&loopinfo, 0, sizeof(loopinfo));
+	}
+	memset(&loopinfo64, 0, sizeof(loopinfo64));
+
+	if (i) {
+		ioctl (fd, LOOP_CLR_FD, 0);
+		close (fd);
+		return 1;
+	}
+	close (fd);
+
+	if (verbose > 1)
+		printf("set_loop(%s,%s,%llu): success\n",
+		       device, file, offset);
+	return 0;
+}
+
+int
+del_loop (const char *device) {
+	int fd;
+
+	if ((fd = open (device, O_RDONLY)) < 0) {
+		int errsv = errno;
+		fprintf(stderr, "loop: can't delete device %s: %s\n",
+			device, strerror (errsv));
+		return 1;
+	}
+	if (ioctl (fd, LOOP_CLR_FD, 0) < 0) {
+		perror ("ioctl: LOOP_CLR_FD");
+		return 1;
+	}
+	close (fd);
+	if (verbose > 1)
+		printf("del_loop(%s): success\n", device);
+	return 0;
+}
+
+
+#include <getopt.h>
+#include <stdarg.h>
+
+int verbose = 0;
+char *progname;
+
+static void
+usage(void) {
+	fprintf(stderr, "usage:\n\
+  %s loop_device                                       # give info\n\
+  %s -d loop_device                                    # delete\n\
+  %s -f                                                # find unused\n\
+  %s [-e encryption] [-o offset] {-f|loop_device} file # setup\n",
+		progname, progname, progname, progname);
+	exit(1);
+}
+
+char *
+xstrdup (const char *s) {
+	char *t;
+
+	if (s == NULL)
+		return NULL;
+
+	t = strdup (s);
+
+	if (t == NULL) {
+		fprintf(stderr, "not enough memory");
+		exit(1);
+	}
+
+	return t;
+}
+
+void
+error (const char *fmt, ...) {
+	va_list args;
+
+	va_start (args, fmt);
+	vfprintf (stderr, fmt, args);
+	va_end (args);
+	fprintf (stderr, "\n");
+}
+
+int
+main(int argc, char **argv) {
+	char *p, *offset, *encryption, *passfd, *device, *file;
+	int delete, find, c;
+	int res = 0;
+	int ro = 0;
+	int pfd = -1;
+	unsigned long long off;
+
+
+	delete = find = 0;
+	off = 0;
+	offset = encryption = passfd = NULL;
+
+	progname = argv[0];
+	if ((p = strrchr(progname, '/')) != NULL)
+		progname = p+1;
+
+	while ((c = getopt(argc, argv, "de:E:fo:p:v")) != -1) {
+		switch (c) {
+		case 'd':
+			delete = 1;
+			break;
+		case 'E':
+		case 'e':
+			encryption = optarg;
+			break;
+		case 'f':
+			find = 1;
+			break;
+		case 'o':
+			offset = optarg;
+			break;
+		case 'p':
+			passfd = optarg;
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		default:
+			usage();
+		}
+	}
+
+	if (argc == 1) {
+		usage();
+	} else if (delete) {
+		if (argc != optind+1 || encryption || offset || find)
+			usage();
+	} else if (find) {
+		if (argc < optind || argc > optind+1)
+			usage();
+	} else {
+		if (argc < optind+1 || argc > optind+2)
+			usage();
+	}
+
+	if (find) {
+		device = find_unused_loop_device();
+		if (device == NULL)
+			return -1;
+		if (verbose)
+			printf("Loop device is %s\n", device);
+		if (argc == optind) {
+			printf("%s\n", device);
+			return 0;
+		}
+		file = argv[optind];
+	} else {
+		device = argv[optind];
+		if (argc == optind+1)
+			file = NULL;
+		else
+			file = argv[optind+1];
+	}
+
+	if (delete)
+		res = del_loop(device);
+	else if (file == NULL)
+		res = show_loop(device);
+	else {
+		if (offset && sscanf(offset, "%llu", &off) != 1)
+			usage();
+		if (passfd && sscanf(passfd, "%d", &pfd) != 1)
+			usage();
+		res = set_loop(device, file, off, encryption, pfd, &ro);
+	}
+	return res;
+}
Index: klibc-1.5/usr/utils/loop.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc-1.5/usr/utils/loop.h	2008-03-07 23:01:49.336694297 +0100
@@ -0,0 +1,51 @@
+#define LO_CRYPT_NONE	0
+#define LO_CRYPT_XOR	1
+#define LO_CRYPT_DES	2
+#define LO_CRYPT_CRYPTOAPI 18
+
+#define LOOP_SET_FD		0x4C00
+#define LOOP_CLR_FD		0x4C01
+#define LOOP_SET_STATUS		0x4C02
+#define LOOP_GET_STATUS		0x4C03
+#define LOOP_SET_STATUS64	0x4C04
+#define LOOP_GET_STATUS64	0x4C05
+
+#define LO_NAME_SIZE	64
+#define LO_KEY_SIZE	32
+
+#include "my_dev_t.h"
+
+struct loop_info {
+	int		lo_number;
+	my_dev_t	lo_device;
+	unsigned long	lo_inode;
+	my_dev_t	lo_rdevice;
+	int		lo_offset;
+	int		lo_encrypt_type;
+	int		lo_encrypt_key_size;
+	int		lo_flags;
+	char		lo_name[LO_NAME_SIZE];
+	unsigned char	lo_encrypt_key[LO_KEY_SIZE];
+	unsigned long	lo_init[2];
+	char		reserved[4];
+};
+
+/*
+ * Where to get __u8, __u32, __u64? Let us use unsigned char/int/long long
+ * and get punished when someone comes with 128-bit long longs.
+ */
+struct loop_info64 {
+	unsigned long long	lo_device;
+	unsigned long long	lo_inode;
+	unsigned long long	lo_rdevice;
+	unsigned long long	lo_offset;
+	unsigned long long	lo_sizelimit; /* bytes, 0 == max available */
+	unsigned int		lo_number;
+	unsigned int		lo_encrypt_type;
+	unsigned int		lo_encrypt_key_size;
+	unsigned int		lo_flags;
+	unsigned char		lo_file_name[LO_NAME_SIZE];
+	unsigned char		lo_crypt_name[LO_NAME_SIZE];
+	unsigned char		lo_encrypt_key[LO_KEY_SIZE];
+	unsigned long long	lo_init[2];
+};
Index: klibc-1.5/usr/utils/my_dev_t.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ klibc-1.5/usr/utils/my_dev_t.h	2008-03-07 23:03:45.148693283 +0100
@@ -0,0 +1,20 @@
+/* silliness to get dev_t defined as the kernel defines it */
+/* glibc uses a different dev_t */
+
+#include <linux/posix_types.h>
+#include <linux/version.h>
+
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(1,3,78)
+/* for i386 - alpha uses unsigned int */
+#define my_dev_t unsigned short
+#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)
+#define my_dev_t __kernel_dev_t
+#else
+#define my_dev_t __kernel_old_dev_t
+#endif
+#endif