lineedit: do not hang on error, but return error indicator.
[oweals/busybox.git] / libbb / loop.c
index a11933f35e81d486fa980fa3d380130d18235c28..b798932faf66aa0e68a8bb4095f9daf74dc26b2b 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>
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 
 /* For 2.6, use the cleaned up header to get the 64 bit API. */
-/* linux/loop.h relies on __u64. Make sure we have that as a proper type
- * until userspace is widely fixed. */
-# if (defined __INTEL_COMPILER && !defined __GNUC__) \
-  || (defined __GNUC__ && defined __STRICT_ANSI__)
-__extension__ typedef long long __s64;
-__extension__ typedef unsigned long long __u64;
-# endif
+// 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
@@ -61,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);
@@ -109,14 +104,25 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
 
        /* 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) {