author | Olivier Brunel
<jjk@jjacky.com> 2015-02-21 13:45:43 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2015-04-04 12:47:34 UTC |
parent | 8e90851f4f33e2524ae11950365dddaabecde5aa |
doc/aa-mount.pod | +71 | -0 |
package/modes | +1 | -0 |
package/targets.mak | +2 | -0 |
src/utils/aa-mount.c | +193 | -0 |
src/utils/deps-exe/aa-mount | +2 | -0 |
src/utils/mount-constants.h | +80 | -0 |
diff --git a/doc/aa-mount.pod b/doc/aa-mount.pod new file mode 100644 index 0000000..e0c1935 --- /dev/null +++ b/doc/aa-mount.pod @@ -0,0 +1,71 @@ +=head1 NAME + +aa-mount - Mount a filesystem + +=head1 SYNOPSIS + +B<aa-mount> [B<-B> | B<-M>] [B<-r> | B<-w>] [B<-t> I<FSTYPE>] [B<-o> I<OPTIONS>] +I<DEVICE> I<MOUNTPOINT> + +=head1 OPTIONS + +=over + +=item B<-B, --bind> + +Remount subtree specified as I<DEVICE> onto I<MOUNTPOINT>, making it available +in the two places. Note that the filesystem moun options remain the same and +cannot be changed via B<--options>, you need a second call to change options, +e.g: + aa-mount -B olddir newdir + aa-mount -o remount,ro,bind olddir newdir + +=item B<-h, --help> + +Show help screen and exit. + +=item B<-M, --move> + +Move subtree specified as I<DEVICE> to I<MOUNTPOINT> So the content will be +atomically moved from its old location (I<DEVICE>) into the new one +(I<MOUNTPOINT>). + +=item B<-o, --options> I<OPTIONS> + +Set I<OPTIONS> as mount options to be used. They will be combined with any other +options specified. + +=item B<-r, --read-only> + +Mount filesystem read-only + +=item B<-t, --fstype> I<FSTYPE> + +Use I<FSTYPE> as type of filesystem. Note that "auto" isn't supported. + +=item B<-V, --version> + +Show version information and exit. + +=item B<-w, --read-write> + +Mount filesystem read-write. + +=back + +=head1 DESCRIPTION + +B<aa-mount>(1) mounts the specified filesystem using to the given options. It +does not read I</etc/fstab> (or any other file), and therefore always requires +both I<DEVICE> and I<MOUNTPOINT> to be specified; It also doesn't support an +option to mount all filesystems from anywhere. + +This also means that when using option remount you need to specify all the +options to be set, since B<aa-mount>(1) will not read I</etc/fstab> to combine +options from there with those on the command line, as B<mount>(8) does. + +Supported options are: defaults, ro, rw, bind, move, async, atime, noatime, dev, +nodev, diratime, nodiratime, dirsync, exec, noexec, mand, nomand, relatime, +norelatime, strictatime, nostrictatime, suid, nosuid, remount, sync. + +Any other options will be given to the kernel as-is. diff --git a/package/modes b/package/modes index 9f00ff7..da1e761 100644 --- a/package/modes +++ b/package/modes @@ -2,6 +2,7 @@ aa-chroot 0755 aa-echo 0755 aa-enable 0755 aa-kill 0755 +aa-mount 0755 aa-pivot 0755 aa-start 0755 aa-stop 0755 diff --git a/package/targets.mak b/package/targets.mak index 5efe0bf..31a2df9 100644 --- a/package/targets.mak +++ b/package/targets.mak @@ -7,6 +7,7 @@ LIBEXEC_TARGETS := \ aa-chroot \ aa-echo \ aa-kill \ +aa-mount \ aa-pivot DOC_TARGETS := \ @@ -18,6 +19,7 @@ aa-pivot.1 \ aa-start.1 \ aa-stop.1 \ aa-kill.1 \ +aa-mount.1 ifdef DO_ALLSTATIC LIBANOPA := libanopa.a diff --git a/src/utils/aa-mount.c b/src/utils/aa-mount.c new file mode 100644 index 0000000..13b9324 --- /dev/null +++ b/src/utils/aa-mount.c @@ -0,0 +1,193 @@ + +#include <getopt.h> +#include <sys/mount.h> +#include <skalibs/strerr2.h> +#include <skalibs/stralloc.h> +#include <anopa/common.h> +#include "mount-constants.h" + +struct mnt_opt +{ + const char *name; + unsigned int len; + unsigned long value; + enum { + OP_ADD, + OP_REM, + OP_SET + } op; +}; + +/* special: we don't own sa */ +static int +add_option (stralloc *sa, unsigned long *flags, char const *options) +{ +#define mnt_opt(name, op, val) { name, strlen (name), val, OP_##op } + struct mnt_opt mnt_options[] = { + mnt_opt ("defaults", SET, MS_MGC_VAL), + mnt_opt ("ro", ADD, MS_RDONLY), + mnt_opt ("rw", REM, MS_RDONLY), + mnt_opt ("bind", ADD, MS_BIND), + mnt_opt ("move", ADD, MS_MOVE), + mnt_opt ("async", REM, MS_SYNCHRONOUS), + mnt_opt ("atime", REM, MS_NOATIME), + mnt_opt ("noatime", ADD, MS_NOATIME), + mnt_opt ("dev", REM, MS_NODEV), + mnt_opt ("nodev", ADD, MS_NODEV), + mnt_opt ("diratime", REM, MS_NODIRATIME), + mnt_opt ("nodiratime", ADD, MS_NODIRATIME), + mnt_opt ("dirsync", ADD, MS_DIRSYNC), + mnt_opt ("exec", REM, MS_NOEXEC), + mnt_opt ("noexec", ADD, MS_NOEXEC), + mnt_opt ("mand", ADD, MS_MANDLOCK), + mnt_opt ("nomand", REM, MS_MANDLOCK), + mnt_opt ("relatime", ADD, MS_RELATIME), + mnt_opt ("norelatime", REM, MS_RELATIME), + mnt_opt ("strictatime", ADD, MS_STRICTATIME), + mnt_opt ("nostrictatime", REM, MS_STRICTATIME), + mnt_opt ("suid", REM, MS_NOSUID), + mnt_opt ("nosuid", ADD, MS_NOSUID), + mnt_opt ("remount", ADD, MS_REMOUNT), + mnt_opt ("sync", ADD, MS_SYNCHRONOUS) + }; +#undef mnt_opt + unsigned int nb = sizeof (mnt_options) / sizeof (*mnt_options); + + for (;;) + { + unsigned int e; + unsigned int i; + + e = str_chr (options, ','); + for (i = 0; i < nb; ++i) + { + if (e == mnt_options[i].len + && !str_diffn (options, mnt_options[i].name, e)) + { + switch (mnt_options[i].op) + { + case OP_ADD: + *flags |= mnt_options[i].value; + break; + + case OP_REM: + *flags &= ~mnt_options[i].value; + break; + + case OP_SET: + *flags = mnt_options[i].value; + break; + } + break; + } + } + if (i >= nb) + { + /* add user option as-is */ + if ((sa->len > 0 && !stralloc_catb (sa, ",", 1)) + || !stralloc_catb (sa, options, e)) + return 0; + } + + options += e; + if (*options == '\0') + return 1; + ++options; + } +} + +static void +dieusage (int rc) +{ + aa_die_usage (rc, "[OPTION...] DEVICE MOUNTPOINT", + " -B, --bind Remount a subtree somewhere else\n" + " -M, --move Move a subtree to some other place\n" + " -t, --type FSTYPE Use FSTYPE as type of filesystem\n" + " -o, --options OPTIONS Use OPTIONS as mount options\n" + " -r, --read-only Mount read-only\n" + " -w, --read-write Mount read-write\n" + " -h, --help Show this help screen and exit\n" + " -V, --version Show version information and exit\n" + ); +} + +int +main (int argc, char * const argv[]) +{ + PROG = "aa-mount"; + stralloc sa = STRALLOC_ZERO; + unsigned long flags = MS_MGC_VAL; + const char *fstype = NULL; + + for (;;) + { + struct option longopts[] = { + { "bind", no_argument, NULL, 'B' }, + { "help", no_argument, NULL, 'h' }, + { "move", no_argument, NULL, 'M' }, + { "options", required_argument, NULL, 'o' }, + { "read-only", no_argument, NULL, 'r' }, + { "type", required_argument, NULL, 't' }, + { "version", no_argument, NULL, 'V' }, + { "read-write", no_argument, NULL, 'w' }, + { NULL, 0, 0, 0 } + }; + int c; + + c = getopt_long (argc, argv, "BhMo:rt:Vw", longopts, NULL); + if (c == -1) + break; + switch (c) + { + case 'B': + if (!add_option (&sa, &flags, "bind")) + strerr_diefu1sys (2, "build user options"); + break; + + case 'h': + dieusage (0); + + case 'M': + if (!add_option (&sa, &flags, "move")) + strerr_diefu1sys (2, "build user options"); + break; + + case 'o': + if (!add_option (&sa, &flags, optarg)) + strerr_diefu1sys (2, "build user options"); + break; + + case 'r': + if (!add_option (&sa, &flags, "ro")) + strerr_diefu1sys (2, "build user options"); + break; + + case 't': + fstype = optarg; + break; + + case 'V': + aa_die_version (); + + case 'w': + if (!add_option (&sa, &flags, "rw")) + strerr_diefu1sys (2, "build user options"); + break; + + default: + dieusage (1); + } + } + argc -= optind; + argv += optind; + + if (argc < 2) + dieusage (1); + + if (!stralloc_0 (&sa)) + strerr_diefu1sys (2, "build user options"); + if (mount (argv[0], argv[1], fstype, flags, sa.s) < 0) + strerr_diefu4sys (3, "mount ", argv[0], " on ", argv[1]); + + return 0; +} diff --git a/src/utils/deps-exe/aa-mount b/src/utils/deps-exe/aa-mount new file mode 100644 index 0000000..30987b4 --- /dev/null +++ b/src/utils/deps-exe/aa-mount @@ -0,0 +1,2 @@ +${LIBANOPA} +-lskarnet diff --git a/src/utils/mount-constants.h b/src/utils/mount-constants.h new file mode 100644 index 0000000..10a27cc --- /dev/null +++ b/src/utils/mount-constants.h @@ -0,0 +1,80 @@ + +#ifndef AA_MOUNT_CONSTANTS_H +#define AA_MOUNT_CONSTANTS_H + +/* taken from util-linux-ng */ + +#ifndef MS_RDONLY +#define MS_RDONLY 1 /* Mount read-only */ +#endif +#ifndef MS_NOSUID +#define MS_NOSUID 2 /* Ignore suid and sgid bits */ +#endif +#ifndef MS_NODEV +#define MS_NODEV 4 /* Disallow access to device special files */ +#endif +#ifndef MS_NOEXEC +#define MS_NOEXEC 8 /* Disallow program execution */ +#endif +#ifndef MS_SYNCHRONOUS +#define MS_SYNCHRONOUS 16 /* Writes are synced at once */ +#endif +#ifndef MS_REMOUNT +#define MS_REMOUNT 32 /* Alter flags of a mounted FS */ +#endif +#ifndef MS_MANDLOCK +#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ +#endif +#ifndef MS_DIRSYNC +#define MS_DIRSYNC 128 /* Directory modifications are synchronous */ +#endif +#ifndef MS_NOATIME +#define MS_NOATIME 0x400 /* 1024: Do not update access times. */ +#endif +#ifndef MS_NODIRATIME +#define MS_NODIRATIME 0x800 /* 2048: Don't update directory access times */ +#endif +#ifndef MS_BIND +#define MS_BIND 0x1000 /* 4096: Mount existing tree also elsewhere */ +#endif +#ifndef MS_MOVE +#define MS_MOVE 0x2000 /* 8192: Atomically move tree */ +#endif +#ifndef MS_REC +#define MS_REC 0x4000 /* 16384: Recursive loopback */ +#endif +#ifndef MS_VERBOSE +#define MS_VERBOSE 0x8000 /* 32768 */ +#endif +#ifndef MS_RELATIME +#define MS_RELATIME 0x200000 /* 200000: Update access times relative to mtime/ctime */ +#endif +#ifndef MS_UNBINDABLE +#define MS_UNBINDABLE (1<<17) /* 131072 unbindable */ +#endif +#ifndef MS_PRIVATE +#define MS_PRIVATE (1<<18) /* 262144 Private */ +#endif +#ifndef MS_SLAVE +#define MS_SLAVE (1<<19) /* 524288 Slave */ +#endif +#ifndef MS_SHARED +#define MS_SHARED (1<<20) /* 1048576 Shared */ +#endif +#ifndef MS_I_VERSION +#define MS_I_VERSION (1<<23) /* update inode I_version field */ +#endif +#ifndef MS_STRICTATIME +#define MS_STRICTATIME (1<<24) /* strict atime semantics */ +#endif +/* + * Magic mount flag number. Had to be or-ed to the flag values. + */ +#ifndef MS_MGC_VAL +#define MS_MGC_VAL 0xC0ED0000 /* magic flag number to indicate "new" flags */ +#endif +#ifndef MS_MGC_MSK +#define MS_MGC_MSK 0xffff0000 /* magic flag number mask */ +#endif + +#endif /* AA_MOUNT_CONSTANTS_H */