+ return 0;
+}
+
+static bool match_fsid(struct parsed_fsid *parsed, nfs_export *exp, char *path)
+{
+ struct stat stb;
+ int type;
+ char u[16];
+
+ if (stat(path, &stb) != 0)
+ return false;
+ if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode))
+ return false;
+
+ switch (parsed->fsidtype) {
+ case FSID_DEV:
+ case FSID_MAJOR_MINOR:
+ case FSID_ENCODE_DEV:
+ if (stb.st_ino != parsed->inode)
+ return false;
+ if (parsed->major != major(stb.st_dev) ||
+ parsed->minor != minor(stb.st_dev))
+ return false;
+ return true;
+ case FSID_NUM:
+ if (((exp->m_export.e_flags & NFSEXP_FSID) == 0 ||
+ exp->m_export.e_fsid != parsed->fsidnum))
+ return false;
+ return true;
+ case FSID_UUID4_INUM:
+ case FSID_UUID16_INUM:
+ if (stb.st_ino != parsed->inode)
+ return false;
+ goto check_uuid;
+ case FSID_UUID8:
+ case FSID_UUID16:
+ if (!is_mountpoint(path))
+ return false;
+ check_uuid:
+ if (exp->m_export.e_uuid)
+ get_uuid(exp->m_export.e_uuid, parsed->uuidlen, u);
+ else
+ for (type = 0;
+ uuid_by_path(path, type, parsed->uuidlen, u);
+ type++)
+ if (memcmp(u, parsed->fhuuid, parsed->uuidlen) == 0)
+ return true;
+
+ if (memcmp(u, parsed->fhuuid, parsed->uuidlen) != 0)
+ return false;
+ return true;
+ }
+ /* Well, unreachable, actually: */
+ return false;
+}
+
+static void nfsd_fh(FILE *f)
+{
+ /* request are:
+ * domain fsidtype fsid
+ * interpret fsid, find export point and options, and write:
+ * domain fsidtype fsid expiry path
+ */
+ char *cp;
+ char *dom;
+ int fsidtype;
+ int fsidlen;
+ char fsid[32];
+ struct parsed_fsid parsed;
+ struct exportent *found = NULL;
+ struct addrinfo *ai = NULL;
+ char *found_path = NULL;
+ nfs_export *exp;
+ int i;
+ int dev_missing = 0;
+
+ if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+ return;
+
+ xlog(D_CALL, "nfsd_fh: inbuf '%s'", lbuf);
+
+ cp = lbuf;
+
+ dom = malloc(strlen(cp));
+ if (dom == NULL)
+ return;
+ if (qword_get(&cp, dom, strlen(cp)) <= 0)
+ goto out;
+ if (qword_get_int(&cp, &fsidtype) != 0)
+ goto out;
+ if (fsidtype < 0 || fsidtype > 7)
+ goto out; /* unknown type */
+ if ((fsidlen = qword_get(&cp, fsid, 32)) <= 0)
+ goto out;
+ if (parse_fsid(fsidtype, fsidlen, fsid, &parsed))
+ goto out;