예제 #1
0
/**
 * Create a writable mimic directory based on reference directory.
 *
 * The mimic directory is a tmpfs populated with bind mounts to the (possibly
 * read only) directories in the reference directory. While all the read-only
 * content stays read-only the actual mimic directory is writable so additional
 * content can be placed there.
 *
 * Flags are forwarded to sc_quirk_mkdir_bind()
 **/
static void sc_quirk_create_writable_mimic(const char *mimic_dir,
					   const char *ref_dir, unsigned flags)
{
	debug("creating writable mimic directory %s based on %s", mimic_dir,
	      ref_dir);
	sc_quirk_setup_tmpfs(mimic_dir);

	// Now copy the ownership and permissions of the mimicked directory
	struct stat stat_buf;
	if (stat(ref_dir, &stat_buf) < 0) {
		die("cannot stat %s", ref_dir);
	}
	if (chown(mimic_dir, stat_buf.st_uid, stat_buf.st_gid) < 0) {
		die("cannot chown for %s", mimic_dir);
	}
	if (chmod(mimic_dir, stat_buf.st_mode) < 0) {
		die("cannot chmod for %s", mimic_dir);
	}

	debug("bind-mounting all the files from the reference directory");
	DIR *dirp SC_CLEANUP(sc_cleanup_closedir) = NULL;
	dirp = opendir(ref_dir);
	if (dirp == NULL) {
		die("cannot open reference directory %s", ref_dir);
	}
	struct dirent *entryp = NULL;
	do {
		char src_name[PATH_MAX * 2] = { 0 };
		char dest_name[PATH_MAX * 2] = { 0 };
		// Set errno to zero, if readdir fails it will not only return null but
		// set errno to a non-zero value. This is how we can differentiate
		// end-of-directory from an actual error.
		errno = 0;
		entryp = readdir(dirp);
		if (entryp == NULL && errno != 0) {
			die("cannot read another directory entry");
		}
		if (entryp == NULL) {
			break;
		}
		if (strcmp(entryp->d_name, ".") == 0
		    || strcmp(entryp->d_name, "..") == 0) {
			continue;
		}
		if (entryp->d_type != DT_DIR && entryp->d_type != DT_REG) {
			die("unsupported entry type of file %s (%d)",
			    entryp->d_name, entryp->d_type);
		}
		sc_must_snprintf(src_name, sizeof src_name, "%s/%s", ref_dir,
				 entryp->d_name);
		sc_must_snprintf(dest_name, sizeof dest_name, "%s/%s",
				 mimic_dir, entryp->d_name);
		sc_quirk_mkdir_bind(src_name, dest_name, flags);
	} while (entryp != NULL);
}
예제 #2
0
/**
 * Setup a quirk for LXD.
 *
 * An existing LXD snap relies on pre-chroot behavior to access /var/lib/lxd
 * while in devmode. Since that directory doesn't exist in the core snap the
 * quirk punches a custom hole so that this directory shows the hostfs content
 * if such directory exists on the host.
 *
 * See: https://bugs.launchpad.net/snap-confine/+bug/1613845
 **/
static void sc_setup_lxd_quirk(void)
{
	const char *hostfs_lxd_dir = SC_HOSTFS_DIR "/var/lib/lxd";
	if (access(hostfs_lxd_dir, F_OK) == 0) {
		const char *lxd_dir = "/var/lib/lxd";
		debug("setting up quirk for LXD (see LP: #1613845)");
		sc_quirk_mkdir_bind(hostfs_lxd_dir, lxd_dir,
				    MS_REC | MS_SLAVE | MS_NODEV | MS_NOSUID |
				    MS_NOEXEC);
	}
}
예제 #3
0
파일: quirks.c 프로젝트: jhodapp/snapd
/**
 * Create a writable mimic directory based on reference directory.
 *
 * The mimic directory is a tmpfs populated with bind mounts to the (possibly
 * read only) directories in the reference directory. While all the read-only
 * content stays read-only the actual mimic directory is writable so additional
 * content can be placed there.
 *
 * Flags are forwarded to sc_quirk_mkdir_bind()
 **/
static void sc_quirk_create_writable_mimic(const char *mimic_dir,
					   const char *ref_dir, unsigned flags)
{
	debug("creating writable mimic directory %s based on %s", mimic_dir,
	      ref_dir);
	sc_quirk_setup_tmpfs(mimic_dir);
	debug("bind-mounting all the files from the reference directory");
	DIR *dirp __attribute__ ((cleanup(sc_cleanup_closedir))) = NULL;
	dirp = opendir(ref_dir);
	if (dirp == NULL) {
		die("cannot open reference directory %s", ref_dir);
	}
	struct dirent *entryp = NULL;
	do {
		char src_name[PATH_MAX * 2];
		char dest_name[PATH_MAX * 2];
		// Set errno to zero, if readdir fails it will not only return null but
		// set errno to a non-zero value. This is how we can differentiate
		// end-of-directory from an actual error.
		errno = 0;
		entryp = readdir(dirp);
		if (entryp == NULL && errno != 0) {
			die("cannot read another directory entry");
		}
		if (entryp == NULL) {
			break;
		}
		if (strcmp(entryp->d_name, ".") == 0
		    || strcmp(entryp->d_name, "..") == 0) {
			continue;
		}
		if (entryp->d_type != DT_DIR && entryp->d_type != DT_REG) {
			die("unsupported entry type of file %s (%d)",
			    entryp->d_name, entryp->d_type);
		}
		must_snprintf(src_name, sizeof src_name, "%s/%s", ref_dir,
			      entryp->d_name);
		must_snprintf(dest_name, sizeof dest_name, "%s/%s", mimic_dir,
			      entryp->d_name);
		sc_quirk_mkdir_bind(src_name, dest_name, flags);
	} while (entryp != NULL);
}