mountd.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 2,539 行 · 第 1/5 页
C
2,539 行
if ((ch1 && ch2) && !strcmp(ch1, ch2)) { if (ch11 && *ch11 != '\0') { *--ch11 = s1; ch11++; } if (ch22 && *ch22 != '\0') { *--ch22 = s2; ch22++; } ch1 = ch11; ch2 = ch22; if ((ch11 && *ch11 == '\0') || !ch11) { /* * count number of slashes remaining in ancestor */ if (ch2) { for (--ch2; ch2 && *ch2!='\0'; ch2++) if (*ch2 == '/') level++; if (*--ch2 == '/') level--; } return(level); } if ((ch11 && *ch11 != '\0') && ((ch22 && *ch22 == '\0') || !ch22)) done = 1; } else { if (ch11 && *ch11 != '\0') *--ch11 = s1; if (ch22 && *ch22 != '\0') *--ch22 = s2; done = 1; } } return(level);}/* * Skip over slashes (/) and go to first character */char *goto_char(ch) char *ch;{ for (;ch && *ch == '/'; ch++) ; if (ch) return(ch); else return(NULL);} /* * Remove an entry from mounted list */mtd_umount(rqstp, transp) struct svc_req *rqstp; SVCXPRT *transp;{ char *path; struct mountdlist *ml, *oldml; struct hostent *client; long pos = -1; if ((client = getclientsname(rqstp,transp))== NULL) { svcerr_weakauth(transp); return; } path = NULL; if (!svc_getargs(transp, xdr_path, &path)) { svcerr_decode(transp); mtd_abort(); return; }#ifdef DEBUG (void) fprintf(stderr, "umounting %s for %s\n", path, client->h_name);#endif oldml = mountlist; for (ml = mountlist; ml != NULL; oldml = ml, ml = ml->ml_nxt) { if (strcmp(ml->ml_path, path) == 0 && strcmp(ml->ml_name, client->h_name) == 0) { if (ml == mountlist) mountlist = ml->ml_nxt; else oldml->ml_nxt = ml->ml_nxt;#ifdef DEBUG (void) fprintf(stderr, "freeing %s\n", path);#endif pos = ml->ml_pos; free(ml->ml_path); free(ml->ml_name); free((char *)ml); break; } } if (!svc_sendreply(transp,xdr_void, NULL)) { syslog(LOG_ERR, "couldn't reply to UMOUNT rpc call"); mtd_abort(); } else { gettimeofday(&now, &tz); if ((now.tv_sec - rmtab_written.tv_sec) > rmtab_sync) { dumptofile(); rmtab_written = now; } else if (pos >= 0) { rmtab_delete(pos); } } svc_freeargs(transp, xdr_path, &path);}/* * Remove all entries for one machine from mounted list */mtd_umountall(rqstp, transp) struct svc_req *rqstp; SVCXPRT *transp;{ char *machine; struct mountdlist *ml, *oldml; if (!svc_getargs(transp, xdr_void, NULL)) { svcerr_decode(transp); return; } /* * We assume that this call is asynchronous and made via the * portmapper callit routine. Therefore return control immediately. * The error causes the portmapper to remain silent, as opposed to * every machine on the net blasting the requester with a response. */ svcerr_systemerr(transp); if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) { machine = ((struct authunix_parms *)rqstp->rq_clntcred)->aup_machname; } else return; oldml = mountlist; for (ml = mountlist; ml != NULL; ml = ml->ml_nxt) { if (strncmp(ml->ml_name, machine, sizeof(machine)) == 0) {#ifdef DEBUG (void) fprintf(stderr, "got a hit\n");#endif if (ml == mountlist) { mountlist = ml->ml_nxt; oldml = mountlist; } else oldml->ml_nxt = ml->ml_nxt; rmtab_delete(ml->ml_pos); free(ml->ml_path); free(ml->ml_name); free((char *)ml); } else oldml = ml; } svc_freeargs(transp, xdr_void, NULL);}FILE *f;/* * Save current mount state info so we * can attempt to recover in case of a crash. */dumptofile(){ static char *t1 = "/etc/zzXXXXXX"; static char *t2 = "/etc/zzXXXXXX"; FILE *fp; struct mountdlist *ml; char *mktemp(); int mf; (void) fclose(f); (void) strcpy(t2, t1); t2 = mktemp(t2); if ((mf = creat(t2, 0644)) < 0) { syslog(LOG_ERR, "creat: %m, cannot dump mountlist to %s", RMTAB); return; } if ((fp = fdopen(mf, "w")) == NULL) { syslog(LOG_ERR, "fdopen: %m, cannot dump mountlist to %s", RMTAB); return; } for (ml = mountlist; ml != NULL; ml = ml->ml_nxt) { ml->ml_pos = ftell(fp); (void) fprintf(fp, "%s:%s\n", ml->ml_name, ml->ml_path); } if (rename(t2, RMTAB) < 0) syslog(LOG_ERR, "rename: %m, cannot dump mountlist to %s", RMTAB); (void) fclose(fp); f = fopen(RMTAB, "r+");}/* * send current export list */mtd_export(transp) SVCXPRT *transp;{ struct exports *ex; if (!svc_getargs(transp, xdr_void, NULL)) { svcerr_decode(transp); mtd_abort(); } else { /* * Send exported request the list of flattened exports * to conform with other os's. Otherwise, all * exported directories would not be seen. */ ex = flatexports; if (!svc_sendreply(transp, xdr_exports, &ex)) { syslog(LOG_ERR, "couldn't reply to EXPORT rpc call"); mtd_abort(); } }}/* * Parse exports file. If this is the first call or the file exportfile * has changed, it is opened and parsed to create an exports list. * File should look like: * * pathname [-r=#] [-o] [name1 name2 ... namen] * or * #anything * * pathname: name of a mounted local file system * name of a directory of a mounted local filesystem * optional options * -r=# for entire filesystem, root maps to # * -o entire filesystem exported readonly * name: netgroup or host name or a list of whitespace separated * names (optional, no names implies everyone) * * A '#' anywhere in the line marks a comment to the end of that line * * NOTE: a non-white character in column 1 indicates a new export * specification. */set_exports(){ int bol; /* begining of line */ int eof; /* end of file */ int opt; /* beginning of option */ struct exports *ex, *ex2; int newdev(); char ch; char *str; char *l; char line[MAXLINE]; /* current line */ struct stat statb; FILE *fp; int isdev; int found; int bad_entry=0; /* true if current entry does not exist or is a duplicate */ if (stat(exportfile, &statb) < 0) {#ifdef DEBUG (void) fprintf(stderr, "%s: stat failed", pgmname); perror("mountd: exportfile");#endif freeex(exports); exports = NULL; freeex(flatexports); flatexports = NULL; return; } if (exportstat.st_mtime == statb.st_mtime) { return; } exportstat = statb; if ((fp = fopen(exportfile, "r")) == NULL) { syslog(LOG_ERR, "fopen: %m"); freeex(exports); exports = NULL; freeex(flatexports); flatexports = NULL; return; } dupcache_inval(); /* invalidate the dup req cache */ freeex(exports); exports = NULL; freeex(flatexports); flatexports = NULL; eof = 0; l = line; *l = '\0'; while (!eof) { switch (*l) { case '\0': case '\n': /* * End of line, read next line and set state vars */ if (fgets(line, MAXLINE, fp) == NULL) { eof = 1; } else { bol = 1; opt = 0; l = line; } break; case ' ': case ' ': /* * If this is the continuation of a bad entry, skip the line */ if (bad_entry) { *l = '\0'; break; } /* * White space, skip to first non-white */ while (*l == ' ' || *l == ' ') { l++; } bol = 0; break; case '#': /* * Comment, skip to end of line. */ *l = '\0'; break; case '-': /* * option of the form: -option=value or -option */ if (bol) { syslog(LOG_ERR, "Cannot parse '%s'", l); *l = '\0'; break; } opt = 1; l++; break; default: /* * normal character: if col one get dir else name or opt */ str = l; while (*l != ' ' && *l != ' ' && *l != '\0' && *l != '\n') { l++; } ch = *l; *l = '\0'; if (bol) { /* * Logic for building export list: * The list is organized by dev horizontally, * all entries of the same dev hang off vertically. * The top dev entry is just the first one read. * * Try to find an exports list entry with the * same dev number. If not found, this entry * represents a new top entry. Connect its * devptr to the front of the exports list. * If a dev match was found, tack this entry on * to the "next" pointer of the top entry for this * dev. Always check if this is a duplicate entry. */#ifdef DEBUG_FULL (void) fprintf(stderr, "--- next /etc/exports entry to add is %s ---\n", str);#endif DEBUG_FULL bad_entry = 0; /* this is a new export entry */ if (stat(str, &statb) < 0) { syslog(LOG_ERR, "stat: %m, Cannot stat %s", str); bad_entry = 1; break; } for (ex = exports; ex != NULL; ex = ex->ex_devptr) if (ex->ex_dev == statb.st_dev) break; if (ex == NULL) { isdev = TRUE;#ifdef DEBUG_FULL (void) fprintf(stderr, "adding new export %s\n", str);#endif DEBUG_FULL newdev(str, statb.st_dev, statb.st_ino, statb.st_gennum); ex = exports; } else { found = FALSE; for (ex2=ex; ex2 != NULL; ex2 = ex2->ex_next) if (ex2->ex_ino == statb.st_ino) { syslog(LOG_ERR, "Duplicate directory entry for %s - duplicate ignored", str); found = TRUE; bad_entry = 1; break; } if (!found) { isdev = FALSE; /* initialize rootmap to nobody and flags to 0 */#ifdef DEBUG_FULL (void) fprintf(stderr, "adding new export %s\n", str);#endif DEBUG_FULL ex->ex_next = newex(str, ex->ex_next, statb.st_dev, statb.st_ino, statb.st_gennum, -2, 0); } else break; /* skip rest of entry */ } } else { if (opt) { opt = 0; if (isdev) setopt(str, ex); else setopt(str, ex->ex_next); } else { if (!isdev) {#ifdef DEBUG_FULL (void) fprintf(stderr, "adding new groups %s to %s\n", str, ex->ex_next->ex_name);#endif DEBUG_FULL ex->ex_next->ex_groups = newgroup(str, ex->ex_next->ex_groups); } else {#ifdef DEBUG_FULL (void) fprintf(stderr, "adding new groups %s to %s\n", str, ex->ex_name);#endif DEBUG_FULL ex->ex_groups = newgroup(str, ex->ex_groups); } } } *l = ch; bol = 0; break; } } (void) fclose(fp);#ifdef DEBUG (void) fprintf(stderr, "*** export list final results ***\n"); print_exports(exports);#endif DEBUG /* * Update the kernel's exportfsdata list so that it is in sync with * the exports file and the mountd's list. */ update_exportfsdata(); flatten_exports();#ifdef DEBUG_FULL (void) fprintf(stderr, "*** export list final results flattened ***\n"); print_exports(flatexports);#endif DEBUG_FULL return;}/* * Make exportfs calls necessary to update kernel's view of exports. */update_exportfsdata(){ struct exports *ex, *ex2, *k_ex=NULL, *k_ptr; struct exportfsdata kbuf; u_int cookie=0; /* * Build a list equivalent to kernel's list. */ for (;;) { if ((exportfs (EXPORTFS_READ, &cookie, &kbuf)) < 0) { if (errno == ENOENT) break; syslog(LOG_ERR, "exportfs READ: %m"); exit (1); } k_ex = newex(kbuf.e_path, k_ex, kbuf.e_fsid, kbuf.e_gnum, kbuf.e_gen, kbuf.e_rootmap, kbuf.e_flags); if (kbuf.e_more == 0) break; }#ifdef DEBUG_FULL (void) fprintf (stderr, "*** Kernel exportfsdata before changes ***\n"); print_exports(k_ex);#endif DEBUG_FULL /* * Loop through mountd's export list. Find matching entry in * local view of kernel's exportfsdata list. If one is not found, * add this export to kernel's list. If they are different, * update the kernel's data. Mark the k_ex entry that has * been looked at so that we know what hasn't been checked yet. */ for (ex=exports; ex!=NULL; ex=ex->ex_devptr) { for (ex2=ex; ex2!=NULL; ex2=ex2->ex_next) { /* find matching kernel entry */ for (k_ptr=k_ex; k_ptr!=NULL; k_ptr=k_ptr->ex_next) if ((strcmp(k_ptr->ex_name, ex2->ex_name))==0) break; /*
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?