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
19 #define _FILE_OFFSET_BITS 64 /* ftw.h */
20 #define _XOPEN_SOURCE 500 /* ftw.h */
21 #define _GNU_SOURCE /* ftw.h */
23 #include <sys/ioctl.h>
24 #include <sys/resource.h>
26 #include <sys/types.h>
35 #include <linux/aufs_type.h>
39 static struct name_array
{
47 static struct ino_array
{
58 static int na_append(char *plink_dir
, char *name
)
62 const int cur
= na
.cur
- na
.o
;
64 l
= strlen(plink_dir
) + strlen(name
) + 2;
66 p
= realloc(na
.o
, sz
);
73 na
.cur
+= sprintf(na
.cur
, "%s/%s", plink_dir
, name
) + 1;
79 static int ia_append(ino_t ino
)
83 const int cur
= ia
.p
- ia
.o
;
85 sz
= na
.bytes
+ sizeof(ino_t
);
86 p
= realloc(ia
.o
, sz
);
99 static int build_array(char *plink_dir
)
107 err
= access(plink_dir
, F_OK
);
112 dp
= opendir(plink_dir
);
114 AuFin("%s", plink_dir
);
115 while ((de
= readdir(dp
))) {
116 if (!strcmp(de
->d_name
, ".") || !strcmp(de
->d_name
, ".."))
119 if (de
->d_type
== DT_DIR
) {
125 err
= na_append(plink_dir
, de
->d_name
);
129 p
= strchr(de
->d_name
, '.');
132 AuFin("internal error, %s", de
->d_name
);
136 ino
= strtoull(de
->d_name
, NULL
, 0);
137 if (ino
== /*ULLONG_MAX*/-1 && errno
== ERANGE
)
138 AuFin("internal error, %s", de
->d_name
);
139 err
= ia_append(ino
);
148 static int ia_test(ino_t ino
)
153 /* todo: hash table */
156 for (i
= 0; i
< ia
.nino
; i
++)
162 /* ---------------------------------------------------------------------- */
164 static int ftw_list(const char *fname
, const struct stat
*st
, int flags
,
167 if (!strcmp(fname
+ ftw
->base
, AUFS_WH_PLINKDIR
))
168 return FTW_SKIP_SUBTREE
;
169 if (flags
== FTW_D
|| flags
== FTW_DNR
)
172 if (ia_test(st
->st_ino
))
178 static int ftw_cpup(const char *fname
, const struct stat
*st
, int flags
,
183 if (!strcmp(fname
+ ftw
->base
, AUFS_WH_PLINKDIR
))
184 return FTW_SKIP_SUBTREE
;
185 if (flags
== FTW_D
|| flags
== FTW_DNR
)
189 * do nothing but update something harmless in order to make it copyup
191 if (ia_test(st
->st_ino
)) {
193 if (!S_ISLNK(st
->st_mode
))
194 err
= chown(fname
, -1, -1);
196 err
= lchown(fname
, -1, -1);
204 /* ---------------------------------------------------------------------- */
207 void au_plink_maint(char *path
)
214 AuFin("dp is not NULL");
220 err
= ioctl(dirfd(dp
), AUFS_CTL_PLINK_MAINT
);
223 AuFin("AUFS_CTL_PLINK_MAINT");
233 void au_clean_plink(void)
237 err
= ioctl(dirfd(dp
), AUFS_CTL_PLINK_CLEAN
);
240 AuFin("AUFS_CTL_PLINK_CLEAN");
244 static int do_plink(char *cwd
, int cmd
, int nbr
, char *br
[])
264 func
= NULL
; /* never reach here */
267 for (i
= 0; i
< nbr
; i
++) {
269 p
= strchr(br
[i
], '=');
270 if (strcmp(p
+ 1, AUFS_BRPERM_RW
)
271 && strcmp(p
+ 1, AUFS_BRPERM_RWNLWH
))
276 p
= malloc(l
+ sizeof(AUFS_WH_PLINKDIR
) + 2);
279 sprintf(p
, "%s/%s", br
[i
], AUFS_WH_PLINKDIR
);
281 err
= build_array(p
);
283 AuFin("build_array");
289 if (cmd
== AuPlink_LIST
) {
291 for (i
= 0; i
< ia
.nino
; i
++)
292 printf("%llu ", (unsigned long long)*ia
.cur
++);
296 err
= getrlimit(RLIMIT_NOFILE
, &rlim
);
299 nftw(cwd
, func
, rlim
.rlim_cur
- 10,
300 FTW_PHYS
| FTW_MOUNT
| FTW_ACTIONRETVAL
);
303 if (cmd
== AuPlink_FLUSH
) {
307 for (i
= 0; i
< na
.nname
; i
++) {
308 Dpri("%s\n", na
.cur
);
309 err
= unlink(na
.cur
);
312 na
.cur
+= strlen(na
.cur
) + 1;
322 int au_plink(char cwd
[], int cmd
, int begin_maint
, int end_maint
)
331 err
= au_proc_getmntent(cwd
, &ent
);
333 AuFin("no such mount point");
335 if (hasmntopt(&ent
, "noplink"))
336 goto out
; /* success */
339 //char a[] = "a,b,br:/tmp/br0=rw:/br1=ro";
340 char a
[] = "a,b,si=1,c";
343 err
= au_br(&br
, &nbr
, &ent
);
344 //printf("nbr %d\n", nbr);
348 err
= do_plink(cwd
, cmd
, nbr
, br
);
354 au_plink_maint(NULL
);