Example #1
0
/*
 * 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;
}
Example #2
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;
}
Example #3
0
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;
}
Example #4
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;
}