aboutsummaryrefslogtreecommitdiff
path: root/mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'mount.c')
-rw-r--r--mount.c139
1 files changed, 125 insertions, 14 deletions
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 */