123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- /*
- * Copyright (C) 2005-2009 Junjiro Okajima
- *
- * This program, aufs is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
- /*
- * The main purpose of this script is updating /etc/mtab and calling auplilnk.
- * This behaviour is highly depending on mount(8) in util-linux package.
- */
- #define _XOPEN_SOURCE 500 /* getsubopt */
- #define _BSD_SOURCE /* dirfd */
- #include <sys/types.h>
- #include <dirent.h>
- #include <mntent.h>
- #include <regex.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <wait.h>
- #include <linux/aufs_type.h>
- #include "au_util.h"
- enum { Remount, Bind, Fake, Update, Verbose, AuFlush, LastOpt };
- static void test_opts(char opts[], unsigned char flags[])
- {
- int c;
- char *p, *o, *val, *pat[] = {
- [Remount] = "remount",
- [Bind] = "bind",
- NULL
- };
- o = strdup(opts);
- if (!o)
- AuFin("stdup");
- p = o;
- while (*p) {
- c = getsubopt(&p, pat, &val);
- switch (c) {
- case Remount:
- flags[Remount] = 1;
- break;
- case Bind:
- flags[Bind] = 1;
- break;
- }
- }
- free(o);
- }
- static int test_flush(char opts[])
- {
- int err, i;
- regex_t preg;
- char *p, *o;
- const char *pat = "^((add|ins|append|prepend|del)[:=]"
- "|(mod|imod)[:=][^,]*=ro"
- "|(noplink|ro)$)";
- o = strdup(opts);
- if (!o)
- AuFin("stdup");
- p = o;
- i = 1;
- while ((p = strchr(p, ','))) {
- i++;
- *p++ = 0;
- }
- /* todo: try getsubopt(3)? */
- err = regcomp(&preg, pat, REG_EXTENDED | REG_NOSUB);
- if (err)
- AuFin("regcomp");
- p = o;
- while (i--) {
- if (!regexec(&preg, p, 0, NULL, 0)) {
- err = 1;
- break;
- } else
- p += strlen(p) + 1;
- }
- regfree(&preg);
- free(o);
- return err;
- }
- static void do_mount(char *dev, char *mntpnt, int argc, char *argv[],
- unsigned char flags[])
- {
- int i;
- const int ac = argc + 6;
- char *av[ac], **a;
- /* todo: eliminate the duplicated options */
- a = av;
- *a++ = "mount";
- *a++ = "-i";
- if (flags[Fake])
- *a++ = "-f";
- if (!flags[Bind] || !flags[Update])
- *a++ = "-n";
- if (flags[Bind] && flags[Verbose])
- *a++ = "-v";
- *a++ = "-t";
- *a++ = AUFS_NAME;
- for (i = 3; i < argc; i++)
- if (strcmp(argv[i], "-v") && strcmp(argv[i], "-n"))
- *a++ = argv[i];
- *a++ = dev;
- *a++ = mntpnt;
- *a++ = NULL;
- #ifdef DEBUG
- for (i = 0; av[i] && i < ac; i++)
- puts(av[i]);
- exit(0);
- #endif
- execvp("mount", av);
- AuFin("mount");
- }
- /* ---------------------------------------------------------------------- */
- int main(int argc, char *argv[])
- {
- int err, c, status;
- pid_t pid;
- unsigned char flags[LastOpt];
- struct mntent ent;
- char *dev, *mntpnt, *opts, *cwd;
- DIR *cur;
- if (argc < 3) {
- errno = EINVAL;
- AuFin(NULL);
- }
- memset(flags, 0, sizeof(flags));
- flags[Update] = 1;
- opts = NULL;
- /* mount(8) always passes the arguments in this order */
- dev = argv[1];
- mntpnt = argv[2];
- while ((c = getopt(argc - 2, argv + 2, "fnvo:")) != -1) {
- switch (c) {
- case 'f':
- flags[Fake] = 1;
- break;
- case 'n':
- flags[Update] = 0;
- break;
- case 'v':
- flags[Verbose] = 1;
- break;
- case 'o':
- opts = optarg;
- break;
- case '?':
- case ':':
- errno = EINVAL;
- AuFin("internal error");
- }
- }
- cur = opendir(".");
- if (!cur)
- AuFin(".");
- err = chdir(mntpnt);
- if (err)
- AuFin("%s", mntpnt);
- cwd = getcwd(NULL, 0); /* glibc */
- if (!cwd)
- AuFin("getcwd");
- err = fchdir(dirfd(cur));
- if (err)
- AuFin("fchdir");
- closedir(cur); /* ignore */
- if (opts)
- test_opts(opts, flags);
- if (!flags[Bind] && flags[Update]) {
- err = access(MTab, R_OK | W_OK);
- if (err)
- AuFin(MTab);
- }
- if (flags[Remount]) {
- errno = EINVAL;
- if (flags[Bind])
- AuFin("both of remount and bind are specified");
- flags[AuFlush] = test_flush(opts);
- if (flags[AuFlush] /* && !flags[Fake] */) {
- err = au_plink(cwd, AuPlink_FLUSH, 1, 1);
- if (err)
- AuFin(NULL);
- }
- }
- pid = fork();
- if (!pid) {
- /* actual mount operation */
- do_mount(dev, mntpnt, argc, argv, flags);
- return 0;
- } else if (pid < 0)
- AuFin("fork");
- err = waitpid(pid, &status, 0);
- if (err < 0)
- AuFin("child process");
- err = !WIFEXITED(status);
- if (!err)
- err = WEXITSTATUS(status);
- if (!err && !flags[Bind]) {
- if (flags[Update])
- err = au_update_mtab(cwd, flags[Remount],
- flags[Verbose]);
- else if (flags[Verbose]) {
- /* withoug blocking plink */
- err = au_proc_getmntent(cwd, &ent);
- if (!err)
- au_print_ent(&ent);
- else
- AuFin("internal error");
- }
- }
- return err;
- }
|