/* * Ideally the mounted aufs should be unmounted even if its mntpnt has very long * pathname. In other words, if umount.aufs cannot handle a long pathname, then * mount.aufs should reject in the beginning. * getmntent(3) in glibc reads 4096 bytes for a single mnt entry. I agree it is * large enough. And mount(8) rejects too long pathname. It is OK too. As long * as 4095 (4096 - 1) bytes pathname succeeds mounting, then it should be * unmounted flawlessly. * Testing on Debian v7 (wheezy) succeeded mounting 4095 bytes pathname, but * failed unmounting. I don't like this unbalancing. So replace getmntent() by * getmntent_r() with larger buffer. Obviously this is less important since such * long pathname is very rare. */ int au_proc_getmntent(char *mntpnt, struct mntent *rent) { int found; struct mntent *p, e; FILE *fp; char a[4096 + 1024], path[PATH_MAX], *decoded; decoded = au_decode_mntpnt(mntpnt, path, sizeof(path)); if (!decoded) AuFin("au_decode_mntpnt"); fp = setmntent(ProcMounts, "r"); if (!fp) AuFin(ProcMounts); /* find the last one */ memset(rent, 0, sizeof(*rent)); found = 0; while ((p = getmntent_r(fp, &e, a, sizeof(a)))) if (!strcmp(p->mnt_dir, decoded)) { Dpri("%s, %s, %s, %s, %d, %d\n", p->mnt_fsname, p->mnt_dir, p->mnt_type, p->mnt_opts, p->mnt_freq, p->mnt_passno); copy_ent(rent, p); found = 1; } endmntent(fp); if (!found) { errno = EINVAL; AuFin("%s, %s", mntpnt, decoded); } return 0; }
static int ftw_cpup(const char *fname, const struct stat *st, int flags, struct FTW *ftw) { int err; if (!strcmp(fname + ftw->base, AUFS_WH_PLINKDIR)) return FTW_SKIP_SUBTREE; if (flags == FTW_D || flags == FTW_DNR) return FTW_CONTINUE; /* * do nothing but update something harmless in order to make it copyup */ if (ia_test(st->st_ino)) { Dpri("%s\n", fname); if (!S_ISLNK(st->st_mode)) err = chown(fname, -1, -1); else err = lchown(fname, -1, -1); if (err) AuFin("%s", fname); } return FTW_CONTINUE; }
int au_proc_getmntent(char *mntpnt, struct mntent *rent) { int found; struct mntent *p; FILE *fp; fp = setmntent(ProcMounts, "r"); if (!fp) AuFin(ProcMounts); /* find the last one */ memset(rent, 0, sizeof(*rent)); found = 0; while ((p = getmntent(fp))) if (!strcmp(p->mnt_dir, mntpnt)) { Dpri("%s, %s, %s, %s, %d, %d\n", p->mnt_fsname, p->mnt_dir, p->mnt_type, p->mnt_opts, p->mnt_freq, p->mnt_passno); copy_ent(rent, p); found = 1; } endmntent(fp); if (!found) { errno = EINVAL; AuFin("%s", mntpnt); } return 0; }
static int do_plink(char *cwd, int cmd, int nbr, char *br[]) { int err, i, l; struct rlimit rlim; __nftw_func_t func; char *p; err = 0; switch (cmd) { case AuPlink_FLUSH: /*FALLTHROUGH*/ case AuPlink_CPUP: func = ftw_cpup; break; case AuPlink_LIST: func = ftw_list; break; default: errno = EINVAL; AuFin(NULL); func = NULL; /* never reach here */ } for (i = 0; i < nbr; i++) { //puts(br[i]); p = strchr(br[i], '='); if (strcmp(p + 1, AUFS_BRPERM_RW) && strcmp(p + 1, AUFS_BRPERM_RWNLWH)) continue; *p = 0; l = strlen(br[i]); p = malloc(l + sizeof(AUFS_WH_PLINKDIR) + 2); if (!p) AuFin("malloc"); sprintf(p, "%s/%s", br[i], AUFS_WH_PLINKDIR); //puts(p); err = build_array(p); if (err) AuFin("build_array"); free(p); } if (!ia.nino) goto out; if (cmd == AuPlink_LIST) { ia.p = ia.o; for (i = 0; i < ia.nino; i++) printf("%llu ", (unsigned long long)*ia.cur++); putchar('\n'); } err = getrlimit(RLIMIT_NOFILE, &rlim); if (err) AuFin("getrlimit"); nftw(cwd, func, rlim.rlim_cur - 10, FTW_PHYS | FTW_MOUNT | FTW_ACTIONRETVAL); /* ignore */ if (cmd == AuPlink_FLUSH) { au_clean_plink(); na.cur = na.o; for (i = 0; i < na.nname; i++) { Dpri("%s\n", na.cur); err = unlink(na.cur); if (err) AuFin("%s", na.cur); na.cur += strlen(na.cur) + 1; } } out: free(ia.o); free(na.o); return err; }