diff --git a/usr.sbin/mountd/mountd.c.orig b/usr.sbin/mountd/mountd.c --- a/usr.sbin/mountd/mountd.c.orig +++ b/usr.sbin/mountd/mountd.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include @@ -71,8 +72,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -234,7 +237,7 @@ static void free_grp(struct grouplist *); static void free_host(struct hostlist *); static void free_v4rootexp(void); -static void get_exportlist_one(int); +static void get_exportlist_one(int, DB *); static void get_exportlist(int); static void insert_exports(struct exportlist *, struct exportlisthead *); static void free_exports(struct exportlisthead *); @@ -307,6 +310,9 @@ static struct exportlist *v4root_ep = NULL; static int has_publicfh = 0; static int has_set_publicfh = 0; +static int n_scanned = 0; +static int n_enabled = 0; +static int n_disabled = 0; static struct pidfh *pfh = NULL; /* Bits for opt_flags above */ @@ -1546,12 +1552,72 @@ static char *line; static size_t linesize; static FILE *exp_file; +static char *cur_file = NULL; +static int cur_line = -1; +static char *dat_path = NULL; +static char *dat_rest = NULL; +static DBT dat_k, dat_d; +static unsigned int dat_p = 0; /* + * Get data from DB and handle multiple share + * options per path (separated by NUL characters) + */ +static int +get_data(DB *dbp) +{ + int len, rc; + char *buf; + + if (dat_path != NULL && dat_rest != NULL && dat_p < dat_d.size) { + buf = (char *)dat_d.data; + while (dat_p < dat_d.size && buf[dat_p] == '\0') + ++dat_p; + + len = strnlen(buf + dat_p, dat_d.size - dat_p); + if (len > 0) { + free(dat_rest); + dat_rest = strndup(buf + dat_p, len); + dat_p += len; + return (1); + } + } + + if (dat_path) { + free(dat_path); + dat_path = NULL; + } + if (dat_rest) { + free(dat_rest); + dat_rest = NULL; + } + + memset(&dat_k, 0, sizeof(dat_k)); + memset(&dat_d, 0, sizeof(dat_d)); + + rc = dbp->seq(dbp, &dat_k, &dat_d, R_NEXT); + switch (rc) { + case 0: + dat_path = strndup(dat_k.data, dat_k.size); + dat_rest = strndup(dat_d.data, dat_d.size); + dat_p = strlen(dat_rest); + return (1); + + case 1: + return (0); + + default: + syslog(LOG_ERR, "Error reading from sharedb: %s", + strerror(errno)); + return (-1); + } +} + +/* * Get the export list from one, currently open file */ static void -get_exportlist_one(int passno) +get_exportlist_one(int passno, DB *db) { struct exportlist *ep; struct grouplist *grp, *tgrp, *savgrp; @@ -1569,14 +1635,7 @@ anon.cr_groups = NULL; dirhead = (struct dirlist *)NULL; unvis_dir[0] = '\0'; - while (get_line()) { - if (debug) - warnx("got line %s", line); - cp = line; - nextfield(&cp, &endcp); - if (*cp == '#') - goto nextline; - + while ((db == NULL ? get_line() : get_data(db)) > 0) { /* * Set defaults. */ @@ -1591,27 +1650,68 @@ ep = (struct exportlist *)NULL; dirp = NULL; - /* - * Handle the V4 root dir. - */ - if (*cp == 'V' && *(cp + 1) == '4' && *(cp + 2) == ':') { + if (db != NULL) { + cp = dat_path; + len = strlen(dat_path); + endcp = dat_rest; + + ++n_scanned; + if (strncmp(dat_path, "V4:", 3) == 0) { + if (v4root_phase > 0) { + syslog(LOG_ERR, + "%s: V4:duplicate entry, ignored", + cur_file); + goto nextline; + } + v4root_phase = 1; + + if (dat_path[3]) { + cp += 3; + len -= 3; + endcp = dat_rest; + } else { + cp = dat_rest; + nextfield(&cp, &endcp); + len = endcp-cp; + } + } + } else { + if (debug) + warnx("%s#%d: got line: %s", cur_file, cur_line, + line); + cp = line; + nextfield(&cp, &endcp); + if (*cp == '#') + goto nextline; + + ++n_scanned; /* - * V4: just indicates that it is the v4 root point, - * so skip over that and set v4root_phase. + * Handle the V4 root dir. */ - if (v4root_phase > 0) { - syslog(LOG_ERR, "V4:duplicate line, ignored"); - goto nextline; + if (*cp == 'V' && *(cp + 1) == '4' && + *(cp + 2) == ':') { + /* + * V4: just indicates that it is the v4 root + * point, so skip over that and set + * v4root_phase. + */ + if (v4root_phase > 0) { + syslog(LOG_ERR, + "%s#%d: V4:duplicate line, ignored", + cur_file, cur_line); + goto nextline; + } + v4root_phase = 1; + cp += 3; + nextfield(&cp, &endcp); } - v4root_phase = 1; - cp += 3; - nextfield(&cp, &endcp); + + len = endcp-cp; } /* * Create new exports list entry */ - len = endcp-cp; tgrp = grp = get_grp(); while (len > 0) { if (len > MNTNAMLEN) { @@ -1633,8 +1733,8 @@ goto nextline; } } else if (*cp == '/') { - savedc = *endcp; - *endcp = '\0'; + savedc = cp[len]; + cp[len] = '\0'; unvis_len = strnunvis(unvis_dir, sizeof(unvis_dir), cp); if (unvis_len <= 0) { @@ -1728,7 +1828,7 @@ } goto nextline; } - *endcp = savedc; + cp[len] = savedc; } else { savedc = *endcp; *endcp = '\0'; @@ -2124,6 +2224,9 @@ read_exportfile(int passno) { int done, i; + char dbpath[MAXPATHLEN]; + DB *sdb; + struct stat sd, sf; /* * Read in the exports file and build the list, calling @@ -2131,13 +2234,43 @@ */ done = 0; for (i = 0; exnames[i] != NULL; i++) { + n_scanned = 0; + n_enabled = 0; + n_disabled = 0; + + snprintf(dbpath, sizeof(dbpath), "%s.db", exnames[i]); + if (stat(dbpath, &sd) == 0 && stat(exnames[i], &sf) == 0 && + timespeccmp(&sd.st_mtim, &sf.st_mtim, <)) + syslog(LOG_WARNING, + "Warning: %s (unused) is newer than %s", + exnames[i], dbpath); + + sdb = dbopen(dbpath, O_RDONLY | O_SHLOCK, 0, DB_BTREE, NULL); + if (sdb != NULL) { + if (debug) + warnx("reading exports from DB %s", dbpath); + cur_file = dbpath; + cur_line = -1; + get_exportlist_one(passno, sdb); + sdb->close(sdb); + done++; + syslog(passno ? LOG_INFO : LOG_NOTICE, + "%s: scanned %d, enabled %d, disabled %d", + dbpath, n_scanned, n_enabled, n_disabled); + continue; + } + if (errno != ENOENT) + syslog(LOG_ERR, "%s: opening DB for reading: %s", + dbpath, strerror(errno)); if (debug) warnx("reading exports from %s", exnames[i]); if ((exp_file = fopen(exnames[i], "r")) == NULL) { syslog(LOG_WARNING, "can't open %s", exnames[i]); continue; } - get_exportlist_one(passno); + cur_file = exnames[i]; + cur_line = 0; + get_exportlist_one(passno, NULL); fclose(exp_file); done++; } @@ -2430,6 +2563,7 @@ "can't delete exports for %s: %m %s", fsp->f_mntonname, errmsg); } + ++n_disabled; } /* @@ -2469,11 +2603,14 @@ struct grouplist *tgrp; if (!(opt_flags & OP_QUIET)) { - if (reason != NULL) - syslog(LOG_ERR, "bad exports list line '%s': %s", line, - reason); + if (cur_line >= 0) + syslog(LOG_ERR, "%s#%d: bad exports list line '%s'%s%s", + cur_file, cur_line, line, + reason ? ": " : "", reason ? reason : ""); else - syslog(LOG_ERR, "bad exports list line '%s'", line); + syslog(LOG_ERR, "%s: %s: bad exports data '%s'%s%s", + cur_file, dat_path, dat_rest, + reason ? ": " : "", reason ? reason : ""); } if (ep && (ep->ex_flag & EX_LINKED) == 0) free_exp(ep); @@ -3323,6 +3460,7 @@ if (ai == NULL) done = TRUE; } + ++n_enabled; if (cp) *cp = savedc; error_exit: @@ -3524,6 +3662,7 @@ do { if ((p = fgetln(exp_file, &len)) == NULL) return (0); + cur_line++; cp = p + len - 1; cont_line = 0; while (cp >= p && @@ -3547,6 +3686,7 @@ totlen += len; line[totlen] = '\0'; } while (totlen == 0 || cont_line); + return (1); }