static void disable_file(OPERATION op, const char *filename) {
	assert(filename);
	assert(op <OPERATION_MAX);
	EUID_ASSERT();

	// Resolve all symlinks
	char* fname = realpath(filename, NULL);
	if (fname == NULL && errno != EACCES) {
		return;
	}
	if (fname == NULL && errno == EACCES) {
		// realpath and stat functions will fail on FUSE filesystems
		// they don't seem to like a uid of 0
		// force mounting
		int fd = open(filename, O_PATH|O_CLOEXEC);
		if (fd < 0) {
			if (arg_debug)
				printf("Warning (blacklisting): cannot open %s: %s\n", filename, strerror(errno));
			return;
		}

		EUID_ROOT();
		int err = bind_mount_path_to_fd(RUN_RO_DIR, fd);
		if (err != 0)
			err = bind_mount_path_to_fd(RUN_RO_FILE, fd);
		EUID_USER();
		close(fd);

		if (err == 0) {
			if (arg_debug)
				printf("Disable %s\n", filename);
			if (op == BLACKLIST_FILE)
				fs_logger2("blacklist", filename);
			else
				fs_logger2("blacklist-nolog", filename);
		}
		else if (arg_debug)
			printf("Warning (blacklisting): cannot mount on %s\n", filename);

		return;
	}

	assert(fname);
	// check for firejail executable
	// we might have a file found in ${PATH} pointing to /usr/bin/firejail
	// blacklisting it here will end up breaking situations like user clicks on a link in Thunderbird
	//     and expects Firefox to open in the same sandbox
	if (strcmp(BINDIR "/firejail", fname) == 0) {
		free(fname);
		return;
	}

	// if the file is not present, do nothing
	int fd = open(fname, O_PATH|O_CLOEXEC);
	if (fd < 0) {
		if (arg_debug)
			printf("Warning (blacklisting): cannot open %s: %s\n", fname, strerror(errno));
		free(fname);
		return;
	}

	struct stat s;
	if (fstat(fd, &s) < 0) {
		if (arg_debug)
			printf("Warning (blacklisting): cannot stat %s: %s\n", fname, strerror(errno));
		free(fname);
		close(fd);
		return;
	}

	// modify the file
	if (op == BLACKLIST_FILE || op == BLACKLIST_NOLOG) {
		// some distros put all executables under /usr/bin and make /bin a symbolic link
		if ((strcmp(fname, "/bin") == 0 || strcmp(fname, "/usr/bin") == 0) &&
		      is_link(filename) &&
		      S_ISDIR(s.st_mode)) {
			fwarning("%s directory link was not blacklisted\n", filename);
		}
		else {
			if (arg_debug) {
				if (strcmp(filename, fname))
					printf("Disable %s (requested %s)\n", fname, filename);
				else
					printf("Disable %s\n", fname);
			}
			else if (arg_debug_blacklists) {
				printf("Disable %s", fname);
				if (op == BLACKLIST_FILE)
					printf("\n");
				else
					printf(" - no logging\n");
			}

			EUID_ROOT();
			if (S_ISDIR(s.st_mode)) {
				if (bind_mount_path_to_fd(RUN_RO_DIR, fd) < 0)
					errExit("disable file");
			}
			else {
				if (bind_mount_path_to_fd(RUN_RO_FILE, fd) < 0)
					errExit("disable file");
			}
			EUID_USER();

			if (op == BLACKLIST_FILE)
				fs_logger2("blacklist", fname);
			else
				fs_logger2("blacklist-nolog", fname);

			// files in /etc will be reprocessed during /etc rebuild
			if (strncmp(fname, "/etc/", 5) == 0) {
				ProfileEntry *prf = malloc(sizeof(ProfileEntry));
				if (!prf)
					errExit("malloc");
				memset(prf, 0, sizeof(ProfileEntry));
				prf->data = strdup(fname);
				if (!prf->data)
					errExit("strdup");
				prf->next = cfg.profile_rebuild_etc;
				cfg.profile_rebuild_etc = prf;
			}
		}
	}
	else if (op == MOUNT_READONLY || op == MOUNT_RDWR || op == MOUNT_NOEXEC) {
		fs_remount_rec(fname, op);
	}
	else if (op == MOUNT_TMPFS) {
		if (!S_ISDIR(s.st_mode)) {
			fwarning("%s is not a directory; cannot mount a tmpfs on top of it.\n", fname);
			goto out;
		}

		uid_t uid = getuid();
		if (uid != 0) {
			// only user owned directories in user home
			if (s.st_uid != uid ||
			    strncmp(cfg.homedir, fname, strlen(cfg.homedir)) != 0 ||
			    fname[strlen(cfg.homedir)] != '/') {
				fwarning("you are not allowed to mount a tmpfs on %s\n", fname);
				goto out;
			}
		}

		fs_tmpfs(fname, uid);
		selinux_relabel_path(fname, fname);
	}
	else
		assert(0);

out:
	close(fd);
	free(fname);
}
static void disable_file(OPERATION op, const char *filename) {
	assert(filename);
	assert(op <OPERATION_MAX);
	EUID_ASSERT();

	 
	char* fname = realpath(filename, NULL);
	if (fname == NULL && errno != EACCES) {
		return;
	}
	if (fname == NULL && errno == EACCES) {
		 
		 
		 
		int fd = open(filename, O_PATH|O_CLOEXEC);
		if (fd < 0) {
			if (arg_debug)
				printf("Warning (blacklisting): cannot open %s: %s\n", filename, strerror(errno));
			return;
		}

		EUID_ROOT();
		int err = bind_mount_path_to_fd(RUN_RO_DIR, fd);
		if (err != 0)
			err = bind_mount_path_to_fd(RUN_RO_FILE, fd);
		EUID_USER();
		close(fd);

		if (err == 0) {
			if (arg_debug)
				printf("Disable %s\n", filename);
			if (op == BLACKLIST_FILE)
				fs_logger2("blacklist", filename);
			else
				fs_logger2("blacklist-nolog", filename);
		}
		else if (arg_debug)
			printf("Warning (blacklisting): cannot mount on %s\n", filename);

		return;
	}

	assert(fname);
	 
	 
	 
	 
	if (strcmp(BINDIR "/firejail", fname) == 0) {
		free(fname);
		return;
	}

	 
	int fd = open(fname, O_PATH|O_CLOEXEC);
	if (fd < 0) {
		if (arg_debug)
			printf("Warning (blacklisting): cannot open %s: %s\n", fname, strerror(errno));
		free(fname);
		return;
	}

	struct stat s;
	if (fstat(fd, &s) < 0) {
		if (arg_debug)
			printf("Warning (blacklisting): cannot stat %s: %s\n", fname, strerror(errno));
		free(fname);
		close(fd);
		return;
	}

	 
	if (op == BLACKLIST_FILE || op == BLACKLIST_NOLOG) {
		 
		if ((strcmp(fname, "/bin") == 0 || strcmp(fname, "/usr/bin") == 0) &&
		      is_link(filename) &&
		      S_ISDIR(s.st_mode)) {
			fwarning("%s directory link was not blacklisted\n", filename);
		}
		else {
			if (arg_debug) {
				if (strcmp(filename, fname))
					printf("Disable %s (requested %s)\n", fname, filename);
				else
					printf("Disable %s\n", fname);
			}
			else if (arg_debug_blacklists) {
				printf("Disable %s", fname);
				if (op == BLACKLIST_FILE)
					printf("\n");
				else
					printf(" - no logging\n");
			}

			EUID_ROOT();
			if (S_ISDIR(s.st_mode)) {
				if (bind_mount_path_to_fd(RUN_RO_DIR, fd) < 0)
					errExit("disable file");
			}
			else {
				if (bind_mount_path_to_fd(RUN_RO_FILE, fd) < 0)
					errExit("disable file");
			}
			EUID_USER();

			if (op == BLACKLIST_FILE)
				fs_logger2("blacklist", fname);
			else
				fs_logger2("blacklist-nolog", fname);

			 
			if (strncmp(fname, "/etc/", 5) == 0) {
				ProfileEntry *prf = malloc(sizeof(ProfileEntry));
				if (!prf)
					errExit("malloc");
				memset(prf, 0, sizeof(ProfileEntry));
				prf->data = strdup(fname);
				if (!prf->data)
					errExit("strdup");
				prf->next = cfg.profile_rebuild_etc;
				cfg.profile_rebuild_etc = prf;
			}
		}
	}
	else if (op == MOUNT_READONLY || op == MOUNT_RDWR || op == MOUNT_NOEXEC) {
		fs_remount_rec(fname, op);
	}
	else if (op == MOUNT_TMPFS) {
		if (!S_ISDIR(s.st_mode)) {
			fwarning("%s is not a directory; cannot mount a tmpfs on top of it.\n", fname);
			goto out;
		}

		uid_t uid = getuid();
		if (uid != 0) {
			 
			if (s.st_uid != uid ||
			    strncmp(cfg.homedir, fname, strlen(cfg.homedir)) != 0 ||
			    fname[strlen(cfg.homedir)] != '/') {
				fwarning("you are not allowed to mount a tmpfs on %s\n", fname);
				goto out;
			}
		}

		fs_tmpfs(fname, uid);
		selinux_relabel_path(fname, fname);
	}
	else
		assert(0);

out:
	close(fd);
	free(fname);
}