diff options
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.patch | 650 |
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 + |