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

📄 tfs_subr.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Construct a pathname for a pnode.  If a parent directory has an fd * open, fchdir to it and return the partial name; otherwise construct the * full pathname of the file.  If a parent directory has a long name, then * fchdir to that directory (this saves on NFS remote lookup calls, since * the kernel directory name lookup cache only caches names of a small * length.) */voidptoname_or_pn(pp, pn)	struct pnode	*pp;	char		*pn;{	char            tpn[MAXPATHLEN];	char		*pnptr = &tpn[MAXPATHLEN - 1];	int             pathsize = 0;	if ((pp->p_fd != 0) && (pp->p_type == PTYPE_DIR) &&	    (change_to_dir(pp) == 0)) {		strcpy(pn, ".");		return;	}	*pnptr = '\0';	do {		pnptr = prepend(pp->p_name, pnptr, &pathsize);		pp = PARENT_PNODE(pp);		if (pp->p_fd != 0 || strlen(pp->p_name) >= 20) {			if (change_to_dir(pp) == 0) {				break;			}		}		pnptr = prepend("/", pnptr, &pathsize);	} while (pp->p_name[0] != '/');	strcpy(pn, pnptr);}/* * Convert pnode to full pathname. */voidptopn(pp, pn)	struct pnode	*pp;	char		*pn;{	ntree_pathname((struct tnode *) pp, pn);}/* * Convert vnode to virtual pathname. */voidvtovn(vp, pn)	struct vnode	*vp;	char		*pn;{	ntree_pathname((struct tnode *) vp, pn);}/* * prepend() tacks a directory name onto the front of a pathname. * The maximum length of the pathname is MAXPATHLEN. */char *prepend(dirname, pathname, pathsize)	char		*dirname;	char		*pathname;	int		*pathsize;{	int		i;		/* directory name size counter */	for (i = 0; *dirname != '\0'; i++, dirname++)		continue;	if ((*pathsize += i) < MAXPATHLEN)		while (i-- > 0)			*--pathname = *--dirname;	return (pathname);}/* * Alarm routines, for timing out the attribute & write caches */#define ALARM_DELAY	5		/* # of secs between alarms */static struct timeval current_time;bool_t		alarm_went_off;extern bool_t	servicing_req;longget_current_time(precise)	bool_t		precise;{	struct timeval	time;	if (current_time.tv_sec == 0) {#ifdef TFSDEBUG		dprint(tfsdebug, 3, "Setting alarm\n");#endif TFSDEBUG		(void) gettimeofday(&current_time, (struct timezone *) NULL);		alarm(ALARM_DELAY);	} else if (precise) {		(void) gettimeofday(&time, (struct timezone *) NULL);		return (time.tv_sec);	}	return (current_time.tv_sec);}/* ARGSUSED */voidalarm_handler(sig, code, scp)	int		sig;	int		code;	struct sigcontext *scp;{	bool_t		more_attrs;	bool_t		more_writes;	if (servicing_req) {		/*		 * Handle this alarm after the current request is serviced.		 * (This avoids race conditions between the attr and write		 * cache timeout routines and other routines which modify		 * the caches.)		 */		alarm_went_off = TRUE;		return;	}	(void) gettimeofday(&current_time, (struct timezone *) NULL);#ifdef TFSDEBUG	dprint(tfsdebug, 3, "ALARM = %u\n", current_time.tv_sec);#endif TFSDEBUG	more_attrs = timeout_attr_cache(current_time.tv_sec);	more_writes = timeout_wcache(current_time.tv_sec);	if ((more_attrs) || (more_writes)) {		alarm(ALARM_DELAY);	} else {		current_time.tv_sec = 0;	}	alarm_went_off = FALSE;}intinit_alarm(){	(void) signal(SIGALRM, alarm_handler);}/* * Routines which keep track of the process's user credentials. *//* * Declare this struct rather than use 'struct ucred' because the fields * of ucred are shorts in 4.0.  This will cause problems if the uid or * gid is ever negative, because setreuid & setregid barf if given a * negative number other than -1.  (An example negative uid/gid is -2 * for 'nobody'.) */static struct {	u_short		cr_uid;			/* effective user id */	u_short		cr_gid;			/* effective group id */	int		cr_groups[NGROUPS];	/* groups, 0 terminated */} user_cred;static int	num_groups;		/* Length of group list *//* * Change user id */voidchange_user_id(uid)	int		uid;{	setreuid(-1, 0);	setreuid(-1, uid);}intcurrent_user_id(){	return (user_cred.cr_uid);}/* * Set uid, gid, and gids to auth params that came in over the wire.  Call * setreuid only if the set of auth params is different from the current set * of user credentials.  NOTE: any other routine which does a setreuid() * must make sure to setreuid() back to the effective user id, otherwise * chaos could result! */intset_user_id(aup)	struct authunix_parms *aup;{#ifdef TFSDEBUG	dprint(tfsdebug, 3, "(uid %d gid %d)  ", aup->aup_uid, aup->aup_gid);#endif TFSDEBUG	/*	 * If the user changes groups on us, we won't catch it here.	 */	if (aup->aup_uid == user_cred.cr_uid) {		return (0);	}	if (setreuid(-1, 0)) {		return (-1);	}	user_cred.cr_gid = aup->aup_gid;	if (setregid(-1, (int) user_cred.cr_gid)) {		return (-1);	}	num_groups = aup->aup_len;	BCOPY((caddr_t) aup->aup_gids, (caddr_t) user_cred.cr_groups,	      num_groups * sizeof (int));	if (setgroups((int) num_groups, (int *) aup->aup_gids)) {		return (-1);	}	user_cred.cr_uid = aup->aup_uid;	if (setreuid(-1, (int) user_cred.cr_uid)) {		return (-1);	}	return (0);}/* * This routine is called by tfs_setattr() to ensure that the user has * the correct access to file 'vp' to set the attributes specified in * 'sa'.  This routine is necessary because the file may have to be * promoted to the front file system before the attributes are set, and * we don't want to copy the file if the setattr is going to fail. */inthas_perm_to_setattr(vp, sa)	struct vnode	*vp;	struct nfssattr *sa;{	struct nfsfattr	attrs;	if (getattrs_of(vp, &attrs) < 0) {		return (errno);	}	/*	 * Change file mode or time.  Must be owner of file.	 */	if ((sa->sa_mode != (u_short) -1 && sa->sa_mode != -1) ||	    sa->sa_atime.tv_sec != -1 || sa->sa_mtime.tv_sec != -1) {		if (user_cred.cr_uid != attrs.na_uid) {			return (EPERM);		}	}	/*	 * Change file/group ownership.  Must be su.	 */	if (sa->sa_uid != -1 &&	    sa->sa_uid != attrs.na_uid &&	    user_cred.cr_uid != 0) {		return (EPERM);	}	if (sa->sa_gid != -1 &&	    sa->sa_gid != attrs.na_gid &&	    !in_group_list((int) sa->sa_gid) &&	    user_cred.cr_uid != 0) {		return (EPERM);	}	/*	 * Truncate file.  Must have write access to the file and the	 * node cannot be a directory.	 */	if (sa->sa_size != -1) {		if (vp->v_pnode->p_type == PTYPE_DIR ||		    !has_access(&attrs, W_OK)) {			return (EACCES);		}	}	return (0);}/* * Check for accessibility of the file with attributes 'attrs', given * the credentials of the user.  'mode' is one of R_OK, W_OK, X_OK, or * an inclusive OR of them.  This function returns TRUE if the file can * be accessed by the user.  This function duplicates the functionality * of the access() system call.  We can't use the access() system call * directly because access() would use the tfsd's real user id and real * group id, and we want to test for access using the effective uid & gid. */bool_thas_access(attrs, mode)	struct nfsfattr	*attrs;	int		mode;{	/*	 * If you're the super-user, you always get access.	 */	if (user_cred.cr_uid == 0) {		return (TRUE);	}	/*	 * Access check is based on only one of owner, group, public.	 * If not owner, then check group.  If not a member of the group, then	 * check public access.	 */	mode <<= 6;	if (user_cred.cr_uid != attrs->na_uid) {		mode >>= 3;		if (!in_group_list((int) attrs->na_gid)) {			mode >>= 3;		}	}	return ((attrs->na_mode & mode) == mode);}static bool_tin_group_list(gid)	int		gid;{	int		i;	if (gid == user_cred.cr_gid) {		return (TRUE);	}	for (i = 0; i < num_groups; i++) {		if (gid == user_cred.cr_groups[i]) {			return (TRUE);		}	}	return (FALSE);}/* * Wrapper routines for NSE library routines which manipulate .tfs_info * files.  These wrapper routines allow the tfsd to print an error message * before returning a cryptic error to the client (e.g. the tfsd may * return EPERM when it doesn't have permission to open .tfs_info, when the * client is doing an operation for which the error EPERM doesn't make sense.) */inttfsd_set_searchlink(directory, name, pp)	char		*directory;	char		*name;	struct pnode	*pp;{	Nse_err		err;	if (err = nse_set_searchlink(directory, name)) {		nse_log_message("warning: can't set searchlink: ");		tfsd_err_print(err);		if (pp) {			print_pnode_path(pp);		}		return (err->code);	}	return (0);}inttfsd_set_whiteout(directory, name, pp)	char		*directory;	char		*name;	struct pnode	*pp;{	Nse_err		err;	if (err = nse_set_whiteout(directory, name)) {		nse_log_message("warning: can't set whiteout: ");		tfsd_err_print(err);		if (pp) {			print_pnode_path(pp);		}		return (err->code);	}	return (0);}inttfsd_clear_whiteout(directory, name, pp)	char		*directory;	char		*name;	struct pnode	*pp;{	Nse_err		err;	if (err = nse_clear_whiteout(directory, name)) {		nse_log_message("warning: can't clear whiteout: ");		tfsd_err_print(err);		if (pp) {			print_pnode_path(pp);		}		return (err->code);	}	return (0);}inttfsd_get_backlink(directory, blp)	char		*directory;	Nse_whiteout	*blp;{	Nse_err		err;	if (err = nse_get_backlink(directory, blp)) {		nse_log_message("warning: can't get backlink: ");		tfsd_err_print(err);		return (err->code);	}	return (0);}inttfsd_set_backlink(directory, name)	char		*directory;	char		*name;{	Nse_err		err;	if (err = nse_set_backlink(directory, name)) {		nse_log_message("warning: can't set backlink: ");		tfsd_err_print(err);		return (err->code);	}	return (0);}inttfsd_get_tfs_info(directory, name, blp, wop, will_write_later, pp,		  ignore_enoent)	char		*directory;	char		*name;	Nse_whiteout	*blp;	Nse_whiteout	*wop;	bool_t		will_write_later;	struct pnode	*pp;	bool_t		ignore_enoent;	/* ignore ENOENT error? */{	Nse_err		err;	if (err = nse_get_tfs_info(directory, name, blp, wop,				   will_write_later)) {		if (ignore_enoent && err->code == ENOENT) {			return (0);		}		nse_log_message("warning: nse_get_tfs_info: ");		tfsd_err_print(err);		if (pp) {			print_pnode_path(pp);		}		return (err->code);	}	return (0);}inttfsd_set_tfs_info(directory, name, bl_first, wo, pp)	char		*directory;	char		*name;	Nse_whiteout	bl_first;	Nse_whiteout	wo;	struct pnode	*pp;{	Nse_err		err;	if (err = nse_set_tfs_info(directory, name, bl_first, wo)) {		nse_log_message("warning: nse_set_tfs_info: ");		tfsd_err_print(err);		if (pp) {			print_pnode_path(pp);		}		return (err->code);	}	return (0);}/* * Miscellaneous *//* * Modify the file with pnode 'pp' with the function 'ffunc' if the file * has a file descriptor, or with 'func' if the file doesn't have an fd. *//* VARARGS4 */intmodify_file(pp, func, ffunc, arg1, arg2)	struct pnode	*pp;	int		(* func)();	int		(* ffunc)();	int		arg1;	int		arg2;{	char		name[MAXNAMLEN];	if (pp->p_fd != 0) {		if (ffunc(pp->p_fd, arg1, arg2) < 0) {			return (errno);		}	} else {		ptoname(pp, name);		if (func(name, arg1, arg2) < 0) {			return (errno);		}	}	return (0);}/* * Set the modify and access times of the file with vnode 'vp' to the * indicated values.  If 'vp' is in a writeable layer, directly modify * the file; otherwise set the mtime in .tfs_backfiles and set the atime * of the read-only file. */intdo_utimes(vp, mtime, atime, set_to_now)	struct vnode	*vp;	long		mtime;	long		atime;	bool_t		set_to_now;{	struct pnode	*parentp;	struct timeval	tvp[2];	struct nfsfattr	attrs;	char		*fname;	char		name[MAXNAMLEN];	int		result;	if (vp->v_is_mount_pt) {		parentp = vp->v_pnode;		fname = ".";	} else {		parentp = get_front_parent_pnode(PARENT_VNODE(vp),						 vp->v_layer);		fname = vp->v_name;	}	if (IS_WRITEABLE(vp)) {		if (result = change_to_dir(parentp)) {			return (result);		}		if (set_to_now) {			if (utimes(fname, (struct timeval *)0) < 0) {				return (errno);			}		} else {			tvp[0].tv_sec = atime;			tvp[0].tv_usec = 0;			tvp[1].tv_sec = mtime;

⌨️ 快捷键说明

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