first = 1;
}
+static void init_exportent (struct exportent *ee, int fromkernel)
+{
+ ee->e_flags = EXPORT_DEFAULT_FLAGS;
+ /* some kernels assume the default is sync rather than
+ * async. More recent kernels always report one or other,
+ * but this test makes sure we assume same as kernel
+ * Ditto for wgather
+ */
+ if (fromkernel) {
+ ee->e_flags &= ~NFSEXP_ASYNC;
+ ee->e_flags &= ~NFSEXP_GATHERED_WRITES;
+ }
+ ee->e_anonuid = 65534;
+ ee->e_anongid = 65534;
+ ee->e_squids = NULL;
+ ee->e_sqgids = NULL;
+ ee->e_mountpoint = NULL;
+ ee->e_fslocmethod = FSLOC_NONE;
+ ee->e_fslocdata = NULL;
+ ee->e_secinfo[0].flav = NULL;
+ ee->e_nsquids = 0;
+ ee->e_nsqgids = 0;
+ ee->e_uuid = NULL;
+ ee->e_ttl = DEFAULT_TTL;
+}
+
struct exportent *
getexportent(int fromkernel, int fromexports)
{
has_default_opts = 0;
has_default_subtree_opts = 0;
- def_ee.e_flags = EXPORT_DEFAULT_FLAGS;
- /* some kernels assume the default is sync rather than
- * async. More recent kernels always report one or other,
- * but this test makes sure we assume same as kernel
- * Ditto for wgather
- */
- if (fromkernel) {
- def_ee.e_flags &= ~NFSEXP_ASYNC;
- def_ee.e_flags &= ~NFSEXP_GATHERED_WRITES;
- }
- def_ee.e_anonuid = 65534;
- def_ee.e_anongid = 65534;
- def_ee.e_squids = NULL;
- def_ee.e_sqgids = NULL;
- def_ee.e_mountpoint = NULL;
- def_ee.e_fslocmethod = FSLOC_NONE;
- def_ee.e_fslocdata = NULL;
- def_ee.e_secinfo[0].flav = NULL;
- def_ee.e_nsquids = 0;
- def_ee.e_nsqgids = 0;
+ init_exportent(&def_ee, fromkernel);
ok = getpath(def_ee.e_path, sizeof(def_ee.e_path));
if (ok <= 0)
return NULL;
- strncpy (def_ee.m_path, def_ee.e_path, sizeof (def_ee.m_path) - 1);
- def_ee.m_path [sizeof (def_ee.m_path) - 1] = '\0';
ok = getexport(exp, sizeof(exp));
}
if (ok < 0) {
return NULL;
}
first = 0;
-
- /* Check for default options */
- if (exp[0] == '-') {
+
+ /*
+ * Check for default options. The kernel will never have default
+ * options in /proc/fs/nfs/exports, however due to the initial '-' in
+ * the -test-client- string from the test export we have to check that
+ * we're not reading from the kernel.
+ */
+ if (exp[0] == '-' && !fromkernel) {
if (parseopts(exp + 1, &def_ee, 0, &has_default_subtree_opts) < 0)
return NULL;
rpath[sizeof (rpath) - 1] = '\0';
strncpy(ee.e_path, rpath, sizeof (ee.e_path) - 1);
ee.e_path[sizeof (ee.e_path) - 1] = '\0';
- strncpy (ee.m_path, ee.e_path, sizeof (ee.m_path) - 1);
- ee.m_path [sizeof (ee.m_path) - 1] = '\0';
}
return ⅇ
dst->e_mountpoint = strdup(src->e_mountpoint);
if (src->e_fslocdata)
dst->e_fslocdata = strdup(src->e_fslocdata);
+ if (src->e_uuid)
+ dst->e_uuid = strdup(src->e_uuid);
dst->e_hostname = NULL;
}
{
static struct exportent ee;
- ee.e_flags = EXPORT_DEFAULT_FLAGS;
- ee.e_anonuid = 65534;
- ee.e_anongid = 65534;
- ee.e_squids = NULL;
- ee.e_sqgids = NULL;
- ee.e_mountpoint = NULL;
- ee.e_fslocmethod = FSLOC_NONE;
- ee.e_fslocdata = NULL;
- ee.e_secinfo[0].flav = NULL;
- ee.e_nsquids = 0;
- ee.e_nsqgids = 0;
- ee.e_uuid = NULL;
+ init_exportent(&ee, 0);
xfree(ee.e_hostname);
ee.e_hostname = xstrdup(hname);
}
strncpy(ee.e_path, path, sizeof (ee.e_path));
ee.e_path[sizeof (ee.e_path) - 1] = '\0';
- strncpy (ee.m_path, ee.e_path, sizeof (ee.m_path) - 1);
- ee.m_path [sizeof (ee.m_path) - 1] = '\0';
if (parseopts(options, &ee, 0, NULL) < 0)
return NULL;
return ⅇ
* do nothing if it's already there. Returns the index of flavor
* in the resulting array in any case.
*/
-static int secinfo_addflavor(struct flav_info *flav, struct exportent *ep)
+int secinfo_addflavor(struct flav_info *flav, struct exportent *ep)
{
struct sec_entry *p;
}
}
-/* options that can vary per flavor: */
-#define NFSEXP_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
- | NFSEXP_ALLSQUASH)
+/*
+ * For those flags which are not allowed to vary by pseudoflavor,
+ * ensure that the export flags agree with the flags on each
+ * pseudoflavor:
+ */
+static void fix_pseudoflavor_flags(struct exportent *ep)
+{
+ struct export_features *ef;
+ struct sec_entry *p;
+
+ ef = get_export_features();
+ for (p = ep->e_secinfo; p->flav; p++)
+ p->flags |= ep->e_flags & ~ef->secinfo_flags;
+}
/*
* Parse option string pointed to by cp and set mount options accordingly.
static int
parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr)
{
- struct sec_entry *p;
int had_subtree_opt = 0;
char *flname = efname?efname:"command line";
int flline = efp?efp->x_line:0;
else if (strcmp(opt, "rw") == 0)
clearflags(NFSEXP_READONLY, active, ep);
else if (!strcmp(opt, "secure"))
- ep->e_flags &= ~NFSEXP_INSECURE_PORT;
+ clearflags(NFSEXP_INSECURE_PORT, active, ep);
else if (!strcmp(opt, "insecure"))
- ep->e_flags |= NFSEXP_INSECURE_PORT;
+ setflags(NFSEXP_INSECURE_PORT, active, ep);
else if (!strcmp(opt, "sync"))
- ep->e_flags &= ~NFSEXP_ASYNC;
+ clearflags(NFSEXP_ASYNC, active, ep);
else if (!strcmp(opt, "async"))
- ep->e_flags |= NFSEXP_ASYNC;
+ setflags(NFSEXP_ASYNC, active, ep);
else if (!strcmp(opt, "nohide"))
- ep->e_flags |= NFSEXP_NOHIDE;
+ setflags(NFSEXP_NOHIDE, active, ep);
else if (!strcmp(opt, "hide"))
- ep->e_flags &= ~NFSEXP_NOHIDE;
+ clearflags(NFSEXP_NOHIDE, active, ep);
else if (!strcmp(opt, "crossmnt"))
- ep->e_flags |= NFSEXP_CROSSMOUNT;
+ setflags(NFSEXP_CROSSMOUNT, active, ep);
else if (!strcmp(opt, "nocrossmnt"))
- ep->e_flags &= ~NFSEXP_CROSSMOUNT;
+ clearflags(NFSEXP_CROSSMOUNT, active, ep);
else if (!strcmp(opt, "wdelay"))
- ep->e_flags |= NFSEXP_GATHERED_WRITES;
+ setflags(NFSEXP_GATHERED_WRITES, active, ep);
else if (!strcmp(opt, "no_wdelay"))
- ep->e_flags &= ~NFSEXP_GATHERED_WRITES;
+ clearflags(NFSEXP_GATHERED_WRITES, active, ep);
else if (strcmp(opt, "root_squash") == 0)
setflags(NFSEXP_ROOTSQUASH, active, ep);
else if (!strcmp(opt, "no_root_squash"))
clearflags(NFSEXP_ALLSQUASH, active, ep);
else if (strcmp(opt, "subtree_check") == 0) {
had_subtree_opt = 1;
- ep->e_flags &= ~NFSEXP_NOSUBTREECHECK;
+ clearflags(NFSEXP_NOSUBTREECHECK, active, ep);
} else if (strcmp(opt, "no_subtree_check") == 0) {
had_subtree_opt = 1;
- ep->e_flags |= NFSEXP_NOSUBTREECHECK;
+ setflags(NFSEXP_NOSUBTREECHECK, active, ep);
} else if (strcmp(opt, "auth_nlm") == 0)
- ep->e_flags &= ~NFSEXP_NOAUTHNLM;
+ clearflags(NFSEXP_NOAUTHNLM, active, ep);
else if (strcmp(opt, "no_auth_nlm") == 0)
- ep->e_flags |= NFSEXP_NOAUTHNLM;
+ setflags(NFSEXP_NOAUTHNLM, active, ep);
else if (strcmp(opt, "secure_locks") == 0)
- ep->e_flags &= ~NFSEXP_NOAUTHNLM;
+ clearflags(NFSEXP_NOAUTHNLM, active, ep);
else if (strcmp(opt, "insecure_locks") == 0)
- ep->e_flags |= NFSEXP_NOAUTHNLM;
+ setflags(NFSEXP_NOAUTHNLM, active, ep);
else if (strcmp(opt, "acl") == 0)
- ep->e_flags &= ~NFSEXP_NOACL;
+ clearflags(NFSEXP_NOACL, active, ep);
else if (strcmp(opt, "no_acl") == 0)
- ep->e_flags |= NFSEXP_NOACL;
+ setflags(NFSEXP_NOACL, active, ep);
else if (strncmp(opt, "anonuid=", 8) == 0) {
char *oe;
ep->e_anonuid = strtol(opt+8, &oe, 10);
char *oe;
if (strcmp(opt+5, "root") == 0) {
ep->e_fsid = 0;
- ep->e_flags |= NFSEXP_FSID;
+ setflags(NFSEXP_FSID, active, ep);
} else {
ep->e_fsid = strtoul(opt+5, &oe, 0);
if (opt[5]!='\0' && *oe == '\0')
- ep->e_flags |= NFSEXP_FSID;
+ setflags(NFSEXP_FSID, active, ep);
else if (valid_uuid(opt+5))
- ep->e_uuid = strdup(opt+7);
+ ep->e_uuid = strdup(opt+5);
else {
xlog(L_ERROR, "%s: %d: bad fsid \"%s\"\n",
flname, flline, opt);
} else {
xlog(L_ERROR, "%s:%d: unknown keyword \"%s\"\n",
flname, flline, opt);
- ep->e_flags |= NFSEXP_ALLSQUASH | NFSEXP_READONLY;
+ setflags(NFSEXP_ALLSQUASH | NFSEXP_READONLY, active, ep);
goto bad_option;
}
free(opt);
cp++;
}
- for (p = ep->e_secinfo; p->flav; p++)
- p->flags |= ep->e_flags & ~NFSEXP_SECINFO_FLAGS;
+ fix_pseudoflavor_flags(ep);
ep->e_squids = squids;
ep->e_sqgids = sqgids;
ep->e_nsquids = nsquids;
xlog(L_ERROR, "%s:%d: syntax error: %s",
efname, efp?efp->x_line:0, msg);
}
-
+struct export_features *get_export_features(void)
+{
+ static char *path = "/proc/fs/nfsd/export_features";
+ static struct export_features ef;
+ static int cached = 0;
+ char buf[50];
+ int c;
+ int fd;
+
+ if (cached)
+ return &ef;
+
+ ef.flags = NFSEXP_OLDFLAGS;
+ ef.secinfo_flags = NFSEXP_OLD_SECINFO_FLAGS;
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ goto good;
+ c = read(fd, buf, 50);
+ close(fd);
+ if (c == -1)
+ goto err;
+ c = sscanf(buf, "%x %x", &ef.flags, &ef.secinfo_flags);
+ if (c != 2)
+ goto err;
+good:
+ cached = 1;
+ return &ef;
+err:
+ xlog(L_WARNING, "unexpected error reading %s", path);
+ return &ef;
+}