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 + -
显示快捷键?