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

📄 tfs_vnodeops.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic char sccsid[] = "@(#)tfs_vnodeops.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 "vnode.h"#include "tfs.h"#include "subr.h"#include <nse/param.h>#include <nse/util.h>#include <nse/searchlink.h>/* * Routines to implement NFS ops.  (Except for readdir, which is in * tfs_dirs.c.) */extern int	chmod();extern int	fchmod();extern int	chown();extern int	fchown();int		tfs_error();int		tfs_null();int		tfs_getattr();int		tfs_setattr_1();int		tfs_setattr_2();static int	do_setattr();int		tfs_lookup_1();int		tfs_lookup_2();static int	do_lookup();int		tfs_readlink();int		tfs_read();int		tfs_write();int		tfs_create_1();int		tfs_create_2();static int	do_create();int		tfs_remove();int		tfs_rename();int		tfs_link();int		tfs_symlink();int		tfs_mkdir_1();int		tfs_mkdir_2();static int	do_mkdir();int		tfs_rmdir();int		tfs_statfs();int		tfs_translate();/* * Error procedure invoked when an obsolete NFS procedure is called. * (i.e. nfs_root & nfs_writecache) */inttfs_error(){	return (EOPNOTSUPP);}/* * Procedure 0.  Null procedure available for ping-ing. */inttfs_null(){#ifdef TFSDEBUG	trace_reset();	print_vnode_trees();	pnode_tree_print();	comp_print();	print_fd_cache();	swqueue_print();#endif TFSDEBUG	/* do nothing */	return (0);}/* * Procedure 1.  Get file attributes. * Returns the current attributes of the file with the given fhandle. *//*ARGSUSED*/inttfs_getattr(vp, fhp, ns)	struct vnode   *vp;	fhandle_t	*fhp;	struct nfsattrstat *ns;{	if (!attr_cache_on) {		init_attr_cache();	}	if (getattrs_of(vp, &ns->ns_attr) < 0) {		return (errno);	}	return (0);}/* * Procedure 2.  Set file attributes. * Sets the attributes of the file with the given fhandle.  Returns * the new attributes. */inttfs_setattr_1(vp, args, ns)	struct vnode	*vp;	struct nfssaargs *args;	struct nfsattrstat *ns;{	int		result;	if (result = do_setattr(vp, args)) {		return (result);	}	if (args->saa_sa.sa_size != (u_long) -1) {		/*		 * Truncate changes the mtime of the file, so make sure that		 * the updated mtime is correct.		 */		(void) write_wcache(vp->v_pnode, (char *) NULL, 0, 0L);	}	if (getattrs_of(vp, &ns->ns_attr) < 0) {		return (errno);	}	return (0);}inttfs_setattr_2(vp, args, dr)	struct vnode	*vp;	struct nfssaargs *args;	struct tfsdiropres *dr;{	int		result;	if (result = do_setattr(vp, args)) {		return (result);	}	fill_diropres(vp, dr);	return (0);}static intdo_setattr(vp, args)	struct vnode	*vp;	struct nfssaargs *args;{	struct pnode	*pp;	char		name[MAXNAMLEN];	struct nfssattr *sa = &args->saa_sa;	bool_t		set_to_now;	int		result;	if (result = has_perm_to_setattr(vp, sa)) {		return (result);	}	pp = vp->v_pnode;	if (pp->p_type == PTYPE_REG && pp->p_needs_write) {		sync_wcache(pp);	}	/*	 * For all operations other than changing the file's access or	 * modify times, copy-on-write the file before changing its attrs.	 */	if ((sa->sa_mode != (u_short) -1 && sa->sa_mode != -1) ||	    sa->sa_uid != -1 || sa->sa_gid != -1 ||	    sa->sa_size != (u_long) -1) {		if (result = promote_file(vp)) {			return (result);		}	}	pp = vp->v_pnode;	if (sa->sa_mode != (u_short) -1 && sa->sa_mode != -1) {		if (result = modify_file(pp, chmod, fchmod,					 (int) sa->sa_mode)) {			return (result);		}	}	if (sa->sa_uid != -1 || sa->sa_gid != -1) {		if (result = modify_file(pp, chown, fchown,					 (int) sa->sa_uid, (int) sa->sa_gid)) {			return (result);		}	}	if (sa->sa_size != (u_long) -1) {		/*		 * ftruncate() needs an fd opened for writing, so just use		 * truncate().		 */		ptoname(pp, name);		if (truncate(name, (long) sa->sa_size) < 0) {			return (errno);		}	}	/*	 * Change file access or modified times.	 */	set_to_now = FALSE;	if (sa->sa_atime.tv_sec != -1 || sa->sa_mtime.tv_sec != -1) {#ifdef SUN_OS_4		/*		 * Allow SysV-compatible option to set access and		 * modified times.		 * XXX - va_mtime.tv_usec == -1 flags this.		 */		if (sa->sa_mtime.tv_sec != -1 && sa->sa_mtime.tv_usec == -1) {			set_to_now = TRUE;		}#endif		if (result = do_utimes(vp, sa->sa_mtime.tv_sec,				       sa->sa_atime.tv_sec, set_to_now)) {			return (result);		}	}	flush_cached_attrs(pp);	return (0);}/* * Procedure 4.  Directory lookup. * Returns an fhandle and file attributes for file name in a directory. */inttfs_lookup_1(pvp, da, dr)	struct vnode	*pvp;	struct nfsdiropargs *da;	struct nfsdiropres *dr;{	struct vnode	*vp;	int		result;	if (result = do_lookup(pvp, da, &vp, &dr->dr_attr)) {		return (result);	}	makefh(&dr->dr_fhandle, vp);	return (0);}inttfs_lookup_2(pvp, da, dr)	struct vnode	*pvp;	struct nfsdiropargs *da;	struct tfsdiropres *dr;{	struct vnode	*vp;	int		result;	if (result = do_lookup(pvp, da, &vp, (struct nfsfattr *) NULL)) {		return (result);	}	fill_diropres(vp, dr);	return (0);}static intdo_lookup(pvp, da, vpp, attrs)	struct vnode	*pvp;	struct nfsdiropargs *da;	struct vnode	**vpp;	struct nfsfattr *attrs;{	struct vnode	*vp;	char		*name = da->da_name;	if (is_tfs_special_file(name)) {		return (ENOENT);	} else if (NSE_STREQ(name, ".")) {		vp = pvp;	} else if (NSE_STREQ(name, "..")) {		vp = PARENT_VNODE(pvp);		if (vp == NULL || pvp->v_is_mount_pt) {			vp = pvp;		}	} else {		vp = lookup_vnode(pvp, name, attrs, FALSE);		if (vp == NULL) {			return (ENOENT);		}		goto got_attrs;	}	if (attrs && getattrs_of(vp, attrs) < 0) {		return (errno);	}got_attrs:	*vpp = vp;	return (0);}/* * Procedure 5.  Read symbolic link. * Returns the string in the symbolic link at the given fhandle. *//* ARGSUSED */inttfs_readlink(vp, fhp, rl)	struct vnode	*vp;	fhandle_t	*fhp;	struct nfsrdlnres *rl;{	char            name[MAXNAMLEN];	int             count;	rl->rl_data = read_result_buffer;	ptoname(vp->v_pnode, name);	count = readlink(name, rl->rl_data, MAXPATHLEN);	if (count < 0) {		rl->rl_data = NULL;		rl->rl_count = 0;		return (errno);	}	rl->rl_data[count] = '\0';	rl->rl_count = count;	return (0);}/* * Procedure 6.  Read data. * Returns some data read from the file at the given fhandle. */inttfs_read(vp, ra, rr)	struct vnode   *vp;	struct nfsreadargs *ra;	struct nfsrdresult *rr;{	struct pnode	*pp;	long		offset;	int		length;	int		count;	/*	 * Check the transfer size restriction.  If we try to send more than	 * NFS_MAXDATA, we will hang the server.  This is only a problem if the	 * client dosn't listen to our transfer size in statfs. 	 */	if (ra->ra_count > NFS_MAXDATA) {		return (EMSGSIZE);	}	rr->rr_data = read_result_buffer;	/*	 * for now we assume no append mode and ignore totcount (read ahead) 	 */	offset = (long) ra->ra_offset;	length = (int) ra->ra_count;	count = 0;	pp = vp->v_pnode;	if (offset >= pp->p_size) {		/*		 * Reading past EOF (happens when the buffer cache		 * reads-ahead before writing.)		 */		goto rdwr_finished;	}	if (get_rw_fd(vp, UIO_READ) < 0) {		return (errno);	}	if (pp->p_needs_write) {		/*		 * Read data from write cache if it's there.		 */		count = read_wcache(pp, rr->rr_data, length, offset);	}	if (count <= 0) {		count = rdwr_fd(pp, rr->rr_data, length, offset, UIO_READ);	}rdwr_finished:	if ((count < 0) || getattrs_of(vp, &rr->rr_attr) < 0) {		return (errno);	}	rr->rr_count = count;	return (0);}/* * Procedure 8.  Write data to file. * Returns attributes of a file after writing some data to it. */inttfs_write(vp, wa, ns)	struct vnode   *vp;	struct nfswriteargs *wa;	struct nfsattrstat *ns;{	struct pnode	*pp;	int		result;	long		offset;	int		length;	/*	 * for now we assume no append mode 	 */	if (result = promote_file(vp)) {		return (result);	}	pp = vp->v_pnode;	if (pp->p_write_error != 0) {		/*		 * Return error code that was returned when an earlier		 * delayed write failed.		 */		return (pp->p_write_error);	}	if (get_rw_fd(vp, UIO_WRITE) < 0) {		return (errno);	}	offset = (long) wa->wa_offset;	length = (int) wa->wa_count;	if (offset + length >= pp->p_size) {		pp->p_size = offset + length;	}	result = write_wcache(pp, wa->wa_data, length, offset);	if ((result < 0) || getattrs_of(vp, &ns->ns_attr) < 0) {		return (errno);	}	return (0);}/* * Procedure 9.  Create a file. * Creates a file with given attributes and returns those attributes * and an fhandle for the new file. */inttfs_create_1(pvp, args, dr)	struct vnode	*pvp;	struct nfscreatargs *args;	struct nfsdiropres *dr;{	struct vnode	*vp;	int		old_size = -1;	int		result;	if (result = do_create(pvp, args, &vp, &old_size)) {		return (result);	}	if (getattrs_of(vp, &dr->dr_attr) < 0) {		return (errno);	}	if (old_size == -1 || args->ca_sa.sa_size == 0) {		/*		 * If the file was just created or truncated, we have to		 * update the mtime of the file, even if no writes are		 * done to the file later.		 */		(void) write_wcache(vp->v_pnode, (char *) NULL, 0, 0L);		if (getattrs_of(vp, &dr->dr_attr) < 0) {			return (errno);		}	}	makefh(&dr->dr_fhandle, vp);	return (0);}inttfs_create_2(pvp, args, dr)	struct vnode	*pvp;	struct nfscreatargs *args;	struct tfsdiropres *dr;{	struct vnode	*vp;	int		result;	if (result = do_create(pvp, args, &vp, (int *) NULL)) {		return (result);	}	fill_diropres(vp, dr);	return (0);}/* * XXX The sa_uid field of the args is used as a transaction ID to check * for duplicate requests.  We really should add a transaction ID field * to the create args. */static intdo_create(pvp, args, vpp, sizep)	struct vnode	*pvp;	struct nfscreatargs *args;	struct vnode	**vpp;	int		*sizep;{	struct vnode	*vp;	struct pnode	*parentp;	struct pnode	*pp;	struct nfsfattr	attrs;	char		*name = args->ca_da.da_name;	int		mode;	int		flags;	int		result;	/*	 * XXX Should get exclusive flag and pass it on here.	 */	if (is_tfs_special_file(name)) {		return (EACCES);	}	vp = lookup_vnode(pvp, name, &attrs, TRUE);	if (vp != NULL && !vp->v_whited_out) {		if (attrs.na_size == 0 && args->ca_sa.sa_size == 0 &&		    dupreq_is_duplicate(TFS_CREATE, args->ca_sa.sa_uid)) {			*vpp = vp;			if (sizep) {				*sizep = attrs.na_size;			}			return (0);		}		/*		 * If file exists in a back file system, create the file in		 * the front file system with the mode of the existing file		 * in the back fs (if we have the proper access to the file.)		 */		if (!has_access(&attrs, W_OK)) {			return (EACCES);		}		if (sizep) {			*sizep = attrs.na_size;		}		parentp = get_front_parent_pnode(pvp, vp->v_layer);		mode = (int) attrs.na_mode;		if (!IS_WRITEABLE(vp)) {			if ((parentp->p_link && parentp->p_link->l_next) ||			    environ_has_multiple_clients(vp)) {				update_ctime(vp, FALSE);			}			release_pnodes(vp);		} else if (args->ca_sa.sa_size == -1) {			/*

⌨️ 快捷键说明

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