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

📄 tfs_subr.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
			tvp[1].tv_usec = 0;			if (utimes(fname, tvp) < 0) {				return (errno);			}		}		return (0);	}	if (set_to_now) {		if (result = get_server_time(parentp, &mtime)) {			return (result);		}		atime = mtime;	}	if (mtime != -1) {		if ((result = update_directory(parentp, fname, DIR_UTIME_FILE,					       mtime)) ||		    (result = change_backlist_mtime(parentp, fname, mtime))) {			return (result);		}	}	if (atime != -1) {		/*		 * Set the access time of the file in the read-only layer		 */		if (get_realattrs_of(vp, &attrs) < 0) {			return (errno);		}		if (attrs.na_atime.tv_sec == atime) {			return (0);		}		tvp[0].tv_sec = atime;		tvp[0].tv_usec = 0;		tvp[1].tv_sec = -1;		tvp[1].tv_usec = 0;		ptoname(vp->v_pnode, name);		result = utimes_as_owner(name, tvp, (int) attrs.na_uid);	}	return (result);}/* * Create a dummy file in 'dir' whose sole purpose is to get the * current 'mtime' on the NFS server on which it resides. This is * used by utimes(x, NULL) to get the right value of 'mtime' for a * file 'x' which is in the read-only layers of 'dir'. */static intget_server_time(dir, mtime)	struct pnode	*dir;	long		*mtime;{	int		fd;	struct stat	stbuf;	int		result = 0;	*mtime = -1;	if (result = change_to_dir(dir)) {		return result;	}	if (utimes(NSE_TFS_FILE, (struct timeval *) NULL) == -1 ||	    stat(NSE_TFS_FILE, &stbuf) == -1) {		if (errno != ENOENT) {			return (errno);		}		fd = open(NSE_TFS_UTIMES_FILE, O_RDWR|O_CREAT, 0666);		if (fd == -1) {			return (errno);		}		if (fstat(fd, &stbuf) == -1) {			result = errno;		}		if (close(fd) == -1 && result == 0) {			result = errno;		}		if (unlink(NSE_TFS_UTIMES_FILE) == -1 && result == 0) {			result = errno;		}	}	*mtime = stbuf.st_mtime;	return (result);}/* * Update the ctime of the file with vnode 'vp' by setting its atime and * mtime to their current values.  This is necessary so that the kernel VFS * will know when a directory has had an entry removed.  (The kernel VFS * needs to flush a directory from the directory name lookup cache (DNLC) * when the directory's ctime changes, because it is possible for someone * on another machine to remove or rename a file/dir that was in the local * machine's DNLC; we don't want the file to be reachable through the DNLC * any longer.)  The tfsd needs to explicitly update the ctime of the * directory in the front layer when a file is removed from a back layer, * or a file is removed by creating a whiteout entry. * * This routine is also called when a file in a back layer is * copy-on-writed, in two cases: 1) there is more than one view on the file * (e.g. the file can be seen in both a var-sun3 and a var-sun4 activation * at the same time), or 2) the environ containing the file is being * accessed by more than one client machine.  In such a case, it is * possible for a client on one machine to copy-on-write a file for which * there is another kernel TFS vnode.  Updating the ctime of the file * in the back layer is the only way to alert the client kernel that the * other TFS vnode's real vnode has changed.  NOTE: this unfortunately updates * the ctime of a file in a read-only layer. * * It is not necessary to call this routine when a directory is * copy-on-writed, because the kernel VFS knows that a directory is * copy-on-writed the first time it is read, and so will flush the real * vnode of a non-writeable directory the first time it is read. */voidupdate_ctime(vp, avoid_dup_updates)	struct vnode	*vp;	bool_t		avoid_dup_updates;{	struct nfsfattr	attrs;	struct timeval	tvp[2];	char		name[MAXNAMLEN];	int		result;	if (avoid_dup_updates) {		if (vp->v_pnode->p_updated) {			return;		}		vp->v_pnode->p_updated = TRUE;	}	if (get_realattrs_of(vp, &attrs) < 0) {		print_warning_msg(vp->v_pnode, "update_ctime: getattrs");		return;	}	tvp[0].tv_sec = attrs.na_atime.tv_sec;	tvp[0].tv_usec = 0;	tvp[1].tv_sec = attrs.na_mtime.tv_sec;	tvp[1].tv_usec = 0;	if (vp->v_pnode->p_type == PTYPE_DIR &&	    change_to_dir(vp->v_pnode) == 0) {		strcpy(name, ".");	} else {		ptoname(vp->v_pnode, name);	}	result = utimes_as_owner(name, tvp, (int) attrs.na_uid);	if (result) {		errno = result;		print_warning_msg(vp->v_pnode, "update_ctime: utimes");	}}intutimes_as_owner(name, tvp, owner)	char		*name;	struct timeval	tvp[2];	int		owner;{	int		result = 0;	if (owner != current_user_id()) {		change_user_id(owner);	}	if (utimes(name, tvp) < 0) {		result = errno;	}	if (owner != current_user_id()) {		change_user_id(current_user_id());	}	return (result);}/* * Determine when the cached mtime for pnode 'pp' will expire and need to * be checked.  Use the algorithm used by the NFS -- base the expire time * on the time since the directory last changed, but set limits on the * maximum and minimum expire times. */voidset_expire_time(pp)	struct pnode	*pp;{	long		delta;	pp->p_expire = get_current_time(FALSE);	delta = (pp->p_expire - pp->p_mtime) >> 4;	if (delta < MIN_DIR_EXPIRE) {		delta = MIN_DIR_EXPIRE;	} else if (delta > MAX_DIR_EXPIRE) {		delta = MAX_DIR_EXPIRE;	}	pp->p_expire += delta;}/* * This routine is called by tfs_rename() and tfs_link(), which create * new names for objects at specified sub-layers.  This routine handles * two complications that arise: * 1) If the source file occurred at a layer further back than the dest *    file, then the original dest file has to be removed.  (This ensures *    that we don't create a file underneath an existing file/whiteout entry.) * 2) If the source file at a layer further forward than the dest file, *    but dest is at a greater sub-layer, then the source file will have *    to be pushed to the sub-layer of dest.  In this case, 'dest_sub_layer' *    is set to the sub-layer that the file has to be pushed to. */inthandle_rename_sub_layers(dest_vp, src_layer, dest_sub_layer)	struct vnode	*dest_vp;	unsigned	src_layer;	int		*dest_sub_layer;{	struct pnode	*src_pp;	struct pnode	*dest_pp;	int		result;	dest_pp = get_front_parent_pnode(PARENT_VNODE(dest_vp),					 dest_vp->v_layer);	if (dest_vp->v_layer < src_layer) {		if (result = clear_file(dest_pp, dest_vp)) {			return (result);		}	} else if (dest_vp->v_layer > src_layer) {		src_pp = get_front_parent_pnode(PARENT_VNODE(dest_vp),						src_layer);		if (src_pp->p_sub_layer < dest_pp->p_sub_layer) {			*dest_sub_layer = dest_pp->p_sub_layer;		}	}	return (0);}/* * Expand the variant searchlink 'path' into 'expanded_path'.  'cp' is a * pointer to the position of the wildcard string in 'path', and 'environ_id' * is the environment ID which should be used to expand the searchlink. * 'use_var_name' indicates whether to use the variant name or the default * name of the environment. */bool_texpand_searchlink(path, environ_id, cp, expanded_path, use_var_name)	char		*path;	unsigned	environ_id;	char		*cp;	char		*expanded_path;	bool_t		use_var_name;{	char		*tailp;	char		oldc;	tailp = cp + strlen(NSE_TFS_WILDCARD);	if (*tailp != '/') {		return (FALSE);	}	oldc = *cp;	*cp = '\0';	strcpy(expanded_path, path);	*cp = oldc;	if (use_var_name && (cp = environ_var_name(environ_id))) {		strcat(expanded_path, cp);	} else if (cp = environ_default_name(environ_id)) {		strcat(expanded_path, cp);	} else {		return (FALSE);	}	strcat(expanded_path, tailp);	return (TRUE);}/* * Convert the path 'path' into a variant searchlink. */static bool_tcreate_variant_searchlink(path, environ_id, unexpanded_path)	char		*path;	unsigned	environ_id;	char		*unexpanded_path;{	char		*cp = NULL;	char		*tailp;	char		oldc;	char		*varname;	char		*default_name;	varname = environ_var_name(environ_id);	if (varname) {		cp = nse_find_substring(path, varname);	}	if (cp) {		tailp = cp + strlen(varname);	} else {		default_name = environ_default_name(environ_id);		cp = nse_find_substring(path, default_name);		if (cp == NULL) {			return (FALSE);		}		tailp = cp + strlen(default_name);	}	if (*tailp != '/') {		return (FALSE);	}	oldc = *cp;	*cp = '\0';	strcpy(unexpanded_path, path);	*cp = oldc;	strcat(unexpanded_path, NSE_TFS_WILDCARD);	strcat(unexpanded_path, tailp);	return (TRUE);}/* * Fill tfsdiropres struct to send back to kernel.  Used by TFS version 2 * requests.  (The client kernel contains the kernel VFS.) */voidfill_diropres(vp, dr)	struct vnode	*vp;	struct tfsdiropres *dr;{	static char	pn[MAXPATHLEN];	makefh(&dr->dr_fh, vp);	dr->dr_nodeid = vp->v_fhid;	ptopn(vp->v_pnode, pn);	if (vp->v_pnode->p_type == PTYPE_DIR) {		/*		 * A mountpoint vnode may have a pnode which is actually		 * a symlink, if a branch mount has been made of a relocated		 * variant.  In this case, we want to return the pathname		 * of the real directory, not the symlink, to the kernel.		 * Note that the pnodes at mountpoints are the only ones		 * which can be assigned a p_type which does not match		 * the type of the real file.		 */		if (vp->v_is_mount_pt) {			struct stat	statb;			while (LSTAT(pn, &statb) == 0 &&			       (statb.st_mode & S_IFMT) == S_IFLNK) {				int		count;				count = readlink(pn, pn, MAXPATHLEN);				if (count < 0) {					break;				}				pn[count] = '\0';			}		}		dr->dr_writeable = (vp->v_layer == 0);	} else {		dr->dr_writeable = IS_WRITEABLE(vp);	}	dr->dr_path = pn;	dr->dr_pathlen = strlen(pn);	sattr_null(&dr->dr_sattrs);	if (!IS_WRITEABLE(vp)) {		if (vp->v_back_owner) {			dr->dr_sattrs.sa_uid = current_user_id();		}		if (vp->v_mtime != 0) {			dr->dr_sattrs.sa_mtime.tv_sec = vp->v_mtime;			dr->dr_sattrs.sa_mtime.tv_usec = 0;		}	}}/* * Set sattr structure to a null value. * XXX machine dependent? */static voidsattr_null(sap)	struct nfssattr	*sap;{	int		n;	char		*cp;	n = sizeof(struct nfssattr);	cp = (char *) sap;	while (n--) {		*cp++ = -1;	}}/* * Chdir to /tmp and dump core there.  Called from various places when * something strange happens. */voidpanic(pp)	struct pnode	*pp;{	if (pp != NULL) {		print_pnode_path(pp);	}	kill_me();}voidkill_me(){	/*	 * Core dump will be successful only if (uid == euid && gid == egid)	 */	(void) setreuid(-1, 0);	(void) setregid(-1, getgid());	(void) chdir("/tmp");	abort();}bool_tis_tfs_special_file(name)	char		*name;{	return (strncmp(name, NSE_TFS_FILE_PREFIX, NSE_TFS_FILE_PREFIX_LEN)		== 0);}voidprint_warning_msg(pp, str)	struct pnode	*pp;	char		*str;{	nse_log_message("warning: ");	tfsd_perror(str);	print_pnode_path(pp);}voidprint_pnode_path(pp)	struct pnode	*pp;{	char		pn[MAXPATHLEN];	ptopn(pp, pn);	fprintf(stderr, " (dir %s)\n", pn);	fprintf(stdout, " (dir %s)\n", pn);}extern int	sys_nerr;extern char	*sys_errlist[];voidtfsd_perror(str)	char		*str;{	char		string[MAXPATHLEN];	strcpy(string, str);	strcat(string, ": ");	if (errno < sys_nerr && errno > 0) {		strcat(string, sys_errlist[errno]);	} else {		str = string + strlen(string);		sprintf(str, "Unknown error #%d", errno);	}	fprintf(stderr, string);	fprintf(stdout, string);}/* * Print the error string to stdout and stderr without the leading * 'tfsd: '. */voidtfsd_err_print(err)	Nse_err		err;{	char		*str;	if (err) {		str = index(err->str, ' ');		str++;		fprintf(stderr, "%s\n", str);		fprintf(stdout, "%s\n", str);	}}inthash_string(compname)	char	       *compname;{	int		sum;	for (sum = 0; *compname; sum += *compname++)		;	return (sum & (HASH_TABLE_SIZE - 1));}/* * get the fhandle from a given vnode. */voidmakefh(fh, vp)	fhandle_t	*fh;	struct vnode	*vp;{	extern time_t	tfsd_timestamp;		BZERO((caddr_t) fh, NFS_FHSIZE);	TFS_FH(fh)->fh_id = vp->v_fhid;	TFS_FH(fh)->fh_parent_id = PARENT_VNODE(vp)->v_fhid;	TFS_FH(fh)->fh_timestamp = tfsd_timestamp;}FILE *open_tfs_file(path, mode, errp)	char		*path;	char		*mode;	Nse_err		*errp;{	FILE		*file;	Nse_err		err;	if (err = nse_fopen(path, mode, &file)) {		if (errp) {			*errp = err;		} else {			nse_log_err_print(err);		}		return (NULL);	}	if (file != NULL) {		setbuffer(file, read_result_buffer, NFS_MAXDATA);	}	return (file);}/* * Returns the next vnode in the directory (which is not a whiteout vnode.) */struct vnode *next_file(vp)	struct vnode	*vp;{	do {		vp = NEXT_VNODE(vp);	} while (vp != NULL && vp->v_whited_out);	return (vp);}/* * Returns the next whiteout vnode in the directory. */struct vnode *next_whiteout(vp)	struct vnode	*vp;{	do {		vp = NEXT_VNODE(vp);	} while (vp != NULL && (!vp->v_whited_out || !IS_WRITEABLE(vp)));	return (vp);}

⌨️ 快捷键说明

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