mount and umount could leak loop device allocations causing the system to
authorErik Andersen <andersen@codepoet.org>
Wed, 26 Jan 2000 20:06:48 +0000 (20:06 -0000)
committerErik Andersen <andersen@codepoet.org>
Wed, 26 Jan 2000 20:06:48 +0000 (20:06 -0000)
quickly run out.  Also disable init's SIGHUP handler during shutdown.
 -Erik

Changelog
init.c
init/init.c
internal.h
mount.c
networking/ping.c
ping.c
umount.c
util-linux/mount.c
util-linux/umount.c
utility.c

index 4dbb46e..46b2a1f 100644 (file)
--- a/Changelog
+++ b/Changelog
            tail -f work only with a single file.  This reduced tail 
            from 6k to 2.4k.  The bigger/more featured tail can still be
            had by disabling BB_FEATURE_SIMPLE_TAIL in dusybox.defs.h
+       * Ping now falls back to doing the right thing if /etc/protocols
+           turns up missing.
+       * Fixed mount and umount.  Previously they could leak loop device 
+           allocations, causing the system to quickly run out.  Fix for umount
+           by Ben Collins <bcollins@debian.org>, and mount was fixed by me.
 
 
        -Erik Andersen
diff --git a/init.c b/init.c
index 5b80cc5..09540ff 100644 (file)
--- a/init.c
+++ b/init.c
@@ -359,6 +359,7 @@ static pid_t run(char* command,
        signal(SIGUSR2, SIG_DFL);
        signal(SIGINT, SIG_DFL);
        signal(SIGTERM, SIG_DFL);
+       signal(SIGHUP, SIG_DFL);
 
        if ((fd = device_open(terminal, O_RDWR)) < 0) {
            message(LOG|CONSOLE, "Bummer, can't open %s\r\n", terminal);
@@ -458,6 +459,9 @@ goodnight:
 #ifndef DEBUG_INIT
 static void shutdown_system(void)
 {
+    /* first disable our SIGHUP signal */
+    signal(SIGHUP, SIG_DFL);
+    
     /* Allow Ctrl-Alt-Del to reboot system. */
     reboot(RB_ENABLE_CAD);
     message(CONSOLE, "\r\nThe system is going down NOW !!\r\n");
index 5b80cc5..09540ff 100644 (file)
@@ -359,6 +359,7 @@ static pid_t run(char* command,
        signal(SIGUSR2, SIG_DFL);
        signal(SIGINT, SIG_DFL);
        signal(SIGTERM, SIG_DFL);
+       signal(SIGHUP, SIG_DFL);
 
        if ((fd = device_open(terminal, O_RDWR)) < 0) {
            message(LOG|CONSOLE, "Bummer, can't open %s\r\n", terminal);
@@ -458,6 +459,9 @@ goodnight:
 #ifndef DEBUG_INIT
 static void shutdown_system(void)
 {
+    /* first disable our SIGHUP signal */
+    signal(SIGHUP, SIG_DFL);
+    
     /* Allow Ctrl-Alt-Del to reboot system. */
     reboot(RB_ENABLE_CAD);
     message(CONSOLE, "\r\nThe system is going down NOW !!\r\n");
index 500a63e..9611c19 100644 (file)
@@ -175,6 +175,10 @@ extern int check_wildcard_match(const char* text, const char* pattern);
 extern long getNum (const char *cp);
 extern pid_t findInitPid();
 
+#if defined BB_FEATURE_MOUNT_LOOP
+extern int del_loop(const char *device);
+#endif
+
 #if defined BB_GUNZIP || defined BB_GZIP || defined BB_PRINTF || defined BB_TAIL
 extern void *xmalloc (size_t size);
 extern void error(char *msg);
diff --git a/mount.c b/mount.c
index 709c7fc..3c1568a 100644 (file)
--- a/mount.c
+++ b/mount.c
@@ -127,11 +127,11 @@ do_mount(char* specialfile, char* dir, char* filesystemtype,
            specialfile = find_unused_loop_device();
            if (specialfile == NULL) {
                fprintf(stderr, "Could not find a spare loop device\n");
-               exit(1);
+               return( FALSE);
            }
            if (set_loop (specialfile, lofile, 0, &loro)) {
                fprintf(stderr, "Could not setup loop device\n");
-               exit(1);
+               return( FALSE);
            }
            if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */
                fprintf(stderr, "WARNING: loop device is read-only\n");
@@ -141,15 +141,26 @@ do_mount(char* specialfile, char* dir, char* filesystemtype,
 #endif
        status=mount(specialfile, dir, filesystemtype, flags, string_flags);
     }
-#if defined BB_MTAB
+
+
+    /* If the mount was sucessful, do anything needed, then return TRUE */
     if (status == 0) {
-       if (useMtab==TRUE)
+
+#if defined BB_MTAB
+       if (useMtab==TRUE) {
            write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts);
-       return 0;
+       }
+#endif
+       return( TRUE);
+    }
+
+    /* Bummer.  mount failed.  Clean up */
+#if defined BB_FEATURE_MOUNT_LOOP
+    if (specialfile != NULL) {
+       del_loop(specialfile);
     }
-    else
 #endif
-       return(status);
+    return( FALSE);
 }
 
 
@@ -166,6 +177,75 @@ extern void whine_if_fstab_is_missing()
 #endif
 
 
+#if defined BB_FEATURE_MOUNT_LOOP
+static int set_loop(const char *device, const char *file, int offset, int *loopro)
+{
+       struct loop_info loopinfo;
+       int     fd, ffd, mode;
+       
+       mode = *loopro ? O_RDONLY : O_RDWR;
+       if ((ffd = open (file, mode)) < 0 && !*loopro
+           && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) {
+         perror (file);
+         return 1;
+       }
+       if ((fd = open (device, mode)) < 0) {
+         close(ffd);
+         perror (device);
+         return 1;
+       }
+       *loopro = (mode == O_RDONLY);
+
+       memset(&loopinfo, 0, sizeof(loopinfo));
+       strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
+       loopinfo.lo_name[LO_NAME_SIZE-1] = 0;
+
+       loopinfo.lo_offset = offset;
+
+       loopinfo.lo_encrypt_key_size = 0;
+       if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
+               perror("ioctl: LOOP_SET_FD");
+               close(fd);
+               close(ffd);
+               return 1;
+       }
+       if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
+               (void) ioctl(fd, LOOP_CLR_FD, 0);
+               perror("ioctl: LOOP_SET_STATUS");
+               close(fd);
+               close(ffd);
+               return 1;
+       }
+       close(fd);
+       close(ffd);
+       return 0;
+}
+
+char *find_unused_loop_device (void)
+{
+       char dev[20];
+       int i, fd;
+       struct stat statbuf;
+       struct loop_info loopinfo;
+
+       for(i = 0; i <= 7; i++) {
+           sprintf(dev, "/dev/loop%d", i);
+           if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
+               if ((fd = open (dev, O_RDONLY)) >= 0) {
+                   if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == -1) {
+                       if (errno == ENXIO) { /* probably free */
+                           close (fd);
+                           return strdup(dev);
+                       }
+                   }
+                   close (fd);
+               }
+           }
+       }
+        return NULL;
+}
+#endif /* BB_FEATURE_MOUNT_LOOP */
+
 /* Seperate standard mount options from the nonstandard string options */
 static void
 parse_mount_options ( char *options, unsigned long *flags, char *strflags)
@@ -240,7 +320,7 @@ mount_one(char *blockDevice, char *directory, char *filesystemType,
                status = do_mount (blockDevice, directory, filesystemType,
                                flags | MS_MGC_VAL, string_flags, useMtab, 
                                fakeIt, mtab_opts);
-               if (status == 0)
+               if (status == TRUE)
                    break;
            }
        }
@@ -253,7 +333,7 @@ mount_one(char *blockDevice, char *directory, char *filesystemType,
                        fakeIt, mtab_opts);
     }
 
-    if (status) {
+    if (status==FALSE) {
        fprintf (stderr, "Mounting %s on %s failed: %s\n",
                 blockDevice, directory, strerror(errno));
        return (FALSE);
@@ -400,70 +480,3 @@ goodbye:
     usage( mount_usage);
 }
 
-#if defined BB_FEATURE_MOUNT_LOOP
-static int set_loop(const char *device, const char *file, int offset, int *loopro)
-{
-       struct loop_info loopinfo;
-       int     fd, ffd, mode;
-       
-       mode = *loopro ? O_RDONLY : O_RDWR;
-       if ((ffd = open (file, mode)) < 0 && !*loopro
-           && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) {
-         perror (file);
-         return 1;
-       }
-       if ((fd = open (device, mode)) < 0) {
-         close(ffd);
-         perror (device);
-         return 1;
-       }
-       *loopro = (mode == O_RDONLY);
-
-       memset(&loopinfo, 0, sizeof(loopinfo));
-       strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
-       loopinfo.lo_name[LO_NAME_SIZE-1] = 0;
-
-       loopinfo.lo_offset = offset;
-
-       loopinfo.lo_encrypt_key_size = 0;
-       if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
-               perror("ioctl: LOOP_SET_FD");
-               close(fd);
-               close(ffd);
-               return 1;
-       }
-       if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
-               (void) ioctl(fd, LOOP_CLR_FD, 0);
-               perror("ioctl: LOOP_SET_STATUS");
-               close(fd);
-               close(ffd);
-               return 1;
-       }
-       close(fd);
-       close(ffd);
-       return 0;
-}
-
-char *find_unused_loop_device (void)
-{
-       char dev[20];
-       int i, fd;
-       struct stat statbuf;
-       struct loop_info loopinfo;
-
-       for(i = 0; i <= 7; i++) {
-               sprintf(dev, "/dev/loop%d", i);
-               if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
-                       if ((fd = open (dev, O_RDONLY)) >= 0) {
-                               if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == -1 &&
-                                  errno == ENXIO) { /* probably free */
-                                       close (fd);
-                                       return strdup(dev);
-                               }
-                               close (fd);
-                       }
-               }
-       }
-        return NULL;
-}
-#endif /* BB_FEATURE_MOUNT_LOOP */
index 92b62de..2b6e7f5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ping.c,v 1.6 1999/12/11 08:41:28 andersen Exp $
+ * $Id: ping.c,v 1.7 2000/01/26 20:06:48 erik Exp $
  * Mini ping implementation for busybox
  *
  * Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
@@ -319,10 +319,11 @@ static void ping(char *host)
     int sockopt;
     
     if (!(proto = getprotobyname("icmp"))) {
-        fprintf(stderr, "ping: unknown protocol icmp\n");
-       exit(1);
+       /* getprotobyname failed, so just silently force 
+        * proto->p_proto to have the correct value for "icmp" */
+       proto->p_proto = 1;
     }
-    if ((pingsock = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) {
+    if ((pingsock = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) { /* 1 == ICMP */
        if (errno == EPERM) {
            fprintf(stderr, "ping: permission denied. (are you root?)\n");
        } else {
diff --git a/ping.c b/ping.c
index 92b62de..2b6e7f5 100644 (file)
--- a/ping.c
+++ b/ping.c
@@ -1,5 +1,5 @@
 /*
- * $Id: ping.c,v 1.6 1999/12/11 08:41:28 andersen Exp $
+ * $Id: ping.c,v 1.7 2000/01/26 20:06:48 erik Exp $
  * Mini ping implementation for busybox
  *
  * Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
@@ -319,10 +319,11 @@ static void ping(char *host)
     int sockopt;
     
     if (!(proto = getprotobyname("icmp"))) {
-        fprintf(stderr, "ping: unknown protocol icmp\n");
-       exit(1);
+       /* getprotobyname failed, so just silently force 
+        * proto->p_proto to have the correct value for "icmp" */
+       proto->p_proto = 1;
     }
-    if ((pingsock = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) {
+    if ((pingsock = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) { /* 1 == ICMP */
        if (errno == EPERM) {
            fprintf(stderr, "ping: permission denied. (are you root?)\n");
        } else {
index 9ad6f26..68b27e3 100644 (file)
--- a/umount.c
+++ b/umount.c
 #include <fstab.h>
 #include <errno.h>
 
-#if defined BB_FEATURE_MOUNT_LOOP
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <linux/loop.h>
-
-static int del_loop(const char *device);
-#endif
-
 static const char umount_usage[] = 
 "umount [flags] filesystem|directory\n\n"
 "Flags:\n"
@@ -52,43 +44,34 @@ static int useMtab = TRUE;
 static int umountAll = FALSE;
 extern const char mtab_file[]; /* Defined in utility.c */
 
+#define MIN(x,y) (x > y ? x : y)
+
 static int 
 do_umount(const char* name, int useMtab)
 {
     int status;
-
-#if defined BB_FEATURE_MOUNT_LOOP
-    /* check to see if this is a loop device */
-    struct stat fst;
-    char dev[20];
-    const char *oldname = NULL;
-    int i;
-    
-    if (stat(name, &fst)) {
-       fprintf(stderr, "umount: %s: %s\n", name, strerror(errno));
-       exit(1);
-    }
-    for (i = 0 ; i <= 7 ; i++) {
-       struct stat lst;
-       sprintf(dev, "/dev/loop%d", i);
-       if (stat(dev, &lst))
-           continue;
-       if (lst.st_dev == fst.st_dev) {
-           oldname = name;
-           name = dev;
-           break;
+    struct mntent *m;
+    FILE *mountTable;
+    const char *blockDevice = NULL;
+
+    if ((mountTable = setmntent (mtab_file, "r"))) {
+       while ((m = getmntent (mountTable)) != 0) {
+           if (strncmp(m->mnt_dir, name,
+                       MIN(strlen(m->mnt_dir),strlen(name))) == 0)
+               blockDevice = m->mnt_fsname;
+           else if (strcmp(m->mnt_fsname, name) == 0) {
+               blockDevice = name;
+               name = m->mnt_dir;
+           }
        }
     }
-#endif
 
     status = umount(name);
 
 #if defined BB_FEATURE_MOUNT_LOOP
-    if (!strncmp("/dev/loop", name, 9)) { /* this was a loop device, delete it */
-       del_loop(name);
-       if (oldname != NULL)
-           name = oldname;
-    }
+    if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9))
+       /* this was a loop device, delete it */
+       del_loop(blockDevice);
 #endif
 #if defined BB_MTAB
     if ( status == 0 ) {
@@ -178,20 +161,3 @@ umount_main(int argc, char** argv)
     }
 }
 
-#if defined BB_FEATURE_MOUNT_LOOP
-static int del_loop(const char *device)
-{
-       int fd;
-
-       if ((fd = open(device, O_RDONLY)) < 0) {
-               perror(device);
-               exit(1);
-       }
-       if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
-               perror("ioctl: LOOP_CLR_FD");
-               exit(1);
-       }
-       close(fd);
-       return(0);
-}
-#endif
index 709c7fc..3c1568a 100644 (file)
@@ -127,11 +127,11 @@ do_mount(char* specialfile, char* dir, char* filesystemtype,
            specialfile = find_unused_loop_device();
            if (specialfile == NULL) {
                fprintf(stderr, "Could not find a spare loop device\n");
-               exit(1);
+               return( FALSE);
            }
            if (set_loop (specialfile, lofile, 0, &loro)) {
                fprintf(stderr, "Could not setup loop device\n");
-               exit(1);
+               return( FALSE);
            }
            if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */
                fprintf(stderr, "WARNING: loop device is read-only\n");
@@ -141,15 +141,26 @@ do_mount(char* specialfile, char* dir, char* filesystemtype,
 #endif
        status=mount(specialfile, dir, filesystemtype, flags, string_flags);
     }
-#if defined BB_MTAB
+
+
+    /* If the mount was sucessful, do anything needed, then return TRUE */
     if (status == 0) {
-       if (useMtab==TRUE)
+
+#if defined BB_MTAB
+       if (useMtab==TRUE) {
            write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts);
-       return 0;
+       }
+#endif
+       return( TRUE);
+    }
+
+    /* Bummer.  mount failed.  Clean up */
+#if defined BB_FEATURE_MOUNT_LOOP
+    if (specialfile != NULL) {
+       del_loop(specialfile);
     }
-    else
 #endif
-       return(status);
+    return( FALSE);
 }
 
 
@@ -166,6 +177,75 @@ extern void whine_if_fstab_is_missing()
 #endif
 
 
+#if defined BB_FEATURE_MOUNT_LOOP
+static int set_loop(const char *device, const char *file, int offset, int *loopro)
+{
+       struct loop_info loopinfo;
+       int     fd, ffd, mode;
+       
+       mode = *loopro ? O_RDONLY : O_RDWR;
+       if ((ffd = open (file, mode)) < 0 && !*loopro
+           && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) {
+         perror (file);
+         return 1;
+       }
+       if ((fd = open (device, mode)) < 0) {
+         close(ffd);
+         perror (device);
+         return 1;
+       }
+       *loopro = (mode == O_RDONLY);
+
+       memset(&loopinfo, 0, sizeof(loopinfo));
+       strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
+       loopinfo.lo_name[LO_NAME_SIZE-1] = 0;
+
+       loopinfo.lo_offset = offset;
+
+       loopinfo.lo_encrypt_key_size = 0;
+       if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
+               perror("ioctl: LOOP_SET_FD");
+               close(fd);
+               close(ffd);
+               return 1;
+       }
+       if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
+               (void) ioctl(fd, LOOP_CLR_FD, 0);
+               perror("ioctl: LOOP_SET_STATUS");
+               close(fd);
+               close(ffd);
+               return 1;
+       }
+       close(fd);
+       close(ffd);
+       return 0;
+}
+
+char *find_unused_loop_device (void)
+{
+       char dev[20];
+       int i, fd;
+       struct stat statbuf;
+       struct loop_info loopinfo;
+
+       for(i = 0; i <= 7; i++) {
+           sprintf(dev, "/dev/loop%d", i);
+           if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
+               if ((fd = open (dev, O_RDONLY)) >= 0) {
+                   if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == -1) {
+                       if (errno == ENXIO) { /* probably free */
+                           close (fd);
+                           return strdup(dev);
+                       }
+                   }
+                   close (fd);
+               }
+           }
+       }
+        return NULL;
+}
+#endif /* BB_FEATURE_MOUNT_LOOP */
+
 /* Seperate standard mount options from the nonstandard string options */
 static void
 parse_mount_options ( char *options, unsigned long *flags, char *strflags)
@@ -240,7 +320,7 @@ mount_one(char *blockDevice, char *directory, char *filesystemType,
                status = do_mount (blockDevice, directory, filesystemType,
                                flags | MS_MGC_VAL, string_flags, useMtab, 
                                fakeIt, mtab_opts);
-               if (status == 0)
+               if (status == TRUE)
                    break;
            }
        }
@@ -253,7 +333,7 @@ mount_one(char *blockDevice, char *directory, char *filesystemType,
                        fakeIt, mtab_opts);
     }
 
-    if (status) {
+    if (status==FALSE) {
        fprintf (stderr, "Mounting %s on %s failed: %s\n",
                 blockDevice, directory, strerror(errno));
        return (FALSE);
@@ -400,70 +480,3 @@ goodbye:
     usage( mount_usage);
 }
 
-#if defined BB_FEATURE_MOUNT_LOOP
-static int set_loop(const char *device, const char *file, int offset, int *loopro)
-{
-       struct loop_info loopinfo;
-       int     fd, ffd, mode;
-       
-       mode = *loopro ? O_RDONLY : O_RDWR;
-       if ((ffd = open (file, mode)) < 0 && !*loopro
-           && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) {
-         perror (file);
-         return 1;
-       }
-       if ((fd = open (device, mode)) < 0) {
-         close(ffd);
-         perror (device);
-         return 1;
-       }
-       *loopro = (mode == O_RDONLY);
-
-       memset(&loopinfo, 0, sizeof(loopinfo));
-       strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
-       loopinfo.lo_name[LO_NAME_SIZE-1] = 0;
-
-       loopinfo.lo_offset = offset;
-
-       loopinfo.lo_encrypt_key_size = 0;
-       if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
-               perror("ioctl: LOOP_SET_FD");
-               close(fd);
-               close(ffd);
-               return 1;
-       }
-       if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
-               (void) ioctl(fd, LOOP_CLR_FD, 0);
-               perror("ioctl: LOOP_SET_STATUS");
-               close(fd);
-               close(ffd);
-               return 1;
-       }
-       close(fd);
-       close(ffd);
-       return 0;
-}
-
-char *find_unused_loop_device (void)
-{
-       char dev[20];
-       int i, fd;
-       struct stat statbuf;
-       struct loop_info loopinfo;
-
-       for(i = 0; i <= 7; i++) {
-               sprintf(dev, "/dev/loop%d", i);
-               if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
-                       if ((fd = open (dev, O_RDONLY)) >= 0) {
-                               if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == -1 &&
-                                  errno == ENXIO) { /* probably free */
-                                       close (fd);
-                                       return strdup(dev);
-                               }
-                               close (fd);
-                       }
-               }
-       }
-        return NULL;
-}
-#endif /* BB_FEATURE_MOUNT_LOOP */
index 9ad6f26..68b27e3 100644 (file)
 #include <fstab.h>
 #include <errno.h>
 
-#if defined BB_FEATURE_MOUNT_LOOP
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <linux/loop.h>
-
-static int del_loop(const char *device);
-#endif
-
 static const char umount_usage[] = 
 "umount [flags] filesystem|directory\n\n"
 "Flags:\n"
@@ -52,43 +44,34 @@ static int useMtab = TRUE;
 static int umountAll = FALSE;
 extern const char mtab_file[]; /* Defined in utility.c */
 
+#define MIN(x,y) (x > y ? x : y)
+
 static int 
 do_umount(const char* name, int useMtab)
 {
     int status;
-
-#if defined BB_FEATURE_MOUNT_LOOP
-    /* check to see if this is a loop device */
-    struct stat fst;
-    char dev[20];
-    const char *oldname = NULL;
-    int i;
-    
-    if (stat(name, &fst)) {
-       fprintf(stderr, "umount: %s: %s\n", name, strerror(errno));
-       exit(1);
-    }
-    for (i = 0 ; i <= 7 ; i++) {
-       struct stat lst;
-       sprintf(dev, "/dev/loop%d", i);
-       if (stat(dev, &lst))
-           continue;
-       if (lst.st_dev == fst.st_dev) {
-           oldname = name;
-           name = dev;
-           break;
+    struct mntent *m;
+    FILE *mountTable;
+    const char *blockDevice = NULL;
+
+    if ((mountTable = setmntent (mtab_file, "r"))) {
+       while ((m = getmntent (mountTable)) != 0) {
+           if (strncmp(m->mnt_dir, name,
+                       MIN(strlen(m->mnt_dir),strlen(name))) == 0)
+               blockDevice = m->mnt_fsname;
+           else if (strcmp(m->mnt_fsname, name) == 0) {
+               blockDevice = name;
+               name = m->mnt_dir;
+           }
        }
     }
-#endif
 
     status = umount(name);
 
 #if defined BB_FEATURE_MOUNT_LOOP
-    if (!strncmp("/dev/loop", name, 9)) { /* this was a loop device, delete it */
-       del_loop(name);
-       if (oldname != NULL)
-           name = oldname;
-    }
+    if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9))
+       /* this was a loop device, delete it */
+       del_loop(blockDevice);
 #endif
 #if defined BB_MTAB
     if ( status == 0 ) {
@@ -178,20 +161,3 @@ umount_main(int argc, char** argv)
     }
 }
 
-#if defined BB_FEATURE_MOUNT_LOOP
-static int del_loop(const char *device)
-{
-       int fd;
-
-       if ((fd = open(device, O_RDONLY)) < 0) {
-               perror(device);
-               exit(1);
-       }
-       if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
-               perror("ioctl: LOOP_CLR_FD");
-               exit(1);
-       }
-       close(fd);
-       return(0);
-}
-#endif
index 8139f38..643c3b5 100644 (file)
--- a/utility.c
+++ b/utility.c
 #include <unistd.h>
 #include <ctype.h>
 
+#if defined BB_FEATURE_MOUNT_LOOP
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/loop.h>
+#endif
+
+
 #if defined BB_MOUNT || defined BB_UMOUNT || defined BB_DF
 #  if defined BB_FEATURE_USE_PROCFS
 const char mtab_file[] = "/proc/mounts";
@@ -1146,4 +1153,22 @@ extern int vdprintf(int d, const char *format, va_list ap)
 }
 #endif
 
+#if defined BB_FEATURE_MOUNT_LOOP
+extern int del_loop(const char *device)
+{
+    int fd;
+
+    if ((fd = open(device, O_RDONLY)) < 0) {
+       perror(device);
+       return( FALSE);
+    }
+    if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
+       perror("ioctl: LOOP_CLR_FD");
+       return( FALSE);
+    }
+    close(fd);
+    return( TRUE);
+}
+#endif
+
 /* END CODE */