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

📄 tfs_mount.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
字号:
#ifndef lintstatic char sccsid[] = "@(#)tfs_mount.c 1.1 92/07/30 Copyr 1988 Sun Micro";#endif/* * Copyright (c) 1987 Sun Microsystems, Inc. */#include <nse/types.h>#include "headers.h"#include "tfs.h"#include "vnode.h"#include "subr.h"#include "tfs_lists.h"#include <nse/param.h>#include <nse/util.h>#include <nse/list.h>#include <sys/socket.h>#include <nse/tfs_calls.h>#include <nse/rev_tree.h>#define TFS_MOUNT_NAME	"tfs_mount"	/* Environment name given to the					 * tfsd by mount_tfs */static Nse_list	viewlist;extern SVCXPRT	*tfsd_xprt;bool_t		svc_finished;int		tfs_mount_1();int		tfs_mount_2();int		tfs_unmount_1();int		tfs_unmount_2();int		tfs_getname();int		tfs_flush();int		create_tmp_view();void		delete_tmp_view();static int	create_view();static char	*branch_to_var_name();#ifdef TFSDEBUGvoid		print_vnode_trees();#endif TFSDEBUGstatic void	add_client_entry();static bool_t	remove_client_entry();static Nse_list	get_covered_mounts();static void	restore_covered_mounts();char		*environ_var_name();char		*environ_default_name();bool_t		environ_has_multiple_clients();static Viewlist	get_environ_entry();static int	select_environ_id();static void	release_environ_id();static bool_t	vl_env_name_eq();static bool_t	vl_environ_id_eq();static void	vl_flush_all_vnodes();static bool_t	ml_path_eq();static bool_t	ml_physical_eq();static void	ml_flush_all_vnodes();static bool_t	cl_equal();static bool_t	cl_name_neq();/* * Add a new mount, version 1 */inttfs_mount_1(vp, ma, mr)	struct vnode	*vp;	Tfs_old_mount_args ma;	Tfs_mount_res	mr;{	Tfs_mount_args_rec new_ma;	int		result;	bzero((char *)&new_ma, sizeof new_ma);	new_ma.environ = ma->environ;	new_ma.tfs_mount_pt = ma->tfs_mount_pt;	new_ma.directory = ma->directory;	new_ma.hostname = ma->hostname;	new_ma.pid = ma->pid;	if (ma->writeable_layers == 0) {		new_ma.writeable_layers = 1;		new_ma.back_read_only = FALSE;		new_ma.conditional_view = NSE_STRDUP("");		new_ma.default_view = NSE_STRDUP("");	} else {		new_ma.writeable_layers = ma->writeable_layers;		new_ma.back_read_only = TRUE;		new_ma.conditional_view = branch_to_var_name(ma->environ);		if (NSE_STREQ(new_ma.conditional_view, NSE_RT_SOURCE_NAME)) {			new_ma.default_view = new_ma.conditional_view;			new_ma.conditional_view = NSE_STRDUP("");		} else {			new_ma.default_view = NSE_STRDUP(NSE_RT_SOURCE_NAME);		}	}	result = tfs_mount_2(vp, &new_ma, mr);	free(new_ma.conditional_view);	free(new_ma.default_view);	return result;}/* * Add a new mount, version 2 *//* ARGSUSED */inttfs_mount_2(vp, ma, mr)	struct vnode	*vp;	Tfs_mount_args	ma;	Tfs_mount_res	mr;{	Viewlist	vl;	Mountlist	ml = NULL;	Mountstack	sp;	int		result = 0;	struct stat	statb;	if (viewlist == NULL) {		viewlist = viewlist_create();	}	if (current_user_id() != 0) {		result = EPERM;		goto error;	}	if ((ma->directory[0] != '/') ||	    (ma->tfs_mount_pt[0] != '/' || ma->tfs_mount_pt[1] == '\0')) {		result = EINVAL;		goto error;	}	if (stat(ma->directory, &statb) == -1) {		result = NSE_TFS_NO_DIRECTORY;		goto error;	}	vl = (Viewlist) nse_list_search(viewlist, vl_env_name_eq,					ma->environ);	if (vl) {		ml = (Mountlist) nse_list_search(vl->vl_mountlist,						 ml_path_eq, ma->tfs_mount_pt);	} else {		if (result = create_view(ma, &vl)) {			goto error;		}		ml = NULL;	}	if (ml == NULL) {		/*		 * Don't allow the client to mount the same physical		 * directory onto a different mount point.		 */		if (nse_list_search(vl->vl_mountlist, ml_physical_eq,				    ma->directory)) {			result = EBUSY;			goto error;		}		ml = (Mountlist) nse_list_add_new_elem(vl->vl_mountlist);		ml->ml_virtual = NSE_STRDUP(ma->tfs_mount_pt);		ml->ml_physical = NSE_STRDUP(ma->directory);		if (NSE_STREQ(ma->environ, TFS_MOUNT_NAME)) {			ml->ml_covered = get_covered_mounts(vl->vl_mountlist,							    ma->tfs_mount_pt);		}		ml->ml_root_vnode = mntpntovp(vl->vl_root_vnode,					      ma->tfs_mount_pt, ma->directory);		ml->ml_refcnt = 1;	} else {		/*		 * Don't allow the client to mount a directory onto		 * a mount point that already has a different directory		 * mounted on it, unless mount_tfs is the client.		 */		if (!NSE_STREQ(ma->directory, ml->ml_physical)) {			if (!NSE_STREQ(ma->environ, TFS_MOUNT_NAME)) {				result = EBUSY;				goto error;			}			sp = NSE_NEW(Mountstack);			sp->name = ml->ml_physical;			sp->covered = ml->ml_covered;			sp->next = ml->ml_dir_stack;			ml->ml_dir_stack = sp;			ml->ml_physical = NSE_STRDUP(ma->directory);			ml->ml_covered = get_covered_mounts(vl->vl_mountlist,							    ma->tfs_mount_pt);			ml->ml_root_vnode = mntpntovp(vl->vl_root_vnode,						      ma->tfs_mount_pt,						      ma->directory);		}		ml->ml_refcnt++;	}	mr->port = tfsd_xprt->xp_port;	makefh(&mr->fh, ml->ml_root_vnode);	mr->pid = getpid();	add_client_entry(vl->vl_clientlist, ma->hostname, ma->pid);error:	if (nse_list_nelems(viewlist) == 0) {		svc_finished = 1;	}	return (result);}/* * Remove a mount, version 1 */inttfs_unmount_1(vp, ua, status)	struct vnode	*vp;	Tfs_old_mount_args ua;	enum nfsstat	*status;{	Tfs_unmount_args_rec new_ua;	new_ua.environ = ua->environ;	new_ua.tfs_mount_pt = ua->tfs_mount_pt;	new_ua.hostname = ua->hostname;	new_ua.pid = ua->pid;	return tfs_unmount_2(vp, &new_ua, status);}/* * Remove a mount, version 2 *//* ARGSUSED */inttfs_unmount_2(vp, ua, status)	struct vnode	*vp;	Tfs_unmount_args ua;	enum nfsstat	*status;{	Viewlist	vl;	Mountlist	ml;	Mountstack	sp;	int		result = 0;	if (current_user_id() != 0) {		result = EPERM;		goto error;	}	if (viewlist == NULL) {		return (EINVAL);	}	vl = (Viewlist) nse_list_search(viewlist, vl_env_name_eq, ua->environ);	if (vl == NULL) {		result = EINVAL;		goto error;	}	ml = (Mountlist) nse_list_search(vl->vl_mountlist, ml_path_eq,					 ua->tfs_mount_pt);	if (ml == NULL ||	    !remove_client_entry(vl->vl_clientlist, ua->hostname, ua->pid)) {		result = EINVAL;		goto error;	}	ml->ml_refcnt--;	if (ml->ml_covered) {		restore_covered_mounts(ml->ml_covered, vl->vl_mountlist,				       vl->vl_root_vnode);	}	if (ml->ml_refcnt == 0) {		/*		 * Free mountlist entry, and viewlist entry also, if this		 * was the last active mount for this view.		 */		remove_from_list(vl->vl_mountlist, (char *) ml);		if (nse_list_nelems(vl->vl_mountlist) == 0) {			release_environ_id(vl->vl_environ_id);			remove_from_list(viewlist, (char *) vl);		}	} else if (ml->ml_dir_stack) {		free(ml->ml_physical);		sp = ml->ml_dir_stack;		ml->ml_dir_stack = sp->next;		ml->ml_physical = sp->name;		ml->ml_covered = sp->covered;		free(sp);		ml->ml_root_vnode = mntpntovp(vl->vl_root_vnode,					      ml->ml_virtual, ml->ml_physical);	} else {		ml->ml_covered = NULL;	}error:	if (nse_list_nelems(viewlist) == 0) {		svc_finished = 1;	}	return (result);}/* ARGSUSED */inttfs_getname(vp, dummy, gr)	struct vnode	*vp;	int		dummy;	Tfs_getname_res	gr;{	static char	path[MAXPATHLEN];	ptopn(vp->v_pnode, path);	gr->path = path;	return (0);}/* * Flush all cached information for the branch specified by 'branch'. * Releases all pnodes, then creates new pnodes for the mountpoint vnodes. *//* ARGSUSED */inttfs_flush(dummy, branch)	int		dummy;	char		**branch;{	if (viewlist) {		nse_list_iterate(viewlist, vl_flush_all_vnodes, *branch);	}	return (0);}intcreate_tmp_view(vp, varname)	struct vnode	*vp;	char		*varname;{	Viewlist	vl;	vl = (Viewlist) nse_list_add_new_elem(viewlist);	vl->vl_environ_id = select_environ_id();	if (vl->vl_environ_id == -1) {		remove_from_list(viewlist, (char *) vl);		return NSE_TFS_TOO_MANY_ENVS;	}	vl->vl_env_name = NSE_STRDUP("tmp");	vl->vl_var_name = NSE_STRDUP(varname);	vl->vl_root_vnode = vp;	vp->v_environ_id = vl->vl_environ_id;	return 0;}voiddelete_tmp_view(vp)	struct vnode	*vp;{	Viewlist	vl;	vl = get_environ_entry(vp->v_environ_id);	release_environ_id(vl->vl_environ_id);	remove_from_list(viewlist, (char *) vl);}static intcreate_view(ma, vlp)	Tfs_mount_args	ma;	Viewlist	*vlp;{	Viewlist	vl;	vl = (Viewlist) nse_list_add_new_elem(viewlist);	vl->vl_environ_id = select_environ_id();	if (vl->vl_environ_id == -1) {		remove_from_list(viewlist, (char *) vl);		return NSE_TFS_TOO_MANY_ENVS;	}	vl->vl_env_name = NSE_STRDUP(ma->environ);	if (ma->conditional_view[0] != '\0') {		vl->vl_var_name = NSE_STRDUP(ma->conditional_view);	}	if (ma->default_view[0] != '\0') {		vl->vl_default_name = NSE_STRDUP(ma->default_view);	}	vl->vl_root_vnode = create_vnode((struct vnode *) NULL, "/",					 (long) 0);	vl->vl_root_vnode->v_environ_id = vl->vl_environ_id;	if (!ma->back_read_only) {		vl->vl_root_vnode->v_back_owner = FALSE;	}	vl->vl_root_vnode->v_writeable = ma->writeable_layers - 1;	*vlp = vl;	return 0;}static char *branch_to_var_name(fullbrname)	char		*fullbrname;{	char		tmpname[MAXPATHLEN];	char		variant[MAXNAMLEN];	nse_parse_branch_name(fullbrname, (char *) NULL, variant);	if (NSE_STREQ(variant, NSE_RT_SOURCE_NAME)) {		strcpy(tmpname, variant);	} else {		strcpy(tmpname, NSE_RT_VAR_PREFIX);		strcat(tmpname, variant);	}	return (NSE_STRDUP(tmpname));}#ifdef TFSDEBUGstatic voidpr_vnode_tree(vl)	Viewlist	vl;{	dprint(0, 0, "Branch: %s\n", vl->vl_env_name);	nse_list_print(vl->vl_mountlist);	nse_list_print(vl->vl_clientlist);	vnode_tree_print(vl->vl_root_vnode);}voidprint_vnode_trees(){	if (viewlist) {		nse_list_iterate(viewlist, pr_vnode_tree);	}}#endif TFSDEBUG/* * Routines to add/remove client entries from clientlists. */static voidadd_client_entry(clientlist, hostname, pid)	Nse_list	clientlist;	char		*hostname;	int		pid;{	Clientlist	cl;	cl = (Clientlist) nse_list_search(clientlist, cl_equal, hostname, pid);	if (cl == NULL) {		cl = (Clientlist) nse_list_add_new_elem(clientlist);		cl->cl_hostname = NSE_STRDUP(hostname);		cl->cl_pid = pid;		cl->cl_refcnt = 1;	} else {		cl->cl_refcnt++;	}}static bool_tremove_client_entry(clientlist, hostname, pid)	Nse_list	clientlist;	char		*hostname;	int		pid;{	Nse_listelem	cl_elem;	Clientlist	cl;	cl_elem = nse_list_search_elem(clientlist, cl_equal, hostname, pid);	if (cl_elem == NULL) {		return (FALSE);	}	cl = (Clientlist) nse_listelem_data(cl_elem);	cl->cl_refcnt--;	if (cl->cl_refcnt == 0) {		nse_listelem_delete(clientlist, cl_elem);	}	return (TRUE);}/* * Removes mountpoints from 'mlist' that will be covered by a mount on * 'path'.  A list of the removed mountpoints is returned. */static Nse_listget_covered_mounts(mlist, path)	Nse_list	mlist;	char		*path;{	Mountlist	ml;	Nse_listelem	elem;	Nse_listelem	end;	Nse_listelem	next;	int		pathlen = strlen(path);	Nse_list	covered_list = NULL;	elem = nse_list_first_elem(mlist);	end = nse_list_end(mlist);	while (elem != end) {		next = nse_listelem_next(elem);		ml = (Mountlist) nse_listelem_data(elem);		if (ml && strncmp(ml->ml_virtual, path, pathlen) == 0 &&		    ml->ml_virtual[pathlen] == '/') {			if (!covered_list) {				covered_list = mountlist_create();			}			nse_list_add_new_data(covered_list, ml);			nse_listelem_remove(mlist, elem);			nse_listelem_destroy_wrapper(elem, (Nse_opaque) NULL);			ml->ml_root_vnode->v_is_mount_pt = FALSE;		}		elem = next;	}	return covered_list;}/* * Put covered mountpoints back into 'mlist'. */static voidrestore_covered_mounts(covered_list, mlist, root_vnode)	Nse_list	covered_list;	Nse_list	mlist;	struct vnode	*root_vnode;{	Mountlist	ml;	Nse_listelem	elem;	Nse_listelem	end;	NSE_LIST_ITERATE(covered_list, Mountlist, ml, elem, end) {		ml->ml_root_vnode = mntpntovp(root_vnode, ml->ml_virtual,					      ml->ml_physical);		nse_list_add_new_data(mlist, ml);		nse_listelem_set_data(elem, (Nse_opaque) NULL);	}	nse_list_destroy(covered_list);}/* * Given the ID of the environment, returns the variant directory string * (to be used in following conditional searchlinks.) */char *environ_var_name(environ_id)	unsigned	environ_id;{	Viewlist	vl;	vl = get_environ_entry(environ_id);	if (vl == NULL) {		return (NULL);	} else {		return (vl->vl_var_name);	}}char *environ_default_name(environ_id)	unsigned	environ_id;{	Viewlist	vl;	vl = get_environ_entry(environ_id);	if (vl == NULL) {		return (NULL);	} else {		return (vl->vl_default_name);	}}bool_tenviron_has_multiple_clients(vp)	struct vnode	*vp;{	Viewlist	vl;	Clientlist	cl;	vl = get_environ_entry(vp->v_environ_id);	cl = (Clientlist) nse_listelem_data(				nse_list_first_elem(vl->vl_clientlist));	if (nse_list_search(vl->vl_clientlist, cl_name_neq, cl->cl_hostname)) {		return TRUE;	} else {		return FALSE;	}}/* * Used by get_environ_entry() so that we don't have to search viewlist every * time.  Set to 0 by release_environ_id(). */static int	last_environ_id;/* * Returns viewlist entry for the environment with id 'environ_id'. */static Viewlistget_environ_entry(environ_id)	unsigned	environ_id;{	static Viewlist	vl;	if (environ_id != last_environ_id) {		vl = (Viewlist) nse_list_search(viewlist, vl_environ_id_eq,						environ_id);		if (vl == NULL) {			last_environ_id = 0;		} else {			last_environ_id = environ_id;		}	}	return (vl);}/* * Routines to manage environment id's, to ensure that no more than * MAX_ENVIRON id's are handed out.  (Restricted by the width of the * v_environ_id field in the vnode.) */static int	next_environ_id;static long	used_environs;static intselect_environ_id(){	long		mask;	int		i;	for (i = 0; i <= MAX_ENVIRON; i++) {		next_environ_id++;		if (next_environ_id > MAX_ENVIRON) {			next_environ_id = 1;		}		mask = 1 << next_environ_id;		if ((used_environs & mask) == 0) {			used_environs |= mask;			return (next_environ_id);		}	}	return (-1);}static voidrelease_environ_id(id)	unsigned	id;{	used_environs &= ~(1 << id);	next_environ_id = id;	last_environ_id = 0;}/* * Routines for viewlists. */static bool_tvl_env_name_eq(vl, name)	Viewlist	vl;	char		*name;{	return (NSE_STREQ(vl->vl_env_name, name));}static bool_tvl_environ_id_eq(vl, num)	Viewlist	vl;	int		num;{	return (vl->vl_environ_id == num);}static voidvl_flush_all_vnodes(vl, name)	Viewlist	vl;	char		*name;{	if (strncmp(vl->vl_env_name, name, strlen(name)) == 0) {		nse_list_iterate(vl->vl_mountlist, ml_flush_all_vnodes);	}}/* * Routines for mountlists. */static bool_tml_path_eq(ml, name)	Mountlist	ml;	char		*name;{	return (NSE_STREQ(ml->ml_virtual, name));}static bool_tml_physical_eq(ml, name)	Mountlist	ml;	char		*name;{	return (NSE_STREQ(ml->ml_physical, name));}static voidml_flush_all_vnodes(ml)	Mountlist	ml;{	(void) update_directory(ml->ml_root_vnode->v_pnode, (char *) NULL,				DIR_FLUSH);}/* * Routines for clientlists. */static bool_tcl_equal(cl, hostname, pid)	Clientlist	cl;	char		*hostname;	int		pid;{	return (NSE_STREQ(cl->cl_hostname, hostname) && (cl->cl_pid == pid));}static bool_tcl_name_neq(cl, hostname)	Clientlist	cl;	char		*hostname;{	return !NSE_STREQ(cl->cl_hostname, hostname);}

⌨️ 快捷键说明

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