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

📄 tfs_lookup.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic char sccsid[] = "@(#)tfs_lookup.c 1.1 92/07/30 Copyr 1988 Sun Micro";#endif/* * Copyright (c) 1987 Sun Microsystems, Inc. */#include <nse/param.h>#include <nse/util.h>#include "headers.h"#include "vnode.h"#include "tfs.h"#include "subr.h"#include <signal.h>#include <nse/searchlink.h>Nse_list	ptrlist_create();/* * Vnode & pnode lookup routines. */struct vnode	*mntpntovp();struct vnode	*lookup_vnode();bool_t		recurse_lookup_pnode();bool_t		lookup_pnode();static bool_t	forward_pnode();struct pnode	*create_pnode();void		create_root_pnode();struct pnode	*follow_searchlink();static struct pnode *expand_slink_to_pnode();static struct pnode *lookup_dir_pnode();struct pnode	*path_to_pnode();static struct pnode *get_pnode();static int	set_visited_pnode();void		clear_visited_pnodes();static void	clear_pnode();/* * Routines which operate on fhandle hash table. */struct vnode	*fhtovp();struct vnode	*fhandle_find();void		fhandle_insert();void		fhandle_remove();/* * Routines which operate on pathname component hash table. */struct vnode	*find_vnode();static struct tnode *comp_find();void		comp_insert();void		comp_remove();/* * Vnode & pnode lookup routines. *//* * Given a mount pathname, allocate a new fhandle and vnode for the root of * the sub-hierarchy.  'virtpn' is the virtual pathname (mountpoint) and * 'realpn' is the directory being mounted */struct vnode *mntpntovp(root_vnode, virtpn, realpn)	struct vnode	*root_vnode;	char		*virtpn;	char		*realpn;{	struct vnode	*pvp;	struct vnode	*vp;	char		compname[MAXNAMLEN];	char		*cp = virtpn;	bool_t		new = FALSE;	vp = root_vnode;	cp++;	while (cp[0] != '\0') {		cp = _nse_extract_name(cp, compname);		pvp = vp;		vp = find_vnode(pvp, compname);		if (vp == NULL) {			vp = create_vnode(pvp, compname, (long) 0);			new = TRUE;		}	}	if (!new) {		/*		 * Make sure that vp's old pnode is released (it won't be		 * if the vnode is swapped out or is a mountpt vnode.)		 */		vp->v_is_mount_pt = FALSE;		if (vp->v_pnode && vp->v_pnode->p_swapped) {			swap_in_directory(vp->v_pnode);		}		vnode_tree_flush(vp);	}	vp->v_is_mount_pt = TRUE;	create_root_pnode(vp, realpn);	vp->v_layer = 0;	return (vp);}/* * Follow the searchlink from the directory with pnode 'pp', and return * a pointer to the directory the searchlink points to.  While we're reading * the .tfs_info file, read in the white-out entries also. * 'first_sub_layer' is the # of the frontmost sub-layer for the current * view. */struct pnode *follow_searchlink(pp, environ_id, first_sub_layer, wop, rename_recovered)	struct pnode	*pp;	unsigned	environ_id;	unsigned	first_sub_layer;	Nse_whiteout	*wop;	bool_t		*rename_recovered;{	char		new_pn[MAXPATHLEN];	char		searchlink[MAXPATHLEN];	struct pnode	*next_pp = NULL;	Nse_whiteout	bl = NULL;	Nse_whiteout	bl_rename;	if (wop) {		*wop = NULL;	}	if (rename_recovered) {		*rename_recovered = FALSE;	}	searchlink[0] = '\0';		if (set_visited_pnode(pp) != 0) {		return (NULL);	}	ptoname_or_pn(pp, new_pn);		if (tfsd_get_tfs_info(new_pn, searchlink, &bl, wop, FALSE,				       pp, TRUE)) {		return (NULL);	}	if (bl && (bl_rename = bl_list_get_rename_elem(bl))) {		(void) finish_rename_directory(new_pn, bl_rename->name);		if (rename_recovered) {			*rename_recovered = TRUE;			nse_dispose_whiteout(bl);			return (NULL);		}	}	nse_dispose_whiteout(bl);	if (searchlink[0] == '\0') {		return (NULL);	}	if (searchlink[0] == '/') {		next_pp = expand_slink_to_pnode(searchlink, environ_id,						first_sub_layer);	}	if (next_pp == NULL) {		nse_log_message("warning: Bad searchlink %s", searchlink);		print_pnode_path(pp);	} else 	if (next_pp->p_visited) {		nse_log_message("warning: Searchlink loop through %s to ",				searchlink);		print_pnode_path(pp);		return (NULL);	}	return (next_pp);}/* * Routines to prevent infinite recursion on circularities in searchlinks * and backlinks. set_visited_pnode and clear_visited_pnodes share * the 'visited_pnode_list'. */static Nse_list	visited_pnode_list = 0;/* * Check to see if pnode 'pp' has already been seen while following * a searchlink chain. If it has, log an error and return true, * otherwise mark it as visited and add it to the 'visited_pnode_list'. * We really shouldn't ever see a previously visited pnode here, but ... */static intset_visited_pnode(pp)	struct pnode	*pp;	{	char		path[MAXPATHLEN];	if (pp->p_visited) {		ptopn(pp, path);		nse_log_message("warning: Searchlink loop through %s\n", path);		return 1;	}	if (visited_pnode_list == 0) {		visited_pnode_list = ptrlist_create();	}	pp->p_visited = TRUE;	pp->p_refcnt++;	nse_list_add_new_data(visited_pnode_list, (Nse_opaque)pp);	return 0;}/* * Clean up pnodes visited while following searchlinks. */voidclear_visited_pnodes(){	if (visited_pnode_list) {		nse_list_iterate(visited_pnode_list, clear_pnode);		nse_list_destroy(visited_pnode_list);		visited_pnode_list = 0;	}}/* * Clear the visited flag of pnode 'pp'. Call free_pnode in case the * last reference to this pnode disappeared after it was visited. */static voidclear_pnode(pp)	struct pnode	*pp;{	pp->p_visited = FALSE;	free_pnode(pp);}/* * Return a vnode for the file 'name' in the directory with vnode 'pvp'. * Returns NULL if the file doesn't exist.  If the parameter 'attrs' is * non-NULL, the attributes of the file are returned.  If 'want_whiteout' * is TRUE, return the whiteout vnode for the file if it exists. */struct vnode *lookup_vnode(pvp, name, attrs, want_whiteout)	struct vnode	*pvp;	char		*name;	struct nfsfattr	*attrs;	bool_t		want_whiteout;{	struct vnode	*vp;	if (validate_directory(pvp) > 0) {		return (NULL);	}	vp = find_vnode(pvp, name);	if (vp == NULL) {		return (NULL);	}	if (vp->v_whited_out) {		if (want_whiteout) {			return (vp);		} else {			return (NULL);		}	}	if (vp->v_layer == INVALID_LAYER) {		vnode_tree_release(vp);		return (NULL);	}	if (!lookup_pnode(pvp, vp, attrs)) {		return (NULL);	}	return (vp);}/* * Lookup the pnode for vnode 'vp'.  Recursively looks up pnodes for all of * 'vp's ancestors, if the pnodes don't exist (because of a tfs_flush.) * Also ensures that all 'vp's ancestor directories are valid. * Returns TRUE if the pnode(s) is/are constructed, FALSE otherwise. */bool_trecurse_lookup_pnode(vp)	struct vnode	*vp;{	struct vnode	*pvp;	pvp = PARENT_VNODE(vp);	if (pvp == NULL) {		return (FALSE);	}	if (pvp->v_dir_valid) {		if (vp->v_pnode != NULL) {			return (TRUE);		}		if (pvp->v_pnode == NULL && !recurse_lookup_pnode(pvp)) {			return (FALSE);		}	} else {		if (vp->v_is_mount_pt) {			if (vp->v_pnode == NULL) {				nse_log_message("panic: recurse_lookup_pnode");				panic((struct pnode *) NULL);			}			return (TRUE);		}		if (!recurse_lookup_pnode(pvp)) {			return (FALSE);		}		if (validate_directory(pvp) > 0) {			return (FALSE);		}	}	return (lookup_pnode(pvp, vp, (struct nfsfattr *) NULL));}/* * Lookup the pnode for vnode 'vp'.  If 'vp' is for a directory, only the * pnode for the frontmost layer is constructed.  Returns TRUE if the pnode * is constructed, FALSE otherwise.  If 'attrs' is non-NULL, the attributes * of the file are returned. */bool_tlookup_pnode(pvp, vp, attrs)	struct vnode	*pvp;	struct vnode	*vp;	struct nfsfattr	*attrs;{	struct pnode	*parentp;	struct stat	statb;	char		*name = vp->v_name;	unsigned	type;	if (vp->v_pnode != NULL) {		if (attrs != NULL && getattrs_of(vp, attrs) < 0) {			vnode_tree_release(vp);			return (FALSE);		}		return (TRUE);	}	parentp = get_pnode_at_layer(pvp, vp->v_layer);	if (change_to_dir(parentp)) {		return (FALSE);	}	if (LSTAT(name, &statb) < 0) {		if (!forward_pnode(pvp, &parentp) || change_to_dir(parentp) ||		    LSTAT(name, &statb) < 0) {			vnode_tree_release(vp);			return (FALSE);		}	}	switch (statb.st_mode & S_IFMT) {	case S_IFREG:		type = PTYPE_REG;		break;	case S_IFDIR:		type = PTYPE_DIR;		break;	case S_IFLNK:		type = PTYPE_LINK;		break;	default:		type = PTYPE_OTHER;		break;	}	vp->v_pnode = create_pnode(parentp, name, type);	if (attrs != NULL) {		fattr_to_nattr(&statb, attrs);		if (attr_cache_on) {			if (vp->v_pnode->p_have_attrs) {				flush_cached_attrs(vp->v_pnode);			}			set_cached_attrs(vp->v_pnode, attrs);		}		fix_attrs(vp, attrs);	} else if ((type == PTYPE_REG) && (!vp->v_pnode->p_needs_write)) {		vp->v_pnode->p_size = statb.st_size;	}	return (TRUE);}/* * If the directory with pnode 'parentp' has been forwarded, return TRUE * and return the new pnode of the directory in '*parentp'. */static bool_tforward_pnode(vp, parentp)	struct vnode	*vp;	struct pnode	**parentp;{	struct pnode	*pp;	struct pnode	*newp;	struct pnode	*front_pp;	char		oldpath[MAXPATHLEN];	char		newpath[MAXPATHLEN];	struct stat	statb;

⌨️ 快捷键说明

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