Bump to version 1.22.1
[platform/upstream/busybox.git] / libbb / loop.c
index 7a551a4..823fba0 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
  * Copyright (C) 2005 by Rob Landley <rob@landley.net>
  *
- * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  */
 #include "libbb.h"
 #include <linux/version.h>
@@ -13,7 +13,8 @@
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 
 /* For 2.6, use the cleaned up header to get the 64 bit API. */
-# include "fix_u32.h" /* some old toolchains need __u64 for linux/loop.h */
+// Commented out per Rob's request
+//# include "fix_u32.h" /* some old toolchains need __u64 for linux/loop.h */
 # include <linux/loop.h>
 typedef struct loop_info64 bb_loop_info;
 # define BB_LOOP_SET_STATUS LOOP_SET_STATUS64
@@ -55,7 +56,7 @@ char* FAST_FUNC query_loop(const char *device)
        fd = open(device, O_RDONLY);
        if (fd >= 0) {
                if (ioctl(fd, BB_LOOP_GET_STATUS, &loopinfo) == 0) {
-                       dev = xasprintf("%lu %s", (long) loopinfo.lo_offset,
+                       dev = xasprintf("%"OFF_FMT"u %s", (off_t) loopinfo.lo_offset,
                                        (char *)loopinfo.lo_file_name);
                }
                close(fd);
@@ -83,7 +84,7 @@ int FAST_FUNC del_loop(const char *device)
    search will re-use an existing loop device already bound to that
    file/offset if it finds one.
  */
-int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offset)
+int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offset, int ro)
 {
        char dev[LOOP_NAMESIZE];
        char *try;
@@ -92,25 +93,38 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
        int i, dfd, ffd, mode, rc = -1;
 
        /* Open the file.  Barf if this doesn't work.  */
-       mode = O_RDWR;
+       mode = ro ? O_RDONLY : O_RDWR;
        ffd = open(file, mode);
        if (ffd < 0) {
-               mode = O_RDONLY;
-               ffd = open(file, mode);
+               if (mode != O_RDONLY) {
+                       mode = O_RDONLY;
+                       ffd = open(file, mode);
+               }
                if (ffd < 0)
                        return -errno;
        }
 
        /* Find a loop device.  */
        try = *device ? *device : dev;
-       for (i = 0; rc; i++) {
+       /* 1048575 is a max possible minor number in Linux circa 2010 */
+       for (i = 0; rc && i < 1048576; i++) {
                sprintf(dev, LOOP_FORMAT, i);
 
-               /* Ran out of block devices, return failure.  */
+               IF_FEATURE_MOUNT_LOOP_CREATE(errno = 0;)
                if (stat(try, &statbuf) != 0 || !S_ISBLK(statbuf.st_mode)) {
+                       if (ENABLE_FEATURE_MOUNT_LOOP_CREATE
+                        && errno == ENOENT
+                        && try == dev
+                       ) {
+                               /* Node doesn't exist, try to create it.  */
+                               if (mknod(dev, S_IFBLK|0644, makedev(7, i)) == 0)
+                                       goto try_to_open;
+                       }
+                       /* Ran out of block devices, return failure.  */
                        rc = -ENOENT;
                        break;
                }
+ try_to_open:
                /* Open the sucker and check its loopiness.  */
                dfd = open(try, mode);
                if (dfd < 0 && errno == EROFS) {
@@ -136,9 +150,9 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
                        }
 
                /* If this block device already set up right, re-use it.
-                  (Yes this is racy, but associating two loop devices with the same
-                  file isn't pretty either.  In general, mounting the same file twice
-                  without using losetup manually is problematic.)
+                * (Yes this is racy, but associating two loop devices with the same
+                * file isn't pretty either.  In general, mounting the same file twice
+                * without using losetup manually is problematic.)
                 */
                } else
                if (strcmp(file, (char *)loopinfo.lo_file_name) != 0