aboutsummaryrefslogtreecommitdiffstats
path: root/main/nfs-utils/0002-mountd-talk-to-kernel-using-file-descriptors-instead.patch
diff options
context:
space:
mode:
Diffstat (limited to 'main/nfs-utils/0002-mountd-talk-to-kernel-using-file-descriptors-instead.patch')
-rw-r--r--main/nfs-utils/0002-mountd-talk-to-kernel-using-file-descriptors-instead.patch650
1 files changed, 650 insertions, 0 deletions
diff --git a/main/nfs-utils/0002-mountd-talk-to-kernel-using-file-descriptors-instead.patch b/main/nfs-utils/0002-mountd-talk-to-kernel-using-file-descriptors-instead.patch
new file mode 100644
index 0000000000..1a50cf28b4
--- /dev/null
+++ b/main/nfs-utils/0002-mountd-talk-to-kernel-using-file-descriptors-instead.patch
@@ -0,0 +1,650 @@
+From 0b6eff3dc8fecff610264209d458ab9ca2344440 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
+Date: Thu, 2 Oct 2014 15:23:29 +0300
+Subject: [PATCH v2 2/5] mountd: talk to kernel using file descriptors instead
+ of FILE
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Timo Teräs <timo.teras@iki.fi>
+---
+ utils/mountd/cache.c | 343 +++++++++++++++++++++++++++------------------------
+ 1 file changed, 183 insertions(+), 160 deletions(-)
+
+diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
+index 663a52a..c23d384 100644
+--- a/utils/mountd/cache.c
++++ b/utils/mountd/cache.c
+@@ -61,15 +61,13 @@ enum nfsd_fsid {
+ * Record is terminated with newline.
+ *
+ */
+-static int cache_export_ent(char *domain, struct exportent *exp, char *p);
++static int cache_export_ent(char *buf, int buflen, char *domain, struct exportent *exp, char *path);
+
+ #define INITIAL_MANAGED_GROUPS 100
+
+-char *lbuf = NULL;
+-int lbuflen = 0;
+ extern int use_ipaddr;
+
+-static void auth_unix_ip(FILE *f)
++static void auth_unix_ip(int f)
+ {
+ /* requests are
+ * class IP-ADDR
+@@ -78,23 +76,26 @@ static void auth_unix_ip(FILE *f)
+ *
+ * "nfsd" IP-ADDR expiry domainname
+ */
+- char *cp;
+ char class[20];
+ char ipaddr[INET6_ADDRSTRLEN + 1];
+ char *client = NULL;
+ struct addrinfo *tmp = NULL;
+- if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+- return;
++ char buf[RPC_CHAN_BUF_SIZE], *bp;
++ int blen;
++
++ blen = read(f, buf, sizeof(buf));
++ if (blen <= 0 || buf[blen-1] != '\n') return;
++ buf[blen-1] = 0;
+
+- xlog(D_CALL, "auth_unix_ip: inbuf '%s'", lbuf);
++ xlog(D_CALL, "auth_unix_ip: inbuf '%s'", buf);
+
+- cp = lbuf;
++ bp = buf;
+
+- if (qword_get(&cp, class, 20) <= 0 ||
++ if (qword_get(&bp, class, 20) <= 0 ||
+ strcmp(class, "nfsd") != 0)
+ return;
+
+- if (qword_get(&cp, ipaddr, sizeof(ipaddr) - 1) <= 0)
++ if (qword_get(&bp, ipaddr, sizeof(ipaddr) - 1) <= 0)
+ return;
+
+ tmp = host_pton(ipaddr);
+@@ -113,16 +114,20 @@ static void auth_unix_ip(FILE *f)
+ freeaddrinfo(ai);
+ }
+ }
+- qword_print(f, "nfsd");
+- qword_print(f, ipaddr);
+- qword_printtimefrom(f, DEFAULT_TTL);
++ bp = buf; blen = sizeof(buf);
++ qword_add(&bp, &blen, "nfsd");
++ qword_add(&bp, &blen, ipaddr);
++ qword_adduint(&bp, &blen, time(0) + DEFAULT_TTL);
+ if (use_ipaddr) {
+ memmove(ipaddr + 1, ipaddr, strlen(ipaddr) + 1);
+ ipaddr[0] = '$';
+- qword_print(f, ipaddr);
++ qword_add(&bp, &blen, ipaddr);
+ } else if (client)
+- qword_print(f, *client?client:"DEFAULT");
+- qword_eol(f);
++ qword_add(&bp, &blen, *client?client:"DEFAULT");
++ qword_addeol(&bp, &blen);
++ if (blen <= 0 || write(f, buf, bp - buf) != bp - buf)
++ xlog(L_ERROR, "auth_unix_ip: error writing reply");
++
+ xlog(D_CALL, "auth_unix_ip: client %p '%s'", client, client?client: "DEFAULT");
+
+ free(client);
+@@ -130,7 +135,7 @@ static void auth_unix_ip(FILE *f)
+
+ }
+
+-static void auth_unix_gid(FILE *f)
++static void auth_unix_gid(int f)
+ {
+ /* Request are
+ * uid
+@@ -144,7 +149,8 @@ static void auth_unix_gid(FILE *f)
+ gid_t *more_groups;
+ int ngroups;
+ int rv, i;
+- char *cp;
++ char buf[RPC_CHAN_BUF_SIZE], *bp;
++ int blen;
+
+ if (groups_len == 0) {
+ groups = malloc(sizeof(gid_t) * INITIAL_MANAGED_GROUPS);
+@@ -156,11 +162,12 @@ static void auth_unix_gid(FILE *f)
+
+ ngroups = groups_len;
+
+- if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+- return;
++ blen = read(f, buf, sizeof(buf));
++ if (blen <= 0 || buf[blen-1] != '\n') return;
++ buf[blen-1] = 0;
+
+- cp = lbuf;
+- if (qword_get_uint(&cp, &uid) != 0)
++ bp = buf;
++ if (qword_get_uint(&bp, &uid) != 0)
+ return;
+
+ pw = getpwuid(uid);
+@@ -180,15 +187,19 @@ static void auth_unix_gid(FILE *f)
+ }
+ }
+ }
+- qword_printuint(f, uid);
+- qword_printtimefrom(f, DEFAULT_TTL);
++
++ bp = buf; blen = sizeof(buf);
++ qword_adduint(&bp, &blen, uid);
++ qword_adduint(&bp, &blen, time(0) + DEFAULT_TTL);
+ if (rv >= 0) {
+- qword_printuint(f, ngroups);
++ qword_adduint(&bp, &blen, ngroups);
+ for (i=0; i<ngroups; i++)
+- qword_printuint(f, groups[i]);
++ qword_adduint(&bp, &blen, groups[i]);
+ } else
+- qword_printuint(f, 0);
+- qword_eol(f);
++ qword_adduint(&bp, &blen, 0);
++ qword_addeol(&bp, &blen);
++ if (blen <= 0 || write(f, buf, bp - buf) != bp - buf)
++ xlog(L_ERROR, "auth_unix_gid: error writing reply");
+ }
+
+ #if USE_BLKID
+@@ -659,14 +670,13 @@ static struct addrinfo *lookup_client_addr(char *dom)
+ return ret;
+ }
+
+-static void nfsd_fh(FILE *f)
++static void nfsd_fh(int 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;
+@@ -678,24 +688,27 @@ static void nfsd_fh(FILE *f)
+ nfs_export *exp;
+ int i;
+ int dev_missing = 0;
++ char buf[RPC_CHAN_BUF_SIZE], *bp;
++ int blen;
+
+- if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+- return;
++ blen = read(f, buf, sizeof(buf));
++ if (blen <= 0 || buf[blen-1] != '\n') return;
++ buf[blen-1] = 0;
+
+- xlog(D_CALL, "nfsd_fh: inbuf '%s'", lbuf);
++ xlog(D_CALL, "nfsd_fh: inbuf '%s'", buf);
+
+- cp = lbuf;
++ bp = buf;
+
+- dom = malloc(strlen(cp));
++ dom = malloc(blen);
+ if (dom == NULL)
+ return;
+- if (qword_get(&cp, dom, strlen(cp)) <= 0)
++ if (qword_get(&bp, dom, blen) <= 0)
+ goto out;
+- if (qword_get_int(&cp, &fsidtype) != 0)
++ if (qword_get_int(&bp, &fsidtype) != 0)
+ goto out;
+ if (fsidtype < 0 || fsidtype > 7)
+ goto out; /* unknown type */
+- if ((fsidlen = qword_get(&cp, fsid, 32)) <= 0)
++ if ((fsidlen = qword_get(&bp, fsid, 32)) <= 0)
+ goto out;
+ if (parse_fsid(fsidtype, fsidlen, fsid, &parsed))
+ goto out;
+@@ -796,12 +809,13 @@ static void nfsd_fh(FILE *f)
+ }
+
+ if (found)
+- if (cache_export_ent(dom, found, found_path) < 0)
++ if (cache_export_ent(buf, sizeof(buf), dom, found, found_path) < 0)
+ found = 0;
+
+- qword_print(f, dom);
+- qword_printint(f, fsidtype);
+- qword_printhex(f, fsid, fsidlen);
++ bp = buf; blen = sizeof(buf);
++ qword_add(&bp, &blen, dom);
++ qword_addint(&bp, &blen, fsidtype);
++ qword_addhex(&bp, &blen, fsid, fsidlen);
+ /* The fsid -> path lookup can be quite expensive as it
+ * potentially stats and reads lots of devices, and some of those
+ * might have spun-down. The Answer is not likely to
+@@ -810,20 +824,21 @@ static void nfsd_fh(FILE *f)
+ * timeout. Maybe this should be configurable on the command
+ * line.
+ */
+- qword_printint(f, 0x7fffffff);
++ qword_addint(&bp, &blen, 0x7fffffff);
+ if (found)
+- qword_print(f, found_path);
+- qword_eol(f);
+- out:
++ qword_add(&bp, &blen, found_path);
++ qword_addeol(&bp, &blen);
++ if (blen <= 0 || write(f, buf, bp - buf) != bp - buf)
++ xlog(L_ERROR, "nfsd_fh: error writing reply");
++out:
+ if (found_path)
+ free(found_path);
+ freeaddrinfo(ai);
+ free(dom);
+ xlog(D_CALL, "nfsd_fh: found %p path %s", found, found ? found->e_path : NULL);
+- return;
+ }
+
+-static void write_fsloc(FILE *f, struct exportent *ep)
++static void write_fsloc(char **bp, int *blen, struct exportent *ep)
+ {
+ struct servers *servers;
+
+@@ -833,20 +848,20 @@ static void write_fsloc(FILE *f, struct exportent *ep)
+ servers = replicas_lookup(ep->e_fslocmethod, ep->e_fslocdata);
+ if (!servers)
+ return;
+- qword_print(f, "fsloc");
+- qword_printint(f, servers->h_num);
++ qword_add(bp, blen, "fsloc");
++ qword_addint(bp, blen, servers->h_num);
+ if (servers->h_num >= 0) {
+ int i;
+ for (i=0; i<servers->h_num; i++) {
+- qword_print(f, servers->h_mp[i]->h_host);
+- qword_print(f, servers->h_mp[i]->h_path);
++ qword_add(bp, blen, servers->h_mp[i]->h_host);
++ qword_add(bp, blen, servers->h_mp[i]->h_path);
+ }
+ }
+- qword_printint(f, servers->h_referral);
++ qword_addint(bp, blen, servers->h_referral);
+ release_replicas(servers);
+ }
+
+-static void write_secinfo(FILE *f, struct exportent *ep, int flag_mask)
++static void write_secinfo(char **bp, int *blen, struct exportent *ep, int flag_mask)
+ {
+ struct sec_entry *p;
+
+@@ -857,45 +872,52 @@ static void write_secinfo(FILE *f, struct exportent *ep, int flag_mask)
+ return;
+ }
+ fix_pseudoflavor_flags(ep);
+- qword_print(f, "secinfo");
+- qword_printint(f, p - ep->e_secinfo);
++ qword_add(bp, blen, "secinfo");
++ qword_addint(bp, blen, p - ep->e_secinfo);
+ for (p = ep->e_secinfo; p->flav; p++) {
+- qword_printint(f, p->flav->fnum);
+- qword_printint(f, p->flags & flag_mask);
++ qword_addint(bp, blen, p->flav->fnum);
++ qword_addint(bp, blen, p->flags & flag_mask);
+ }
+
+ }
+
+-static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *exp)
++static int dump_to_cache(int f, char *buf, int buflen, char *domain, char *path, struct exportent *exp)
+ {
+- qword_print(f, domain);
+- qword_print(f, path);
++ char *bp = buf;
++ int blen = buflen;
++ time_t now = time(0);
++
++ qword_add(&bp, &blen, domain);
++ qword_add(&bp, &blen, path);
+ if (exp) {
+ int different_fs = strcmp(path, exp->e_path) != 0;
+ int flag_mask = different_fs ? ~NFSEXP_FSID : ~0;
+
+- qword_printtimefrom(f, exp->e_ttl);
+- qword_printint(f, exp->e_flags & flag_mask);
+- qword_printint(f, exp->e_anonuid);
+- qword_printint(f, exp->e_anongid);
+- qword_printint(f, exp->e_fsid);
+- write_fsloc(f, exp);
+- write_secinfo(f, exp, flag_mask);
+- if (exp->e_uuid == NULL || different_fs) {
+- char u[16];
+- if (uuid_by_path(path, 0, 16, u)) {
+- qword_print(f, "uuid");
+- qword_printhex(f, u, 16);
+- }
+- } else {
+- char u[16];
+- get_uuid(exp->e_uuid, 16, u);
+- qword_print(f, "uuid");
+- qword_printhex(f, u, 16);
+- }
++ qword_adduint(&bp, &blen, now + exp->e_ttl);
++ qword_addint(&bp, &blen, exp->e_flags & flag_mask);
++ qword_addint(&bp, &blen, exp->e_anonuid);
++ qword_addint(&bp, &blen, exp->e_anongid);
++ qword_addint(&bp, &blen, exp->e_fsid);
++ write_fsloc(&bp, &blen, exp);
++ write_secinfo(&bp, &blen, exp, flag_mask);
++ if (exp->e_uuid == NULL || different_fs) {
++ char u[16];
++ if (uuid_by_path(path, 0, 16, u)) {
++ qword_add(&bp, &blen, "uuid");
++ qword_addhex(&bp, &blen, u, 16);
++ }
++ } else {
++ char u[16];
++ get_uuid(exp->e_uuid, 16, u);
++ qword_add(&bp, &blen, "uuid");
++ qword_addhex(&bp, &blen, u, 16);
++ }
+ } else
+- qword_printtimefrom(f, DEFAULT_TTL);
+- return qword_eol(f);
++ qword_adduint(&bp, &blen, now + DEFAULT_TTL);
++ qword_addeol(&bp, &blen);
++ if (blen <= 0) return -1;
++ if (write(f, buf, bp - buf) != bp - buf) return -1;
++ return 0;
+ }
+
+ static nfs_export *
+@@ -1245,27 +1267,27 @@ static struct exportent *lookup_junction(char *dom, const char *pathname,
+ return exp;
+ }
+
+-static void lookup_nonexport(FILE *f, char *dom, char *path,
++static void lookup_nonexport(int f, char *buf, int buflen, char *dom, char *path,
+ struct addrinfo *ai)
+ {
+ struct exportent *eep;
+
+ eep = lookup_junction(dom, path, ai);
+- dump_to_cache(f, dom, path, eep);
++ dump_to_cache(f, buf, buflen, dom, path, eep);
+ if (eep == NULL)
+ return;
+ exportent_release(eep);
+ free(eep);
+ }
+ #else /* !HAVE_NFS_PLUGIN_H */
+-static void lookup_nonexport(FILE *f, char *dom, char *path,
++static void lookup_nonexport(int f, char *buf, int buflen, char *dom, char *path,
+ struct addrinfo *UNUSED(ai))
+ {
+- dump_to_cache(f, dom, path, NULL);
++ dump_to_cache(f, buf, buflen, dom, path, NULL);
+ }
+ #endif /* !HAVE_NFS_PLUGIN_H */
+
+-static void nfsd_export(FILE *f)
++static void nfsd_export(int f)
+ {
+ /* requests are:
+ * domain path
+@@ -1273,26 +1295,28 @@ static void nfsd_export(FILE *f)
+ * domain path expiry flags anonuid anongid fsid
+ */
+
+- char *cp;
+ char *dom, *path;
+ nfs_export *found = NULL;
+ struct addrinfo *ai = NULL;
++ char buf[RPC_CHAN_BUF_SIZE], *bp;
++ int blen;
+
+- if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+- return;
++ blen = read(f, buf, sizeof(buf));
++ if (blen <= 0 || buf[blen-1] != '\n') return;
++ buf[blen-1] = 0;
+
+- xlog(D_CALL, "nfsd_export: inbuf '%s'", lbuf);
++ xlog(D_CALL, "nfsd_export: inbuf '%s'", buf);
+
+- cp = lbuf;
+- dom = malloc(strlen(cp));
+- path = malloc(strlen(cp));
++ bp = buf;
++ dom = malloc(blen);
++ path = malloc(blen);
+
+ if (!dom || !path)
+ goto out;
+
+- if (qword_get(&cp, dom, strlen(lbuf)) <= 0)
++ if (qword_get(&bp, dom, blen) <= 0)
+ goto out;
+- if (qword_get(&cp, path, strlen(lbuf)) <= 0)
++ if (qword_get(&bp, path, blen) <= 0)
+ goto out;
+
+ auth_reload();
+@@ -1306,14 +1330,14 @@ static void nfsd_export(FILE *f)
+ found = lookup_export(dom, path, ai);
+
+ if (found) {
+- if (dump_to_cache(f, dom, path, &found->m_export) < 0) {
++ if (dump_to_cache(f, buf, sizeof(buf), dom, path, &found->m_export) < 0) {
+ xlog(L_WARNING,
+ "Cannot export %s, possibly unsupported filesystem"
+ " or fsid= required", path);
+- dump_to_cache(f, dom, path, NULL);
++ dump_to_cache(f, buf, sizeof(buf), dom, path, NULL);
+ }
+ } else
+- lookup_nonexport(f, dom, path, ai);
++ lookup_nonexport(f, buf, sizeof(buf), dom, path, ai);
+
+ out:
+ xlog(D_CALL, "nfsd_export: found %p path %s", found, path ? path : NULL);
+@@ -1325,15 +1349,14 @@ static void nfsd_export(FILE *f)
+
+ struct {
+ char *cache_name;
+- void (*cache_handle)(FILE *f);
+- FILE *f;
+- char vbuf[RPC_CHAN_BUF_SIZE];
++ void (*cache_handle)(int f);
++ int f;
+ } cachelist[] = {
+- { "auth.unix.ip", auth_unix_ip, NULL, ""},
+- { "auth.unix.gid", auth_unix_gid, NULL, ""},
+- { "nfsd.export", nfsd_export, NULL, ""},
+- { "nfsd.fh", nfsd_fh, NULL, ""},
+- { NULL, NULL, NULL, ""}
++ { "auth.unix.ip", auth_unix_ip, -1 },
++ { "auth.unix.gid", auth_unix_gid, -1 },
++ { "nfsd.export", nfsd_export, -1 },
++ { "nfsd.fh", nfsd_fh, -1 },
++ { NULL, NULL, -1 }
+ };
+
+ extern int manage_gids;
+@@ -1350,11 +1373,7 @@ void cache_open(void)
+ if (!manage_gids && cachelist[i].cache_handle == auth_unix_gid)
+ continue;
+ sprintf(path, "/proc/net/rpc/%s/channel", cachelist[i].cache_name);
+- cachelist[i].f = fopen(path, "r+");
+- if (cachelist[i].f != NULL) {
+- setvbuf(cachelist[i].f, cachelist[i].vbuf, _IOLBF,
+- RPC_CHAN_BUF_SIZE);
+- }
++ cachelist[i].f = open(path, O_RDWR);
+ }
+ }
+
+@@ -1366,8 +1385,8 @@ void cache_set_fds(fd_set *fdset)
+ {
+ int i;
+ for (i=0; cachelist[i].cache_name; i++) {
+- if (cachelist[i].f)
+- FD_SET(fileno(cachelist[i].f), fdset);
++ if (cachelist[i].f >= 0)
++ FD_SET(cachelist[i].f, fdset);
+ }
+ }
+
+@@ -1380,11 +1399,11 @@ int cache_process_req(fd_set *readfds)
+ int i;
+ int cnt = 0;
+ for (i=0; cachelist[i].cache_name; i++) {
+- if (cachelist[i].f != NULL &&
+- FD_ISSET(fileno(cachelist[i].f), readfds)) {
++ if (cachelist[i].f >= 0 &&
++ FD_ISSET(cachelist[i].f, readfds)) {
+ cnt++;
+ cachelist[i].cache_handle(cachelist[i].f);
+- FD_CLR(fileno(cachelist[i].f), readfds);
++ FD_CLR(cachelist[i].f, readfds);
+ }
+ }
+ return cnt;
+@@ -1397,14 +1416,14 @@ int cache_process_req(fd_set *readfds)
+ * % echo $domain $path $[now+DEFAULT_TTL] $options $anonuid $anongid $fsid > /proc/net/rpc/nfsd.export/channel
+ */
+
+-static int cache_export_ent(char *domain, struct exportent *exp, char *path)
++static int cache_export_ent(char *buf, int buflen, char *domain, struct exportent *exp, char *path)
+ {
+- int err;
+- FILE *f = fopen("/proc/net/rpc/nfsd.export/channel", "w");
+- if (!f)
+- return -1;
++ int f, err;
++
++ f = open("/proc/net/rpc/nfsd.export/channel", O_WRONLY);
++ if (f < 0) return -1;
+
+- err = dump_to_cache(f, domain, exp->e_path, exp);
++ err = dump_to_cache(f, buf, buflen, domain, exp->e_path, exp);
+ if (err) {
+ xlog(L_WARNING,
+ "Cannot export %s, possibly unsupported filesystem or"
+@@ -1445,13 +1464,13 @@ static int cache_export_ent(char *domain, struct exportent *exp, char *path)
+ continue;
+ dev = stb.st_dev;
+ path[l] = 0;
+- dump_to_cache(f, domain, path, exp);
++ dump_to_cache(f, buf, buflen, domain, path, exp);
+ path[l] = c;
+ }
+ break;
+ }
+
+- fclose(f);
++ close(f);
+ return err;
+ }
+
+@@ -1462,27 +1481,25 @@ static int cache_export_ent(char *domain, struct exportent *exp, char *path)
+ */
+ int cache_export(nfs_export *exp, char *path)
+ {
+- char buf[INET6_ADDRSTRLEN];
+- int err;
+- FILE *f;
++ char ip[INET6_ADDRSTRLEN];
++ char buf[RPC_CHAN_BUF_SIZE], *bp;
++ int blen, f;
+
+- f = fopen("/proc/net/rpc/auth.unix.ip/channel", "w");
+- if (!f)
++ f = open("/proc/net/rpc/auth.unix.ip/channel", O_WRONLY);
++ if (f < 0)
+ return -1;
+
+-
+- qword_print(f, "nfsd");
+- qword_print(f,
+- host_ntop(get_addrlist(exp->m_client, 0), buf, sizeof(buf)));
+- qword_printtimefrom(f, exp->m_export.e_ttl);
+- qword_print(f, exp->m_client->m_hostname);
+- err = qword_eol(f);
+-
+- fclose(f);
+-
+- err = cache_export_ent(exp->m_client->m_hostname, &exp->m_export, path)
+- || err;
+- return err;
++ bp = buf, blen = sizeof(buf);
++ qword_add(&bp, &blen, "nfsd");
++ qword_add(&bp, &blen, host_ntop(get_addrlist(exp->m_client, 0), ip, sizeof(ip)));
++ qword_adduint(&bp, &blen, time(0) + exp->m_export.e_ttl);
++ qword_add(&bp, &blen, exp->m_client->m_hostname);
++ qword_addeol(&bp, &blen);
++ if (blen <= 0 || write(f, buf, bp - buf) != bp - buf) blen = -1;
++ close(f);
++ if (blen < 0) return -1;
++
++ return cache_export_ent(buf, sizeof(buf), exp->m_client->m_hostname, &exp->m_export, path);
+ }
+
+ /**
+@@ -1501,27 +1518,33 @@ int cache_export(nfs_export *exp, char *path)
+ struct nfs_fh_len *
+ cache_get_filehandle(nfs_export *exp, int len, char *p)
+ {
+- FILE *f = fopen("/proc/fs/nfsd/filehandle", "r+");
+- char buf[200];
+- char *bp = buf;
+- int failed;
+ static struct nfs_fh_len fh;
++ char buf[RPC_CHAN_BUF_SIZE], *bp;
++ int blen, f;
++
++ f = open("/proc/fs/nfsd/filehandle", O_RDWR);
++ if (f < 0) {
++ f = open("/proc/fs/nfs/filehandle", O_RDWR);
++ if (f < 0) return NULL;
++ }
+
+- if (!f)
+- f = fopen("/proc/fs/nfs/filehandle", "r+");
+- if (!f)
++ bp = buf, blen = sizeof(buf);
++ qword_add(&bp, &blen, exp->m_client->m_hostname);
++ qword_add(&bp, &blen, p);
++ qword_addint(&bp, &blen, len);
++ qword_addeol(&bp, &blen);
++ if (blen <= 0 || write(f, buf, bp - buf) != bp - buf) {
++ close(f);
+ return NULL;
++ }
++ bp = buf;
++ blen = read(f, buf, sizeof(buf));
++ close(f);
+
+- qword_print(f, exp->m_client->m_hostname);
+- qword_print(f, p);
+- qword_printint(f, len);
+- failed = qword_eol(f);
+-
+- if (!failed)
+- failed = (fgets(buf, sizeof(buf), f) == NULL);
+- fclose(f);
+- if (failed)
++ if (blen <= 0 || buf[blen-1] != '\n')
+ return NULL;
++ buf[blen-1] = 0;
++
+ memset(fh.fh_handle, 0, sizeof(fh.fh_handle));
+ fh.fh_size = qword_get(&bp, (char *)fh.fh_handle, NFS3_FHSIZE);
+ return &fh;
+--
+2.1.2
+