diff options
| author | Jay Freeman (saurik) <saurik@saurik.com> | 2008-11-20 03:37:30 +0000 |
|---|---|---|
| committer | Jay Freeman (saurik) <saurik@saurik.com> | 2008-11-20 18:38:36 +0000 |
| commit | e520d036165b36cf5c4cb305f9cec7d183977b61 (patch) | |
| tree | 0d8d9be5d26483338bbe42e7503255c6a1a12c51 /init | |
| parent | abb9638e3696e393d6dc45439feda91073e52103 (diff) | |
| download | system_core-e520d036165b36cf5c4cb305f9cec7d183977b61.tar.gz system_core-e520d036165b36cf5c4cb305f9cec7d183977b61.tar.bz2 system_core-e520d036165b36cf5c4cb305f9cec7d183977b61.zip | |
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.
Diffstat (limited to 'init')
| -rw-r--r-- | init/builtins.c | 66 |
1 files changed, 61 insertions, 5 deletions
diff --git a/init/builtins.c b/init/builtins.c index ba344100..bbee7b2d 100644 --- a/init/builtins.c +++ b/init/builtins.c @@ -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) |
