From f1f22dbf6222c4899b45d9c83ccf1b6314464869 Mon Sep 17 00:00:00 2001 From: Ritesh Raj Sarraf Date: Mon, 30 Jun 2014 13:45:52 +0530 Subject: [PATCH] Imported Upstream version 1.9.4 --- COPYING | 9 +- Makefile.am | 2 +- README | 10 +- aros/aros_compat.h | 17 + configure.ac | 4 +- doc/Makefile.am | 9 + doc/nfs-ls.1 | 120 +++++ doc/nfs-ls.1.xml | 126 +++++ examples/Makefile.am | 19 +- examples/nfsclient-bcast.c | 2 +- examples/nfsclient-raw.c | 12 +- examples/portmap-client.c | 493 ++++++++++++++++++ include/Makefile.am | 6 +- include/libnfs-private.h | 21 +- include/nfsc/libnfs-raw.h | 182 ++++++- include/nfsc/libnfs.h | 16 +- include/slist.h | 8 +- lib/Makefile.am | 4 +- lib/init.c | 59 ++- lib/libnfs-sync.c | 118 +++-- lib/libnfs-win32.def | 22 +- lib/libnfs.c | 969 +++++++++++++++++++++-------------- lib/pdu.c | 65 ++- lib/socket.c | 130 +++-- mount/Makefile.am | 8 +- mount/libnfs-raw-mount.c | 29 ++ mount/libnfs-raw-mount.h | 32 +- mount/mount.x | 29 +- nfs/Makefile.am | 6 +- nfs/libnfs-raw-nfs.c | 50 +- nfs/libnfs-raw-nfs.h | 43 +- nfs/nfs.x | 48 +- nlm/Makefile.am | 6 +- nlm/libnfs-raw-nlm.c | 29 ++ nlm/libnfs-raw-nlm.h | 40 +- nlm/nlm.x | 39 +- nsm/Makefile.am | 6 +- nsm/libnfs-raw-nsm.c | 30 ++ nsm/libnfs-raw-nsm.h | 29 ++ nsm/nsm.x | 34 +- packaging/RPM/libnfs.spec.in | 16 +- portmap/Makefile.am | 6 +- portmap/libnfs-raw-portmap.c | 181 ++++++- portmap/libnfs-raw-portmap.h | 277 +++++++--- portmap/portmap.c | 290 +++++++++-- portmap/portmap.x | 131 ++++- rquota/Makefile.am | 8 +- rquota/libnfs-raw-rquota.c | 29 ++ rquota/libnfs-raw-rquota.h | 32 +- rquota/rquota.x | 29 +- utils/Makefile.am | 9 + {examples => utils}/nfs-ls.c | 39 +- win32/win32_errnowrapper.h | 21 + 53 files changed, 3169 insertions(+), 780 deletions(-) create mode 100644 doc/Makefile.am create mode 100644 doc/nfs-ls.1 create mode 100644 doc/nfs-ls.1.xml create mode 100644 examples/portmap-client.c create mode 100644 utils/Makefile.am rename {examples => utils}/nfs-ls.c (87%) diff --git a/COPYING b/COPYING index 306c29d..17a553e 100644 --- a/COPYING +++ b/COPYING @@ -1,13 +1,18 @@ Libnfs components fall under two separate licences -The lib and include directories -=============================== +The library sources and include directories +=========================================== The nfs client library itself, i.e. the lib and include directories, is licenced under GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. +The protocol definition, .x, files +================================== +These are based on old RFCs and studying how wireshark dissects various packets. +These are distributed under the simplified BSD licence. + The examples directory ================================ The utility and example applications using this library, i.e. the diff --git a/Makefile.am b/Makefile.am index 4ffb68f..f01dba3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = mount nfs nlm nsm portmap rquota lib include . $(MAYBE_EXAMPLES) +SUBDIRS = doc mount nfs nlm nsm portmap rquota lib include utils . $(MAYBE_EXAMPLES) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libnfs.pc diff --git a/README b/README index 4e312da..b0655ea 100644 --- a/README +++ b/README @@ -28,7 +28,7 @@ URL-FORMAT: Libnfs uses RFC2224 style URLs extended with libnfs specific url arguments some minor extensions. The basic syntax of these URLs is : -nfs:///path[?arg=val[&arg=val]*] +nfs:///path[?arg=val[&arg=val]*] Arguments supported by libnfs are : tcp-syncnt= : Number of SYNs to send during the session establish @@ -62,6 +62,14 @@ This is highly non-portable so IF this works on your linux system, count yourself lucky. +DOCUMENTATION +============= +libnfs sources ship with prebuilt manpage(s) in the doc directory. +If you change the manpage sources you need to manually regenerate the new +manpages by running + cd doc + make doc + FUSE ==== A simple FUSE filesystem built on libnfs can be found in diff --git a/aros/aros_compat.h b/aros/aros_compat.h index 76de2ac..2089bc8 100644 --- a/aros/aros_compat.h +++ b/aros/aros_compat.h @@ -1,3 +1,20 @@ +/* + Copyright (C) 2013 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, see . +*/ + #ifndef AROS_COMPAT_H #define AROS_COMPAT_H diff --git a/configure.ac b/configure.ac index c52a370..2cb979e 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.50) -AC_INIT([libnfs], [1.9.3], [ronniesahlberg@gmail.com]) +AC_INIT([libnfs], [1.9.4], [ronniesahlberg@gmail.com]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign]) AC_CANONICAL_HOST @@ -155,6 +155,7 @@ AC_CHECK_MEMBER([struct sockaddr_storage.ss_family], #output AC_CONFIG_FILES([Makefile] + [doc/Makefile] [include/Makefile] [lib/Makefile] [mount/Makefile] @@ -163,6 +164,7 @@ AC_CONFIG_FILES([Makefile] [nsm/Makefile] [portmap/Makefile] [rquota/Makefile] + [utils/Makefile] [examples/Makefile] ) diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..8b9753c --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,9 @@ +XSLTPROC = /usr/bin/xsltproc + +EXTRA_DIST = nfs-ls.1 nfs-ls.1.xml + +# Manpages +man1_MANS = nfs-ls.1 + +doc: + -test -z "$(XSLTPROC)" || $(XSLTPROC) -o nfs-ls.1 http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl nfs-ls.1.xml diff --git a/doc/nfs-ls.1 b/doc/nfs-ls.1 new file mode 100644 index 0000000..1c09bfc --- /dev/null +++ b/doc/nfs-ls.1 @@ -0,0 +1,120 @@ +'\" t +.\" Title: nfs-ls +.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] +.\" Generator: DocBook XSL Stylesheets v1.78.1 +.\" Date: 05/14/2014 +.\" Manual: nfs-ls: list servers, exports and directories +.\" Source: nfs-ls +.\" Language: English +.\" +.TH "NFS\-LS" "1" "05/14/2014" "nfs\-ls" "nfs\-ls: list servers, exports" +.\" ----------------------------------------------------------------- +.\" * Define some portability stuff +.\" ----------------------------------------------------------------- +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.\" http://bugs.debian.org/507673 +.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.\" ----------------------------------------------------------------- +.\" * MAIN CONTENT STARTS HERE * +.\" ----------------------------------------------------------------- +.SH "NAME" +nfs-ls \- Utility to list NFS servers, exports and directories +.SH "SYNOPSIS" +.HP \w'\fBnfs\-ls\ [\ OPTIONS\ ]\ \fR\ 'u +\fBnfs\-ls [ OPTIONS ] \fR +.HP \w'\fBnfs\-ls\fR\ 'u +\fBnfs\-ls\fR [\-R\ \-\-recursive] [\-s\ \-\-summary] [\-D\ \-\-discovery] [\-?\ \-\-help] [\-\-usage] +.SH "DESCRIPTION" +.PP +nfs\-ls is a utility to list NFS servers, exports or directories\&. +.PP +Example: List the content of a directory on the NFS server +.sp +.if n \{\ +.RS 4 +.\} +.nf +$ nfs\-ls nfs://127\&.0\&.0\&.1/data/tmp +\-rwxrwxr\-x 1 1000 1000 1190802 a\&.out +\-rwxr\-xr\-x 1 1000 1000 13 foo123\&.copy +\-rwxrwxrwx 1 1000 1000 8 foo123\&.writtenx + +.fi +.if n \{\ +.RE +.\} +.sp +.SH "OPTIONS" +.PP +\-s \-\-summary +.RS 4 +Print a summary line at the end of output\&. +.RE +.PP +\-R \-\-recursive +.RS 4 +Recursive listing of the specified URL\&. +.RE +.PP +\-D \-\-discovery; +.RS 4 +This option is used to discover local NFS servers and to list the exports for specific servers\&. +.sp +When used with the \*(Aqnfs://\*(Aq URL the command will try to detect all local NFS servers and will list their IPs\&. +.sp +When used with a \*(Aqnfs://server\*(Aq the command will list all the exports on the specified server\&. +.sp +Example: Discover and list all local NFS servers +.sp +.if n \{\ +.RS 4 +.\} +.nf +$ nfs\-ls \-D nfs:// +nfs://10\&.10\&.10\&.10 +nfs://10\&.0\&.0\&.10 + +.fi +.if n \{\ +.RE +.\} +.sp +Example: List the exports for a server +.sp +.if n \{\ +.RS 4 +.\} +.nf +$ nfs\-ls \-D nfs://10\&.10\&.10\&.10 +nfs://10\&.10\&.10\&.10/foo +nfs://10\&.10\&.10\&.10/bar + +.fi +.if n \{\ +.RE +.\} +.sp +.RE +.PP +\-? \-\-help +.RS 4 +Display basic help text\&. +.RE +.PP +\-\-usage +.RS 4 +Display basic usage text\&. +.RE +.SH "SEE ALSO" +.PP +\m[blue]\fB\%http://github.com/sahlberg/libnfs\fR\m[] diff --git a/doc/nfs-ls.1.xml b/doc/nfs-ls.1.xml new file mode 100644 index 0000000..9329369 --- /dev/null +++ b/doc/nfs-ls.1.xml @@ -0,0 +1,126 @@ + + + + + nfs-ls + 1 + nfs-ls + nfs-ls: list servers, exports and directories + + + + + nfs-ls + Utility to list NFS servers, exports and directories + + + + + nfs-ls [ OPTIONS ] <NFS-URL> + + + + nfs-ls + -R --recursive + -s --summary + -D --discovery + -? --help + --usage + + + + + DESCRIPTION + + nfs-ls is a utility to list NFS servers, exports or directories. + + + Example: List the content of a directory on the NFS server + +$ nfs-ls nfs://127.0.0.1/data/tmp +-rwxrwxr-x 1 1000 1000 1190802 a.out +-rwxr-xr-x 1 1000 1000 13 foo123.copy +-rwxrwxrwx 1 1000 1000 8 foo123.writtenx + + + + + + OPTIONS + + + + -s --summary + + + Print a summary line at the end of output. + + + + + -R --recursive + + + Recursive listing of the specified URL. + + + + + -D --discovery; + + + This option is used to discover local NFS servers and to list + the exports for specific servers. + + + When used with the 'nfs://' URL the command will try to + detect all local NFS servers and will list their IPs. + + + When used with a 'nfs://server' the command will + list all the exports on the specified server. + + + Example: Discover and list all local NFS servers + +$ nfs-ls -D nfs:// +nfs://10.10.10.10 +nfs://10.0.0.10 + + + Example: List the exports for a server + +$ nfs-ls -D nfs://10.10.10.10 +nfs://10.10.10.10/foo +nfs://10.10.10.10/bar + + + + + + -? --help + + + Display basic help text. + + + + + --usage + + + Display basic usage text. + + + + + + + + SEE ALSO + + + + + + diff --git a/examples/Makefile.am b/examples/Makefile.am index 10fd9ea..fdf9fbd 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,4 +1,4 @@ -noinst_PROGRAMS = nfsclient-async nfsclient-raw nfsclient-sync nfsclient-bcast nfsclient-listservers nfs-ls nfs-cp nfs-io +noinst_PROGRAMS = nfsclient-async nfsclient-raw nfsclient-sync nfsclient-bcast nfsclient-listservers nfs-cp nfs-io portmap-client AM_CPPFLAGS = \ -I$(abs_top_srcdir)/include \ @@ -10,20 +10,3 @@ AM_CPPFLAGS = \ "-D_U_=__attribute__((unused))" AM_LDFLAGS = ../lib/.libs/libnfs.la -lpopt - -nfs_ls_SOURCES = nfs-ls.c - -nfs_cp_SOURCES = nfs-cp.c - -nfs_io_SOURCES = nfs-io.c - -nfsclient_async_SOURCES = nfsclient-async.c - -nfsclient_raw_SOURCES = nfsclient-raw.c - -nfsclient_sync_SOURCES = nfsclient-sync.c - -nfsclient_bcast_SOURCES = nfsclient-bcast.c - -nfsclient_listservers_SOURCES = nfsclient-listservers.c - diff --git a/examples/nfsclient-bcast.c b/examples/nfsclient-bcast.c index 62ea654..45a6385 100644 --- a/examples/nfsclient-bcast.c +++ b/examples/nfsclient-bcast.c @@ -212,7 +212,7 @@ int main(int argc _U_, char *argv[] _U_) exit(10); } - if (rpc_pmap_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, pm_cb, &data) < 0) { + if (rpc_pmap2_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, pm_cb, &data) < 0) { printf("Failed to set up callit function\n"); exit(10); } diff --git a/examples/nfsclient-raw.c b/examples/nfsclient-raw.c index fd6575f..8b7d727 100644 --- a/examples/nfsclient-raw.c +++ b/examples/nfsclient-raw.c @@ -340,7 +340,7 @@ void pmap_getport1_cb(struct rpc_context *rpc, int status, void *data, void *pri } printf("Send getport request asking for MOUNT port\n"); - if (rpc_pmap_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, IPPROTO_TCP, pmap_getport2_cb, client) != 0) { + if (rpc_pmap2_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, IPPROTO_TCP, pmap_getport2_cb, client) != 0) { printf("Failed to send getport request\n"); exit(10); } @@ -349,8 +349,8 @@ void pmap_getport1_cb(struct rpc_context *rpc, int status, void *data, void *pri void pmap_dump_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; - struct pmap_dump_result *dr = data; - struct pmap_mapping_list *list = dr->list; + struct pmap2_dump_result *dr = data; + struct pmap2_mapping_list *list = dr->list; if (status == RPC_STATUS_ERROR) { printf("portmapper null call failed with \"%s\"\n", (char *)data); @@ -372,7 +372,7 @@ void pmap_dump_cb(struct rpc_context *rpc, int status, void *data, void *private } printf("Send getport request asking for MOUNT port\n"); - if (rpc_pmap_getport_async(rpc, RQUOTA_PROGRAM, RQUOTA_V1, IPPROTO_TCP, pmap_getport1_cb, client) != 0) { + if (rpc_pmap2_getport_async(rpc, RQUOTA_PROGRAM, RQUOTA_V1, IPPROTO_TCP, pmap_getport1_cb, client) != 0) { printf("Failed to send getport request\n"); exit(10); } @@ -393,7 +393,7 @@ void pmap_null_cb(struct rpc_context *rpc, int status, void *data, void *private printf("Got reply from server for PORTMAP/NULL procedure.\n"); printf("Send PMAP/DUMP command\n"); - if (rpc_pmap_dump_async(rpc, pmap_dump_cb, client) != 0) { + if (rpc_pmap2_dump_async(rpc, pmap_dump_cb, client) != 0) { printf("Failed to send getport request\n"); exit(10); } @@ -410,7 +410,7 @@ void pmap_connect_cb(struct rpc_context *rpc, int status, void *data _U_, void * } printf("Send NULL request to check if portmapper is actually running\n"); - if (rpc_pmap_null_async(rpc, pmap_null_cb, client) != 0) { + if (rpc_pmap2_null_async(rpc, pmap_null_cb, client) != 0) { printf("Failed to send null request\n"); exit(10); } diff --git a/examples/portmap-client.c b/examples/portmap-client.c new file mode 100644 index 0000000..526e348 --- /dev/null +++ b/examples/portmap-client.c @@ -0,0 +1,493 @@ +/* + Copyright (C) by Ronnie Sahlberg 2014 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +/* Example program using the lowlevel raw interface. + * This allow accurate control of the exact commands that are being used. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef WIN32 +#include "win32_compat.h" +#endif + +#ifdef HAVE_POLL_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include "libnfs-zdr.h" +#include "libnfs.h" +#include "libnfs-raw.h" +#include "libnfs-raw-mount.h" +#include "libnfs-raw-nfs.h" +#include "libnfs-raw-portmap.h" +#include "libnfs-raw-rquota.h" + +struct client { + int is_finished; +}; + +void pmap2_dump_cb(struct rpc_context *rpc, int status, void *data, void *private_data) +{ + struct client *client = private_data; + struct pmap2_dump_result *dr = data; + struct pmap2_mapping_list *list = dr->list; + + if (status == RPC_STATUS_ERROR) { + printf("PORTMAP2/DUMP call failed with \"%s\"\n", (char *)data); + exit(10); + } + if (status != RPC_STATUS_SUCCESS) { + printf("PORTMAP2/DUMP call failed, status:%d\n", status); + exit(10); + } + + printf("PORTMAP2/DUMP:\n"); + while (list) { + printf(" Prog:%d Vers:%d Protocol:%d Port:%d\n", + list->map.prog, + list->map.vers, + list->map.prot, + list->map.port); + list = list->next; + } + client->is_finished = 1; +} + +void pmap3_dump_cb(struct rpc_context *rpc, int status, void *data, void *private_data) +{ + struct client *client = private_data; + struct pmap3_dump_result *dr = data; + struct pmap3_mapping_list *list = dr->list; + + if (status == RPC_STATUS_ERROR) { + printf("PORTMAP3/DUMP call failed with \"%s\"\n", (char *)data); + exit(10); + } + if (status != RPC_STATUS_SUCCESS) { + printf("PORTMAP3/DUMP call failed, status:%d\n", status); + exit(10); + } + + printf("PORTMAP3/DUMP:\n"); + while (list) { + printf(" Prog:%d Vers:%d Netid:%s Addr:%s Owner:%s\n", + list->map.prog, + list->map.vers, + list->map.netid, + list->map.addr, + list->map.owner); + list = list->next; + } + client->is_finished = 1; +} + +void pmap3_getaddr_cb(struct rpc_context *rpc, int status, void *data, void *private_data) +{ + struct client *client = private_data; + struct pmap3_string_result *gar = data; + + if (status == RPC_STATUS_ERROR) { + printf("PORTMAP3/GETADDR call failed with \"%s\"\n", (char *)data); + exit(10); + } + if (status != RPC_STATUS_SUCCESS) { + printf("PORTMAP3/GETADDR call failed, status:%d\n", status); + exit(10); + } + + printf("PORTMAP3/GETADDR:\n"); + printf(" Addr:%s\n", gar->addr); + + client->is_finished = 1; +} + +void pmap3_set_cb(struct rpc_context *rpc, int status, void *data, void *private_data) +{ + struct client *client = private_data; + uint32_t res = *(uint32_t *)data; + + if (status == RPC_STATUS_ERROR) { + printf("PORTMAP3/SET call failed with \"%s\"\n", (char *)data); + exit(10); + } + if (status != RPC_STATUS_SUCCESS) { + printf("PORTMAP3/SET call failed, status:%d\n", status); + exit(10); + } + + printf("PORTMAP3/SET:\n"); + printf(" Res:%d\n", res); + + client->is_finished = 1; +} + +void pmap3_unset_cb(struct rpc_context *rpc, int status, void *data, void *private_data) +{ + struct client *client = private_data; + uint32_t res = *(uint32_t *)data; + + if (status == RPC_STATUS_ERROR) { + printf("PORTMAP3/UNSET call failed with \"%s\"\n", (char *)data); + exit(10); + } + if (status != RPC_STATUS_SUCCESS) { + printf("PORTMAP3/UNSET call failed, status:%d\n", status); + exit(10); + } + + printf("PORTMAP3/UNSET:\n"); + printf(" Res:%d\n", res); + + client->is_finished = 1; +} + +void pmap3_gettime_cb(struct rpc_context *rpc, int status, void *data, void *private_data) +{ + struct client *client = private_data; + time_t t = *(uint32_t *)data; + + if (status == RPC_STATUS_ERROR) { + printf("PORTMAP3/GETTIME call failed with \"%s\"\n", (char *)data); + exit(10); + } + if (status != RPC_STATUS_SUCCESS) { + printf("PORTMAP3/GETTIME call failed, status:%d\n", status); + exit(10); + } + + printf("PORTMAP3/GETTIME:\n"); + printf(" Time:%d %s\n", (int)t, ctime(&t)); + + client->is_finished = 1; +} + +void pmap3_uaddr2taddr_cb(struct rpc_context *rpc, int status, void *data, void *private_data) +{ + struct client *client = private_data; + struct pmap3_netbuf *nb = data; + struct sockaddr_storage *ss; + char host[256], port[6]; + int i; + + if (status == RPC_STATUS_ERROR) { + printf("PORTMAP3/UADDR2TADDR call failed with \"%s\"\n", (char *)data); + exit(10); + } + if (status != RPC_STATUS_SUCCESS) { + printf("PORTMAP3/UADDR2TADDR call failed, status:%d\n", status); + exit(10); + } + + printf("PORTMAP3/UADDR2TADDR:\n"); + printf(" MaxLen:%d\n", nb->maxlen); + printf(" "); + for (i = 0; i < nb->maxlen; i++) { + printf("%02x ", nb->buf.buf_val[i]); + if (i %16 == 15) { + printf("\n "); + } + } + printf("\n"); + printf(" ---\n"); + ss = (struct sockaddr_storage *)&nb->buf.buf_val[0]; + getnameinfo((struct sockaddr *)ss, sizeof(struct sockaddr_storage), + &host[0], sizeof(host), &port[0], sizeof(port), + NI_NUMERICHOST|NI_NUMERICSERV); + switch (ss->ss_family) { + case AF_INET: + printf(" IPv4: %s:%s\n", &host[0], &port[0]); + break; + case AF_INET6: + printf(" IPv6: %s:%s\n", &host[0], &port[0]); + break; + } + client->is_finished = 1; +} + +void pmap2_null_cb(struct rpc_context *rpc, int status, void *data, void *private_data) +{ + struct client *client = private_data; + + if (status == RPC_STATUS_ERROR) { + printf("PORTMAP2/NULL call failed with \"%s\"\n", (char *)data); + exit(10); + } + if (status != RPC_STATUS_SUCCESS) { + printf("PORTMAP2/NULL call failed, status:%d\n", status); + exit(10); + } + + printf("PORTMAP2/NULL responded and server is alive\n"); + client->is_finished = 1; +} + +void pmap3_null_cb(struct rpc_context *rpc, int status, void *data, void *private_data) +{ + struct client *client = private_data; + + if (status == RPC_STATUS_ERROR) { + printf("PORTMAP3/NULL call failed with \"%s\"\n", (char *)data); + exit(10); + } + if (status != RPC_STATUS_SUCCESS) { + printf("PORTMAP3/NULL call failed, status:%d\n", status); + exit(10); + } + + printf("PORTMAP3/NULL responded and server is alive\n"); + client->is_finished = 1; +} + +void pmap_null_cb(struct rpc_context *rpc, int status, void *data, void *private_data) +{ + struct client *client = private_data; + + if (status == RPC_STATUS_ERROR) { + printf("PORTMAP/NULL call failed with \"%s\"\n", (char *)data); + exit(10); + } + if (status != RPC_STATUS_SUCCESS) { + printf("PORTMAP/NULL call failed, status:%d\n", status); + exit(10); + } + + client->is_finished = 1; +} + +void pmap_connect_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data) +{ + struct client *client = private_data; + + if (status != RPC_STATUS_SUCCESS) { + printf("connection to portmapper failed\n"); + exit(10); + } + + if (rpc_pmap2_null_async(rpc, pmap_null_cb, client) != 0) { + printf("Failed to send null request\n"); + exit(10); + } +} + + +static void wait_until_finished(struct rpc_context *rpc, struct client *client) +{ + struct pollfd pfd; + + client->is_finished = 0; + for (;;) { + pfd.fd = rpc_get_fd(rpc); + pfd.events = rpc_which_events(rpc); + + if (poll(&pfd, 1, -1) < 0) { + printf("Poll failed"); + exit(10); + } + if (rpc_service(rpc, pfd.revents) < 0) { + printf("rpc_service failed\n"); + break; + } + if (client->is_finished) { + break; + } + } +} + +int main(int argc _U_, char *argv[] _U_) +{ + struct rpc_context *rpc; + struct client client; + char *server = NULL; + int i; + int null2 = 0; + int dump2 = 0; + int null3 = 0; + int set3 = 0; + int unset3 = 0; + int getaddr3 = 0; + int dump3 = 0; + int gettime3 = 0; + int u2t3 = 0; + int command_found = 0; + + int set3prog, set3vers; + char *set3netid, *set3addr, *set3owner; + int unset3prog, unset3vers; + char *unset3netid, *unset3addr, *unset3owner; + int getaddr3prog, getaddr3vers; + char *getaddr3netid, *getaddr3addr, *getaddr3owner; + char *u2t3string; + + rpc = rpc_init_context(); + if (rpc == NULL) { + printf("failed to init context\n"); + exit(10); + } + + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "dump2")) { + dump2 = 1; + command_found++; + } else if (!strcmp(argv[i], "null2")) { + null2 = 1; + command_found++; + } else if (!strcmp(argv[i], "dump3")) { + dump3 = 1; + command_found++; + } else if (!strcmp(argv[i], "gettime3")) { + gettime3 = 1; + command_found++; + } else if (!strcmp(argv[i], "u2t3")) { + u2t3 = 1; + u2t3string = argv[++i]; + command_found++; + } else if (!strcmp(argv[i], "getaddr3")) { + getaddr3 = 1; + getaddr3prog = atoi(argv[++i]); + getaddr3vers = atoi(argv[++i]); + getaddr3netid = argv[++i]; + getaddr3addr = argv[++i]; + getaddr3owner = argv[++i]; + command_found++; + } else if (!strcmp(argv[i], "set3")) { + set3 = 1; + set3prog = atoi(argv[++i]); + set3vers = atoi(argv[++i]); + set3netid = argv[++i]; + set3addr = argv[++i]; + set3owner = argv[++i]; + command_found++; + } else if (!strcmp(argv[i], "null3")) { + null3 = 1; + command_found++; + } else { + server = argv[i]; + } + } + if (command_found == 0 || server == NULL) { + fprintf(stderr, "Usage: portmap-client \n"); + exit(10); + } + + if (rpc_connect_async(rpc, server, 111, pmap_connect_cb, &client) != 0) { + printf("Failed to start connection\n"); + exit(10); + } + wait_until_finished(rpc, &client); + + if (null2) { + if (rpc_pmap2_null_async(rpc, pmap2_null_cb, &client) != 0) { + printf("Failed to send NULL2 request\n"); + exit(10); + } + wait_until_finished(rpc, &client); + } + if (dump2) { + if (rpc_pmap2_dump_async(rpc, pmap2_dump_cb, &client) != 0) { + printf("Failed to send DUMP2 request\n"); + exit(10); + } + wait_until_finished(rpc, &client); + } + if (null3) { + if (rpc_pmap3_null_async(rpc, pmap3_null_cb, &client) != 0) { + printf("Failed to send NULL3 request\n"); + exit(10); + } + wait_until_finished(rpc, &client); + } + if (dump3) { + if (rpc_pmap3_dump_async(rpc, pmap3_dump_cb, &client) != 0) { + printf("Failed to send DUMP3 request\n"); + exit(10); + } + wait_until_finished(rpc, &client); + } + if (gettime3) { + if (rpc_pmap3_gettime_async(rpc, pmap3_gettime_cb, &client) != 0) { + printf("Failed to send GETTIME3 request\n"); + exit(10); + } + wait_until_finished(rpc, &client); + } + if (u2t3) { + if (rpc_pmap3_uaddr2taddr_async(rpc, u2t3string, pmap3_uaddr2taddr_cb, &client) != 0) { + printf("Failed to send UADDR2TADDR3 request\n"); + exit(10); + } + wait_until_finished(rpc, &client); + } + if (getaddr3) { + struct pmap3_mapping map; + + map.prog = getaddr3prog; + map.vers = getaddr3vers; + map.netid = getaddr3netid; + map.addr = getaddr3addr; + map.owner = getaddr3owner; + if (rpc_pmap3_getaddr_async(rpc, &map, pmap3_getaddr_cb, &client) != 0) { + printf("Failed to send GETADDR3 request\n"); + exit(10); + } + wait_until_finished(rpc, &client); + } + if (set3) { + struct pmap3_mapping map; + + map.prog = set3prog; + map.vers = set3vers; + map.netid = set3netid; + map.addr = set3addr; + map.owner = set3owner; + if (rpc_pmap3_set_async(rpc, &map, pmap3_set_cb, &client) != 0) { + printf("Failed to send SET3 request\n"); + exit(10); + } + wait_until_finished(rpc, &client); + } + if (unset3) { + struct pmap3_mapping map; + + map.prog = unset3prog; + map.vers = unset3vers; + map.netid = unset3netid; + map.addr = unset3addr; + map.owner = unset3owner; + if (rpc_pmap3_unset_async(rpc, &map, pmap3_unset_cb, &client) != 0) { + printf("Failed to send UNSET3 request\n"); + exit(10); + } + wait_until_finished(rpc, &client); + } + + + rpc_destroy_context(rpc); + rpc=NULL; + return 0; +} diff --git a/include/Makefile.am b/include/Makefile.am index 27810e0..98ab2cf 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,7 +1,5 @@ nfscdir = $(includedir)/nfsc dist_nfsc_HEADERS = \ - libnfs-private.h \ - slist.h \ nfsc/libnfs.h \ nfsc/libnfs-raw.h \ nfsc/libnfs-zdr.h \ @@ -11,3 +9,7 @@ dist_nfsc_HEADERS = \ ../nlm/libnfs-raw-nlm.h \ ../nsm/libnfs-raw-nsm.h \ ../rquota/libnfs-raw-rquota.h + +dist_noinst_HEADERS = \ + libnfs-private.h \ + slist.h diff --git a/include/libnfs-private.h b/include/libnfs-private.h index 07ce9a8..ef3b9de 100644 --- a/include/libnfs-private.h +++ b/include/libnfs-private.h @@ -65,6 +65,16 @@ struct rpc_fragment { #define RPC_CONTEXT_MAGIC 0xc6e46435 #define RPC_PARAM_UNDEFINED -1 +/* + * Queue is singly-linked but we hold on to the tail + */ +struct rpc_queue { + struct rpc_pdu *head, *tail; +}; + +#define HASHES 1024 +#define NFS_RA_TIMEOUT 5 + struct rpc_context { uint32_t magic; int fd; @@ -82,9 +92,9 @@ struct rpc_context { char *encodebuf; int encodebuflen; - struct rpc_pdu *outqueue; + struct rpc_queue outqueue; struct sockaddr_storage udp_src; - struct rpc_pdu *waitpdu; + struct rpc_queue waitpdu[HASHES]; uint32_t inpos; uint32_t insize; @@ -106,6 +116,7 @@ struct rpc_context { int tcp_syncnt; int uid; int gid; + uint32_t readahead; }; struct rpc_pdu { @@ -126,6 +137,11 @@ struct rpc_pdu { uint32_t zdr_decode_bufsize; }; +void rpc_reset_queue(struct rpc_queue *q); +void rpc_enqueue(struct rpc_queue *q, struct rpc_pdu *pdu); +void rpc_return_to_queue(struct rpc_queue *q, struct rpc_pdu *pdu); +unsigned int rpc_hash_xid(uint32_t xid); + struct rpc_pdu *rpc_allocate_pdu(struct rpc_context *rpc, int program, int version, int procedure, rpc_cb cb, void *private_data, zdrproc_t zdr_decode_fn, int zdr_bufsize); void rpc_free_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu); int rpc_queue_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu); @@ -160,6 +176,7 @@ void rpc_unset_autoreconnect(struct rpc_context *rpc); void rpc_set_tcp_syncnt(struct rpc_context *rpc, int v); void rpc_set_uid(struct rpc_context *rpc, int uid); void rpc_set_gid(struct rpc_context *rpc, int gid); +void rpc_set_readahead(struct rpc_context *rpc, uint32_t v); int rpc_add_fragment(struct rpc_context *rpc, char *data, uint64_t size); void rpc_free_all_fragments(struct rpc_context *rpc); diff --git a/include/nfsc/libnfs-raw.h b/include/nfsc/libnfs-raw.h index 9d6b0ec..3ba9de3 100644 --- a/include/nfsc/libnfs-raw.h +++ b/include/nfsc/libnfs-raw.h @@ -110,7 +110,7 @@ int rpc_connect_async(struct rpc_context *rpc, const char *server, int port, rpc * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete. * : data is NULL. */ -int rpc_connect_program_async(struct rpc_context *rpc, char *server, int program, int version, rpc_cb cb, void *private_data); +int rpc_connect_program_async(struct rpc_context *rpc, const char *server, int program, int version, rpc_cb cb, void *private_data); /* * When disconnecting a connection in flight. All commands in flight will be called with the callback * and status RPC_STATUS_ERROR. Data will be the error string for the disconnection. @@ -119,11 +119,11 @@ int rpc_disconnect(struct rpc_context *rpc, char *error); /* - * PORTMAP FUNCTIONS + * PORTMAP v2 FUNCTIONS */ /* - * Call PORTMAPPER/NULL + * Call PORTMAPPER2/NULL * Function returns * 0 : The connection was initiated. Once the connection establish finishes, the callback will be invoked. * <0 : An error occured when trying to set up the connection. The callback will not be invoked. @@ -136,11 +136,11 @@ int rpc_disconnect(struct rpc_context *rpc, char *error); * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete. * data is NULL. */ -EXTERN int rpc_pmap_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); +EXTERN int rpc_pmap2_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* - * Call PORTMAPPER/GETPORT. + * Call PORTMAPPER2/GETPORT. * Function returns * 0 : The connection was initiated. Once the connection establish finishes, the callback will be invoked. * <0 : An error occured when trying to set up the connection. The callback will not be invoked. @@ -153,10 +153,10 @@ EXTERN int rpc_pmap_null_async(struct rpc_context *rpc, rpc_cb cb, void *private * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete. * data is NULL. */ -EXTERN int rpc_pmap_getport_async(struct rpc_context *rpc, int program, int version, int protocol, rpc_cb cb, void *private_data); +EXTERN int rpc_pmap2_getport_async(struct rpc_context *rpc, int program, int version, int protocol, rpc_cb cb, void *private_data); /* - * Call PORTMAPPER/SET + * Call PORTMAPPER2/SET * Function returns * 0 : The connection was initiated. Once the connection establish finishes, the callback will be invoked. * <0 : An error occured when trying to set up the connection. The callback will not be invoked. @@ -169,10 +169,10 @@ EXTERN int rpc_pmap_getport_async(struct rpc_context *rpc, int program, int vers * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete. * data is NULL. */ -EXTERN int rpc_pmap_set_async(struct rpc_context *rpc, int program, int version, int protocol, int port, rpc_cb cb, void *private_data); +EXTERN int rpc_pmap2_set_async(struct rpc_context *rpc, int program, int version, int protocol, int port, rpc_cb cb, void *private_data); /* - * Call PORTMAPPER/UNSET + * Call PORTMAPPER2/UNSET * Function returns * 0 : The connection was initiated. Once the connection establish finishes, the callback will be invoked. * <0 : An error occured when trying to set up the connection. The callback will not be invoked. @@ -185,39 +185,189 @@ EXTERN int rpc_pmap_set_async(struct rpc_context *rpc, int program, int version, * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete. * data is NULL. */ -EXTERN int rpc_pmap_unset_async(struct rpc_context *rpc, int program, int version, int protocol, int port, rpc_cb cb, void *private_data); +EXTERN int rpc_pmap2_unset_async(struct rpc_context *rpc, int program, int version, int protocol, int port, rpc_cb cb, void *private_data); /* - * Call PORTMAPPER/DUMP. + * Call PORTMAPPER2/DUMP. * Function returns * 0 : The connection was initiated. Once the connection establish finishes, the callback will be invoked. * <0 : An error occured when trying to set up the connection. The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the portmapper daemon. - * data is struct *pmap_mapping_list. + * data is struct pmap2_dump_result. * RPC_STATUS_ERROR : An error occured when trying to contact the portmapper. * data is the error string. * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete. * data is NULL. */ -EXTERN int rpc_pmap_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); +EXTERN int rpc_pmap2_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* - * Call PORTMAPPER/CALLIT. + * Call PORTMAPPER2/CALLIT. * Function returns * 0 : The connection was initiated. Once the connection establish finishes, the callback will be invoked. * <0 : An error occured when trying to set up the connection. The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the portmapper daemon - * data is a 'pmap_call_result' pointer. + * data is a 'pmap2_call_result' pointer. * RPC_STATUS_ERROR : An error occured when trying to contact the portmapper. * data is the error string. * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete. * data is NULL. */ -EXTERN int rpc_pmap_callit_async(struct rpc_context *rpc, int program, int version, int procedure, char *data, int datalen, rpc_cb cb, void *private_data); +EXTERN int rpc_pmap2_callit_async(struct rpc_context *rpc, int program, int version, int procedure, char *data, int datalen, rpc_cb cb, void *private_data); + +/* + * PORTMAP v3 FUNCTIONS + */ + +/* + * Call PORTMAPPER3/NULL + * Function returns + * 0 : The connection was initiated. Once the connection establish finishes, the callback will be invoked. + * <0 : An error occured when trying to set up the connection. The callback will not be invoked. + * + * When the callback is invoked, status indicates the result: + * RPC_STATUS_SUCCESS : We got a successful response from the portmapper daemon. + * data is NULL. + * RPC_STATUS_ERROR : An error occured when trying to contact the portmapper. + * data is the error string. + * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete. + * data is NULL. + */ +EXTERN int rpc_pmap3_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); + +/* + * Call PORTMAPPER3/SET. + * Function returns + * 0 : The connection was initiated. Once the connection establish finishes, the callback will be invoked. + * <0 : An error occured when trying to set up the connection. The callback will not be invoked. + * + * When the callback is invoked, status indicates the result: + * RPC_STATUS_SUCCESS : We got a successful response from the portmapper daemon. + * data is uint32_t * + * RPC_STATUS_ERROR : An error occured when trying to contact the portmapper. + * data is the error string. + * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete. + * data is NULL. + */ +struct pmap3_mapping; +EXTERN int rpc_pmap3_set_async(struct rpc_context *rpc, struct pmap3_mapping *map, rpc_cb cb, void *private_data); + +/* + * Call PORTMAPPER3/UNSET. + * Function returns + * 0 : The connection was initiated. Once the connection establish finishes, the callback will be invoked. + * <0 : An error occured when trying to set up the connection. The callback will not be invoked. + * + * When the callback is invoked, status indicates the result: + * RPC_STATUS_SUCCESS : We got a successful response from the portmapper daemon. + * data is uint32_t * + * RPC_STATUS_ERROR : An error occured when trying to contact the portmapper. + * data is the error string. + * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete. + * data is NULL. + */ +EXTERN int rpc_pmap3_unset_async(struct rpc_context *rpc, struct pmap3_mapping *map, rpc_cb cb, void *private_data); + +/* + * Call PORTMAPPER3/GETADDR. + * Function returns + * 0 : The connection was initiated. Once the connection establish finishes, the callback will be invoked. + * <0 : An error occured when trying to set up the connection. The callback will not be invoked. + * + * When the callback is invoked, status indicates the result: + * RPC_STATUS_SUCCESS : We got a successful response from the portmapper daemon. + * data is struct pmap3_string_result. + * RPC_STATUS_ERROR : An error occured when trying to contact the portmapper. + * data is the error string. + * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete. + * data is NULL. + */ +EXTERN int rpc_pmap3_getaddr_async(struct rpc_context *rpc, struct pmap3_mapping *map, rpc_cb cb, void *private_data); + +/* + * Call PORTMAPPER3/DUMP. + * Function returns + * 0 : The connection was initiated. Once the connection establish finishes, the callback will be invoked. + * <0 : An error occured when trying to set up the connection. The callback will not be invoked. + * + * When the callback is invoked, status indicates the result: + * RPC_STATUS_SUCCESS : We got a successful response from the portmapper daemon. + * data is struct pmap3_dump_result. + * RPC_STATUS_ERROR : An error occured when trying to contact the portmapper. + * data is the error string. + * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete. + * data is NULL. + */ +EXTERN int rpc_pmap3_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); + +/* + * Call PORTMAPPER3/CALLIT. + * Function returns + * 0 : The connection was initiated. Once the connection establish finishes, the callback will be invoked. + * <0 : An error occured when trying to set up the connection. The callback will not be invoked. + * + * When the callback is invoked, status indicates the result: + * RPC_STATUS_SUCCESS : We got a successful response from the portmapper daemon + * data is a 'pmap3_call_result' pointer. + * RPC_STATUS_ERROR : An error occured when trying to contact the portmapper. + * data is the error string. + * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete. + * data is NULL. + */ +EXTERN int rpc_pmap3_callit_async(struct rpc_context *rpc, int program, int version, int procedure, char *data, int datalen, rpc_cb cb, void *private_data); + +/* + * Call PORTMAPPER3/GETTIME. + * Function returns + * 0 : The connection was initiated. Once the connection establish finishes, the callback will be invoked. + * <0 : An error occured when trying to set up the connection. The callback will not be invoked. + * + * When the callback is invoked, status indicates the result: + * RPC_STATUS_SUCCESS : We got a successful response from the portmapper daemon. + * data is a uint32_t *. + * RPC_STATUS_ERROR : An error occured when trying to contact the portmapper. + * data is the error string. + * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete. + * data is NULL. + */ +EXTERN int rpc_pmap3_gettime_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); + +/* + * Call PORTMAPPER3/UADDR2TADDR. + * Function returns + * 0 : The connection was initiated. Once the connection establish finishes, the callback will be invoked. + * <0 : An error occured when trying to set up the connection. The callback will not be invoked. + * + * When the callback is invoked, status indicates the result: + * RPC_STATUS_SUCCESS : We got a successful response from the portmapper daemon. + * data is a struct pmap3_netbuf *. + * RPC_STATUS_ERROR : An error occured when trying to contact the portmapper. + * data is the error string. + * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete. + * data is NULL. + */ +EXTERN int rpc_pmap3_uaddr2taddr_async(struct rpc_context *rpc, char *uaddr, rpc_cb cb, void *private_data); + +/* + * Call PORTMAPPER3/TADDR2UADDR. + * Function returns + * 0 : The connection was initiated. Once the connection establish finishes, the callback will be invoked. + * <0 : An error occured when trying to set up the connection. The callback will not be invoked. + * + * When the callback is invoked, status indicates the result: + * RPC_STATUS_SUCCESS : We got a successful response from the portmapper daemon. + * data is a struct pmap3_string_result *. + * RPC_STATUS_ERROR : An error occured when trying to contact the portmapper. + * data is the error string. + * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete. + * data is NULL. + */ +struct pmap3_netbuf; +EXTERN int rpc_pmap3_taddr2uaddr_async(struct rpc_context *rpc, struct pmap3_netbuf *netbuf, rpc_cb cb, void *private_data); /* * MOUNT v3 FUNCTIONS diff --git a/include/nfsc/libnfs.h b/include/nfsc/libnfs.h index 406fcdf..dfa2185 100644 --- a/include/nfsc/libnfs.h +++ b/include/nfsc/libnfs.h @@ -28,11 +28,17 @@ #if defined(AROS) #include #endif +#if defined(__APPLE__) && defined(__MACH__) +#include +#endif #ifdef __cplusplus extern "C" { #endif +#define LIBNFS_FEATURE_READAHEAD +#define NFS_BLKSIZE 4096 + struct nfs_context; struct rpc_context; @@ -181,6 +187,7 @@ EXTERN uint64_t nfs_get_writemax(struct nfs_context *nfs); EXTERN void nfs_set_tcp_syncnt(struct nfs_context *nfs, int v); EXTERN void nfs_set_uid(struct nfs_context *nfs, int uid); EXTERN void nfs_set_gid(struct nfs_context *nfs, int gid); +EXTERN void nfs_set_readahead(struct nfs_context *nfs, uint32_t v); /* * MOUNT THE EXPORT @@ -322,13 +329,15 @@ EXTERN int nfs_fstat(struct nfs_context *nfs, struct nfsfh *nfsfh, struct stat * /* * Async open() * - * mode is a combination of the flags : O_RDOLNY, O_WRONLY, O_RDWR , O_SYNC + * mode is a combination of the flags : + * O_RDOLNY, O_WRONLY, O_RDWR , O_SYNC, O_APPEND * * Function returns * 0 : The operation was initiated. Once the operation finishes, the callback will be invoked. * <0 : An error occured when trying to set up the operation. The callback will not be invoked. * * Supported flags are + * O_APPEND * O_RDONLY * O_WRONLY * O_RDWR @@ -504,14 +513,14 @@ EXTERN int nfs_write(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t coun * -errno : An error occured. * data is the error string. */ -EXTERN int nfs_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, int whence, nfs_cb cb, void *private_data); +EXTERN int nfs_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int64_t offset, int whence, nfs_cb cb, void *private_data); /* * Sync lseek() * Function returns * >=0 : numer of bytes read. * -errno : An error occured. */ -EXTERN int nfs_lseek(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, int whence, uint64_t *current_offset); +EXTERN int nfs_lseek(struct nfs_context *nfs, struct nfsfh *nfsfh, int64_t offset, int whence, uint64_t *current_offset); /* @@ -776,6 +785,7 @@ struct nfsdirent { struct timeval ctime; uint32_t uid; uint32_t gid; + uint32_t nlink; }; /* * nfs_readdir() never blocks, so no special sync/async versions are available diff --git a/include/slist.h b/include/slist.h index 8bb6ca4..5755ca1 100644 --- a/include/slist.h +++ b/include/slist.h @@ -18,15 +18,15 @@ #ifndef _LIBNFS_SLIST_H_ #define _LIBNFS_SLIST_H_ -#define SLIST_ADD(list, item) \ +#define LIBNFS_LIST_ADD(list, item) \ do { \ (item)->next = (*list); \ (*list) = (item); \ } while (0); -#define SLIST_ADD_END(list, item) \ +#define LIBNFS_LIST_ADD_END(list, item) \ if ((*list) == NULL) { \ - SLIST_ADD((list), (item)); \ + LIBNFS_LIST_ADD((list), (item)); \ } else { \ void *head = (*list); \ while ((*list)->next) \ @@ -36,7 +36,7 @@ (*list) = head; \ } -#define SLIST_REMOVE(list, item) \ +#define LIBNFS_LIST_REMOVE(list, item) \ if ((*list) == (item)) { \ (*list) = (item)->next; \ } else { \ diff --git a/lib/Makefile.am b/lib/Makefile.am index aa0855f..1f9a55a 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -18,9 +18,9 @@ libnfs_la_SOURCES = \ pdu.c \ socket.c -SOCURRENT=4 +SOCURRENT=5 SOREVISION=0 -SOAGE=0 +SOAGE=1 libnfs_la_LDFLAGS = -version-info $(SOCURRENT):$(SOREVISION):$(SOAGE) libnfs_la_LIBADD = \ ../mount/libmount.la \ diff --git a/lib/init.c b/lib/init.c index 36d4880..d41c4f8 100644 --- a/lib/init.c +++ b/lib/init.c @@ -1,7 +1,10 @@ /* Copyright (C) 2010 by Ronnie Sahlberg - + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -49,6 +52,7 @@ struct rpc_context *rpc_init_context(void) { struct rpc_context *rpc; static uint32_t salt = 0; + unsigned int i; rpc = malloc(sizeof(struct rpc_context)); if (rpc == NULL) { @@ -83,10 +87,19 @@ struct rpc_context *rpc_init_context(void) rpc->uid = getuid(); rpc->gid = getgid(); #endif + rpc_reset_queue(&rpc->outqueue); + for (i = 0; i < HASHES; i++) + rpc_reset_queue(&rpc->waitpdu[i]); return rpc; } +void rpc_set_readahead(struct rpc_context *rpc, uint32_t v) +{ + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + rpc->readahead = v; +} struct rpc_context *rpc_init_udp_context(void) { @@ -155,19 +168,27 @@ char *rpc_get_error(struct rpc_context *rpc) void rpc_error_all_pdus(struct rpc_context *rpc, char *error) { - struct rpc_pdu *pdu; + struct rpc_pdu *pdu, *next; + unsigned int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); - while((pdu = rpc->outqueue) != NULL) { + while ((pdu = rpc->outqueue.head) != NULL) { pdu->cb(rpc, RPC_STATUS_ERROR, error, pdu->private_data); - SLIST_REMOVE(&rpc->outqueue, pdu); + rpc->outqueue.head = pdu->next; rpc_free_pdu(rpc, pdu); } - while((pdu = rpc->waitpdu) != NULL) { - pdu->cb(rpc, RPC_STATUS_ERROR, error, pdu->private_data); - SLIST_REMOVE(&rpc->waitpdu, pdu); - rpc_free_pdu(rpc, pdu); + rpc->outqueue.tail = NULL; + + for (i = 0; i < HASHES; i++) { + struct rpc_queue *q = &rpc->waitpdu[i]; + + while((pdu = q->head) != NULL) { + pdu->cb(rpc, RPC_STATUS_ERROR, error, pdu->private_data); + q->head = pdu->next; + rpc_free_pdu(rpc, pdu); + } + q->tail = NULL; } } @@ -186,7 +207,7 @@ void rpc_free_all_fragments(struct rpc_context *rpc) while (rpc->fragments != NULL) { struct rpc_fragment *fragment = rpc->fragments; - SLIST_REMOVE(&rpc->fragments, fragment); + rpc->fragments = fragment->next; rpc_free_fragment(fragment); } } @@ -210,25 +231,31 @@ int rpc_add_fragment(struct rpc_context *rpc, char *data, uint64_t size) } memcpy(fragment->data, data, fragment->size); - SLIST_ADD_END(&rpc->fragments, fragment); + LIBNFS_LIST_ADD_END(&rpc->fragments, fragment); return 0; } void rpc_destroy_context(struct rpc_context *rpc) { struct rpc_pdu *pdu; + unsigned int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); - while((pdu = rpc->outqueue) != NULL) { + while((pdu = rpc->outqueue.head) != NULL) { pdu->cb(rpc, RPC_STATUS_CANCEL, NULL, pdu->private_data); - SLIST_REMOVE(&rpc->outqueue, pdu); + LIBNFS_LIST_REMOVE(&rpc->outqueue.head, pdu); rpc_free_pdu(rpc, pdu); } - while((pdu = rpc->waitpdu) != NULL) { - pdu->cb(rpc, RPC_STATUS_CANCEL, NULL, pdu->private_data); - SLIST_REMOVE(&rpc->waitpdu, pdu); - rpc_free_pdu(rpc, pdu); + + for (i = 0; i < HASHES; i++) { + struct rpc_queue *q = &rpc->waitpdu[i]; + + while((pdu = q->head) != NULL) { + pdu->cb(rpc, RPC_STATUS_CANCEL, NULL, pdu->private_data); + LIBNFS_LIST_REMOVE(&q->head, pdu); + rpc_free_pdu(rpc, pdu); + } } rpc_free_all_fragments(rpc); diff --git a/lib/libnfs-sync.c b/lib/libnfs-sync.c index 7ba5222..d4a5451 100644 --- a/lib/libnfs-sync.c +++ b/lib/libnfs-sync.c @@ -29,6 +29,10 @@ #include "win32_compat.h" #endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + #ifdef HAVE_NET_IF_H #include #endif @@ -49,10 +53,6 @@ #include #endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - #ifdef HAVE_POLL_H #include #endif @@ -94,11 +94,12 @@ #include "libnfs-private.h" struct sync_cb_data { - int is_finished; - int status; - uint64_t offset; - void *return_data; - int return_int; + int is_finished; + int status; + uint64_t offset; + void *return_data; + int return_int; + const char *call; }; @@ -351,7 +352,7 @@ static void pread_cb(int status, struct nfs_context *nfs, void *data, void *priv cb_data->status = status; if (status < 0) { - nfs_set_error(nfs, "pread call failed with \"%s\"", (char *)data); + nfs_set_error(nfs, "%s call failed with \"%s\"", cb_data->call, (char *)data); return; } @@ -365,6 +366,7 @@ int nfs_pread(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uin cb_data.is_finished = 0; cb_data.return_data = buffer; + cb_data.call = "pread"; if (nfs_pread_async(nfs, nfsfh, offset, count, pread_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_pread_async failed"); @@ -381,7 +383,20 @@ int nfs_pread(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uin */ int nfs_read(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, char *buffer) { - return nfs_pread(nfs, nfsfh, nfs_get_current_offset(nfsfh), count, buffer); + struct sync_cb_data cb_data; + + cb_data.is_finished = 0; + cb_data.return_data = buffer; + cb_data.call = "read"; + + if (nfs_read_async(nfs, nfsfh, count, pread_cb, &cb_data) != 0) { + nfs_set_error(nfs, "nfs_read_async failed"); + return -1; + } + + wait_for_nfs_reply(nfs, &cb_data); + + return cb_data.status; } /* @@ -448,10 +463,8 @@ static void pwrite_cb(int status, struct nfs_context *nfs, void *data, void *pri cb_data->is_finished = 1; cb_data->status = status; - if (status < 0) { - nfs_set_error(nfs, "pwrite call failed with \"%s\"", (char *)data); - return; - } + if (status < 0) + nfs_set_error(nfs, "%s call failed with \"%s\"", cb_data->call, (char *)data); } int nfs_pwrite(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, char *buf) @@ -459,6 +472,7 @@ int nfs_pwrite(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, ui struct sync_cb_data cb_data; cb_data.is_finished = 0; + cb_data.call = "pwrite"; if (nfs_pwrite_async(nfs, nfsfh, offset, count, buf, pwrite_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_pwrite_async failed"); @@ -475,7 +489,19 @@ int nfs_pwrite(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, ui */ int nfs_write(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, char *buf) { - return nfs_pwrite(nfs, nfsfh, nfs_get_current_offset(nfsfh), count, buf); + struct sync_cb_data cb_data; + + cb_data.is_finished = 0; + cb_data.call = "write"; + + if (nfs_write_async(nfs, nfsfh, count, buf, pwrite_cb, &cb_data) != 0) { + nfs_set_error(nfs, "nfs_write_async failed"); + return -1; + } + + wait_for_nfs_reply(nfs, &cb_data); + + return cb_data.status; } @@ -813,7 +839,7 @@ static void lseek_cb(int status, struct nfs_context *nfs, void *data, void *priv } } -int nfs_lseek(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, int whence, uint64_t *current_offset) +int nfs_lseek(struct nfs_context *nfs, struct nfsfh *nfsfh, int64_t offset, int whence, uint64_t *current_offset) { struct sync_cb_data cb_data; @@ -1328,7 +1354,7 @@ void free_nfs_srvr_list(struct nfs_server_list *srv) free(srv); srv = next; } -} +} struct nfs_list_data { int status; @@ -1364,7 +1390,7 @@ void callit_cb(struct rpc_context *rpc, int status, void *data _U_, void *privat srv_data->status = -1; return; } - + /* check for dupes */ for (srvr = srv_data->srvrs; srvr; srvr = srvr->next) { if (!strcmp(hostdd, srvr->addr)) { @@ -1374,7 +1400,7 @@ void callit_cb(struct rpc_context *rpc, int status, void *data _U_, void *privat srvr = malloc(sizeof(struct nfs_server_list)); if (srvr == NULL) { - rpc_set_error(rpc, "Malloc failed when allocating server structure"); + rpc_set_error(rpc, "Malloc failed when allocating server structure"); srv_data->status = -1; return; } @@ -1399,7 +1425,7 @@ static int send_nfsd_probes(struct rpc_context *rpc, INTERFACE_INFO *InterfaceLi assert(rpc->magic == RPC_CONTEXT_MAGIC); - for(i = 0; i < numIfs; i++) + for(i = 0; i < numIfs; i++) { SOCKADDR *pAddress; char bcdd[16]; @@ -1409,35 +1435,35 @@ static int send_nfsd_probes(struct rpc_context *rpc, INTERFACE_INFO *InterfaceLi if(pAddress->sa_family != AF_INET) continue; - + nFlags = InterfaceList[i].iiFlags; - if (!(nFlags & IFF_UP)) + if (!(nFlags & IFF_UP)) { continue; } - if (nFlags & IFF_LOOPBACK) + if (nFlags & IFF_LOOPBACK) { continue; } - if (!(nFlags & IFF_BROADCAST)) + if (!(nFlags & IFF_BROADCAST)) { continue; } - if (getnameinfo(pAddress, sizeof(struct sockaddr_in), &bcdd[0], sizeof(bcdd), NULL, 0, NI_NUMERICHOST) < 0) + if (getnameinfo(pAddress, sizeof(struct sockaddr_in), &bcdd[0], sizeof(bcdd), NULL, 0, NI_NUMERICHOST) < 0) { continue; } - if (rpc_set_udp_destination(rpc, bcdd, 111, 1) < 0) + if (rpc_set_udp_destination(rpc, bcdd, 111, 1) < 0) { return -1; } - if (rpc_pmap_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, callit_cb, data) < 0) + if (rpc_pmap2_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, callit_cb, data) < 0) { return -1; } @@ -1457,34 +1483,34 @@ struct nfs_server_list *nfs_find_local_servers(void) int nNumInterfaces = 0; rpc = rpc_init_udp_context(); - if (rpc == NULL) + if (rpc == NULL) { return NULL; } - if (rpc_bind_udp(rpc, "0.0.0.0", 0) < 0) + if (rpc_bind_udp(rpc, "0.0.0.0", 0) < 0) { rpc_destroy_context(rpc); return NULL; } - if (WSAIoctl(rpc_get_fd(rpc), SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList, sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR) + if (WSAIoctl(rpc_get_fd(rpc), SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList, sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR) { return NULL; } nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO); - for (loop=0; loop<3; loop++) + for (loop=0; loop<3; loop++) { - if (send_nfsd_probes(rpc, InterfaceList, nNumInterfaces, &data) != 0) + if (send_nfsd_probes(rpc, InterfaceList, nNumInterfaces, &data) != 0) { rpc_destroy_context(rpc); return NULL; } win32_gettimeofday(&tv_start, NULL); - for(;;) + for(;;) { int mpt; @@ -1496,18 +1522,18 @@ struct nfs_server_list *nfs_find_local_servers(void) - (tv_current.tv_sec *1000 + tv_current.tv_usec / 1000) + (tv_start.tv_sec *1000 + tv_start.tv_usec / 1000); - if (poll(&pfd, 1, mpt) < 0) + if (poll(&pfd, 1, mpt) < 0) { free_nfs_srvr_list(data.srvrs); rpc_destroy_context(rpc); return NULL; } - if (pfd.revents == 0) + if (pfd.revents == 0) { break; } - - if (rpc_service(rpc, pfd.revents) < 0) + + if (rpc_service(rpc, pfd.revents) < 0) { break; } @@ -1516,7 +1542,7 @@ struct nfs_server_list *nfs_find_local_servers(void) rpc_destroy_context(rpc); - if (data.status != 0) + if (data.status != 0) { free_nfs_srvr_list(data.srvrs); return NULL; @@ -1571,7 +1597,7 @@ static int send_nfsd_probes(struct rpc_context *rpc, struct ifconf *ifc, struct return -1; } - if (rpc_pmap_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, callit_cb, data) < 0) { + if (rpc_pmap2_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, callit_cb, data) < 0) { return -1; } } @@ -1607,21 +1633,21 @@ struct nfs_server_list *nfs_find_local_servers(void) while(ifc.ifc_len > (size - sizeof(struct ifreq))) { size *= 2; - free(ifc.ifc_buf); + free(ifc.ifc_buf); ifc.ifc_len = size; ifc.ifc_buf = malloc(size); memset(ifc.ifc_buf, 0, size); if (ioctl(rpc_get_fd(rpc), SIOCGIFCONF, (caddr_t)&ifc) < 0) { rpc_destroy_context(rpc); - free(ifc.ifc_buf); + free(ifc.ifc_buf); return NULL; } - } + } for (loop=0; loop<3; loop++) { if (send_nfsd_probes(rpc, &ifc, &data) != 0) { rpc_destroy_context(rpc); - free(ifc.ifc_buf); + free(ifc.ifc_buf); return NULL; } @@ -1645,14 +1671,14 @@ struct nfs_server_list *nfs_find_local_servers(void) if (pfd.revents == 0) { break; } - + if (rpc_service(rpc, pfd.revents) < 0) { break; } } } - free(ifc.ifc_buf); + free(ifc.ifc_buf); rpc_destroy_context(rpc); if (data.status != 0) { diff --git a/lib/libnfs-win32.def b/lib/libnfs-win32.def index 7eae952..5a0df03 100644 --- a/lib/libnfs-win32.def +++ b/lib/libnfs-win32.def @@ -70,6 +70,7 @@ nfs_set_auth nfs_set_gid nfs_set_tcp_syncnt nfs_set_uid +nfs_set_readahead nfs_stat nfs_stat_async nfs_stat64 @@ -96,12 +97,21 @@ rpc_disconnect rpc_get_error rpc_get_fd rpc_init_context -rpc_pmap_null_async -rpc_pmap_getport_async -rpc_pmap_set_async -rpc_pmap_unset_async -rpc_pmap_dump_async -rpc_pmap_callit_async +rpc_pmap2_null_async +rpc_pmap2_getport_async +rpc_pmap2_set_async +rpc_pmap2_unset_async +rpc_pmap2_dump_async +rpc_pmap2_callit_async +rpc_pmap3_null_async +rpc_pmap3_set_async +rpc_pmap3_unset_async +rpc_pmap3_getaddr_async +rpc_pmap3_dump_async +rpc_pmap3_callit_async +rpc_pmap3_gettime_async +rpc_pmap3_uaddr2taddr_async +rpc_pmap3_taddr2uaddr_async rpc_mount_null_async rpc_mount_mnt_async rpc_mount_dump_async diff --git a/lib/libnfs.c b/lib/libnfs.c index bb89d4a..94f03cb 100644 --- a/lib/libnfs.c +++ b/lib/libnfs.c @@ -69,21 +69,41 @@ #include #include #include "libnfs-zdr.h" +#include "slist.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-mount.h" #include "libnfs-raw-nfs.h" +#include "libnfs-raw-portmap.h" #include "libnfs-private.h" +#define MAX_DIR_CACHE 128 + struct nfsdir { + struct nfs_fh3 fh; + fattr3 attr; + struct nfsdir *next; + struct nfsdirent *entries; struct nfsdirent *current; }; +struct nfs_readahead { + uint64_t fh_offset; + uint64_t last_offset; + uint64_t buf_offset; + uint64_t buf_count; + time_t buf_ts; + void *buf; + uint32_t cur_ra; +}; + struct nfsfh { struct nfs_fh3 fh; int is_sync; + int is_append; uint64_t offset; + struct nfs_readahead ra; }; struct nfs_context { @@ -94,6 +114,7 @@ struct nfs_context { uint64_t readmax; uint64_t writemax; char *cwd; + struct nfsdir *dircache; }; void nfs_free_nfsdir(struct nfsdir *nfsdir) @@ -106,11 +127,42 @@ void nfs_free_nfsdir(struct nfsdir *nfsdir) free(nfsdir->entries); nfsdir->entries = dirent; } + free(nfsdir->fh.data.data_val); free(nfsdir); } +static void nfs_dircache_add(struct nfs_context *nfs, struct nfsdir *nfsdir) +{ + int i; + LIBNFS_LIST_ADD(&nfs->dircache, nfsdir); + + for (nfsdir = nfs->dircache, i = 0; nfsdir; nfsdir = nfsdir->next, i++) { + if (i > MAX_DIR_CACHE) { + LIBNFS_LIST_REMOVE(&nfs->dircache, nfsdir); + nfs_free_nfsdir(nfsdir); + break; + } + } +} + +static struct nfsdir *nfs_dircache_find(struct nfs_context *nfs, struct nfs_fh3 *fh) +{ + struct nfsdir *nfsdir; + + for (nfsdir = nfs->dircache; nfsdir; nfsdir = nfsdir->next) { + if (nfsdir->fh.data.data_len == fh->data.data_len && + !memcmp(nfsdir->fh.data.data_val, fh->data.data_val, fh->data.data_len)) { + LIBNFS_LIST_REMOVE(&nfs->dircache, nfsdir); + return nfsdir; + } + } + + return NULL; +} + struct nfs_cb_data; -typedef int (*continue_func)(struct nfs_context *nfs, struct nfs_cb_data *data); +typedef int (*continue_func)(struct nfs_context *nfs, fattr3 *attr, + struct nfs_cb_data *data); struct nfs_cb_data { struct nfs_context *nfs; @@ -132,9 +184,8 @@ struct nfs_cb_data { int cancel; int oom; int num_calls; - uint64_t start_offset, max_offset; + uint64_t offset, count, max_offset, org_offset, org_count; char *buffer; - size_t request_size; char *usrbuf; }; @@ -142,9 +193,10 @@ struct nfs_mcb_data { struct nfs_cb_data *data; uint64_t offset; uint64_t count; + int update_pos; }; -static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh); +static int nfs_lookup_path_async_internal(struct nfs_context *nfs, fattr3 *attr, struct nfs_cb_data *data, struct nfs_fh3 *fh); void nfs_set_auth(struct nfs_context *nfs, struct AUTH *auth) { @@ -178,12 +230,14 @@ char *nfs_get_error(struct nfs_context *nfs) static int nfs_set_context_args(struct nfs_context *nfs, char *arg, char *val) { - if (!strncmp(arg, "tcp-syncnt", 10)) { + if (!strcmp(arg, "tcp-syncnt")) { rpc_set_tcp_syncnt(nfs_get_rpc_context(nfs), atoi(val)); - } else if (!strncmp(arg, "uid", 3)) { + } else if (!strcmp(arg, "uid")) { rpc_set_uid(nfs_get_rpc_context(nfs), atoi(val)); - } else if (!strncmp(arg, "gid", 3)) { + } else if (!strcmp(arg, "gid")) { rpc_set_gid(nfs_get_rpc_context(nfs), atoi(val)); + } else if (!strcmp(arg, "readahaed")) { + rpc_set_readahead(nfs_get_rpc_context(nfs), atoi(val)); } return 0; } @@ -375,6 +429,12 @@ void nfs_destroy_context(struct nfs_context *nfs) nfs->rootfh.data.data_val = NULL; } + while (nfs->dircache) { + struct nfsdir *nfsdir = nfs->dircache; + LIBNFS_LIST_REMOVE(&nfs->dircache, nfsdir); + nfs_free_nfsdir(nfsdir); + } + free(nfs); } @@ -394,6 +454,30 @@ void free_rpc_cb_data(struct rpc_cb_data *data) free(data); } +static void rpc_connect_program_5_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + struct rpc_cb_data *data = private_data; + + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + /* Dont want any more callbacks even if the socket is closed */ + rpc->connect_cb = NULL; + + if (status == RPC_STATUS_ERROR) { + data->cb(rpc, status, command_data, data->private_data); + free_rpc_cb_data(data); + return; + } + if (status == RPC_STATUS_CANCEL) { + data->cb(rpc, status, "Command was cancelled", data->private_data); + free_rpc_cb_data(data); + return; + } + + data->cb(rpc, status, NULL, data->private_data); + free_rpc_cb_data(data); +} + static void rpc_connect_program_4_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct rpc_cb_data *data = private_data; @@ -414,6 +498,25 @@ static void rpc_connect_program_4_cb(struct rpc_context *rpc, int status, void * return; } + switch (data->program) { + case MOUNT_PROGRAM: + if (rpc_mount3_null_async(rpc, rpc_connect_program_5_cb, + data) != 0) { + data->cb(rpc, status, command_data, data->private_data); + free_rpc_cb_data(data); + return; + } + return; + case NFS_PROGRAM: + if (rpc_nfs3_null_async(rpc, rpc_connect_program_5_cb, + data) != 0) { + data->cb(rpc, status, command_data, data->private_data); + free_rpc_cb_data(data); + return; + } + return; + } + data->cb(rpc, status, NULL, data->private_data); free_rpc_cb_data(data); } @@ -421,7 +524,9 @@ static void rpc_connect_program_4_cb(struct rpc_context *rpc, int status, void * static void rpc_connect_program_3_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct rpc_cb_data *data = private_data; - uint32_t rpc_port; + struct pmap3_string_result *gar; + uint32_t rpc_port = 0; + unsigned char *ptr; assert(rpc->magic == RPC_CONTEXT_MAGIC); @@ -436,7 +541,29 @@ static void rpc_connect_program_3_cb(struct rpc_context *rpc, int status, void * return; } - rpc_port = *(uint32_t *)command_data; + switch (rpc->s.ss_family) { + case AF_INET: + rpc_port = *(uint32_t *)command_data; + break; + case AF_INET6: + /* ouch. portmapper and ipv6 are not great */ + gar = command_data; + if (gar->addr == NULL) { + break; + } + ptr = strrchr(gar->addr, '.'); + if (ptr == NULL) { + break; + } + rpc_port = atoi(ptr + 1); + *ptr = 0; + ptr = strrchr(gar->addr, '.'); + if (ptr == NULL) { + break; + } + rpc_port += 256 * atoi(ptr + 1); + break; + } if (rpc_port == 0) { rpc_set_error(rpc, "RPC error. Program is not available on %s", data->server); data->cb(rpc, RPC_STATUS_ERROR, rpc_get_error(rpc), data->private_data); @@ -455,6 +582,7 @@ static void rpc_connect_program_3_cb(struct rpc_context *rpc, int status, void * static void rpc_connect_program_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct rpc_cb_data *data = private_data; + struct pmap3_mapping map; assert(rpc->magic == RPC_CONTEXT_MAGIC); @@ -469,10 +597,26 @@ static void rpc_connect_program_2_cb(struct rpc_context *rpc, int status, void * return; } - if (rpc_pmap_getport_async(rpc, data->program, data->version, IPPROTO_TCP, rpc_connect_program_3_cb, private_data) != 0) { - data->cb(rpc, status, command_data, data->private_data); - free_rpc_cb_data(data); - return; + switch (rpc->s.ss_family) { + case AF_INET: + if (rpc_pmap2_getport_async(rpc, data->program, data->version, IPPROTO_TCP, rpc_connect_program_3_cb, private_data) != 0) { + data->cb(rpc, status, command_data, data->private_data); + free_rpc_cb_data(data); + return; + } + break; + case AF_INET6: + map.prog=data->program; + map.vers=data->version; + map.netid=""; + map.addr=""; + map.owner=""; + if (rpc_pmap3_getaddr_async(rpc, &map, rpc_connect_program_3_cb, private_data) != 0) { + data->cb(rpc, status, command_data, data->private_data); + free_rpc_cb_data(data); + return; + } + break; } } @@ -496,14 +640,25 @@ static void rpc_connect_program_1_cb(struct rpc_context *rpc, int status, void * return; } - if (rpc_pmap_null_async(rpc, rpc_connect_program_2_cb, data) != 0) { - data->cb(rpc, status, command_data, data->private_data); - free_rpc_cb_data(data); - return; + switch (rpc->s.ss_family) { + case AF_INET: + if (rpc_pmap2_null_async(rpc, rpc_connect_program_2_cb, data) != 0) { + data->cb(rpc, status, command_data, data->private_data); + free_rpc_cb_data(data); + return; + } + break; + case AF_INET6: + if (rpc_pmap3_null_async(rpc, rpc_connect_program_2_cb, data) != 0) { + data->cb(rpc, status, command_data, data->private_data); + free_rpc_cb_data(data); + return; + } + break; } } -int rpc_connect_program_async(struct rpc_context *rpc, char *server, int program, int version, rpc_cb cb, void *private_data) +int rpc_connect_program_async(struct rpc_context *rpc, const char *server, int program, int version, rpc_cb cb, void *private_data) { struct rpc_cb_data *data; @@ -542,9 +697,6 @@ static void free_nfs_cb_data(struct nfs_cb_data *data) } - - - static void nfs_mount_10_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; @@ -627,36 +779,6 @@ static void nfs_mount_8_cb(struct rpc_context *rpc, int status, void *command_da } } - -static void nfs_mount_7_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) -{ - struct nfs_cb_data *data = private_data; - struct nfs_context *nfs = data->nfs; - - assert(rpc->magic == RPC_CONTEXT_MAGIC); - - /* Dont want any more callbacks even if the socket is closed */ - rpc->connect_cb = NULL; - - if (status == RPC_STATUS_ERROR) { - data->cb(-EFAULT, nfs, command_data, data->private_data); - free_nfs_cb_data(data); - return; - } - if (status == RPC_STATUS_CANCEL) { - data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); - free_nfs_cb_data(data); - return; - } - - if (rpc_nfs3_null_async(rpc, nfs_mount_8_cb, data) != 0) { - data->cb(-ENOMEM, nfs, command_data, data->private_data); - free_nfs_cb_data(data); - return; - } -} - - static void nfs_mount_6_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; @@ -695,11 +817,13 @@ static void nfs_mount_6_cb(struct rpc_context *rpc, int status, void *command_da memcpy(nfs->rootfh.data.data_val, res->mountres3_u.mountinfo.fhandle.fhandle3_val, nfs->rootfh.data.data_len); rpc_disconnect(rpc, "normal disconnect"); - if (rpc_connect_async(rpc, nfs->server, 2049, nfs_mount_7_cb, data) != 0) { + + if (rpc_connect_program_async(nfs->rpc, nfs->server, NFS_PROGRAM, NFS_V3, nfs_mount_8_cb, data) != 0) { data->cb(-ENOMEM, nfs, command_data, data->private_data); free_nfs_cb_data(data); return; } + /* NFS TCP connections we want to autoreconnect after sessions are torn down (due to inactivity or error) */ rpc_set_autoreconnect(rpc); } @@ -730,123 +854,6 @@ static void nfs_mount_5_cb(struct rpc_context *rpc, int status, void *command_da } } -static void nfs_mount_4_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) -{ - struct nfs_cb_data *data = private_data; - struct nfs_context *nfs = data->nfs; - - assert(rpc->magic == RPC_CONTEXT_MAGIC); - - /* Dont want any more callbacks even if the socket is closed */ - rpc->connect_cb = NULL; - - if (status == RPC_STATUS_ERROR) { - data->cb(-EFAULT, nfs, command_data, data->private_data); - free_nfs_cb_data(data); - return; - } - if (status == RPC_STATUS_CANCEL) { - data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); - free_nfs_cb_data(data); - return; - } - - if (rpc_mount3_null_async(rpc, nfs_mount_5_cb, data) != 0) { - data->cb(-ENOMEM, nfs, command_data, data->private_data); - free_nfs_cb_data(data); - return; - } -} - -static void nfs_mount_3_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) -{ - struct nfs_cb_data *data = private_data; - struct nfs_context *nfs = data->nfs; - uint32_t mount_port; - - assert(rpc->magic == RPC_CONTEXT_MAGIC); - - if (status == RPC_STATUS_ERROR) { - data->cb(-EFAULT, nfs, command_data, data->private_data); - free_nfs_cb_data(data); - return; - } - if (status == RPC_STATUS_CANCEL) { - data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); - free_nfs_cb_data(data); - return; - } - - mount_port = *(uint32_t *)command_data; - if (mount_port == 0) { - rpc_set_error(rpc, "RPC error. Mount program is not available on %s", nfs->server); - data->cb(-ENOENT, nfs, command_data, data->private_data); - free_nfs_cb_data(data); - return; - } - - rpc_disconnect(rpc, "normal disconnect"); - if (rpc_connect_async(rpc, nfs->server, mount_port, nfs_mount_4_cb, data) != 0) { - data->cb(-ENOMEM, nfs, command_data, data->private_data); - free_nfs_cb_data(data); - return; - } -} - - -static void nfs_mount_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) -{ - struct nfs_cb_data *data = private_data; - struct nfs_context *nfs = data->nfs; - - assert(rpc->magic == RPC_CONTEXT_MAGIC); - - if (status == RPC_STATUS_ERROR) { - data->cb(-EFAULT, nfs, command_data, data->private_data); - free_nfs_cb_data(data); - return; - } - if (status == RPC_STATUS_CANCEL) { - data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); - free_nfs_cb_data(data); - return; - } - - if (rpc_pmap_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, IPPROTO_TCP, nfs_mount_3_cb, private_data) != 0) { - data->cb(-ENOMEM, nfs, command_data, data->private_data); - free_nfs_cb_data(data); - return; - } -} - -static void nfs_mount_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) -{ - struct nfs_cb_data *data = private_data; - struct nfs_context *nfs = data->nfs; - - assert(rpc->magic == RPC_CONTEXT_MAGIC); - - /* Dont want any more callbacks even if the socket is closed */ - rpc->connect_cb = NULL; - - if (status == RPC_STATUS_ERROR) { - data->cb(-EFAULT, nfs, command_data, data->private_data); - free_nfs_cb_data(data); - return; - } - if (status == RPC_STATUS_CANCEL) { - data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); - free_nfs_cb_data(data); - return; - } - - if (rpc_pmap_null_async(rpc, nfs_mount_2_cb, data) != 0) { - data->cb(-ENOMEM, nfs, command_data, data->private_data); - free_nfs_cb_data(data); - return; - } -} - /* * Async call for mounting an nfs share and geting the root filehandle */ @@ -875,7 +882,7 @@ int nfs_mount_async(struct nfs_context *nfs, const char *server, const char *exp data->cb = cb; data->private_data = private_data; - if (rpc_connect_async(nfs->rpc, server, 111, nfs_mount_1_cb, data) != 0) { + if (rpc_connect_program_async(nfs->rpc, server, MOUNT_PROGRAM, MOUNT_V3, nfs_mount_5_cb, data) != 0) { rpc_set_error(nfs->rpc, "Failed to start connection"); free_nfs_cb_data(data); return -1; @@ -895,6 +902,7 @@ static void nfs_lookup_path_1_cb(struct rpc_context *rpc, int status, void *comm struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; LOOKUP3res *res; + fattr3 *attr; assert(rpc->magic == RPC_CONTEXT_MAGIC); @@ -917,15 +925,17 @@ static void nfs_lookup_path_1_cb(struct rpc_context *rpc, int status, void *comm return; } - if (nfs_lookup_path_async_internal(nfs, data, &res->LOOKUP3res_u.resok.object) != 0) { - rpc_set_error(nfs->rpc, "Failed to create lookup pdu"); - data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); - free_nfs_cb_data(data); - return; - } + attr = res->LOOKUP3res_u.resok.obj_attributes.attributes_follow ? + &res->LOOKUP3res_u.resok.obj_attributes.post_op_attr_u.attributes : + NULL; + + /* This function will always invoke the callback and cleanup + * for failures. So no need to check the return value. + */ + nfs_lookup_path_async_internal(nfs, attr, data, &res->LOOKUP3res_u.resok.object); } -static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh) +static int nfs_lookup_path_async_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data, struct nfs_fh3 *fh) { char *path, *slash; LOOKUP3args args; @@ -964,11 +974,10 @@ static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb if (slash != NULL) { *slash = '/'; } - data->continue_cb(nfs, data); + data->continue_cb(nfs, attr, data); return 0; } - memset(&args, 0, sizeof(LOOKUP3args)); args.what.dir = *fh; args.what.name = path; @@ -1043,7 +1052,7 @@ static int nfs_normalize_path(struct nfs_context *nfs, char *path) /* /$ -> \0 */ len = strlen(path); - if (len >= 1) { + if (len > 1) { if (path[len - 1] == '/') { path[len - 1] = '\0'; len--; @@ -1085,9 +1094,45 @@ static int nfs_normalize_path(struct nfs_context *nfs, char *path) return 0; } +static void nfs_lookup_path_getattr_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + struct nfs_cb_data *data = private_data; + struct nfs_context *nfs = data->nfs; + GETATTR3res *res; + fattr3 *attr; + + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + if (status == RPC_STATUS_ERROR) { + data->cb(-EFAULT, nfs, command_data, data->private_data); + free_nfs_cb_data(data); + return; + } + if (status == RPC_STATUS_CANCEL) { + data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); + free_nfs_cb_data(data); + return; + } + + res = command_data; + if (res->status != NFS3_OK) { + rpc_set_error(nfs->rpc, "NFS: GETATTR of %s failed with %s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); + data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data); + free_nfs_cb_data(data); + return; + } + + attr = &res->GETATTR3res_u.resok.obj_attributes; + /* This function will always invoke the callback and cleanup + * for failures. So no need to check the return value. + */ + nfs_lookup_path_async_internal(nfs, attr, data, &nfs->rootfh); +} + static int nfs_lookuppath_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data, continue_func continue_cb, void *continue_data, void (*free_continue_data)(void *), int continue_int) { struct nfs_cb_data *data; + struct GETATTR3args args; if (path[0] == '\0') { path = "."; @@ -1133,18 +1178,27 @@ static int nfs_lookuppath_async(struct nfs_context *nfs, const char *path, nfs_c } data->path = data->saved_path; - - if (nfs_lookup_path_async_internal(nfs, data, &nfs->rootfh) != 0) { - /* return 0 here since the callback will be invoked if there is a failure */ + if (data->path[0]) { + /* This function will always invoke the callback and cleanup + * for failures. So no need to check the return value. + */ + nfs_lookup_path_async_internal(nfs, NULL, data, &nfs->rootfh); return 0; } + + /* We have a request for "", so just perform a GETATTR3 so we can + * return the attributes to the caller. + */ + memset(&args, 0, sizeof(GETATTR3args)); + args.object = nfs->rootfh; + if (rpc_nfs3_getattr_async(nfs->rpc, nfs_lookup_path_getattr_cb, &args, data) != 0) { + free_nfs_cb_data(data); + return -1; + } return 0; } - - - /* * Async stat() */ @@ -1195,8 +1249,8 @@ static void nfs_stat_1_cb(struct rpc_context *rpc, int status, void *command_dat st.st_rdev = 0; st.st_size = res->GETATTR3res_u.resok.obj_attributes.size; #ifndef WIN32 - st.st_blksize = 4096; - st.st_blocks = res->GETATTR3res_u.resok.obj_attributes.size / 4096; + st.st_blksize = NFS_BLKSIZE; + st.st_blocks = res->GETATTR3res_u.resok.obj_attributes.size / NFS_BLKSIZE; #endif//WIN32 st.st_atime = res->GETATTR3res_u.resok.obj_attributes.atime.seconds; st.st_mtime = res->GETATTR3res_u.resok.obj_attributes.mtime.seconds; @@ -1206,7 +1260,7 @@ static void nfs_stat_1_cb(struct rpc_context *rpc, int status, void *command_dat free_nfs_cb_data(data); } -static int nfs_stat_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_stat_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { struct GETATTR3args args; @@ -1286,7 +1340,7 @@ static void nfs_stat64_1_cb(struct rpc_context *rpc, int status, void *command_d free_nfs_cb_data(data); } -static int nfs_stat64_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_stat64_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { struct GETATTR3args args; @@ -1355,6 +1409,9 @@ static void nfs_open_trunc_cb(struct rpc_context *rpc, int status, void *command if (data->continue_int & O_SYNC) { nfsfh->is_sync = 1; } + if (data->continue_int & O_APPEND) { + nfsfh->is_append = 1; + } /* steal the filehandle */ nfsfh->fh = data->fh; @@ -1451,6 +1508,9 @@ static void nfs_open_cb(struct rpc_context *rpc, int status, void *command_data, if (data->continue_int & O_SYNC) { nfsfh->is_sync = 1; } + if (data->continue_int & O_APPEND) { + nfsfh->is_append = 1; + } /* steal the filehandle */ nfsfh->fh = data->fh; @@ -1460,7 +1520,7 @@ static void nfs_open_cb(struct rpc_context *rpc, int status, void *command_data, free_nfs_cb_data(data); } -static int nfs_open_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_open_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { int nfsmode = 0; ACCESS3args args; @@ -1504,7 +1564,7 @@ int nfs_open_async(struct nfs_context *nfs, const char *path, int flags, nfs_cb /* * Async chdir() */ -static int nfs_chdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_chdir_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { /* steal saved_path */ free(nfs->cwd); @@ -1564,25 +1624,30 @@ static void nfs_pread_mcb(struct rpc_context *rpc, int status, void *command_dat if (res->status != NFS3_OK) { rpc_set_error(nfs->rpc, "NFS: Read failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->error = 1; - } else { + } else { + uint64_t count = res->READ3res_u.resok.count; + + if (mdata->update_pos) + data->nfsfh->offset += count; + /* if we have more than one call or we have received a short read we need a reassembly buffer */ - if (data->num_calls || (res->READ3res_u.resok.count < mdata->count && !res->READ3res_u.resok.eof)) { + if (data->num_calls || (count < mdata->count && !res->READ3res_u.resok.eof)) { if (data->buffer == NULL) { - data->buffer = malloc(data->request_size); + data->buffer = malloc(data->count); if (data->buffer == NULL) { - rpc_set_error(nfs->rpc, "Out-Of-Memory: Failed to allocate reassembly buffer for %d bytes", (int)data->request_size); + rpc_set_error(nfs->rpc, "Out-Of-Memory: Failed to allocate reassembly buffer for %d bytes", (int)data->count); data->oom = 1; } } } - if (res->READ3res_u.resok.count > 0) { - if (res->READ3res_u.resok.count <= mdata->count) { + if (count > 0) { + if (count <= mdata->count) { /* copy data into reassembly buffer if we have one */ if (data->buffer != NULL) { - memcpy(&data->buffer[mdata->offset - data->start_offset], res->READ3res_u.resok.data.data_val, res->READ3res_u.resok.count); + memcpy(&data->buffer[mdata->offset - data->offset], res->READ3res_u.resok.data.data_val, count); } - if (data->max_offset < mdata->offset + res->READ3res_u.resok.count) { - data->max_offset = mdata->offset + res->READ3res_u.resok.count; + if (data->max_offset < mdata->offset + count) { + data->max_offset = mdata->offset + count; } } else { rpc_set_error(nfs->rpc, "NFS: Read overflow. Server has sent more data than requested!"); @@ -1590,15 +1655,15 @@ static void nfs_pread_mcb(struct rpc_context *rpc, int status, void *command_dat } } /* check if we have received a short read */ - if (res->READ3res_u.resok.count < mdata->count && !res->READ3res_u.resok.eof) { - if (res->READ3res_u.resok.count == 0) { + if (count < mdata->count && !res->READ3res_u.resok.eof) { + if (count == 0) { rpc_set_error(nfs->rpc, "NFS: Read failed. No bytes read and not at EOF!"); data->error = 1; } else { /* reissue reminder of this read request */ READ3args args; - mdata->offset += res->READ3res_u.resok.count; - mdata->count -= res->READ3res_u.resok.count; + mdata->offset += count; + mdata->count -= count; nfs_fill_READ3args(&args, data->nfsfh, mdata->offset, mdata->count); if (rpc_nfs3_read_async(nfs->rpc, nfs_pread_mcb, &args, mdata) == 0) { data->num_calls++; @@ -1634,17 +1699,37 @@ static void nfs_pread_mcb(struct rpc_context *rpc, int status, void *command_dat return; } - data->nfsfh->offset = data->max_offset; if (data->buffer) { - data->cb(data->max_offset - data->start_offset, nfs, data->buffer, data->private_data); + if (data->max_offset > data->org_offset + data->org_count) { + data->max_offset = data->org_offset + data->org_count; + } + data->cb(data->max_offset - data->org_offset, nfs, data->buffer + (data->org_offset - data->offset), data->private_data); } else { data->cb(res->READ3res_u.resok.count, nfs, res->READ3res_u.resok.data.data_val, data->private_data); } + data->nfsfh->ra.fh_offset = data->max_offset; + if (data->nfsfh->ra.cur_ra) { + free(data->nfsfh->ra.buf); + data->nfsfh->ra.buf = data->buffer; + data->nfsfh->ra.buf_offset = data->offset; + data->nfsfh->ra.buf_count = data->count; + data->nfsfh->ra.buf_ts = time(NULL); + data->buffer = NULL; + } free_nfs_cb_data(data); } -int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, nfs_cb cb, void *private_data) +static void nfs_ra_invalidate(struct nfsfh *nfsfh) { + free(nfsfh->ra.buf); + nfsfh->ra.buf = NULL; + nfsfh->ra.buf_offset = 0; + nfsfh->ra.buf_count = 0; + nfsfh->ra.buf_ts = time(NULL); + nfsfh->ra.cur_ra = NFS_BLKSIZE; +} + +static int nfs_pread_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, nfs_cb cb, void *private_data, int update_pos) { struct nfs_cb_data *data; @@ -1658,18 +1743,78 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offse data->cb = cb; data->private_data = private_data; data->nfsfh = nfsfh; - data->request_size = count; - - nfsfh->offset = offset; + data->org_offset = offset; + data->org_count = count; assert(data->num_calls == 0); + if (nfs->rpc->readahead && time(NULL) - nfsfh->ra.buf_ts > NFS_RA_TIMEOUT) { + /* readahead cache timeout */ + nfs_ra_invalidate(nfsfh); + } + + if (nfs->rpc->readahead) { + if (offset >= nfsfh->ra.last_offset && + offset - NFS_BLKSIZE <= nfsfh->ra.fh_offset + nfsfh->ra.cur_ra) { + if (nfs->rpc->readahead > nfsfh->ra.cur_ra) { + nfsfh->ra.cur_ra <<= 1; + } + } else { + nfsfh->ra.cur_ra = NFS_BLKSIZE; + } + + nfsfh->ra.last_offset = offset; + + if (nfsfh->ra.buf_offset <= offset && + nfsfh->ra.buf_offset + nfsfh->ra.buf_count >= offset + count) { + /* serve request completely from cache */ + data->buffer = malloc(count); + if (data->buffer == NULL) { + free_nfs_cb_data(data); + return -ENOMEM; + } + memcpy(data->buffer, nfsfh->ra.buf + (offset - nfsfh->ra.buf_offset), count); + data->cb(count, nfs, data->buffer, data->private_data); + nfsfh->ra.fh_offset = offset + count; + free_nfs_cb_data(data); + return 0; + } + + /* align start offset to blocksize */ + count += offset & (NFS_BLKSIZE - 1); + offset &= ~(NFS_BLKSIZE - 1); + + /* align end offset to blocksize and add readahead */ + count += nfsfh->ra.cur_ra - 1; + count &= ~(NFS_BLKSIZE - 1); + + data->buffer = malloc(count); + if (data->buffer == NULL) { + free_nfs_cb_data(data); + return -ENOMEM; + } + data->offset = offset; + data->count = count; + + if (nfsfh->ra.buf_count && nfsfh->ra.buf_offset <= offset && + nfsfh->ra.buf_offset + nfsfh->ra.buf_count >= offset) { + /* serve request partially from cache */ + size_t overlap = (nfsfh->ra.buf_offset + nfsfh->ra.buf_count) - offset; + if (overlap > count) count = overlap; + memcpy(data->buffer, nfsfh->ra.buf + (offset - nfsfh->ra.buf_offset), overlap); + offset += overlap; + count -= overlap; + } + } else { + data->offset = offset; + data->count = count; + } + + data->max_offset = offset; + /* chop requests into chunks of at most READMAX bytes if necessary. * we send all reads in parallel so that performance is still good. */ - data->max_offset = offset; - data->start_offset = offset; - do { uint64_t readcount = count; struct nfs_mcb_data *mdata; @@ -1693,6 +1838,7 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offse mdata->data = data; mdata->offset = offset; mdata->count = readcount; + mdata->update_pos = update_pos; nfs_fill_READ3args(&args, nfsfh, offset, readcount); @@ -1715,12 +1861,17 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offse return 0; } +int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, nfs_cb cb, void *private_data) +{ + return nfs_pread_async_internal(nfs, nfsfh, offset, count, cb, private_data, 0); +} + /* * Async read() */ int nfs_read_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, nfs_cb cb, void *private_data) { - return nfs_pread_async(nfs, nfsfh, nfsfh->offset, count, cb, private_data); + return nfs_pread_async_internal(nfs, nfsfh, nfsfh->offset, count, cb, private_data, 1); } @@ -1735,7 +1886,7 @@ static void nfs_fill_WRITE3args (WRITE3args *args, struct nfsfh *fh, uint64_t of args->file = fh->fh; args->offset = offset; args->count = count; - args->stable = fh->is_sync?FILE_SYNC:UNSTABLE; + args->stable = fh->is_sync ? FILE_SYNC : UNSTABLE; args->data.data_len = count; args->data.data_val = buf; } @@ -1766,17 +1917,23 @@ static void nfs_pwrite_mcb(struct rpc_context *rpc, int status, void *command_da rpc_set_error(nfs->rpc, "NFS: Write failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->error = 1; } else { - if (res->WRITE3res_u.resok.count < mdata->count) { - if (res->WRITE3res_u.resok.count == 0) { + uint64_t count = res->WRITE3res_u.resok.count; + + if (mdata->update_pos) + data->nfsfh->offset += count; + + if (count < mdata->count) { + if (count == 0) { rpc_set_error(nfs->rpc, "NFS: Write failed. No bytes written!"); data->error = 1; } else { /* reissue reminder of this write request */ WRITE3args args; - mdata->offset += res->WRITE3res_u.resok.count; - mdata->count -= res->WRITE3res_u.resok.count; + mdata->offset += count; + mdata->count -= count; + nfs_fill_WRITE3args(&args, data->nfsfh, mdata->offset, mdata->count, - &data->usrbuf[mdata->offset - data->start_offset]); + &data->usrbuf[mdata->offset - data->offset]); if (rpc_nfs3_write_async(nfs->rpc, nfs_pwrite_mcb, &args, mdata) == 0) { data->num_calls++; return; @@ -1786,9 +1943,9 @@ static void nfs_pwrite_mcb(struct rpc_context *rpc, int status, void *command_da } } } - if (res->WRITE3res_u.resok.count > 0) { - if (data->max_offset < mdata->offset + res->WRITE3res_u.resok.count) { - data->max_offset = mdata->offset + res->WRITE3res_u.resok.count; + if (count > 0) { + if (data->max_offset < mdata->offset + count) { + data->max_offset = mdata->offset + count; } } } @@ -1816,14 +1973,13 @@ static void nfs_pwrite_mcb(struct rpc_context *rpc, int status, void *command_da return; } - data->nfsfh->offset = data->max_offset; - data->cb(data->max_offset - data->start_offset, nfs, NULL, data->private_data); + data->cb(data->max_offset - data->offset, nfs, NULL, data->private_data); free_nfs_cb_data(data); } -int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, char *buf, nfs_cb cb, void *private_data) +static int nfs_pwrite_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, char *buf, nfs_cb cb, void *private_data, int update_pos) { struct nfs_cb_data *data; @@ -1839,8 +1995,6 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs data->nfsfh = nfsfh; data->usrbuf = buf; - nfsfh->offset = offset; - /* hello, clang-analyzer */ assert(data->num_calls == 0); @@ -1848,7 +2002,7 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs * we send all writes in parallel so that performance is still good. */ data->max_offset = offset; - data->start_offset = offset; + data->offset = offset; do { uint64_t writecount = count; @@ -1873,8 +2027,9 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs mdata->data = data; mdata->offset = offset; mdata->count = writecount; + mdata->update_pos = update_pos; - nfs_fill_WRITE3args(&args, nfsfh, offset, writecount, &buf[offset - data->start_offset]); + nfs_fill_WRITE3args(&args, nfsfh, offset, writecount, &buf[offset - data->offset]); if (rpc_nfs3_write_async(nfs->rpc, nfs_pwrite_mcb, &args, mdata) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send WRITE call for %s", data->path); @@ -1895,12 +2050,80 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs return 0; } +int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, char *buf, nfs_cb cb, void *private_data) +{ + return nfs_pwrite_async_internal(nfs, nfsfh, offset, count, buf, cb, private_data, 0); +} + /* * Async write() */ +static void nfs_write_append_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + struct nfs_cb_data *data = private_data; + struct nfs_context *nfs = data->nfs; + GETATTR3res *res; + + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + if (status == RPC_STATUS_ERROR) { + data->cb(-EFAULT, nfs, command_data, data->private_data); + free_nfs_cb_data(data); + return; + } + if (status == RPC_STATUS_CANCEL) { + data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); + free_nfs_cb_data(data); + return; + } + + res = command_data; + if (res->status != NFS3_OK) { + rpc_set_error(nfs->rpc, "NFS: GETATTR failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); + data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data); + free_nfs_cb_data(data); + return; + } + + if (nfs_pwrite_async_internal(nfs, data->nfsfh, res->GETATTR3res_u.resok.obj_attributes.size, data->count, data->usrbuf, data->cb, data->private_data, 1) != 0) { + data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); + free_nfs_cb_data(data); + return; + } + free_nfs_cb_data(data); +} + int nfs_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, char *buf, nfs_cb cb, void *private_data) { - return nfs_pwrite_async(nfs, nfsfh, nfsfh->offset, count, buf, cb, private_data); + nfs_ra_invalidate(nfsfh); + if (nfsfh->is_append) { + struct GETATTR3args args; + struct nfs_cb_data *data; + + data = malloc(sizeof(struct nfs_cb_data)); + if (data == NULL) { + rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure"); + return -1; + } + memset(data, 0, sizeof(struct nfs_cb_data)); + data->nfs = nfs; + data->cb = cb; + data->private_data = private_data; + data->nfsfh = nfsfh; + data->usrbuf = buf; + data->count = count; + + memset(&args, 0, sizeof(GETATTR3args)); + args.object = nfsfh->fh; + + if (rpc_nfs3_getattr_async(nfs->rpc, nfs_write_append_cb, &args, data) != 0) { + rpc_set_error(nfs->rpc, "out of memory: failed to send GETATTR"); + free_nfs_cb_data(data); + return -1; + } + return 0; + } + return nfs_pwrite_async_internal(nfs, nfsfh, nfsfh->offset, count, buf, cb, private_data, 1); } @@ -1916,6 +2139,7 @@ int nfs_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, voi free(nfsfh->fh.data.data_val); nfsfh->fh.data.data_val = NULL; } + free(nfsfh->ra.buf); free(nfsfh); cb(0, nfs, NULL, private_data); @@ -2089,7 +2313,7 @@ int nfs_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t l /* * Async truncate() */ -static int nfs_truncate_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_truncate_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { uint64_t offset = data->continue_int; struct nfsfh nfsfh; @@ -2160,7 +2384,7 @@ static void nfs_mkdir_cb(struct rpc_context *rpc, int status, void *command_data free_nfs_cb_data(data); } -static int nfs_mkdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_mkdir_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { char *str = data->continue_data; MKDIR3args args; @@ -2251,7 +2475,7 @@ static void nfs_rmdir_cb(struct rpc_context *rpc, int status, void *command_data free_nfs_cb_data(data); } -static int nfs_rmdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_rmdir_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { char *str = data->continue_data; RMDIR3args args; @@ -2396,7 +2620,7 @@ static void nfs_creat_1_cb(struct rpc_context *rpc, int status, void *command_da return; } -static int nfs_creat_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_creat_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { char *str = data->continue_data; CREATE3args args; @@ -2487,7 +2711,7 @@ static void nfs_unlink_cb(struct rpc_context *rpc, int status, void *command_dat free_nfs_cb_data(data); } -static int nfs_unlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_unlink_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { char *str = data->continue_data; struct REMOVE3args args; @@ -2586,7 +2810,7 @@ static void nfs_mknod_cb(struct rpc_context *rpc, int status, void *command_data free_nfs_cb_data(data); } -static int nfs_mknod_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_mknod_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { struct mknod_cb_data *cb_data = data->continue_data; char *str = cb_data->path; @@ -2734,6 +2958,7 @@ static void nfs_opendir3_cb(struct rpc_context *rpc, int status, void *command_d nfsdirent->ctime.tv_usec = attributes->ctime.nseconds/1000; nfsdirent->uid = attributes->uid; nfsdirent->gid = attributes->gid; + nfsdirent->nlink = attributes->nlink; } } @@ -2840,49 +3065,54 @@ static void nfs_opendir2_cb(struct rpc_context *rpc, int status, void *command_d return; } + if (res->READDIR3res_u.resok.dir_attributes.attributes_follow) + nfsdir->attr = res->READDIR3res_u.resok.dir_attributes.post_op_attr_u.attributes; + /* steal the dirhandle */ nfsdir->current = nfsdir->entries; - rdpe_cb_data = malloc(sizeof(struct rdpe_cb_data)); - rdpe_cb_data->getattrcount = 0; - rdpe_cb_data->status = RPC_STATUS_SUCCESS; - rdpe_cb_data->data = data; - for (nfsdirent = nfsdir->entries; nfsdirent; nfsdirent = nfsdirent->next) { - struct rdpe_lookup_cb_data *rdpe_lookup_cb_data; - LOOKUP3args args; - - rdpe_lookup_cb_data = malloc(sizeof(struct rdpe_lookup_cb_data)); - rdpe_lookup_cb_data->rdpe_cb_data = rdpe_cb_data; - rdpe_lookup_cb_data->nfsdirent = nfsdirent; - - memset(&args, 0, sizeof(LOOKUP3args)); - args.what.dir = data->fh; - args.what.name = nfsdirent->name; - - if (rpc_nfs3_lookup_async(nfs->rpc, nfs_opendir3_cb, &args, rdpe_lookup_cb_data) != 0) { - rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR LOOKUP call"); - - /* if we have already commands in flight, we cant just stop, we have to wait for the - * commands in flight to complete - */ - if (rdpe_cb_data->getattrcount > 0) { + if (nfsdir->entries) { + rdpe_cb_data = malloc(sizeof(struct rdpe_cb_data)); + rdpe_cb_data->getattrcount = 0; + rdpe_cb_data->status = RPC_STATUS_SUCCESS; + rdpe_cb_data->data = data; + for (nfsdirent = nfsdir->entries; nfsdirent; nfsdirent = nfsdirent->next) { + struct rdpe_lookup_cb_data *rdpe_lookup_cb_data; + LOOKUP3args args; + + rdpe_lookup_cb_data = malloc(sizeof(struct rdpe_lookup_cb_data)); + rdpe_lookup_cb_data->rdpe_cb_data = rdpe_cb_data; + rdpe_lookup_cb_data->nfsdirent = nfsdirent; + + memset(&args, 0, sizeof(LOOKUP3args)); + args.what.dir = data->fh; + args.what.name = nfsdirent->name; + + if (rpc_nfs3_lookup_async(nfs->rpc, nfs_opendir3_cb, &args, rdpe_lookup_cb_data) != 0) { + rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR LOOKUP call"); + + /* if we have already commands in flight, we cant just stop, we have to wait for the + * commands in flight to complete + */ + if (rdpe_cb_data->getattrcount > 0) { + nfs_free_nfsdir(nfsdir); + data->continue_data = NULL; + free_nfs_cb_data(data); + rdpe_cb_data->status = RPC_STATUS_ERROR; + free(rdpe_lookup_cb_data); + return; + } + + data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); nfs_free_nfsdir(nfsdir); data->continue_data = NULL; free_nfs_cb_data(data); - rdpe_cb_data->status = RPC_STATUS_ERROR; free(rdpe_lookup_cb_data); + free(rdpe_cb_data); return; } - - data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); - nfs_free_nfsdir(nfsdir); - data->continue_data = NULL; - free_nfs_cb_data(data); - free(rdpe_lookup_cb_data); - free(rdpe_cb_data); - return; + rdpe_cb_data->getattrcount++; } - rdpe_cb_data->getattrcount++; } } @@ -2969,6 +3199,7 @@ static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_da nfsdirent->ctime.tv_usec = entry->name_attributes.post_op_attr_u.attributes.ctime.nseconds/1000; nfsdirent->uid = entry->name_attributes.post_op_attr_u.attributes.uid; nfsdirent->gid = entry->name_attributes.post_op_attr_u.attributes.gid; + nfsdirent->nlink = entry->name_attributes.post_op_attr_u.attributes.nlink; } nfsdirent->next = nfsdir->entries; @@ -2998,6 +3229,9 @@ static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_da return; } + if (res->READDIRPLUS3res_u.resok.dir_attributes.attributes_follow) + nfsdir->attr = res->READDIRPLUS3res_u.resok.dir_attributes.post_op_attr_u.attributes; + /* steal the dirhandle */ data->continue_data = NULL; nfsdir->current = nfsdir->entries; @@ -3006,9 +3240,34 @@ static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_da free_nfs_cb_data(data); } -static int nfs_opendir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_opendir_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { READDIRPLUS3args args; + struct nfsdir *nfsdir = data->continue_data;; + struct nfsdir *cached; + + cached = nfs_dircache_find(nfs, &data->fh); + if (cached) { + if (attr && attr->mtime.seconds == cached->attr.mtime.seconds) { + cached->current = cached->entries; + data->cb(0, nfs, cached, data->private_data); + free_nfs_cb_data(data); + return 0; + } else { + /* cache must be stale */ + nfs_free_nfsdir(cached); + } + } + + nfsdir->fh.data.data_len = data->fh.data.data_len; + nfsdir->fh.data.data_val = malloc(nfsdir->fh.data.data_len); + if (nfsdir->fh.data.data_val == NULL) { + rpc_set_error(nfs->rpc, "OOM when allocating fh for nfsdir"); + data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); + free_nfs_cb_data(data); + return -1; + } + memcpy(nfsdir->fh.data.data_val, data->fh.data.data_val, data->fh.data.data_len); args.dir = data->fh; args.cookie = 0; @@ -3058,9 +3317,9 @@ struct nfsdirent *nfs_readdir(struct nfs_context *nfs _U_, struct nfsdir *nfsdir /* * closedir() */ -void nfs_closedir(struct nfs_context *nfs _U_, struct nfsdir *nfsdir) +void nfs_closedir(struct nfs_context *nfs, struct nfsdir *nfsdir) { - nfs_free_nfsdir(nfsdir); + nfs_dircache_add(nfs, nfsdir); } @@ -3081,7 +3340,7 @@ void nfs_getcwd(struct nfs_context *nfs, const char **cwd) struct lseek_cb_data { struct nfs_context *nfs; struct nfsfh *nfsfh; - uint64_t offset; + int64_t offset; nfs_cb cb; void *private_data; }; @@ -3091,6 +3350,7 @@ static void nfs_lseek_1_cb(struct rpc_context *rpc, int status, void *command_da GETATTR3res *res; struct lseek_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; + uint64_t size = 0; assert(rpc->magic == RPC_CONTEXT_MAGIC); @@ -3113,24 +3373,41 @@ static void nfs_lseek_1_cb(struct rpc_context *rpc, int status, void *command_da return; } - data->nfsfh->offset = data->offset + res->GETATTR3res_u.resok.obj_attributes.size; - data->cb(0, nfs, &data->nfsfh->offset, data->private_data); + size = res->GETATTR3res_u.resok.obj_attributes.size; + + if (data->offset < 0 && + (uint64_t)(-data->offset) > size) { + data->cb(-EINVAL, nfs, &data->nfsfh->offset, data->private_data); + } else { + data->nfsfh->offset = data->offset + size; + data->cb(0, nfs, &data->nfsfh->offset, data->private_data); + } + free(data); } -int nfs_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, int whence, nfs_cb cb, void *private_data) +int nfs_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int64_t offset, int whence, nfs_cb cb, void *private_data) { struct lseek_cb_data *data; struct GETATTR3args args; if (whence == SEEK_SET) { - nfsfh->offset = offset; - cb(0, nfs, &nfsfh->offset, private_data); + if (offset < 0) { + cb(-EINVAL, nfs, &nfsfh->offset, private_data); + } else { + nfsfh->offset = offset; + cb(0, nfs, &nfsfh->offset, private_data); + } return 0; } if (whence == SEEK_CUR) { - nfsfh->offset += offset; - cb(0, nfs, &nfsfh->offset, private_data); + if (offset < 0 && + nfsfh->offset < (uint64_t)(-offset)) { + cb(-EINVAL, nfs, &nfsfh->offset, private_data); + } else { + nfsfh->offset += offset; + cb(0, nfs, &nfsfh->offset, private_data); + } return 0; } @@ -3191,11 +3468,11 @@ static void nfs_statvfs_1_cb(struct rpc_context *rpc, int status, void *command_ return; } - svfs.f_bsize = 4096; - svfs.f_frsize = 4096; - svfs.f_blocks = res->FSSTAT3res_u.resok.tbytes/4096; - svfs.f_bfree = res->FSSTAT3res_u.resok.fbytes/4096; - svfs.f_bavail = res->FSSTAT3res_u.resok.abytes/4096; + svfs.f_bsize = NFS_BLKSIZE; + svfs.f_frsize = NFS_BLKSIZE; + svfs.f_blocks = res->FSSTAT3res_u.resok.tbytes/NFS_BLKSIZE; + svfs.f_bfree = res->FSSTAT3res_u.resok.fbytes/NFS_BLKSIZE; + svfs.f_bavail = res->FSSTAT3res_u.resok.abytes/NFS_BLKSIZE; svfs.f_files = res->FSSTAT3res_u.resok.tfiles; svfs.f_ffree = res->FSSTAT3res_u.resok.ffiles; #if !defined(ANDROID) @@ -3209,7 +3486,7 @@ static void nfs_statvfs_1_cb(struct rpc_context *rpc, int status, void *command_ free_nfs_cb_data(data); } -static int nfs_statvfs_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_statvfs_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { FSSTAT3args args; @@ -3271,7 +3548,7 @@ static void nfs_readlink_1_cb(struct rpc_context *rpc, int status, void *command free_nfs_cb_data(data); } -static int nfs_readlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_readlink_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { READLINK3args args; @@ -3333,7 +3610,7 @@ static void nfs_chmod_cb(struct rpc_context *rpc, int status, void *command_data free_nfs_cb_data(data); } -static int nfs_chmod_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_chmod_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { SETATTR3args args; @@ -3388,7 +3665,7 @@ int nfs_fchmod_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode, nfs } memcpy(data->fh.data.data_val, nfsfh->fh.data.data_val, data->fh.data.data_len); - if (nfs_chmod_continue_internal(nfs, data) != 0) { + if (nfs_chmod_continue_internal(nfs, NULL, data) != 0) { return -1; } @@ -3436,7 +3713,7 @@ struct nfs_chown_data { gid_t gid; }; -static int nfs_chown_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_chown_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { SETATTR3args args; struct nfs_chown_data *chown_data = data->continue_data; @@ -3522,7 +3799,7 @@ int nfs_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int } memcpy(data->fh.data.data_val, nfsfh->fh.data.data_val, data->fh.data.data_len); - if (nfs_chown_continue_internal(nfs, data) != 0) { + if (nfs_chown_continue_internal(nfs, NULL, data) != 0) { return -1; } @@ -3567,7 +3844,7 @@ static void nfs_utimes_cb(struct rpc_context *rpc, int status, void *command_dat free_nfs_cb_data(data); } -static int nfs_utimes_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_utimes_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { SETATTR3args args; struct timeval *utimes_data = data->continue_data; @@ -3705,7 +3982,7 @@ static void nfs_access_cb(struct rpc_context *rpc, int status, void *command_dat free_nfs_cb_data(data); } -static int nfs_access_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_access_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { int nfsmode = 0; ACCESS3args args; @@ -3802,7 +4079,7 @@ static void nfs_symlink_cb(struct rpc_context *rpc, int status, void *command_da free_nfs_cb_data(data); } -static int nfs_symlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_symlink_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { struct nfs_symlink_data *symlink_data = data->continue_data; SYMLINK3args args; @@ -3938,7 +4215,7 @@ static void nfs_rename_cb(struct rpc_context *rpc, int status, void *command_dat free_nfs_cb_data(data); } -static int nfs_rename_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_rename_continue_2_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { struct nfs_rename_data *rename_data = data->continue_data; RENAME3args args; @@ -3961,7 +4238,7 @@ static int nfs_rename_continue_2_internal(struct nfs_context *nfs, struct nfs_cb } -static int nfs_rename_continue_1_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_rename_continue_1_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { struct nfs_rename_data *rename_data = data->continue_data; char* newpath = strdup(rename_data->newpath); @@ -4108,7 +4385,7 @@ static void nfs_link_cb(struct rpc_context *rpc, int status, void *command_data, free_nfs_cb_data(data); } -static int nfs_link_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_link_continue_2_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { struct nfs_link_data *link_data = data->continue_data; LINK3args args; @@ -4131,7 +4408,7 @@ static int nfs_link_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_d } -static int nfs_link_continue_1_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +static int nfs_link_continue_1_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data) { struct nfs_link_data *link_data = data->continue_data; @@ -4233,6 +4510,10 @@ void nfs_set_gid(struct nfs_context *nfs, int gid) { rpc_set_gid(nfs->rpc, gid); } +void nfs_set_readahead(struct nfs_context *nfs, uint32_t v) { + rpc_set_readahead(nfs->rpc, v); +} + void nfs_set_error(struct nfs_context *nfs, char *error_string, ...) { va_list ap; @@ -4317,91 +4598,6 @@ static void mount_export_4_cb(struct rpc_context *rpc, int status, void *command } } -static void mount_export_3_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) -{ - struct mount_cb_data *data = private_data; - uint32_t mount_port; - - assert(rpc->magic == RPC_CONTEXT_MAGIC); - - if (status == RPC_STATUS_ERROR) { - data->cb(rpc, -EFAULT, command_data, data->private_data); - free_mount_cb_data(data); - return; - } - if (status == RPC_STATUS_CANCEL) { - data->cb(rpc, -EINTR, "Command was cancelled", data->private_data); - free_mount_cb_data(data); - return; - } - - mount_port = *(uint32_t *)command_data; - if (mount_port == 0) { - rpc_set_error(rpc, "RPC error. Mount program is not available"); - data->cb(rpc, -ENOENT, command_data, data->private_data); - free_mount_cb_data(data); - return; - } - - rpc_disconnect(rpc, "normal disconnect"); - if (rpc_connect_async(rpc, data->server, mount_port, mount_export_4_cb, data) != 0) { - data->cb(rpc, -ENOMEM, command_data, data->private_data); - free_mount_cb_data(data); - return; - } -} - -static void mount_export_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) -{ - struct mount_cb_data *data = private_data; - - assert(rpc->magic == RPC_CONTEXT_MAGIC); - - if (status == RPC_STATUS_ERROR) { - data->cb(rpc, -EFAULT, command_data, data->private_data); - free_mount_cb_data(data); - return; - } - if (status == RPC_STATUS_CANCEL) { - data->cb(rpc, -EINTR, "Command was cancelled", data->private_data); - free_mount_cb_data(data); - return; - } - - if (rpc_pmap_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, IPPROTO_TCP, mount_export_3_cb, private_data) != 0) { - data->cb(rpc, -ENOMEM, command_data, data->private_data); - free_mount_cb_data(data); - return; - } -} - -static void mount_export_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) -{ - struct mount_cb_data *data = private_data; - - assert(rpc->magic == RPC_CONTEXT_MAGIC); - - /* Dont want any more callbacks even if the socket is closed */ - rpc->connect_cb = NULL; - - if (status == RPC_STATUS_ERROR) { - data->cb(rpc, -EFAULT, command_data, data->private_data); - free_mount_cb_data(data); - return; - } - if (status == RPC_STATUS_CANCEL) { - data->cb(rpc, -EINTR, "Command was cancelled", data->private_data); - free_mount_cb_data(data); - return; - } - - if (rpc_pmap_null_async(rpc, mount_export_2_cb, data) != 0) { - data->cb(rpc, -ENOMEM, command_data, data->private_data); - free_mount_cb_data(data); - return; - } -} - int mount_getexports_async(struct rpc_context *rpc, const char *server, rpc_cb cb, void *private_data) { struct mount_cb_data *data; @@ -4420,7 +4616,8 @@ int mount_getexports_async(struct rpc_context *rpc, const char *server, rpc_cb c free_mount_cb_data(data); return -1; } - if (rpc_connect_async(rpc, data->server, 111, mount_export_1_cb, data) != 0) { + if (rpc_connect_program_async(rpc, data->server, MOUNT_PROGRAM, MOUNT_V3, mount_export_4_cb, data) != 0) { + rpc_set_error(rpc, "Failed to start connection"); free_mount_cb_data(data); return -1; } diff --git a/lib/pdu.c b/lib/pdu.c index 5def0bc..4d487b7 100644 --- a/lib/pdu.c +++ b/lib/pdu.c @@ -49,6 +49,41 @@ #include "libnfs-raw.h" #include "libnfs-private.h" +void rpc_reset_queue(struct rpc_queue *q) +{ + q->head = NULL; + q->tail = NULL; +} + +/* + * Push to the tail end of the queue + */ +void rpc_enqueue(struct rpc_queue *q, struct rpc_pdu *pdu) +{ + if (q->head == NULL) + q->head = pdu; + else + q->tail->next = pdu; + q->tail = pdu; + pdu->next = NULL; +} + +/* + * Push to the front/head of the queue + */ +void rpc_return_to_queue(struct rpc_queue *q, struct rpc_pdu *pdu) +{ + pdu->next = q->head; + q->head = pdu; + if (q->tail == NULL) + q->tail = pdu; +} + +unsigned int rpc_hash_xid(uint32_t xid) +{ + return (xid * 7919) % HASHES; +} + struct rpc_pdu *rpc_allocate_pdu(struct rpc_context *rpc, int program, int version, int procedure, rpc_cb cb, void *private_data, zdrproc_t zdr_decode_fn, int zdr_decode_bufsize) { struct rpc_pdu *pdu; @@ -129,13 +164,17 @@ int rpc_queue_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu) /* for udp we dont queue, we just send it straight away */ if (rpc->is_udp != 0) { + unsigned int hash; + // XXX add a rpc->udp_dest_sock_size and get rid of sys/socket.h and netinet/in.h if (sendto(rpc->fd, rpc->encodebuf, size, MSG_DONTWAIT, rpc->udp_dest, sizeof(struct sockaddr_in)) < 0) { rpc_set_error(rpc, "Sendto failed with errno %s", strerror(errno)); rpc_free_pdu(rpc, pdu); return -1; } - SLIST_ADD_END(&rpc->waitpdu, pdu); + + hash = rpc_hash_xid(pdu->xid); + rpc_enqueue(&rpc->waitpdu[hash], pdu); return 0; } @@ -153,7 +192,7 @@ int rpc_queue_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu) } memcpy(pdu->outdata.data, rpc->encodebuf, pdu->outdata.size); - SLIST_ADD_END(&rpc->outqueue, pdu); + rpc_enqueue(&rpc->outqueue, pdu); return 0; } @@ -237,9 +276,11 @@ static int rpc_process_reply(struct rpc_context *rpc, struct rpc_pdu *pdu, ZDR * int rpc_process_pdu(struct rpc_context *rpc, char *buf, int size) { - struct rpc_pdu *pdu; + struct rpc_pdu *pdu, *prev_pdu; + struct rpc_queue *q; ZDR zdr; int pos, recordmarker = 0; + unsigned int hash; uint32_t xid; char *reasbuf = NULL; @@ -302,12 +343,26 @@ int rpc_process_pdu(struct rpc_context *rpc, char *buf, int size) } zdr_setpos(&zdr, pos); - for (pdu=rpc->waitpdu; pdu; pdu=pdu->next) { + /* Look up the transaction in a hash table of our requests */ + hash = rpc_hash_xid(xid); + q = &rpc->waitpdu[hash]; + + /* Follow the hash chain. Linear traverse singly-linked list, + * but track previous entry for optimised removal */ + prev_pdu = NULL; + for (pdu=q->head; pdu; pdu=pdu->next) { if (pdu->xid != xid) { + prev_pdu = pdu; continue; } if (rpc->is_udp == 0 || rpc->is_broadcast == 0) { - SLIST_REMOVE(&rpc->waitpdu, pdu); + /* Singly-linked but we track head and tail */ + if (pdu == q->head) + q->head = pdu->next; + if (pdu == q->tail) + q->tail = prev_pdu; + if (prev_pdu != NULL) + prev_pdu->next = pdu->next; } if (rpc_process_reply(rpc, pdu, &zdr) != 0) { rpc_set_error(rpc, "rpc_procdess_reply failed"); diff --git a/lib/socket.c b/lib/socket.c index 055109a..f973f01 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -80,7 +80,6 @@ #include "win32_errnowrapper.h" #endif - static int rpc_reconnect_requeue(struct rpc_context *rpc); static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_storage *s); @@ -96,6 +95,14 @@ static void set_nonblocking(int fd) #endif //FIXME } +static void set_nolinger(int fd) +{ + struct linger lng; + lng.l_onoff = 1; + lng.l_linger = 0; + setsockopt(fd, SOL_SOCKET, SO_LINGER, &lng, sizeof(lng)); +} + #ifdef HAVE_NETINET_TCP_H int set_tcp_sockopt(int sockfd, int optname, int value) { @@ -123,6 +130,11 @@ int rpc_get_fd(struct rpc_context *rpc) return rpc->fd; } +static int rpc_has_queue(struct rpc_queue *q) +{ + return q->head != NULL; +} + int rpc_which_events(struct rpc_context *rpc) { int events; @@ -136,7 +148,7 @@ int rpc_which_events(struct rpc_context *rpc) return POLLIN; } - if (rpc->outqueue) { + if (rpc_has_queue(&rpc->outqueue)) { events |= POLLOUT; } return events; @@ -145,6 +157,7 @@ int rpc_which_events(struct rpc_context *rpc) static int rpc_write_to_socket(struct rpc_context *rpc) { int32_t count; + struct rpc_pdu *pdu; assert(rpc->magic == RPC_CONTEXT_MAGIC); @@ -153,12 +166,12 @@ static int rpc_write_to_socket(struct rpc_context *rpc) return -1; } - while (rpc->outqueue != NULL) { + while ((pdu = rpc->outqueue.head) != NULL) { int64_t total; - total = rpc->outqueue->outdata.size; + total = pdu->outdata.size; - count = send(rpc->fd, rpc->outqueue->outdata.data + rpc->outqueue->written, total - rpc->outqueue->written, 0); + count = send(rpc->fd, pdu->outdata.data + pdu->written, total - pdu->written, 0); if (count == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { return 0; @@ -167,12 +180,16 @@ static int rpc_write_to_socket(struct rpc_context *rpc) return -1; } - rpc->outqueue->written += count; - if (rpc->outqueue->written == total) { - struct rpc_pdu *pdu = rpc->outqueue; + pdu->written += count; + if (pdu->written == total) { + unsigned int hash; - SLIST_REMOVE(&rpc->outqueue, pdu); - SLIST_ADD_END(&rpc->waitpdu, pdu); + rpc->outqueue.head = pdu->next; + if (pdu->next == NULL) + rpc->outqueue.tail = NULL; + + hash = rpc_hash_xid(pdu->xid); + rpc_enqueue(&rpc->waitpdu[hash], pdu); } } return 0; @@ -369,7 +386,7 @@ int rpc_service(struct rpc_context *rpc, int revents) } } - if (revents & POLLOUT && rpc->outqueue != NULL) { + if (revents & POLLOUT && rpc_has_queue(&rpc->outqueue)) { if (rpc_write_to_socket(rpc) != 0) { rpc_set_error(rpc, "write to socket failed"); return -1; @@ -418,6 +435,15 @@ static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_s if (rpc->tcp_syncnt != RPC_PARAM_UNDEFINED) { set_tcp_sockopt(rpc->fd, TCP_SYNCNT, rpc->tcp_syncnt); } +#endif + break; + case AF_INET6: + socksize = sizeof(struct sockaddr_in6); + rpc->fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); +#ifdef HAVE_NETINET_TCP_H + if (rpc->tcp_syncnt != RPC_PARAM_UNDEFINED) { + set_tcp_sockopt(rpc->fd, TCP_SYNCNT, rpc->tcp_syncnt); + } #endif break; default: @@ -449,7 +475,7 @@ static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_s * binding will usually succeed. */ { - struct sockaddr_in sin; + struct sockaddr_storage ss; static int portOfs = 0; const int firstPort = 512; /* >= 512 according to Sun docs */ const int portCount = IPPORT_RESERVED - firstPort; @@ -466,12 +492,26 @@ static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_s /* skip well-known ports */ if (!getservbyport(port, "tcp")) { - memset(&sin, 0, sizeof(sin)); - sin.sin_port = port; - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = 0; + memset(&ss, 0, sizeof(ss)); - rc = bind(rpc->fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)); + switch (s->ss_family) { + case AF_INET: + ((struct sockaddr_in *)&ss)->sin_port = port; + ((struct sockaddr_in *)&ss)->sin_family = AF_INET; +#ifdef HAVE_SOCKADDR_LEN + ((struct sockaddr_in *)&ss)->sin_len = sizeof(struct sockaddr_in); +#endif + break; + case AF_INET6: + ((struct sockaddr_in6 *)&ss)->sin6_port = port; + ((struct sockaddr_in6 *)&ss)->sin6_family = AF_INET6; +#ifdef HAVE_SOCKADDR_LEN + ((struct sockaddr_in6 *)&ss)->sin6_len = sizeof(struct sockaddr6_in); +#endif + break; + } + + rc = bind(rpc->fd, (struct sockaddr *)&ss, socksize); #if !defined(WIN32) /* we got EACCES, so don't try again */ if (rc != 0 && errno == EACCES) @@ -482,6 +522,7 @@ static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_s } set_nonblocking(rpc->fd); + set_nolinger(rpc->fd); if (connect(rpc->fd, (struct sockaddr *)s, socksize) != 0 && errno != EINPROGRESS) { rpc_set_error(rpc, "connect() to server failed. %s(%d)", strerror(errno), errno); @@ -493,7 +534,7 @@ static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_s int rpc_connect_async(struct rpc_context *rpc, const char *server, int port, rpc_cb cb, void *private_data) { - struct sockaddr_in *sin = (struct sockaddr_in *)&rpc->s; + struct addrinfo *ai = NULL; assert(rpc->magic == RPC_CONTEXT_MAGIC); @@ -509,18 +550,27 @@ int rpc_connect_async(struct rpc_context *rpc, const char *server, int port, rpc rpc->auto_reconnect = 0; - sin->sin_family = AF_INET; - sin->sin_port = htons(port); - if (inet_pton(AF_INET, server, &sin->sin_addr) != 1) { - rpc_set_error(rpc, "Not a valid server ip address"); + if (getaddrinfo(server, NULL, NULL, &ai) != 0) { + rpc_set_error(rpc, "Invalid address:%s. " + "Can not resolv into IPv4/v6 structure.", server); return -1; - } - + } - switch (rpc->s.ss_family) { + switch (ai->ai_family) { case AF_INET: + ((struct sockaddr_in *)&rpc->s)->sin_family = ai->ai_family; + ((struct sockaddr_in *)&rpc->s)->sin_port = htons(port); + ((struct sockaddr_in *)&rpc->s)->sin_addr = ((struct sockaddr_in *)(ai->ai_addr))->sin_addr; +#ifdef HAVE_SOCKADDR_LEN + ((struct sockaddr_in *)&rpc->s)->sin_len = sizeof(struct sockaddr_in); +#endif + break; + case AF_INET6: + ((struct sockaddr_in6 *)&rpc->s)->sin6_family = ai->ai_family; + ((struct sockaddr_in6 *)&rpc->s)->sin6_port = htons(port); + ((struct sockaddr_in6 *)&rpc->s)->sin6_addr = ((struct sockaddr_in6 *)(ai->ai_addr))->sin6_addr; #ifdef HAVE_SOCKADDR_LEN - sin->sin_len = sizeof(struct sockaddr_in); + ((struct sockaddr_in6 *)&rpc->s)->sin6_len = sizeof(struct sockaddr_in6); #endif break; } @@ -528,6 +578,8 @@ int rpc_connect_async(struct rpc_context *rpc, const char *server, int port, rpc rpc->connect_cb = cb; rpc->connect_data = private_data; + freeaddrinfo(ai); + if (rpc_connect_sockaddr_async(rpc, &rpc->s) != 0) { return -1; } @@ -570,6 +622,7 @@ static void reconnect_cb(struct rpc_context *rpc, int status, void *data _U_, vo static int rpc_reconnect_requeue(struct rpc_context *rpc) { struct rpc_pdu *pdu; + unsigned int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); @@ -583,11 +636,15 @@ static int rpc_reconnect_requeue(struct rpc_context *rpc) /* socket is closed so we will not get any replies to any commands * in flight. Move them all over from the waitpdu queue back to the out queue */ - for (pdu=rpc->waitpdu; pdu; pdu=pdu->next) { - SLIST_REMOVE(&rpc->waitpdu, pdu); - SLIST_ADD(&rpc->outqueue, pdu); - /* we have to re-send the whole pdu again */ - pdu->written = 0; + for (i = 0; i < HASHES; i++) { + struct rpc_queue *q = &rpc->waitpdu[i]; + + for (pdu=q->head; pdu; pdu=pdu->next) { + rpc_return_to_queue(&rpc->outqueue, pdu); + /* we have to re-send the whole pdu again */ + pdu->written = 0; + } + rpc_reset_queue(q); } if (rpc->auto_reconnect != 0) { @@ -697,14 +754,19 @@ int rpc_queue_length(struct rpc_context *rpc) { int i=0; struct rpc_pdu *pdu; + unsigned int n; assert(rpc->magic == RPC_CONTEXT_MAGIC); - for(pdu = rpc->outqueue; pdu; pdu = pdu->next) { + for(pdu = rpc->outqueue.head; pdu; pdu = pdu->next) { i++; } - for(pdu = rpc->waitpdu; pdu; pdu = pdu->next) { - i++; + + for (n = 0; n < HASHES; n++) { + struct rpc_queue *q = &rpc->waitpdu[n]; + + for(pdu = q->head; pdu; pdu = pdu->next) + i++; } return i; } diff --git a/mount/Makefile.am b/mount/Makefile.am index 138d031..de7fdbd 100644 --- a/mount/Makefile.am +++ b/mount/Makefile.am @@ -17,6 +17,8 @@ mount-stamp : mount.x rm -f $(mount_GENERATED) touch mount-stamp -compile_rpc: - rpcgen -h mount.x | sed -e "s/#include //" | sed -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" > libnfs-raw-mount.h - rpcgen -c mount.x | sed -e "s/#include \".*mount.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-mount.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" > libnfs-raw-mount.c +compile_rpc: + cat mount.x | head -29 >libnfs-raw-mount.h + rpcgen -h mount.x | sed -e "s/#include //" | sed -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" >> libnfs-raw-mount.h + cat mount.x | head -29 >libnfs-raw-mount.c + rpcgen -c mount.x | sed -e "s/#include \".*mount.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-mount.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" >> libnfs-raw-mount.c diff --git a/mount/libnfs-raw-mount.c b/mount/libnfs-raw-mount.c index 81fae00..0a70d43 100644 --- a/mount/libnfs-raw-mount.c +++ b/mount/libnfs-raw-mount.c @@ -1,3 +1,32 @@ +/* +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + /* * Please do not edit this file. * It was generated using rpcgen. diff --git a/mount/libnfs-raw-mount.h b/mount/libnfs-raw-mount.h index 1cb2775..9f07d31 100644 --- a/mount/libnfs-raw-mount.h +++ b/mount/libnfs-raw-mount.h @@ -1,3 +1,32 @@ +/* +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + /* * Please do not edit this file. * It was generated using rpcgen. @@ -6,7 +35,8 @@ #ifndef _MOUNT_H_RPCGEN #define _MOUNT_H_RPCGEN -#include + + #ifdef __cplusplus extern "C" { diff --git a/mount/mount.x b/mount/mount.x index 10e6a1f..62b4e39 100644 --- a/mount/mount.x +++ b/mount/mount.x @@ -1,4 +1,31 @@ -/* copied from RFC1813 and RFC1094 */ +/* +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ const MNTPATHLEN = 1024; /* Maximum bytes in a path name */ const MNTNAMLEN = 255; /* Maximum bytes in a name */ diff --git a/nfs/Makefile.am b/nfs/Makefile.am index aad66ce..2177519 100644 --- a/nfs/Makefile.am +++ b/nfs/Makefile.am @@ -18,5 +18,7 @@ nfs-stamp : nfs.x touch nfs-stamp compile_rpc: - rpcgen -h nfs.x | sed -e "s/#include //" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/#define _NFS_H_RPCGEN/#define _NFS_H_RPCGEN\n#include /g" -e "s/#define NFS3_COOKIEVERFSIZE 8/#define NFS3_COOKIEVERFSIZE 8\n\n#if defined(ANDROID)\ntypedef long long int quad_t;\ntypedef long long unsigned u_quad_t;\n#endif\n#if defined(WIN32)\ntypedef long long int quad_t;\ntypedef long long unsigned u_quad_t;\n#endif/g" > libnfs-raw-nfs.h - rpcgen -c nfs.x | sed -e "s/#include \".*nfs.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-nfs.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" > libnfs-raw-nfs.c + cat nfs.x | head -29 >libnfs-raw-nfs.h + rpcgen -h nfs.x | sed -e "s/#include //" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/#define _NFS_H_RPCGEN/#define _NFS_H_RPCGEN\n#include /g" -e "s/#define NFS3_COOKIEVERFSIZE 8/#define NFS3_COOKIEVERFSIZE 8\n\n#if defined(ANDROID)\ntypedef long long int quad_t;\ntypedef long long unsigned u_quad_t;\n#endif\n#if defined(WIN32)\ntypedef long long int quad_t;\ntypedef long long unsigned u_quad_t;\n#endif/g" >> libnfs-raw-nfs.h + cat nfs.x | head -29 >libnfs-raw-nfs.c + rpcgen -c nfs.x | sed -e "s/#include \".*nfs.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-nfs.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" >> libnfs-raw-nfs.c diff --git a/nfs/libnfs-raw-nfs.c b/nfs/libnfs-raw-nfs.c index 04e914d..30d05a5 100644 --- a/nfs/libnfs-raw-nfs.c +++ b/nfs/libnfs-raw-nfs.c @@ -1,3 +1,32 @@ +/* +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + /* * Please do not edit this file. * It was generated using rpcgen. @@ -17,24 +46,13 @@ zdr_cookieverf3 (ZDR *zdrs, cookieverf3 objp) return TRUE; } -bool_t -zdr_uint64 (ZDR *zdrs, uint64 *objp) -{ - register int32_t *buf; - buf = NULL; - - if (!zdr_u_quad_t (zdrs, objp)) - return FALSE; - return TRUE; -} - bool_t zdr_cookie3 (ZDR *zdrs, cookie3 *objp) { register int32_t *buf; buf = NULL; - if (!zdr_uint64 (zdrs, objp)) + if (!zdr_u_quad_t (zdrs, objp)) return FALSE; return TRUE; } @@ -124,7 +142,7 @@ zdr_size3 (ZDR *zdrs, size3 *objp) register int32_t *buf; buf = NULL; - if (!zdr_uint64 (zdrs, objp)) + if (!zdr_u_quad_t (zdrs, objp)) return FALSE; return TRUE; } @@ -135,7 +153,7 @@ zdr_fileid3 (ZDR *zdrs, fileid3 *objp) register int32_t *buf; buf = NULL; - if (!zdr_uint64 (zdrs, objp)) + if (!zdr_u_quad_t (zdrs, objp)) return FALSE; return TRUE; } @@ -188,7 +206,7 @@ zdr_fattr3 (ZDR *zdrs, fattr3 *objp) return FALSE; if (!zdr_specdata3 (zdrs, &objp->rdev)) return FALSE; - if (!zdr_uint64 (zdrs, &objp->fsid)) + if (!zdr_u_quad_t (zdrs, &objp->fsid)) return FALSE; if (!zdr_fileid3 (zdrs, &objp->fileid)) return FALSE; @@ -250,7 +268,7 @@ zdr_offset3 (ZDR *zdrs, offset3 *objp) register int32_t *buf; buf = NULL; - if (!zdr_uint64 (zdrs, objp)) + if (!zdr_u_quad_t (zdrs, objp)) return FALSE; return TRUE; } diff --git a/nfs/libnfs-raw-nfs.h b/nfs/libnfs-raw-nfs.h index 8eb3b2e..4b4c874 100644 --- a/nfs/libnfs-raw-nfs.h +++ b/nfs/libnfs-raw-nfs.h @@ -1,3 +1,32 @@ +/* +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + /* * Please do not edit this file. * It was generated using rpcgen. @@ -30,9 +59,7 @@ typedef long long unsigned u_quad_t; typedef char cookieverf3[NFS3_COOKIEVERFSIZE]; -typedef u_quad_t uint64; - -typedef uint64 cookie3; +typedef u_quad_t cookie3; struct nfs_fh3 { struct { @@ -67,9 +94,9 @@ typedef u_int uid3; typedef u_int gid3; -typedef uint64 size3; +typedef u_quad_t size3; -typedef uint64 fileid3; +typedef u_quad_t fileid3; struct specdata3 { u_int specdata1; @@ -92,7 +119,7 @@ struct fattr3 { size3 size; size3 used; specdata3 rdev; - uint64 fsid; + u_quad_t fsid; fileid3 fileid; nfstime3 atime; nfstime3 mtime; @@ -148,7 +175,7 @@ enum stable_how { }; typedef enum stable_how stable_how; -typedef uint64 offset3; +typedef u_quad_t offset3; typedef u_int count3; @@ -1611,7 +1638,6 @@ extern int nfsacl_program_3_freeresult (); #if defined(__STDC__) || defined(__cplusplus) extern bool_t zdr_cookieverf3 (ZDR *, cookieverf3); -extern bool_t zdr_uint64 (ZDR *, uint64*); extern bool_t zdr_cookie3 (ZDR *, cookie3*); extern bool_t zdr_nfs_fh3 (ZDR *, nfs_fh3*); extern bool_t zdr_filename3 (ZDR *, filename3*); @@ -1799,7 +1825,6 @@ extern bool_t zdr_SETACL3res (ZDR *, SETACL3res*); #else /* K&R C */ extern bool_t zdr_cookieverf3 (); -extern bool_t zdr_uint64 (); extern bool_t zdr_cookie3 (); extern bool_t zdr_nfs_fh3 (); extern bool_t zdr_filename3 (); diff --git a/nfs/nfs.x b/nfs/nfs.x index cc19757..ca48c03 100644 --- a/nfs/nfs.x +++ b/nfs/nfs.x @@ -1,4 +1,31 @@ -/* NFS part from rfc 1813, NFSACL part is from wireshark sources */ +/* +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ /* * NFS v3 Definitions @@ -10,16 +37,7 @@ const NFS3_COOKIEVERFSIZE = 8; typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE]; -/*unsigned hyper can be overridden by giving rpcgen -DU_INT64_PLATTFORM_TYPE=" - where rpcgen doesn't know anything about hyper - default to unsigned hyper as of rfc 1813 */ -#ifndef U_INT64_PLATTFORM_TYPE -#define U_INT64_PLATTFORM_TYPE unsigned hyper -#endif/*U_INT64_PLATTFORM_TYPE*/ - -typedef U_INT64_PLATTFORM_TYPE uint64; - -typedef uint64 cookie3; +typedef u_quad_t cookie3; struct nfs_fh3 { opaque data; @@ -48,9 +66,9 @@ typedef unsigned int uid3; typedef unsigned int gid3; -typedef uint64 size3; +typedef u_quad_t size3; -typedef uint64 fileid3; +typedef u_quad_t fileid3; struct specdata3 { unsigned int specdata1; @@ -71,7 +89,7 @@ struct fattr3 { size3 size; size3 used; specdata3 rdev; - uint64 fsid; + u_quad_t fsid; fileid3 fileid; nfstime3 atime; nfstime3 mtime; @@ -124,7 +142,7 @@ enum stable_how { FILE_SYNC = 2 }; -typedef uint64 offset3; +typedef u_quad_t offset3; typedef unsigned int count3; diff --git a/nlm/Makefile.am b/nlm/Makefile.am index 5b6d02f..0cc563d 100644 --- a/nlm/Makefile.am +++ b/nlm/Makefile.am @@ -18,5 +18,7 @@ nlm-stamp : nlm.x touch nlm-stamp compile_rpc: - rpcgen -h nlm.x | sed -e "s/#include //" | sed -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" > libnfs-raw-nlm.h - rpcgen -c nlm.x | sed -e "s/#include \".*nlm.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-nlm.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" > libnfs-raw-nlm.c + cat nlm.x | head -29 >libnfs-raw-nlm.h + rpcgen -h nlm.x | sed -e "s/#include //" | sed -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" >> libnfs-raw-nlm.h + cat nlm.x | head -29 >libnfs-raw-nlm.c + rpcgen -c nlm.x | sed -e "s/#include \".*nlm.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-nlm.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" >> libnfs-raw-nlm.c diff --git a/nlm/libnfs-raw-nlm.c b/nlm/libnfs-raw-nlm.c index 808924a..7930261 100644 --- a/nlm/libnfs-raw-nlm.c +++ b/nlm/libnfs-raw-nlm.c @@ -1,3 +1,32 @@ +/* +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + /* * Please do not edit this file. * It was generated using rpcgen. diff --git a/nlm/libnfs-raw-nlm.h b/nlm/libnfs-raw-nlm.h index 6437aa4..eb73c1a 100644 --- a/nlm/libnfs-raw-nlm.h +++ b/nlm/libnfs-raw-nlm.h @@ -1,3 +1,32 @@ +/* +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + /* * Please do not edit this file. * It was generated using rpcgen. @@ -6,20 +35,13 @@ #ifndef _NLM_H_RPCGEN #define _NLM_H_RPCGEN -#include + + #ifdef __cplusplus extern "C" { #endif -#if defined(ANDROID) -typedef long long int quad_t; -typedef long long unsigned u_quad_t; -#endif -#if defined(WIN32) -typedef long long int quad_t; -typedef long long unsigned u_quad_t; -#endif struct nlm_fh4 { struct { diff --git a/nlm/nlm.x b/nlm/nlm.x index 8ec6614..6cd39c2 100644 --- a/nlm/nlm.x +++ b/nlm/nlm.x @@ -1,6 +1,31 @@ -/* based on rfc1813 and wireshark */ - -typedef unsigned hyper uint64; +/* +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ struct nlm_fh4 { opaque data<>; @@ -29,8 +54,8 @@ struct nlm4_holder { bool exclusive; unsigned int svid; nlm4_oh oh; - uint64 l_offset; - uint64 l_len; + u_quad_t l_offset; + u_quad_t l_len; }; const NLM_MAXNAME = 256; @@ -39,8 +64,8 @@ struct nlm4_lock { struct nlm_fh4 fh; nlm4_oh oh; unsigned int svid; - uint64 l_offset; - uint64 l_len; + u_quad_t l_offset; + u_quad_t l_len; }; struct nlm4_share { diff --git a/nsm/Makefile.am b/nsm/Makefile.am index 6362ddb..3bf06a8 100644 --- a/nsm/Makefile.am +++ b/nsm/Makefile.am @@ -18,5 +18,7 @@ nsm-stamp : nsm.x touch nsm-stamp compile_rpc: - rpcgen -h nsm.x | sed -e "s/#include //" | sed -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" > libnfs-raw-nsm.h - rpcgen -c nsm.x | sed -e "s/#include \".*nsm.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-nsm.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" > libnfs-raw-nsm.c + cat nsm.x | head -29 >libnfs-raw-nsm.h + rpcgen -h nsm.x | sed -e "s/#include //" | sed -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" >> libnfs-raw-nsm.h + cat nsm.x | head -29 >libnfs-raw-nsm.c + rpcgen -c nsm.x | sed -e "s/#include \".*nsm.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-nsm.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" >> libnfs-raw-nsm.c diff --git a/nsm/libnfs-raw-nsm.c b/nsm/libnfs-raw-nsm.c index cee4d89..d3be832 100644 --- a/nsm/libnfs-raw-nsm.c +++ b/nsm/libnfs-raw-nsm.c @@ -1,3 +1,32 @@ +/* +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + /* * Please do not edit this file. * It was generated using rpcgen. @@ -90,6 +119,7 @@ zdr_NSM1_MONargs (ZDR *zdrs, NSM1_MONargs *objp) register int32_t *buf; buf = NULL; + int i; if (!zdr_nsm_mon_id (zdrs, &objp->mon_id)) return FALSE; if (!zdr_opaque (zdrs, objp->priv, 16)) diff --git a/nsm/libnfs-raw-nsm.h b/nsm/libnfs-raw-nsm.h index b68a1bd..d656f3f 100644 --- a/nsm/libnfs-raw-nsm.h +++ b/nsm/libnfs-raw-nsm.h @@ -1,3 +1,32 @@ +/* +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + /* * Please do not edit this file. * It was generated using rpcgen. diff --git a/nsm/nsm.x b/nsm/nsm.x index 43fbc14..430a5e4 100644 --- a/nsm/nsm.x +++ b/nsm/nsm.x @@ -1,11 +1,31 @@ /* - * NSM definitions from: - * Protocols for Interworking: XNFS, Version 3W - * http://pubs.opengroup.org/onlinepubs/9629799/chap11.htm - * - * Symbols then massaged to avoid too much namespace pollution - * and to bring more inline with convention in nlm. - */ +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ /* * This defines the maximum length of the string diff --git a/packaging/RPM/libnfs.spec.in b/packaging/RPM/libnfs.spec.in index 98acdbc..8b34636 100644 --- a/packaging/RPM/libnfs.spec.in +++ b/packaging/RPM/libnfs.spec.in @@ -95,8 +95,20 @@ development libraries for LibNFS %{_libdir}/libnfs.la %{_libdir}/pkgconfig/libnfs.pc +%package utils +Summary: Utility programs for LibNFS +Group: Applications/System + +%description utils +Utility programs for LibNFS + +%files utils +%defattr(-,root,root) +%{_bindir}/nfs-ls +%{_mandir}/man1/nfs-ls.1.gz + %changelog -* Wed Mar 19 2014: Version 1.9.3 +* Wed Mar 19 2014 : Version 1.9.3 - Add O_TRUNC support to nfs_open() - Add a simple but incomplete LD_PRELOAD tool - Fixes for some memory leaks and C++ compile support @@ -120,7 +132,7 @@ development libraries for LibNFS - RPC layer support for NSM - Add example FUSE filesystem. - Minor fixes. -* Sun Oct 30 2013 : Version 1.8 +* Wed Oct 30 2013 : Version 1.8 - Fix nasty memory leak in read_from_socket - minor updates * Sun Oct 20 2013 : Version 1.7 diff --git a/portmap/Makefile.am b/portmap/Makefile.am index 4d486fc..682ca2a 100644 --- a/portmap/Makefile.am +++ b/portmap/Makefile.am @@ -18,5 +18,7 @@ portmap-stamp : portmap.x touch portmap-stamp compile_rpc: - rpcgen -h portmap.x | sed -e "s/#include //" | sed -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" > libnfs-raw-portmap.h - rpcgen -c portmap.x | sed -e "s/#include \".*portmap.h\"/#include \"libnfs-zdr.h\"\n#include \"libnfs-raw-portmap.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" > libnfs-raw-portmap.c + cat portmap.x | head -29 >libnfs-raw-portmap.h + rpcgen -h portmap.x | sed -e "s/#include //" | sed -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" >> libnfs-raw-portmap.h + cat portmap.x | head -29 >libnfs-raw-portmap.c + rpcgen -c portmap.x | sed -e "s/#include \".*portmap.h\"/#include \"libnfs-zdr.h\"\n#include \"libnfs-raw-portmap.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" >> libnfs-raw-portmap.c diff --git a/portmap/libnfs-raw-portmap.c b/portmap/libnfs-raw-portmap.c index a07a1e6..12b919d 100644 --- a/portmap/libnfs-raw-portmap.c +++ b/portmap/libnfs-raw-portmap.c @@ -1,3 +1,32 @@ +/* +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + /* * Please do not edit this file. * It was generated using rpcgen. @@ -7,7 +36,7 @@ #include "libnfs-raw-portmap.h" bool_t -zdr_pmap_mapping (ZDR *zdrs, pmap_mapping *objp) +zdr_pmap2_mapping (ZDR *zdrs, pmap2_mapping *objp) { register int32_t *buf; buf = NULL; @@ -63,7 +92,7 @@ zdr_pmap_mapping (ZDR *zdrs, pmap_mapping *objp) } bool_t -zdr_pmap_call_args (ZDR *zdrs, pmap_call_args *objp) +zdr_pmap2_call_args (ZDR *zdrs, pmap2_call_args *objp) { register int32_t *buf; buf = NULL; @@ -119,7 +148,7 @@ zdr_pmap_call_args (ZDR *zdrs, pmap_call_args *objp) } bool_t -zdr_pmap_call_result (ZDR *zdrs, pmap_call_result *objp) +zdr_pmap2_call_result (ZDR *zdrs, pmap2_call_result *objp) { register int32_t *buf; buf = NULL; @@ -132,25 +161,161 @@ zdr_pmap_call_result (ZDR *zdrs, pmap_call_result *objp) } bool_t -zdr_pmap_mapping_list (ZDR *zdrs, pmap_mapping_list *objp) +zdr_pmap2_mapping_list (ZDR *zdrs, pmap2_mapping_list *objp) +{ + register int32_t *buf; + buf = NULL; + + if (!zdr_pmap2_mapping (zdrs, &objp->map)) + return FALSE; + if (!zdr_pointer (zdrs, (char **)&objp->next, sizeof (pmap2_mapping_list), (zdrproc_t) zdr_pmap2_mapping_list)) + return FALSE; + return TRUE; +} + +bool_t +zdr_pmap2_dump_result (ZDR *zdrs, pmap2_dump_result *objp) +{ + register int32_t *buf; + buf = NULL; + + if (!zdr_pointer (zdrs, (char **)&objp->list, sizeof (pmap2_mapping_list), (zdrproc_t) zdr_pmap2_mapping_list)) + return FALSE; + return TRUE; +} + +bool_t +zdr_pmap3_string_result (ZDR *zdrs, pmap3_string_result *objp) +{ + register int32_t *buf; + buf = NULL; + + if (!zdr_string (zdrs, &objp->addr, ~0)) + return FALSE; + return TRUE; +} + +bool_t +zdr_pmap3_mapping (ZDR *zdrs, pmap3_mapping *objp) +{ + register int32_t *buf; + buf = NULL; + + if (!zdr_u_int (zdrs, &objp->prog)) + return FALSE; + if (!zdr_u_int (zdrs, &objp->vers)) + return FALSE; + if (!zdr_string (zdrs, &objp->netid, ~0)) + return FALSE; + if (!zdr_string (zdrs, &objp->addr, ~0)) + return FALSE; + if (!zdr_string (zdrs, &objp->owner, ~0)) + return FALSE; + return TRUE; +} + +bool_t +zdr_pmap3_mapping_list (ZDR *zdrs, pmap3_mapping_list *objp) +{ + register int32_t *buf; + buf = NULL; + + if (!zdr_pmap3_mapping (zdrs, &objp->map)) + return FALSE; + if (!zdr_pointer (zdrs, (char **)&objp->next, sizeof (pmap3_mapping_list), (zdrproc_t) zdr_pmap3_mapping_list)) + return FALSE; + return TRUE; +} + +bool_t +zdr_pmap3_dump_result (ZDR *zdrs, pmap3_dump_result *objp) +{ + register int32_t *buf; + buf = NULL; + + if (!zdr_pointer (zdrs, (char **)&objp->list, sizeof (pmap3_mapping_list), (zdrproc_t) zdr_pmap3_mapping_list)) + return FALSE; + return TRUE; +} + +bool_t +zdr_pmap3_call_args (ZDR *zdrs, pmap3_call_args *objp) { register int32_t *buf; buf = NULL; - if (!zdr_pmap_mapping (zdrs, &objp->map)) + + if (zdrs->x_op == ZDR_ENCODE) { + buf = ZDR_INLINE (zdrs, 3 * BYTES_PER_ZDR_UNIT); + if (buf == NULL) { + if (!zdr_u_int (zdrs, &objp->prog)) + return FALSE; + if (!zdr_u_int (zdrs, &objp->vers)) + return FALSE; + if (!zdr_u_int (zdrs, &objp->proc)) + return FALSE; + + } else { + IZDR_PUT_U_LONG(buf, objp->prog); + IZDR_PUT_U_LONG(buf, objp->vers); + IZDR_PUT_U_LONG(buf, objp->proc); + } + if (!zdr_bytes (zdrs, (char **)&objp->args.args_val, (u_int *) &objp->args.args_len, ~0)) + return FALSE; + return TRUE; + } else if (zdrs->x_op == ZDR_DECODE) { + buf = ZDR_INLINE (zdrs, 3 * BYTES_PER_ZDR_UNIT); + if (buf == NULL) { + if (!zdr_u_int (zdrs, &objp->prog)) + return FALSE; + if (!zdr_u_int (zdrs, &objp->vers)) + return FALSE; + if (!zdr_u_int (zdrs, &objp->proc)) + return FALSE; + + } else { + objp->prog = IZDR_GET_U_LONG(buf); + objp->vers = IZDR_GET_U_LONG(buf); + objp->proc = IZDR_GET_U_LONG(buf); + } + if (!zdr_bytes (zdrs, (char **)&objp->args.args_val, (u_int *) &objp->args.args_len, ~0)) + return FALSE; + return TRUE; + } + + if (!zdr_u_int (zdrs, &objp->prog)) + return FALSE; + if (!zdr_u_int (zdrs, &objp->vers)) return FALSE; - if (!zdr_pointer (zdrs, (char **)&objp->next, sizeof (pmap_mapping_list), (zdrproc_t) zdr_pmap_mapping_list)) + if (!zdr_u_int (zdrs, &objp->proc)) + return FALSE; + if (!zdr_bytes (zdrs, (char **)&objp->args.args_val, (u_int *) &objp->args.args_len, ~0)) return FALSE; return TRUE; } bool_t -zdr_pmap_dump_result (ZDR *zdrs, pmap_dump_result *objp) +zdr_pmap3_call_result (ZDR *zdrs, pmap3_call_result *objp) { register int32_t *buf; buf = NULL; - if (!zdr_pointer (zdrs, (char **)&objp->list, sizeof (pmap_mapping_list), (zdrproc_t) zdr_pmap_mapping_list)) + if (!zdr_u_int (zdrs, &objp->port)) + return FALSE; + if (!zdr_bytes (zdrs, (char **)&objp->res.res_val, (u_int *) &objp->res.res_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +zdr_pmap3_netbuf (ZDR *zdrs, pmap3_netbuf *objp) +{ + register int32_t *buf; + buf = NULL; + + if (!zdr_u_int (zdrs, &objp->maxlen)) + return FALSE; + if (!zdr_bytes (zdrs, (char **)&objp->buf.buf_val, (u_int *) &objp->buf.buf_len, ~0)) return FALSE; return TRUE; } diff --git a/portmap/libnfs-raw-portmap.h b/portmap/libnfs-raw-portmap.h index f8d9a45..676be5e 100644 --- a/portmap/libnfs-raw-portmap.h +++ b/portmap/libnfs-raw-portmap.h @@ -1,3 +1,32 @@ +/* +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + /* * Please do not edit this file. * It was generated using rpcgen. @@ -15,15 +44,15 @@ extern "C" { #define PMAP_PORT 111 -struct pmap_mapping { +struct pmap2_mapping { u_int prog; u_int vers; u_int prot; u_int port; }; -typedef struct pmap_mapping pmap_mapping; +typedef struct pmap2_mapping pmap2_mapping; -struct pmap_call_args { +struct pmap2_call_args { u_int prog; u_int vers; u_int proc; @@ -32,89 +61,219 @@ struct pmap_call_args { char *args_val; } args; }; -typedef struct pmap_call_args pmap_call_args; +typedef struct pmap2_call_args pmap2_call_args; -struct pmap_call_result { +struct pmap2_call_result { u_int port; struct { u_int res_len; char *res_val; } res; }; -typedef struct pmap_call_result pmap_call_result; +typedef struct pmap2_call_result pmap2_call_result; + +struct pmap2_mapping_list { + pmap2_mapping map; + struct pmap2_mapping_list *next; +}; +typedef struct pmap2_mapping_list pmap2_mapping_list; + +struct pmap2_dump_result { + struct pmap2_mapping_list *list; +}; +typedef struct pmap2_dump_result pmap2_dump_result; + +struct pmap3_string_result { + char *addr; +}; +typedef struct pmap3_string_result pmap3_string_result; + +struct pmap3_mapping { + u_int prog; + u_int vers; + char *netid; + char *addr; + char *owner; +}; +typedef struct pmap3_mapping pmap3_mapping; + +struct pmap3_mapping_list { + pmap3_mapping map; + struct pmap3_mapping_list *next; +}; +typedef struct pmap3_mapping_list pmap3_mapping_list; + +struct pmap3_dump_result { + struct pmap3_mapping_list *list; +}; +typedef struct pmap3_dump_result pmap3_dump_result; -struct pmap_mapping_list { - pmap_mapping map; - struct pmap_mapping_list *next; +struct pmap3_call_args { + u_int prog; + u_int vers; + u_int proc; + struct { + u_int args_len; + char *args_val; + } args; +}; +typedef struct pmap3_call_args pmap3_call_args; + +struct pmap3_call_result { + u_int port; + struct { + u_int res_len; + char *res_val; + } res; }; -typedef struct pmap_mapping_list pmap_mapping_list; +typedef struct pmap3_call_result pmap3_call_result; -struct pmap_dump_result { - struct pmap_mapping_list *list; +struct pmap3_netbuf { + u_int maxlen; + struct { + u_int buf_len; + char *buf_val; + } buf; }; -typedef struct pmap_dump_result pmap_dump_result; +typedef struct pmap3_netbuf pmap3_netbuf; #define PMAP_PROGRAM 100000 #define PMAP_V2 2 #if defined(__STDC__) || defined(__cplusplus) -#define PMAP_NULL 0 -extern void * pmap_null_2(void *, CLIENT *); -extern void * pmap_null_2_svc(void *, struct svc_req *); -#define PMAP_SET 1 -extern bool_t * pmap_set_2(pmap_mapping *, CLIENT *); -extern bool_t * pmap_set_2_svc(pmap_mapping *, struct svc_req *); -#define PMAP_UNSET 2 -extern bool_t * pmap_unset_2(pmap_mapping *, CLIENT *); -extern bool_t * pmap_unset_2_svc(pmap_mapping *, struct svc_req *); -#define PMAP_GETPORT 3 -extern u_int * pmap_getport_2(pmap_mapping *, CLIENT *); -extern u_int * pmap_getport_2_svc(pmap_mapping *, struct svc_req *); -#define PMAP_DUMP 4 -extern pmap_mapping_list * pmap_dump_2(void *, CLIENT *); -extern pmap_mapping_list * pmap_dump_2_svc(void *, struct svc_req *); -#define PMAP_CALLIT 5 -extern pmap_call_result * pmap_callit_2(pmap_call_args *, CLIENT *); -extern pmap_call_result * pmap_callit_2_svc(pmap_call_args *, struct svc_req *); +#define PMAP2_NULL 0 +extern void * pmap2_null_2(void *, CLIENT *); +extern void * pmap2_null_2_svc(void *, struct svc_req *); +#define PMAP2_SET 1 +extern bool_t * pmap2_set_2(pmap2_mapping *, CLIENT *); +extern bool_t * pmap2_set_2_svc(pmap2_mapping *, struct svc_req *); +#define PMAP2_UNSET 2 +extern bool_t * pmap2_unset_2(pmap2_mapping *, CLIENT *); +extern bool_t * pmap2_unset_2_svc(pmap2_mapping *, struct svc_req *); +#define PMAP2_GETPORT 3 +extern u_int * pmap2_getport_2(pmap2_mapping *, CLIENT *); +extern u_int * pmap2_getport_2_svc(pmap2_mapping *, struct svc_req *); +#define PMAP2_DUMP 4 +extern pmap2_dump_result * pmap2_dump_2(void *, CLIENT *); +extern pmap2_dump_result * pmap2_dump_2_svc(void *, struct svc_req *); +#define PMAP2_CALLIT 5 +extern pmap2_call_result * pmap2_callit_2(pmap2_call_args *, CLIENT *); +extern pmap2_call_result * pmap2_callit_2_svc(pmap2_call_args *, struct svc_req *); extern int pmap_program_2_freeresult (SVCXPRT *, zdrproc_t, caddr_t); #else /* K&R C */ -#define PMAP_NULL 0 -extern void * pmap_null_2(); -extern void * pmap_null_2_svc(); -#define PMAP_SET 1 -extern bool_t * pmap_set_2(); -extern bool_t * pmap_set_2_svc(); -#define PMAP_UNSET 2 -extern bool_t * pmap_unset_2(); -extern bool_t * pmap_unset_2_svc(); -#define PMAP_GETPORT 3 -extern u_int * pmap_getport_2(); -extern u_int * pmap_getport_2_svc(); -#define PMAP_DUMP 4 -extern pmap_mapping_list * pmap_dump_2(); -extern pmap_mapping_list * pmap_dump_2_svc(); -#define PMAP_CALLIT 5 -extern pmap_call_result * pmap_callit_2(); -extern pmap_call_result * pmap_callit_2_svc(); +#define PMAP2_NULL 0 +extern void * pmap2_null_2(); +extern void * pmap2_null_2_svc(); +#define PMAP2_SET 1 +extern bool_t * pmap2_set_2(); +extern bool_t * pmap2_set_2_svc(); +#define PMAP2_UNSET 2 +extern bool_t * pmap2_unset_2(); +extern bool_t * pmap2_unset_2_svc(); +#define PMAP2_GETPORT 3 +extern u_int * pmap2_getport_2(); +extern u_int * pmap2_getport_2_svc(); +#define PMAP2_DUMP 4 +extern pmap2_dump_result * pmap2_dump_2(); +extern pmap2_dump_result * pmap2_dump_2_svc(); +#define PMAP2_CALLIT 5 +extern pmap2_call_result * pmap2_callit_2(); +extern pmap2_call_result * pmap2_callit_2_svc(); extern int pmap_program_2_freeresult (); #endif /* K&R C */ +#define PMAP_V3 3 + +#if defined(__STDC__) || defined(__cplusplus) +#define PMAP3_NULL 0 +extern void * pmap3_null_3(void *, CLIENT *); +extern void * pmap3_null_3_svc(void *, struct svc_req *); +#define PMAP3_SET 1 +extern bool_t * pmap3_set_3(pmap3_mapping *, CLIENT *); +extern bool_t * pmap3_set_3_svc(pmap3_mapping *, struct svc_req *); +#define PMAP3_UNSET 2 +extern bool_t * pmap3_unset_3(pmap3_mapping *, CLIENT *); +extern bool_t * pmap3_unset_3_svc(pmap3_mapping *, struct svc_req *); +#define PMAP3_GETADDR 3 +extern pmap3_string_result * pmap3_getaddr_3(pmap3_mapping *, CLIENT *); +extern pmap3_string_result * pmap3_getaddr_3_svc(pmap3_mapping *, struct svc_req *); +#define PMAP3_DUMP 4 +extern pmap3_dump_result * pmap3_dump_3(void *, CLIENT *); +extern pmap3_dump_result * pmap3_dump_3_svc(void *, struct svc_req *); +#define PMAP3_CALLIT 5 +extern pmap3_call_result * pmap3_callit_3(pmap3_call_args *, CLIENT *); +extern pmap3_call_result * pmap3_callit_3_svc(pmap3_call_args *, struct svc_req *); +#define PMAP3_GETTIME 6 +extern u_int * pmap3_gettime_3(void *, CLIENT *); +extern u_int * pmap3_gettime_3_svc(void *, struct svc_req *); +#define PMAP3_UADDR2TADDR 7 +extern pmap3_netbuf * pmap3_uaddr2taddr_3(char **, CLIENT *); +extern pmap3_netbuf * pmap3_uaddr2taddr_3_svc(char **, struct svc_req *); +#define PMAP3_TADDR2UADDR 8 +extern struct pmap3_string_result * pmap3_taddr2uaddr_3(pmap3_netbuf *, CLIENT *); +extern struct pmap3_string_result * pmap3_taddr2uaddr_3_svc(pmap3_netbuf *, struct svc_req *); +extern int pmap_program_3_freeresult (SVCXPRT *, zdrproc_t, caddr_t); + +#else /* K&R C */ +#define PMAP3_NULL 0 +extern void * pmap3_null_3(); +extern void * pmap3_null_3_svc(); +#define PMAP3_SET 1 +extern bool_t * pmap3_set_3(); +extern bool_t * pmap3_set_3_svc(); +#define PMAP3_UNSET 2 +extern bool_t * pmap3_unset_3(); +extern bool_t * pmap3_unset_3_svc(); +#define PMAP3_GETADDR 3 +extern pmap3_string_result * pmap3_getaddr_3(); +extern pmap3_string_result * pmap3_getaddr_3_svc(); +#define PMAP3_DUMP 4 +extern pmap3_dump_result * pmap3_dump_3(); +extern pmap3_dump_result * pmap3_dump_3_svc(); +#define PMAP3_CALLIT 5 +extern pmap3_call_result * pmap3_callit_3(); +extern pmap3_call_result * pmap3_callit_3_svc(); +#define PMAP3_GETTIME 6 +extern u_int * pmap3_gettime_3(); +extern u_int * pmap3_gettime_3_svc(); +#define PMAP3_UADDR2TADDR 7 +extern pmap3_netbuf * pmap3_uaddr2taddr_3(); +extern pmap3_netbuf * pmap3_uaddr2taddr_3_svc(); +#define PMAP3_TADDR2UADDR 8 +extern struct pmap3_string_result * pmap3_taddr2uaddr_3(); +extern struct pmap3_string_result * pmap3_taddr2uaddr_3_svc(); +extern int pmap_program_3_freeresult (); +#endif /* K&R C */ /* the zdr functions */ #if defined(__STDC__) || defined(__cplusplus) -extern bool_t zdr_pmap_mapping (ZDR *, pmap_mapping*); -extern bool_t zdr_pmap_call_args (ZDR *, pmap_call_args*); -extern bool_t zdr_pmap_call_result (ZDR *, pmap_call_result*); -extern bool_t zdr_pmap_mapping_list (ZDR *, pmap_mapping_list*); -extern bool_t zdr_pmap_dump_result (ZDR *, pmap_dump_result*); +extern bool_t zdr_pmap2_mapping (ZDR *, pmap2_mapping*); +extern bool_t zdr_pmap2_call_args (ZDR *, pmap2_call_args*); +extern bool_t zdr_pmap2_call_result (ZDR *, pmap2_call_result*); +extern bool_t zdr_pmap2_mapping_list (ZDR *, pmap2_mapping_list*); +extern bool_t zdr_pmap2_dump_result (ZDR *, pmap2_dump_result*); +extern bool_t zdr_pmap3_string_result (ZDR *, pmap3_string_result*); +extern bool_t zdr_pmap3_mapping (ZDR *, pmap3_mapping*); +extern bool_t zdr_pmap3_mapping_list (ZDR *, pmap3_mapping_list*); +extern bool_t zdr_pmap3_dump_result (ZDR *, pmap3_dump_result*); +extern bool_t zdr_pmap3_call_args (ZDR *, pmap3_call_args*); +extern bool_t zdr_pmap3_call_result (ZDR *, pmap3_call_result*); +extern bool_t zdr_pmap3_netbuf (ZDR *, pmap3_netbuf*); #else /* K&R C */ -extern bool_t zdr_pmap_mapping (); -extern bool_t zdr_pmap_call_args (); -extern bool_t zdr_pmap_call_result (); -extern bool_t zdr_pmap_mapping_list (); -extern bool_t zdr_pmap_dump_result (); +extern bool_t zdr_pmap2_mapping (); +extern bool_t zdr_pmap2_call_args (); +extern bool_t zdr_pmap2_call_result (); +extern bool_t zdr_pmap2_mapping_list (); +extern bool_t zdr_pmap2_dump_result (); +extern bool_t zdr_pmap3_string_result (); +extern bool_t zdr_pmap3_mapping (); +extern bool_t zdr_pmap3_mapping_list (); +extern bool_t zdr_pmap3_dump_result (); +extern bool_t zdr_pmap3_call_args (); +extern bool_t zdr_pmap3_call_result (); +extern bool_t zdr_pmap3_netbuf (); #endif /* K&R C */ diff --git a/portmap/portmap.c b/portmap/portmap.c index 5042e8c..9b0e0f6 100644 --- a/portmap/portmap.c +++ b/portmap/portmap.c @@ -25,19 +25,21 @@ #include "libnfs-private.h" #include "libnfs-raw-portmap.h" - -int rpc_pmap_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) +/* + * PORTMAP v2 + */ +int rpc_pmap2_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; - pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP_NULL, cb, private_data, (zdrproc_t)zdr_void, 0); + pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP2_NULL, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { - rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for portmap/null call"); + rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP2/NULL call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { - rpc_set_error(rpc, "Out of memory. Failed to queue pdu for portmap/null call"); + rpc_set_error(rpc, "Out of memory. Failed to queue pdu for PORTMAP2/NULL call"); rpc_free_pdu(rpc, pdu); return -1; } @@ -45,14 +47,14 @@ int rpc_pmap_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) return 0; } -int rpc_pmap_getport_async(struct rpc_context *rpc, int program, int version, int protocol, rpc_cb cb, void *private_data) +int rpc_pmap2_getport_async(struct rpc_context *rpc, int program, int version, int protocol, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; - struct pmap_mapping m; + struct pmap2_mapping m; - pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP_GETPORT, cb, private_data, (zdrproc_t)zdr_int, sizeof(uint32_t)); + pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP2_GETPORT, cb, private_data, (zdrproc_t)zdr_int, sizeof(uint32_t)); if (pdu == NULL) { - rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for portmap/getport call"); + rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP2/GETPORT call"); return -1; } @@ -60,14 +62,14 @@ int rpc_pmap_getport_async(struct rpc_context *rpc, int program, int version, in m.vers = version; m.prot = protocol; m.port = 0; - if (zdr_pmap_mapping(&pdu->zdr, &m) == 0) { - rpc_set_error(rpc, "ZDR error: Failed to encode data for portmap/getport call"); + if (zdr_pmap2_mapping(&pdu->zdr, &m) == 0) { + rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP2/GETPORT call"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { - rpc_set_error(rpc, "Failed to queue portmap/getport pdu"); + rpc_set_error(rpc, "Failed to queue PORTMAP2/GETPORT pdu"); rpc_free_pdu(rpc, pdu); return -1; } @@ -75,14 +77,14 @@ int rpc_pmap_getport_async(struct rpc_context *rpc, int program, int version, in return 0; } -int rpc_pmap_set_async(struct rpc_context *rpc, int program, int version, int protocol, int port, rpc_cb cb, void *private_data) +int rpc_pmap2_set_async(struct rpc_context *rpc, int program, int version, int protocol, int port, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; - struct pmap_mapping m; + struct pmap2_mapping m; - pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP_SET, cb, private_data, (zdrproc_t)zdr_int, sizeof(uint32_t)); + pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP2_SET, cb, private_data, (zdrproc_t)zdr_int, sizeof(uint32_t)); if (pdu == NULL) { - rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for portmap/set call"); + rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP2/SET call"); return -1; } @@ -90,14 +92,14 @@ int rpc_pmap_set_async(struct rpc_context *rpc, int program, int version, int pr m.vers = version; m.prot = protocol; m.port = port; - if (zdr_pmap_mapping(&pdu->zdr, &m) == 0) { - rpc_set_error(rpc, "ZDR error: Failed to encode data for portmap/set call"); + if (zdr_pmap2_mapping(&pdu->zdr, &m) == 0) { + rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP2/SET call"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { - rpc_set_error(rpc, "Failed to queue portmap/set pdu"); + rpc_set_error(rpc, "Failed to queue PORTMAP2/SET pdu"); rpc_free_pdu(rpc, pdu); return -1; } @@ -105,14 +107,14 @@ int rpc_pmap_set_async(struct rpc_context *rpc, int program, int version, int pr return 0; } -int rpc_pmap_unset_async(struct rpc_context *rpc, int program, int version, int protocol, int port, rpc_cb cb, void *private_data) +int rpc_pmap2_unset_async(struct rpc_context *rpc, int program, int version, int protocol, int port, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; - struct pmap_mapping m; + struct pmap2_mapping m; - pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP_UNSET, cb, private_data, (zdrproc_t)zdr_int, sizeof(uint32_t)); + pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP2_UNSET, cb, private_data, (zdrproc_t)zdr_int, sizeof(uint32_t)); if (pdu == NULL) { - rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for portmap/unset call"); + rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP2/UNSET call"); return -1; } @@ -120,14 +122,14 @@ int rpc_pmap_unset_async(struct rpc_context *rpc, int program, int version, int m.vers = version; m.prot = protocol; m.port = port; - if (zdr_pmap_mapping(&pdu->zdr, &m) == 0) { - rpc_set_error(rpc, "ZDR error: Failed to encode data for portmap/unset call"); + if (zdr_pmap2_mapping(&pdu->zdr, &m) == 0) { + rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP2/UNSET call"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { - rpc_set_error(rpc, "Failed to queue portmap/unset pdu"); + rpc_set_error(rpc, "Failed to queue PORTMAP2/UNSET pdu"); rpc_free_pdu(rpc, pdu); return -1; } @@ -135,18 +137,18 @@ int rpc_pmap_unset_async(struct rpc_context *rpc, int program, int version, int return 0; } -int rpc_pmap_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) +int rpc_pmap2_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; - pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP_DUMP, cb, private_data, (zdrproc_t)zdr_pmap_dump_result, sizeof(pmap_dump_result)); + pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP2_DUMP, cb, private_data, (zdrproc_t)zdr_pmap2_dump_result, sizeof(pmap2_dump_result)); if (pdu == NULL) { - rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for portmap/dump call"); + rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP2/DUMP call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { - rpc_set_error(rpc, "Failed to queue portmap/dump pdu"); + rpc_set_error(rpc, "Failed to queue PORTMAP2/DUMP pdu"); rpc_free_pdu(rpc, pdu); return -1; } @@ -154,14 +156,14 @@ int rpc_pmap_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) return 0; } -int rpc_pmap_callit_async(struct rpc_context *rpc, int program, int version, int procedure, char *data, int datalen, rpc_cb cb, void *private_data) +int rpc_pmap2_callit_async(struct rpc_context *rpc, int program, int version, int procedure, char *data, int datalen, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; - struct pmap_call_args ca; + struct pmap2_call_args ca; - pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP_CALLIT, cb, private_data, (zdrproc_t)zdr_pmap_call_result, sizeof(pmap_call_result)); + pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP2_CALLIT, cb, private_data, (zdrproc_t)zdr_pmap2_call_result, sizeof(pmap2_call_result)); if (pdu == NULL) { - rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for portmap/callit call"); + rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP2/CALLIT call"); return -1; } @@ -171,14 +173,228 @@ int rpc_pmap_callit_async(struct rpc_context *rpc, int program, int version, int ca.args.args_len = datalen; ca.args.args_val = data; - if (zdr_pmap_call_args(&pdu->zdr, &ca) == 0) { - rpc_set_error(rpc, "ZDR error: Failed to encode data for portmap/callit call"); + if (zdr_pmap2_call_args(&pdu->zdr, &ca) == 0) { + rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP2/CALLIT call"); + rpc_free_pdu(rpc, pdu); + return -1; + } + + if (rpc_queue_pdu(rpc, pdu) != 0) { + rpc_set_error(rpc, "Failed to queue PORTMAP2/CALLIT pdu: %s", rpc_get_error(rpc)); + return -1; + } + + return 0; +} + +/* + * PORTMAP v3 + */ +int rpc_pmap3_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) +{ + struct rpc_pdu *pdu; + + pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_NULL, cb, private_data, (zdrproc_t)zdr_void, 0); + if (pdu == NULL) { + rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/NULL call"); + return -1; + } + + if (rpc_queue_pdu(rpc, pdu) != 0) { + rpc_set_error(rpc, "Out of memory. Failed to queue pdu for PORTMAP3/NULL call"); + rpc_free_pdu(rpc, pdu); + return -1; + } + + return 0; +} + +int rpc_pmap3_set_async(struct rpc_context *rpc, struct pmap3_mapping *map, rpc_cb cb, void *private_data) +{ + struct rpc_pdu *pdu; + + pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_SET, cb, private_data, (zdrproc_t)zdr_int, sizeof(uint32_t)); + if (pdu == NULL) { + rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/SET call"); + return -1; + } + + if (zdr_pmap3_mapping(&pdu->zdr, map) == 0) { + rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP3/SET call"); + rpc_free_pdu(rpc, pdu); + return -1; + } + + if (rpc_queue_pdu(rpc, pdu) != 0) { + rpc_set_error(rpc, "Failed to queue PORTMAP3/SET pdu"); + rpc_free_pdu(rpc, pdu); + return -1; + } + + return 0; +} + +int rpc_pmap3_unset_async(struct rpc_context *rpc, struct pmap3_mapping *map, rpc_cb cb, void *private_data) +{ + struct rpc_pdu *pdu; + + pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_UNSET, cb, private_data, (zdrproc_t)zdr_int, sizeof(uint32_t)); + if (pdu == NULL) { + rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/UNSET call"); + return -1; + } + + if (zdr_pmap3_mapping(&pdu->zdr, map) == 0) { + rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP3/UNSET call"); + rpc_free_pdu(rpc, pdu); + return -1; + } + + if (rpc_queue_pdu(rpc, pdu) != 0) { + rpc_set_error(rpc, "Failed to queue PORTMAP3/UNSET pdu"); + rpc_free_pdu(rpc, pdu); + return -1; + } + + return 0; +} + +int rpc_pmap3_getaddr_async(struct rpc_context *rpc, struct pmap3_mapping *map, rpc_cb cb, void *private_data) +{ + struct rpc_pdu *pdu; + + pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_GETADDR, cb, private_data, (zdrproc_t)zdr_pmap3_string_result, sizeof(pmap3_string_result)); + if (pdu == NULL) { + rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/GETADDR call"); + return -1; + } + + if (zdr_pmap3_mapping(&pdu->zdr, map) == 0) { + rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP3/GETADDR call"); + rpc_free_pdu(rpc, pdu); + return -1; + } + + if (rpc_queue_pdu(rpc, pdu) != 0) { + rpc_set_error(rpc, "Failed to queue PORTMAP3/GETADDR pdu"); + rpc_free_pdu(rpc, pdu); + return -1; + } + + return 0; +} + +int rpc_pmap3_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) +{ + struct rpc_pdu *pdu; + + pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_DUMP, cb, private_data, (zdrproc_t)zdr_pmap3_dump_result, sizeof(pmap3_dump_result)); + if (pdu == NULL) { + rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/DUMP call"); + return -1; + } + + if (rpc_queue_pdu(rpc, pdu) != 0) { + rpc_set_error(rpc, "Failed to queue PORTMAP3/DUMP pdu"); + rpc_free_pdu(rpc, pdu); + return -1; + } + + return 0; +} + +int rpc_pmap3_gettime_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) +{ + struct rpc_pdu *pdu; + + pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_GETTIME, cb, private_data, (zdrproc_t)zdr_int, sizeof(uint32_t)); + if (pdu == NULL) { + rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/GETTIME call"); + return -1; + } + + if (rpc_queue_pdu(rpc, pdu) != 0) { + rpc_set_error(rpc, "Failed to queue PORTMAP3/GETTIME pdu"); + rpc_free_pdu(rpc, pdu); + return -1; + } + + return 0; +} + +int rpc_pmap3_callit_async(struct rpc_context *rpc, int program, int version, int procedure, char *data, int datalen, rpc_cb cb, void *private_data) +{ + struct rpc_pdu *pdu; + struct pmap3_call_args ca; + + pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_CALLIT, cb, private_data, (zdrproc_t)zdr_pmap3_call_result, sizeof(pmap3_call_result)); + if (pdu == NULL) { + rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/CALLIT call"); + return -1; + } + + ca.prog = program; + ca.vers = version; + ca.proc = procedure; + ca.args.args_len = datalen; + ca.args.args_val = data; + + if (zdr_pmap3_call_args(&pdu->zdr, &ca) == 0) { + rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP3/CALLIT call"); + rpc_free_pdu(rpc, pdu); + return -1; + } + + if (rpc_queue_pdu(rpc, pdu) != 0) { + rpc_set_error(rpc, "Failed to queue PORTMAP3/CALLIT pdu: %s", rpc_get_error(rpc)); + return -1; + } + + return 0; +} + +int rpc_pmap3_uaddr2taddr_async(struct rpc_context *rpc, char *uaddr, rpc_cb cb, void *private_data) +{ + struct rpc_pdu *pdu; + + pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_UADDR2TADDR, cb, private_data, (zdrproc_t)zdr_pmap3_netbuf, sizeof(pmap3_netbuf)); + if (pdu == NULL) { + rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/UADDR2TADDR call"); + return -1; + } + + if (zdr_string(&pdu->zdr, &uaddr, 255) == 0) { + rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP3/UADDR2TADDR call"); + rpc_free_pdu(rpc, pdu); + return -1; + } + + if (rpc_queue_pdu(rpc, pdu) != 0) { + rpc_set_error(rpc, "Failed to queue PORTMAP3/UADDR2TADDR pdu: %s", rpc_get_error(rpc)); + return -1; + } + + return 0; +} + +int rpc_pmap3_taddr2uaddr_async(struct rpc_context *rpc, struct pmap3_netbuf *nb, rpc_cb cb, void *private_data) +{ + struct rpc_pdu *pdu; + + pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_TADDR2UADDR, cb, private_data, (zdrproc_t)zdr_pmap3_string_result, sizeof(pmap3_string_result)); + if (pdu == NULL) { + rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/TADDR2UADDR call"); + return -1; + } + + if (zdr_pmap3_netbuf(&pdu->zdr, nb) == 0) { + rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP3/TADDR2UADDR call"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { - rpc_set_error(rpc, "Failed to queue portmap/callit pdu: %s", rpc_get_error(rpc)); + rpc_set_error(rpc, "Failed to queue PORTMAP3/TADDR2UADDR pdu: %s", rpc_get_error(rpc)); return -1; } diff --git a/portmap/portmap.x b/portmap/portmap.x index 17fd980..5ceb436 100644 --- a/portmap/portmap.x +++ b/portmap/portmap.x @@ -1,56 +1,151 @@ /* - * From RFC1833 - */ +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ const PMAP_PORT = 111; /* portmapper port number */ -struct pmap_mapping { +struct pmap2_mapping { unsigned int prog; unsigned int vers; unsigned int prot; unsigned int port; }; -struct pmap_call_args { +struct pmap2_call_args { unsigned int prog; unsigned int vers; unsigned int proc; opaque args<>; }; -struct pmap_call_result { +struct pmap2_call_result { unsigned int port; opaque res<>; }; -struct pmap_mapping_list { - pmap_mapping map; - pmap_mapping_list *next; +struct pmap2_mapping_list { + pmap2_mapping map; + pmap2_mapping_list *next; +}; + +struct pmap2_dump_result { + struct pmap2_mapping_list *list; +}; + +struct pmap3_string_result { + string addr<>; }; -struct pmap_dump_result { - struct pmap_mapping_list *list; +struct pmap3_mapping { + unsigned int prog; + unsigned int vers; + string netid<>; + string addr<>; + string owner<>; +}; + +struct pmap3_mapping_list { + pmap3_mapping map; + pmap3_mapping_list *next; +}; + +struct pmap3_dump_result { + struct pmap3_mapping_list *list; +}; + +struct pmap3_call_args { + unsigned int prog; + unsigned int vers; + unsigned int proc; + opaque args<>; +}; + +struct pmap3_call_result { + unsigned int port; + opaque res<>; +}; + +struct pmap3_netbuf { + unsigned int maxlen; + /* This pretty much contains a sockaddr_storage. + * Beware differences in endianess for ss_family + * and whether or not ss_len exists. + */ + opaque buf<>; }; program PMAP_PROGRAM { version PMAP_V2 { void - PMAP_NULL(void) = 0; + PMAP2_NULL(void) = 0; bool - PMAP_SET(pmap_mapping) = 1; + PMAP2_SET(pmap2_mapping) = 1; bool - PMAP_UNSET(pmap_mapping) = 2; + PMAP2_UNSET(pmap2_mapping) = 2; unsigned int - PMAP_GETPORT(pmap_mapping) = 3; + PMAP2_GETPORT(pmap2_mapping) = 3; - pmap_mapping_list - PMAP_DUMP(void) = 4; + pmap2_dump_result + PMAP2_DUMP(void) = 4; - pmap_call_result - PMAP_CALLIT(pmap_call_args) = 5; + pmap2_call_result + PMAP2_CALLIT(pmap2_call_args) = 5; } = 2; + version PMAP_V3 { + void + PMAP3_NULL(void) = 0; + + bool + PMAP3_SET(pmap3_mapping) = 1; + + bool + PMAP3_UNSET(pmap3_mapping) = 2; + + pmap3_string_result + PMAP3_GETADDR(pmap3_mapping) = 3; + + pmap3_dump_result + PMAP3_DUMP(void) = 4; + + pmap3_call_result + PMAP3_CALLIT(pmap3_call_args) = 5; + + unsigned int + PMAP3_GETTIME(void) = 6; + + pmap3_netbuf + PMAP3_UADDR2TADDR(string) = 7; + + struct pmap3_string_result + PMAP3_TADDR2UADDR(pmap3_netbuf) = 8; + } = 3; } = 100000; diff --git a/rquota/Makefile.am b/rquota/Makefile.am index 02f86f7..5a604a8 100644 --- a/rquota/Makefile.am +++ b/rquota/Makefile.am @@ -16,7 +16,9 @@ $(rquota_GENERATED) : rquota-stamp rquota-stamp : rquota.x rm -f $(rquota_GENERATED) touch rquota-stamp - + compile_rpc: - rpcgen -h rquota.x | sed -e "s/#include //" | sed -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" > libnfs-raw-rquota.h - rpcgen -c rquota.x | sed -e "s/#include \".*rquota.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-rquota.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" > libnfs-raw-rquota.c + cat rquota.x | head -29 >libnfs-raw-rquota.h + rpcgen -h rquota.x | sed -e "s/#include //" | sed -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" >> libnfs-raw-rquota.h + cat rquota.x | head -29 >libnfs-raw-rquota.c + rpcgen -c rquota.x | sed -e "s/#include \".*rquota.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-rquota.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" >> libnfs-raw-rquota.c diff --git a/rquota/libnfs-raw-rquota.c b/rquota/libnfs-raw-rquota.c index 4b0e330..482645f 100644 --- a/rquota/libnfs-raw-rquota.c +++ b/rquota/libnfs-raw-rquota.c @@ -1,3 +1,32 @@ +/* +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + /* * Please do not edit this file. * It was generated using rpcgen. diff --git a/rquota/libnfs-raw-rquota.h b/rquota/libnfs-raw-rquota.h index 4690da6..ed5fcb9 100644 --- a/rquota/libnfs-raw-rquota.h +++ b/rquota/libnfs-raw-rquota.h @@ -1,3 +1,32 @@ +/* +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + /* * Please do not edit this file. * It was generated using rpcgen. @@ -6,7 +35,8 @@ #ifndef _RQUOTA_H_RPCGEN #define _RQUOTA_H_RPCGEN -#include + + #ifdef __cplusplus extern "C" { diff --git a/rquota/rquota.x b/rquota/rquota.x index fb8bc0e..e0a764f 100644 --- a/rquota/rquota.x +++ b/rquota/rquota.x @@ -1,4 +1,31 @@ -/* implementation based on wireshark c-code */ +/* +Copyright (c) 2014, Ronnie Sahlberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ const RQUOTAPATHLEN = 1024; /* Guess this is max. It is max for mount so probably rquota too */ diff --git a/utils/Makefile.am b/utils/Makefile.am new file mode 100644 index 0000000..e8bb94e --- /dev/null +++ b/utils/Makefile.am @@ -0,0 +1,9 @@ +bin_PROGRAMS = nfs-ls + +AM_CPPFLAGS = \ + -I$(abs_top_srcdir)/include \ + -I$(abs_top_srcdir)/include/nfsc \ + -I$(abs_top_srcdir)/mount \ + "-D_U_=__attribute__((unused))" + +AM_LDFLAGS = ../lib/.libs/libnfs.la diff --git a/examples/nfs-ls.c b/utils/nfs-ls.c similarity index 87% rename from examples/nfs-ls.c rename to utils/nfs-ls.c index c680617..7653f56 100644 --- a/examples/nfs-ls.c +++ b/utils/nfs-ls.c @@ -91,7 +91,6 @@ void process_dir(struct nfs_context *nfs, char *dir, int level) { struct nfsdirent *nfsdirent; struct statvfs svfs; struct nfsdir *nfsdir; - struct nfs_stat_64 st; if (!level) { printf("Recursion detected!\n"); @@ -109,15 +108,9 @@ void process_dir(struct nfs_context *nfs, char *dir, int level) { if (!strcmp(nfsdirent->name, ".") || !strcmp(nfsdirent->name, "..")) { continue; } - snprintf(path, 1024, "%s/%s", dir, nfsdirent->name); - ret = nfs_stat64(nfs, path, &st); - if (ret != 0) { - fprintf(stderr, "Failed to stat(%s) %s\n", path, nfs_get_error(nfs)); - continue; - } - switch (st.nfs_mode & S_IFMT) { + switch (nfsdirent->mode & S_IFMT) { #ifndef WIN32 case S_IFLNK: printf("l"); @@ -137,28 +130,28 @@ void process_dir(struct nfs_context *nfs, char *dir, int level) { break; } printf("%c%c%c", - "-r"[!!(st.nfs_mode & S_IRUSR)], - "-w"[!!(st.nfs_mode & S_IWUSR)], - "-x"[!!(st.nfs_mode & S_IXUSR)] + "-r"[!!(nfsdirent->mode & S_IRUSR)], + "-w"[!!(nfsdirent->mode & S_IWUSR)], + "-x"[!!(nfsdirent->mode & S_IXUSR)] ); printf("%c%c%c", - "-r"[!!(st.nfs_mode & S_IRGRP)], - "-w"[!!(st.nfs_mode & S_IWGRP)], - "-x"[!!(st.nfs_mode & S_IXGRP)] + "-r"[!!(nfsdirent->mode & S_IRGRP)], + "-w"[!!(nfsdirent->mode & S_IWGRP)], + "-x"[!!(nfsdirent->mode & S_IXGRP)] ); printf("%c%c%c", - "-r"[!!(st.nfs_mode & S_IROTH)], - "-w"[!!(st.nfs_mode & S_IWOTH)], - "-x"[!!(st.nfs_mode & S_IXOTH)] + "-r"[!!(nfsdirent->mode & S_IROTH)], + "-w"[!!(nfsdirent->mode & S_IWOTH)], + "-x"[!!(nfsdirent->mode & S_IXOTH)] ); - printf(" %2d", (int)st.nfs_nlink); - printf(" %5d", (int)st.nfs_uid); - printf(" %5d", (int)st.nfs_gid); - printf(" %12" PRId64, st.nfs_size); + printf(" %2d", (int)nfsdirent->nlink); + printf(" %5d", (int)nfsdirent->uid); + printf(" %5d", (int)nfsdirent->gid); + printf(" %12" PRId64, nfsdirent->size); printf(" %s\n", path + 1); - if (recursive && (st.nfs_mode & S_IFMT) == S_IFDIR) { + if (recursive && (nfsdirent->mode & S_IFMT) == S_IFDIR) { process_dir(nfs, path, level - 1); } } @@ -172,7 +165,7 @@ int main(int argc, char *argv[]) uint64_t offset; struct client client; struct statvfs stvfs; - struct nfs_url *url; + struct nfs_url *url = NULL; exports export, tmp; #ifdef WIN32 diff --git a/win32/win32_errnowrapper.h b/win32/win32_errnowrapper.h index ebed01c..1699d5e 100644 --- a/win32/win32_errnowrapper.h +++ b/win32/win32_errnowrapper.h @@ -1,3 +1,24 @@ +/* +Copyright (c) 2014, Ronnie Sahlberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ #ifndef WIN32_ERRNOWRAPPER_H_ #define WIN32_ERRNOWRAPPER_H_ -- 2.34.1