summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Andersen <andersen@codepoet.org>2000-01-13 06:38:14 +0000
committerErik Andersen <andersen@codepoet.org>2000-01-13 06:38:14 +0000
commitb7cc49d992ed9a5a59261096012e0b4a811bb7f4 (patch)
treed151960bd89e78df235150a498cb63f39bfcab2e
parent05df239ed90584156b820dbf3ede638208eb440f (diff)
downloadbusybox-w32-b7cc49d992ed9a5a59261096012e0b4a811bb7f4.tar.gz
busybox-w32-b7cc49d992ed9a5a59261096012e0b4a811bb7f4.tar.bz2
busybox-w32-b7cc49d992ed9a5a59261096012e0b4a811bb7f4.zip
* Added -o loop option for mount, and support in umount for loop
devices. Support is toggled by MOUNT_LOOP feature -- Ben Collins <bcollins@debian.org> -Erik
-rw-r--r--Changelog3
-rw-r--r--busybox.def.h11
-rw-r--r--mount.c139
-rw-r--r--umount.c72
-rw-r--r--util-linux/mount.c139
-rw-r--r--util-linux/umount.c72
6 files changed, 392 insertions, 44 deletions
diff --git a/Changelog b/Changelog
index d0878bc9c..6c68d844d 100644
--- a/Changelog
+++ b/Changelog
@@ -10,6 +10,9 @@
10 * mkdir -p would print an error when asked to mkdir an existing dir 10 * mkdir -p would print an error when asked to mkdir an existing dir
11 with no interveining subdirectories. 11 with no interveining subdirectories.
12 * Fixed "syslogd -O" so that it works. 12 * Fixed "syslogd -O" so that it works.
13 * Added -o loop option for mount, and support in umount for loop
14 devices. Support is toggled by MOUNT_LOOP feature -- Ben Collins
15 <bcollins@debian.org>
13 16
14 -Erik Andersen 17 -Erik Andersen
15 18
diff --git a/busybox.def.h b/busybox.def.h
index 65ed365a5..099eba96c 100644
--- a/busybox.def.h
+++ b/busybox.def.h
@@ -103,20 +103,31 @@
103// enable features that use the /proc filesystem (apps that 103// enable features that use the /proc filesystem (apps that
104// break without this will tell you on compile)... 104// break without this will tell you on compile)...
105#define BB_FEATURE_USE_PROCFS 105#define BB_FEATURE_USE_PROCFS
106//
106// Use termios to manipulate the screen ('more' is prettier with this on) 107// Use termios to manipulate the screen ('more' is prettier with this on)
107#define BB_FEATURE_USE_TERMIOS 108#define BB_FEATURE_USE_TERMIOS
109//
108// calculate terminal & column widths (for more and ls) 110// calculate terminal & column widths (for more and ls)
109#define BB_FEATURE_AUTOWIDTH 111#define BB_FEATURE_AUTOWIDTH
112//
110// show username/groupnames (bypasses libc6 NSS) for ls 113// show username/groupnames (bypasses libc6 NSS) for ls
111#define BB_FEATURE_LS_USERNAME 114#define BB_FEATURE_LS_USERNAME
115//
112// show file timestamps in ls 116// show file timestamps in ls
113#define BB_FEATURE_LS_TIMESTAMPS 117#define BB_FEATURE_LS_TIMESTAMPS
118//
114// enable ls -p and -F 119// enable ls -p and -F
115#define BB_FEATURE_LS_FILETYPES 120#define BB_FEATURE_LS_FILETYPES
121//
116// Change ping implementation -- simplified, featureless, but really small. 122// Change ping implementation -- simplified, featureless, but really small.
117//#define BB_SIMPLE_PING 123//#define BB_SIMPLE_PING
124////
118// Make init use a simplified /etc/inittab file (recommended). 125// Make init use a simplified /etc/inittab file (recommended).
119#define BB_FEATURE_USE_INITTAB 126#define BB_FEATURE_USE_INITTAB
127//
120//Enable init being called as /linuxrc 128//Enable init being called as /linuxrc
121#define BB_FEATURE_LINUXRC 129#define BB_FEATURE_LINUXRC
122// 130//
131// Enable support for loop devices in mount
132#define BB_FEATURE_MOUNT_LOOP
133//
diff --git a/mount.c b/mount.c
index ee6fe15e6..8777a3be4 100644
--- a/mount.c
+++ b/mount.c
@@ -28,7 +28,10 @@
28 * putting it back as a compile-time option some time), 28 * putting it back as a compile-time option some time),
29 * major adjustments to option parsing, and some serious 29 * major adjustments to option parsing, and some serious
30 * dieting all around. 30 * dieting all around.
31*/ 31 *
32 * 2000-01-12 Ben Collins <bcollins@debian.org>, Borrowed utils-linux's
33 * mount to add loop support.
34 */
32 35
33#include "internal.h" 36#include "internal.h"
34#include <stdlib.h> 37#include <stdlib.h>
@@ -41,6 +44,17 @@
41#include <ctype.h> 44#include <ctype.h>
42#include <fstab.h> 45#include <fstab.h>
43 46
47#if defined BB_FEATURE_MOUNT_LOOP
48#include <fcntl.h>
49#include <sys/ioctl.h>
50#include <linux/loop.h>
51
52static int set_loop(const char *device, const char *file, int offset, int *loopro);
53static char *find_unused_loop_device (void);
54
55static int use_loop = 0;
56#endif
57
44extern const char mtab_file[]; /* Defined in utility.c */ 58extern const char mtab_file[]; /* Defined in utility.c */
45 59
46static const char mount_usage[] = "\tmount [flags]\n" 60static const char mount_usage[] = "\tmount [flags]\n"
@@ -61,6 +75,9 @@ static const char mount_usage[] = "\tmount [flags]\n"
61 "\tasync / sync:\tWrites are asynchronous / synchronous.\n" 75 "\tasync / sync:\tWrites are asynchronous / synchronous.\n"
62 "\tdev / nodev:\tAllow use of special device files / disallow them.\n" 76 "\tdev / nodev:\tAllow use of special device files / disallow them.\n"
63 "\texec / noexec:\tAllow use of executable files / disallow them.\n" 77 "\texec / noexec:\tAllow use of executable files / disallow them.\n"
78#if defined BB_FEATURE_MOUNT_LOOP
79 "\tloop: Mounts a file via loop device.\n"
80#endif
64 "\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n" 81 "\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n"
65 "\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n" 82 "\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n"
66 "\tro / rw: Mount for read-only / read-write.\n" 83 "\tro / rw: Mount for read-only / read-write.\n"
@@ -91,28 +108,48 @@ static const struct mount_options mount_options[] = {
91 {0, 0, 0} 108 {0, 0, 0}
92}; 109};
93 110
94#if ! defined BB_MTAB
95#define do_mount(specialfile, dir, filesystemtype, flags, string_flags, useMtab, fakeIt, mtab_opts) \
96 mount(specialfile, dir, filesystemtype, flags, string_flags)
97#else
98static int 111static int
99do_mount(char* specialfile, char* dir, char* filesystemtype, 112do_mount(char* specialfile, char* dir, char* filesystemtype,
100 long flags, void* string_flags, int useMtab, int fakeIt, char* mtab_opts) 113 long flags, void* string_flags, int useMtab, int fakeIt, char* mtab_opts)
101{ 114{
102 int status=0; 115 int status=0;
103 116
117#if defined BB_MTAB
104 if (fakeIt==FALSE) 118 if (fakeIt==FALSE)
119#endif
120 {
121#if defined BB_FEATURE_MOUNT_LOOP
122 if (use_loop) {
123 int loro = flags & MS_RDONLY;
124 char *lofile = specialfile;
125 specialfile = find_unused_loop_device();
126 if (specialfile == NULL) {
127 fprintf(stderr, "Could not find a spare loop device\n");
128 exit(1);
129 }
130 if (set_loop (specialfile, lofile, 0, &loro)) {
131 fprintf(stderr, "Could not setup loop device\n");
132 exit(1);
133 }
134 if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */
135 fprintf(stderr, "WARNING: loop device is read-only\n");
136 flags &= ~MS_RDONLY;
137 }
138 }
139#endif
105 status=mount(specialfile, dir, filesystemtype, flags, string_flags); 140 status=mount(specialfile, dir, filesystemtype, flags, string_flags);
106 141 }
107 if ( status == 0 ) { 142#if defined BB_MTAB
108 if ( useMtab==TRUE ) 143 if (status == 0) {
144 if (useMtab==TRUE)
109 write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts); 145 write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts);
110 return 0; 146 return 0;
111 } 147 }
112 else 148 else
113 return( status);
114}
115#endif 149#endif
150 return(status);
151}
152
116 153
117 154
118#if defined BB_MTAB 155#if defined BB_MTAB
@@ -148,16 +185,20 @@ parse_mount_options ( char *options, unsigned long *flags, char *strflags)
148 } 185 }
149 f++; 186 f++;
150 } 187 }
188#if defined BB_FEATURE_MOUNT_LOOP
189 if (gotone==FALSE && !strcasecmp ("loop", options)) { /* loop device support */
190 use_loop = 1;
191 gotone=TRUE;
192 }
193#endif
151 if (*strflags && strflags!= '\0' && gotone==FALSE) { 194 if (*strflags && strflags!= '\0' && gotone==FALSE) {
152 char *temp=strflags; 195 char *temp=strflags;
153 temp += strlen (strflags); 196 temp += strlen (strflags);
154 *temp++ = ','; 197 *temp++ = ',';
155 *temp++ = '\0'; 198 *temp++ = '\0';
156 } 199 }
157 if (gotone==FALSE) { 200 if (gotone==FALSE)
158 strcat (strflags, options); 201 strcat (strflags, options);
159 gotone=FALSE;
160 }
161 if (comma) { 202 if (comma) {
162 *comma = ','; 203 *comma = ',';
163 options = ++comma; 204 options = ++comma;
@@ -356,3 +397,73 @@ extern int mount_main (int argc, char **argv)
356goodbye: 397goodbye:
357 usage( mount_usage); 398 usage( mount_usage);
358} 399}
400
401#if defined BB_FEATURE_MOUNT_LOOP
402static int set_loop(const char *device, const char *file, int offset, int *loopro)
403{
404 struct loop_info loopinfo;
405 int fd, ffd, mode;
406
407 mode = *loopro ? O_RDONLY : O_RDWR;
408 if ((ffd = open (file, mode)) < 0 && !*loopro
409 && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) {
410 perror (file);
411 return 1;
412 }
413 if ((fd = open (device, mode)) < 0) {
414 close(ffd);
415 perror (device);
416 return 1;
417 }
418 *loopro = (mode == O_RDONLY);
419
420 memset(&loopinfo, 0, sizeof(loopinfo));
421 strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
422 loopinfo.lo_name[LO_NAME_SIZE-1] = 0;
423
424 loopinfo.lo_offset = offset;
425
426 loopinfo.lo_encrypt_key_size = 0;
427 if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
428 perror("ioctl: LOOP_SET_FD");
429 exit(1);
430 }
431 if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
432 (void) ioctl(fd, LOOP_CLR_FD, 0);
433 perror("ioctl: LOOP_SET_STATUS");
434 exit(1);
435 }
436 close(fd);
437 close(ffd);
438 return 0;
439}
440
441static char *find_unused_loop_device (void)
442{
443 char dev[20];
444 int i, fd, somedev = 0, someloop = 0;
445 struct stat statbuf;
446 struct loop_info loopinfo;
447
448 for(i = 0; i < 256; i++) {
449 sprintf(dev, "/dev/loop%d", i);
450 if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
451 somedev++;
452 fd = open (dev, O_RDONLY);
453 if (fd >= 0) {
454 if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0)
455 someloop++; /* in use */
456 else if (errno == ENXIO) {
457 close (fd);
458 return strdup(dev); /* probably free */
459 }
460 close (fd);
461 }
462 continue;
463 }
464 if (i >= 7)
465 break;
466 }
467 return NULL;
468}
469#endif /* BB_FEATURE_MOUNT_LOOP */
diff --git a/umount.c b/umount.c
index ab76be4da..af1b3a43e 100644
--- a/umount.c
+++ b/umount.c
@@ -28,6 +28,14 @@
28#include <fstab.h> 28#include <fstab.h>
29#include <errno.h> 29#include <errno.h>
30 30
31#if defined BB_FEATURE_MOUNT_LOOP
32#include <fcntl.h>
33#include <sys/ioctl.h>
34#include <linux/loop.h>
35
36static int del_loop(const char *device);
37#endif
38
31static const char umount_usage[] = 39static const char umount_usage[] =
32"Usage: umount [flags] filesystem|directory\n\n" 40"Usage: umount [flags] filesystem|directory\n\n"
33"Flags:\n" 41"Flags:\n"
@@ -44,23 +52,54 @@ static int useMtab = TRUE;
44static int umountAll = FALSE; 52static int umountAll = FALSE;
45extern const char mtab_file[]; /* Defined in utility.c */ 53extern const char mtab_file[]; /* Defined in utility.c */
46 54
47#if ! defined BB_MTAB
48#define do_umount( blockDevice, useMtab) umount( blockDevice)
49#else
50static int 55static int
51do_umount(const char* name, int useMtab) 56do_umount(const char* name, int useMtab)
52{ 57{
53 int status = umount(name); 58 int status;
59
60#if defined BB_FEATURE_MOUNT_LOOP
61 /* check to see if this is a loop device */
62 struct stat fst;
63 char dev[20];
64 const char *oldname = NULL;
65 int i;
66
67 if (stat(name, &fst)) {
68 fprintf(stderr, "umount: %s: %s\n", name, strerror(errno));
69 exit(1);
70 }
71 for (i = 0 ; i <= 7 ; i++) {
72 struct stat lst;
73 sprintf(dev, "/dev/loop%d", i);
74 if (stat(dev, &lst))
75 continue;
76 if (lst.st_dev == fst.st_dev) {
77 oldname = name;
78 name = dev;
79 break;
80 }
81 }
82#endif
83
84 status = umount(name);
54 85
86#if defined BB_FEATURE_MOUNT_LOOP
87 if (!strncmp("/dev/loop", name, 9)) { /* this was a loop device, delete it */
88 del_loop(name);
89 if (oldname != NULL)
90 name = oldname;
91 }
92#endif
93#if defined BB_MTAB
55 if ( status == 0 ) { 94 if ( status == 0 ) {
56 if ( useMtab==TRUE ) 95 if ( useMtab==TRUE )
57 erase_mtab(name); 96 erase_mtab(name);
58 return 0; 97 return 0;
59 } 98 }
60 else 99 else
61 return( status);
62}
63#endif 100#endif
101 return(status);
102}
64 103
65static int 104static int
66umount_all(int useMtab) 105umount_all(int useMtab)
@@ -135,7 +174,24 @@ umount_main(int argc, char** argv)
135 exit (TRUE); 174 exit (TRUE);
136 else { 175 else {
137 perror("umount"); 176 perror("umount");
138 exit( FALSE); 177 exit(FALSE);
139 } 178 }
140} 179}
141 180
181#if defined BB_FEATURE_MOUNT_LOOP
182static int del_loop(const char *device)
183{
184 int fd;
185
186 if ((fd = open(device, O_RDONLY)) < 0) {
187 perror(device);
188 exit(1);
189 }
190 if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
191 perror("ioctl: LOOP_CLR_FD");
192 exit(1);
193 }
194 close(fd);
195 return(0);
196}
197#endif
diff --git a/util-linux/mount.c b/util-linux/mount.c
index ee6fe15e6..8777a3be4 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -28,7 +28,10 @@
28 * putting it back as a compile-time option some time), 28 * putting it back as a compile-time option some time),
29 * major adjustments to option parsing, and some serious 29 * major adjustments to option parsing, and some serious
30 * dieting all around. 30 * dieting all around.
31*/ 31 *
32 * 2000-01-12 Ben Collins <bcollins@debian.org>, Borrowed utils-linux's
33 * mount to add loop support.
34 */
32 35
33#include "internal.h" 36#include "internal.h"
34#include <stdlib.h> 37#include <stdlib.h>
@@ -41,6 +44,17 @@
41#include <ctype.h> 44#include <ctype.h>
42#include <fstab.h> 45#include <fstab.h>
43 46
47#if defined BB_FEATURE_MOUNT_LOOP
48#include <fcntl.h>
49#include <sys/ioctl.h>
50#include <linux/loop.h>
51
52static int set_loop(const char *device, const char *file, int offset, int *loopro);
53static char *find_unused_loop_device (void);
54
55static int use_loop = 0;
56#endif
57
44extern const char mtab_file[]; /* Defined in utility.c */ 58extern const char mtab_file[]; /* Defined in utility.c */
45 59
46static const char mount_usage[] = "\tmount [flags]\n" 60static const char mount_usage[] = "\tmount [flags]\n"
@@ -61,6 +75,9 @@ static const char mount_usage[] = "\tmount [flags]\n"
61 "\tasync / sync:\tWrites are asynchronous / synchronous.\n" 75 "\tasync / sync:\tWrites are asynchronous / synchronous.\n"
62 "\tdev / nodev:\tAllow use of special device files / disallow them.\n" 76 "\tdev / nodev:\tAllow use of special device files / disallow them.\n"
63 "\texec / noexec:\tAllow use of executable files / disallow them.\n" 77 "\texec / noexec:\tAllow use of executable files / disallow them.\n"
78#if defined BB_FEATURE_MOUNT_LOOP
79 "\tloop: Mounts a file via loop device.\n"
80#endif
64 "\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n" 81 "\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n"
65 "\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n" 82 "\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n"
66 "\tro / rw: Mount for read-only / read-write.\n" 83 "\tro / rw: Mount for read-only / read-write.\n"
@@ -91,28 +108,48 @@ static const struct mount_options mount_options[] = {
91 {0, 0, 0} 108 {0, 0, 0}
92}; 109};
93 110
94#if ! defined BB_MTAB
95#define do_mount(specialfile, dir, filesystemtype, flags, string_flags, useMtab, fakeIt, mtab_opts) \
96 mount(specialfile, dir, filesystemtype, flags, string_flags)
97#else
98static int 111static int
99do_mount(char* specialfile, char* dir, char* filesystemtype, 112do_mount(char* specialfile, char* dir, char* filesystemtype,
100 long flags, void* string_flags, int useMtab, int fakeIt, char* mtab_opts) 113 long flags, void* string_flags, int useMtab, int fakeIt, char* mtab_opts)
101{ 114{
102 int status=0; 115 int status=0;
103 116
117#if defined BB_MTAB
104 if (fakeIt==FALSE) 118 if (fakeIt==FALSE)
119#endif
120 {
121#if defined BB_FEATURE_MOUNT_LOOP
122 if (use_loop) {
123 int loro = flags & MS_RDONLY;
124 char *lofile = specialfile;
125 specialfile = find_unused_loop_device();
126 if (specialfile == NULL) {
127 fprintf(stderr, "Could not find a spare loop device\n");
128 exit(1);
129 }
130 if (set_loop (specialfile, lofile, 0, &loro)) {
131 fprintf(stderr, "Could not setup loop device\n");
132 exit(1);
133 }
134 if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */
135 fprintf(stderr, "WARNING: loop device is read-only\n");
136 flags &= ~MS_RDONLY;
137 }
138 }
139#endif
105 status=mount(specialfile, dir, filesystemtype, flags, string_flags); 140 status=mount(specialfile, dir, filesystemtype, flags, string_flags);
106 141 }
107 if ( status == 0 ) { 142#if defined BB_MTAB
108 if ( useMtab==TRUE ) 143 if (status == 0) {
144 if (useMtab==TRUE)
109 write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts); 145 write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts);
110 return 0; 146 return 0;
111 } 147 }
112 else 148 else
113 return( status);
114}
115#endif 149#endif
150 return(status);
151}
152
116 153
117 154
118#if defined BB_MTAB 155#if defined BB_MTAB
@@ -148,16 +185,20 @@ parse_mount_options ( char *options, unsigned long *flags, char *strflags)
148 } 185 }
149 f++; 186 f++;
150 } 187 }
188#if defined BB_FEATURE_MOUNT_LOOP
189 if (gotone==FALSE && !strcasecmp ("loop", options)) { /* loop device support */
190 use_loop = 1;
191 gotone=TRUE;
192 }
193#endif
151 if (*strflags && strflags!= '\0' && gotone==FALSE) { 194 if (*strflags && strflags!= '\0' && gotone==FALSE) {
152 char *temp=strflags; 195 char *temp=strflags;
153 temp += strlen (strflags); 196 temp += strlen (strflags);
154 *temp++ = ','; 197 *temp++ = ',';
155 *temp++ = '\0'; 198 *temp++ = '\0';
156 } 199 }
157 if (gotone==FALSE) { 200 if (gotone==FALSE)
158 strcat (strflags, options); 201 strcat (strflags, options);
159 gotone=FALSE;
160 }
161 if (comma) { 202 if (comma) {
162 *comma = ','; 203 *comma = ',';
163 options = ++comma; 204 options = ++comma;
@@ -356,3 +397,73 @@ extern int mount_main (int argc, char **argv)
356goodbye: 397goodbye:
357 usage( mount_usage); 398 usage( mount_usage);
358} 399}
400
401#if defined BB_FEATURE_MOUNT_LOOP
402static int set_loop(const char *device, const char *file, int offset, int *loopro)
403{
404 struct loop_info loopinfo;
405 int fd, ffd, mode;
406
407 mode = *loopro ? O_RDONLY : O_RDWR;
408 if ((ffd = open (file, mode)) < 0 && !*loopro
409 && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) {
410 perror (file);
411 return 1;
412 }
413 if ((fd = open (device, mode)) < 0) {
414 close(ffd);
415 perror (device);
416 return 1;
417 }
418 *loopro = (mode == O_RDONLY);
419
420 memset(&loopinfo, 0, sizeof(loopinfo));
421 strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
422 loopinfo.lo_name[LO_NAME_SIZE-1] = 0;
423
424 loopinfo.lo_offset = offset;
425
426 loopinfo.lo_encrypt_key_size = 0;
427 if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
428 perror("ioctl: LOOP_SET_FD");
429 exit(1);
430 }
431 if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
432 (void) ioctl(fd, LOOP_CLR_FD, 0);
433 perror("ioctl: LOOP_SET_STATUS");
434 exit(1);
435 }
436 close(fd);
437 close(ffd);
438 return 0;
439}
440
441static char *find_unused_loop_device (void)
442{
443 char dev[20];
444 int i, fd, somedev = 0, someloop = 0;
445 struct stat statbuf;
446 struct loop_info loopinfo;
447
448 for(i = 0; i < 256; i++) {
449 sprintf(dev, "/dev/loop%d", i);
450 if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
451 somedev++;
452 fd = open (dev, O_RDONLY);
453 if (fd >= 0) {
454 if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0)
455 someloop++; /* in use */
456 else if (errno == ENXIO) {
457 close (fd);
458 return strdup(dev); /* probably free */
459 }
460 close (fd);
461 }
462 continue;
463 }
464 if (i >= 7)
465 break;
466 }
467 return NULL;
468}
469#endif /* BB_FEATURE_MOUNT_LOOP */
diff --git a/util-linux/umount.c b/util-linux/umount.c
index ab76be4da..af1b3a43e 100644
--- a/util-linux/umount.c
+++ b/util-linux/umount.c
@@ -28,6 +28,14 @@
28#include <fstab.h> 28#include <fstab.h>
29#include <errno.h> 29#include <errno.h>
30 30
31#if defined BB_FEATURE_MOUNT_LOOP
32#include <fcntl.h>
33#include <sys/ioctl.h>
34#include <linux/loop.h>
35
36static int del_loop(const char *device);
37#endif
38
31static const char umount_usage[] = 39static const char umount_usage[] =
32"Usage: umount [flags] filesystem|directory\n\n" 40"Usage: umount [flags] filesystem|directory\n\n"
33"Flags:\n" 41"Flags:\n"
@@ -44,23 +52,54 @@ static int useMtab = TRUE;
44static int umountAll = FALSE; 52static int umountAll = FALSE;
45extern const char mtab_file[]; /* Defined in utility.c */ 53extern const char mtab_file[]; /* Defined in utility.c */
46 54
47#if ! defined BB_MTAB
48#define do_umount( blockDevice, useMtab) umount( blockDevice)
49#else
50static int 55static int
51do_umount(const char* name, int useMtab) 56do_umount(const char* name, int useMtab)
52{ 57{
53 int status = umount(name); 58 int status;
59
60#if defined BB_FEATURE_MOUNT_LOOP
61 /* check to see if this is a loop device */
62 struct stat fst;
63 char dev[20];
64 const char *oldname = NULL;
65 int i;
66
67 if (stat(name, &fst)) {
68 fprintf(stderr, "umount: %s: %s\n", name, strerror(errno));
69 exit(1);
70 }
71 for (i = 0 ; i <= 7 ; i++) {
72 struct stat lst;
73 sprintf(dev, "/dev/loop%d", i);
74 if (stat(dev, &lst))
75 continue;
76 if (lst.st_dev == fst.st_dev) {
77 oldname = name;
78 name = dev;
79 break;
80 }
81 }
82#endif
83
84 status = umount(name);
54 85
86#if defined BB_FEATURE_MOUNT_LOOP
87 if (!strncmp("/dev/loop", name, 9)) { /* this was a loop device, delete it */
88 del_loop(name);
89 if (oldname != NULL)
90 name = oldname;
91 }
92#endif
93#if defined BB_MTAB
55 if ( status == 0 ) { 94 if ( status == 0 ) {
56 if ( useMtab==TRUE ) 95 if ( useMtab==TRUE )
57 erase_mtab(name); 96 erase_mtab(name);
58 return 0; 97 return 0;
59 } 98 }
60 else 99 else
61 return( status);
62}
63#endif 100#endif
101 return(status);
102}
64 103
65static int 104static int
66umount_all(int useMtab) 105umount_all(int useMtab)
@@ -135,7 +174,24 @@ umount_main(int argc, char** argv)
135 exit (TRUE); 174 exit (TRUE);
136 else { 175 else {
137 perror("umount"); 176 perror("umount");
138 exit( FALSE); 177 exit(FALSE);
139 } 178 }
140} 179}
141 180
181#if defined BB_FEATURE_MOUNT_LOOP
182static int del_loop(const char *device)
183{
184 int fd;
185
186 if ((fd = open(device, O_RDONLY)) < 0) {
187 perror(device);
188 exit(1);
189 }
190 if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
191 perror("ioctl: LOOP_CLR_FD");
192 exit(1);
193 }
194 close(fd);
195 return(0);
196}
197#endif