mountd.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 2,539 行 · 第 1/5 页

C
2,539
字号
}/* Is "export_gname" a netgroup and if so is client "mach" in it ?? * Searches netgroup cache, rebuilds the ng entry if it is timed out, * adds a new ng entry if need be.  Sets ng_or_host to 0 if export_gname * is a netgroup, 1 if it is a hostname. */int innetgr_cache(export_gname, mach, ng_or_host)	char *export_gname, *mach;	int *ng_or_host;{	struct ng *ngp;	int success, match;	static int variance;#ifdef DEBUG	(void)fprintf(stderr, "innetgr_cache called with gname: %s, mach: %s\n",		export_gname, mach);#endif DEBUG	/* Try to find netgroup in cache */	for (ngp = nglist; ngp != NULL; ngp = ngp->next_ng) {		if (strcmp(export_gname, ngp->ng_name) == 0) {			/*			 * In cache, is it timed out?  Netgroups time out			 * after 15-30 minutes.			 */			gettimeofday(&now, &tz);			if (variance > 900) 				variance=0;			if (now.tv_sec - ngp->ng_stamp > (ngtimeout+variance)) {			/*			 * Timed out, re-expand it			 */#ifdef DEBUG				(void)fprintf(stderr, 				    "timed out: variance is %d\n", variance);#endif DEBUG				success = expand_ng(ngp->ng_name);				if (success) {					free_ng(ngp);					ngp = nglist;					/* add 1 minute to variance */					variance += 60;				}				else {					syslog(LOG_ERR, 					  "Could not expand netgroup %s", 					   ngp->ng_name);					*ng_or_host = 1;					return(FALSE);				}			}			/* Is requesting host in this ng? */			match = check_ng(ngp, mach);			return(match);		}	}	/* 	 * export_gname not found in cache, try to expand it	 */	success = expand_ng(export_gname);	if (! success) {		*ng_or_host = 1;  /* its a hostname */		return(FALSE);	}	match = check_ng(nglist, mach);	return(match);}	/* * returns true if mach is in the cached netgroup pointed to by ngp */intcheck_ng(ngp, mach)	struct ng *ngp;	char *mach;{	struct hlist *hptr;	for (hptr = ngp->ng_hosts; hptr != NULL; hptr = hptr->next_host) {		if ((strcmp(hptr->hname, mach) == 0) || 		    (strcmp(hptr->hname, "everyone") == 0))			return(TRUE);	}#ifdef DEBUG	(void)fprintf(stderr, "Check ng returning FALSE\n");#endif DEBUG	return(FALSE);}new_ng(ngname)	char *ngname;{	struct ng *new;	char *newname;	new = (struct ng *)exmalloc(sizeof(*new));	newname = (char *)exmalloc(strlen(ngname) + 1);	(void)strcpy(newname, ngname);	new->ng_name = newname;	new->ng_hosts = NULL;	gettimeofday(&now, &tz);	new->ng_stamp = now.tv_sec;	new->next_ng = nglist;	new->prev_ng = NULL;	if (nglist != NULL)		nglist->prev_ng = new;	nglist = new;}new_ng_host(hname)	char *hname;{	struct hlist *new;	char *newname;	new = (struct hlist *)exmalloc(sizeof(*new));	newname = (char *)exmalloc(strlen(hname) + 1);	(void)strcpy(newname, hname);	new->hname = newname;	new->next_host = nglist->ng_hosts;	nglist->ng_hosts = new;}free_ng(ngp)	struct ng *ngp;{	struct hlist *hptr, *tmphptr;	hptr = ngp->ng_hosts;	while (hptr) {		tmphptr = hptr->next_host;		free(hptr->hname);		free(hptr);		hptr = tmphptr;	}	if (nglist == ngp) {		nglist = ngp->next_ng;		ngp->next_ng->prev_ng = NULL;	}	else {		ngp->prev_ng->next_ng = ngp->next_ng;		if (ngp->next_ng != NULL)			ngp->next_ng->prev_ng = ngp->prev_ng;	}	free(ngp->ng_name);	free(ngp);}#ifdef DEBUGprint_ngcache(){	struct ng *ngp;	struct hlist *hptr;	(void) fprintf(stderr, "NETGROUPS CACHE begin: \n");	for (ngp = nglist; ngp != NULL; ngp = ngp->next_ng) {		(void) fprintf(stderr, "\t ng_name: %s  stamp: %d\n",			ngp->ng_name, ngp->ng_stamp);		(void) fprintf(stderr, "\t HOSTS:\n");		for (hptr=ngp->ng_hosts; hptr!=NULL; hptr=hptr->next_host) {			(void)fprintf(stderr, "\t\t %s\n", hptr->hname);		}	}	(void) fprintf(stderr, "NETGROUPS CACHE end.\n");}#endif DEBUG/* * Initialize the duplicate reply cache. . . */dupcache_init() {	register struct dupreq *dr;	register struct dupreq **dt;	int i;	dupcache_max = 1024;	drhashsz = dupcache_max / 16;	drhashszminus1 = drhashsz - 1;	dr= (struct dupreq *) malloc(sizeof(*dr) * dupcache_max);	dt= (struct dupreq **) malloc(sizeof(struct dupreq *) * drhashsz);	for (i = 0; i < dupcache_max; i++)		dr[i].rc_next = &(dr[i + 1]);	dr[dupcache_max - 1].rc_next = dr;	dupreqcache = dr;	drmru = dr;	for (i = 0; i < drhashsz; i++)		dt[i] = NULL;	drhashtbl = dt;}dupcache_inval(){	int i;#ifdef DEBUG	(void) fprintf(stderr, "Invalidating duplicate requests cache\n");#endif DEBUG	for (i = 0; i < dupcache_max; i++)		unhash(&dupreqcache[i]);}dupcache_enter(addr,dev,ino,gen, anc_name)	struct in_addr addr;	dev_t  dev;	u_long	ino;		u_long	gen;		char *anc_name;{	register struct dupreq *dr;	char *newname;#ifdef DEBUG	(void) fprintf(stderr,"Entering addr:%x dev:%x ino:%d %d anc:%s\n",		addr.s_addr,dev,ino,gen, anc_name);#endif DEBUG	dr = drmru->rc_next;	unhash(dr);	drmru = dr;	newname = (char *)exmalloc(strlen(anc_name) + 1);	(void) strcpy(newname, anc_name);	dr->rc_addr = addr;	dr->rc_dev = dev;	dr->rc_ino = ino;	dr->rc_gen = gen;	dr->rc_ancname = newname;	dr->rc_chain = drhashtbl[((addr.s_addr ^ (int) dev ^ (int) ino ^ (int) gen) % drhashszminus1)];	drhashtbl[((addr.s_addr ^ (int)dev ^ (int)ino ^ (int) gen) % drhashszminus1)] = dr;#ifdef DEBUG	print_dupcache();#endif DEBUG}/* * returns a pointer to the dup req cache entry if it exists */struct dupreq *dupcache_check(addr,dev,ino,gen)	struct in_addr addr;	dev_t  dev;	u_long	ino;		u_long	gen;	{	register struct dupreq *dr;#ifdef DEBUG	(void) fprintf(stderr,"CHECK DUP CACHE for addr:%x dev:%x ino:%d %d\n",			addr.s_addr,dev,ino,gen);#endif DEBUG	dr = KEYTOLIST(addr.s_addr,dev,ino,gen); 	while (dr != NULL) { 		if (NOTDUP(dr,addr.s_addr,dev,ino,gen)) {			dr = dr->rc_chain;			continue;		}#ifdef DEBUG		(void)fprintf(stderr,"\t Got it!\n");#endif DEBUG		return(dr);	}#ifdef DEBUG	(void)fprintf(stderr,"\t Nope\n");#endif DEBUG	return((struct dupreq *) 0);}staticunhash(dr)	struct dupreq *dr;{	struct dupreq *drt;	struct dupreq *drtprev = NULL;	 	drt = REQTOLIST(dr); 	while (drt != NULL) { 		if (drt == dr) { 			if (drtprev == NULL) {				REQTOLIST(dr) = drt->rc_chain;			} else {				drtprev->rc_chain = drt->rc_chain;			}			free(dr->rc_ancname);			return; 		}			drtprev = drt;		drt = drt->rc_chain;	}	}#ifdef DEBUGprint_dupcache(){	struct dupreq *dr, **dt;	int i;	(void) fprintf(stderr, "DUP REQS CACHE begin: \n");	dt = drhashtbl;	for (i=0; i < drhashsz; i++) {		(void)fprintf(stderr, "hash list[%d]\n", i);		for (dr = dt[i]; dr != NULL; dr = dr->rc_chain) {		    (void)fprintf(stderr,"\t addr:%x dev:%x ino:%d %d anc:%s\n",			dr->rc_addr, dr->rc_dev, dr->rc_ino, dr->rc_gen,			dr->rc_ancname);		}	}	(void) fprintf(stderr, "DUP REQS CACHE end.\n");}#endif DEBUG/* * Input name in raw, canonicalized pathname output to canon.  If dosymlinks * is nonzero, resolves all symbolic links encountered during canonicalization * into an equivalent symlink-free form.  Returns 0 on success, -1 on failure. * * Sets errno on failure. */intpathcanon(raw, canon, dosymlinks)    char	*raw,		*canon;    int		dosymlinks;{    register char	*s,			*d;    register char	*limit = canon + MAXPATHLEN;    char		*modcanon;    int			nlink = 0;    /*     * Make sure that none of the operations overflow the corresponding buffers.     * The code below does the copy operations by hand so that it can easily     * keep track of whether overflow is about to occur.     */    s = raw;    d = canon;    modcanon = canon;    while (d < limit && *s)	*d++ = *s++;    /* Add a trailing slash to simplify the code below. */    s = "/";    while (d < limit && (*d++ = *s++))	continue;	    /*     * Canonicalize the path.  The strategy is to update in place, with     * d pointing to the end of the canonicalized portion and s to the     * current spot from which we're copying.  This works because     * canonicalization doesn't increase path length, except as discussed     * below.  Note also that the path has had a slash added at its end.     * This greatly simplifies the treatment of boundary conditions.     */    d = s = modcanon;    while (d < limit && *s) {	if ((*d++ = *s++) == '/' && d > canon + 1) {	    register char  *t = d - 2;	    switch (*t) {	    case '/':		/* Found // in the name. */		d--;		continue;	    case '.': 		switch (*--t) {		case '/':		    /* Found /./ in the name. */		    d -= 2;		    continue;		case '.': 		    if (*--t == '/') {			/* Found /../ in the name. */			while (t > canon && *--t != '/')			    continue;			d = t + 1;		    }		    continue;		default:		    break;		}		break;	    default:		break;	    }	    /*	     * We're at the end of a component.  If dosymlinks is set	     * see whether the component is a symbolic link.  If so,	     * replace it by its contents.	     */	    if (dosymlinks) {		char		link[MAXPATHLEN + 1];		register int	llen;		/*		 * See whether it's a symlink by trying to read it.		 *		 * Start by isolating it.		 */		*(d - 1) = '\0';		if ((llen = readlink(canon, link, sizeof link)) >= 0) {		    /* Make sure that there are no circular links. */		    nlink++;		    if (nlink > MAXSYMLINKS) {			errno = ELOOP;			return (-1);		    }		    /*		     * The component is a symlink.  Since its value can be		     * of arbitrary size, we can't continue copying in place.		     * Instead, form the new path suffix in the link buffer		     * and then copy it back to its proper spot in canon.		     */		    t = link + llen;		    *t++ = '/';		    /*		     * Copy the remaining unresolved portion to the end		     * of the symlink. If the sum of the unresolved part and		     * the readlink exceeds MAXPATHLEN, the extra bytes		     * will be dropped off. Too bad!		     */		    (void) strncpy(t, s, sizeof link - llen - 1);		    link[sizeof link - 1] = '\0';		    /*		     * If the link's contents are absolute, copy it back		     * to the start of canon, otherwise to the beginning of		     * the link's position in the path.		     */		    if (link[0] == '/') {			/* Absolute. */			(void) strcpy(canon, link);			d = s = canon;		    }		    else {			/*			 * Relative: find beginning of component and copy.			 */			--d;			while (d > canon && *--d != '/')			    continue;			s = ++d;			/*			 * If the sum of the resolved part, the readlink			 * and the remaining unresolved part exceeds			 * MAXPATHLEN, the extra bytes will be dropped off.			*/			if (strlen(link) >= (limit - s)) {				(void) strncpy(s, link, limit - s);				*(limit - 1) = '\0';			} else {				(void) strcpy(s, link);			}		    }		    continue;		} else {		   /*		    * readlink call failed. It can be because it was		    * not a link (i.e. a file, dir etc.) or because the		    * the call actually failed.		    */		    if (errno != EINVAL)			return (-1);		    *(d - 1) = '/';	/* Restore it */		}	    } /* if (dosymlinks) */	}    } /* while */    /* Remove the trailing slash that was added above. */    if (*(d - 1) == '/' && d > canon + 1)	    d--;    *d = '\0';    return (0);}/* * Canonicalize the path given in raw, resolving away all symbolic link * components.  Store the result into the buffer named by canon, which * must be long enough (MAXPATHLEN bytes will suffice).  Returns NULL * on failure and canon on success. * * The routine indirectly invokes the readlink() system call  * so it inherits the possibility of hanging due to inaccessible file  * system resources. */char *realpath(raw, canon)    char	*raw;    char	*canon;{    return (pathcanon(raw, canon, 1) < 0 ? NULL : canon);}

⌨️ 快捷键说明

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