aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Andersen <andersen@codepoet.org>2000-01-26 20:06:48 +0000
committerErik Andersen <andersen@codepoet.org>2000-01-26 20:06:48 +0000
commit5cbdd712f5320ffc109053a94b7cf36c82292cf6 (patch)
tree77236e83cc0583411a75b752a6152d445eb680e0
parent3fe39dce5d1a0b0946878c66bbd7f694c5aa38ea (diff)
downloadbusybox-w32-5cbdd712f5320ffc109053a94b7cf36c82292cf6.tar.gz
busybox-w32-5cbdd712f5320ffc109053a94b7cf36c82292cf6.tar.bz2
busybox-w32-5cbdd712f5320ffc109053a94b7cf36c82292cf6.zip
mount and umount could leak loop device allocations causing the system to
quickly run out. Also disable init's SIGHUP handler during shutdown. -Erik
-rw-r--r--Changelog5
-rw-r--r--init.c4
-rw-r--r--init/init.c4
-rw-r--r--internal.h4
-rw-r--r--mount.c165
-rw-r--r--networking/ping.c9
-rw-r--r--ping.c9
-rw-r--r--umount.c70
-rw-r--r--util-linux/mount.c165
-rw-r--r--util-linux/umount.c70
-rw-r--r--utility.c25
11 files changed, 266 insertions, 264 deletions
diff --git a/Changelog b/Changelog
index 4dbb46e4f..46b2a1f09 100644
--- a/Changelog
+++ b/Changelog
@@ -32,6 +32,11 @@
32 tail -f work only with a single file. This reduced tail 32 tail -f work only with a single file. This reduced tail
33 from 6k to 2.4k. The bigger/more featured tail can still be 33 from 6k to 2.4k. The bigger/more featured tail can still be
34 had by disabling BB_FEATURE_SIMPLE_TAIL in dusybox.defs.h 34 had by disabling BB_FEATURE_SIMPLE_TAIL in dusybox.defs.h
35 * Ping now falls back to doing the right thing if /etc/protocols
36 turns up missing.
37 * Fixed mount and umount. Previously they could leak loop device
38 allocations, causing the system to quickly run out. Fix for umount
39 by Ben Collins <bcollins@debian.org>, and mount was fixed by me.
35 40
36 41
37 -Erik Andersen 42 -Erik Andersen
diff --git a/init.c b/init.c
index 5b80cc561..09540ff01 100644
--- a/init.c
+++ b/init.c
@@ -359,6 +359,7 @@ static pid_t run(char* command,
359 signal(SIGUSR2, SIG_DFL); 359 signal(SIGUSR2, SIG_DFL);
360 signal(SIGINT, SIG_DFL); 360 signal(SIGINT, SIG_DFL);
361 signal(SIGTERM, SIG_DFL); 361 signal(SIGTERM, SIG_DFL);
362 signal(SIGHUP, SIG_DFL);
362 363
363 if ((fd = device_open(terminal, O_RDWR)) < 0) { 364 if ((fd = device_open(terminal, O_RDWR)) < 0) {
364 message(LOG|CONSOLE, "Bummer, can't open %s\r\n", terminal); 365 message(LOG|CONSOLE, "Bummer, can't open %s\r\n", terminal);
@@ -458,6 +459,9 @@ goodnight:
458#ifndef DEBUG_INIT 459#ifndef DEBUG_INIT
459static void shutdown_system(void) 460static void shutdown_system(void)
460{ 461{
462 /* first disable our SIGHUP signal */
463 signal(SIGHUP, SIG_DFL);
464
461 /* Allow Ctrl-Alt-Del to reboot system. */ 465 /* Allow Ctrl-Alt-Del to reboot system. */
462 reboot(RB_ENABLE_CAD); 466 reboot(RB_ENABLE_CAD);
463 message(CONSOLE, "\r\nThe system is going down NOW !!\r\n"); 467 message(CONSOLE, "\r\nThe system is going down NOW !!\r\n");
diff --git a/init/init.c b/init/init.c
index 5b80cc561..09540ff01 100644
--- a/init/init.c
+++ b/init/init.c
@@ -359,6 +359,7 @@ static pid_t run(char* command,
359 signal(SIGUSR2, SIG_DFL); 359 signal(SIGUSR2, SIG_DFL);
360 signal(SIGINT, SIG_DFL); 360 signal(SIGINT, SIG_DFL);
361 signal(SIGTERM, SIG_DFL); 361 signal(SIGTERM, SIG_DFL);
362 signal(SIGHUP, SIG_DFL);
362 363
363 if ((fd = device_open(terminal, O_RDWR)) < 0) { 364 if ((fd = device_open(terminal, O_RDWR)) < 0) {
364 message(LOG|CONSOLE, "Bummer, can't open %s\r\n", terminal); 365 message(LOG|CONSOLE, "Bummer, can't open %s\r\n", terminal);
@@ -458,6 +459,9 @@ goodnight:
458#ifndef DEBUG_INIT 459#ifndef DEBUG_INIT
459static void shutdown_system(void) 460static void shutdown_system(void)
460{ 461{
462 /* first disable our SIGHUP signal */
463 signal(SIGHUP, SIG_DFL);
464
461 /* Allow Ctrl-Alt-Del to reboot system. */ 465 /* Allow Ctrl-Alt-Del to reboot system. */
462 reboot(RB_ENABLE_CAD); 466 reboot(RB_ENABLE_CAD);
463 message(CONSOLE, "\r\nThe system is going down NOW !!\r\n"); 467 message(CONSOLE, "\r\nThe system is going down NOW !!\r\n");
diff --git a/internal.h b/internal.h
index 500a63e62..9611c1922 100644
--- a/internal.h
+++ b/internal.h
@@ -175,6 +175,10 @@ extern int check_wildcard_match(const char* text, const char* pattern);
175extern long getNum (const char *cp); 175extern long getNum (const char *cp);
176extern pid_t findInitPid(); 176extern pid_t findInitPid();
177 177
178#if defined BB_FEATURE_MOUNT_LOOP
179extern int del_loop(const char *device);
180#endif
181
178#if defined BB_GUNZIP || defined BB_GZIP || defined BB_PRINTF || defined BB_TAIL 182#if defined BB_GUNZIP || defined BB_GZIP || defined BB_PRINTF || defined BB_TAIL
179extern void *xmalloc (size_t size); 183extern void *xmalloc (size_t size);
180extern void error(char *msg); 184extern void error(char *msg);
diff --git a/mount.c b/mount.c
index 709c7fc49..3c1568aad 100644
--- a/mount.c
+++ b/mount.c
@@ -127,11 +127,11 @@ do_mount(char* specialfile, char* dir, char* filesystemtype,
127 specialfile = find_unused_loop_device(); 127 specialfile = find_unused_loop_device();
128 if (specialfile == NULL) { 128 if (specialfile == NULL) {
129 fprintf(stderr, "Could not find a spare loop device\n"); 129 fprintf(stderr, "Could not find a spare loop device\n");
130 exit(1); 130 return( FALSE);
131 } 131 }
132 if (set_loop (specialfile, lofile, 0, &loro)) { 132 if (set_loop (specialfile, lofile, 0, &loro)) {
133 fprintf(stderr, "Could not setup loop device\n"); 133 fprintf(stderr, "Could not setup loop device\n");
134 exit(1); 134 return( FALSE);
135 } 135 }
136 if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */ 136 if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */
137 fprintf(stderr, "WARNING: loop device is read-only\n"); 137 fprintf(stderr, "WARNING: loop device is read-only\n");
@@ -141,15 +141,26 @@ do_mount(char* specialfile, char* dir, char* filesystemtype,
141#endif 141#endif
142 status=mount(specialfile, dir, filesystemtype, flags, string_flags); 142 status=mount(specialfile, dir, filesystemtype, flags, string_flags);
143 } 143 }
144#if defined BB_MTAB 144
145
146 /* If the mount was sucessful, do anything needed, then return TRUE */
145 if (status == 0) { 147 if (status == 0) {
146 if (useMtab==TRUE) 148
149#if defined BB_MTAB
150 if (useMtab==TRUE) {
147 write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts); 151 write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts);
148 return 0; 152 }
153#endif
154 return( TRUE);
155 }
156
157 /* Bummer. mount failed. Clean up */
158#if defined BB_FEATURE_MOUNT_LOOP
159 if (specialfile != NULL) {
160 del_loop(specialfile);
149 } 161 }
150 else
151#endif 162#endif
152 return(status); 163 return( FALSE);
153} 164}
154 165
155 166
@@ -166,6 +177,75 @@ extern void whine_if_fstab_is_missing()
166#endif 177#endif
167 178
168 179
180#if defined BB_FEATURE_MOUNT_LOOP
181static int set_loop(const char *device, const char *file, int offset, int *loopro)
182{
183 struct loop_info loopinfo;
184 int fd, ffd, mode;
185
186 mode = *loopro ? O_RDONLY : O_RDWR;
187 if ((ffd = open (file, mode)) < 0 && !*loopro
188 && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) {
189 perror (file);
190 return 1;
191 }
192 if ((fd = open (device, mode)) < 0) {
193 close(ffd);
194 perror (device);
195 return 1;
196 }
197 *loopro = (mode == O_RDONLY);
198
199 memset(&loopinfo, 0, sizeof(loopinfo));
200 strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
201 loopinfo.lo_name[LO_NAME_SIZE-1] = 0;
202
203 loopinfo.lo_offset = offset;
204
205 loopinfo.lo_encrypt_key_size = 0;
206 if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
207 perror("ioctl: LOOP_SET_FD");
208 close(fd);
209 close(ffd);
210 return 1;
211 }
212 if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
213 (void) ioctl(fd, LOOP_CLR_FD, 0);
214 perror("ioctl: LOOP_SET_STATUS");
215 close(fd);
216 close(ffd);
217 return 1;
218 }
219 close(fd);
220 close(ffd);
221 return 0;
222}
223
224char *find_unused_loop_device (void)
225{
226 char dev[20];
227 int i, fd;
228 struct stat statbuf;
229 struct loop_info loopinfo;
230
231 for(i = 0; i <= 7; i++) {
232 sprintf(dev, "/dev/loop%d", i);
233 if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
234 if ((fd = open (dev, O_RDONLY)) >= 0) {
235 if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == -1) {
236 if (errno == ENXIO) { /* probably free */
237 close (fd);
238 return strdup(dev);
239 }
240 }
241 close (fd);
242 }
243 }
244 }
245 return NULL;
246}
247#endif /* BB_FEATURE_MOUNT_LOOP */
248
169/* Seperate standard mount options from the nonstandard string options */ 249/* Seperate standard mount options from the nonstandard string options */
170static void 250static void
171parse_mount_options ( char *options, unsigned long *flags, char *strflags) 251parse_mount_options ( char *options, unsigned long *flags, char *strflags)
@@ -240,7 +320,7 @@ mount_one(char *blockDevice, char *directory, char *filesystemType,
240 status = do_mount (blockDevice, directory, filesystemType, 320 status = do_mount (blockDevice, directory, filesystemType,
241 flags | MS_MGC_VAL, string_flags, useMtab, 321 flags | MS_MGC_VAL, string_flags, useMtab,
242 fakeIt, mtab_opts); 322 fakeIt, mtab_opts);
243 if (status == 0) 323 if (status == TRUE)
244 break; 324 break;
245 } 325 }
246 } 326 }
@@ -253,7 +333,7 @@ mount_one(char *blockDevice, char *directory, char *filesystemType,
253 fakeIt, mtab_opts); 333 fakeIt, mtab_opts);
254 } 334 }
255 335
256 if (status) { 336 if (status==FALSE) {
257 fprintf (stderr, "Mounting %s on %s failed: %s\n", 337 fprintf (stderr, "Mounting %s on %s failed: %s\n",
258 blockDevice, directory, strerror(errno)); 338 blockDevice, directory, strerror(errno));
259 return (FALSE); 339 return (FALSE);
@@ -400,70 +480,3 @@ goodbye:
400 usage( mount_usage); 480 usage( mount_usage);
401} 481}
402 482
403#if defined BB_FEATURE_MOUNT_LOOP
404static int set_loop(const char *device, const char *file, int offset, int *loopro)
405{
406 struct loop_info loopinfo;
407 int fd, ffd, mode;
408
409 mode = *loopro ? O_RDONLY : O_RDWR;
410 if ((ffd = open (file, mode)) < 0 && !*loopro
411 && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) {
412 perror (file);
413 return 1;
414 }
415 if ((fd = open (device, mode)) < 0) {
416 close(ffd);
417 perror (device);
418 return 1;
419 }
420 *loopro = (mode == O_RDONLY);
421
422 memset(&loopinfo, 0, sizeof(loopinfo));
423 strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
424 loopinfo.lo_name[LO_NAME_SIZE-1] = 0;
425
426 loopinfo.lo_offset = offset;
427
428 loopinfo.lo_encrypt_key_size = 0;
429 if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
430 perror("ioctl: LOOP_SET_FD");
431 close(fd);
432 close(ffd);
433 return 1;
434 }
435 if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
436 (void) ioctl(fd, LOOP_CLR_FD, 0);
437 perror("ioctl: LOOP_SET_STATUS");
438 close(fd);
439 close(ffd);
440 return 1;
441 }
442 close(fd);
443 close(ffd);
444 return 0;
445}
446
447char *find_unused_loop_device (void)
448{
449 char dev[20];
450 int i, fd;
451 struct stat statbuf;
452 struct loop_info loopinfo;
453
454 for(i = 0; i <= 7; i++) {
455 sprintf(dev, "/dev/loop%d", i);
456 if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
457 if ((fd = open (dev, O_RDONLY)) >= 0) {
458 if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == -1 &&
459 errno == ENXIO) { /* probably free */
460 close (fd);
461 return strdup(dev);
462 }
463 close (fd);
464 }
465 }
466 }
467 return NULL;
468}
469#endif /* BB_FEATURE_MOUNT_LOOP */
diff --git a/networking/ping.c b/networking/ping.c
index 92b62def3..2b6e7f5f2 100644
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: ping.c,v 1.6 1999/12/11 08:41:28 andersen Exp $ 2 * $Id: ping.c,v 1.7 2000/01/26 20:06:48 erik Exp $
3 * Mini ping implementation for busybox 3 * Mini ping implementation for busybox
4 * 4 *
5 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> 5 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
@@ -319,10 +319,11 @@ static void ping(char *host)
319 int sockopt; 319 int sockopt;
320 320
321 if (!(proto = getprotobyname("icmp"))) { 321 if (!(proto = getprotobyname("icmp"))) {
322 fprintf(stderr, "ping: unknown protocol icmp\n"); 322 /* getprotobyname failed, so just silently force
323 exit(1); 323 * proto->p_proto to have the correct value for "icmp" */
324 proto->p_proto = 1;
324 } 325 }
325 if ((pingsock = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) { 326 if ((pingsock = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) { /* 1 == ICMP */
326 if (errno == EPERM) { 327 if (errno == EPERM) {
327 fprintf(stderr, "ping: permission denied. (are you root?)\n"); 328 fprintf(stderr, "ping: permission denied. (are you root?)\n");
328 } else { 329 } else {
diff --git a/ping.c b/ping.c
index 92b62def3..2b6e7f5f2 100644
--- a/ping.c
+++ b/ping.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: ping.c,v 1.6 1999/12/11 08:41:28 andersen Exp $ 2 * $Id: ping.c,v 1.7 2000/01/26 20:06:48 erik Exp $
3 * Mini ping implementation for busybox 3 * Mini ping implementation for busybox
4 * 4 *
5 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> 5 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
@@ -319,10 +319,11 @@ static void ping(char *host)
319 int sockopt; 319 int sockopt;
320 320
321 if (!(proto = getprotobyname("icmp"))) { 321 if (!(proto = getprotobyname("icmp"))) {
322 fprintf(stderr, "ping: unknown protocol icmp\n"); 322 /* getprotobyname failed, so just silently force
323 exit(1); 323 * proto->p_proto to have the correct value for "icmp" */
324 proto->p_proto = 1;
324 } 325 }
325 if ((pingsock = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) { 326 if ((pingsock = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) { /* 1 == ICMP */
326 if (errno == EPERM) { 327 if (errno == EPERM) {
327 fprintf(stderr, "ping: permission denied. (are you root?)\n"); 328 fprintf(stderr, "ping: permission denied. (are you root?)\n");
328 } else { 329 } else {
diff --git a/umount.c b/umount.c
index 9ad6f26c2..68b27e385 100644
--- a/umount.c
+++ b/umount.c
@@ -28,14 +28,6 @@
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
39static const char umount_usage[] = 31static const char umount_usage[] =
40"umount [flags] filesystem|directory\n\n" 32"umount [flags] filesystem|directory\n\n"
41"Flags:\n" 33"Flags:\n"
@@ -52,43 +44,34 @@ static int useMtab = TRUE;
52static int umountAll = FALSE; 44static int umountAll = FALSE;
53extern const char mtab_file[]; /* Defined in utility.c */ 45extern const char mtab_file[]; /* Defined in utility.c */
54 46
47#define MIN(x,y) (x > y ? x : y)
48
55static int 49static int
56do_umount(const char* name, int useMtab) 50do_umount(const char* name, int useMtab)
57{ 51{
58 int status; 52 int status;
59 53 struct mntent *m;
60#if defined BB_FEATURE_MOUNT_LOOP 54 FILE *mountTable;
61 /* check to see if this is a loop device */ 55 const char *blockDevice = NULL;
62 struct stat fst; 56
63 char dev[20]; 57 if ((mountTable = setmntent (mtab_file, "r"))) {
64 const char *oldname = NULL; 58 while ((m = getmntent (mountTable)) != 0) {
65 int i; 59 if (strncmp(m->mnt_dir, name,
66 60 MIN(strlen(m->mnt_dir),strlen(name))) == 0)
67 if (stat(name, &fst)) { 61 blockDevice = m->mnt_fsname;
68 fprintf(stderr, "umount: %s: %s\n", name, strerror(errno)); 62 else if (strcmp(m->mnt_fsname, name) == 0) {
69 exit(1); 63 blockDevice = name;
70 } 64 name = m->mnt_dir;
71 for (i = 0 ; i <= 7 ; i++) { 65 }
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 } 66 }
81 } 67 }
82#endif
83 68
84 status = umount(name); 69 status = umount(name);
85 70
86#if defined BB_FEATURE_MOUNT_LOOP 71#if defined BB_FEATURE_MOUNT_LOOP
87 if (!strncmp("/dev/loop", name, 9)) { /* this was a loop device, delete it */ 72 if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9))
88 del_loop(name); 73 /* this was a loop device, delete it */
89 if (oldname != NULL) 74 del_loop(blockDevice);
90 name = oldname;
91 }
92#endif 75#endif
93#if defined BB_MTAB 76#if defined BB_MTAB
94 if ( status == 0 ) { 77 if ( status == 0 ) {
@@ -178,20 +161,3 @@ umount_main(int argc, char** argv)
178 } 161 }
179} 162}
180 163
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 709c7fc49..3c1568aad 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -127,11 +127,11 @@ do_mount(char* specialfile, char* dir, char* filesystemtype,
127 specialfile = find_unused_loop_device(); 127 specialfile = find_unused_loop_device();
128 if (specialfile == NULL) { 128 if (specialfile == NULL) {
129 fprintf(stderr, "Could not find a spare loop device\n"); 129 fprintf(stderr, "Could not find a spare loop device\n");
130 exit(1); 130 return( FALSE);
131 } 131 }
132 if (set_loop (specialfile, lofile, 0, &loro)) { 132 if (set_loop (specialfile, lofile, 0, &loro)) {
133 fprintf(stderr, "Could not setup loop device\n"); 133 fprintf(stderr, "Could not setup loop device\n");
134 exit(1); 134 return( FALSE);
135 } 135 }
136 if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */ 136 if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */
137 fprintf(stderr, "WARNING: loop device is read-only\n"); 137 fprintf(stderr, "WARNING: loop device is read-only\n");
@@ -141,15 +141,26 @@ do_mount(char* specialfile, char* dir, char* filesystemtype,
141#endif 141#endif
142 status=mount(specialfile, dir, filesystemtype, flags, string_flags); 142 status=mount(specialfile, dir, filesystemtype, flags, string_flags);
143 } 143 }
144#if defined BB_MTAB 144
145
146 /* If the mount was sucessful, do anything needed, then return TRUE */
145 if (status == 0) { 147 if (status == 0) {
146 if (useMtab==TRUE) 148
149#if defined BB_MTAB
150 if (useMtab==TRUE) {
147 write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts); 151 write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts);
148 return 0; 152 }
153#endif
154 return( TRUE);
155 }
156
157 /* Bummer. mount failed. Clean up */
158#if defined BB_FEATURE_MOUNT_LOOP
159 if (specialfile != NULL) {
160 del_loop(specialfile);
149 } 161 }
150 else
151#endif 162#endif
152 return(status); 163 return( FALSE);
153} 164}
154 165
155 166
@@ -166,6 +177,75 @@ extern void whine_if_fstab_is_missing()
166#endif 177#endif
167 178
168 179
180#if defined BB_FEATURE_MOUNT_LOOP
181static int set_loop(const char *device, const char *file, int offset, int *loopro)
182{
183 struct loop_info loopinfo;
184 int fd, ffd, mode;
185
186 mode = *loopro ? O_RDONLY : O_RDWR;
187 if ((ffd = open (file, mode)) < 0 && !*loopro
188 && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) {
189 perror (file);
190 return 1;
191 }
192 if ((fd = open (device, mode)) < 0) {
193 close(ffd);
194 perror (device);
195 return 1;
196 }
197 *loopro = (mode == O_RDONLY);
198
199 memset(&loopinfo, 0, sizeof(loopinfo));
200 strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
201 loopinfo.lo_name[LO_NAME_SIZE-1] = 0;
202
203 loopinfo.lo_offset = offset;
204
205 loopinfo.lo_encrypt_key_size = 0;
206 if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
207 perror("ioctl: LOOP_SET_FD");
208 close(fd);
209 close(ffd);
210 return 1;
211 }
212 if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
213 (void) ioctl(fd, LOOP_CLR_FD, 0);
214 perror("ioctl: LOOP_SET_STATUS");
215 close(fd);
216 close(ffd);
217 return 1;
218 }
219 close(fd);
220 close(ffd);
221 return 0;
222}
223
224char *find_unused_loop_device (void)
225{
226 char dev[20];
227 int i, fd;
228 struct stat statbuf;
229 struct loop_info loopinfo;
230
231 for(i = 0; i <= 7; i++) {
232 sprintf(dev, "/dev/loop%d", i);
233 if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
234 if ((fd = open (dev, O_RDONLY)) >= 0) {
235 if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == -1) {
236 if (errno == ENXIO) { /* probably free */
237 close (fd);
238 return strdup(dev);
239 }
240 }
241 close (fd);
242 }
243 }
244 }
245 return NULL;
246}
247#endif /* BB_FEATURE_MOUNT_LOOP */
248
169/* Seperate standard mount options from the nonstandard string options */ 249/* Seperate standard mount options from the nonstandard string options */
170static void 250static void
171parse_mount_options ( char *options, unsigned long *flags, char *strflags) 251parse_mount_options ( char *options, unsigned long *flags, char *strflags)
@@ -240,7 +320,7 @@ mount_one(char *blockDevice, char *directory, char *filesystemType,
240 status = do_mount (blockDevice, directory, filesystemType, 320 status = do_mount (blockDevice, directory, filesystemType,
241 flags | MS_MGC_VAL, string_flags, useMtab, 321 flags | MS_MGC_VAL, string_flags, useMtab,
242 fakeIt, mtab_opts); 322 fakeIt, mtab_opts);
243 if (status == 0) 323 if (status == TRUE)
244 break; 324 break;
245 } 325 }
246 } 326 }
@@ -253,7 +333,7 @@ mount_one(char *blockDevice, char *directory, char *filesystemType,
253 fakeIt, mtab_opts); 333 fakeIt, mtab_opts);
254 } 334 }
255 335
256 if (status) { 336 if (status==FALSE) {
257 fprintf (stderr, "Mounting %s on %s failed: %s\n", 337 fprintf (stderr, "Mounting %s on %s failed: %s\n",
258 blockDevice, directory, strerror(errno)); 338 blockDevice, directory, strerror(errno));
259 return (FALSE); 339 return (FALSE);
@@ -400,70 +480,3 @@ goodbye:
400 usage( mount_usage); 480 usage( mount_usage);
401} 481}
402 482
403#if defined BB_FEATURE_MOUNT_LOOP
404static int set_loop(const char *device, const char *file, int offset, int *loopro)
405{
406 struct loop_info loopinfo;
407 int fd, ffd, mode;
408
409 mode = *loopro ? O_RDONLY : O_RDWR;
410 if ((ffd = open (file, mode)) < 0 && !*loopro
411 && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) {
412 perror (file);
413 return 1;
414 }
415 if ((fd = open (device, mode)) < 0) {
416 close(ffd);
417 perror (device);
418 return 1;
419 }
420 *loopro = (mode == O_RDONLY);
421
422 memset(&loopinfo, 0, sizeof(loopinfo));
423 strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
424 loopinfo.lo_name[LO_NAME_SIZE-1] = 0;
425
426 loopinfo.lo_offset = offset;
427
428 loopinfo.lo_encrypt_key_size = 0;
429 if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
430 perror("ioctl: LOOP_SET_FD");
431 close(fd);
432 close(ffd);
433 return 1;
434 }
435 if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
436 (void) ioctl(fd, LOOP_CLR_FD, 0);
437 perror("ioctl: LOOP_SET_STATUS");
438 close(fd);
439 close(ffd);
440 return 1;
441 }
442 close(fd);
443 close(ffd);
444 return 0;
445}
446
447char *find_unused_loop_device (void)
448{
449 char dev[20];
450 int i, fd;
451 struct stat statbuf;
452 struct loop_info loopinfo;
453
454 for(i = 0; i <= 7; i++) {
455 sprintf(dev, "/dev/loop%d", i);
456 if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
457 if ((fd = open (dev, O_RDONLY)) >= 0) {
458 if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == -1 &&
459 errno == ENXIO) { /* probably free */
460 close (fd);
461 return strdup(dev);
462 }
463 close (fd);
464 }
465 }
466 }
467 return NULL;
468}
469#endif /* BB_FEATURE_MOUNT_LOOP */
diff --git a/util-linux/umount.c b/util-linux/umount.c
index 9ad6f26c2..68b27e385 100644
--- a/util-linux/umount.c
+++ b/util-linux/umount.c
@@ -28,14 +28,6 @@
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
39static const char umount_usage[] = 31static const char umount_usage[] =
40"umount [flags] filesystem|directory\n\n" 32"umount [flags] filesystem|directory\n\n"
41"Flags:\n" 33"Flags:\n"
@@ -52,43 +44,34 @@ static int useMtab = TRUE;
52static int umountAll = FALSE; 44static int umountAll = FALSE;
53extern const char mtab_file[]; /* Defined in utility.c */ 45extern const char mtab_file[]; /* Defined in utility.c */
54 46
47#define MIN(x,y) (x > y ? x : y)
48
55static int 49static int
56do_umount(const char* name, int useMtab) 50do_umount(const char* name, int useMtab)
57{ 51{
58 int status; 52 int status;
59 53 struct mntent *m;
60#if defined BB_FEATURE_MOUNT_LOOP 54 FILE *mountTable;
61 /* check to see if this is a loop device */ 55 const char *blockDevice = NULL;
62 struct stat fst; 56
63 char dev[20]; 57 if ((mountTable = setmntent (mtab_file, "r"))) {
64 const char *oldname = NULL; 58 while ((m = getmntent (mountTable)) != 0) {
65 int i; 59 if (strncmp(m->mnt_dir, name,
66 60 MIN(strlen(m->mnt_dir),strlen(name))) == 0)
67 if (stat(name, &fst)) { 61 blockDevice = m->mnt_fsname;
68 fprintf(stderr, "umount: %s: %s\n", name, strerror(errno)); 62 else if (strcmp(m->mnt_fsname, name) == 0) {
69 exit(1); 63 blockDevice = name;
70 } 64 name = m->mnt_dir;
71 for (i = 0 ; i <= 7 ; i++) { 65 }
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 } 66 }
81 } 67 }
82#endif
83 68
84 status = umount(name); 69 status = umount(name);
85 70
86#if defined BB_FEATURE_MOUNT_LOOP 71#if defined BB_FEATURE_MOUNT_LOOP
87 if (!strncmp("/dev/loop", name, 9)) { /* this was a loop device, delete it */ 72 if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9))
88 del_loop(name); 73 /* this was a loop device, delete it */
89 if (oldname != NULL) 74 del_loop(blockDevice);
90 name = oldname;
91 }
92#endif 75#endif
93#if defined BB_MTAB 76#if defined BB_MTAB
94 if ( status == 0 ) { 77 if ( status == 0 ) {
@@ -178,20 +161,3 @@ umount_main(int argc, char** argv)
178 } 161 }
179} 162}
180 163
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/utility.c b/utility.c
index 8139f38d9..643c3b5f2 100644
--- a/utility.c
+++ b/utility.c
@@ -36,6 +36,13 @@
36#include <unistd.h> 36#include <unistd.h>
37#include <ctype.h> 37#include <ctype.h>
38 38
39#if defined BB_FEATURE_MOUNT_LOOP
40#include <fcntl.h>
41#include <sys/ioctl.h>
42#include <linux/loop.h>
43#endif
44
45
39#if defined BB_MOUNT || defined BB_UMOUNT || defined BB_DF 46#if defined BB_MOUNT || defined BB_UMOUNT || defined BB_DF
40# if defined BB_FEATURE_USE_PROCFS 47# if defined BB_FEATURE_USE_PROCFS
41const char mtab_file[] = "/proc/mounts"; 48const char mtab_file[] = "/proc/mounts";
@@ -1146,4 +1153,22 @@ extern int vdprintf(int d, const char *format, va_list ap)
1146} 1153}
1147#endif 1154#endif
1148 1155
1156#if defined BB_FEATURE_MOUNT_LOOP
1157extern int del_loop(const char *device)
1158{
1159 int fd;
1160
1161 if ((fd = open(device, O_RDONLY)) < 0) {
1162 perror(device);
1163 return( FALSE);
1164 }
1165 if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
1166 perror("ioctl: LOOP_CLR_FD");
1167 return( FALSE);
1168 }
1169 close(fd);
1170 return( TRUE);
1171}
1172#endif
1173
1149/* END CODE */ 1174/* END CODE */