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

📄 tfs_client.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
字号:
#ifndef lintstatic char sccsid[] = "@(#)tfs_client.c 1.1 92/07/30 Copyr 1988 Sun Micro";#endif/* * Copyright (c) 1987 Sun Microsystems, Inc. *//* * Library routines which make RPC calls to the TFS server to obtain their * results. */#include <nse/param.h>#include <sys/stat.h>#include <sys/socket.h>#include <sys/dir.h>#include <stdio.h>#include <strings.h>#include <nse/util.h>#include <nse_impl/tfs_user.h>#include <nse/tfs_calls.h>Nse_err		nse_tfs_flush();Nse_err		nse_tfs_sync();Nse_err		nse_tfs_getname();Nse_err		nse_tfs_push();Nse_err		nse_tfs_pull();Nse_err		nse_unwhiteout();struct direct	*nse_readdir_whiteout();static int	get_wo_entries();Nse_err		nse_tfs_set_searchlink();Nse_err		nse_tfs_set_cond_searchlink();static Nse_err	set_searchlink();Nse_err		nse_tfs_clear_front_fs();Nse_err		nse_tfs_wo_readonly_files();static Nse_err	tfs_rpc_call();static Nse_err	get_parent_nodeid();static Nse_err	get_nodeid();/* * Tell the TFS to flush any cached information it might be keeping for the * current branch. */Nse_errnse_tfs_flush(branch)	char		*branch;{#ifdef lint	if (branch[0]) {}#endif lint#ifdef notdef	char		branchid[NSE_MAXLONGBRANCHNAMELEN];	char		*cp = branchid;	enum nfsstat	status;	Nse_err		err;	if (branch == NULL) {		branch = getenv(NSE_BRANCH_ENV);		if (branch == NULL) {			return nse_err_format(NSE_BRERR_NONAME);		}	}	if (err = nse_branch_to_ascii_id(branch, branchid)) {		return err;	}	err = nse_tfs_rpc_call(branch, TFS_FLUSH,					xdr_wrapstring, (char *) &cp,					xdr_enum, (char *) &status);	if (err == NULL && (int) status != 0) {		err = nse_err_format((int) status);	}	return err;#endif notdef}/* * Tell the TFS to synchronize its write cache with disk. */Nse_errnse_tfs_sync(branch)	char		*branch;{	return (nse_tfs_rpc_call(branch, TFS_SYNC, xdr_void, (char *)NULL,				 xdr_void, (char *) NULL));}/* * Get a translation for the virtual name 'virt_path', and return it in * 'phys_path'. */Nse_errnse_tfs_getname(branch, virt_path, phys_path)	char		*branch;	char		*virt_path;	char		*phys_path;{	Tfs_getname_res_rec gr;	Tfs_fhandle_rec	fhandle;	gr.path = phys_path;	return tfs_rpc_call(branch, TFS_GETNAME, "getname", virt_path, FALSE,			    xdr_tfs_fhandle, (char *) &fhandle,			    xdr_tfs_getname_res, (char *) &gr);}Nse_errnse_tfs_push(branch, path)	char		*branch;	char		*path;{	Tfs_fhandle_rec	fhandle;	enum nfsstat	status;	return tfs_rpc_call(branch, TFS_PUSH, "push", path, FALSE,			    xdr_tfs_fhandle, (char *) &fhandle,			    xdr_enum, (char *) &status);}Nse_errnse_tfs_pull(branch, path)	char		*branch;	char		*path;{	Tfs_fhandle_rec	fhandle;	enum nfsstat	status;	return tfs_rpc_call(branch, TFS_PULL, "pull", path, FALSE,			    xdr_tfs_fhandle, (char *) &fhandle,			    xdr_enum, (char *) &status);}/* * Unwhiteout the file referenced by 'path'.  Returns 0 if all goes well, or * a non-zero error code if an error occurs. */Nse_errnse_unwhiteout(branch, path)	char		*branch;	char		*path;{	Tfs_name_args_rec ua;	char		dir_name[MAXPATHLEN];	char		name[MAXNAMLEN];	enum nfsstat	status;	_nse_parse_filename(path, dir_name, name);	ua.name = name;	return tfs_rpc_call(branch, TFS_UNWHITEOUT, "unwhiteout", dir_name,			    TRUE, xdr_tfs_name_args, (char *) &ua,			    xdr_enum, (char *) &status);}/* * Get next whited-out entry in a directory.  (Copy of readdir(3) code.) * 'dirp' should be initialized with opendir(3), and closed with * closedir(3). */struct direct *nse_readdir_whiteout(branch, dirname, dirp)	char		*branch;	char		*dirname;	DIR		*dirp;{	struct direct	*dp;#ifdef SUN_OS_4	int saveloc = 0;next:        if (dirp->dd_size != 0) {                dp = (struct direct *)&dirp->dd_buf[dirp->dd_loc];                saveloc = dirp->dd_loc;   /* save for possible EOF */                dirp->dd_loc += dp->d_reclen;        }        if (dirp->dd_loc >= dirp->dd_size)                dirp->dd_loc = dirp->dd_size = 0;        if (dirp->dd_size == 0  /* refill buffer */          && (dirp->dd_size = get_wo_entries(branch, dirname, dirp->dd_buf,					     (int) dirp->dd_bsize)             ) <= 0           ) {                if (dirp->dd_size == 0) /* This means EOF */                        dirp->dd_loc = saveloc;  /* EOF so save for telldir */                return (NULL);    /* error or EOF */        }        dp = (struct direct *)&dirp->dd_buf[dirp->dd_loc];        if (dp->d_reclen <= 0)                return (NULL);        if (dp->d_fileno == 0)                goto next;        dirp->dd_off = dp->d_off;        return(dp);#else	for (;;) {		if (dirp->dd_loc == 0) {			dirp->dd_size = get_wo_entries(branch, dirname,							dirp->dd_buf,							(int) dirp->dd_bsize);			if (dirp->dd_size <= 0)				return (NULL);			dirp->dd_entno = 0;		}		if (dirp->dd_loc >= dirp->dd_size) {			dirp->dd_loc = 0;			continue;		}		dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc);		if (dp->d_reclen <= 0)			return (NULL);		dirp->dd_loc += dp->d_reclen;		dirp->dd_entno++;		if (dp->d_fileno == 0)			continue;		return (dp);	}#endif}/* * Get the whited-out files in the directory with name 'path' (which can be a * relative pathname.)  'buf' is filled with the whited-out entries of the * front file system only.  This function returns the number of bytes in * 'buf', 0 if the end of the directory has been reached. */static intget_wo_entries(branch, path, buf, nbytes)	char		*branch;	char		*path;	char		*buf;	int		nbytes;{	/*	 * One-entry cache to keep track of the current offset within the	 * directory, and whether or not we've reached eof in the directory	 * yet.	 */	static char	last_path[MAXPATHLEN];	static int	last_offset;	static int	eof = 0;	Tfs_get_wo_args_rec args;	Tfs_get_wo_res_rec result;	Nse_err		err;	if (NSE_STREQ(path, last_path)) {		if (eof) {			last_path[0] = '\0';			return (0);		}		args.offset = last_offset;	} else {		strcpy(last_path, path);		last_offset = 0;		eof = 0;	}	args.nbytes = nbytes;	args.offset = last_offset;	result.buf = buf;	result.count = nbytes;	err = tfs_rpc_call(branch, TFS_GET_WO, "get_whiteout_entries",			   path, TRUE, xdr_tfs_get_wo_args, (char *) &args,			   xdr_tfs_get_wo_res, (char *) &result);	if (err) {		nse_err_print(err);		last_path[0] = '\0';		return (-1);	} else {		last_offset = result.offset;		eof = result.eof;		return (result.count);	}}Nse_errnse_tfs_set_searchlink(branch, directory, name)	char		*branch;	char		*directory;	char		*name;{	return (set_searchlink(branch, directory, name, FALSE));}Nse_errnse_tfs_set_cond_searchlink(branch, directory, name)	char		*branch;	char		*directory;	char		*name;{	return set_searchlink(branch, directory, name, TRUE);}static Nse_errset_searchlink(branch, directory, name, conditional_set)	char		*branch;	char		*directory;	char		*name;	bool_t		conditional_set;{	Tfs_searchlink_args_rec sa;	enum nfsstat	status;	sa.value = name;	sa.conditional = conditional_set;	return tfs_rpc_call(branch, TFS_SET_SEARCHLINK, "set_searchlink",			    directory, TRUE,			    xdr_tfs_searchlink_args, (char *) &sa,			    xdr_enum, (char *) &status);}Nse_errnse_tfs_clear_front_fs(branch, path)	char		*branch;	char		*path;{	Tfs_name_args_rec pa;	char		dir_name[MAXPATHLEN];	char		name[MAXPATHLEN];	enum nfsstat	status;	_nse_parse_filename(path, dir_name, name);	pa.name = name;	return tfs_rpc_call(branch, TFS_CLEAR_FRONT, "clear_front_fs",			    dir_name, TRUE, xdr_tfs_name_args, (char *) &pa,			    xdr_enum, (char *) &status);}Nse_errnse_tfs_wo_readonly_files(branch, path)	char		*branch;	char		*path;{	Tfs_fhandle_rec	fhandle;	enum nfsstat	status;	return tfs_rpc_call(branch, TFS_WO_READONLY_FILES, "wo_readonly_files",			    path, TRUE, xdr_tfs_fhandle, (char *) &fhandle,			    xdr_enum, (char *) &status);}/* * Make the TFS RPC call 'procnum' on the file named 'path'.  'follow_symlink' * determines whether a symlink should be followed when getting the fhandle * for the file.  If an error code is returned by the TFS server, format * an error struct and return.  Note that the TFS server can't format the * error for the NSE_TFS_NOT_UNDER_MOUNTPT error because the TFS doesn't * know the name of the file in this case while the client does. * This routine relies on the fhandle being the first word of args, and on * the return status being the first word of res. */static Nse_errtfs_rpc_call(branch, procnum, procname, path, follow_symlink, xdr_args, args,	     xdr_res, res)	char		*branch;	int		procnum;	char		*procname;	char		*path;	bool_t		follow_symlink;	xdrproc_t	xdr_args;	char		*args;	xdrproc_t	xdr_res;	char		*res;{	Tfs_fhandle	fhp;	int		ntries = 0;	int		status;	Nse_err		err;	fhp = (Tfs_fhandle) args;	if (err = get_nodeid(path, follow_symlink, &fhp->nodeid)) {		return err;	}	fhp->parent_id = 0;retry:	err = nse_tfs_rpc_call(branch, procnum, xdr_args, args, xdr_res, res);	if (err) {		return err;	}	status = *(int *) res;	if (status == 0) {		return NULL;	} else if (status > 0) {		errno = status;		if (procnum == TFS_UNWHITEOUT || procnum == TFS_CLEAR_FRONT) {			return nse_err_format_errno("TFS %s of %s/%s",						    procname, path,						  ((Tfs_name_args)args)->name);		} else {			return nse_err_format_errno("TFS %s of %s", procname,						    path);		}	} else if (status == NSE_TFS_NOT_UNDER_MOUNTPT && ntries == 0) {		/*		 * get nodeid of parent directory and try again		 */		ntries++;		if (err = get_parent_nodeid(path, follow_symlink,					    &fhp->parent_id)) {			return err;		}		goto retry;	} else {		/*		 * NSE_TFS_NOT_UNDER_MOUNTPT takes a path argument; other		 * TFS error returns which could be seen here take no		 * arguments.		 */		return nse_err_format((int) status, path);	}}static Nse_errget_parent_nodeid(path, follow_symlink, nodeidp)	char		*path;	bool_t		follow_symlink;	long		*nodeidp;{	struct stat	statb;	char		abs_path[MAXPATHLEN];	char		abs_dir[MAXPATHLEN];	char		dir[MAXPATHLEN];	char		*cp;	if (follow_symlink && lstat(path, &statb) == 0 &&	    (statb.st_mode & S_IFMT) == S_IFLNK) {		/*		 * If we're following symlinks and this file is a symlink,		 * we want to stat the directory that is the parent of the		 * file referenced by the symlink.		 */		if (nse_abspath(path, abs_path) == NULL) {			strcpy(abs_path, path);		} else {			/* XXX cover up for bug in nse_abspath()!			 */			cp = &abs_path[strlen(abs_path) - 1];			if (*cp == '/') {				*cp = '\0';			}		}		_nse_parse_filename(abs_path, abs_dir, (char *) NULL);	} else {		/*		 * Could be any # of symlinks above the file		 */		_nse_parse_filename(path, dir, (char *) NULL);		if (nse_abspath(dir, abs_dir) == NULL) {			strcpy(abs_dir, dir);		}	}	return get_nodeid(abs_dir, FALSE, nodeidp); }static Nse_errget_nodeid(path, follow_symlink, nodeidp)	char		*path;	bool_t		follow_symlink;	long		*nodeidp;{	struct stat	statb;	static char *last_name = NULL;	static bool_t last_symlink;	static long last_ino;	if (last_name && NSE_STREQ(path, last_name) &&	    follow_symlink == last_symlink) {		*nodeidp = last_ino;		return NSE_OK;	}	if (follow_symlink) {		if (stat(path, &statb) < 0) {			return nse_err_format_errno("Stat of \"%s\"", path);		}	} else {		if (lstat(path, &statb) < 0) {			return nse_err_format_errno("Stat of \"%s\"", path);		}	}	NSE_DISPOSE(last_name);	last_ino = *nodeidp = statb.st_ino;	last_name = NSE_STRDUP(path);	last_symlink = follow_symlink;	return NULL;}

⌨️ 快捷键说明

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