Welcome to little lamb

Code » anopa » commit e52e63d

Add aa-mount

author Olivier Brunel
2015-02-21 13:45:43 UTC
committer Olivier Brunel
2015-04-04 12:47:34 UTC
parent 8e90851f4f33e2524ae11950365dddaabecde5aa

Add aa-mount

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 */