2 * Copyright (C) 2005-2009 Junjiro Okajima
4 * This program, aufs is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * The main purpose of this script is updating /etc/mtab and calling auplilnk.
21 * This behaviour is highly depending on mount(8) in util-linux package.
24 #define _XOPEN_SOURCE 500 /* getsubopt */
25 #define _BSD_SOURCE /* dirfd */
27 #include <sys/types.h>
37 #include <linux/aufs_type.h>
40 enum { Remount
, Bind
, Fake
, Update
, Verbose
, AuFlush
, LastOpt
};
41 static void test_opts(char opts
[], unsigned char flags
[])
44 char *p
, *o
, *val
, *pat
[] = {
45 [Remount
] = "remount",
56 c
= getsubopt(&p
, pat
, &val
);
69 static int test_flush(char opts
[])
74 const char *pat
= "^((add|ins|append|prepend|del)[:=]"
75 "|(mod|imod)[:=][^,]*=ro"
85 while ((p
= strchr(p
, ','))) {
90 /* todo: try getsubopt(3)? */
91 err
= regcomp(&preg
, pat
, REG_EXTENDED
| REG_NOSUB
);
97 if (!regexec(&preg
, p
, 0, NULL
, 0)) {
109 static void do_mount(char *dev
, char *mntpnt
, int argc
, char *argv
[],
110 unsigned char flags
[])
113 const int ac
= argc
+ 6;
116 /* todo: eliminate the duplicated options */
122 if (!flags
[Bind
] || !flags
[Update
])
124 if (flags
[Bind
] && flags
[Verbose
])
129 for (i
= 3; i
< argc
; i
++)
130 if (strcmp(argv
[i
], "-v") && strcmp(argv
[i
], "-n"))
137 for (i
= 0; av
[i
] && i
< ac
; i
++)
145 /* ---------------------------------------------------------------------- */
147 int main(int argc
, char *argv
[])
151 unsigned char flags
[LastOpt
];
153 char *dev
, *mntpnt
, *opts
, *cwd
;
161 memset(flags
, 0, sizeof(flags
));
165 /* mount(8) always passes the arguments in this order */
168 while ((c
= getopt(argc
- 2, argv
+ 2, "fnvo:")) != -1) {
185 AuFin("internal error");
195 cwd
= getcwd(NULL
, 0); /* glibc */
198 err
= fchdir(dirfd(cur
));
201 closedir(cur
); /* ignore */
204 test_opts(opts
, flags
);
206 if (!flags
[Bind
] && flags
[Update
]) {
207 err
= access(MTab
, R_OK
| W_OK
);
212 if (flags
[Remount
]) {
215 AuFin("both of remount and bind are specified");
216 flags
[AuFlush
] = test_flush(opts
);
217 if (flags
[AuFlush
] /* && !flags[Fake] */) {
218 err
= au_plink(cwd
, AuPlink_FLUSH
, 1, 1);
226 /* actual mount operation */
227 do_mount(dev
, mntpnt
, argc
, argv
, flags
);
232 err
= waitpid(pid
, &status
, 0);
234 AuFin("child process");
236 err
= !WIFEXITED(status
);
238 err
= WEXITSTATUS(status
);
240 if (!err
&& !flags
[Bind
]) {
242 err
= au_update_mtab(cwd
, flags
[Remount
],
244 else if (flags
[Verbose
]) {
245 /* withoug blocking plink */
246 err
= au_proc_getmntent(cwd
, &ent
);
250 AuFin("internal error");