Skip to content

Commit

Permalink
a different approach to add an "offset" option for loop device mounts…
Browse files Browse the repository at this point in the history
… to the

mount applet

advantages/differences (in my opinion):

- less changes to the original code at all
- less hunks to maintain, if the original code will be changed in the future
- a more neutral implementation, because a present "offset" option isn't
  "eaten up" any longer, if the device to be mounted isn't a file (loop
  mounts are auto-detected anyway, the "loop" option is silently ignored
  by the original code) and so this option is still usable for other
  (future) purposes, if it's passed along the path up to the filesystem
  driver
- tested with the following cases:
  - as the only option specified => only one entry in filteropts
  ----------------------------------------------------------------------
  root@FB7490:/var/media/ftp $ mount -o offset=256 /var/media/ftp/filesystem.image /var/test;grep /var/test /proc/mounts;losetup -a | grep filesystem\.image;umount /var/test
  /dev/loop2 /var/test ext2 rw,relatime 0 0
  /dev/loop2: 256 /var/media/ftp/filesystem.image
  ----------------------------------------------------------------------
  - preceded with an option for the mount applet => even the first and last entry in filteropts
  root@FB7490:/var/media/ftp $ mount -o ro,offset=256 /var/media/ftp/filesystem.image /var/test;grep /var/test /proc/mounts;losetup -a | grep filesystem\.image;umount /var/test
  /dev/loop2 /var/test ext2 ro,relatime 0 0
  /dev/loop2: 256 /var/media/ftp/filesystem.image
  ----------------------------------------------------------------------
  - preceded with an option for the filesystem_driver => the 2nd and last entry in filteropts
  root@FB7490:/var/media/ftp $ mount -o user_xattr,offset=256 /var/media/ftp/filesystem.image /var/test;grep /var/test /proc/mounts;losetup -a | grep filesystem\.image;umount /var/test
  /dev/loop2 /var/test ext2 rw,relatime,user_xattr 0 0
  /dev/loop2: 256 /var/media/ftp/filesystem.image
  ----------------------------------------------------------------------
  - preceded with options for the filesystem_driver and a followed by another one for the applet => 2nd and last
  root@FB7490:/var/media/ftp $ mount -o user_xattr,offset=256,ro /var/media/ftp/filesystem.image /var/test;grep /var/test /proc/mounts;losetup -a | grep filesystem\.image;umount /var/test
  /dev/loop2 /var/test ext2 ro,relatime,user_xattr 0 0
  /dev/loop2: 256 /var/media/ftp/filesystem.image
  ----------------------------------------------------------------------
  - preceded with options for the filesystem_driver and a followed by another one => 2nd and not the last
  root@FB7490:/var/media/ftp $ mount -o user_xattr,offset=256,acl /var/media/ftp/filesystem.image /var/test;grep /var/test /proc/mounts;losetup -a | grep filesystem\.image;umount /var/test
  /dev/loop2 /var/test ext2 rw,relatime,user_xattr,acl 0 0
  /dev/loop2: 256 /var/media/ftp/filesystem.image
  ----------------------------------------------------------------------
  - followed by an option for the filesystem driver => first and not the last option in filteropts
  root@FB7490:/var/media/ftp $ mount -o offset=256,acl /var/media/ftp/filesystem.image /var/test;grep /var/test /proc/mounts;losetup -a | grep filesystem\.image;umount /var/test
  /dev/loop2 /var/test ext2 rw,relatime,acl 0 0
  /dev/loop2: 256 /var/media/ftp/filesystem.image
- as far as I oversee the test results, every possible combination works as expected
  • Loading branch information
PeterPawn committed Jun 12, 2016
1 parent d3f61bf commit 26e888c
Showing 1 changed file with 32 additions and 114 deletions.
146 changes: 32 additions & 114 deletions make/busybox/patches/411-mount_loop_offset_option.freetz.patch
Expand Up @@ -4,134 +4,52 @@
//usage: "\n-o OPT:"
//usage: IF_FEATURE_MOUNT_LOOP(
//usage: "\n loop Ignored (loop devices are autodetected)"
+//usage: "\n offset=OFS The data start is moved OFS bytes into the specified file or device"
+//usage: "\n offset=OFS The data start is moved OFS bytes into the specified file"
//usage: )
//usage: IF_FEATURE_MOUNT_FLAGS(
//usage: "\n [a]sync Writes are [a]synchronous"
@@ -316,6 +317,7 @@

IF_FEATURE_MOUNT_LOOP(
/* "loop" */ 0,
+ /* "offset=" */ 0,
)

IF_FEATURE_MOUNT_FSTAB(
@@ -376,6 +378,7 @@
static const char mount_option_str[] =
IF_FEATURE_MOUNT_LOOP(
"loop\0"
+ "offset=\0"
)
IF_FEATURE_MOUNT_FSTAB(
"defaults\0"
@@ -563,7 +566,7 @@

// Use the mount_options list to parse options into flags.
// Also update list of unrecognized options if unrecognized != NULL
-static unsigned long parse_mount_options(char *options, char **unrecognized)
+static unsigned long parse_mount_options(char *options, char **unrecognized, unsigned long long *loopOffset)
{
unsigned long flags = MS_SILENT;

@@ -582,8 +585,8 @@

if (strncasecmp(option_str, options, opt_len) == 0
&& (options[opt_len] == '\0'
- /* or is it "comment=" thingy in fstab? */
- IF_FEATURE_MOUNT_FSTAB(IF_DESKTOP( || option_str[opt_len-1] == '=' ))
+ /* or is it "comment=" thingy in fstab? or "offset=" loop option? */
+ || ( ((ENABLE_FEATURE_MOUNT_FSTAB && ENABLE_DESKTOP) || ENABLE_FEATURE_MOUNT_LOOP) && option_str[opt_len-1] == '=' )
)
) {
unsigned long fl = mount_options[i];
@@ -591,6 +594,12 @@
flags &= fl;
else
flags |= fl;
+
+ if (ENABLE_FEATURE_MOUNT_LOOP && loopOffset) {
+ if (strncasecmp(options, "offset=", 7) == 0)
+ *loopOffset = xatoull(options+7);
+ }
+
goto found;
}
option_str += opt_len + 1;
@@ -1875,12 +1884,13 @@
@@ -1875,6 +1876,7 @@
int rc = -1;
unsigned long vfsflags;
char *loopFile = NULL, *filteropts = NULL;
+ unsigned long long loopOffset = 0;
+ const char *offsetString = "offset=\0";
llist_t *fl = NULL;
struct stat st;

errno = 0;

- vfsflags = parse_mount_options(mp->mnt_opts, &filteropts);
+ vfsflags = parse_mount_options(mp->mnt_opts, &filteropts, &loopOffset);

// Treat fstype "auto" as unspecified
if (mp->mnt_type && strcmp(mp->mnt_type, "auto") == 0)
@@ -1955,7 +1965,7 @@
len, share,
share + len + 1 /* "dir1/dir2" */
);
- parse_mount_options(unc, &filteropts);
+ parse_mount_options(unc, &filteropts, NULL);
if (ENABLE_FEATURE_CLEAN_UP) free(unc);
}

@@ -1969,7 +1979,7 @@
if (ENABLE_FEATURE_CLEAN_UP) free(lsa);
ip = xasprintf("ip=%s", dotted);
if (ENABLE_FEATURE_CLEAN_UP) free(dotted);
- parse_mount_options(ip, &filteropts);
+ parse_mount_options(ip, &filteropts, NULL);
if (ENABLE_FEATURE_CLEAN_UP) free(ip);

mp->mnt_type = (char*)"cifs";
@@ -1999,7 +2009,7 @@
@@ -1997,9 +1999,35 @@
) {
// Do we need to allocate a loopback device for it?
if (ENABLE_FEATURE_MOUNT_LOOP && S_ISREG(st.st_mode)) {
+ long long loopOffset = 0; // no offset specified
+ char *offsetOption;
loopFile = bb_simplify_path(mp->mnt_fsname);
mp->mnt_fsname = NULL; // will receive malloced loop dev name
- if (set_loop(&mp->mnt_fsname, loopFile, 0, /*ro:*/ (vfsflags & MS_RDONLY)) < 0) {
+ if (filteropts && (offsetOption = strstr(filteropts, offsetString))) {
+ // it's only our offsetString, if preceeded by comma or we're
+ // at the very beginning of "filteropts"
+ if (offsetOption == filteropts || *(offsetOption - 1) == ',') {
+ char *nextOption;
+ // no further check for valid value is performed here,
+ // offset stays 0 if it's invalid - but we remove this
+ // option here anyway, other checks are done already
+ if ((nextOption = strchr(offsetOption, ','))) {
+ // xatoull would take a ',' as part of the number
+ // and gets into a fuss about any non-numeric
+ // character following this one
+ *(nextOption++) = '\0';
+ loopOffset = xatoull(offsetOption + strlen(offsetString));
+ strcpy(offsetOption, nextOption);
+ }
+ else { // last option, simply truncate the string
+ loopOffset = xatoull(offsetOption + strlen(offsetString));
+ nextOption = offsetOption - 1;
+ if (offsetOption == filteropts) nextOption = filteropts;
+ *nextOption = '\0';
+ }
+ }
+ }
+ if (set_loop(&mp->mnt_fsname, loopFile, loopOffset, /*ro:*/ (vfsflags & MS_RDONLY)) < 0) {
if (errno == EPERM || errno == EACCES)
bb_error_msg(bb_msg_perm_denied_are_you_root);
else
@@ -2213,7 +2223,7 @@
// Past this point, we are handling either "mount -a [opts]"
// or "mount [opts] single_param"

- cmdopt_flags = parse_mount_options(cmdopts, NULL);
+ cmdopt_flags = parse_mount_options(cmdopts, NULL, NULL);
if (nonroot && (cmdopt_flags & ~MS_SILENT)) // Non-root users cannot specify flags
bb_error_msg_and_die(bb_msg_you_must_be_root);

@@ -2287,7 +2297,7 @@
continue;

// Skip noauto and swap anyway
- if ((parse_mount_options(mtcur->mnt_opts, NULL) & (MOUNT_NOAUTO | MOUNT_SWAP))
+ if ((parse_mount_options(mtcur->mnt_opts, NULL, NULL) & (MOUNT_NOAUTO | MOUNT_SWAP))
// swap is bogus "fstype", parse_mount_options can't check fstypes
|| strcasecmp(mtcur->mnt_type, "swap") == 0
) {
@@ -2348,7 +2358,7 @@
// exit_group(32) = ?
#if 0
// In case we want to simply skip swap partitions:
- l = parse_mount_options(mtcur->mnt_opts, NULL);
+ l = parse_mount_options(mtcur->mnt_opts, NULL, NULL);
if ((l & MOUNT_SWAP)
// swap is bogus "fstype", parse_mount_options can't check fstypes
|| strcasecmp(mtcur->mnt_type, "swap") == 0
@@ -2358,7 +2368,7 @@
#endif
if (nonroot) {
// fstab must have "users" or "user"
- l = parse_mount_options(mtcur->mnt_opts, NULL);
+ l = parse_mount_options(mtcur->mnt_opts, NULL, NULL);
if (!(l & MOUNT_USERS))
bb_error_msg_and_die(bb_msg_you_must_be_root);
}

0 comments on commit 26e888c

Please sign in to comment.