Added support for loop@/path/to/filename to init's mount.

In keeping with the pattern of mtd@partition, I have added loop@path as a way to specify a loopback device. This way you can do things like mount directories in /system using cramfs from a file otherwise on /system (just one example oof how I'm using it). I specifically went with loop@ rather than adding this feature as a flag as the flags system is designed to set bits in the flags argument to mount: using loop@ fit the model in a much simpler manner and actually feels "correct".

This is a better version of the previously submitted 4045 that also refactors the mtd@ case. The reason for this is that I received comments that I should check for errors and return errors rather that do work in the case of success and fall through, but the mtd@ case wasn't doing that either and it became awkward to design the function so that it was half in one style of error handling and half in another. I also made certain to use inequality comparisons for Unix's -1 error returns rather than checking for -1, refactored my large if statement so as not to have danling parentheses, and disassocited the loop device on mount failure.
This commit is contained in:
Jay Freeman (saurik) 2008-11-20 03:37:30 +00:00
parent abb9638e36
commit e520d03616
1 changed files with 61 additions and 5 deletions

View File

@ -29,6 +29,7 @@
#include <stdlib.h>
#include <sys/mount.h>
#include <sys/resource.h>
#include <linux/loop.h>
#include "init.h"
#include "keywords.h"
@ -231,7 +232,7 @@ static struct {
int do_mount(int nargs, char **args)
{
char tmp[64];
char *source;
char *source, *target, *system;
char *options = NULL;
unsigned flags = 0;
int n, i;
@ -249,15 +250,70 @@ int do_mount(int nargs, char **args)
options = args[n];
}
system = args[1];
source = args[2];
target = args[3];
if (!strncmp(source, "mtd@", 4)) {
n = mtd_name_to_number(source + 4);
if (n >= 0) {
sprintf(tmp, "/dev/block/mtdblock%d", n);
source = tmp;
if (n < 0) {
return -1;
}
sprintf(tmp, "/dev/block/mtdblock%d", n);
if (mount(tmp, target, system, flags, options) < 0) {
return -1;
}
return 0;
} else if (!strncmp(source, "loop@", 5)) {
int mode, loop, fd;
struct loop_info info;
mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR;
fd = open(source + 5, mode);
if (fd < 0) {
return -1;
}
for (n = 0; ; n++) {
sprintf(tmp, "/dev/block/loop%d", n);
loop = open(tmp, mode);
if (loop < 0) {
return -1;
}
/* if it is a blank loop device */
if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) {
/* if it becomes our loop device */
if (ioctl(loop, LOOP_SET_FD, fd) >= 0) {
close(fd);
if (mount(tmp, target, system, flags, options) < 0) {
ioctl(loop, LOOP_CLR_FD, 0);
close(loop);
return -1;
}
close(loop);
return 0;
}
}
close(loop);
}
close(fd);
ERROR("out of loopback devices");
return -1;
} else {
if (mount(source, target, system, flags, options) < 0) {
return -1;
}
return 0;
}
return mount(source, args[3], args[1], flags, options);
}
int do_setkey(int nargs, char **args)