Add -o loop= option to mount, and fix error detection in mount and umount
This fixes bug http://b.android.com/18419, which complains about a bogus error check in the mount command (it also was wrong in the umount command) and also asks for the mount command to support more than one loopback device, as mentioned in the FIXME comments in mount.c. This required some corresponding changes to umount.c Change-Id: Ib796c70926395e61557e487bad64984d3295d5f3
This commit is contained in:
parent
ed6b39cc77
commit
940c81078e
2 changed files with 43 additions and 19 deletions
|
|
@ -15,8 +15,8 @@
|
|||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
// FIXME - only one loop mount is supported at a time
|
||||
#define LOOP_DEVICE "/dev/block/loop0"
|
||||
#define DEFAULT_LOOP_DEVICE "/dev/block/loop0"
|
||||
#define LOOPDEV_MAXLEN 64
|
||||
|
||||
struct mount_opts {
|
||||
const char str[8];
|
||||
|
|
@ -87,7 +87,7 @@ static void add_extra_option(struct extra_opts *extra, char *s)
|
|||
}
|
||||
|
||||
static unsigned long
|
||||
parse_mount_options(char *arg, unsigned long rwflag, struct extra_opts *extra, int* loop)
|
||||
parse_mount_options(char *arg, unsigned long rwflag, struct extra_opts *extra, int* loop, char *loopdev)
|
||||
{
|
||||
char *s;
|
||||
|
||||
|
|
@ -100,8 +100,15 @@ parse_mount_options(char *arg, unsigned long rwflag, struct extra_opts *extra, i
|
|||
if (no)
|
||||
s += 2;
|
||||
|
||||
if (strncmp(s, "loop=", 5) == 0) {
|
||||
*loop = 1;
|
||||
strlcpy(loopdev, s + 5, LOOPDEV_MAXLEN);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(s, "loop") == 0) {
|
||||
*loop = 1;
|
||||
strlcpy(loopdev, DEFAULT_LOOP_DEVICE, LOOPDEV_MAXLEN);
|
||||
continue;
|
||||
}
|
||||
for (i = 0, res = 1; i < ARRAY_SIZE(options); i++) {
|
||||
|
|
@ -131,7 +138,8 @@ static struct extra_opts extra;
|
|||
static unsigned long rwflag;
|
||||
|
||||
static int
|
||||
do_mount(char *dev, char *dir, char *type, unsigned long rwflag, void *data, int loop)
|
||||
do_mount(char *dev, char *dir, char *type, unsigned long rwflag, void *data, int loop,
|
||||
char *loopdev)
|
||||
{
|
||||
char *s;
|
||||
int error = 0;
|
||||
|
|
@ -142,14 +150,13 @@ do_mount(char *dev, char *dir, char *type, unsigned long rwflag, void *data, int
|
|||
|
||||
flags = (rwflag & MS_RDONLY) ? O_RDONLY : O_RDWR;
|
||||
|
||||
// FIXME - only one loop mount supported at a time
|
||||
file_fd = open(dev, flags);
|
||||
if (file_fd < -1) {
|
||||
if (file_fd < 0) {
|
||||
perror("open backing file failed");
|
||||
return 1;
|
||||
}
|
||||
device_fd = open(LOOP_DEVICE, flags);
|
||||
if (device_fd < -1) {
|
||||
device_fd = open(loopdev, flags);
|
||||
if (device_fd < 0) {
|
||||
perror("open loop device failed");
|
||||
close(file_fd);
|
||||
return 1;
|
||||
|
|
@ -163,7 +170,7 @@ do_mount(char *dev, char *dir, char *type, unsigned long rwflag, void *data, int
|
|||
|
||||
close(file_fd);
|
||||
close(device_fd);
|
||||
dev = LOOP_DEVICE;
|
||||
dev = loopdev;
|
||||
}
|
||||
|
||||
while ((s = strsep(&type, ",")) != NULL) {
|
||||
|
|
@ -268,6 +275,7 @@ int mount_main(int argc, char *argv[])
|
|||
char *dir = NULL;
|
||||
int c;
|
||||
int loop = 0;
|
||||
char loopdev[LOOPDEV_MAXLEN];
|
||||
|
||||
progname = argv[0];
|
||||
rwflag = MS_VERBOSE;
|
||||
|
|
@ -281,7 +289,7 @@ int mount_main(int argc, char *argv[])
|
|||
break;
|
||||
switch (c) {
|
||||
case 'o':
|
||||
rwflag = parse_mount_options(optarg, rwflag, &extra, &loop);
|
||||
rwflag = parse_mount_options(optarg, rwflag, &extra, &loop, loopdev);
|
||||
break;
|
||||
case 'r':
|
||||
rwflag |= MS_RDONLY;
|
||||
|
|
@ -319,6 +327,6 @@ int mount_main(int argc, char *argv[])
|
|||
exit(1);
|
||||
}
|
||||
|
||||
return do_mount(dev, dir, type, rwflag, extra.str, loop);
|
||||
return do_mount(dev, dir, type, rwflag, extra.str, loop, loopdev);
|
||||
/* We leak dev and dir in some cases, but we're about to exit */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,24 @@
|
|||
#include <unistd.h>
|
||||
#include <linux/loop.h>
|
||||
|
||||
// FIXME - only one loop mount is supported at a time
|
||||
#define LOOP_DEVICE "/dev/block/loop0"
|
||||
#define LOOPDEV_MAXLEN 64
|
||||
#define LOOP_MAJOR 7
|
||||
|
||||
static int is_loop_mount(const char* path)
|
||||
static int is_loop(char *dev)
|
||||
{
|
||||
struct stat st;
|
||||
int ret = 0;
|
||||
|
||||
if (stat(dev, &st) == 0) {
|
||||
if (S_ISBLK(st.st_mode) && (major(st.st_rdev) == LOOP_MAJOR)) {
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int is_loop_mount(const char* path, char *loopdev)
|
||||
{
|
||||
FILE* f;
|
||||
int count;
|
||||
|
|
@ -29,7 +43,8 @@ static int is_loop_mount(const char* path)
|
|||
do {
|
||||
count = fscanf(f, "%255s %255s %255s\n", device, mount_path, rest);
|
||||
if (count == 3) {
|
||||
if (strcmp(LOOP_DEVICE, device) == 0 && strcmp(path, mount_path) == 0) {
|
||||
if (is_loop(device) && strcmp(path, mount_path) == 0) {
|
||||
strlcpy(loopdev, device, LOOPDEV_MAXLEN);
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
|
|
@ -43,13 +58,14 @@ static int is_loop_mount(const char* path)
|
|||
int umount_main(int argc, char *argv[])
|
||||
{
|
||||
int loop, loop_fd;
|
||||
|
||||
char loopdev[LOOPDEV_MAXLEN];
|
||||
|
||||
if(argc != 2) {
|
||||
fprintf(stderr,"umount <path>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
loop = is_loop_mount(argv[1]);
|
||||
loop = is_loop_mount(argv[1], loopdev);
|
||||
if(umount(argv[1])){
|
||||
fprintf(stderr,"failed.\n");
|
||||
return 1;
|
||||
|
|
@ -57,8 +73,8 @@ int umount_main(int argc, char *argv[])
|
|||
|
||||
if (loop) {
|
||||
// free the loop device
|
||||
loop_fd = open(LOOP_DEVICE, O_RDONLY);
|
||||
if (loop_fd < -1) {
|
||||
loop_fd = open(loopdev, O_RDONLY);
|
||||
if (loop_fd < 0) {
|
||||
perror("open loop device failed");
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue