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
-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
Libnfs uses RFC2224 style URLs extended with libnfs specific url arguments some minor extensions.
The basic syntax of these URLs is :
-nfs://<server|ipv4>/path[?arg=val[&arg=val]*]
+nfs://<server|ipv4|ipv6>/path[?arg=val[&arg=val]*]
Arguments supported by libnfs are :
tcp-syncnt=<int> : Number of SYNs to send during the session establish
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
+/*
+ Copyright (C) 2013 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
#ifndef AROS_COMPAT_H
#define AROS_COMPAT_H
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
#output
AC_CONFIG_FILES([Makefile]
+ [doc/Makefile]
[include/Makefile]
[lib/Makefile]
[mount/Makefile]
[nsm/Makefile]
[portmap/Makefile]
[rquota/Makefile]
+ [utils/Makefile]
[examples/Makefile]
)
--- /dev/null
+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
--- /dev/null
+'\" t
+.\" Title: nfs-ls
+.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" 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\ ]\ <NFS\-URL>\fR\ 'u
+\fBnfs\-ls [ OPTIONS ] <NFS\-URL>\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[]
--- /dev/null
+<?xml version="1.0" encoding="iso-8859-1"?>
+<refentry id="nfs-ls.1">
+
+<refmeta>
+ <refentrytitle>nfs-ls</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo class="source">nfs-ls</refmiscinfo>
+ <refmiscinfo class="manual">nfs-ls: list servers, exports and directories</refmiscinfo>
+</refmeta>
+
+
+<refnamediv>
+ <refname>nfs-ls</refname>
+ <refpurpose>Utility to list NFS servers, exports and directories</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+ <cmdsynopsis>
+ <command>nfs-ls [ OPTIONS ] <NFS-URL></command>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>nfs-ls</command>
+ <arg choice="opt">-R --recursive</arg>
+ <arg choice="opt">-s --summary</arg>
+ <arg choice="opt">-D --discovery</arg>
+ <arg choice="opt">-? --help</arg>
+ <arg choice="opt">--usage</arg>
+ </cmdsynopsis>
+
+</refsynopsisdiv>
+
+ <refsect1><title>DESCRIPTION</title>
+ <para>
+ nfs-ls is a utility to list NFS servers, exports or directories.
+ </para>
+ <para>
+ Example: List the content of a directory on the NFS server
+ <screen format="linespecific">
+$ 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
+ </screen>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+
+ <varlistentry><term>-s --summary</term>
+ <listitem>
+ <para>
+ Print a summary line at the end of output.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term>-R --recursive</term>
+ <listitem>
+ <para>
+ Recursive listing of the specified URL.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term>-D --discovery;</term>
+ <listitem>
+ <para>
+ This option is used to discover local NFS servers and to list
+ the exports for specific servers.
+ </para>
+ <para>
+ When used with the 'nfs://' URL the command will try to
+ detect all local NFS servers and will list their IPs.
+ </para>
+ <para>
+ When used with a 'nfs://server' the command will
+ list all the exports on the specified server.
+ </para>
+ <para>
+ Example: Discover and list all local NFS servers
+ <screen format="linespecific">
+$ nfs-ls -D nfs://
+nfs://10.10.10.10
+nfs://10.0.0.10
+ </screen>
+
+ Example: List the exports for a server
+ <screen format="linespecific">
+$ nfs-ls -D nfs://10.10.10.10
+nfs://10.10.10.10/foo
+nfs://10.10.10.10/bar
+ </screen>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term>-? --help</term>
+ <listitem>
+ <para>
+ Display basic help text.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term>--usage</term>
+ <listitem>
+ <para>
+ Display basic usage text.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1><title>SEE ALSO</title>
+ <para>
+ <ulink url="http://github.com/sahlberg/libnfs"/>
+ </para>
+ </refsect1>
+
+</refentry>
-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 \
"-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
-
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);
}
}
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);
}
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);
}
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);
}
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);
}
}
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);
}
--- /dev/null
+/*
+ Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 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 <http://www.gnu.org/licenses/>.
+*/
+
+/* 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 <poll.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <time.h>
+#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 <command*> <server>\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;
+}
nfscdir = $(includedir)/nfsc
dist_nfsc_HEADERS = \
- libnfs-private.h \
- slist.h \
nfsc/libnfs.h \
nfsc/libnfs-raw.h \
nfsc/libnfs-zdr.h \
../nlm/libnfs-raw-nlm.h \
../nsm/libnfs-raw-nsm.h \
../rquota/libnfs-raw-rquota.h
+
+dist_noinst_HEADERS = \
+ libnfs-private.h \
+ slist.h
#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;
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;
int tcp_syncnt;
int uid;
int gid;
+ uint32_t readahead;
};
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);
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);
* 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.
/*
- * 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.
* 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.
* 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.
* 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.
* 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
#if defined(AROS)
#include <sys/time.h>
#endif
+#if defined(__APPLE__) && defined(__MACH__)
+#include <sys/time.h>
+#endif
#ifdef __cplusplus
extern "C" {
#endif
+#define LIBNFS_FEATURE_READAHEAD
+#define NFS_BLKSIZE 4096
+
struct nfs_context;
struct rpc_context;
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
/*
* Async open(<filename>)
*
- * 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
* -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);
/*
struct timeval ctime;
uint32_t uid;
uint32_t gid;
+ uint32_t nlink;
};
/*
* nfs_readdir() never blocks, so no special sync/async versions are available
#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) \
(*list) = head; \
}
-#define SLIST_REMOVE(list, item) \
+#define LIBNFS_LIST_REMOVE(list, item) \
if ((*list) == (item)) { \
(*list) = (item)->next; \
} else { \
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 \
/*
Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
-
+ 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
{
struct rpc_context *rpc;
static uint32_t salt = 0;
+ unsigned int i;
rpc = malloc(sizeof(struct rpc_context));
if (rpc == NULL) {
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)
{
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;
}
}
while (rpc->fragments != NULL) {
struct rpc_fragment *fragment = rpc->fragments;
- SLIST_REMOVE(&rpc->fragments, fragment);
+ rpc->fragments = fragment->next;
rpc_free_fragment(fragment);
}
}
}
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);
#include "win32_compat.h"
#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#include <sys/ioctl.h>
#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
#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;
};
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;
}
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");
*/
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;
}
/*
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)
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");
*/
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;
}
}
}
-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;
free(srv);
srv = next;
}
-}
+}
struct nfs_list_data {
int status;
srv_data->status = -1;
return;
}
-
+
/* check for dupes */
for (srvr = srv_data->srvrs; srvr; srvr = srvr->next) {
if (!strcmp(hostdd, srvr->addr)) {
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;
}
assert(rpc->magic == RPC_CONTEXT_MAGIC);
- for(i = 0; i < numIfs; i++)
+ for(i = 0; i < numIfs; i++)
{
SOCKADDR *pAddress;
char bcdd[16];
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;
}
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;
- (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;
}
rpc_destroy_context(rpc);
- if (data.status != 0)
+ if (data.status != 0)
{
free_nfs_srvr_list(data.srvrs);
return NULL;
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;
}
}
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;
}
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) {
nfs_set_gid
nfs_set_tcp_syncnt
nfs_set_uid
+nfs_set_readahead
nfs_stat
nfs_stat_async
nfs_stat64
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
#include <sys/stat.h>
#include <fcntl.h>
#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 {
uint64_t readmax;
uint64_t writemax;
char *cwd;
+ struct nfsdir *dircache;
};
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;
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;
};
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)
{
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;
}
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);
}
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;
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);
}
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);
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);
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);
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;
}
}
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;
}
-
-
-
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;
}
}
-
-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;
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);
}
}
}
-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
*/
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;
struct nfs_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs;
LOOKUP3res *res;
+ fattr3 *attr;
assert(rpc->magic == RPC_CONTEXT_MAGIC);
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;
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;
/* /$ -> \0 */
len = strlen(path);
- if (len >= 1) {
+ if (len > 1) {
if (path[len - 1] == '/') {
path[len - 1] = '\0';
len--;
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 = ".";
}
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()
*/
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;
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;
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;
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;
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;
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;
/*
* 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);
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!");
}
}
/* 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++;
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;
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;
mdata->data = data;
mdata->offset = offset;
mdata->count = readcount;
+ mdata->update_pos = update_pos;
nfs_fill_READ3args(&args, nfsfh, offset, readcount);
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);
}
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;
}
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;
}
}
}
- 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;
}
}
}
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;
data->nfsfh = nfsfh;
data->usrbuf = buf;
- nfsfh->offset = offset;
-
/* hello, clang-analyzer */
assert(data->num_calls == 0);
* 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;
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);
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);
}
free(nfsfh->fh.data.data_val);
nfsfh->fh.data.data_val = NULL;
}
+ free(nfsfh->ra.buf);
free(nfsfh);
cb(0, nfs, NULL, private_data);
/*
* 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;
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;
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;
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;
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;
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;
nfsdirent->ctime.tv_usec = attributes->ctime.nseconds/1000;
nfsdirent->uid = attributes->uid;
nfsdirent->gid = attributes->gid;
+ nfsdirent->nlink = attributes->nlink;
}
}
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++;
}
}
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;
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;
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;
/*
* 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);
}
struct lseek_cb_data {
struct nfs_context *nfs;
struct nfsfh *nfsfh;
- uint64_t offset;
+ int64_t offset;
nfs_cb cb;
void *private_data;
};
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);
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;
}
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)
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;
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;
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;
}
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;
}
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;
}
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;
}
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;
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;
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;
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;
}
-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);
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;
}
-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;
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;
}
}
-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;
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;
}
#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;
/* 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;
}
}
memcpy(pdu->outdata.data, rpc->encodebuf, pdu->outdata.size);
- SLIST_ADD_END(&rpc->outqueue, pdu);
+ rpc_enqueue(&rpc->outqueue, pdu);
return 0;
}
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;
}
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");
#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);
#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)
{
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;
return POLLIN;
}
- if (rpc->outqueue) {
+ if (rpc_has_queue(&rpc->outqueue)) {
events |= POLLOUT;
}
return events;
static int rpc_write_to_socket(struct rpc_context *rpc)
{
int32_t count;
+ struct rpc_pdu *pdu;
assert(rpc->magic == RPC_CONTEXT_MAGIC);
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;
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;
}
}
- 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;
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:
* 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;
/* 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)
}
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);
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);
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;
}
rpc->connect_cb = cb;
rpc->connect_data = private_data;
+ freeaddrinfo(ai);
+
if (rpc_connect_sockaddr_async(rpc, &rpc->s) != 0) {
return -1;
}
static int rpc_reconnect_requeue(struct rpc_context *rpc)
{
struct rpc_pdu *pdu;
+ unsigned int i;
assert(rpc->magic == RPC_CONTEXT_MAGIC);
/* 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) {
{
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;
}
rm -f $(mount_GENERATED)
touch mount-stamp
-compile_rpc:
- rpcgen -h mount.x | sed -e "s/#include <rpc\/rpc.h>//" | 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 <rpc\/rpc.h>//" | 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
+/*
+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.
+/*
+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.
#ifndef _MOUNT_H_RPCGEN
#define _MOUNT_H_RPCGEN
-#include <nfsc/libnfs-zdr.h>
+
+
#ifdef __cplusplus
extern "C" {
-/* 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 */
touch nfs-stamp
compile_rpc:
- rpcgen -h nfs.x | sed -e "s/#include <rpc\/rpc.h>//" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/#define _NFS_H_RPCGEN/#define _NFS_H_RPCGEN\n#include <nfsc\/libnfs-zdr.h>/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 <rpc\/rpc.h>//" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/#define _NFS_H_RPCGEN/#define _NFS_H_RPCGEN\n#include <nfsc\/libnfs-zdr.h>/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
+/*
+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.
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;
}
register int32_t *buf;
buf = NULL;
- if (!zdr_uint64 (zdrs, objp))
+ if (!zdr_u_quad_t (zdrs, objp))
return FALSE;
return TRUE;
}
register int32_t *buf;
buf = NULL;
- if (!zdr_uint64 (zdrs, objp))
+ if (!zdr_u_quad_t (zdrs, objp))
return FALSE;
return TRUE;
}
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;
register int32_t *buf;
buf = NULL;
- if (!zdr_uint64 (zdrs, objp))
+ if (!zdr_u_quad_t (zdrs, objp))
return FALSE;
return TRUE;
}
+/*
+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.
typedef char cookieverf3[NFS3_COOKIEVERFSIZE];
-typedef u_quad_t uint64;
-
-typedef uint64 cookie3;
+typedef u_quad_t cookie3;
struct nfs_fh3 {
struct {
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;
size3 size;
size3 used;
specdata3 rdev;
- uint64 fsid;
+ u_quad_t fsid;
fileid3 fileid;
nfstime3 atime;
nfstime3 mtime;
};
typedef enum stable_how stable_how;
-typedef uint64 offset3;
+typedef u_quad_t offset3;
typedef u_int count3;
#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*);
#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 ();
-/* 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
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<NFS3_FHSIZE>;
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;
size3 size;
size3 used;
specdata3 rdev;
- uint64 fsid;
+ u_quad_t fsid;
fileid3 fileid;
nfstime3 atime;
nfstime3 mtime;
FILE_SYNC = 2
};
-typedef uint64 offset3;
+typedef u_quad_t offset3;
typedef unsigned int count3;
touch nlm-stamp
compile_rpc:
- rpcgen -h nlm.x | sed -e "s/#include <rpc\/rpc.h>//" | 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 <rpc\/rpc.h>//" | 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
+/*
+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.
+/*
+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.
#ifndef _NLM_H_RPCGEN
#define _NLM_H_RPCGEN
-#include <nfsc/libnfs-zdr.h>
+
+
#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 {
-/* 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<>;
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;
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 {
touch nsm-stamp
compile_rpc:
- rpcgen -h nsm.x | sed -e "s/#include <rpc\/rpc.h>//" | 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 <rpc\/rpc.h>//" | 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
+/*
+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.
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))
+/*
+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.
/*
- * 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
%{_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
- 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
touch portmap-stamp
compile_rpc:
- rpcgen -h portmap.x | sed -e "s/#include <rpc\/rpc.h>//" | 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 <rpc\/rpc.h>//" | 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
+/*
+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.
#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;
}
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;
}
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;
}
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;
}
+/*
+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.
#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;
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 */
#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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
/*
- * 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;
rquota-stamp : rquota.x
rm -f $(rquota_GENERATED)
touch rquota-stamp
-
+
compile_rpc:
- rpcgen -h rquota.x | sed -e "s/#include <rpc\/rpc.h>//" | 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 <rpc\/rpc.h>//" | 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
+/*
+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.
+/*
+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.
#ifndef _RQUOTA_H_RPCGEN
#define _RQUOTA_H_RPCGEN
-#include <nfsc/libnfs-zdr.h>
+
+
#ifdef __cplusplus
extern "C" {
-/* 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 */
--- /dev/null
+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
struct nfsdirent *nfsdirent;
struct statvfs svfs;
struct nfsdir *nfsdir;
- struct nfs_stat_64 st;
if (!level) {
printf("Recursion detected!\n");
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");
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);
}
}
uint64_t offset;
struct client client;
struct statvfs stvfs;
- struct nfs_url *url;
+ struct nfs_url *url = NULL;
exports export, tmp;
#ifdef WIN32
+/*
+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_