⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mount_tfs.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic char sccsid[] = "@(#)mount_tfs.c 1.1 92/07/30 Copyr 1988 Sun Micro";#endif/* * Usage:  mount_tfs [-r] fs1 fs2 ... fsN dir * * TFS mounts fs1 on fs2 on ... on dir. * * Sets up searchlinks from the directory fs1 to fs2, from fs2 to fs3, ... * from fsN to dir, then TFS-mounts fs1 onto dir.  Before TFS-mounting * fs1 onto 'dir', these two steps are taken: *	1) loopback mount / onto /tmp_mnt/Tfs_native *	2) loopback mount /tmp_mnt/Tfs_empty onto 'dir' * * The searchlink from fsN points to /tmp_mnt/Tfs_native/'dir' instead of * 'dir'.  The two loopback mounts prevent the tfsd from deadlocking with * itself.  (After the TFS mount, the tfsd will be serving filesystem * requests for files under 'dir'.  The back layer that the tfsd is serving * is also 'dir'.  We want to prevent the tfsd from waiting for itself when * it accesses files in 'dir'.  The first loopback mount duplicates the * native file system so that the native version of 'dir' can be accessed * through /tmp_mnt/Tfs_native/'dir'.  The second loopback mount of an * empty directory over 'dir' prevents the kernel from using the TFS * version of 'dir' when files are accessed in /tmp_mnt/Tfs_native/'dir'.) * * When the searchlinks between layers are set, searchlinks are also set * in the sub-directories of each layer. * * NOTE: this command does not interact well with NSE exec-sets. * If you activate an environment whose exec-set has /usr/lib as a control * point, and also mount_tfs a directory over /usr/lib, then the tfsd * will deadlock when you try to reference /usr/lib. * * The directories fs1, ..., fsN must be writeable, so that searchlinks * can be set in them. */#include <nse/param.h>#include <stdio.h>#include <pwd.h>#include <nse/util.h>#include <sys/stat.h>#include <sys/dir.h>#include <sys/file.h>#include <mntent.h>#include <errno.h>#include <nse/searchlink.h>#include <nse/tfs_calls.h>#include <nse_impl/tfs.h>#include <nse_impl/tfs_user.h>#include <nse/tfs_mount.h>#define TFSD_ENV_NAME "tfs_mount"	/* Environment name given to the					 * tfsd for TFS mounts */bool_t		read_only;char		*tfs_loopback_dir = "/tmp_mnt/Tfs_native";char		*tfs_empty_dir = "/tmp_mnt/Tfs_empty";int		tfs_major_dev;Nse_err		do_mounts();Nse_err		do_loopback_mounts();Nse_err		tfs_mount();void		get_mountpt_devid();Nse_err		ping_tfsd();void		find_subdirs();Nse_err		build_subdirs();Nse_err		build_searchlinks();Nse_err		recursive_set_searchlinks();Nse_err		set_searchlink();Nse_err		make_directory();void		unmount_all();Nse_list	nse_stringlist_create();main(argc, argv)	int		argc;	char		*argv[];{	char		**dir_names;	int		*dir_owners;	int		i;	char		*cp;	struct stat	statb;	char		fname[MAXPATHLEN];	Nse_list	mtab_list;	Nse_list	subdir_list;	bool_t		invoked_from_mount = FALSE;	Nse_err		err;	nse_set_cmdname(argv[0]);	if (geteuid() != 0) {		fprintf(stderr, "%s: Must be root\n", nse_get_cmdname());		exit(1);	}	if (argc < 3) {		usage();	}	argv++;	argc--;	if (options(&argc, &argv)) {		exit (1);	}	if (argc < 2) {		usage();	}	if (argc == 4 && NSE_STREQ(argv[2], "tfs")) {		/*		 * Allow this command to be exec'ed from the mount command,		 * in which case the usage line is:		 *	mount_tfs fsname dir tfs opts		 */		struct mntent	mt;		argc -= 2;		mt.mnt_opts = argv[3];		read_only = (hasmntopt(&mt, MNTOPT_RO) != NULL);		invoked_from_mount = TRUE;	}	/*	 * Assert: argc == # of directories	 *	   argv[0] contains the name of the frontmost directory	 *	   argv[argc - 1] contains the name of the backmost directory	 *		(the one being mounted on)	 *	 * First fully qualify the directory names.	 */	dir_names = (char **) nse_malloc((unsigned)(argc + 1) *					 sizeof(char *));	dir_owners = (int *) nse_malloc((unsigned)(argc + 1) * sizeof(int));	for (i = 0; i < argc; i++) {		if (realpath(argv[i], fname) == NULL) {			fprintf(stderr, "%s: ", nse_get_cmdname());			perror(argv[i]);			exit (1);		}		dir_names[i] = NSE_STRDUP(fname);	}	dir_names[argc] = NULL;	dir_owners[argc] = NULL;	/*	 * Make sure that all of the specified directories are indeed	 * directories.	 */	for (i = 0; i < argc; i++) {		if (stat(dir_names[i], &statb) < 0) {			fprintf(stderr, "%s: ", nse_get_cmdname());			perror(argv[i]);			exit (1);		}		if (!NSE_ISDIR(&statb)) {			fprintf(stderr, "%s: %s is not a directory\n",				nse_get_cmdname(), argv[i]);			exit (1);		}		dir_owners[i] = statb.st_uid;	}	/*	 * Don't allow TFS mounts over '/'.	 */	for (cp = dir_names[argc - 1]; *cp == '/'; cp++) ;	if (*cp == '\0') {		fprintf(stderr, "%s: Cannot mount over \"/\"\n",			nse_get_cmdname());		exit (1);	}	if (err = nse_mtab_read(&mtab_list)) {		nse_err_print(err);		exit (1);	}	/*	 * Build list of sub-TFS mounts that will be covered by this TFS	 * mount.  This list will be used by build_subdirs() to make the	 * subdirectories under the new TFS mount so that set_searchlink()	 * can set searchlinks to the directories currently TFS-mounted on	 * the subdirectories.  This allows the following sequence to work:	 * 1) TFS mount /foo on /usr/src/sys; 2) TFS mount /bar on	 * /usr/src, such that the first TFS mount shows through under	 * /usr/src/sys.	 */	subdir_list = nse_stringlist_create();	nse_list_iterate(mtab_list, find_subdirs, dir_names[argc - 1],			 subdir_list);	/*	 * Build searchlinks between all the directories 'fs1' ... 'fsN',	 * 'dir'.  The searchlink from 'fsN' is set to point to	 * /tmp_mnt/Tfs_native/'dir'.	 */	for (i = 0; i < argc - 1; i++) {		/*		 * Don't want to build searchlinks as root, because root		 * may have inadequate permissions.		 */		setregid(0, group_of_user(dir_owners[i]));		setreuid(0, dir_owners[i]);		err = (Nse_err) nse_list_iterate_or(subdir_list, build_subdirs,						    dir_names[i]);		if (!err) {			err = build_searchlinks(dir_names[i], dir_names[i + 1],						(i == argc - 2));		}		setreuid(0, 0);		setregid(0, 0);		if (err) {			nse_err_print(err);			exit (1);		}	}	err = do_mounts(dir_names[0], dir_names[argc - 1], invoked_from_mount);	if (err) {		nse_err_print(err);		exit (1);	} else {		exit (0);	}}Nse_errdo_mounts(fsname, dir, invoked_from_mount)	char		*fsname;	char		*dir;	bool_t		invoked_from_mount;{	Nse_list	mtab_list;	struct mntent	*mnt;	int		old_mask;	Nse_err		err;	if (err = ping_tfsd()) {		nse_err_print(err);		exit (1);	}	mtab_list = nse_mtablist_create();	/*	 * Block signals while the mounts are taking place, because if	 * the process is killed between the loopback mount over 'dir'	 * and the TFS mount over 'dir', 'dir' will be left empty.	 */	old_mask = sigblock(sigmask(SIGINT) | sigmask(SIGTERM) |			    sigmask(SIGQUIT));	if ((err = do_loopback_mounts(dir, mtab_list)) ||	    (err = tfs_mount(fsname, dir, &mnt))) {		unmount_all(mtab_list);		(void) sigsetmask(old_mask);		return err;	}	/*	 * Don't add mtab entry for the TFS mount to /etc/mtab if command	 * was invoked from /etc/mount, because /etc/mount will add this	 * entry itself.  	 */	if (!invoked_from_mount) {		get_mountpt_devid(mnt);		(void) nse_list_add_new_data(mtab_list, mnt);	}	if (err = nse_mtab_add(mtab_list)) {		fprintf(stderr, "%s: Warning: ", nse_get_cmdname());		nse_err_print(err);	}	(void) sigsetmask(old_mask);	return NULL;}/* * Make the loopback mounts: 1) / onto /tmp_mnt/Tfs_native, and * 2) /tmp_mnt/Tfs_empty onto 'covered_dir'. */Nse_errdo_loopback_mounts(covered_dir, mtab_list)	char		*covered_dir;	Nse_list	mtab_list;{	struct stat	statb;	int		rootino;	int		rootdev;	struct mntent	*mnt;	Nse_err		err;	if ((err = make_directory(tfs_loopback_dir)) ||	    (err = make_directory(tfs_empty_dir))) {		return err;	}	if (stat("/", &statb) < 0) {		return nse_err_format_errno("Stat of \"/\"");	}	rootino = statb.st_ino;	rootdev = statb.st_dev;	if (stat(tfs_loopback_dir, &statb) < 0) {		return nse_err_format_errno("Stat of \"%s\"",					    tfs_loopback_dir);	}	if (statb.st_ino != rootino || statb.st_dev != rootdev) {		if (err = nse_mount_loopback("/", tfs_loopback_dir, FALSE,					     &mnt)) {			return err;		}		get_mountpt_devid(mnt);		(void) nse_list_add_new_data(mtab_list, mnt);	}	if (err = nse_mount_loopback(tfs_empty_dir, covered_dir, FALSE,				     &mnt)) {		return err;	}	get_mountpt_devid(mnt);	(void) nse_list_add_new_data(mtab_list, mnt);	return NULL;}Nse_errtfs_mount(fsname, dir, mntp)	char		*fsname;	char		*dir;	struct mntent	**mntp;{	Tfs_mount_args_rec ma;	ma.environ = TFSD_ENV_NAME;	ma.tfs_mount_pt = dir;	ma.directory = fsname;	ma.hostname = _nse_hostname();	ma.pid = 1;	ma.writeable_layers = 1;	ma.back_owner = -1;	ma.back_read_only = FALSE;	ma.default_view = "";	ma.conditional_view = "";	return nse_tfs_mount(&ma, dir, _nse_hostname(), read_only, mntp,			     TFS_VERSION);}/* * Get the device # of the new mountpoint and put it into the mount option * string. */voidget_mountpt_devid(mnt)	struct mntent	*mnt;{	struct stat	statb;	char		opts[100];	if (stat(mnt->mnt_dir, &statb) == 0) {		sprintf(opts, "%s,%s=%04x", mnt->mnt_opts, MNTINFO_DEV,			statb.st_dev & 0xffff);		free(mnt->mnt_opts);		mnt->mnt_opts = NSE_STRDUP(opts);	}}/* * Ping the tfsd and make sure it's alive.  This ensures that the tfsd is * alive before a loopback mount can cover a directory whose contents may * be necessary to start the tfsd.  E.g., if the tfsd is being started * from /usr/etc, and the user wants to TFS mount a directory onto /usr/etc, * then the loopback mount of /tmp_mnt/Tfs_empty onto /usr/etc will be * made before the TFS mount, and /usr/etc will be empty until the TFS * mount is done. */Nse_errping_tfsd(){	return nse_tfs_rpc_call_to_host(_nse_hostname(), RFS_NULL,					xdr_void, (char *) NULL,					xdr_void, (char *) NULL);}/* * If the mtab entry 'mnt' is for a TFS mount on a subdirectory of 'path', * add it to subdir_list.  subdir_list is built so that a TFS mount over * a parent directory of an existing TFS mount will not obscure the * existing TFS mount.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -