Merge pull request #47 from Memphiz/win32fix3
authorRonnie Sahlberg <ronniesahlberg@gmail.com>
Sun, 12 Jan 2014 23:18:59 +0000 (15:18 -0800)
committerRonnie Sahlberg <ronniesahlberg@gmail.com>
Sun, 12 Jan 2014 23:18:59 +0000 (15:18 -0800)
[win32] - fixed bad number casting when using libnfs on 64bit win8 syste...

35 files changed:
Makefile.am
README
aros/Makefile.AROS
configure.ac
examples/Makefile.am
examples/fuse_nfs.c [new file with mode: 0644]
examples/nfs-cp.c
examples/nfs-io.c [new file with mode: 0644]
examples/nfs-ls.c
examples/nfsclient-raw.c
examples/nfsclient-sync.c
include/Makefile.am
include/libnfs-private.h
include/nfsc/libnfs-raw.h
include/nfsc/libnfs.h
lib/Makefile.am
lib/init.c
lib/libnfs-win32.def
lib/libnfs-zdr.c
lib/libnfs.c
lib/pdu.c
lib/socket.c
libnfs.pc.in
mount/mount.c
nfs/Makefile.am
nfs/libnfs-raw-nfs.c
nfs/libnfs-raw-nfs.h
nfs/nfs.c
nfs/nfs.x
nsm/Makefile.am [new file with mode: 0644]
nsm/libnfs-raw-nsm.c [new file with mode: 0644]
nsm/libnfs-raw-nsm.h [new file with mode: 0644]
nsm/nsm.c [new file with mode: 0644]
nsm/nsm.x [new file with mode: 0644]
packaging/RPM/libnfs.spec.in

index 18277c0de522792a6e219b78355ce6e840fdbee9..3dec3434e6a4dad3989ef78f0a33cd9c993c0e80 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = mount nfs nlm portmap rquota lib include . $(MAYBE_EXAMPLES)
+SUBDIRS = mount nfs nlm nsm portmap rquota lib include . $(MAYBE_EXAMPLES)
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libnfs.pc
diff --git a/README b/README
index 4115911b561300fe03e2bcf00cdc49ac004ace45..6d3eb739a34ba22c26e337effaa265a80fa32acb 100644 (file)
--- a/README
+++ b/README
@@ -23,6 +23,21 @@ stat(), read(), ...
 
 examples/nfsclient-sync.c provides examples on how to use this API
 
+URL-FORMAT:
+===========
+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]*]
+
+Arguments supported by libnfs are :
+ tcp-syncnt=<int>  : Number of SYNs to send during the seccion establish
+                     before failing settin up the tcp connection to the
+                     server.
+ uid=<int>         : UID value to use when talking to the server.
+                     default it 65534 on Windows and getuid() on unixen.
+ gid=<int>         : GID value to use when talking to the server.
+                     default it 65534 on Windows and getgid() on unixen.
 
 
 ROOT vs NON-ROOT
@@ -47,6 +62,14 @@ This is highly non-portable so IF this works on your linux system, count
 yourself lucky.
 
 
+FUSE
+====
+A simple FUSE filesystem built on libnfs can be found in
+examples/fuse_nfs.c
+
+Compile using : gcc fuse_nfs.c -o fuse_nfs -lfuse -lnfs
+Mount using : sudo ./fuse_nfs -n nfs://<server>/<export> -m <mountpoint>
+
 
 PLATFORM support
 =================
index 6d39137f5cbaa24a1616e939c0ec44f9fbe7a78a..9c97dc0d1f180469f4ff46cf1b667ae6eb007e4c 100755 (executable)
@@ -21,6 +21,18 @@ lib/libnfs.a: $(OBJS)
        echo $(CC) $(CFLAGS) -c -o $@ $<
        $(CC) $(CFLAGS) -c -o $@ $<
 
+install: all
+       cp lib/libnfs.a GCC:lib
+       mkdir -p INCLUDE:nfsc
+       cp include/nfsc/libnfs.h INCLUDE:nfsc
+       cp include/nfsc/libnfs-raw.h INCLUDE:nfsc
+       cp include/nfsc/libnfs-zdr.h INCLUDE:nfsc
+       cp mount/libnfs-raw-mount.h INCLUDE:nfsc
+       cp nlm/libnfs-raw-nlm.h INCLUDE:nfsc
+       cp nfs/libnfs-raw-nfs.h INCLUDE:nfsc
+       cp portmap/libnfs-raw-portmap.h INCLUDE:nfsc
+       cp rquota/libnfs-raw-rquota.h INCLUDE:nfsc
+
 examples/nfsclient-listservers: examples/nfsclient-listservers.c lib/libnfs.a
        $(CC) $(CFLAGS) -o $@ $< lib/libnfs.a
 
index e5b170eb424f6432c0db534d4542f8b85e8e8f9b..98599ee22de218fff905f1bd92dbe3cb5555da38 100644 (file)
@@ -1,5 +1,5 @@
 AC_PREREQ(2.50)
-AC_INIT([libnfs], [1.6.0], [ronniesahlberg@gmail.com])
+AC_INIT([libnfs], [1.8.90], [ronniesahlberg@gmail.com])
 AC_CONFIG_HEADERS([config.h])
 AM_INIT_AUTOMAKE([foreign])
 AC_CANONICAL_HOST
@@ -121,6 +121,10 @@ AC_CHECK_HEADERS([sys/statvfs.h])
 dnl Check for sys/socket.h
 AC_CHECK_HEADERS([sys/socket.h])
 
+# check for netinet/tcp.h
+dnl Check for netinet/tcp.h
+AC_CHECK_HEADERS([netinet/tcp.h])
+
 # check for netinet/in.h
 dnl Check for netinet/in.h
 AC_CHECK_HEADERS([netinet/in.h])
@@ -156,6 +160,7 @@ AC_CONFIG_FILES([Makefile]
                 [mount/Makefile]
                 [nfs/Makefile]
                 [nlm/Makefile]
+                [nsm/Makefile]
                 [portmap/Makefile]
                 [rquota/Makefile]
                 [examples/Makefile]
index 200ba115fb44b7898d904b9522628e0c513601ca..39f5a17eea57d402499c5de6951ad3f22078a2cc 100644 (file)
@@ -1,12 +1,12 @@
-noinst_PROGRAMS = nfsclient-async nfsclient-raw nfsclient-sync nfsclient-bcast nfsclient-listservers nfs-ls nfs-cp
+noinst_PROGRAMS = nfsclient-async nfsclient-raw nfsclient-sync nfsclient-bcast nfsclient-listservers nfs-ls nfs-cp nfs-io
 
 AM_CPPFLAGS = \
        -I$(abs_top_srcdir)/include \
        -I$(abs_top_srcdir)/include/nfsc \
-       -I../mount \
-       -I../nfs \
-       -I../rquota \
-       -I../portmap \
+       -I$(abs_top_srcdir)/mount \
+       -I$(abs_top_srcdir)/nfs \
+       -I$(abs_top_srcdir)/rquota \
+       -I$(abs_top_srcdir)/portmap \
        "-D_U_=__attribute__((unused))"
 
 AM_LDFLAGS = ../lib/.libs/libnfs.la -lpopt
@@ -15,6 +15,8 @@ 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
diff --git a/examples/fuse_nfs.c b/examples/fuse_nfs.c
new file mode 100644 (file)
index 0000000..261a6aa
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+   Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2013
+   
+   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/>.
+*/
+/* A FUSE filesystem based on libnfs. */
+
+#define FUSE_USE_VERSION 26
+#define _FILE_OFFSET_BITS 64
+
+#include <fuse.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+
+#include <nfsc/libnfs.h>
+
+#define discard_const(ptr) ((void *)((intptr_t)(ptr)))
+
+struct nfs_context *nfs = NULL;
+
+static int fuse_nfs_getattr(const char *path, struct stat *stbuf)
+{
+       int ret = 0;
+
+       memset(stbuf, 0, sizeof(struct stat));
+       ret = nfs_stat(nfs, path, stbuf);
+
+       return ret;
+}
+
+static int fuse_nfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+                        off_t offset, struct fuse_file_info *fi)
+{
+       struct nfsdir *nfsdir;
+       struct nfsdirent *nfsdirent;
+
+       int ret = 0;
+
+       ret = nfs_opendir(nfs, path, &nfsdir);
+       if (ret < 0) {
+               return ret;
+       }
+       while ((nfsdirent = nfs_readdir(nfs, nfsdir)) != NULL) {
+               filler(buf, nfsdirent->name, NULL, 0);
+       }
+
+       return ret;
+}
+
+static int fuse_nfs_open(const char *path, struct fuse_file_info *fi)
+{
+       int ret = 0;
+       struct nfsfh *nfsfh;
+
+       fi->fh = 0;
+       ret = nfs_open(nfs, path, fi->flags, &nfsfh);
+       if (ret < 0) {
+               return ret;
+       }
+
+       fi->fh = (uint64_t)nfsfh;
+
+       return ret;
+}
+
+static int fuse_nfs_release(const char *path, struct fuse_file_info *fi)
+{
+       struct nfsfh *nfsfh = (struct nfsfh *)fi->fh;
+
+       nfs_close(nfs, nfsfh);
+       return 0;
+}
+
+static int fuse_nfs_read(const char *path, char *buf, size_t size,
+       off_t offset, struct fuse_file_info *fi)
+{
+       int ret = 0;
+       struct nfsfh *nfsfh = (struct nfsfh *)fi->fh;
+
+       ret = nfs_pread(nfs, nfsfh, offset, size, buf);
+
+       return ret;
+}
+
+static int fuse_nfs_write(const char *path, const char *buf, size_t size,
+       off_t offset, struct fuse_file_info *fi)
+{
+       int ret = 0;
+       struct nfsfh *nfsfh = (struct nfsfh *)fi->fh;
+
+       ret = nfs_pwrite(nfs, nfsfh, offset, size, discard_const(buf));
+
+       return ret;
+}
+
+static int fuse_nfs_create(const char *path, mode_t mode, struct fuse_file_info *fi)
+{
+       int ret = 0;
+       struct nfsfh *nfsfh;
+
+       ret = nfs_creat(nfs, path, mode, &nfsfh);
+       if (ret < 0) {
+               return ret;
+       }
+
+       fi->fh = (uint64_t)nfsfh;
+
+       return ret;
+}
+
+static int fuse_nfs_utime(const char *path, struct utimbuf *times)
+{
+       int ret = 0;
+
+       ret = nfs_utime(nfs, path, times);
+       if (ret < 0) {
+               return ret;
+       }
+
+       return ret;
+}
+
+static int fuse_nfs_unlink(const char *path)
+{
+       int ret = 0;
+
+       ret = nfs_unlink(nfs, path);
+       if (ret < 0) {
+               return ret;
+       }
+
+       return ret;
+}
+
+static int fuse_nfs_rmdir(const char *path)
+{
+       int ret = 0;
+
+       ret = nfs_rmdir(nfs, path);
+       if (ret < 0) {
+               return ret;
+       }
+
+       return ret;
+}
+
+static int fuse_nfs_mkdir(const char *path, mode_t mode)
+{
+       int ret = 0;
+
+       ret = nfs_mkdir(nfs, path);
+       if (ret < 0) {
+               return ret;
+       }
+       ret = nfs_chmod(nfs, path, mode);
+       if (ret < 0) {
+               return ret;
+       }
+
+       return ret;
+}
+
+static struct fuse_operations nfs_oper = {
+       .create         = fuse_nfs_create,
+       .getattr        = fuse_nfs_getattr,
+       .mkdir          = fuse_nfs_mkdir,
+       .open           = fuse_nfs_open,
+       .read           = fuse_nfs_read,
+       .readdir        = fuse_nfs_readdir,
+       .release        = fuse_nfs_release,
+       .rmdir          = fuse_nfs_rmdir,
+       .unlink         = fuse_nfs_unlink,
+       .utime          = fuse_nfs_utime,
+       .write          = fuse_nfs_write,
+};
+
+void print_usage(char *name)
+{
+       printf("Usage: %s [-?|--help] [-n|--nfs-share=nfs-url] mountpoint\n",
+               name);
+       exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+       int ret = 0;
+       static struct option long_opts[] = {
+               { "help", no_argument, 0, '?' },
+               { "nfs-share", required_argument, 0, 'n' },
+               { "mountpoint", required_argument, 0, 'm' },
+               { NULL, 0, 0, 0 }
+       };
+       int c;
+       int opt_idx = 0;
+       char *url = NULL;
+       char *mnt = NULL;
+       char *server = NULL, *export = NULL, *strp;
+       int fuse_nfs_argc = 5;
+       char *fuse_nfs_argv[16] = {
+               "fuse-nfs",
+               "<export>",
+               "-oallow_other",
+               "-odefault_permissions",
+               "-omax_write=32768",
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+        };
+
+       while ((c = getopt_long(argc, argv, "?hm:n:", long_opts,
+                   &opt_idx)) > 0) {
+               switch (c) {
+               case 'h':
+               case '?':
+                       print_usage(argv[0]);
+                       return 0;
+               case 'm':
+                       mnt = strdup(optarg);
+                       break;
+               case 'n':
+                       url = strdup(optarg);
+                       break;
+               }
+       }
+
+       if (url == NULL) {
+               fprintf(stderr, "-n was not specified.\n");
+               ret = 10;
+               goto finished;
+       }
+       if (mnt == NULL) {
+               fprintf(stderr, "-m was not specified.\n");
+               ret = 10;
+               goto finished;
+       }
+
+
+       if (strncmp(url, "nfs://", 6)) {
+               fprintf(stderr, "Invalid URL specified.\n");
+               ret = 10;
+               goto finished;
+       }
+       server = strdup(url + 6);
+       if (server == NULL) {
+               fprintf(stderr, "Failed to strdup server string\n");
+               ret = 10;
+               goto finished;
+       }
+       if (server[0] == '/' || server[0] == '\0') {
+               fprintf(stderr, "Invalid server string.\n");
+               ret = 10;
+               goto finished;
+       }
+       strp = strchr(server, '/');
+       if (strp == NULL) {
+               fprintf(stderr, "Invalid URL specified.\n");
+               ret = 10;
+               goto finished;
+       }
+       export = strdup(strp);
+       if (export == NULL) {
+               fprintf(stderr, "Failed to strdup server string\n");
+               ret = 10;
+               goto finished;
+       }
+       if (export[0] != '/') {
+               fprintf(stderr, "Invalid export.\n");
+               ret = 10;
+               goto finished;
+       }
+       *strp = 0;
+
+       nfs = nfs_init_context();
+       if (nfs == NULL) {
+               printf("failed to init context\n");
+               goto finished;
+       }
+
+       ret = nfs_mount(nfs, server, export);
+       if (ret != 0) {
+               printf("Failed to mount nfs share : %s\n", nfs_get_error(nfs));
+               goto finished;
+       }
+
+
+       fuse_nfs_argv[1] = mnt;
+       return fuse_main(fuse_nfs_argc, fuse_nfs_argv, &nfs_oper, NULL);
+
+finished:
+       if (nfs != NULL) {
+               nfs_destroy_context(nfs);
+       }
+       free(server);
+       free(export);
+       free(url);
+       free(mnt);
+       return ret;
+}
index 3d25189ca57b263718e60bd4c9af2557f17dfef7..fe9911de50b6e79c520086ab0413b23db05fd975 100644 (file)
@@ -59,6 +59,7 @@ struct file_context {
        int fd;
        struct nfs_context *nfs;
        struct nfsfh *nfsfh;
+       struct nfs_url *url;
 };
 
 void usage(void)
@@ -81,6 +82,7 @@ free_file_context(struct file_context *file_context)
        if (file_context->nfs != NULL) {
                nfs_destroy_context(file_context->nfs);
        }
+       nfs_destroy_url(file_context->url);
        free(file_context);
 }
 
@@ -120,7 +122,6 @@ static struct file_context *
 open_file(const char *url, int flags)
 {
        struct file_context *file_context;
-       char *server = NULL, *path = NULL, *file = NULL, *strp;
 
        file_context = malloc(sizeof(struct file_context));
        if (file_context == NULL) {
@@ -131,8 +132,8 @@ open_file(const char *url, int flags)
        file_context->fd     = -1;
        file_context->nfs    = NULL;
        file_context->nfsfh  = NULL;
+       file_context->url    = NULL;
        
-
        if (strncmp(url, "nfs://", 6)) {
                file_context->is_nfs = 0;
                file_context->fd = open(url, flags, 0660);
@@ -153,77 +154,40 @@ open_file(const char *url, int flags)
                return NULL;
        }
 
-       server = strdup(url + 6);
-       if (server == NULL) {
-               fprintf(stderr, "Failed to strdup server string\n");
-               free_file_context(file_context);
-               return NULL;
-       }
-       if (server[0] == '/' || server[0] == '\0') {
-               fprintf(stderr, "Invalid server string.\n");
-               free(server);
-               free_file_context(file_context);
-               return NULL;
-       }
-       strp = strchr(server, '/');
-       path = strdup(strp);
-       *strp = 0;
-       if (path == NULL) {
-               fprintf(stderr, "Invalid URL specified.\n");
-               free(server);
+       file_context->url = nfs_parse_url_full(file_context->nfs, url);
+       if (file_context->url == NULL) {
+               fprintf(stderr, "%s\n", nfs_get_error(file_context->nfs));
                free_file_context(file_context);
                return NULL;
        }
 
-       strp = strrchr(path, '/');
-       if (strp == NULL) {
-               fprintf(stderr, "Invalid URL specified.\n");
-               free(path);
-               free(server);
-               free_file_context(file_context);
-               return NULL;
-       }
-       file = strdup(strp);
-       *strp = 0;
-
-       if (nfs_mount(file_context->nfs, server, path) != 0) {
-               fprintf(stderr, "Failed to mount nfs share : %s\n",
+       if (nfs_mount(file_context->nfs, file_context->url->server,
+                               file_context->url->path) != 0) {
+               fprintf(stderr, "Failed to mount nfs share : %s\n",
                               nfs_get_error(file_context->nfs));
-               free(file);
-               free(path);
-               free(server);
                free_file_context(file_context);
                return NULL;
        }
 
        if (flags == O_RDONLY) {
-               if (nfs_open(file_context->nfs, file, flags,
+               if (nfs_open(file_context->nfs, file_context->url->file, flags,
                                &file_context->nfsfh) != 0) {
-                       fprintf(stderr, "Failed to open file : %s\n",
+                       fprintf(stderr, "Failed to open file %s: %s\n",
+                                      file_context->url->file,
                                       nfs_get_error(file_context->nfs));
-                       free(file);
-                       free(path);
-                       free(server);
                        free_file_context(file_context);
                        return NULL;
                }
        } else {
-               if (nfs_creat(file_context->nfs, file, 0660,
+               if (nfs_creat(file_context->nfs, file_context->url->file, 0660,
                                &file_context->nfsfh) != 0) {
-                       fprintf(stderr, "Failed to creat file %s  %s\n", file,
+                       fprintf(stderr, "Failed to creat file %s: %s\n",
+                                      file_context->url->file,
                                       nfs_get_error(file_context->nfs));
-                       free(file);
-                       free(path);
-                       free(server);
                        free_file_context(file_context);
                        return NULL;
                }
        }
-
-       free(file);
-       free(path);
-       free(server);
-
        return file_context;
 }
 
@@ -297,7 +261,7 @@ int main(int argc, char *argv[])
 
                off += count;
        }
-       printf("copied %d bytes\n", (int)count);
+       printf("copied %d bytes\n", (int)off);
 
        free_file_context(src);
        free_file_context(dst);
diff --git a/examples/nfs-io.c b/examples/nfs-io.c
new file mode 100644 (file)
index 0000000..bda05d5
--- /dev/null
@@ -0,0 +1,177 @@
+/* 
+   Copyright (C) by Peter Lieven <pl@kamp.de> 2013
+   
+   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/>.
+*/
+
+#define _FILE_OFFSET_BITS 64
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef AROS
+#include "aros_compat.h"
+#endif
+#ifdef WIN32
+#include "win32_compat.h"
+#pragma comment(lib, "ws2_32.lib")
+WSADATA wsaData;
+#define PRId64 "ll"
+#else
+#include <inttypes.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#ifndef AROS
+#include <sys/statvfs.h>
+#endif
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "libnfs-zdr.h"
+#include "libnfs.h"
+#include "libnfs-raw.h"
+#include "libnfs-raw-mount.h"
+
+void print_usage(void)
+{
+       fprintf(stderr, "Usage: nfs-io [-?|--help|--usage] [stat|creat|unlink|mkdir|rmdir] <url>\n");
+}
+
+int main(int argc, char *argv[])
+{
+       int ret = 1;
+       struct nfs_context *nfs = NULL;
+       struct nfsfh *nfsfh = NULL;
+       struct nfs_url *url = NULL;
+
+#ifdef WIN32
+       if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
+               printf("Failed to start Winsock2\n");
+               exit(10);
+       }
+#endif
+
+#ifdef AROS
+       aros_init_socket();
+#endif
+
+       if (argc < 3) {
+               fprintf(stderr, "No URL specified.\n");
+               goto finished;
+       }
+
+       nfs = nfs_init_context();
+       if (nfs == NULL) {
+               printf("failed to init context\n");
+               goto finished;
+       }
+
+       url = nfs_parse_url_full(nfs, argv[argc - 1]);
+       if (url == NULL) {
+               fprintf(stderr, "%s\n", nfs_get_error(nfs));
+               goto finished;
+       }
+
+       if (nfs_mount(nfs, url->server, url->path) != 0) {
+               fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs));
+               goto finished;
+       }
+
+       if (!strncmp(argv[1], "creat", 5)) {
+               ret = nfs_creat(nfs, url->file, 0600, &nfsfh);
+       } else if (!strncmp(argv[1], "unlink", 6)) {
+               ret = nfs_unlink(nfs, url->file);
+       } else if (!strncmp(argv[1], "mkdir", 5)) {
+               ret = nfs_mkdir(nfs, url->file);
+       } else if (!strncmp(argv[1], "rmdir", 5)) {
+               ret = nfs_rmdir(nfs, url->file);
+       } else if (!strncmp(argv[1], "stat", 4)) {
+               struct stat st;
+               ret = nfs_stat(nfs, url->file, &st);
+               if (!ret) {
+                       switch (st.st_mode & S_IFMT) {
+       #ifndef WIN32
+                       case S_IFLNK:
+                               printf("l");
+                               break;
+       #endif
+                       case S_IFREG:
+                               printf("-");
+                               break;
+                       case S_IFDIR:
+                               printf("d");
+                               break;
+                       case S_IFCHR:
+                               printf("c");
+                               break;
+                       case S_IFBLK:
+                               printf("b");
+                               break;
+                       }
+                       printf("%c%c%c",
+                               "-r"[!!(st.st_mode & S_IRUSR)],
+                               "-w"[!!(st.st_mode & S_IWUSR)],
+                               "-x"[!!(st.st_mode & S_IXUSR)]
+                       );
+                       printf("%c%c%c",
+                               "-r"[!!(st.st_mode & S_IRGRP)],
+                               "-w"[!!(st.st_mode & S_IWGRP)],
+                               "-x"[!!(st.st_mode & S_IXGRP)]
+                       );
+                       printf("%c%c%c",
+                               "-r"[!!(st.st_mode & S_IROTH)],
+                               "-w"[!!(st.st_mode & S_IWOTH)],
+                               "-x"[!!(st.st_mode & S_IXOTH)]
+                       );
+                       printf(" %2d", (int) st.st_nlink);
+                       printf(" %5d", st.st_uid);
+                       printf(" %5d", st.st_gid);
+                       printf(" %12" PRId64, st.st_size);
+                       printf("\n");
+               }
+       } else {
+               goto finished;
+       }
+       
+       if (ret) {
+               fprintf(stderr, "ERROR: %s\n", nfs_get_error(nfs));
+       }
+
+finished:
+       if (ret > 0) {
+               print_usage();
+       }
+       nfs_destroy_url(url);
+       if (nfs != NULL) {              
+               if (nfsfh) {
+                       nfs_close(nfs, nfsfh);
+               }
+               nfs_destroy_context(nfs);
+       }
+       return !!ret;
+}
+
index e0131c8b745d719daaa34f7ca8e62103eca9463c..e87ffa82b91cc11162d52629037398e02a0bd4df 100644 (file)
@@ -35,6 +35,7 @@ WSADATA wsaData;
 #include <inttypes.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <sys/statvfs.h>
 #ifndef AROS
 #include <sys/statvfs.h>
 #endif
@@ -62,103 +63,44 @@ struct client {
        int is_finished;
 };
 
+int recursive = 0, summary = 0, discovery = 0;
+
 void print_usage(void)
 {
-       fprintf(stderr, "Usage: nfs-ls [-?|--help] [--usage] <url>\n");
+       fprintf(stderr, "Usage: nfs-ls [-?|--help|--usage] [-R|--recursive] [-s|--summary] [-D|--discovery] <url>\n");
 }
 
-int main(int argc, char *argv[])
-{
-       struct nfs_context *nfs = NULL;
-       int i, ret, res;
-       uint64_t offset;
-       struct client client;
-       struct stat st;
-       struct nfsfh  *nfsfh;
-       struct nfsdir *nfsdir;
-       struct nfsdirent *nfsdirent;
-       struct statvfs svfs;
-       exports export, tmp;
-       const char *url = NULL;
-       char *server = NULL, *path = NULL, *strp;
+int process_server(const char *server) {
+       struct exportnode *exports;
+       struct exportnode *export;
 
-#ifdef WIN32
-       if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
-               printf("Failed to start Winsock2\n");
-               exit(10);
-       }
-#endif
-
-#ifdef AROS
-       aros_init_socket();
-#endif
-
-       url = argv[1];
-
-       if (url == NULL) {
-               fprintf(stderr, "No URL specified.\n");
-               print_usage();
-               exit(0);
+       exports = mount_getexports(server);
+       if (exports == NULL) {
+               fprintf(stderr, "Failed to get exports for server %s.\n", server);
+               return -1;
        }
-
-       if (strncmp(url, "nfs://", 6)) {
-               fprintf(stderr, "Invalid URL specified.\n");
-               print_usage();
-               exit(0);
+       for (export=exports; export; export = export->ex_next) {
+               printf("nfs://%s%s\n", server, export->ex_dir);
        }
+       mount_free_export_list(exports);
+       return 0;
+}
 
-       server = strdup(url + 6);
-       if (server == NULL) {
-               fprintf(stderr, "Failed to strdup server string\n");
-               exit(10);
-       }
-       if (server[0] == '/' || server[0] == '\0') {
-               fprintf(stderr, "Invalid server string.\n");
-               free(server);
-               exit(10);
-       }
-       strp = strchr(server, '/');
-       if (strp == NULL) {
-               fprintf(stderr, "Invalid URL specified.\n");
-               print_usage();
-               free(server);
-               exit(0);
-       }
-       path = strdup(strp);
-       if (path == NULL) {
-               fprintf(stderr, "Failed to strdup server string\n");
-               free(server);
-               exit(10);
-       }
-       if (path[0] != '/') {
-               fprintf(stderr, "Invalid path.\n");
-               free(server);
-               free(path);
+void process_dir(struct nfs_context *nfs, char *dir, int level) {
+       int ret;
+       struct nfsdirent *nfsdirent;
+       struct statvfs svfs;
+       struct nfsdir *nfsdir;
+       struct stat st;
+       
+       if (!level) {
+               printf("Recursion detected!\n");
                exit(10);
        }
-       *strp = 0;
        
-       client.server = server;
-       client.export = path;
-       client.is_finished = 0;
-
-
-       nfs = nfs_init_context();
-       if (nfs == NULL) {
-               printf("failed to init context\n");
-               goto finished;
-       }
-
-       ret = nfs_mount(nfs, client.server, client.export);
-       if (ret != 0) {
-               printf("Failed to mount nfs share : %s\n", nfs_get_error(nfs));
-               goto finished;
-       }
-
-
-       ret = nfs_opendir(nfs, "/", &nfsdir);
+       ret = nfs_opendir(nfs, dir, &nfsdir);
        if (ret != 0) {
-               printf("Failed to opendir(\"/\")\n", nfs_get_error(nfs));
+               printf("Failed to opendir(\"%s\") %s\n", dir, nfs_get_error(nfs));
                exit(10);
        }
        while((nfsdirent = nfs_readdir(nfs, nfsdir)) != NULL) {
@@ -168,7 +110,7 @@ int main(int argc, char *argv[])
                        continue;
                }
 
-               sprintf(path, "%s/%s", "/", nfsdirent->name);
+               snprintf(path, 1024, "%s/%s", dir, nfsdirent->name);
                ret = nfs_stat(nfs, path, &st);
                if (ret != 0) {
                        fprintf(stderr, "Failed to stat(%s) %s\n", path, nfs_get_error(nfs));
@@ -178,6 +120,8 @@ int main(int argc, char *argv[])
                switch (st.st_mode & S_IFMT) {
 #ifndef WIN32
                case S_IFLNK:
+                       printf("l");
+                       break;
 #endif
                case S_IFREG:
                        printf("-");
@@ -207,22 +151,130 @@ int main(int argc, char *argv[])
                        "-w"[!!(st.st_mode & S_IWOTH)],
                        "-x"[!!(st.st_mode & S_IXOTH)]
                );
-               printf(" %2d", st.st_nlink);
+               printf(" %2d", (int) st.st_nlink);
                printf(" %5d", st.st_uid);
                printf(" %5d", st.st_gid);
                printf(" %12" PRId64, st.st_size);
 
-               printf(" %s\n", nfsdirent->name);
+               printf(" %s\n", path + 1);
+               
+               if (recursive && (st.st_mode & S_IFMT) == S_IFDIR) {
+                       process_dir(nfs, path, level - 1);
+               }
        }
        nfs_closedir(nfs, nfsdir);
+}
 
+int main(int argc, char *argv[])
+{
+       struct nfs_context *nfs = NULL;
+       int i, ret = 1, res;
+       uint64_t offset;
+       struct client client;
+       struct statvfs stvfs;
+       struct nfs_url *url;
+       exports export, tmp;
 
+#ifdef WIN32
+       if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
+               printf("Failed to start Winsock2\n");
+               exit(10);
+       }
+#endif
+
+#ifdef AROS
+       aros_init_socket();
+#endif
+
+       if (argc < 2) {
+               fprintf(stderr, "No URL specified.\n");
+               goto finished;
+       }
+
+       for (i=1; i < argc -1; i++) {
+               if (!strcmp(argv[i], "-R") || !strcmp(argv[i], "--recursive")) {
+                       recursive++;
+               } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--summary")) {
+                       summary++;
+               } else if (!strcmp(argv[i], "-D") || !strcmp(argv[i], "--discovery")) {
+                       discovery++;
+               } else{
+                       goto finished;
+               }
+       }
+
+       nfs = nfs_init_context();
+       if (nfs == NULL) {
+               printf("failed to init context\n");
+               goto finished;
+       }
+
+       if (discovery) {
+               url = nfs_parse_url_incomplete(nfs, argv[argc - 1]);
+               if (url == NULL) {
+                       fprintf(stderr, "%s\n", nfs_get_error(nfs));
+                       goto finished;
+               }
+               if (!url->server) {
+                       struct nfs_server_list *srvrs;
+                       struct nfs_server_list *srv;
+
+                       srvrs = nfs_find_local_servers();
+                       if (srvrs == NULL) {
+                               fprintf(stderr, "Failed to find local servers.\n");
+                               goto finished;
+                       }
+                       for (srv=srvrs; srv; srv = srv->next) {
+                               if (recursive) {
+                                       process_server(srv->addr);
+                               } else {
+                                       printf("nfs://%s\n", srv->addr);
+                               }
+                       }
+                       free_nfs_srvr_list(srvrs);
+                       ret = 0;
+                       goto finished;
+               }
+               if (url->server && !url->path) {
+                       ret = process_server(url->server);
+                       goto finished;
+               }
+               nfs_destroy_url(url);
+       }
+
+       url = nfs_parse_url_dir(nfs, argv[argc - 1]);
+       if (url == NULL) {
+               fprintf(stderr, "%s\n", nfs_get_error(nfs));
+               goto finished;
+       }
+
+       client.server = url->server;
+       client.export = url->path;
+       client.is_finished = 0;
+
+       if ((ret = nfs_mount(nfs, client.server, client.export)) != 0) {
+               fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs));
+               goto finished;
+       }
+
+       process_dir(nfs, "", 16);
+
+       if (summary) {
+               if (nfs_statvfs(nfs, "/", &stvfs) != 0) {
+                       goto finished;
+               }
+               printf("\n%12" PRId64 " of %12" PRId64 " bytes free.\n",
+                      stvfs.f_frsize * stvfs.f_bfree, stvfs.f_frsize * stvfs.f_blocks);
+       }
+
+       ret = 0;
 finished:
-       free(server);
-       free(path);
-       if (nfs != NULL) {              
+       if (ret > 0) {
+               print_usage();
+       }
+       nfs_destroy_url(url);
+       if (nfs != NULL) {
                nfs_destroy_context(nfs);
        }
-       return 0;
+       return ret;
 }
-
index 80a38f0a07944209137395477f87275ef9206438..28dd45ceccf77bc469a9d32cd420a8ae27e2d360 100644 (file)
@@ -85,7 +85,7 @@ void rquota_connect_cb(struct rpc_context *rpc, int status, void *data _U_, void
        printf("Connected to RPC.RQUOTAD on %s:%d\n", client->server, client->rquota_port);
        printf("Send GETQUOTA request for uid 100\n");
        if (rpc_rquota1_getquota_async(rpc, rquota_getquota_cb, EXPORT, 100, client) != 0) {
-               printf("Failed to send fsinfo request\n");
+               printf("Failed to send getquota request\n");
                exit(10);
        }
 }
@@ -170,6 +170,7 @@ void nfs_fsinfo_cb(struct rpc_context *rpc _U_, int status, void *data, void *pr
 void nfs_connect_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data)
 {
        struct client *client = private_data;
+       struct FSINFO3args args;
 
        if (status != RPC_STATUS_SUCCESS) {
                printf("connection to RPC.MOUNTD on server %s failed\n", client->server);
@@ -178,7 +179,8 @@ void nfs_connect_cb(struct rpc_context *rpc, int status, void *data _U_, void *p
 
        printf("Connected to RPC.NFSD on %s:%d\n", client->server, client->mount_port);
        printf("Send FSINFO request\n");
-       if (rpc_nfs_fsinfo_async(rpc, nfs_fsinfo_cb, &client->rootfh, client) != 0) {
+       args.fsroot = client->rootfh;
+       if (rpc_nfs3_fsinfo_async(rpc, nfs_fsinfo_cb, &args, client) != 0) {
                printf("Failed to send fsinfo request\n");
                exit(10);
        }
index 9ca58b467c8461f97c9043d1fcc120d2edd0416c..29a4daf3dc9c24e3a7f53532155624ff622f3c3f 100644 (file)
@@ -163,7 +163,7 @@ int main(int argc, char *argv[])
 
        ret = nfs_opendir(nfs, "/", &nfsdir);
        if (ret != 0) {
-               printf("Failed to opendir(\"/\")\n", nfs_get_error(nfs));
+               printf("Failed to opendir(\"/\") %s\n", nfs_get_error(nfs));
                exit(10);
        }
        while((nfsdirent = nfs_readdir(nfs, nfsdir)) != NULL) {
@@ -212,7 +212,7 @@ int main(int argc, char *argv[])
                        "-w"[!!(st.st_mode & S_IWOTH)],
                        "-x"[!!(st.st_mode & S_IXOTH)]
                );
-               printf(" %2d", st.st_nlink);
+               printf(" %2d", (int)st.st_nlink);
                printf(" %5d", st.st_uid);
                printf(" %5d", st.st_gid);
                printf(" %12" PRId64, st.st_size);
index d757d2b8c03ac16f28c8b60b1d4976266f1c622a..e1e65dc49aeeda58fc6f5e61dc4460c0469454d5 100644 (file)
@@ -7,4 +7,5 @@ dist_nfsc_HEADERS = \
        ${abs_top_srcdir}/portmap/libnfs-raw-portmap.h \
        ${abs_top_srcdir}/nfs/libnfs-raw-nfs.h \
        ${abs_top_srcdir}/nlm/libnfs-raw-nlm.h \
+       ${abs_top_srcdir}/nsm/libnfs-raw-nsm.h \
        ${abs_top_srcdir}/rquota/libnfs-raw-rquota.h
index 79ac411339668ffcb4e79d3edd00c95ed2b4f54c..a2f3e1a2a09bc8cebba77132ba1f8bdc6850c1d7 100644 (file)
@@ -56,9 +56,10 @@ struct rpc_fragment {
 };
 
 #define RPC_CONTEXT_MAGIC 0xc6e46435
+#define RPC_PARAM_UNDEFINED -1
 
 struct rpc_context {
-        uint32_t magic;
+       uint32_t magic;
        int fd;
        int is_connected;
 
@@ -68,37 +69,42 @@ struct rpc_context {
        void *connect_data;
 
        struct AUTH *auth;
-       unsigned long xid;
+       uint32_t xid;
 
-       /* buffer used for encoding RPC PDU */
-       char *encodebuf;
-       int encodebuflen;
+       /* buffer used for encoding RPC PDU */
+       char *encodebuf;
+       int encodebuflen;
 
-       struct rpc_pdu *outqueue;
-       struct sockaddr_storage udp_src;
-       struct rpc_pdu *waitpdu;
+       struct rpc_pdu *outqueue;
+       struct sockaddr_storage udp_src;
+       struct rpc_pdu *waitpdu;
 
-       uint32_t inpos;
-       uint32_t insize;
-       char *inbuf;
+       uint32_t inpos;
+       uint32_t insize;
+       char *inbuf;
 
-       /* special fields for UDP, which can sometimes be BROADCASTed */
-       int is_udp;
-       struct sockaddr *udp_dest;
-       int is_broadcast;
+       /* special fields for UDP, which can sometimes be BROADCASTed */
+       int is_udp;
+       struct sockaddr *udp_dest;
+       int is_broadcast;
 
-       /* track the address we connect to so we can auto-reconnect on session failure */
-       struct sockaddr_storage s;
-       int auto_reconnect;
+       /* track the address we connect to so we can auto-reconnect on session failure */
+       struct sockaddr_storage s;
+       int auto_reconnect;
 
        /* fragment reassembly */
        struct rpc_fragment *fragments;
+       
+       /* parameters passable via URL */
+       int tcp_syncnt;
+       int uid;
+       int gid;
 };
 
 struct rpc_pdu {
        struct rpc_pdu *next;
 
-       unsigned long xid;
+       uint32_t xid;
        ZDR zdr;
 
        uint32_t written;
@@ -135,6 +141,10 @@ struct sockaddr *rpc_get_recv_sockaddr(struct rpc_context *rpc);
 void rpc_set_autoreconnect(struct rpc_context *rpc);
 void rpc_unset_autoreconnect(struct rpc_context *rpc);
 
+void rpc_set_tcp_syncnt(struct rpc_context *rpc, int v);
+void rpc_set_uid(struct rpc_context *rpc, int uid);
+void rpc_set_gid(struct rpc_context *rpc, int gid);
+
 int rpc_add_fragment(struct rpc_context *rpc, char *data, uint64_t size);
 void rpc_free_all_fragments(struct rpc_context *rpc);
 
index b71e6b0f0cd8c41c8704bf590eb990776eb6e002..b62ea70b801bfe1729d8208c94f0773664c85dde 100644 (file)
@@ -53,6 +53,12 @@ struct rpc_context *nfs_get_rpc_context(struct nfs_context *nfs);
 */
 struct nfs_fh3 *nfs_get_fh(struct nfsfh *nfsfh);
 
+/* Control what the next XID value to be used on the context will be.
+   This can be used when multiple contexts are used to the same server
+   to avoid that the two contexts have xid collissions.
+ */
+void rpc_set_next_xid(struct rpc_context *rpc, uint32_t xid);
+
 #define RPC_STATUS_SUCCESS             0
 #define RPC_STATUS_ERROR               1
 #define RPC_STATUS_CANCEL              2
@@ -72,6 +78,21 @@ struct nfs_fh3 *nfs_get_fh(struct nfsfh *nfsfh);
  *                    : data is NULL.
  */
 int rpc_connect_async(struct rpc_context *rpc, const char *server, int port, rpc_cb cb, void *private_data);
+/*
+ * Async function to connect to a specific RPC program/version
+ * 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 : The tcp connection was successfully established.
+ *                      data is NULL.
+ * RPC_STATUS_ERROR   : The connection failed to establish.
+ *                      data is the erro string.
+ * 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);
 /*
  * 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.
@@ -97,7 +118,7 @@ int rpc_disconnect(struct rpc_context *rpc, char *error);
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_pmap_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+EXTERN int rpc_pmap_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
 
 
 /*
@@ -114,7 +135,7 @@ int rpc_pmap_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_pmap_getport_async(struct rpc_context *rpc, int program, int version, int protocol, rpc_cb cb, void *private_data);
+EXTERN int rpc_pmap_getport_async(struct rpc_context *rpc, int program, int version, int protocol, rpc_cb cb, void *private_data);
 
 /*
  * Call PORTMAPPER/SET
@@ -130,7 +151,7 @@ int rpc_pmap_getport_async(struct rpc_context *rpc, int program, int version, in
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-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_pmap_set_async(struct rpc_context *rpc, int program, int version, int protocol, int port, rpc_cb cb, void *private_data);
 
 /*
  * Call PORTMAPPER/UNSET
@@ -146,7 +167,7 @@ int rpc_pmap_set_async(struct rpc_context *rpc, int program, int version, int pr
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-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_pmap_unset_async(struct rpc_context *rpc, int program, int version, int protocol, int port, rpc_cb cb, void *private_data);
 
 /*
  * Call PORTMAPPER/CALLIT.
@@ -162,16 +183,16 @@ int rpc_pmap_unset_async(struct rpc_context *rpc, int program, int version, int
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-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_pmap_callit_async(struct rpc_context *rpc, int program, int version, int procedure, char *data, int datalen, rpc_cb cb, void *private_data);
 
 /* 
- * MOUNT FUNCTIONS
+ * MOUNT v3 FUNCTIONS
  */
 char *mountstat3_to_str(int stat);
 int mountstat3_to_errno(int error);
 
 /*
- * Call MOUNT/NULL
+ * Call MOUNT3/NULL
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -184,10 +205,11 @@ int mountstat3_to_errno(int error);
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_mount_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+EXTERN int rpc_mount3_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+EXTERN int rpc_mount_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
 
 /*
- * Call MOUNT/MNT
+ * Call MOUNT3/MNT
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -200,10 +222,11 @@ int rpc_mount_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_mount_mnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data);
+EXTERN int rpc_mount3_mnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data);
+EXTERN int rpc_mount_mnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data);
 
 /*
- * Call MOUNT/DUMP
+ * Call MOUNT3/DUMP
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -216,10 +239,11 @@ int rpc_mount_mnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_mount_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+EXTERN int rpc_mount3_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+EXTERN int rpc_mount_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
 
 /*
- * Call MOUNT/UMNT
+ * Call MOUNT3/UMNT
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -232,10 +256,11 @@ int rpc_mount_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_mount_umnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data);
+EXTERN int rpc_mount3_umnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data);
+EXTERN int rpc_mount_umnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data);
 
 /*
- * Call MOUNT/UMNTALL
+ * Call MOUNT3/UMNTALL
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -248,10 +273,11 @@ int rpc_mount_umnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_mount_umntall_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+EXTERN int rpc_mount3_umntall_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+EXTERN int rpc_mount_umntall_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
 
 /*
- * Call MOUNT/EXPORT
+ * Call MOUNT3/EXPORT
  * NOTE: You must include 'libnfs-raw-mount.h' to get the definitions of the
  * returned structures.
  *
@@ -268,20 +294,122 @@ int rpc_mount_umntall_async(struct rpc_context *rpc, rpc_cb cb, void *private_da
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_mount_export_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+EXTERN int rpc_mount3_export_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+EXTERN int rpc_mount_export_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
 
+/* 
+ * MOUNT v1 FUNCTIONS (Used with NFSv2)
+ */
+/*
+ * Call MOUNT1/NULL
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 mount daemon.
+ *                      data is NULL.
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the mount daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+EXTERN int rpc_mount1_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
 
+/*
+ * Call MOUNT1/MNT
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 mount daemon.
+ *                      data is union mountres1.
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the mount daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+EXTERN int rpc_mount1_mnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data);
+
+/*
+ * Call MOUNT1/DUMP
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 mount daemon.
+ *                      data is a mountlist.
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the mount daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+EXTERN int rpc_mount1_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+
+/*
+ * Call MOUNT1/UMNT
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 mount daemon.
+ *                      data NULL.
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the mount daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+EXTERN int rpc_mount1_umnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data);
+
+/*
+ * Call MOUNT1/UMNTALL
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 mount daemon.
+ *                      data NULL.
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the mount daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+EXTERN int rpc_mount1_umntall_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+
+/*
+ * Call MOUNT1/EXPORT
+ * NOTE: You must include 'libnfs-raw-mount.h' to get the definitions of the
+ * returned structures.
+ *
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 mount daemon.
+ *                      data is a pointer to an exports pointer:
+ *                      exports export = *(exports *)data;
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the mount daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+EXTERN int rpc_mount1_export_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
 
 
 /* 
- * NFS FUNCTIONS
+ * NFS v3 FUNCTIONS
  */
 struct nfs_fh3;
 char *nfsstat3_to_str(int error);
 int nfsstat3_to_errno(int error);
 
 /*
- * Call NFS/NULL
+ * Call NFS3/NULL
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -294,10 +422,11 @@ int nfsstat3_to_errno(int error);
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfs_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+EXTERN int rpc_nfs3_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+EXTERN int rpc_nfs_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
 
 /*
- * Call NFS/GETATTR
+ * Call NFS3/GETATTR
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -310,10 +439,30 @@ int rpc_nfs_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfs_getattr_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data);
+struct GETATTR3args;
+EXTERN int rpc_nfs3_getattr_async(struct rpc_context *rpc, rpc_cb cb, struct GETATTR3args *args, void *private_data);
+EXTERN int rpc_nfs_getattr_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data);
 
 /*
- * Call NFS/LOOKUP
+ * Call NFS3/PATHCONF
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is PATHCONF3res
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct PATHCONF3args;
+EXTERN int rpc_nfs3_pathconf_async(struct rpc_context *rpc, rpc_cb cb, struct PATHCONF3args *args, void *private_data);
+EXTERN int rpc_nfs_pathconf_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data);
+
+/*
+ * Call NFS3/LOOKUP
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -326,10 +475,12 @@ int rpc_nfs_getattr_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfs_lookup_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *name, void *private_data);
+struct LOOKUP3args;
+EXTERN int rpc_nfs3_lookup_async(struct rpc_context *rpc, rpc_cb cb, struct LOOKUP3args *args, void *private_data);
+EXTERN int rpc_nfs_lookup_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *name, void *private_data);
 
 /*
- * Call NFS/ACCESS
+ * Call NFS3/ACCESS
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -342,10 +493,12 @@ int rpc_nfs_lookup_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfs_access_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, int access, void *private_data);
+struct ACCESS3args;
+EXTERN int rpc_nfs3_access_async(struct rpc_context *rpc, rpc_cb cb, struct ACCESS3args *args, void *private_data);
+EXTERN int rpc_nfs_access_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, int access, void *private_data);
 
 /*
- * Call NFS/READ
+ * Call NFS3/READ
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -358,10 +511,12 @@ int rpc_nfs_access_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfs_read_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t offset, uint64_t count, void *private_data);
+struct READ3args;
+EXTERN int rpc_nfs3_read_async(struct rpc_context *rpc, rpc_cb cb, struct READ3args *args, void *private_data);
+EXTERN int rpc_nfs_read_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t offset, uint64_t count, void *private_data);
 
 /*
- * Call NFS/WRITE
+ * Call NFS3/WRITE
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -374,10 +529,12 @@ int rpc_nfs_read_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, u
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfs_write_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *buf, uint64_t offset, uint64_t count, int stable_how, void *private_data);
+struct WRITE3args;
+EXTERN int rpc_nfs3_write_async(struct rpc_context *rpc, rpc_cb cb, struct WRITE3args *args, void *private_data);
+EXTERN int rpc_nfs_write_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *buf, uint64_t offset, uint64_t count, int stable_how, void *private_data);
 
 /*
- * Call NFS/COMMIT
+ * Call NFS3/COMMIT
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -390,11 +547,12 @@ int rpc_nfs_write_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfs_commit_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data);
-
+struct COMMIT3args;
+EXTERN int rpc_nfs3_commit_async(struct rpc_context *rpc, rpc_cb cb, struct COMMIT3args *args, void *private_data);
+EXTERN int rpc_nfs_commit_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data);
 
 /*
- * Call NFS/SETATTR
+ * Call NFS3/SETATTR
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -408,12 +566,11 @@ int rpc_nfs_commit_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
  *                     data is NULL.
  */
 struct SETATTR3args;
-int rpc_nfs_setattr_async(struct rpc_context *rpc, rpc_cb cb, struct SETATTR3args *args, void *private_data);
-
-
+EXTERN int rpc_nfs3_setattr_async(struct rpc_context *rpc, rpc_cb cb, struct SETATTR3args *args, void *private_data);
+EXTERN int rpc_nfs_setattr_async(struct rpc_context *rpc, rpc_cb cb, struct SETATTR3args *args, void *private_data);
 
 /*
- * Call NFS/MKDIR
+ * Call NFS3/MKDIR
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -427,14 +584,11 @@ int rpc_nfs_setattr_async(struct rpc_context *rpc, rpc_cb cb, struct SETATTR3arg
  *                     data is NULL.
  */
 struct MKDIR3args;
-int rpc_nfs_mkdir_async(struct rpc_context *rpc, rpc_cb cb, struct MKDIR3args *args, void *private_data);
-
-
-
-
+EXTERN int rpc_nfs3_mkdir_async(struct rpc_context *rpc, rpc_cb cb, struct MKDIR3args *args, void *private_data);
+EXTERN int rpc_nfs_mkdir_async(struct rpc_context *rpc, rpc_cb cb, struct MKDIR3args *args, void *private_data);
 
 /*
- * Call NFS/RMDIR
+ * Call NFS3/RMDIR
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -447,13 +601,12 @@ int rpc_nfs_mkdir_async(struct rpc_context *rpc, rpc_cb cb, struct MKDIR3args *a
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfs_rmdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *dir, void *private_data);
-
-
-
+struct RMDIR3args;
+EXTERN int rpc_nfs3_rmdir_async(struct rpc_context *rpc, rpc_cb cb, struct RMDIR3args *args, void *private_data);
+EXTERN int rpc_nfs_rmdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *dir, void *private_data);
 
 /*
- * Call NFS/CREATE
+ * Call NFS3/CREATE
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -467,11 +620,11 @@ int rpc_nfs_rmdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
  *                     data is NULL.
  */
 struct CREATE3args;
-int rpc_nfs_create_async(struct rpc_context *rpc, rpc_cb cb, struct CREATE3args *args, void *private_data);
-
+EXTERN int rpc_nfs3_create_async(struct rpc_context *rpc, rpc_cb cb, struct CREATE3args *args, void *private_data);
+EXTERN int rpc_nfs_create_async(struct rpc_context *rpc, rpc_cb cb, struct CREATE3args *args, void *private_data);
 
 /*
- * Call NFS/MKNOD
+ * Call NFS3/MKNOD
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -484,11 +637,12 @@ int rpc_nfs_create_async(struct rpc_context *rpc, rpc_cb cb, struct CREATE3args
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfs_mknod_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *file, int mode, int major, int minor, void *private_data);
-
+struct MKNOD3args;
+EXTERN int rpc_nfs3_mknod_async(struct rpc_context *rpc, rpc_cb cb, struct MKNOD3args *args, void *private_data);
+EXTERN int rpc_nfs_mknod_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *file, int mode, int major, int minor, void *private_data);
 
 /*
- * Call NFS/REMOVE
+ * Call NFS3/REMOVE
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -501,12 +655,12 @@ int rpc_nfs_mknod_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfs_remove_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *name, void *private_data);
-
-
+struct REMOVE3args;
+EXTERN int rpc_nfs3_remove_async(struct rpc_context *rpc, rpc_cb cb, struct REMOVE3args *args, void *private_data);
+EXTERN int rpc_nfs_remove_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *name, void *private_data);
 
 /*
- * Call NFS/READDIR
+ * Call NFS3/READDIR
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -519,10 +673,12 @@ int rpc_nfs_remove_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfs_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t cookie, char *cookieverf, int count, void *private_data);
+struct READDIR3args;
+EXTERN int rpc_nfs3_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct READDIR3args *args, void *private_data);
+EXTERN int rpc_nfs_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t cookie, char *cookieverf, int count, void *private_data);
 
 /*
- * Call NFS/READDIRPLUS
+ * Call NFS3/READDIRPLUS
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -535,10 +691,12 @@ int rpc_nfs_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfs_readdirplus_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t cookie, char *cookieverf, int count, void *private_data);
+struct READDIRPLUS3args;
+EXTERN int rpc_nfs3_readdirplus_async(struct rpc_context *rpc, rpc_cb cb, struct READDIRPLUS3args *args, void *private_data);
+EXTERN int rpc_nfs_readdirplus_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t cookie, char *cookieverf, int count, void *private_data);
 
 /*
- * Call NFS/FSSTAT
+ * Call NFS3/FSSTAT
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. The callback will not be invoked.
@@ -551,101 +709,374 @@ int rpc_nfs_readdirplus_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfs_fsstat_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data);
+struct FSSTAT3args;
+EXTERN int rpc_nfs3_fsstat_async(struct rpc_context *rpc, rpc_cb cb, struct FSSTAT3args *args, void *private_data);
+EXTERN int rpc_nfs_fsstat_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data);
 
+/*
+ * Call NFS3/FSINFO
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is FSINFO3res
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct FSINFO3args;
+EXTERN int rpc_nfs3_fsinfo_async(struct rpc_context *rpc, rpc_cb cb, struct FSINFO3args *args, void *private_data);
+EXTERN int rpc_nfs_fsinfo_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data);
 
+/*
+ * Call NFS3/READLINK
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is READLINK3res *
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct READLINK3args;
+EXTERN int rpc_nfs3_readlink_async(struct rpc_context *rpc, rpc_cb cb, struct READLINK3args *args, void *private_data);
+EXTERN int rpc_nfs_readlink_async(struct rpc_context *rpc, rpc_cb cb, struct READLINK3args *args, void *private_data);
 
 /*
- * Call NFS/FSINFO
+ * Call NFS3/SYMLINK
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. 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 nfs daemon.
- *                      data is FSINFO3res
+ *                      data is SYMLINK3res *
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct SYMLINK3args;
+EXTERN int rpc_nfs3_symlink_async(struct rpc_context *rpc, rpc_cb cb, struct SYMLINK3args *args, void *private_data);
+EXTERN int rpc_nfs_symlink_async(struct rpc_context *rpc, rpc_cb cb, struct SYMLINK3args *args, void *private_data);
+
+/*
+ * Call NFS3/RENAME
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is RENAME3res *
  * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
  *                      data is the error string.
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfs_fsinfo_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data);
+struct RENAME3args;
+EXTERN int rpc_nfs3_rename_async(struct rpc_context *rpc, rpc_cb cb, struct RENAME3args *args, void *private_data);
+EXTERN int rpc_nfs_rename_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *olddir, char *oldname, struct nfs_fh3 *newdir, char *newname, void *private_data);
 
+/*
+ * Call NFS3/LINK
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is LINK3res *
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct LINK3args;
+EXTERN int rpc_nfs3_link_async(struct rpc_context *rpc, rpc_cb cb, struct LINK3args *args, void *private_data);
+EXTERN int rpc_nfs_link_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *file, struct nfs_fh3 *newdir, char *newname, void *private_data);
 
+/* 
+ * NFS v2 FUNCTIONS
+ */
 
 /*
- * Call NFS/READLINK
+ * Call NFS2/NULL
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. 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 nfs daemon.
- *                      data is READLINK3res *
+ *                      data is NULL.
  * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
  *                      data is the error string.
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-struct READLINK3args;
-int rpc_nfs_readlink_async(struct rpc_context *rpc, rpc_cb cb, struct READLINK3args *args, void *private_data);
+EXTERN int rpc_nfs2_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
 
+/*
+ * Call NFS2/GETATTR
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is GETATTR2res
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct GETATTR2args;
+EXTERN int rpc_nfs2_getattr_async(struct rpc_context *rpc, rpc_cb cb, struct GETATTR2args *args, void *private_data);
 
+/*
+ * Call NFS2/SETATTR
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is SETATTR2res *
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct SETATTR2args;
+EXTERN int rpc_nfs2_setattr_async(struct rpc_context *rpc, rpc_cb cb, struct SETATTR2args *args, void *private_data);
 
 /*
- * Call NFS/SYMLINK
+ * Call NFS2/LOOKUP
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. 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 nfs daemon.
- *                      data is SYMLINK3res *
+ *                      data is LOOKUP2res
  * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
  *                      data is the error string.
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-struct SYMLINK3args;
-int rpc_nfs_symlink_async(struct rpc_context *rpc, rpc_cb cb, struct SYMLINK3args *args, void *private_data);
+struct LOOKUP2args;
+EXTERN int rpc_nfs2_lookup_async(struct rpc_context *rpc, rpc_cb cb, struct LOOKUP2args *args, void *private_data);
 
+/*
+ * Call NFS2/READLINK
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is READLINK2res *
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct READLINK2args;
+EXTERN int rpc_nfs32_readlink_async(struct rpc_context *rpc, rpc_cb cb, struct READLINK2args *args, void *private_data);
 
 /*
- * Call NFS/RENAME
+ * Call NFS2/READ
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. 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 nfs daemon.
- *                      data is RENAME3res *
+ *                      data is READ2res
  * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
  *                      data is the error string.
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfs_rename_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *olddir, char *oldname, struct nfs_fh3 *newdir, char *newname, void *private_data);
+struct READ2args;
+EXTERN int rpc_nfs2_read_async(struct rpc_context *rpc, rpc_cb cb, struct READ2args *args, void *private_data);
 
+/*
+ * Call NFS2/WRITE
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is WRITE2res *
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct WRITE2args;
+EXTERN int rpc_nfs2_write_async(struct rpc_context *rpc, rpc_cb cb, struct WRITE2args *args, void *private_data);
+
+/*
+ * Call NFS2/CREATE
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is CREATE2res *
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct CREATE2args;
+EXTERN int rpc_nfs2_create_async(struct rpc_context *rpc, rpc_cb cb, struct CREATE2args *args, void *private_data);
 
+/*
+ * Call NFS2/REMOVE
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is REMOVE2res *
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct REMOVE2args;
+EXTERN int rpc_nfs2_remove_async(struct rpc_context *rpc, rpc_cb cb, struct REMOVE2args *args, void *private_data);
 
 /*
- * Call NFS/LINK
+ * Call NFS2/RENAME
  * Function returns
  *  0 : The call was initiated. The callback will be invoked when the call completes.
  * <0 : An error occured when trying to set up the call. 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 nfs daemon.
- *                      data is LINK3res *
+ *                      data is RENAME2res *
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct RENAME2args;
+EXTERN int rpc_nfs2_rename_async(struct rpc_context *rpc, rpc_cb cb, struct RENAME2args *args, void *private_data);
+
+/*
+ * Call NFS2/LINK
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is LINK2res *
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct LINK2args;
+EXTERN int rpc_nfs2_link_async(struct rpc_context *rpc, rpc_cb cb, struct LINK2args *args, void *private_data);
+
+/*
+ * Call NFS2/SYMLINK
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is SYMLINK2res *
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct SYMLINK2args;
+EXTERN int rpc_nfs2_symlink_async(struct rpc_context *rpc, rpc_cb cb, struct SYMLINK2args *args, void *private_data);
+
+/*
+ * Call NFS2/MKDIR
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is MKDIR2res *
  * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
  *                      data is the error string.
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfs_link_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *file, struct nfs_fh3 *newdir, char *newname, void *private_data);
+struct MKDIR2args;
+EXTERN int rpc_nfs2_mkdir_async(struct rpc_context *rpc, rpc_cb cb, struct MKDIR2args *args, void *private_data);
 
+/*
+ * Call NFS2/RMDIR
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is RMDIR2res *
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct RMDIR2args;
+EXTERN int rpc_nfs2_rmdir_async(struct rpc_context *rpc, rpc_cb cb, struct RMDIR2args *args, void *private_data);
 
+/*
+ * Call NFS2/READDIR
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is READDIR2res *
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct READDIR2args;
+EXTERN int rpc_nfs2_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct READDIR2args *args, void *private_data);
 
+/*
+ * Call NFS2/STATFS
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nfs daemon.
+ *                      data is STATFS2res *
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nfs daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct STATFS2args;
+EXTERN int rpc_nfs2_statfs_async(struct rpc_context *rpc, rpc_cb cb, struct STATFS2args *args, void *private_data);
 
 /* 
  * RQUOTA FUNCTIONS
@@ -667,7 +1098,7 @@ int rquotastat_to_errno(int error);
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_rquota1_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+EXTERN int rpc_rquota1_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
 
 /*
  * Call RQUOTA1/GETQUOTA
@@ -683,7 +1114,7 @@ int rpc_rquota1_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_dat
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_rquota1_getquota_async(struct rpc_context *rpc, rpc_cb cb, char *export, int uid, void *private_data);
+EXTERN int rpc_rquota1_getquota_async(struct rpc_context *rpc, rpc_cb cb, char *export, int uid, void *private_data);
 
 /*
  * Call RQUOTA1/GETACTIVEQUOTA
@@ -699,7 +1130,7 @@ int rpc_rquota1_getquota_async(struct rpc_context *rpc, rpc_cb cb, char *export,
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_rquota1_getactivequota_async(struct rpc_context *rpc, rpc_cb cb, char *export, int uid, void *private_data);
+EXTERN int rpc_rquota1_getactivequota_async(struct rpc_context *rpc, rpc_cb cb, char *export, int uid, void *private_data);
 
 
 
@@ -777,7 +1208,7 @@ int rpc_rquota2_getactivequota_async(struct rpc_context *rpc, rpc_cb cb, char *e
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nfsacl_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+EXTERN int rpc_nfsacl_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
 
 /*
  * Call NFSACL/GETACL
@@ -795,7 +1226,7 @@ int rpc_nfsacl_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data
  *                     data is NULL.
  */
 struct GETACL3args;
-int rpc_nfsacl_getacl_async(struct rpc_context *rpc, rpc_cb cb, struct GETACL3args *args, void *private_data);
+EXTERN int rpc_nfsacl_getacl_async(struct rpc_context *rpc, rpc_cb cb, struct GETACL3args *args, void *private_data);
 
 
 
@@ -815,7 +1246,7 @@ int rpc_nfsacl_getacl_async(struct rpc_context *rpc, rpc_cb cb, struct GETACL3ar
  *                     data is NULL.
  */
 struct SETACL3args;
-int rpc_nfsacl_setacl_async(struct rpc_context *rpc, rpc_cb cb, struct SETACL3args *args, void *private_data);
+EXTERN int rpc_nfsacl_setacl_async(struct rpc_context *rpc, rpc_cb cb, struct SETACL3args *args, void *private_data);
 
 
 
@@ -841,7 +1272,7 @@ char *nlmstat4_to_str(int stat);
  * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
  *                     data is NULL.
  */
-int rpc_nlm4_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+EXTERN int rpc_nlm4_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
 
 /*
  * Call NLM/TEST
@@ -860,7 +1291,7 @@ int rpc_nlm4_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
  *                     data is NULL.
  */
 struct NLM4_TESTargs;
-int rpc_nlm4_test_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_TESTargs *args, void *private_data);
+EXTERN int rpc_nlm4_test_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_TESTargs *args, void *private_data);
 
 /*
  * Call NLM/LOCK
@@ -879,7 +1310,7 @@ int rpc_nlm4_test_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_TESTargs
  *                     data is NULL.
  */
 struct NLM4_LOCKargs;
-int rpc_nlm4_lock_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_LOCKargs *args, void *private_data);
+EXTERN int rpc_nlm4_lock_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_LOCKargs *args, void *private_data);
 
 /*
  * Call NLM/CANCEL
@@ -898,7 +1329,7 @@ int rpc_nlm4_lock_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_LOCKargs
  *                     data is NULL.
  */
 struct NLM4_CANCargs;
-int rpc_nlm4_cancel_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_CANCargs *args, void *private_data);
+EXTERN int rpc_nlm4_cancel_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_CANCargs *args, void *private_data);
 
 /*
  * Call NLM/UNLOCK
@@ -917,6 +1348,142 @@ int rpc_nlm4_cancel_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_CANCar
  *                     data is NULL.
  */
 struct NLM4_UNLOCKargs;
-int rpc_nlm4_unlock_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_UNLOCKargs *args, void *private_data);
+EXTERN int rpc_nlm4_unlock_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_UNLOCKargs *args, void *private_data);
+
+/*
+ * NSM functions
+ */
+char *nsmstat1_to_str(int stat);
+       
+/*
+ * Call NSM/NULL
+ * Call the NULL procedure for the NSM protocol
+ *
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nsm daemon.
+ *                      data is NULL
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nsm daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+EXTERN int rpc_nsm1_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+
+/*
+ * Call NSM/STAT
+ * Call the STAT procedure for the NSM protocol
+ *
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nsm daemon.
+ *                      data is NSM1_STATres
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nsm daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct NSM1_STATargs;
+EXTERN int rpc_nsm1_stat_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_STATargs *args, void *private_data);
+
+/*
+ * Call NSM/MON
+ * Call the MON procedure for the NSM protocol
+ *
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nsm daemon.
+ *                      data is NSM1_MONres
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nsm daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct NSM1_MONargs;
+EXTERN int rpc_nsm1_mon_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_MONargs *args, void *private_data);
+
+/*
+ * Call NSM/UNMON
+ * Call the UNMON procedure for the NSM protocol
+ *
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nsm daemon.
+ *                      data is NSM1_UNMONres
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nsm daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct NSM1_UNMONargs;
+EXTERN int rpc_nsm1_unmon_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_UNMONargs *args, void *private_data);
+
+/*
+ * Call NSM/UNMONALL
+ * Call the UNMONALL procedure for the NSM protocol
+ *
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nsm daemon.
+ *                      data is NSM1_UNMONALLres
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nsm daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct NSM1_UNMONALLargs;
+EXTERN int rpc_nsm1_unmonall_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_UNMONALLargs *args, void *private_data);
+
+/*
+ * Call NSM/SIMUCRASH
+ * Call the SIMUCRASH procedure for the NSM protocol
+ *
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nsm daemon.
+ *                      data is NULL
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nsm daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+EXTERN int rpc_nsm1_simucrash_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+
+/*
+ * Call NSM/NOTIFY
+ * Call the NOTIFY procedure for the NSM protocol
+ *
+ * Function returns
+ *  0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. 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 nsm daemon.
+ *                      data is NULL
+ * RPC_STATUS_ERROR   : An error occured when trying to contact the nsm daemon.
+ *                      data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ *                     data is NULL.
+ */
+struct NSM1_NOTIFYargs;
+EXTERN int rpc_nsm1_notify_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_NOTIFYargs *args, void *private_data);
 
 #endif
index 82b4a061d4499c675fb8e92b7776c3f636837ce0..388ea78e6293685ebe5ad028fe063c8f55e33cc0 100644 (file)
 struct nfs_context;
 struct rpc_context;
 
+struct nfs_url {
+       char *server;
+       char *path;
+       char *file;
+};
+
 #if defined(WIN32)
 #define EXTERN __declspec( dllexport )
 #else
@@ -71,7 +77,6 @@ EXTERN int nfs_queue_length(struct nfs_context *nfs);
 struct AUTH;
 EXTERN void nfs_set_auth(struct nfs_context *nfs, struct AUTH *auth);
 
-
 /*
  * When an operation failed, this function can extract a detailed error string.
  */
@@ -106,6 +111,49 @@ EXTERN struct nfs_context *nfs_init_context(void);
 EXTERN void nfs_destroy_context(struct nfs_context *nfs);
 
 
+/*
+ * URL parsing functions.
+ * These functions all parse a URL of the form 
+ * nfs://server/path/file?argv=val[&arg=val]*
+ * and returns a nfs_url.
+ *
+ * Apart from parsing the URL the functions will also update
+ * the nfs context to reflect settings controlled via url arguments.
+ *
+ * Current URL arguments are :
+ * tcp-syncnt=<int>  : Number of SYNs to send during the seccion establish
+ *                     before failing settin up the tcp connection to the
+ *                     server.
+ * uid=<int>         : UID value to use when talking to the server.
+ *                     default it 65534 on Windows and getuid() on unixen.
+ * gid=<int>         : GID value to use when talking to the server.
+ *                     default it 65534 on Windows and getgid() on unixen.
+ */
+/*
+ * Parse a complete NFS URL including, server, path and
+ * filename. Fail if any component is missing.
+ */
+EXTERN struct nfs_url *nfs_parse_url_full(struct nfs_context *nfs, const char *url);
+
+/*
+ * Parse an NFS URL, but do not split path and file. File
+ * in the resulting struct remains NULL.
+ */
+EXTERN struct nfs_url *nfs_parse_url_dir(struct nfs_context *nfs, const char *url);
+
+/*
+ * Parse an NFS URL, but do not fail if file, path or even server is missing.
+ * Check elements of the resulting struct for NULL.
+ */
+EXTERN struct nfs_url *nfs_parse_url_incomplete(struct nfs_context *nfs, const char *url);
+
+
+/*
+ * Free the URL struct returned by the nfs_parse_url_* functions.
+ */
+EXTERN void nfs_destroy_url(struct nfs_url *url);
+
+
 struct nfsfh;
 
 /*
@@ -649,13 +697,16 @@ struct nfsdirent  {
        char *name;
        uint64_t inode;
 
-       /* some extra fields we get for free through the READDIRPLUS3 call. You need libnfs-raw-nfs.h for these */
+       /* Some extra fields we get for free through the READDIRPLUS3 call.
+         You need libnfs-raw-nfs.h for type/mode constants */
        uint32_t type; /* NF3REG, NF3DIR, NF3BLK, ... */
        uint32_t mode;
        uint64_t size;
        struct timeval atime;
        struct timeval mtime;
        struct timeval ctime;
+       uint32_t uid;
+       uint32_t gid;
 };
 /*
  * nfs_readdir() never blocks, so no special sync/async versions are available
index 30efafe5102078c1ba7ba6c0607aacb5d9eef053..de4fc5883acc7dee1b87a06671f503008b69a50b 100644 (file)
@@ -2,11 +2,12 @@ lib_LTLIBRARIES = libnfs.la
 
 libnfs_la_CPPFLAGS = -I$(abs_top_srcdir)/include \
                     -I$(abs_top_srcdir)/include/nfsc \
-                    -I../mount \
-                    -I../nfs \
-                    -I../nlm \
-                    -I../portmap \
-                    -I../rquota \
+                    -I$(abs_top_srcdir)/mount \
+                    -I$(abs_top_srcdir)/nfs \
+                    -I$(abs_top_srcdir)/nlm \
+                    -I$(abs_top_srcdir)/nsm \
+                    -I$(abs_top_srcdir)/portmap \
+                    -I$(abs_top_srcdir)/rquota \
                     "-D_U_=__attribute__((unused))"
 
 libnfs_la_SOURCES = \
@@ -17,11 +18,15 @@ libnfs_la_SOURCES = \
        pdu.c \
        socket.c
 
-libnfs_la_LDFLAGS = -version-info 1:6:0
+SOCURRENT=1
+SOREVISION=8
+SOAGE=0
+libnfs_la_LDFLAGS = -version-info $(SOCURRENT):$(SOREVISION):$(SOAGE)
 libnfs_la_LIBADD = \
        ../mount/libmount.la \
        ../nfs/libnfs.la \
        ../nlm/libnlm.la \
+       ../nsm/libnsm.la \
        ../portmap/libportmap.la \
        ../rquota/librquota.la 
 
index 62a8f81ac96fffa8d2e55f9e76dd2ae2683cd9d5..93d1db8b088b3780601d5251b63fb30d71a0e28e 100644 (file)
@@ -57,7 +57,9 @@ struct rpc_context *rpc_init_context(void)
        memset(rpc, 0, sizeof(struct rpc_context));
 
        rpc->magic = RPC_CONTEXT_MAGIC;
-       rpc->encodebuflen = 65536;
+
+       /* Allow 1M of data (for writes) and some */
+       rpc->encodebuflen = 1024 * 1024 + 4096;
        rpc->encodebuf = malloc(rpc->encodebuflen);
        if (rpc->encodebuf == NULL) {
                free(rpc);
@@ -70,9 +72,17 @@ struct rpc_context *rpc_init_context(void)
                free(rpc);
                return NULL;
        }
-       rpc->xid = salt + time(NULL);
+       rpc->xid = salt + time(NULL) + getpid() << 16;
        salt += 0x01000000;
        rpc->fd = -1;
+       rpc->tcp_syncnt = RPC_PARAM_UNDEFINED;
+#ifdef WIN32
+       rpc->uid = 65534;
+       rpc->gid = 65534;
+#else
+       rpc->uid = getuid();
+       rpc->gid = getgid();
+#endif
 
        return rpc;
 }
@@ -100,6 +110,24 @@ void rpc_set_auth(struct rpc_context *rpc, struct AUTH *auth)
        rpc->auth = auth;
 }
 
+static void rpc_set_uid_gid(struct rpc_context *rpc, int uid, int gid) {
+       if (uid != rpc->uid || gid != rpc->gid) {
+               struct AUTH *auth = libnfs_authunix_create("libnfs", uid, gid, 0, NULL);
+               if (auth != NULL) {
+                       rpc_set_auth(rpc, auth);
+                       rpc->uid = uid;
+                       rpc->gid = gid;
+               }
+       }
+}
+
+void rpc_set_uid(struct rpc_context *rpc, int uid) {
+       rpc_set_uid_gid(rpc, uid, rpc->gid);
+}
+
+void rpc_set_gid(struct rpc_context *rpc, int gid) {
+       rpc_set_uid_gid(rpc, rpc->uid, gid);
+}
 
 void rpc_set_error(struct rpc_context *rpc, char *error_string, ...)
 {
index 25ddfe85825acb28ebd437253c966991c88d5e17..7d7e10867b79dd43dd654d4191b25a3d227ca670 100644 (file)
@@ -46,6 +46,10 @@ nfs_open
 nfs_open_async
 nfs_opendir
 nfs_opendir_async
+nfs_parse_url_full
+nfs_parse_url_dir
+nfs_parse_url_incomplete
+nfs_destroy_url
 nfs_pread
 nfs_pread_async
 nfs_pwrite
@@ -79,20 +83,112 @@ nfs_which_events
 nfs_write
 nfs_write_async
 win32_poll
-rpc_which_events
-rpc_service
-rpc_init_context
-rpc_get_fd
-rpc_get_error
+rpc_connect_async
 rpc_destroy_context
-rpc_rquota1_getquota_async
+rpc_disconnect
+rpc_get_error
+rpc_get_fd
+rpc_init_context
 rpc_pmap_null_async
 rpc_pmap_getport_async
-rpc_nfsacl_null_async
-rpc_nfsacl_getacl_async
+rpc_pmap_set_async
+rpc_pmap_unset_async
+rpc_pmap_callit_async
 rpc_mount_null_async
 rpc_mount_mnt_async
+rpc_mount_dump_async
+rpc_mount_umnt_async
+rpc_mount_umntall_async
 rpc_mount_export_async
-rpc_disconnect
-rpc_connect_async
+rpc_mount1_null_async
+rpc_mount1_mnt_async
+rpc_mount1_dump_async
+rpc_mount1_umnt_async
+rpc_mount1_umntall_async
+rpc_mount1_export_async
+rpc_mount3_null_async
+rpc_mount3_mnt_async
+rpc_mount3_dump_async
+rpc_mount3_umnt_async
+rpc_mount3_umntall_async
+rpc_mount3_export_async
+rpc_nfsacl_null_async
+rpc_nfsacl_getacl_async
+rpc_nfsacl_setacl_async
+rpc_nfs_null_async
+rpc_nfs_getattr_async
+rpc_nfs_pathconf_async
+rpc_nfs_lookup_async
+rpc_nfs_access_async
+rpc_nfs_read_async
+rpc_nfs_write_async
+rpc_nfs_commit_async
+rpc_nfs_setattr_async
+rpc_nfs_mkdir_async
+rpc_nfs_rmdir_async
+rpc_nfs_create_async
+rpc_nfs_mknod_async
+rpc_nfs_remove_async
+rpc_nfs_readdir_async
+rpc_nfs_readdirplus_async
+rpc_nfs_fsstat_async
 rpc_nfs_fsinfo_async
+rpc_nfs_readlink_async
+rpc_nfs_symlink_async
+rpc_nfs_rename_async
+rpc_nfs_link_async
+rpc_nfs2_null_async
+rpc_nfs2_getattr_async
+rpc_nfs2_setattr_async
+rpc_nfs2_lookup_async
+rpc_nfs2_readlink_async
+rpc_nfs2_read_async
+rpc_nfs2_write_async
+rpc_nfs2_create_async
+rpc_nfs2_remove_async
+rpc_nfs2_rename_async
+rpc_nfs2_link_async
+rpc_nfs2_symlink_async
+rpc_nfs2_mkdir_async
+rpc_nfs2_rmdir_async
+rpc_nfs2_readdir_async
+rpc_nfs2_statfs_async
+rpc_nfs3_null_async
+rpc_nfs3_getattr_async
+rpc_nfs3_pathconf_async
+rpc_nfs3_lookup_async
+rpc_nfs3_access_async
+rpc_nfs3_read_async
+rpc_nfs3_write_async
+rpc_nfs3_commit_async
+rpc_nfs3_setattr_async
+rpc_nfs3_mkdir_async
+rpc_nfs3_rmdir_async
+rpc_nfs3_create_async
+rpc_nfs3_mknod_async
+rpc_nfs3_remove_async
+rpc_nfs3_readdir_async
+rpc_nfs3_readdirplus_async
+rpc_nfs3_fsstat_async
+rpc_nfs3_fsinfo_async
+rpc_nfs3_readlink_async
+rpc_nfs3_symlink_async
+rpc_nfs3_rename_async
+rpc_nfs3_link_async
+rpc_nlm4_null_async
+rpc_nlm4_test_async
+rpc_nlm4_lock_async
+rpc_nlm4_cancel_async
+rpc_nlm4_unlock_async
+rpc_nsm1_null_async
+rpc_nsm1_stat_async
+rpc_nsm1_mon_async
+rpc_nsm1_unmon_async
+rpc_nsm1_unmonall_async
+rpc_nsm1_simucrash_async
+rpc_nsm1_notify_async
+rpc_rquota1_null_async
+rpc_rquota1_getquota_async
+rpc_rquota1_getactivequota_async
+rpc_service
+rpc_which_events
index 5d98706dd79c4533634272ee46681608d2db5568..7539b08d7ccf7776a3f0f6cc52391e5f760ed62d 100644 (file)
@@ -124,7 +124,7 @@ bool_t libnfs_zdr_u_quad_t(ZDR *zdrs, uint64_t *u)
                *u = ntohl(*(uint32_t *)&zdrs->buf[zdrs->pos]);
                zdrs->pos += 4;
                *u <<= 32;
-               *u |= ntohl(*(uint32_t *)&zdrs->buf[zdrs->pos]);
+               *u |= (uint32_t)ntohl(*(uint32_t *)&zdrs->buf[zdrs->pos]);
                zdrs->pos += 4;
                return TRUE;
                break;
@@ -219,6 +219,9 @@ bool_t libnfs_zdr_opaque(ZDR *zdrs, char *objp, uint32_t size)
        case ZDR_ENCODE:
                memcpy(&zdrs->buf[zdrs->pos], objp, size);
                zdrs->pos += size;
+               if (zdrs->pos & 3) {
+                       memset(&zdrs->buf[zdrs->pos], 0x00, 4 - (zdrs->pos & 3));
+               }
                zdrs->pos = (zdrs->pos + 3) & ~3;
                return TRUE;
        case ZDR_DECODE:
@@ -476,10 +479,12 @@ struct AUTH *libnfs_authunix_create(char *host, uint32_t uid, uint32_t gid, uint
 
        size = 4 + 4 + ((strlen(host) + 3) & ~3) + 4 + 4 + 4 + len * 4;
        auth = malloc(sizeof(struct AUTH));
+       memset(auth, 0x00, sizeof(struct AUTH));
        auth->ah_cred.oa_flavor = AUTH_UNIX;
        auth->ah_cred.oa_length = size;
        auth->ah_cred.oa_base = malloc(size);
 
+       memset(auth->ah_cred.oa_base, 0x00, size);
        buf = (uint32_t *)auth->ah_cred.oa_base;
        idx = 0;
        buf[idx++] = htonl(time(NULL));
@@ -506,7 +511,7 @@ struct AUTH *libnfs_authunix_create(char *host, uint32_t uid, uint32_t gid, uint
 struct AUTH *libnfs_authunix_create_default(void)
 {
 #ifdef WIN32
-       return libnfs_authunix_create("libnfs", 65535, 65535, 0, NULL);
+       return libnfs_authunix_create("libnfs", 65534, 65534, 0, NULL);
 #else
        return libnfs_authunix_create("libnfs", getuid(), getgid(), 0, NULL);
 #endif
index a1a62bb574dd7ef4cd8c7b280d5c6d09dea4048d..ca8ed379de8d529a9f3609e419fc740f629c37d3 100644 (file)
@@ -173,6 +173,159 @@ char *nfs_get_error(struct nfs_context *nfs)
        return rpc_get_error(nfs->rpc);
 };
 
+static int nfs_set_context_args(struct nfs_context *nfs, char *arg, char *val)
+{
+       if (!strncmp(arg, "tcp-syncnt", 10)) {
+               rpc_set_tcp_syncnt(nfs_get_rpc_context(nfs), atoi(val));
+       } else if (!strncmp(arg, "uid", 3)) {
+               rpc_set_uid(nfs_get_rpc_context(nfs), atoi(val));
+       } else if (!strncmp(arg, "gid", 3)) {
+               rpc_set_gid(nfs_get_rpc_context(nfs), atoi(val));
+       }
+       return 0;
+}
+
+static struct nfs_url *nfs_parse_url(struct nfs_context *nfs, const char *url, int dir, int incomplete)
+{
+       struct nfs_url *urls;
+       char *strp, *flagsp, *strp2;
+
+       if (strncmp(url, "nfs://", 6)) {
+               rpc_set_error(nfs->rpc, "Invalid URL specified");
+               return NULL;
+       }
+
+       urls = malloc(sizeof(struct nfs_url));
+       if (urls == NULL) {
+               rpc_set_error(nfs->rpc, "Out of memory");
+               return NULL;
+       }
+
+       memset(urls, 0x00, sizeof(struct nfs_url));
+       urls->server = strdup(url + 6);
+       if (urls->server == NULL) {
+               nfs_destroy_url(urls);
+               rpc_set_error(nfs->rpc, "Out of memory");
+               return NULL;
+       }
+
+       if (urls->server[0] == '/' || urls->server[0] == '\0' ||
+               urls->server[0] == '?') {
+               if (incomplete) {
+                       flagsp = strchr(urls->server, '?');
+                       goto flags;
+               }
+               nfs_destroy_url(urls);
+               rpc_set_error(nfs->rpc, "Invalid server string");
+               return NULL;
+       }
+
+       strp = strchr(urls->server, '/');
+       if (strp == NULL) {
+               if (incomplete) {
+                       flagsp = strchr(urls->server, '?');
+                       goto flags;
+               }
+               nfs_destroy_url(urls);
+               rpc_set_error(nfs->rpc, "Incomplete or invalid URL specified.");
+               return NULL;
+       }
+
+       urls->path = strdup(strp);
+       if (urls->path == NULL) {
+               nfs_destroy_url(urls);
+               rpc_set_error(nfs->rpc, "Out of memory");
+               return NULL;
+       }
+       *strp = 0;
+
+       if (dir) {
+               flagsp = strchr(urls->path, '?');
+               goto flags;
+       }
+
+       strp = strrchr(urls->path, '/');
+       if (strp == NULL) {
+               if (incomplete) {
+                       flagsp = strchr(urls->path, '?');
+                       goto flags;
+               }
+               nfs_destroy_url(urls);
+               rpc_set_error(nfs->rpc, "Incomplete or invalid URL specified.");
+               return NULL;
+       }
+       urls->file = strdup(strp);
+       if (urls->path == NULL) {
+               nfs_destroy_url(urls);
+               rpc_set_error(nfs->rpc, "Out of memory");
+               return NULL;
+       }
+       *strp = 0;
+       flagsp = strchr(urls->file, '?');
+
+flags:
+       if (flagsp) {
+               *flagsp = 0;
+       }
+
+       if (urls->file && !strlen(urls->file)) {
+               free(urls->file);
+               urls->file = NULL;
+               if (!incomplete) {
+                       nfs_destroy_url(urls);
+                       rpc_set_error(nfs->rpc, "Incomplete or invalid URL specified.");
+                       return NULL;
+               }
+       }
+
+       while (flagsp != NULL && *(flagsp+1) != 0) {
+               strp = flagsp + 1;
+               flagsp = strchr(strp, '&');
+               if (flagsp) {
+                       *flagsp = 0;
+               }
+               strp2 = strchr(strp, '=');
+               if (strp2) {
+                       *strp2 = 0;
+                       strp2++;
+                       nfs_set_context_args(nfs, strp, strp2);
+               }
+       }
+
+       if (urls->server && strlen(urls->server) <= 1) {
+               free(urls->server);
+               urls->server = NULL;
+       }
+
+       return urls;
+}
+
+struct nfs_url *nfs_parse_url_full(struct nfs_context *nfs, const char *url)
+{
+       return nfs_parse_url(nfs, url, 0, 0);
+}
+
+struct nfs_url *nfs_parse_url_dir(struct nfs_context *nfs, const char *url)
+{
+       return nfs_parse_url(nfs, url, 1, 0);
+}
+
+struct nfs_url *nfs_parse_url_incomplete(struct nfs_context *nfs, const char *url)
+{
+       return nfs_parse_url(nfs, url, 0, 1);
+}
+
+
+void nfs_destroy_url(struct nfs_url *url)
+{
+       if (url) {
+               free(url->server);
+               free(url->path);
+               free(url->file);
+       }
+       free(url);
+}
+
 struct nfs_context *nfs_init_context(void)
 {
        struct nfs_context *nfs;
@@ -219,6 +372,155 @@ void nfs_destroy_context(struct nfs_context *nfs)
        free(nfs);
 }
 
+struct rpc_cb_data {
+       char *server;
+       uint32_t program;
+       uint32_t version;
+
+       rpc_cb cb;
+       void *private_data;
+};
+
+void free_rpc_cb_data(struct rpc_cb_data *data)
+{
+       free(data->server);
+       data->server = NULL;
+       free(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;
+
+       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_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;
+
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
+       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;
+       }
+
+       rpc_port = *(uint32_t *)command_data;
+       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);
+               free_rpc_cb_data(data);
+               return;
+       }
+
+       rpc_disconnect(rpc, "normal disconnect");
+       if (rpc_connect_async(rpc, data->server, rpc_port, rpc_connect_program_4_cb, data) != 0) {
+               data->cb(rpc, status, command_data, data->private_data);
+               free_rpc_cb_data(data);
+               return;
+       }
+}
+
+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;
+
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
+       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;
+       }
+
+       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;
+       }
+}
+
+static void rpc_connect_program_1_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;
+       }
+
+       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;
+       }
+}
+
+int rpc_connect_program_async(struct rpc_context *rpc, char *server, int program, int version, rpc_cb cb, void *private_data)
+{
+       struct rpc_cb_data *data;
+
+       data = malloc(sizeof(struct rpc_cb_data));
+       if (data == NULL) {
+               return -1;
+       }
+       memset(data, 0, sizeof(struct rpc_cb_data));
+       data->server       = strdup(server);
+       data->program      = program;
+       data->version      = version;
+
+       data->cb           = cb;
+       data->private_data = private_data;
+
+       if (rpc_connect_async(rpc, server, 111, rpc_connect_program_1_cb, data) != 0) {
+               rpc_set_error(rpc, "Failed to start connection");
+               free_rpc_cb_data(data);
+               return -1;
+       }
+       return 0;
+}
+
 void free_nfs_cb_data(struct nfs_cb_data *data)
 {
        if (data->saved_path != NULL) {
@@ -275,6 +577,7 @@ static void nfs_mount_9_cb(struct rpc_context *rpc, int status, void *command_da
        struct nfs_cb_data *data = private_data;
        struct nfs_context *nfs = data->nfs;
        FSINFO3res *res = command_data;
+       struct GETATTR3args args;
 
        assert(rpc->magic == RPC_CONTEXT_MAGIC);
 
@@ -292,7 +595,10 @@ static void nfs_mount_9_cb(struct rpc_context *rpc, int status, void *command_da
        nfs->readmax = res->FSINFO3res_u.resok.rtmax;
        nfs->writemax = res->FSINFO3res_u.resok.wtmax;
 
-       if (rpc_nfs_getattr_async(rpc, nfs_mount_10_cb, &nfs->rootfh, data) != 0) {
+       memset(&args, 0, sizeof(GETATTR3args));
+       args.object = nfs->rootfh;
+
+       if (rpc_nfs3_getattr_async(rpc, nfs_mount_10_cb, &args, data) != 0) {
                data->cb(-ENOMEM, nfs, command_data, data->private_data);
                free_nfs_cb_data(data);
                return;
@@ -303,6 +609,7 @@ static void nfs_mount_8_cb(struct rpc_context *rpc, int status, void *command_da
 {
        struct nfs_cb_data *data = private_data;
        struct nfs_context *nfs = data->nfs;
+       struct FSINFO3args args;
 
        assert(rpc->magic == RPC_CONTEXT_MAGIC);
 
@@ -317,7 +624,8 @@ static void nfs_mount_8_cb(struct rpc_context *rpc, int status, void *command_da
                return;
        }
 
-       if (rpc_nfs_fsinfo_async(rpc, nfs_mount_9_cb, &nfs->rootfh, data) != 0) {
+       args.fsroot = nfs->rootfh;
+       if (rpc_nfs3_fsinfo_async(rpc, nfs_mount_9_cb, &args, data) != 0) {
                data->cb(-ENOMEM, nfs, command_data, data->private_data);
                free_nfs_cb_data(data);
                return;
@@ -346,7 +654,7 @@ static void nfs_mount_7_cb(struct rpc_context *rpc, int status, void *command_da
                return;
        }
 
-       if (rpc_nfs_null_async(rpc, nfs_mount_8_cb, data) != 0) {
+       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;
@@ -420,7 +728,7 @@ static void nfs_mount_5_cb(struct rpc_context *rpc, int status, void *command_da
                return;
        }
 
-       if (rpc_mount_mnt_async(rpc, nfs_mount_6_cb, nfs->export, data) != 0) {
+       if (rpc_mount3_mnt_async(rpc, nfs_mount_6_cb, nfs->export, data) != 0) {
                data->cb(-ENOMEM, nfs, command_data, data->private_data);
                free_nfs_cb_data(data);
                return;
@@ -448,7 +756,7 @@ static void nfs_mount_4_cb(struct rpc_context *rpc, int status, void *command_da
                return;
        }
 
-       if (rpc_mount_null_async(rpc, nfs_mount_5_cb, data) != 0) {
+       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;
@@ -625,6 +933,7 @@ static void nfs_lookup_path_1_cb(struct rpc_context *rpc, int status, void *comm
 static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh)
 {
        char *path, *str;
+       LOOKUP3args args;
 
        while (*data->path == '/') {
              data->path++;
@@ -655,7 +964,12 @@ static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb
                return 0;
        }
 
-       if (rpc_nfs_lookup_async(nfs->rpc, nfs_lookup_path_1_cb, fh, path, data) != 0) {
+
+       memset(&args, 0, sizeof(LOOKUP3args));
+       args.what.dir = *fh;
+       args.what.name = path;
+
+       if (rpc_nfs3_lookup_async(nfs->rpc, nfs_lookup_path_1_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send lookup call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -768,7 +1082,12 @@ static void nfs_stat_1_cb(struct rpc_context *rpc, int status, void *command_dat
 
 static int nfs_stat_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
 {
-       if (rpc_nfs_getattr_async(nfs->rpc, nfs_stat_1_cb, &data->fh, data) != 0) {
+       struct GETATTR3args args;
+
+       memset(&args, 0, sizeof(GETATTR3args));
+       args.object = data->fh;
+
+       if (rpc_nfs3_getattr_async(nfs->rpc, nfs_stat_1_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send STAT GETATTR call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -861,8 +1180,7 @@ static void nfs_open_cb(struct rpc_context *rpc, int status, void *command_data,
        }
 
        /* steal the filehandle */
-       nfsfh->fh.data.data_len = data->fh.data.data_len;
-       nfsfh->fh.data.data_val = data->fh.data.data_val;
+       nfsfh->fh = data->fh;
        data->fh.data.data_val = NULL;
 
        data->cb(0, nfs, nfsfh, data->private_data);
@@ -872,6 +1190,7 @@ static void nfs_open_cb(struct rpc_context *rpc, int status, void *command_data,
 static int nfs_open_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
 {
        int nfsmode = 0;
+       ACCESS3args args;
 
        if (data->continue_int & O_WRONLY) {
                nfsmode |= ACCESS3_MODIFY;
@@ -883,7 +1202,11 @@ static int nfs_open_continue_internal(struct nfs_context *nfs, struct nfs_cb_dat
                nfsmode |= ACCESS3_READ;
        }
 
-       if (rpc_nfs_access_async(nfs->rpc, nfs_open_cb, &data->fh, nfsmode, data) != 0) {
+       memset(&args, 0, sizeof(ACCESS3args));
+       args.object = data->fh;
+       args.access = nfsmode;
+
+       if (rpc_nfs3_access_async(nfs->rpc, nfs_open_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send OPEN ACCESS call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -1021,7 +1344,14 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offse
        nfsfh->offset = offset;
 
        if (count <= nfs_get_readmax(nfs)) {
-               if (rpc_nfs_read_async(nfs->rpc, nfs_pread_cb, &nfsfh->fh, offset, count, data) != 0) {
+               READ3args args;
+
+               memset(&args, 0, sizeof(READ3args));
+               args.file = nfsfh->fh;
+               args.offset = offset;
+               args.count = count;
+
+               if (rpc_nfs3_read_async(nfs->rpc, nfs_pread_cb, &args, data) != 0) {
                        rpc_set_error(nfs->rpc, "RPC error: Failed to send READ call for %s", data->path);
                        data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                        free_nfs_cb_data(data);
@@ -1032,7 +1362,7 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offse
 
        /* trying to read more than maximum server read size, we has to chop it up into smaller
         * reads and collect into a reassembly buffer.
-        * we send all reads in parallell so that performance is still good.
+        * we send all reads in parallel so that performance is still good.
         */
        data->max_offset = offset;
        data->start_offset = offset;
@@ -1048,6 +1378,7 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offse
        while (count > 0) {
                uint64_t readcount = count;
                struct nfs_mcb_data *mdata;
+               READ3args args;
 
                if (readcount > nfs_get_readmax(nfs)) {
                        readcount = nfs_get_readmax(nfs);
@@ -1062,7 +1393,13 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offse
                mdata->data   = data;
                mdata->offset = offset;
                mdata->count  = readcount;
-               if (rpc_nfs_read_async(nfs->rpc, nfs_pread_mcb, &nfsfh->fh, offset, readcount, mdata) != 0) {
+
+               memset(&args, 0, sizeof(READ3args));
+               args.file = nfsfh->fh;
+               args.offset = offset;
+               args.count = readcount;
+
+               if (rpc_nfs3_read_async(nfs->rpc, nfs_pread_mcb, &args, mdata) != 0) {
                        rpc_set_error(nfs->rpc, "RPC error: Failed to send READ call for %s", data->path);
                        data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                        free(mdata);
@@ -1201,7 +1538,17 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs
        nfsfh->offset = offset;
 
        if (count <= nfs_get_writemax(nfs)) {
-               if (rpc_nfs_write_async(nfs->rpc, nfs_pwrite_cb, &nfsfh->fh, buf, offset, count, nfsfh->is_sync?FILE_SYNC:UNSTABLE, data) != 0) {
+               WRITE3args args;
+
+               memset(&args, 0, sizeof(WRITE3args));
+               args.file = nfsfh->fh;
+               args.offset = offset;
+               args.count  = count;
+               args.stable = nfsfh->is_sync?FILE_SYNC:UNSTABLE;
+               args.data.data_len = count;
+               args.data.data_val = buf;
+
+               if (rpc_nfs3_write_async(nfs->rpc, nfs_pwrite_cb, &args, data) != 0) {
                        rpc_set_error(nfs->rpc, "RPC error: Failed to send WRITE call for %s", data->path);
                        data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                        free_nfs_cb_data(data);
@@ -1212,7 +1559,7 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs
 
        /* trying to write more than maximum server write size, we has to chop it up into smaller
         * chunks.
-        * we send all writes in parallell so that performance is still good.
+        * we send all writes in parallel so that performance is still good.
         */
        data->max_offset = offset;
        data->start_offset = offset;
@@ -1220,6 +1567,7 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs
        while (count > 0) {
                uint64_t writecount = count;
                struct nfs_mcb_data *mdata;
+               WRITE3args args;
 
                if (writecount > nfs_get_writemax(nfs)) {
                        writecount = nfs_get_writemax(nfs);
@@ -1235,7 +1583,15 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs
                mdata->offset = offset;
                mdata->count  = writecount;
 
-               if (rpc_nfs_write_async(nfs->rpc, nfs_pwrite_mcb, &nfsfh->fh, &buf[offset - data->start_offset], offset, writecount, nfsfh->is_sync?FILE_SYNC:UNSTABLE, mdata) != 0) {
+               memset(&args, 0, sizeof(WRITE3args));
+               args.file = nfsfh->fh;
+               args.offset = offset;
+               args.count  = writecount;
+               args.stable = nfsfh->is_sync?FILE_SYNC:UNSTABLE;
+               args.data.data_len = writecount;
+               args.data.data_val = &buf[offset - data->start_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);
                        data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                        free(mdata);
@@ -1287,6 +1643,7 @@ int nfs_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, voi
 int nfs_fstat_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data)
 {
        struct nfs_cb_data *data;
+       struct GETATTR3args args;
 
        data = malloc(sizeof(struct nfs_cb_data));
        if (data == NULL) {
@@ -1298,7 +1655,10 @@ int nfs_fstat_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, voi
        data->cb           = cb;
        data->private_data = private_data;
 
-       if (rpc_nfs_getattr_async(nfs->rpc, nfs_stat_1_cb, &nfsfh->fh, data) != 0) {
+       memset(&args, 0, sizeof(GETATTR3args));
+       args.object = nfsfh->fh;
+
+       if (rpc_nfs3_getattr_async(nfs->rpc, nfs_stat_1_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send STAT GETATTR call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -1346,6 +1706,7 @@ static void nfs_fsync_cb(struct rpc_context *rpc, int status, void *command_data
 int nfs_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data)
 {
        struct nfs_cb_data *data;
+       struct COMMIT3args args;
 
        data = malloc(sizeof(struct nfs_cb_data));
        if (data == NULL) {
@@ -1357,7 +1718,10 @@ int nfs_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, voi
        data->cb           = cb;
        data->private_data = private_data;
 
-       if (rpc_nfs_commit_async(nfs->rpc, nfs_fsync_cb, &nfsfh->fh, data) != 0) {
+       args.file = nfsfh->fh;
+       args.offset = 0;
+       args.count = 0;
+       if (rpc_nfs3_commit_async(nfs->rpc, nfs_fsync_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send COMMIT call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -1419,12 +1783,11 @@ int nfs_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t l
        data->private_data = private_data;
 
        memset(&args, 0, sizeof(SETATTR3args));
-       args.object.data.data_len = nfsfh->fh.data.data_len;
-       args.object.data.data_val = nfsfh->fh.data.data_val;
+       args.object = nfsfh->fh;
        args.new_attributes.size.set_it = 1;
        args.new_attributes.size.set_size3_u.size = length;
 
-       if (rpc_nfs_setattr_async(nfs->rpc, nfs_ftruncate_cb, &args, data) != 0) {
+       if (rpc_nfs3_setattr_async(nfs->rpc, nfs_ftruncate_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -1442,8 +1805,7 @@ static int nfs_truncate_continue_internal(struct nfs_context *nfs, struct nfs_cb
        uint64_t offset = data->continue_int;
        struct nfsfh nfsfh;
 
-       nfsfh.fh.data.data_val = data->fh.data.data_val;
-       nfsfh.fh.data.data_len = data->fh.data.data_len;
+       nfsfh.fh = data->fh;
 
        if (nfs_ftruncate_async(nfs, &nfsfh, offset, data->cb, data->private_data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
@@ -1517,13 +1879,12 @@ static int nfs_mkdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_da
        str = &str[strlen(str) + 1];
 
        memset(&args, 0, sizeof(MKDIR3args));
-       args.where.dir.data.data_len = data->fh.data.data_len;
-       args.where.dir.data.data_val = data->fh.data.data_val;
+       args.where.dir = data->fh;
        args.where.name = str;
        args.attributes.mode.set_it = 1;
        args.attributes.mode.set_mode3_u.mode = 0755;
 
-       if (rpc_nfs_mkdir_async(nfs->rpc, nfs_mkdir_cb, &args, data) != 0) {
+       if (rpc_nfs3_mkdir_async(nfs->rpc, nfs_mkdir_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send MKDIR call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -1603,10 +1964,13 @@ static void nfs_rmdir_cb(struct rpc_context *rpc, int status, void *command_data
 static int nfs_rmdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
 {
        char *str = data->continue_data;
-       
+       RMDIR3args args;
+
        str = &str[strlen(str) + 1];
 
-       if (rpc_nfs_rmdir_async(nfs->rpc, nfs_rmdir_cb, &data->fh, str, data) != 0) {
+       args.object.dir = data->fh;
+       args.object.name = str;
+       if (rpc_nfs3_rmdir_async(nfs->rpc, nfs_rmdir_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send RMDIR call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -1704,6 +2068,7 @@ static void nfs_creat_1_cb(struct rpc_context *rpc, int status, void *command_da
        struct nfs_cb_data *data = private_data;
        struct nfs_context *nfs = data->nfs;
        char *str = data->continue_data;
+       LOOKUP3args args;
 
        assert(rpc->magic == RPC_CONTEXT_MAGIC);
 
@@ -1723,11 +2088,15 @@ static void nfs_creat_1_cb(struct rpc_context *rpc, int status, void *command_da
        if (res->status != NFS3_OK) {
                rpc_set_error(nfs->rpc, "NFS: CREATE of %s/%s failed with %s(%d)", data->saved_path, str, 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 (rpc_nfs_lookup_async(nfs->rpc, nfs_create_2_cb, &data->fh, str, data) != 0) {
+       memset(&args, 0, sizeof(LOOKUP3args));
+       args.what.dir = data->fh;
+       args.what.name = str;
+
+       if (rpc_nfs3_lookup_async(nfs->rpc, nfs_create_2_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send lookup call for %s/%s", data->saved_path, str);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -1744,14 +2113,13 @@ static int nfs_creat_continue_internal(struct nfs_context *nfs, struct nfs_cb_da
        str = &str[strlen(str) + 1];
 
        memset(&args, 0, sizeof(CREATE3args));
-       args.where.dir.data.data_len = data->fh.data.data_len;
-       args.where.dir.data.data_val = data->fh.data.data_val;
+       args.where.dir = data->fh;
        args.where.name = str;
        args.how.mode = UNCHECKED;
        args.how.createhow3_u.obj_attributes.mode.set_it = 1;
        args.how.createhow3_u.obj_attributes.mode.set_mode3_u.mode = data->continue_int;
 
-       if (rpc_nfs_create_async(nfs->rpc, nfs_creat_1_cb, &args, data) != 0) {
+       if (rpc_nfs3_create_async(nfs->rpc, nfs_creat_1_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send CREATE call for %s/%s", data->path, str);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -1830,10 +2198,13 @@ static void nfs_unlink_cb(struct rpc_context *rpc, int status, void *command_dat
 static int nfs_unlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
 {
        char *str = data->continue_data;
-       
+       struct REMOVE3args args;
+
        str = &str[strlen(str) + 1];
 
-       if (rpc_nfs_remove_async(nfs->rpc, nfs_unlink_cb, &data->fh, str, data) != 0) {
+       args.object.dir = data->fh;
+       args.object.name = str;
+       if (rpc_nfs3_remove_async(nfs->rpc, nfs_unlink_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send REMOVE call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -1926,10 +2297,44 @@ static int nfs_mknod_continue_internal(struct nfs_context *nfs, struct nfs_cb_da
 {
        struct mknod_cb_data *cb_data = data->continue_data;
        char *str = cb_data->path;
+       MKNOD3args args;
        
        str = &str[strlen(str) + 1];
 
-       if (rpc_nfs_mknod_async(nfs->rpc, nfs_mknod_cb, &data->fh, str, cb_data->mode, cb_data->major, cb_data->minor, data) != 0) {
+       args.where.dir = data->fh;
+       args.where.name = str;
+       switch (cb_data->mode & S_IFMT) {
+       case S_IFCHR:
+               args.what.type = NF3CHR;
+               args.what.mknoddata3_u.chr_device.dev_attributes.mode.set_it = 1;
+               args.what.mknoddata3_u.chr_device.dev_attributes.mode.set_mode3_u.mode = cb_data->mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
+               args.what.mknoddata3_u.chr_device.spec.specdata1 = cb_data->major;
+               args.what.mknoddata3_u.chr_device.spec.specdata2 = cb_data->minor;
+               break;
+       case S_IFBLK:
+               args.what.type = NF3BLK;
+               args.what.mknoddata3_u.blk_device.dev_attributes.mode.set_it = 1;
+               args.what.mknoddata3_u.blk_device.dev_attributes.mode.set_mode3_u.mode = cb_data->mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
+               args.what.mknoddata3_u.blk_device.spec.specdata1 = cb_data->major;
+               args.what.mknoddata3_u.blk_device.spec.specdata2 = cb_data->minor;
+       case S_IFSOCK:
+               args.what.type = NF3SOCK;
+               args.what.mknoddata3_u.sock_attributes.mode.set_it = 1;
+               args.what.mknoddata3_u.sock_attributes.mode.set_mode3_u.mode = cb_data->mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
+               break;
+       case S_IFIFO:
+               args.what.type = NF3FIFO;
+               args.what.mknoddata3_u.pipe_attributes.mode.set_it = 1;
+               args.what.mknoddata3_u.pipe_attributes.mode.set_mode3_u.mode = cb_data->mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
+               break;
+       default:
+               rpc_set_error(nfs->rpc, "Invalid file type for NFS3/MKNOD call");
+               data->cb(-EINVAL, nfs, rpc_get_error(nfs->rpc), data->private_data);
+               free_nfs_cb_data(data);
+               return -1;
+       }
+
+       if (rpc_nfs3_mknod_async(nfs->rpc, nfs_mknod_cb, &args, data) != 0) {
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
                return -1;
@@ -2033,6 +2438,8 @@ static void nfs_opendir3_cb(struct rpc_context *rpc, int status, void *command_d
                        nfsdirent->mtime.tv_usec = attributes->mtime.nseconds/1000;
                        nfsdirent->ctime.tv_sec  = attributes->ctime.seconds;
                        nfsdirent->ctime.tv_usec = attributes->ctime.nseconds/1000;
+                       nfsdirent->uid = attributes->uid;
+                       nfsdirent->gid = attributes->gid;
                }
        }
 
@@ -2117,7 +2524,14 @@ static void nfs_opendir2_cb(struct rpc_context *rpc, int status, void *command_d
        }
 
        if (res->READDIR3res_u.resok.reply.eof == 0) {
-               if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir2_cb, &data->fh, cookie, res->READDIR3res_u.resok.cookieverf, 8192, data) != 0) {
+               READDIR3args args;
+
+               args.dir = data->fh;
+               args.cookie = cookie;
+               memcpy(&args.cookieverf, res->READDIR3res_u.resok.cookieverf, sizeof(cookieverf3));
+               args.count = 8192;
+
+               if (rpc_nfs3_readdir_async(nfs->rpc, nfs_opendir2_cb, &args, data) != 0) {
                        rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR call for %s", data->path);
                        data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                        nfs_free_nfsdir(nfsdir);
@@ -2137,12 +2551,17 @@ static void nfs_opendir2_cb(struct rpc_context *rpc, int status, void *command_d
        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;
 
-               if (rpc_nfs_lookup_async(nfs->rpc, nfs_opendir3_cb, &data->fh, nfsdirent->name, rdpe_lookup_cb_data) != 0) {
+               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
@@ -2179,9 +2598,14 @@ static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_da
        assert(rpc->magic == RPC_CONTEXT_MAGIC);
 
        if (status == RPC_STATUS_ERROR || (status == RPC_STATUS_SUCCESS && res->status == NFS3ERR_NOTSUPP) ){
-               cookieverf3 cv;
+               READDIR3args args;
+
+               args.dir = data->fh;
+               args.cookie = cookie;
+               memset(&args.cookieverf, 0, sizeof(cookieverf3));
+               args.count = 8192;
 
-               if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir2_cb, &data->fh, 0, (char *)&cv, 8192, data) != 0) {
+               if (rpc_nfs3_readdir_async(nfs->rpc, nfs_opendir2_cb, &args, data) != 0) {
                        rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR call for %s", data->path);
                        data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                        nfs_free_nfsdir(nfsdir);
@@ -2242,6 +2666,8 @@ static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_da
                        nfsdirent->mtime.tv_usec = entry->name_attributes.post_op_attr_u.attributes.mtime.nseconds/1000;
                        nfsdirent->ctime.tv_sec  = entry->name_attributes.post_op_attr_u.attributes.ctime.seconds;
                        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->next  = nfsdir->entries;
@@ -2252,7 +2678,15 @@ static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_da
        }
 
        if (res->READDIRPLUS3res_u.resok.reply.eof == 0) {
-               if (rpc_nfs_readdirplus_async(nfs->rpc, nfs_opendir_cb, &data->fh, cookie, res->READDIRPLUS3res_u.resok.cookieverf, 8192, data) != 0) {
+               READDIRPLUS3args args;
+
+               args.dir = data->fh;
+               args.cookie = cookie;
+               memcpy(&args.cookieverf, res->READDIRPLUS3res_u.resok.cookieverf, sizeof(cookieverf3));
+               args.dircount = 8192;
+               args.maxcount = 8192;
+
+               if (rpc_nfs3_readdirplus_async(nfs->rpc, nfs_opendir_cb, &args, data) != 0) {
                        rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIRPLUS call for %s", data->path);
                        data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                        nfs_free_nfsdir(nfsdir);
@@ -2273,10 +2707,14 @@ static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_da
 
 static int nfs_opendir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
 {
-       cookieverf3 cv;
-
-       memset(cv, 0, sizeof(cookieverf3));
-       if (rpc_nfs_readdirplus_async(nfs->rpc, nfs_opendir_cb, &data->fh, 0, (char *)&cv, 8192, data) != 0) {
+       READDIRPLUS3args args;
+
+       args.dir = data->fh;
+       args.cookie = 0;
+       memset(&args.cookieverf, 0, sizeof(cookieverf3));
+       args.dircount = 8192;
+       args.maxcount = 8192;
+       if (rpc_nfs3_readdirplus_async(nfs->rpc, nfs_opendir_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIRPLUS call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -2373,6 +2811,7 @@ static void nfs_lseek_1_cb(struct rpc_context *rpc, int status, void *command_da
 int nfs_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_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;
@@ -2397,7 +2836,10 @@ int nfs_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offse
        data->cb           = cb;
        data->private_data = private_data;
 
-       if (rpc_nfs_getattr_async(nfs->rpc, nfs_lseek_1_cb, &nfsfh->fh, data) != 0) {
+       memset(&args, 0, sizeof(GETATTR3args));
+       args.object = nfsfh->fh;
+
+       if (rpc_nfs3_getattr_async(nfs->rpc, nfs_lseek_1_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send LSEEK GETATTR call");
                free(data);
                return -1;
@@ -2459,7 +2901,10 @@ static void nfs_statvfs_1_cb(struct rpc_context *rpc, int status, void *command_
 
 static int nfs_statvfs_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
 {
-       if (rpc_nfs_fsstat_async(nfs->rpc, nfs_statvfs_1_cb, &data->fh, data) != 0) {
+       FSSTAT3args args;
+
+       args.fsroot = data->fh;
+       if (rpc_nfs3_fsstat_async(nfs->rpc, nfs_statvfs_1_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send FSSTAT call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -2520,10 +2965,9 @@ static int nfs_readlink_continue_internal(struct nfs_context *nfs, struct nfs_cb
 {
        READLINK3args args;
 
-       args.symlink.data.data_len = data->fh.data.data_len; 
-       args.symlink.data.data_val = data->fh.data.data_val; 
+       args.symlink = data->fh;
 
-       if (rpc_nfs_readlink_async(nfs->rpc, nfs_readlink_1_cb, &args, data) != 0) {
+       if (rpc_nfs3_readlink_async(nfs->rpc, nfs_readlink_1_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send READLINK call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -2584,12 +3028,11 @@ static int nfs_chmod_continue_internal(struct nfs_context *nfs, struct nfs_cb_da
        SETATTR3args args;
 
        memset(&args, 0, sizeof(SETATTR3args));
-       args.object.data.data_len = data->fh.data.data_len;
-       args.object.data.data_val = data->fh.data.data_val;
+       args.object = data->fh;
        args.new_attributes.mode.set_it = 1;
        args.new_attributes.mode.set_mode3_u.mode = data->continue_int;
 
-       if (rpc_nfs_setattr_async(nfs->rpc, nfs_chmod_cb, &args, data) != 0) {
+       if (rpc_nfs3_setattr_async(nfs->rpc, nfs_chmod_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -2690,8 +3133,7 @@ static int nfs_chown_continue_internal(struct nfs_context *nfs, struct nfs_cb_da
        struct nfs_chown_data *chown_data = data->continue_data;
 
        memset(&args, 0, sizeof(SETATTR3args));
-       args.object.data.data_len = data->fh.data.data_len;
-       args.object.data.data_val = data->fh.data.data_val;
+       args.object = data->fh;
        if (chown_data->uid != (uid_t)-1) {
                args.new_attributes.uid.set_it = 1;
                args.new_attributes.uid.set_uid3_u.uid = chown_data->uid;
@@ -2701,7 +3143,7 @@ static int nfs_chown_continue_internal(struct nfs_context *nfs, struct nfs_cb_da
                args.new_attributes.gid.set_gid3_u.gid = chown_data->gid;
        }
 
-       if (rpc_nfs_setattr_async(nfs->rpc, nfs_chown_cb, &args, data) != 0) {
+       if (rpc_nfs3_setattr_async(nfs->rpc, nfs_chown_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -2823,8 +3265,7 @@ static int nfs_utimes_continue_internal(struct nfs_context *nfs, struct nfs_cb_d
        struct timeval *utimes_data = data->continue_data;
 
        memset(&args, 0, sizeof(SETATTR3args));
-       args.object.data.data_len = data->fh.data.data_len;
-       args.object.data.data_val = data->fh.data.data_val;
+       args.object = data->fh;
        if (utimes_data != NULL) {
                args.new_attributes.atime.set_it = SET_TO_CLIENT_TIME;
                args.new_attributes.atime.set_atime_u.atime.seconds  = utimes_data[0].tv_sec;
@@ -2837,7 +3278,7 @@ static int nfs_utimes_continue_internal(struct nfs_context *nfs, struct nfs_cb_d
                args.new_attributes.mtime.set_it = SET_TO_SERVER_TIME;
        }
 
-       if (rpc_nfs_setattr_async(nfs->rpc, nfs_utimes_cb, &args, data) != 0) {
+       if (rpc_nfs3_setattr_async(nfs->rpc, nfs_utimes_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -2959,6 +3400,7 @@ static void nfs_access_cb(struct rpc_context *rpc, int status, void *command_dat
 static int nfs_access_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
 {
        int nfsmode = 0;
+       ACCESS3args args;
 
        if (data->continue_int & R_OK) {
                nfsmode |= ACCESS3_READ;
@@ -2970,7 +3412,11 @@ static int nfs_access_continue_internal(struct nfs_context *nfs, struct nfs_cb_d
                nfsmode |= ACCESS3_EXECUTE;
        }
 
-       if (rpc_nfs_access_async(nfs->rpc, nfs_access_cb, &data->fh, nfsmode, data) != 0) {
+       memset(&args, 0, sizeof(ACCESS3args));
+       args.object = data->fh;
+       args.access = nfsmode;
+
+       if (rpc_nfs3_access_async(nfs->rpc, nfs_access_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send OPEN ACCESS call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -3051,17 +3497,16 @@ static void nfs_symlink_cb(struct rpc_context *rpc, int status, void *command_da
 static int nfs_symlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
 {
        struct nfs_symlink_data *symlink_data = data->continue_data;
-       SYMLINK3args sa;
+       SYMLINK3args args;
 
-       memset(&sa, 0, sizeof(SYMLINK3args));
-       sa.where.dir.data.data_len = data->fh.data.data_len;
-       sa.where.dir.data.data_val = data->fh.data.data_val;
-       sa.where.name = symlink_data->newpathobject;
-       sa.symlink.symlink_attributes.mode.set_it = 1;
-       sa.symlink.symlink_attributes.mode.set_mode3_u.mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH;
-       sa.symlink.symlink_data = symlink_data->oldpath;
+       memset(&args, 0, sizeof(SYMLINK3args));
+       args.where.dir = data->fh;
+       args.where.name = symlink_data->newpathobject;
+       args.symlink.symlink_attributes.mode.set_it = 1;
+       args.symlink.symlink_attributes.mode.set_mode3_u.mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH;
+       args.symlink.symlink_data = symlink_data->oldpath;
 
-       if (rpc_nfs_symlink_async(nfs->rpc, nfs_symlink_cb, &sa, data) != 0) {
+       if (rpc_nfs3_symlink_async(nfs->rpc, nfs_symlink_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send SYMLINK call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -3188,13 +3633,17 @@ static void nfs_rename_cb(struct rpc_context *rpc, int status, void *command_dat
 static int nfs_rename_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
 {
        struct nfs_rename_data *rename_data = data->continue_data;
+       RENAME3args args;
 
        /* steal the filehandle */
-       rename_data->newdir.data.data_len = data->fh.data.data_len;
-       rename_data->newdir.data.data_val = data->fh.data.data_val;
+       rename_data->newdir = data->fh;
        data->fh.data.data_val = NULL;
 
-       if (rpc_nfs_rename_async(nfs->rpc, nfs_rename_cb, &rename_data->olddir, rename_data->oldobject, &rename_data->newdir, rename_data->newobject, data) != 0) {
+       args.from.dir = rename_data->olddir;
+       args.from.name = rename_data->oldobject;
+       args.to.dir = rename_data->newdir;
+       args.to.name = rename_data->newobject;
+       if (rpc_nfs3_rename_async(nfs->rpc, nfs_rename_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send RENAME call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -3209,8 +3658,7 @@ static int nfs_rename_continue_1_internal(struct nfs_context *nfs, struct nfs_cb
        struct nfs_rename_data *rename_data = data->continue_data;
 
        /* steal the filehandle */
-       rename_data->olddir.data.data_len = data->fh.data.data_len;
-       rename_data->olddir.data.data_val = data->fh.data.data_val;
+       rename_data->olddir = data->fh;
        data->fh.data.data_val = NULL;
 
        if (nfs_lookuppath_async(nfs, rename_data->newpath, data->cb, data->private_data, nfs_rename_continue_2_internal, rename_data, free_nfs_rename_data, 0) != 0) {
@@ -3346,13 +3794,17 @@ static void nfs_link_cb(struct rpc_context *rpc, int status, void *command_data,
 static int nfs_link_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
 {
        struct nfs_link_data *link_data = data->continue_data;
+       LINK3args args;
 
        /* steal the filehandle */
-       link_data->newdir.data.data_len = data->fh.data.data_len;
-       link_data->newdir.data.data_val = data->fh.data.data_val;
+       link_data->newdir = data->fh;
        data->fh.data.data_val = NULL;
 
-       if (rpc_nfs_link_async(nfs->rpc, nfs_link_cb, &link_data->oldfh, &link_data->newdir, link_data->newobject, data) != 0) {
+       memset(&args, 0, sizeof(LINK3args));
+       args.file = link_data->oldfh;
+       args.link.dir = link_data->newdir;
+       args.link.name = link_data->newobject;
+       if (rpc_nfs3_link_async(nfs->rpc, nfs_link_cb, &args, data) != 0) {
                rpc_set_error(nfs->rpc, "RPC error: Failed to send LINK call for %s", data->path);
                data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
                free_nfs_cb_data(data);
@@ -3367,8 +3819,7 @@ static int nfs_link_continue_1_internal(struct nfs_context *nfs, struct nfs_cb_d
        struct nfs_link_data *link_data = data->continue_data;
 
        /* steal the filehandle */
-       link_data->oldfh.data.data_len = data->fh.data.data_len;
-       link_data->oldfh.data.data_val = data->fh.data.data_val;
+       link_data->oldfh = data->fh;
        data->fh.data.data_val = NULL;
 
        if (nfs_lookuppath_async(nfs, link_data->newpath, data->cb, data->private_data, nfs_link_continue_2_internal, link_data, free_nfs_link_data, 0) != 0) {
@@ -3450,11 +3901,7 @@ uint64_t nfs_get_readmax(struct nfs_context *nfs)
  */
 uint64_t nfs_get_writemax(struct nfs_context *nfs)
 {
-       /* Some ZDR libraries can not marshall PDUs bigger than this */
-        if (nfs->writemax < 32768) {
-               return nfs->writemax;
-       }
-       return 32768;
+       return nfs->writemax;
 }
 
 void nfs_set_error(struct nfs_context *nfs, char *error_string, ...)
@@ -3534,7 +3981,7 @@ static void mount_export_4_cb(struct rpc_context *rpc, int status, void *command
                return;
        }
 
-       if (rpc_mount_export_async(rpc, mount_export_5_cb, data) != 0) {
+       if (rpc_mount3_export_async(rpc, mount_export_5_cb, data) != 0) {
                data->cb(rpc, -ENOMEM, command_data, data->private_data);
                free_mount_cb_data(data);
                return;
index eca054c658ecd20b7c52b3b41792e04991ab1218..c2538efa8e127cf7240545c1a4e42560a112d6ff 100644 (file)
--- a/lib/pdu.c
+++ b/lib/pdu.c
@@ -113,6 +113,10 @@ void rpc_free_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu)
        free(pdu);
 }
 
+void rpc_set_next_xid(struct rpc_context *rpc, uint32_t xid)
+{
+       rpc->xid = xid;
+}
 
 int rpc_queue_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu)
 {
@@ -230,7 +234,7 @@ int rpc_process_pdu(struct rpc_context *rpc, char *buf, int size)
        struct rpc_pdu *pdu;
        ZDR zdr;
        int pos, recordmarker = 0;
-       unsigned int xid;
+       uint32_t xid;
        char *reasbuf = NULL;
 
        assert(rpc->magic == RPC_CONTEXT_MAGIC);
index 8dc3ed2d6b0d5a9fc1a5d731f2cd96bd3ad0d48c..1676084f21dfad95b764c74cef4997af46cc303d 100644 (file)
 #include <sys/socket.h>
 #endif
 
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+
 #ifdef HAVE_NETDB_H
 #include <netdb.h>
 #endif
@@ -92,6 +96,26 @@ static void set_nonblocking(int fd)
 #endif //FIXME
 }
 
+#ifdef HAVE_NETINET_TCP_H
+int set_tcp_sockopt(int sockfd, int optname, int value)
+{
+       int level;
+
+       #if defined(__FreeBSD__) || defined(__sun) || (defined(__APPLE__) && defined(__MACH__))
+       struct protoent *buf;
+
+       if ((buf = getprotobyname("tcp")) != NULL)
+               level = buf->p_proto;
+       else
+               return -1;
+       #else
+               level = SOL_TCP;
+       #endif
+
+       return setsockopt(sockfd, level, optname, (char *)&value, sizeof(value));
+}
+#endif
+
 int rpc_get_fd(struct rpc_context *rpc)
 {
        assert(rpc->magic == RPC_CONTEXT_MAGIC);
@@ -163,8 +187,6 @@ static int rpc_read_from_socket(struct rpc_context *rpc)
 
        assert(rpc->magic == RPC_CONTEXT_MAGIC);
 
-       assert(rpc->magic == RPC_CONTEXT_MAGIC);
-
        if (ioctl(rpc->fd, FIONREAD, &available) != 0) {
                rpc_set_error(rpc, "Ioctl FIONREAD returned error : %d. Closing socket.", errno);
                return -1;
@@ -258,14 +280,17 @@ static int rpc_read_from_socket(struct rpc_context *rpc)
        rpc->inpos += count;
 
        if (rpc->inpos == rpc->insize) {
-               if (rpc_process_pdu(rpc, rpc->inbuf, pdu_size) != 0) {
-                       rpc_set_error(rpc, "Invalid/garbage pdu received from server. Closing socket");
-                       return -1;
-               }
-               free(rpc->inbuf);
+               char *buf = rpc->inbuf;
+
                rpc->inbuf  = NULL;
                rpc->insize = 0;
                rpc->inpos  = 0;
+
+               if (rpc_process_pdu(rpc, buf, pdu_size) != 0) {
+                       rpc_set_error(rpc, "Invalid/garbage pdu received from server. Closing socket");
+                       return -1;
+               }
+               free(buf);
        }
 
        return 0;
@@ -367,6 +392,13 @@ void rpc_unset_autoreconnect(struct rpc_context *rpc)
        rpc->auto_reconnect = 0;
 }
 
+void rpc_set_tcp_syncnt(struct rpc_context *rpc, int v)
+{
+       assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
+       rpc->tcp_syncnt = v;
+}
+
 static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_storage *s)
 {
        int socksize;
@@ -377,6 +409,11 @@ static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_s
        case AF_INET:
                socksize = sizeof(struct sockaddr_in);
                rpc->fd = socket(AF_INET, 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:
                rpc_set_error(rpc, "Can not handle AF_FAMILY:%d", s->ss_family);
index e7e3a913bb94dab36af1a67c71321691b42c3931..fdc012c85aa4468eb59c9fa59585065c3cedad48 100644 (file)
@@ -12,4 +12,3 @@ Requires:
 Conflicts:
 Libs: -L${libdir} -lnfs
 Cflags: -I${includedir}
-Requires.private: @LIBNFS_PC_REQ_PRIVATE@
index 1f520cd6794fa3f28a5f725eabcf09bc91579402..b3f87ff4115a4d95b9e17a29142681184fb3d316 100644 (file)
@@ -27,7 +27,7 @@
 #include "libnfs-private.h"
 #include "libnfs-raw-mount.h"
 
-int rpc_mount_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+int rpc_mount3_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
 {
        struct rpc_pdu *pdu;
 
@@ -46,7 +46,12 @@ int rpc_mount_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
        return 0;
 }
 
-int rpc_mount_mnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data)
+int rpc_mount_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+{
+       return rpc_mount3_null_async(rpc, cb, private_data);
+}
+
+int rpc_mount3_mnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data)
 {
        struct rpc_pdu *pdu;
 
@@ -71,7 +76,12 @@ int rpc_mount_mnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *
        return 0;
 }
 
-int rpc_mount_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+int rpc_mount_mnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data)
+{
+       return rpc_mount3_mnt_async(rpc, cb, export, private_data);
+}
+
+int rpc_mount3_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
 {
        struct rpc_pdu *pdu;
 
@@ -90,7 +100,12 @@ int rpc_mount_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
        return 0;
 }
 
-int rpc_mount_umnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data)
+int rpc_mount_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+{
+       return rpc_mount3_dump_async(rpc, cb, private_data);
+}
+
+int rpc_mount3_umnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data)
 {
        struct rpc_pdu *pdu;
 
@@ -115,7 +130,12 @@ int rpc_mount_umnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void
        return 0;
 }
 
-int rpc_mount_umntall_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+int rpc_mount_umnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data)
+{
+       return rpc_mount3_umnt_async(rpc, cb, export, private_data);
+}
+
+int rpc_mount3_umntall_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
 {
        struct rpc_pdu *pdu;
 
@@ -134,7 +154,12 @@ int rpc_mount_umntall_async(struct rpc_context *rpc, rpc_cb cb, void *private_da
        return 0;
 }
 
-int rpc_mount_export_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+int rpc_mount_umntall_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+{
+       return rpc_mount3_umntall_async(rpc, cb, private_data);
+}
+
+int rpc_mount3_export_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
 {
        struct rpc_pdu *pdu;
 
@@ -153,6 +178,11 @@ int rpc_mount_export_async(struct rpc_context *rpc, rpc_cb cb, void *private_dat
        return 0;
 }
 
+int rpc_mount_export_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+{
+       return rpc_mount3_export_async(rpc, cb, private_data);
+}
+
 char *mountstat3_to_str(int st)
 {
        enum mountstat3 stat = st;
@@ -193,5 +223,129 @@ int mountstat3_to_errno(int st)
        return -ERANGE;
 }
 
+int rpc_mount1_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V1, MOUNT1_NULL, cb, private_data, (zdrproc_t)zdr_void, 0);
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for MOUNT1/NULL call");
+               return -1;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for MOUNT1/NULL call");
+               rpc_free_pdu(rpc, pdu);
+               return -1;
+       }
+
+       return 0;
+}
+
+int rpc_mount1_mnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V1, MOUNT1_MNT, cb, private_data, (zdrproc_t)zdr_mountres1, sizeof(mountres1));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for MOUNT1/MNT call");
+               return -1;
+       }
+
+       if (zdr_dirpath(&pdu->zdr, &export) == 0) {
+               rpc_set_error(rpc, "ZDR error. Failed to encode MOUNT1/MNT call");
+               rpc_free_pdu(rpc, pdu);
+               return -1;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for MOUNT1/MNT call");
+               rpc_free_pdu(rpc, pdu);
+               return -1;
+       }
+
+       return 0;
+}
+
+int rpc_mount1_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V1, MOUNT1_DUMP, cb, private_data, (zdrproc_t)zdr_mountlist, sizeof(mountlist));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Failed to allocate pdu for MOUNT1/DUMP");
+               return -1;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Failed to queue MOUNT1/DUMP pdu");
+               rpc_free_pdu(rpc, pdu);
+               return -1;
+       }
+
+       return 0;
+}
+
+int rpc_mount1_umnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V1, MOUNT1_UMNT, cb, private_data, (zdrproc_t)zdr_void, 0);
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Failed to allocate pdu for MOUNT1/UMNT");
+               return -1;
+       }
+
+       if (zdr_dirpath(&pdu->zdr, &export) == 0) {
+               rpc_set_error(rpc, "failed to encode dirpath for MOUNT1/UMNT");
+               rpc_free_pdu(rpc, pdu);
+               return -1;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Failed to queue MOUNT1/UMNT pdu");
+               rpc_free_pdu(rpc, pdu);
+               return -1;
+       }
+
+       return 0;
+}
+
+int rpc_mount1_umntall_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V1, MOUNT1_UMNTALL, cb, private_data, (zdrproc_t)zdr_void, 0);
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Failed to allocate pdu for MOUNT1/UMNTALL");
+               return -1;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Failed to queue MOUNT1/UMNTALL pdu");
+               rpc_free_pdu(rpc, pdu);
+               return -1;
+       }
+
+       return 0;
+}
+
+int rpc_mount1_export_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V1, MOUNT1_EXPORT, cb, private_data, (zdrproc_t)zdr_exports, sizeof(exports));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Failed to allocate pdu for MOUNT1/EXPORT");
+               return -1;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Failed to queue MOUNT1/EXPORT pdu");
+               rpc_free_pdu(rpc, pdu);
+               return -1;
+       }
 
+       return 0;
+}
 
index d6f75a0af36eae54cf3856666aadf5dfd6106b8a..82e60c58baf53daf1d17b0169eda336da47cd612 100644 (file)
@@ -18,5 +18,5 @@ nfs-stamp : nfs.x
        touch nfs-stamp
 
 compile_rpc:   
-       rpcgen -h nfs.x | sed -e "s/#include <rpc\/rpc.h>//" | sed -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" > 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
        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
index ce319ec7601e5826f3dfa5f3829f5762b7171068..04e914d74e3b24411cdaa92c6ecc43ef2817636e 100644 (file)
@@ -2094,6 +2094,960 @@ zdr_SETATTR3res (ZDR *zdrs, SETATTR3res *objp)
        return TRUE;
 }
 
+bool_t
+zdr_fhandle2 (ZDR *zdrs, fhandle2 objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_opaque (zdrs, objp, FHSIZE2))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_ftype2 (ZDR *zdrs, ftype2 *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_enum (zdrs, (enum_t *) objp))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_fattr2 (ZDR *zdrs, fattr2 *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+
+       if (zdrs->x_op == ZDR_ENCODE) {
+                if (!zdr_ftype2 (zdrs, &objp->type))
+                        return FALSE;
+               buf = ZDR_INLINE (zdrs, 10 * BYTES_PER_ZDR_UNIT);
+               if (buf == NULL) {
+                        if (!zdr_u_int (zdrs, &objp->mode))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->nlink))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->uid))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->gid))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->size))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->blocksize))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->rdev))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->blocks))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->fsid))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->fileid))
+                                return FALSE;
+
+               } else {
+               IZDR_PUT_U_LONG(buf, objp->mode);
+               IZDR_PUT_U_LONG(buf, objp->nlink);
+               IZDR_PUT_U_LONG(buf, objp->uid);
+               IZDR_PUT_U_LONG(buf, objp->gid);
+               IZDR_PUT_U_LONG(buf, objp->size);
+               IZDR_PUT_U_LONG(buf, objp->blocksize);
+               IZDR_PUT_U_LONG(buf, objp->rdev);
+               IZDR_PUT_U_LONG(buf, objp->blocks);
+               IZDR_PUT_U_LONG(buf, objp->fsid);
+               IZDR_PUT_U_LONG(buf, objp->fileid);
+               }
+                if (!zdr_nfstime3 (zdrs, &objp->atime))
+                        return FALSE;
+                if (!zdr_nfstime3 (zdrs, &objp->mtime))
+                        return FALSE;
+                if (!zdr_nfstime3 (zdrs, &objp->ctime))
+                        return FALSE;
+               return TRUE;
+       } else if (zdrs->x_op == ZDR_DECODE) {
+                if (!zdr_ftype2 (zdrs, &objp->type))
+                        return FALSE;
+               buf = ZDR_INLINE (zdrs, 10 * BYTES_PER_ZDR_UNIT);
+               if (buf == NULL) {
+                        if (!zdr_u_int (zdrs, &objp->mode))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->nlink))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->uid))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->gid))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->size))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->blocksize))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->rdev))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->blocks))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->fsid))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->fileid))
+                                return FALSE;
+
+               } else {
+               objp->mode = IZDR_GET_U_LONG(buf);
+               objp->nlink = IZDR_GET_U_LONG(buf);
+               objp->uid = IZDR_GET_U_LONG(buf);
+               objp->gid = IZDR_GET_U_LONG(buf);
+               objp->size = IZDR_GET_U_LONG(buf);
+               objp->blocksize = IZDR_GET_U_LONG(buf);
+               objp->rdev = IZDR_GET_U_LONG(buf);
+               objp->blocks = IZDR_GET_U_LONG(buf);
+               objp->fsid = IZDR_GET_U_LONG(buf);
+               objp->fileid = IZDR_GET_U_LONG(buf);
+               }
+                if (!zdr_nfstime3 (zdrs, &objp->atime))
+                        return FALSE;
+                if (!zdr_nfstime3 (zdrs, &objp->mtime))
+                        return FALSE;
+                if (!zdr_nfstime3 (zdrs, &objp->ctime))
+                        return FALSE;
+        return TRUE;
+       }
+
+        if (!zdr_ftype2 (zdrs, &objp->type))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->mode))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->nlink))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->uid))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->gid))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->size))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->blocksize))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->rdev))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->blocks))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->fsid))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->fileid))
+                return FALSE;
+        if (!zdr_nfstime3 (zdrs, &objp->atime))
+                return FALSE;
+        if (!zdr_nfstime3 (zdrs, &objp->mtime))
+                return FALSE;
+        if (!zdr_nfstime3 (zdrs, &objp->ctime))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_sattr2 (ZDR *zdrs, sattr2 *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+
+       if (zdrs->x_op == ZDR_ENCODE) {
+               buf = ZDR_INLINE (zdrs, 4 * BYTES_PER_ZDR_UNIT);
+               if (buf == NULL) {
+                        if (!zdr_u_int (zdrs, &objp->mode))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->uid))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->gid))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->size))
+                                return FALSE;
+
+               } else {
+               IZDR_PUT_U_LONG(buf, objp->mode);
+               IZDR_PUT_U_LONG(buf, objp->uid);
+               IZDR_PUT_U_LONG(buf, objp->gid);
+               IZDR_PUT_U_LONG(buf, objp->size);
+               }
+                if (!zdr_nfstime3 (zdrs, &objp->atime))
+                        return FALSE;
+                if (!zdr_nfstime3 (zdrs, &objp->mtime))
+                        return FALSE;
+               return TRUE;
+       } else if (zdrs->x_op == ZDR_DECODE) {
+               buf = ZDR_INLINE (zdrs, 4 * BYTES_PER_ZDR_UNIT);
+               if (buf == NULL) {
+                        if (!zdr_u_int (zdrs, &objp->mode))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->uid))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->gid))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->size))
+                                return FALSE;
+
+               } else {
+               objp->mode = IZDR_GET_U_LONG(buf);
+               objp->uid = IZDR_GET_U_LONG(buf);
+               objp->gid = IZDR_GET_U_LONG(buf);
+               objp->size = IZDR_GET_U_LONG(buf);
+               }
+                if (!zdr_nfstime3 (zdrs, &objp->atime))
+                        return FALSE;
+                if (!zdr_nfstime3 (zdrs, &objp->mtime))
+                        return FALSE;
+        return TRUE;
+       }
+
+        if (!zdr_u_int (zdrs, &objp->mode))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->uid))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->gid))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->size))
+                return FALSE;
+        if (!zdr_nfstime3 (zdrs, &objp->atime))
+                return FALSE;
+        if (!zdr_nfstime3 (zdrs, &objp->mtime))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_filename2 (ZDR *zdrs, filename2 *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_string (zdrs, objp, MAXNAMLEN2))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_path2 (ZDR *zdrs, path2 *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_string (zdrs, objp, MAXPATHLEN2))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_nfsdata2 (ZDR *zdrs, nfsdata2 *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_bytes (zdrs, (char **)&objp->nfsdata2_val, (u_int *) &objp->nfsdata2_len, NFSMAXDATA2))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_nfscookie2 (ZDR *zdrs, nfscookie2 objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_opaque (zdrs, objp, NFSCOOKIESIZE2))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_entry2 (ZDR *zdrs, entry2 *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_u_int (zdrs, &objp->fileid))
+                return FALSE;
+        if (!zdr_filename2 (zdrs, &objp->name))
+                return FALSE;
+        if (!zdr_nfscookie2 (zdrs, objp->cookie))
+                return FALSE;
+        if (!zdr_pointer (zdrs, (char **)&objp->nextentry, sizeof (entry2), (zdrproc_t) zdr_entry2))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_diropargs2 (ZDR *zdrs, diropargs2 *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_fhandle2 (zdrs, objp->dir))
+                return FALSE;
+        if (!zdr_filename2 (zdrs, &objp->name))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_GETATTR2args (ZDR *zdrs, GETATTR2args *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_fhandle2 (zdrs, objp->fhandle))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_GETATTR2resok (ZDR *zdrs, GETATTR2resok *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_fattr2 (zdrs, &objp->attributes))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_GETATTR2res (ZDR *zdrs, GETATTR2res *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nfsstat3 (zdrs, &objp->status))
+                return FALSE;
+       switch (objp->status) {
+       case NFS3_OK:
+                if (!zdr_GETATTR2resok (zdrs, &objp->GETATTR2res_u.resok))
+                        return FALSE;
+               break;
+       default:
+               break;
+       }
+       return TRUE;
+}
+
+bool_t
+zdr_SETATTR2args (ZDR *zdrs, SETATTR2args *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_fhandle2 (zdrs, objp->fhandle))
+                return FALSE;
+        if (!zdr_sattr2 (zdrs, &objp->attributes))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_SETATTR2resok (ZDR *zdrs, SETATTR2resok *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_fattr2 (zdrs, &objp->attributes))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_SETATTR2res (ZDR *zdrs, SETATTR2res *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nfsstat3 (zdrs, &objp->status))
+                return FALSE;
+       switch (objp->status) {
+       case NFS3_OK:
+                if (!zdr_SETATTR2resok (zdrs, &objp->SETATTR2res_u.resok))
+                        return FALSE;
+               break;
+       default:
+               break;
+       }
+       return TRUE;
+}
+
+bool_t
+zdr_LOOKUP2args (ZDR *zdrs, LOOKUP2args *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_diropargs2 (zdrs, &objp->what))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_LOOKUP2resok (ZDR *zdrs, LOOKUP2resok *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_fhandle2 (zdrs, objp->file))
+                return FALSE;
+        if (!zdr_fattr2 (zdrs, &objp->attributes))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_LOOKUP2res (ZDR *zdrs, LOOKUP2res *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nfsstat3 (zdrs, &objp->status))
+                return FALSE;
+       switch (objp->status) {
+       case NFS3_OK:
+                if (!zdr_LOOKUP2resok (zdrs, &objp->LOOKUP2res_u.resok))
+                        return FALSE;
+               break;
+       default:
+               break;
+       }
+       return TRUE;
+}
+
+bool_t
+zdr_READLINK2args (ZDR *zdrs, READLINK2args *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_fhandle2 (zdrs, objp->file))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_READLINK2resok (ZDR *zdrs, READLINK2resok *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_path2 (zdrs, &objp->data))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_READLINK2res (ZDR *zdrs, READLINK2res *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nfsstat3 (zdrs, &objp->status))
+                return FALSE;
+       switch (objp->status) {
+       case NFS3_OK:
+                if (!zdr_READLINK2resok (zdrs, &objp->READLINK2res_u.resok))
+                        return FALSE;
+               break;
+       default:
+               break;
+       }
+       return TRUE;
+}
+
+bool_t
+zdr_READ2args (ZDR *zdrs, READ2args *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_fhandle2 (zdrs, objp->file))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->offset))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->count))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->totalcount))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_READ2resok (ZDR *zdrs, READ2resok *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_fattr2 (zdrs, &objp->attributes))
+                return FALSE;
+        if (!zdr_nfsdata2 (zdrs, &objp->data))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_READ2res (ZDR *zdrs, READ2res *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nfsstat3 (zdrs, &objp->status))
+                return FALSE;
+       switch (objp->status) {
+       case NFS3_OK:
+                if (!zdr_READ2resok (zdrs, &objp->READ2res_u.resok))
+                        return FALSE;
+               break;
+       default:
+               break;
+       }
+       return TRUE;
+}
+
+bool_t
+zdr_WRITE2args (ZDR *zdrs, WRITE2args *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+
+       if (zdrs->x_op == ZDR_ENCODE) {
+                if (!zdr_fhandle2 (zdrs, objp->file))
+                        return FALSE;
+               buf = ZDR_INLINE (zdrs, 3 * BYTES_PER_ZDR_UNIT);
+               if (buf == NULL) {
+                        if (!zdr_u_int (zdrs, &objp->beginoffset))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->offset))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->totalcount))
+                                return FALSE;
+
+               } else {
+               IZDR_PUT_U_LONG(buf, objp->beginoffset);
+               IZDR_PUT_U_LONG(buf, objp->offset);
+               IZDR_PUT_U_LONG(buf, objp->totalcount);
+               }
+                if (!zdr_nfsdata2 (zdrs, &objp->data))
+                        return FALSE;
+               return TRUE;
+       } else if (zdrs->x_op == ZDR_DECODE) {
+                if (!zdr_fhandle2 (zdrs, objp->file))
+                        return FALSE;
+               buf = ZDR_INLINE (zdrs, 3 * BYTES_PER_ZDR_UNIT);
+               if (buf == NULL) {
+                        if (!zdr_u_int (zdrs, &objp->beginoffset))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->offset))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->totalcount))
+                                return FALSE;
+
+               } else {
+               objp->beginoffset = IZDR_GET_U_LONG(buf);
+               objp->offset = IZDR_GET_U_LONG(buf);
+               objp->totalcount = IZDR_GET_U_LONG(buf);
+               }
+                if (!zdr_nfsdata2 (zdrs, &objp->data))
+                        return FALSE;
+        return TRUE;
+       }
+
+        if (!zdr_fhandle2 (zdrs, objp->file))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->beginoffset))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->offset))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->totalcount))
+                return FALSE;
+        if (!zdr_nfsdata2 (zdrs, &objp->data))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_WRITE2resok (ZDR *zdrs, WRITE2resok *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_fattr2 (zdrs, &objp->attributes))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_WRITE2res (ZDR *zdrs, WRITE2res *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nfsstat3 (zdrs, &objp->status))
+                return FALSE;
+       switch (objp->status) {
+       case NFS3_OK:
+                if (!zdr_WRITE2resok (zdrs, &objp->WRITE2res_u.resok))
+                        return FALSE;
+               break;
+       default:
+               break;
+       }
+       return TRUE;
+}
+
+bool_t
+zdr_CREATE2args (ZDR *zdrs, CREATE2args *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_diropargs2 (zdrs, &objp->where))
+                return FALSE;
+        if (!zdr_sattr2 (zdrs, &objp->attributes))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_CREATE2resok (ZDR *zdrs, CREATE2resok *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_fhandle2 (zdrs, objp->file))
+                return FALSE;
+        if (!zdr_fattr2 (zdrs, &objp->attributes))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_CREATE2res (ZDR *zdrs, CREATE2res *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nfsstat3 (zdrs, &objp->status))
+                return FALSE;
+       switch (objp->status) {
+       case NFS3_OK:
+                if (!zdr_CREATE2resok (zdrs, &objp->CREATE2res_u.resok))
+                        return FALSE;
+               break;
+       default:
+               break;
+       }
+       return TRUE;
+}
+
+bool_t
+zdr_REMOVE2args (ZDR *zdrs, REMOVE2args *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_diropargs2 (zdrs, &objp->what))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_REMOVE2res (ZDR *zdrs, REMOVE2res *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nfsstat3 (zdrs, &objp->status))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_RENAME2args (ZDR *zdrs, RENAME2args *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_diropargs2 (zdrs, &objp->from))
+                return FALSE;
+        if (!zdr_diropargs2 (zdrs, &objp->to))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_RENAME2res (ZDR *zdrs, RENAME2res *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nfsstat3 (zdrs, &objp->status))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_LINK2args (ZDR *zdrs, LINK2args *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_fhandle2 (zdrs, objp->from))
+                return FALSE;
+        if (!zdr_diropargs2 (zdrs, &objp->to))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_LINK2res (ZDR *zdrs, LINK2res *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nfsstat3 (zdrs, &objp->status))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_SYMLINK2args (ZDR *zdrs, SYMLINK2args *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_diropargs2 (zdrs, &objp->from))
+                return FALSE;
+        if (!zdr_path2 (zdrs, &objp->to))
+                return FALSE;
+        if (!zdr_sattr2 (zdrs, &objp->attributes))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_SYMLINK2res (ZDR *zdrs, SYMLINK2res *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nfsstat3 (zdrs, &objp->status))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_MKDIR2args (ZDR *zdrs, MKDIR2args *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_diropargs2 (zdrs, &objp->where))
+                return FALSE;
+        if (!zdr_sattr2 (zdrs, &objp->attributes))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_MKDIR2resok (ZDR *zdrs, MKDIR2resok *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_fhandle2 (zdrs, objp->file))
+                return FALSE;
+        if (!zdr_fattr2 (zdrs, &objp->attributes))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_MKDIR2res (ZDR *zdrs, MKDIR2res *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nfsstat3 (zdrs, &objp->status))
+                return FALSE;
+       switch (objp->status) {
+       case NFS3_OK:
+                if (!zdr_MKDIR2resok (zdrs, &objp->MKDIR2res_u.resok))
+                        return FALSE;
+               break;
+       default:
+               break;
+       }
+       return TRUE;
+}
+
+bool_t
+zdr_RMDIR2args (ZDR *zdrs, RMDIR2args *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_diropargs2 (zdrs, &objp->what))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_RMDIR2res (ZDR *zdrs, RMDIR2res *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nfsstat3 (zdrs, &objp->status))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_READDIR2args (ZDR *zdrs, READDIR2args *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_fhandle2 (zdrs, objp->dir))
+                return FALSE;
+        if (!zdr_nfscookie2 (zdrs, objp->cookie))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->count))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_READDIR2resok (ZDR *zdrs, READDIR2resok *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_pointer (zdrs, (char **)&objp->entries, sizeof (entry2), (zdrproc_t) zdr_entry2))
+                return FALSE;
+        if (!zdr_bool (zdrs, &objp->eof))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_READDIR2res (ZDR *zdrs, READDIR2res *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nfsstat3 (zdrs, &objp->status))
+                return FALSE;
+       switch (objp->status) {
+       case NFS3_OK:
+                if (!zdr_READDIR2resok (zdrs, &objp->READDIR2res_u.resok))
+                        return FALSE;
+               break;
+       default:
+               break;
+       }
+       return TRUE;
+}
+
+bool_t
+zdr_STATFS2args (ZDR *zdrs, STATFS2args *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_fhandle2 (zdrs, objp->dir))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_STATFS2resok (ZDR *zdrs, STATFS2resok *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+
+       if (zdrs->x_op == ZDR_ENCODE) {
+               buf = ZDR_INLINE (zdrs, 5 * BYTES_PER_ZDR_UNIT);
+               if (buf == NULL) {
+                        if (!zdr_u_int (zdrs, &objp->tsize))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->bsize))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->blocks))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->bfree))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->bavail))
+                                return FALSE;
+               } else {
+                       IZDR_PUT_U_LONG(buf, objp->tsize);
+                       IZDR_PUT_U_LONG(buf, objp->bsize);
+                       IZDR_PUT_U_LONG(buf, objp->blocks);
+                       IZDR_PUT_U_LONG(buf, objp->bfree);
+                       IZDR_PUT_U_LONG(buf, objp->bavail);
+               }
+               return TRUE;
+       } else if (zdrs->x_op == ZDR_DECODE) {
+               buf = ZDR_INLINE (zdrs, 5 * BYTES_PER_ZDR_UNIT);
+               if (buf == NULL) {
+                        if (!zdr_u_int (zdrs, &objp->tsize))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->bsize))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->blocks))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->bfree))
+                                return FALSE;
+                        if (!zdr_u_int (zdrs, &objp->bavail))
+                                return FALSE;
+               } else {
+                       objp->tsize = IZDR_GET_U_LONG(buf);
+                       objp->bsize = IZDR_GET_U_LONG(buf);
+                       objp->blocks = IZDR_GET_U_LONG(buf);
+                       objp->bfree = IZDR_GET_U_LONG(buf);
+                       objp->bavail = IZDR_GET_U_LONG(buf);
+               }
+        return TRUE;
+       }
+
+        if (!zdr_u_int (zdrs, &objp->tsize))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->bsize))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->blocks))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->bfree))
+                return FALSE;
+        if (!zdr_u_int (zdrs, &objp->bavail))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_STATFS2res (ZDR *zdrs, STATFS2res *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nfsstat3 (zdrs, &objp->status))
+                return FALSE;
+       switch (objp->status) {
+       case NFS3_OK:
+                if (!zdr_STATFS2resok (zdrs, &objp->STATFS2res_u.resok))
+                        return FALSE;
+               break;
+       default:
+               break;
+       }
+       return TRUE;
+}
+
 bool_t
 zdr_nfsacl_type (ZDR *zdrs, nfsacl_type *objp)
 {
index dc47c05ef76f8b16178c18d42b38bc76af61ffa4..8eb3b2e21fea18701caace016262e6758fcf3867 100644 (file)
@@ -5,9 +5,11 @@
 
 #ifndef _NFS_H_RPCGEN
 #define _NFS_H_RPCGEN
-
 #include <nfsc/libnfs-zdr.h>
 
+
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -915,6 +917,331 @@ struct SETATTR3res {
        } SETATTR3res_u;
 };
 typedef struct SETATTR3res SETATTR3res;
+#define FHSIZE2 32
+
+typedef char fhandle2[FHSIZE2];
+
+enum ftype2 {
+       NF2NON = 0,
+       NF2REG = 1,
+       NF2DIR = 2,
+       NF2BLK = 3,
+       NF2CHR = 4,
+       NF2LNK = 5,
+};
+typedef enum ftype2 ftype2;
+
+struct fattr2 {
+       ftype2 type;
+       u_int mode;
+       u_int nlink;
+       u_int uid;
+       u_int gid;
+       u_int size;
+       u_int blocksize;
+       u_int rdev;
+       u_int blocks;
+       u_int fsid;
+       u_int fileid;
+       nfstime3 atime;
+       nfstime3 mtime;
+       nfstime3 ctime;
+};
+typedef struct fattr2 fattr2;
+
+struct sattr2 {
+       u_int mode;
+       u_int uid;
+       u_int gid;
+       u_int size;
+       nfstime3 atime;
+       nfstime3 mtime;
+};
+typedef struct sattr2 sattr2;
+#define MAXNAMLEN2 255
+
+typedef char *filename2;
+#define MAXPATHLEN2 1024
+
+typedef char *path2;
+#define NFSMAXDATA2 8192
+
+typedef struct {
+       u_int nfsdata2_len;
+       char *nfsdata2_val;
+} nfsdata2;
+#define NFSCOOKIESIZE2 4
+
+typedef char nfscookie2[NFSCOOKIESIZE2];
+
+struct entry2 {
+       u_int fileid;
+       filename2 name;
+       nfscookie2 cookie;
+       struct entry2 *nextentry;
+};
+typedef struct entry2 entry2;
+
+struct diropargs2 {
+       fhandle2 dir;
+       filename2 name;
+};
+typedef struct diropargs2 diropargs2;
+
+struct GETATTR2args {
+       fhandle2 fhandle;
+};
+typedef struct GETATTR2args GETATTR2args;
+
+struct GETATTR2resok {
+       fattr2 attributes;
+};
+typedef struct GETATTR2resok GETATTR2resok;
+
+struct GETATTR2res {
+       nfsstat3 status;
+       union {
+               GETATTR2resok resok;
+       } GETATTR2res_u;
+};
+typedef struct GETATTR2res GETATTR2res;
+
+struct SETATTR2args {
+       fhandle2 fhandle;
+       sattr2 attributes;
+};
+typedef struct SETATTR2args SETATTR2args;
+
+struct SETATTR2resok {
+       fattr2 attributes;
+};
+typedef struct SETATTR2resok SETATTR2resok;
+
+struct SETATTR2res {
+       nfsstat3 status;
+       union {
+               SETATTR2resok resok;
+       } SETATTR2res_u;
+};
+typedef struct SETATTR2res SETATTR2res;
+
+struct LOOKUP2args {
+       diropargs2 what;
+};
+typedef struct LOOKUP2args LOOKUP2args;
+
+struct LOOKUP2resok {
+       fhandle2 file;
+       fattr2 attributes;
+};
+typedef struct LOOKUP2resok LOOKUP2resok;
+
+struct LOOKUP2res {
+       nfsstat3 status;
+       union {
+               LOOKUP2resok resok;
+       } LOOKUP2res_u;
+};
+typedef struct LOOKUP2res LOOKUP2res;
+
+struct READLINK2args {
+       fhandle2 file;
+};
+typedef struct READLINK2args READLINK2args;
+
+struct READLINK2resok {
+       path2 data;
+};
+typedef struct READLINK2resok READLINK2resok;
+
+struct READLINK2res {
+       nfsstat3 status;
+       union {
+               READLINK2resok resok;
+       } READLINK2res_u;
+};
+typedef struct READLINK2res READLINK2res;
+
+struct READ2args {
+       fhandle2 file;
+       u_int offset;
+       u_int count;
+       u_int totalcount;
+};
+typedef struct READ2args READ2args;
+
+struct READ2resok {
+       fattr2 attributes;
+       nfsdata2 data;
+};
+typedef struct READ2resok READ2resok;
+
+struct READ2res {
+       nfsstat3 status;
+       union {
+               READ2resok resok;
+       } READ2res_u;
+};
+typedef struct READ2res READ2res;
+
+struct WRITE2args {
+       fhandle2 file;
+       u_int beginoffset;
+       u_int offset;
+       u_int totalcount;
+       nfsdata2 data;
+};
+typedef struct WRITE2args WRITE2args;
+
+struct WRITE2resok {
+       fattr2 attributes;
+};
+typedef struct WRITE2resok WRITE2resok;
+
+struct WRITE2res {
+       nfsstat3 status;
+       union {
+               WRITE2resok resok;
+       } WRITE2res_u;
+};
+typedef struct WRITE2res WRITE2res;
+
+struct CREATE2args {
+       diropargs2 where;
+       sattr2 attributes;
+};
+typedef struct CREATE2args CREATE2args;
+
+struct CREATE2resok {
+       fhandle2 file;
+       fattr2 attributes;
+};
+typedef struct CREATE2resok CREATE2resok;
+
+struct CREATE2res {
+       nfsstat3 status;
+       union {
+               CREATE2resok resok;
+       } CREATE2res_u;
+};
+typedef struct CREATE2res CREATE2res;
+
+struct REMOVE2args {
+       diropargs2 what;
+};
+typedef struct REMOVE2args REMOVE2args;
+
+struct REMOVE2res {
+       nfsstat3 status;
+};
+typedef struct REMOVE2res REMOVE2res;
+
+struct RENAME2args {
+       diropargs2 from;
+       diropargs2 to;
+};
+typedef struct RENAME2args RENAME2args;
+
+struct RENAME2res {
+       nfsstat3 status;
+};
+typedef struct RENAME2res RENAME2res;
+
+struct LINK2args {
+       fhandle2 from;
+       diropargs2 to;
+};
+typedef struct LINK2args LINK2args;
+
+struct LINK2res {
+       nfsstat3 status;
+};
+typedef struct LINK2res LINK2res;
+
+struct SYMLINK2args {
+       diropargs2 from;
+       path2 to;
+       sattr2 attributes;
+};
+typedef struct SYMLINK2args SYMLINK2args;
+
+struct SYMLINK2res {
+       nfsstat3 status;
+};
+typedef struct SYMLINK2res SYMLINK2res;
+
+struct MKDIR2args {
+       diropargs2 where;
+       sattr2 attributes;
+};
+typedef struct MKDIR2args MKDIR2args;
+
+struct MKDIR2resok {
+       fhandle2 file;
+       fattr2 attributes;
+};
+typedef struct MKDIR2resok MKDIR2resok;
+
+struct MKDIR2res {
+       nfsstat3 status;
+       union {
+               MKDIR2resok resok;
+       } MKDIR2res_u;
+};
+typedef struct MKDIR2res MKDIR2res;
+
+struct RMDIR2args {
+       diropargs2 what;
+};
+typedef struct RMDIR2args RMDIR2args;
+
+struct RMDIR2res {
+       nfsstat3 status;
+};
+typedef struct RMDIR2res RMDIR2res;
+
+struct READDIR2args {
+       fhandle2 dir;
+       nfscookie2 cookie;
+       u_int count;
+};
+typedef struct READDIR2args READDIR2args;
+
+struct READDIR2resok {
+       entry2 *entries;
+       bool_t eof;
+};
+typedef struct READDIR2resok READDIR2resok;
+
+struct READDIR2res {
+       nfsstat3 status;
+       union {
+               READDIR2resok resok;
+       } READDIR2res_u;
+};
+typedef struct READDIR2res READDIR2res;
+
+struct STATFS2args {
+       fhandle2 dir;
+};
+typedef struct STATFS2args STATFS2args;
+
+struct STATFS2resok {
+       u_int tsize;
+       u_int bsize;
+       u_int blocks;
+       u_int bfree;
+       u_int bavail;
+};
+typedef struct STATFS2resok STATFS2resok;
+
+struct STATFS2res {
+       nfsstat3 status;
+       union {
+               STATFS2resok resok;
+       } STATFS2res_u;
+};
+typedef struct STATFS2res STATFS2res;
 
 enum nfsacl_type {
        NFSACL_TYPE_USER_OBJ = 0x0001,
@@ -1007,6 +1334,110 @@ struct SETACL3res {
 typedef struct SETACL3res SETACL3res;
 
 #define NFS_PROGRAM 100003
+#define NFS_V2 2
+
+#if defined(__STDC__) || defined(__cplusplus)
+#define NFS2_NULL 0
+extern  void * nfs2_null_2(void *, CLIENT *);
+extern  void * nfs2_null_2_svc(void *, struct svc_req *);
+#define NFS2_GETATTR 1
+extern  GETATTR2res * nfs2_getattr_2(GETATTR2args *, CLIENT *);
+extern  GETATTR2res * nfs2_getattr_2_svc(GETATTR2args *, struct svc_req *);
+#define NFS2_SETATTR 2
+extern  SETATTR2res * nfs2_setattr_2(SETATTR2args *, CLIENT *);
+extern  SETATTR2res * nfs2_setattr_2_svc(SETATTR2args *, struct svc_req *);
+#define NFS2_LOOKUP 4
+extern  LOOKUP2res * nfs2_lookup_2(LOOKUP2args *, CLIENT *);
+extern  LOOKUP2res * nfs2_lookup_2_svc(LOOKUP2args *, struct svc_req *);
+#define NFS2_READLINK 5
+extern  READLINK2res * nfs2_readlink_2(READLINK2args *, CLIENT *);
+extern  READLINK2res * nfs2_readlink_2_svc(READLINK2args *, struct svc_req *);
+#define NFS2_READ 6
+extern  READ2res * nfs2_read_2(READ2args *, CLIENT *);
+extern  READ2res * nfs2_read_2_svc(READ2args *, struct svc_req *);
+#define NFS2_WRITE 8
+extern  WRITE2res * nfs2_write_2(WRITE2args *, CLIENT *);
+extern  WRITE2res * nfs2_write_2_svc(WRITE2args *, struct svc_req *);
+#define NFS2_CREATE 9
+extern  CREATE2res * nfs2_create_2(CREATE2args *, CLIENT *);
+extern  CREATE2res * nfs2_create_2_svc(CREATE2args *, struct svc_req *);
+#define NFS2_REMOVE 10
+extern  REMOVE2res * nfs2_remove_2(REMOVE2args *, CLIENT *);
+extern  REMOVE2res * nfs2_remove_2_svc(REMOVE2args *, struct svc_req *);
+#define NFS2_RENAME 11
+extern  RENAME2res * nfs2_rename_2(RENAME2args *, CLIENT *);
+extern  RENAME2res * nfs2_rename_2_svc(RENAME2args *, struct svc_req *);
+#define NFS2_LINK 12
+extern  LINK2res * nfs2_link_2(LINK2args *, CLIENT *);
+extern  LINK2res * nfs2_link_2_svc(LINK2args *, struct svc_req *);
+#define NFS2_SYMLINK 13
+extern  SYMLINK2res * nfs2_symlink_2(SYMLINK2args *, CLIENT *);
+extern  SYMLINK2res * nfs2_symlink_2_svc(SYMLINK2args *, struct svc_req *);
+#define NFS2_MKDIR 14
+extern  MKDIR2res * nfs2_mkdir_2(MKDIR2args *, CLIENT *);
+extern  MKDIR2res * nfs2_mkdir_2_svc(MKDIR2args *, struct svc_req *);
+#define NFS2_RMDIR 15
+extern  RMDIR2res * nfs2_rmdir_2(RMDIR2args *, CLIENT *);
+extern  RMDIR2res * nfs2_rmdir_2_svc(RMDIR2args *, struct svc_req *);
+#define NFS2_READDIR 16
+extern  READDIR2res * nfs2_readdir_2(READDIR2args *, CLIENT *);
+extern  READDIR2res * nfs2_readdir_2_svc(READDIR2args *, struct svc_req *);
+#define NFS2_STATFS 17
+extern  STATFS2res * nfs2_statfs_2(STATFS2args *, CLIENT *);
+extern  STATFS2res * nfs2_statfs_2_svc(STATFS2args *, struct svc_req *);
+extern int nfs_program_2_freeresult (SVCXPRT *, zdrproc_t, caddr_t);
+
+#else /* K&R C */
+#define NFS2_NULL 0
+extern  void * nfs2_null_2();
+extern  void * nfs2_null_2_svc();
+#define NFS2_GETATTR 1
+extern  GETATTR2res * nfs2_getattr_2();
+extern  GETATTR2res * nfs2_getattr_2_svc();
+#define NFS2_SETATTR 2
+extern  SETATTR2res * nfs2_setattr_2();
+extern  SETATTR2res * nfs2_setattr_2_svc();
+#define NFS2_LOOKUP 4
+extern  LOOKUP2res * nfs2_lookup_2();
+extern  LOOKUP2res * nfs2_lookup_2_svc();
+#define NFS2_READLINK 5
+extern  READLINK2res * nfs2_readlink_2();
+extern  READLINK2res * nfs2_readlink_2_svc();
+#define NFS2_READ 6
+extern  READ2res * nfs2_read_2();
+extern  READ2res * nfs2_read_2_svc();
+#define NFS2_WRITE 8
+extern  WRITE2res * nfs2_write_2();
+extern  WRITE2res * nfs2_write_2_svc();
+#define NFS2_CREATE 9
+extern  CREATE2res * nfs2_create_2();
+extern  CREATE2res * nfs2_create_2_svc();
+#define NFS2_REMOVE 10
+extern  REMOVE2res * nfs2_remove_2();
+extern  REMOVE2res * nfs2_remove_2_svc();
+#define NFS2_RENAME 11
+extern  RENAME2res * nfs2_rename_2();
+extern  RENAME2res * nfs2_rename_2_svc();
+#define NFS2_LINK 12
+extern  LINK2res * nfs2_link_2();
+extern  LINK2res * nfs2_link_2_svc();
+#define NFS2_SYMLINK 13
+extern  SYMLINK2res * nfs2_symlink_2();
+extern  SYMLINK2res * nfs2_symlink_2_svc();
+#define NFS2_MKDIR 14
+extern  MKDIR2res * nfs2_mkdir_2();
+extern  MKDIR2res * nfs2_mkdir_2_svc();
+#define NFS2_RMDIR 15
+extern  RMDIR2res * nfs2_rmdir_2();
+extern  RMDIR2res * nfs2_rmdir_2_svc();
+#define NFS2_READDIR 16
+extern  READDIR2res * nfs2_readdir_2();
+extern  READDIR2res * nfs2_readdir_2_svc();
+#define NFS2_STATFS 17
+extern  STATFS2res * nfs2_statfs_2();
+extern  STATFS2res * nfs2_statfs_2_svc();
+extern int nfs_program_2_freeresult ();
+#endif /* K&R C */
 #define NFS_V3 3
 
 #if defined(__STDC__) || defined(__cplusplus)
@@ -1307,6 +1738,56 @@ extern  bool_t zdr_SETATTR3args (ZDR *, SETATTR3args*);
 extern  bool_t zdr_SETATTR3resok (ZDR *, SETATTR3resok*);
 extern  bool_t zdr_SETATTR3resfail (ZDR *, SETATTR3resfail*);
 extern  bool_t zdr_SETATTR3res (ZDR *, SETATTR3res*);
+extern  bool_t zdr_fhandle2 (ZDR *, fhandle2);
+extern  bool_t zdr_ftype2 (ZDR *, ftype2*);
+extern  bool_t zdr_fattr2 (ZDR *, fattr2*);
+extern  bool_t zdr_sattr2 (ZDR *, sattr2*);
+extern  bool_t zdr_filename2 (ZDR *, filename2*);
+extern  bool_t zdr_path2 (ZDR *, path2*);
+extern  bool_t zdr_nfsdata2 (ZDR *, nfsdata2*);
+extern  bool_t zdr_nfscookie2 (ZDR *, nfscookie2);
+extern  bool_t zdr_entry2 (ZDR *, entry2*);
+extern  bool_t zdr_diropargs2 (ZDR *, diropargs2*);
+extern  bool_t zdr_GETATTR2args (ZDR *, GETATTR2args*);
+extern  bool_t zdr_GETATTR2resok (ZDR *, GETATTR2resok*);
+extern  bool_t zdr_GETATTR2res (ZDR *, GETATTR2res*);
+extern  bool_t zdr_SETATTR2args (ZDR *, SETATTR2args*);
+extern  bool_t zdr_SETATTR2resok (ZDR *, SETATTR2resok*);
+extern  bool_t zdr_SETATTR2res (ZDR *, SETATTR2res*);
+extern  bool_t zdr_LOOKUP2args (ZDR *, LOOKUP2args*);
+extern  bool_t zdr_LOOKUP2resok (ZDR *, LOOKUP2resok*);
+extern  bool_t zdr_LOOKUP2res (ZDR *, LOOKUP2res*);
+extern  bool_t zdr_READLINK2args (ZDR *, READLINK2args*);
+extern  bool_t zdr_READLINK2resok (ZDR *, READLINK2resok*);
+extern  bool_t zdr_READLINK2res (ZDR *, READLINK2res*);
+extern  bool_t zdr_READ2args (ZDR *, READ2args*);
+extern  bool_t zdr_READ2resok (ZDR *, READ2resok*);
+extern  bool_t zdr_READ2res (ZDR *, READ2res*);
+extern  bool_t zdr_WRITE2args (ZDR *, WRITE2args*);
+extern  bool_t zdr_WRITE2resok (ZDR *, WRITE2resok*);
+extern  bool_t zdr_WRITE2res (ZDR *, WRITE2res*);
+extern  bool_t zdr_CREATE2args (ZDR *, CREATE2args*);
+extern  bool_t zdr_CREATE2resok (ZDR *, CREATE2resok*);
+extern  bool_t zdr_CREATE2res (ZDR *, CREATE2res*);
+extern  bool_t zdr_REMOVE2args (ZDR *, REMOVE2args*);
+extern  bool_t zdr_REMOVE2res (ZDR *, REMOVE2res*);
+extern  bool_t zdr_RENAME2args (ZDR *, RENAME2args*);
+extern  bool_t zdr_RENAME2res (ZDR *, RENAME2res*);
+extern  bool_t zdr_LINK2args (ZDR *, LINK2args*);
+extern  bool_t zdr_LINK2res (ZDR *, LINK2res*);
+extern  bool_t zdr_SYMLINK2args (ZDR *, SYMLINK2args*);
+extern  bool_t zdr_SYMLINK2res (ZDR *, SYMLINK2res*);
+extern  bool_t zdr_MKDIR2args (ZDR *, MKDIR2args*);
+extern  bool_t zdr_MKDIR2resok (ZDR *, MKDIR2resok*);
+extern  bool_t zdr_MKDIR2res (ZDR *, MKDIR2res*);
+extern  bool_t zdr_RMDIR2args (ZDR *, RMDIR2args*);
+extern  bool_t zdr_RMDIR2res (ZDR *, RMDIR2res*);
+extern  bool_t zdr_READDIR2args (ZDR *, READDIR2args*);
+extern  bool_t zdr_READDIR2resok (ZDR *, READDIR2resok*);
+extern  bool_t zdr_READDIR2res (ZDR *, READDIR2res*);
+extern  bool_t zdr_STATFS2args (ZDR *, STATFS2args*);
+extern  bool_t zdr_STATFS2resok (ZDR *, STATFS2resok*);
+extern  bool_t zdr_STATFS2res (ZDR *, STATFS2res*);
 extern  bool_t zdr_nfsacl_type (ZDR *, nfsacl_type*);
 extern  bool_t zdr_nfsacl_ace (ZDR *, nfsacl_ace*);
 extern  bool_t zdr_GETACL3args (ZDR *, GETACL3args*);
@@ -1445,6 +1926,56 @@ extern bool_t zdr_SETATTR3args ();
 extern bool_t zdr_SETATTR3resok ();
 extern bool_t zdr_SETATTR3resfail ();
 extern bool_t zdr_SETATTR3res ();
+extern bool_t zdr_fhandle2 ();
+extern bool_t zdr_ftype2 ();
+extern bool_t zdr_fattr2 ();
+extern bool_t zdr_sattr2 ();
+extern bool_t zdr_filename2 ();
+extern bool_t zdr_path2 ();
+extern bool_t zdr_nfsdata2 ();
+extern bool_t zdr_nfscookie2 ();
+extern bool_t zdr_entry2 ();
+extern bool_t zdr_diropargs2 ();
+extern bool_t zdr_GETATTR2args ();
+extern bool_t zdr_GETATTR2resok ();
+extern bool_t zdr_GETATTR2res ();
+extern bool_t zdr_SETATTR2args ();
+extern bool_t zdr_SETATTR2resok ();
+extern bool_t zdr_SETATTR2res ();
+extern bool_t zdr_LOOKUP2args ();
+extern bool_t zdr_LOOKUP2resok ();
+extern bool_t zdr_LOOKUP2res ();
+extern bool_t zdr_READLINK2args ();
+extern bool_t zdr_READLINK2resok ();
+extern bool_t zdr_READLINK2res ();
+extern bool_t zdr_READ2args ();
+extern bool_t zdr_READ2resok ();
+extern bool_t zdr_READ2res ();
+extern bool_t zdr_WRITE2args ();
+extern bool_t zdr_WRITE2resok ();
+extern bool_t zdr_WRITE2res ();
+extern bool_t zdr_CREATE2args ();
+extern bool_t zdr_CREATE2resok ();
+extern bool_t zdr_CREATE2res ();
+extern bool_t zdr_REMOVE2args ();
+extern bool_t zdr_REMOVE2res ();
+extern bool_t zdr_RENAME2args ();
+extern bool_t zdr_RENAME2res ();
+extern bool_t zdr_LINK2args ();
+extern bool_t zdr_LINK2res ();
+extern bool_t zdr_SYMLINK2args ();
+extern bool_t zdr_SYMLINK2res ();
+extern bool_t zdr_MKDIR2args ();
+extern bool_t zdr_MKDIR2resok ();
+extern bool_t zdr_MKDIR2res ();
+extern bool_t zdr_RMDIR2args ();
+extern bool_t zdr_RMDIR2res ();
+extern bool_t zdr_READDIR2args ();
+extern bool_t zdr_READDIR2resok ();
+extern bool_t zdr_READDIR2res ();
+extern bool_t zdr_STATFS2args ();
+extern bool_t zdr_STATFS2resok ();
+extern bool_t zdr_STATFS2res ();
 extern bool_t zdr_nfsacl_type ();
 extern bool_t zdr_nfsacl_ace ();
 extern bool_t zdr_GETACL3args ();
index 44b7538aa11ed58e2952cfddee245e98272bcdbd..a97d40ab7d543e6d8a37ce97b7a5d5665a3dd852 100644 (file)
--- a/nfs/nfs.c
+++ b/nfs/nfs.c
@@ -103,18 +103,21 @@ int nfsstat3_to_errno(int error)
 }
 
 
-int rpc_nfs_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+/*
+ * NFSv3
+ */
+int rpc_nfs3_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
 {
        struct rpc_pdu *pdu;
 
        pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_NULL, cb, private_data, (zdrproc_t)zdr_void, 0);
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/null call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/NULL call");
                return -1;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/null call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/NULL call");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
@@ -122,28 +125,673 @@ int rpc_nfs_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
        return 0;
 }
 
-int rpc_nfs_getattr_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data)
+int rpc_nfs_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+{
+       return rpc_nfs3_null_async(rpc, cb, private_data);
+}
+
+int rpc_nfs3_getattr_async(struct rpc_context *rpc, rpc_cb cb, struct GETATTR3args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
-       GETATTR3args args;
 
        pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_GETATTR, cb, private_data, (zdrproc_t)zdr_GETATTR3res, sizeof(GETATTR3res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/null call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/GETATTR call");
+               return -1;
+       }
+
+       if (zdr_GETATTR3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode GETATTR3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/GETATTR call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_getattr_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data)
+{
+       GETATTR3args args;
+
+       memset(&args, 0, sizeof(GETATTR3args));
+       args.object.data.data_len = fh->data.data_len; 
+       args.object.data.data_val = fh->data.data_val; 
+
+       return rpc_nfs3_getattr_async(rpc, cb, &args, private_data);
+}
+
+int rpc_nfs3_pathconf_async(struct rpc_context *rpc, rpc_cb cb, struct PATHCONF3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_PATHCONF, cb, private_data, (zdrproc_t)zdr_PATHCONF3res, sizeof(PATHCONF3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/PATHCONF call");
+               return -1;
+       }
+
+       if (zdr_PATHCONF3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode PATHCONF3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/PATHCONF call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_pathconf_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data)
+{
+       PATHCONF3args args;
+
+       memset(&args, 0, sizeof(PATHCONF3args));
+       args.object.data.data_len = fh->data.data_len; 
+       args.object.data.data_val = fh->data.data_val; 
+
+       return rpc_nfs3_pathconf_async(rpc, cb, &args, private_data);
+}
+
+int rpc_nfs3_lookup_async(struct rpc_context *rpc, rpc_cb cb, struct LOOKUP3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_LOOKUP, cb, private_data, (zdrproc_t)zdr_LOOKUP3res, sizeof(LOOKUP3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/LOOKUP call");
+               return -1;
+       }
+
+       if (zdr_LOOKUP3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode LOOKUP3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/LOOKUP call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_lookup_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *name, void *private_data)
+{
+       LOOKUP3args args;
+
+       memset(&args, 0, sizeof(LOOKUP3args));
+       args.what.dir.data.data_len = fh->data.data_len; 
+       args.what.dir.data.data_val = fh->data.data_val; 
+       args.what.name              = name;
+
+       return rpc_nfs3_lookup_async(rpc, cb, &args, private_data);
+}
+
+int rpc_nfs3_access_async(struct rpc_context *rpc, rpc_cb cb, struct ACCESS3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_ACCESS, cb, private_data, (zdrproc_t)zdr_ACCESS3res, sizeof(ACCESS3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/ACCESS call");
+               return -1;
+       }
+
+       if (zdr_ACCESS3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode ACCESS3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/ACCESS call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_access_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, int access, void *private_data)
+{
+       ACCESS3args args;
+
+       memset(&args, 0, sizeof(ACCESS3args));
+       args.object.data.data_len = fh->data.data_len;
+       args.object.data.data_val = fh->data.data_val;
+       args.access = access;
+
+       return rpc_nfs3_access_async(rpc, cb, &args, private_data);
+}
+
+int rpc_nfs3_read_async(struct rpc_context *rpc, rpc_cb cb, struct READ3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_READ, cb, private_data, (zdrproc_t)zdr_READ3res, sizeof(READ3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/READ call");
+               return -1;
+       }
+
+       if (zdr_READ3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode READ3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/READ call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_read_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t offset, uint64_t count, void *private_data)
+{
+       READ3args args;
+
+       memset(&args, 0, sizeof(READ3args));
+       args.file.data.data_len = fh->data.data_len;
+       args.file.data.data_val = fh->data.data_val;
+       args.offset = offset;
+       args.count = count;
+
+       return rpc_nfs3_read_async(rpc, cb, &args, private_data);
+}
+
+int rpc_nfs3_write_async(struct rpc_context *rpc, rpc_cb cb, struct WRITE3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_WRITE, cb, private_data, (zdrproc_t)zdr_WRITE3res, sizeof(WRITE3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/WRITE call");
+               return -1;
+       }
+
+       if (zdr_WRITE3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode WRITE3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/WRITE call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_write_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *buf, uint64_t offset, uint64_t count, int stable_how, void *private_data)
+{
+       WRITE3args args;
+
+       memset(&args, 0, sizeof(WRITE3args));
+       args.file.data.data_len = fh->data.data_len;
+       args.file.data.data_val = fh->data.data_val;
+       args.offset = offset;
+       args.count  = count;
+       args.stable = stable_how;
+       args.data.data_len = count;
+       args.data.data_val = buf;
+
+       return rpc_nfs3_write_async(rpc, cb, &args, private_data);
+}
+
+int rpc_nfs3_commit_async(struct rpc_context *rpc, rpc_cb cb, struct COMMIT3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_COMMIT, cb, private_data, (zdrproc_t)zdr_COMMIT3res, sizeof(COMMIT3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/COMMIT call");
+               return -1;
+       }
+
+       if (zdr_COMMIT3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode COMMIT3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/COMMIT call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_commit_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data)
+{
+       COMMIT3args args;
+
+       memset(&args, 0, sizeof(COMMIT3args));
+       args.file.data.data_len = fh->data.data_len;
+       args.file.data.data_val = fh->data.data_val;
+       args.offset = 0;
+       args.count  = 0;
+
+       return rpc_nfs3_commit_async(rpc, cb, &args, private_data);
+}
+
+int rpc_nfs3_setattr_async(struct rpc_context *rpc, rpc_cb cb, SETATTR3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_SETATTR, cb, private_data, (zdrproc_t)zdr_SETATTR3res, sizeof(SETATTR3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/SETATTR call");
+               return -1;
+       }
+
+       if (zdr_SETATTR3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode SETATTR3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/SETATTR call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_setattr_async(struct rpc_context *rpc, rpc_cb cb, SETATTR3args *args, void *private_data)
+{
+       return rpc_nfs3_setattr_async(rpc, cb, args, private_data);
+}
+
+int rpc_nfs3_mkdir_async(struct rpc_context *rpc, rpc_cb cb, MKDIR3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_MKDIR, cb, private_data, (zdrproc_t)zdr_MKDIR3res, sizeof(MKDIR3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/MKDIR call");
+               return -1;
+       }
+
+       if (zdr_MKDIR3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode MKDIR3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/MKDIR call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_mkdir_async(struct rpc_context *rpc, rpc_cb cb, MKDIR3args *args, void *private_data)
+{
+       return rpc_nfs3_mkdir_async(rpc, cb, args, private_data);
+}
+
+int rpc_nfs3_rmdir_async(struct rpc_context *rpc, rpc_cb cb, struct RMDIR3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_RMDIR, cb, private_data, (zdrproc_t)zdr_RMDIR3res, sizeof(RMDIR3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/RMDIR call");
+               return -1;
+       }
+
+       if (zdr_RMDIR3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode RMDIR3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/RMDIR call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_rmdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *dir, void *private_data)
+{
+       RMDIR3args args;
+
+       memset(&args, 0, sizeof(RMDIR3args));
+       args.object.dir.data.data_len = fh->data.data_len;
+       args.object.dir.data.data_val = fh->data.data_val;
+       args.object.name = dir;
+
+       return rpc_nfs3_rmdir_async(rpc, cb, &args, private_data);
+}
+
+int rpc_nfs3_create_async(struct rpc_context *rpc, rpc_cb cb, CREATE3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_CREATE, cb, private_data, (zdrproc_t)zdr_CREATE3res, sizeof(CREATE3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/CREATE call");
+               return -1;
+       }
+
+       if (zdr_CREATE3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode CREATE3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/CREATE call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_create_async(struct rpc_context *rpc, rpc_cb cb, CREATE3args *args, void *private_data)
+{
+       return rpc_nfs3_create_async(rpc, cb, args, private_data);
+}
+
+int rpc_nfs3_mknod_async(struct rpc_context *rpc, rpc_cb cb, struct MKNOD3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_MKNOD, cb, private_data, (zdrproc_t)zdr_MKNOD3res, sizeof(MKNOD3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/MKNOD call");
+               return -1;
+       }
+
+       if (zdr_MKNOD3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode MKNOD3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/MKNOD call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_mknod_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *file, int mode, int major, int minor, void *private_data)
+{
+       MKNOD3args args;
+
+       memset(&args, 0, sizeof(MKNOD3args));
+       args.where.dir.data.data_len = fh->data.data_len;
+       args.where.dir.data.data_val = fh->data.data_val;
+       args.where.name = file;
+
+       switch (mode & S_IFMT) {
+       case S_IFCHR:
+               args.what.type = NF3CHR;
+               args.what.mknoddata3_u.chr_device.dev_attributes.mode.set_it = 1;
+               args.what.mknoddata3_u.chr_device.dev_attributes.mode.set_mode3_u.mode = mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
+               args.what.mknoddata3_u.chr_device.spec.specdata1 = major;
+               args.what.mknoddata3_u.chr_device.spec.specdata2 = minor;
+               break;
+       case S_IFBLK:
+               args.what.type = NF3BLK;
+               args.what.mknoddata3_u.blk_device.dev_attributes.mode.set_it = 1;
+               args.what.mknoddata3_u.blk_device.dev_attributes.mode.set_mode3_u.mode = mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
+               args.what.mknoddata3_u.blk_device.spec.specdata1 = major;
+               args.what.mknoddata3_u.blk_device.spec.specdata2 = minor;
+       case S_IFSOCK:
+               args.what.type = NF3SOCK;
+               args.what.mknoddata3_u.sock_attributes.mode.set_it = 1;
+               args.what.mknoddata3_u.sock_attributes.mode.set_mode3_u.mode = mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
+               break;
+       case S_IFIFO:
+               args.what.type = NF3FIFO;
+               args.what.mknoddata3_u.pipe_attributes.mode.set_it = 1;
+               args.what.mknoddata3_u.pipe_attributes.mode.set_mode3_u.mode = mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
+               break;
+       default:
+               rpc_set_error(rpc, "Invalid file type for NFS3/MKNOD call");
+               return -1;
+       }
+
+       return rpc_nfs3_mknod_async(rpc, cb, &args, private_data);
+}
+
+int rpc_nfs3_remove_async(struct rpc_context *rpc, rpc_cb cb, struct REMOVE3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_REMOVE, cb, private_data, (zdrproc_t)zdr_REMOVE3res, sizeof(REMOVE3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/REMOVE call");
+               return -1;
+       }
+
+       if (zdr_REMOVE3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode REMOVE3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/REMOVE call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_remove_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *file, void *private_data)
+{
+       REMOVE3args args;
+
+       memset(&args, 0, sizeof(REMOVE3args));
+       args.object.dir.data.data_len = fh->data.data_len;
+       args.object.dir.data.data_val = fh->data.data_val;
+       args.object.name = file;
+
+       return rpc_nfs3_remove_async(rpc, cb, &args, private_data);
+}
+
+int rpc_nfs3_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct READDIR3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_READDIR, cb, private_data, (zdrproc_t)zdr_READDIR3res, sizeof(READDIR3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/READDIR call");
+               return -1;
+       }
+
+       if (zdr_READDIR3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode READDIR3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/READDIR call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t cookie, char *cookieverf, int count, void *private_data)
+{
+       READDIR3args args;
+
+       memset(&args, 0, sizeof(READDIR3args));
+       args.dir.data.data_len = fh->data.data_len;
+       args.dir.data.data_val = fh->data.data_val;
+       args.cookie = cookie;
+       memcpy(&args.cookieverf, cookieverf, sizeof(cookieverf3)); 
+       args.count = count;
+
+       return rpc_nfs3_readdir_async(rpc, cb, &args, private_data);
+}
+
+int rpc_nfs3_readdirplus_async(struct rpc_context *rpc, rpc_cb cb, struct READDIRPLUS3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_READDIRPLUS, cb, private_data, (zdrproc_t)zdr_READDIRPLUS3res, sizeof(READDIRPLUS3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/READDIRPLUS call");
+               return -1;
+       }
+
+       if (zdr_READDIRPLUS3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode READDIRPLUS3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/READDIRPLUS call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_readdirplus_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t cookie, char *cookieverf, int count, void *private_data)
+{
+       READDIRPLUS3args args;
+
+       memset(&args, 0, sizeof(READDIRPLUS3args));
+       args.dir.data.data_len = fh->data.data_len;
+       args.dir.data.data_val = fh->data.data_val;
+       args.cookie = cookie;
+       memcpy(&args.cookieverf, cookieverf, sizeof(cookieverf3)); 
+       args.dircount = count;
+       args.maxcount = count;
+
+       return rpc_nfs3_readdirplus_async(rpc, cb, &args, private_data);
+}
+
+int rpc_nfs3_fsstat_async(struct rpc_context *rpc, rpc_cb cb, struct FSSTAT3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_FSSTAT, cb, private_data, (zdrproc_t)zdr_FSSTAT3res, sizeof(FSSTAT3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/FSSTAT call");
+               return -1;
+       }
+
+       if (zdr_FSSTAT3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode FSSTAT3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/FSSTAT call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_fsstat_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data)
+{
+       FSSTAT3args args;
+
+       memset(&args, 0, sizeof(FSSTAT3args));
+       args.fsroot.data.data_len = fh->data.data_len; 
+       args.fsroot.data.data_val = fh->data.data_val; 
+
+       return rpc_nfs3_fsstat_async(rpc, cb, &args, private_data);
+}
+
+int rpc_nfs3_fsinfo_async(struct rpc_context *rpc, rpc_cb cb, struct FSINFO3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_FSINFO, cb, private_data, (zdrproc_t)zdr_FSINFO3res, sizeof(FSINFO3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/FSINFO call");
+               return -1;
+       }
+
+       if (zdr_FSINFO3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode FSINFO3args");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/FSINFO call");
+               rpc_free_pdu(rpc, pdu);
+               return -3;
+       }
+
+       return 0;
+}
+
+int rpc_nfs_fsinfo_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data)
+{
+       FSINFO3args args;
+
+       memset(&args, 0, sizeof(FSINFO3args));
+       args.fsroot.data.data_len = fh->data.data_len; 
+       args.fsroot.data.data_val = fh->data.data_val; 
+
+       return rpc_nfs3_fsinfo_async(rpc, cb, &args, private_data);
+}
+
+int rpc_nfs3_readlink_async(struct rpc_context *rpc, rpc_cb cb, READLINK3args *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_READLINK, cb, private_data, (zdrproc_t)zdr_READLINK3res, sizeof(READLINK3res));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/READLINK call");
                return -1;
        }
 
-       args.object.data.data_len = fh->data.data_len; 
-       args.object.data.data_val = fh->data.data_val; 
-
-       if (zdr_GETATTR3args(&pdu->zdr, &args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode GETATTR3args");
+       if (zdr_READLINK3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode READLINK3args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/null call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/READLINK call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -151,29 +799,29 @@ int rpc_nfs_getattr_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh
        return 0;
 }
 
-int rpc_nfs_lookup_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *name, void *private_data)
+int rpc_nfs_readlink_async(struct rpc_context *rpc, rpc_cb cb, READLINK3args *args, void *private_data)
+{
+       return rpc_nfs3_readlink_async(rpc, cb, args, private_data);
+}
+
+int rpc_nfs3_symlink_async(struct rpc_context *rpc, rpc_cb cb, SYMLINK3args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
-       LOOKUP3args args;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_LOOKUP, cb, private_data, (zdrproc_t)zdr_LOOKUP3res, sizeof(LOOKUP3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_SYMLINK, cb, private_data, (zdrproc_t)zdr_SYMLINK3res, sizeof(SYMLINK3res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/lookup call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/SYMLINK call");
                return -1;
        }
 
-       args.what.dir.data.data_len = fh->data.data_len; 
-       args.what.dir.data.data_val = fh->data.data_val; 
-       args.what.name              = name;
-
-       if (zdr_LOOKUP3args(&pdu->zdr, &args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode LOOKUP3args");
+       if (zdr_SYMLINK3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode SYMLINK3args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/lookup call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/SYMLINK call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -181,30 +829,29 @@ int rpc_nfs_lookup_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
        return 0;
 }
 
+int rpc_nfs_symlink_async(struct rpc_context *rpc, rpc_cb cb, SYMLINK3args *args, void *private_data)
+{
+       return rpc_nfs3_symlink_async(rpc, cb, args, private_data);
+}
 
-int rpc_nfs_access_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, int access, void *private_data)
+int rpc_nfs3_rename_async(struct rpc_context *rpc, rpc_cb cb, struct RENAME3args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
-       ACCESS3args args;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_ACCESS, cb, private_data, (zdrproc_t)zdr_ACCESS3res, sizeof(ACCESS3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_RENAME, cb, private_data, (zdrproc_t)zdr_RENAME3res, sizeof(RENAME3res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/access call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/RENAME call");
                return -1;
        }
 
-       args.object.data.data_len = fh->data.data_len;
-       args.object.data.data_val = fh->data.data_val;
-       args.access = access;
-
-       if (zdr_ACCESS3args(&pdu->zdr, &args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode ACCESS3args");
+       if (zdr_RENAME3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode RENAME3args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/access call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/RENAME call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -212,32 +859,39 @@ int rpc_nfs_access_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
        return 0;
 }
 
+int rpc_nfs_rename_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *olddir, char *oldname, struct nfs_fh3 *newdir, char *newname, void *private_data)
+{
+       RENAME3args args;
+
+       memset(&args, 0, sizeof(RENAME3args));
+       args.from.dir.data.data_len = olddir->data.data_len;
+       args.from.dir.data.data_val = olddir->data.data_val;
+       args.from.name = oldname;
+       args.to.dir.data.data_len = newdir->data.data_len;
+       args.to.dir.data.data_val = newdir->data.data_val;
+       args.to.name = newname;
 
+       return rpc_nfs3_rename_async(rpc, cb, &args, private_data);
+}
 
-int rpc_nfs_read_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t offset, uint64_t count, void *private_data)
+int rpc_nfs3_link_async(struct rpc_context *rpc, rpc_cb cb, struct LINK3args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
-       READ3args args;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_READ, cb, private_data, (zdrproc_t)zdr_READ3res, sizeof(READ3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_LINK, cb, private_data, (zdrproc_t)zdr_LINK3res, sizeof(LINK3res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/read call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/LINK call");
                return -1;
        }
 
-       args.file.data.data_len = fh->data.data_len;
-       args.file.data.data_val = fh->data.data_val;
-       args.offset = offset;
-       args.count = count;
-
-       if (zdr_READ3args(&pdu->zdr, &args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode READ3args");
+       if (zdr_LINK3args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode LINK3args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/read call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/LINK call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -245,67 +899,60 @@ int rpc_nfs_read_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, u
        return 0;
 }
 
+int rpc_nfs_link_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *file, struct nfs_fh3 *newdir, char *newname, void *private_data)
+{
+       LINK3args args;
 
-int rpc_nfs_write_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *buf, uint64_t offset, uint64_t count, int stable_how, void *private_data)
+       memset(&args, 0, sizeof(LINK3args));
+       args.file.data.data_len = file->data.data_len;
+       args.file.data.data_val = file->data.data_val;
+       args.link.dir.data.data_len = newdir->data.data_len;
+       args.link.dir.data.data_val = newdir->data.data_val;
+       args.link.name = newname;
+
+       return rpc_nfs3_link_async(rpc, cb, &args, private_data);
+}
+
+/*
+ * NFSv2
+ */
+int rpc_nfs2_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
 {
        struct rpc_pdu *pdu;
-       WRITE3args args;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_WRITE, cb, private_data, (zdrproc_t)zdr_WRITE3res, sizeof(WRITE3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_NULL, cb, private_data, (zdrproc_t)zdr_void, 0);
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/write call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/NULL call");
                return -1;
        }
 
-       args.file.data.data_len = fh->data.data_len;
-       args.file.data.data_val = fh->data.data_val;
-       args.offset = offset;
-       args.count  = count;
-       args.stable = stable_how;
-       args.data.data_len = count;
-       args.data.data_val = buf;
-
-       if (zdr_WRITE3args(&pdu->zdr, &args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode WRITE3args");
-               rpc_free_pdu(rpc, pdu);
-               return -2;
-       }
-
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/write call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/NULL call");
                rpc_free_pdu(rpc, pdu);
-               return -3;
+               return -2;
        }
 
        return 0;
 }
 
-
-
-int rpc_nfs_commit_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data)
+int rpc_nfs2_getattr_async(struct rpc_context *rpc, rpc_cb cb, struct GETATTR2args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
-       COMMIT3args args;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_COMMIT, cb, private_data, (zdrproc_t)zdr_COMMIT3res, sizeof(COMMIT3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_GETATTR, cb, private_data, (zdrproc_t)zdr_GETATTR2res, sizeof(GETATTR2res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/commit call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/GETATTR call");
                return -1;
        }
 
-       args.file.data.data_len = fh->data.data_len;
-       args.file.data.data_val = fh->data.data_val;
-       args.offset = 0;
-       args.count  = 0;
-
-       if (zdr_COMMIT3args(&pdu->zdr, &args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode WRITE3args");
+       if (zdr_GETATTR2args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode GETATTR2args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/commit call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/GETATTR call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -313,25 +960,24 @@ int rpc_nfs_commit_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
        return 0;
 }
 
-
-int rpc_nfs_setattr_async(struct rpc_context *rpc, rpc_cb cb, SETATTR3args *args, void *private_data)
+int rpc_nfs2_setattr_async(struct rpc_context *rpc, rpc_cb cb, SETATTR2args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_SETATTR, cb, private_data, (zdrproc_t)zdr_SETATTR3res, sizeof(SETATTR3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_SETATTR, cb, private_data, (zdrproc_t)zdr_SETATTR2res, sizeof(SETATTR2res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/setattr call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/SETATTR call");
                return -1;
        }
 
-       if (zdr_SETATTR3args(&pdu->zdr, args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode SETATTR3args");
+       if (zdr_SETATTR2args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode SETATTR2args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/setattr call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/SETATTR call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -339,26 +985,24 @@ int rpc_nfs_setattr_async(struct rpc_context *rpc, rpc_cb cb, SETATTR3args *args
        return 0;
 }
 
-
-
-int rpc_nfs_mkdir_async(struct rpc_context *rpc, rpc_cb cb, MKDIR3args *args, void *private_data)
+int rpc_nfs2_lookup_async(struct rpc_context *rpc, rpc_cb cb, struct LOOKUP2args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_MKDIR, cb, private_data, (zdrproc_t)zdr_MKDIR3res, sizeof(MKDIR3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_LOOKUP, cb, private_data, (zdrproc_t)zdr_LOOKUP2res, sizeof(LOOKUP2res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/setattr call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/LOOKUP call");
                return -1;
        }
 
-       if (zdr_MKDIR3args(&pdu->zdr, args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode MKDIR3args");
+       if (zdr_LOOKUP2args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode LOOKUP2args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/mkdir call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/LOOKUP call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -366,33 +1010,24 @@ int rpc_nfs_mkdir_async(struct rpc_context *rpc, rpc_cb cb, MKDIR3args *args, vo
        return 0;
 }
 
-
-
-
-int rpc_nfs_rmdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *dir, void *private_data)
+int rpc_nfs2_readlink_async(struct rpc_context *rpc, rpc_cb cb, READLINK2args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
-       RMDIR3args args;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_RMDIR, cb, private_data, (zdrproc_t)zdr_RMDIR3res, sizeof(RMDIR3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_READLINK, cb, private_data, (zdrproc_t)zdr_READLINK2res, sizeof(READLINK2res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/rmdir call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/READLINK call");
                return -1;
        }
 
-       memset(&args, 0, sizeof(RMDIR3args));
-       args.object.dir.data.data_len = fh->data.data_len;
-       args.object.dir.data.data_val = fh->data.data_val;
-       args.object.name = dir;
-
-       if (zdr_RMDIR3args(&pdu->zdr, &args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode RMDIR3args");
+       if (zdr_READLINK2args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode READLINK2args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/rmdir call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/READLINK call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -400,26 +1035,24 @@ int rpc_nfs_rmdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
        return 0;
 }
 
-
-
-int rpc_nfs_create_async(struct rpc_context *rpc, rpc_cb cb, CREATE3args *args, void *private_data)
+int rpc_nfs2_read_async(struct rpc_context *rpc, rpc_cb cb, struct READ2args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_CREATE, cb, private_data, (zdrproc_t)zdr_CREATE3res, sizeof(CREATE3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_READ, cb, private_data, (zdrproc_t)zdr_READ2res, sizeof(READ2res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/create call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/READ call");
                return -1;
        }
 
-       if (zdr_CREATE3args(&pdu->zdr, args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode CREATE3args");
+       if (zdr_READ2args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode READ2args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/create call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/READ call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -427,61 +1060,24 @@ int rpc_nfs_create_async(struct rpc_context *rpc, rpc_cb cb, CREATE3args *args,
        return 0;
 }
 
-
-
-int rpc_nfs_mknod_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *file, int mode, int major, int minor, void *private_data)
+int rpc_nfs2_write_async(struct rpc_context *rpc, rpc_cb cb, struct WRITE2args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
-       MKNOD3args args;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_MKNOD, cb, private_data, (zdrproc_t)zdr_MKNOD3res, sizeof(MKNOD3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_WRITE, cb, private_data, (zdrproc_t)zdr_WRITE2res, sizeof(WRITE2res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/mknod call");
-               return -1;
-       }
-
-       memset(&args, 0, sizeof(MKNOD3args));
-       args.where.dir.data.data_len = fh->data.data_len;
-       args.where.dir.data.data_val = fh->data.data_val;
-       args.where.name = file;
-       switch (mode & S_IFMT) {
-       case S_IFCHR:
-               args.what.type = NF3CHR;
-               args.what.mknoddata3_u.chr_device.dev_attributes.mode.set_it = 1;
-               args.what.mknoddata3_u.chr_device.dev_attributes.mode.set_mode3_u.mode = mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
-               args.what.mknoddata3_u.chr_device.spec.specdata1 = major;
-               args.what.mknoddata3_u.chr_device.spec.specdata2 = minor;
-               break;
-       case S_IFBLK:
-               args.what.type = NF3BLK;
-               args.what.mknoddata3_u.blk_device.dev_attributes.mode.set_it = 1;
-               args.what.mknoddata3_u.blk_device.dev_attributes.mode.set_mode3_u.mode = mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
-               args.what.mknoddata3_u.blk_device.spec.specdata1 = major;
-               args.what.mknoddata3_u.blk_device.spec.specdata2 = minor;
-       case S_IFSOCK:
-               args.what.type = NF3SOCK;
-               args.what.mknoddata3_u.sock_attributes.mode.set_it = 1;
-               args.what.mknoddata3_u.sock_attributes.mode.set_mode3_u.mode = mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
-               break;
-       case S_IFIFO:
-               args.what.type = NF3FIFO;
-               args.what.mknoddata3_u.pipe_attributes.mode.set_it = 1;
-               args.what.mknoddata3_u.pipe_attributes.mode.set_mode3_u.mode = mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
-               break;
-       default:
-               rpc_set_error(rpc, "Invalid file type for nfs/mknod call");
-               rpc_free_pdu(rpc, pdu);
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/WRITE call");
                return -1;
        }
 
-       if (zdr_MKNOD3args(&pdu->zdr, &args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode MKNOD3args");
+       if (zdr_WRITE2args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode WRITE2args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/mknod call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/WRITE call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -489,31 +1085,24 @@ int rpc_nfs_mknod_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
        return 0;
 }
 
-
-int rpc_nfs_remove_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *file, void *private_data)
+int rpc_nfs2_create_async(struct rpc_context *rpc, rpc_cb cb, CREATE2args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
-       REMOVE3args args;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_REMOVE, cb, private_data, (zdrproc_t)zdr_REMOVE3res, sizeof(REMOVE3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_CREATE, cb, private_data, (zdrproc_t)zdr_CREATE2res, sizeof(CREATE2res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/remove call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/CREATE call");
                return -1;
        }
 
-       memset(&args, 0, sizeof(REMOVE3args));
-       args.object.dir.data.data_len = fh->data.data_len;
-       args.object.dir.data.data_val = fh->data.data_val;
-       args.object.name = file;
-
-       if (zdr_REMOVE3args(&pdu->zdr, &args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode REMOVE3args");
+       if (zdr_CREATE2args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode CREATE2args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/remove call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/CREATE call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -521,32 +1110,24 @@ int rpc_nfs_remove_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
        return 0;
 }
 
-int rpc_nfs_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t cookie, char *cookieverf, int count, void *private_data)
+int rpc_nfs2_remove_async(struct rpc_context *rpc, rpc_cb cb, struct REMOVE2args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
-       READDIR3args args;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_READDIR, cb, private_data, (zdrproc_t)zdr_READDIR3res, sizeof(READDIR3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_REMOVE, cb, private_data, (zdrproc_t)zdr_REMOVE2res, sizeof(REMOVE2res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/readdir call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/REMOVE call");
                return -1;
        }
 
-       memset(&args, 0, sizeof(READDIR3args));
-       args.dir.data.data_len = fh->data.data_len;
-       args.dir.data.data_val = fh->data.data_val;
-       args.cookie = cookie;
-       memcpy(&args.cookieverf, cookieverf, sizeof(cookieverf3)); 
-       args.count = count;
-
-       if (zdr_READDIR3args(&pdu->zdr, &args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode READDIR3args");
+       if (zdr_REMOVE2args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode REMOVE2args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/readdir call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/REMOVE call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -554,33 +1135,24 @@ int rpc_nfs_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh
        return 0;
 }
 
-int rpc_nfs_readdirplus_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t cookie, char *cookieverf, int count, void *private_data)
+int rpc_nfs2_rename_async(struct rpc_context *rpc, rpc_cb cb, struct RENAME2args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
-       READDIRPLUS3args args;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_READDIRPLUS, cb, private_data, (zdrproc_t)zdr_READDIRPLUS3res, sizeof(READDIRPLUS3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_RENAME, cb, private_data, (zdrproc_t)zdr_RENAME2res, sizeof(RENAME2res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/readdirplus call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/RENAME call");
                return -1;
        }
 
-       memset(&args, 0, sizeof(READDIRPLUS3args));
-       args.dir.data.data_len = fh->data.data_len;
-       args.dir.data.data_val = fh->data.data_val;
-       args.cookie = cookie;
-       memcpy(&args.cookieverf, cookieverf, sizeof(cookieverf3)); 
-       args.dircount = count;
-       args.maxcount = count;
-
-       if (zdr_READDIRPLUS3args(&pdu->zdr, &args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode READDIRPLUS3args");
+       if (zdr_RENAME2args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode RENAME2args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/readdirplus call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/RENAME call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -588,28 +1160,24 @@ int rpc_nfs_readdirplus_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3
        return 0;
 }
 
-int rpc_nfs_fsstat_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data)
+int rpc_nfs2_link_async(struct rpc_context *rpc, rpc_cb cb, LINK2args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
-       FSSTAT3args args;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_FSSTAT, cb, private_data, (zdrproc_t)zdr_FSSTAT3res, sizeof(FSSTAT3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_LINK, cb, private_data, (zdrproc_t)zdr_LINK2res, sizeof(LINK2res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/fsstat call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/LINK call");
                return -1;
        }
 
-       args.fsroot.data.data_len = fh->data.data_len; 
-       args.fsroot.data.data_val = fh->data.data_val; 
-
-       if (zdr_FSSTAT3args(&pdu->zdr, &args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode FSSTAT3args");
+       if (zdr_LINK2args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode LINK2args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/fsstat call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/LINK call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -617,28 +1185,24 @@ int rpc_nfs_fsstat_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
        return 0;
 }
 
-int rpc_nfs_fsinfo_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data)
+int rpc_nfs2_symlink_async(struct rpc_context *rpc, rpc_cb cb, SYMLINK2args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
-       FSINFO3args args;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_FSINFO, cb, private_data, (zdrproc_t)zdr_FSINFO3res, sizeof(FSINFO3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_SYMLINK, cb, private_data, (zdrproc_t)zdr_SYMLINK2res, sizeof(SYMLINK2res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/fsinfo call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/SYMLINK call");
                return -1;
        }
 
-       args.fsroot.data.data_len = fh->data.data_len; 
-       args.fsroot.data.data_val = fh->data.data_val; 
-
-       if (zdr_FSINFO3args(&pdu->zdr, &args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode FSINFO3args");
+       if (zdr_SYMLINK2args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode SYMLINK2args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/fsinfo call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/SYMLINK call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -646,24 +1210,24 @@ int rpc_nfs_fsinfo_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh,
        return 0;
 }
 
-int rpc_nfs_readlink_async(struct rpc_context *rpc, rpc_cb cb, READLINK3args *args, void *private_data)
+int rpc_nfs2_mkdir_async(struct rpc_context *rpc, rpc_cb cb, MKDIR2args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_READLINK, cb, private_data, (zdrproc_t)zdr_READLINK3res, sizeof(READLINK3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_MKDIR, cb, private_data, (zdrproc_t)zdr_MKDIR2res, sizeof(MKDIR2res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/readlink call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/MKDIR call");
                return -1;
        }
 
-       if (zdr_READLINK3args(&pdu->zdr, args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode READLINK3args");
+       if (zdr_MKDIR2args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode MKDIR2args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/readlink call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/MKDIR call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -671,25 +1235,24 @@ int rpc_nfs_readlink_async(struct rpc_context *rpc, rpc_cb cb, READLINK3args *ar
        return 0;
 }
 
-
-int rpc_nfs_symlink_async(struct rpc_context *rpc, rpc_cb cb, SYMLINK3args *args, void *private_data)
+int rpc_nfs2_rmdir_async(struct rpc_context *rpc, rpc_cb cb, struct RMDIR2args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_SYMLINK, cb, private_data, (zdrproc_t)zdr_SYMLINK3res, sizeof(SYMLINK3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_RMDIR, cb, private_data, (zdrproc_t)zdr_RMDIR2res, sizeof(RMDIR2res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/symlink call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/RMDIR call");
                return -1;
        }
 
-       if (zdr_SYMLINK3args(&pdu->zdr, args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode SYMLINK3args");
+       if (zdr_RMDIR2args(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode RMDIR2args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/symlink call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/RMDIR call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -697,36 +1260,24 @@ int rpc_nfs_symlink_async(struct rpc_context *rpc, rpc_cb cb, SYMLINK3args *args
        return 0;
 }
 
-
-
-
-int rpc_nfs_rename_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *olddir, char *oldname, struct nfs_fh3 *newdir, char *newname, void *private_data)
+int rpc_nfs2_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct READDIR2args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
-       RENAME3args args;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_RENAME, cb, private_data, (zdrproc_t)zdr_RENAME3res, sizeof(RENAME3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_READDIR, cb, private_data, (zdrproc_t)zdr_READDIR2res, sizeof(READDIR2res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/rename call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/READDIR call");
                return -1;
        }
 
-       memset(&args, 0, sizeof(RENAME3args));
-       args.from.dir.data.data_len = olddir->data.data_len;
-       args.from.dir.data.data_val = olddir->data.data_val;
-       args.from.name = oldname;
-       args.to.dir.data.data_len = newdir->data.data_len;
-       args.to.dir.data.data_val = newdir->data.data_val;
-       args.to.name = newname;
-
-       if (zdr_RENAME3args(&pdu->zdr, &args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode RENAME3args");
+       if (zdr_READDIR2args(&pdu->zdr,  args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode READDIR2args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/rename call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/READDIR call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
@@ -734,42 +1285,27 @@ int rpc_nfs_rename_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *old
        return 0;
 }
 
-
-
-
-int rpc_nfs_link_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *file, struct nfs_fh3 *newdir, char *newname, void *private_data)
+int rpc_nfs2_statfs_async(struct rpc_context *rpc, rpc_cb cb, struct STATFS2args *args, void *private_data)
 {
        struct rpc_pdu *pdu;
-       LINK3args args;
 
-       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_LINK, cb, private_data, (zdrproc_t)zdr_LINK3res, sizeof(LINK3res));
+       pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_STATFS, cb, private_data, (zdrproc_t)zdr_STATFS2res, sizeof(STATFS2res));
        if (pdu == NULL) {
-               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfs/link call");
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/STATFS call");
                return -1;
        }
 
-       memset(&args, 0, sizeof(LINK3args));
-       args.file.data.data_len = file->data.data_len;
-       args.file.data.data_val = file->data.data_val;
-       args.link.dir.data.data_len = newdir->data.data_len;
-       args.link.dir.data.data_val = newdir->data.data_val;
-       args.link.name = newname;
-
-       if (zdr_LINK3args(&pdu->zdr, &args) == 0) {
-               rpc_set_error(rpc, "ZDR error: Failed to encode LINK3args");
+       if (zdr_STATFS2args(&pdu->zdr,  args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode STATFS2args");
                rpc_free_pdu(rpc, pdu);
                return -2;
        }
 
        if (rpc_queue_pdu(rpc, pdu) != 0) {
-               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfs/link call");
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/STATFS call");
                rpc_free_pdu(rpc, pdu);
                return -3;
        }
 
        return 0;
 }
-
-
-
-
index 6e2d7a47d6bd9f044cfd762565bea6a1eec4615d..cc19757ea607ede75d79d47517a068050eb01123 100644 (file)
--- a/nfs/nfs.x
+++ b/nfs/nfs.x
@@ -1,5 +1,8 @@
 /* NFS part from rfc 1813, NFSACL part is from wireshark sources */
 
+/*
+ * NFS v3 Definitions
+ */
 const NFS3_FHSIZE    = 64;    /* Maximum bytes in a V3 file handle */
 const NFS3_WRITEVERFSIZE = 8;
 const NFS3_CREATEVERFSIZE = 8;
@@ -777,7 +780,338 @@ union SETATTR3res switch (nfsstat3 status) {
                SETATTR3resfail resfail;
 };
 
+/*
+ * NFS v2 Definitions
+ * We share many definitions from v3
+ */
+const FHSIZE2 = 32;
+typedef opaque fhandle2[FHSIZE2];
+
+enum ftype2 {
+       NF2NON    = 0,
+       NF2REG    = 1,
+       NF2DIR    = 2,
+       NF2BLK    = 3,
+       NF2CHR    = 4,
+       NF2LNK    = 5
+};
+
+struct fattr2 {
+       ftype2       type;
+       unsigned int mode;
+       unsigned int nlink;
+       unsigned int uid;
+       unsigned int gid;
+       unsigned int size;
+       unsigned int blocksize;
+       unsigned int rdev;
+       unsigned int blocks;
+       unsigned int fsid;
+       unsigned int fileid;
+       nfstime3 atime;
+       nfstime3 mtime;
+       nfstime3 ctime;
+};
+
+struct sattr2 {
+       unsigned int mode;
+       unsigned int uid;
+       unsigned int gid;
+       unsigned int size;
+       nfstime3     atime;
+       nfstime3     mtime;
+};
+
+const MAXNAMLEN2 = 255;
+typedef string filename2<MAXNAMLEN2>;
+
+const MAXPATHLEN2 = 1024;
+typedef string path2<MAXPATHLEN2>;
+
+const NFSMAXDATA2 = 8192;
+typedef opaque nfsdata2<NFSMAXDATA2>;
+
+const NFSCOOKIESIZE2 = 4;
+typedef opaque nfscookie2[NFSCOOKIESIZE2];
+
+struct entry2 {
+       unsigned int fileid;
+       filename2 name;
+       nfscookie2 cookie;
+       entry2 *nextentry;
+};
+
+struct diropargs2 {
+       fhandle2  dir;
+       filename2 name;
+};
+
+struct GETATTR2args {
+       fhandle2 fhandle;
+};
+
+struct GETATTR2resok {
+       fattr2 attributes;
+};
+
+union GETATTR2res switch (nfsstat3 status) {
+       case NFS3_OK:
+               GETATTR2resok resok;
+       default:
+               void;
+};
+
+struct SETATTR2args {
+       fhandle2 fhandle;
+        sattr2 attributes;
+};
+
+struct SETATTR2resok {
+       fattr2 attributes;
+};
+
+union SETATTR2res switch (nfsstat3 status) {
+       case NFS3_OK:
+               SETATTR2resok resok;
+       default:
+               void;
+};
+
+struct LOOKUP2args {
+       diropargs2 what;
+};
+
+struct LOOKUP2resok {
+       fhandle2 file;
+       fattr2   attributes;
+};
+
+union LOOKUP2res switch (nfsstat3 status) {
+       case NFS3_OK:
+               LOOKUP2resok resok;
+       default:
+               void;
+};
+
+struct READLINK2args {
+       fhandle2 file;
+};
+
+struct READLINK2resok {
+       path2 data;
+};
+
+union READLINK2res switch (nfsstat3 status) {
+       case NFS3_OK:
+               READLINK2resok resok;
+       default:
+               void;
+};
+
+struct READ2args {
+       fhandle2 file;
+       unsigned int offset;
+       unsigned int count;
+       unsigned int totalcount;
+};
+
+struct READ2resok {
+       fattr2   attributes;
+       nfsdata2 data;
+};
+
+union READ2res switch (nfsstat3 status) {
+       case NFS3_OK:
+               READ2resok resok;
+       default:
+               void;
+};
+
+struct WRITE2args {
+       fhandle2 file;
+       unsigned int beginoffset;
+       unsigned int offset;
+       unsigned int totalcount;
+       nfsdata2 data;
+};
+
+struct WRITE2resok {
+       fattr2 attributes;
+};
+
+union WRITE2res switch (nfsstat3 status) {
+       case NFS3_OK:
+               WRITE2resok resok;
+       default:
+               void;
+};
+
+struct CREATE2args {
+       diropargs2 where;
+        sattr2 attributes;
+};
+
+struct CREATE2resok {
+       fhandle2 file;
+       fattr2   attributes;
+};
+
+union CREATE2res switch (nfsstat3 status) {
+       case NFS3_OK:
+               CREATE2resok resok;
+       default:
+               void;
+};
+
+struct REMOVE2args {
+       diropargs2 what;
+};
+
+struct REMOVE2res {
+       nfsstat3 status;
+};
+
+struct RENAME2args {
+       diropargs2 from;
+       diropargs2 to;
+};
+
+struct RENAME2res {
+       nfsstat3 status;
+};
+
+struct LINK2args {
+       fhandle2 from;
+       diropargs2 to;
+};
+
+struct LINK2res {
+       nfsstat3 status;
+};
+
+struct SYMLINK2args {
+       diropargs2 from;
+       path2 to;
+        sattr2 attributes;
+};
+
+struct SYMLINK2res {
+       nfsstat3 status;
+};
+
+struct MKDIR2args {
+       diropargs2 where;
+        sattr2 attributes;
+};
+
+struct MKDIR2resok {
+       fhandle2 file;
+       fattr2   attributes;
+};
+
+union MKDIR2res switch (nfsstat3 status) {
+       case NFS3_OK:
+               MKDIR2resok resok;
+       default:
+               void;
+};
+
+struct RMDIR2args {
+       diropargs2 what;
+};
+
+struct RMDIR2res {
+       nfsstat3 status;
+};
+
+struct READDIR2args {
+       fhandle2 dir;
+       nfscookie2 cookie;
+       unsigned int count;
+};
+
+struct READDIR2resok {
+       entry2 *entries;
+       bool    eof;
+};
+
+union READDIR2res switch (nfsstat3 status) {
+       case NFS3_OK:
+               READDIR2resok resok;
+       default:
+               void;
+};
+
+struct STATFS2args {
+       fhandle2 dir;
+};
+
+struct STATFS2resok {
+       unsigned int tsize;
+       unsigned int bsize;
+       unsigned int blocks;
+       unsigned int bfree;
+       unsigned int bavail;
+};
+
+union STATFS2res switch (nfsstat3 status) {
+       case NFS3_OK:
+               STATFS2resok resok;
+       default:
+               void;
+};
+
 program NFS_PROGRAM {
+       version NFS_V2 {
+               void
+               NFS2_NULL(void)                    = 0;
+
+               GETATTR2res
+               NFS2_GETATTR(GETATTR2args)         = 1;
+
+               SETATTR2res
+               NFS2_SETATTR(SETATTR2args)         = 2;
+
+               LOOKUP2res
+               NFS2_LOOKUP(LOOKUP2args)           = 4;
+
+               READLINK2res
+               NFS2_READLINK(READLINK2args)       = 5;
+
+               READ2res
+               NFS2_READ(READ2args)               = 6;
+
+               WRITE2res
+               NFS2_WRITE(WRITE2args)             = 8;
+
+               CREATE2res
+               NFS2_CREATE(CREATE2args)           = 9;
+
+               REMOVE2res
+               NFS2_REMOVE(REMOVE2args)           = 10;
+
+               RENAME2res
+               NFS2_RENAME(RENAME2args)           = 11;
+
+               LINK2res
+               NFS2_LINK(LINK2args)               = 12;
+
+               SYMLINK2res
+               NFS2_SYMLINK(SYMLINK2args)         = 13;
+
+               MKDIR2res
+               NFS2_MKDIR(MKDIR2args)             = 14;
+
+               RMDIR2res
+               NFS2_RMDIR(RMDIR2args)             = 15;
+
+               READDIR2res
+               NFS2_READDIR(READDIR2args)         = 16;
+
+               STATFS2res
+               NFS2_STATFS(STATFS2args)           = 17;
+       } = 2;
+
        version NFS_V3 {
                void
                NFS3_NULL(void)                    = 0;
diff --git a/nsm/Makefile.am b/nsm/Makefile.am
new file mode 100644 (file)
index 0000000..1ec6ed6
--- /dev/null
@@ -0,0 +1,22 @@
+noinst_LTLIBRARIES = libnsm.la
+
+nsm_SOURCES_GENERATED =
+nsm_HEADERS_GENERATED =
+nsm_GENERATED = $(nsm_SOURCES_GENERATED) $(nsm_HEADERS_GENERATED)
+
+CLEANFILES = $(nsm_GENERATED) nsm-stamp
+
+libnsm_la_CPPFLAGS = -I$(abs_top_srcdir)/include \
+                    -I$(abs_top_srcdir)/include/nfsc
+libnsm_la_SOURCES = \
+       $(nsm_SOURCES_GENERATED) \
+       nsm.c libnfs-raw-nsm.c
+
+$(nsm_GENERATED) : nsm-stamp
+nsm-stamp : nsm.x
+       rm -f $(nsm_GENERATED)
+       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
diff --git a/nsm/libnfs-raw-nsm.c b/nsm/libnfs-raw-nsm.c
new file mode 100644 (file)
index 0000000..cc3997d
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "libnfs-zdr.h"
+#include "libnfs-raw-nsm.h"
+
+bool_t
+zdr_nsmstat1 (ZDR *zdrs, nsmstat1 *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_enum (zdrs, (enum_t *) objp))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_nsm_my_id (ZDR *zdrs, nsm_my_id *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_string (zdrs, &objp->my_name, NSM_MAXSTRLEN))
+                return FALSE;
+        if (!zdr_int (zdrs, &objp->my_prog))
+                return FALSE;
+        if (!zdr_int (zdrs, &objp->my_vers))
+                return FALSE;
+        if (!zdr_int (zdrs, &objp->my_proc))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_nsm_mon_id (ZDR *zdrs, nsm_mon_id *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_string (zdrs, &objp->mon_name, NSM_MAXSTRLEN))
+                return FALSE;
+        if (!zdr_nsm_my_id (zdrs, &objp->my_id))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_NSM1_STATres (ZDR *zdrs, NSM1_STATres *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nsmstat1 (zdrs, &objp->res))
+                return FALSE;
+        if (!zdr_int (zdrs, &objp->state))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_NSM1_STATargs (ZDR *zdrs, NSM1_STATargs *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_string (zdrs, &objp->mon_name, NSM_MAXSTRLEN))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_NSM1_MONres (ZDR *zdrs, NSM1_MONres *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nsmstat1 (zdrs, &objp->res))
+                return FALSE;
+        if (!zdr_int (zdrs, &objp->state))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_NSM1_MONargs (ZDR *zdrs, NSM1_MONargs *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+       int i;
+        if (!zdr_nsm_mon_id (zdrs, &objp->mon_id))
+                return FALSE;
+        if (!zdr_opaque (zdrs, objp->priv, 16))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_NSM1_UNMONres (ZDR *zdrs, NSM1_UNMONres *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_int (zdrs, &objp->state))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_NSM1_UNMONargs (ZDR *zdrs, NSM1_UNMONargs *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nsm_mon_id (zdrs, &objp->mon_id))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_NSM1_UNMONALLres (ZDR *zdrs, NSM1_UNMONALLres *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_int (zdrs, &objp->state))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_NSM1_UNMONALLargs (ZDR *zdrs, NSM1_UNMONALLargs *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_nsm_my_id (zdrs, &objp->my_id))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+zdr_NSM1_NOTIFYargs (ZDR *zdrs, NSM1_NOTIFYargs *objp)
+{
+       register int32_t *buf;
+       buf = NULL;
+
+        if (!zdr_string (zdrs, &objp->mon_name, NSM_MAXSTRLEN))
+                return FALSE;
+        if (!zdr_int (zdrs, &objp->state))
+                return FALSE;
+       return TRUE;
+}
diff --git a/nsm/libnfs-raw-nsm.h b/nsm/libnfs-raw-nsm.h
new file mode 100644 (file)
index 0000000..b68a1bd
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _NSM_H_RPCGEN
+#define _NSM_H_RPCGEN
+
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NSM_MAXSTRLEN 1024
+
+enum nsmstat1 {
+       NSM_STAT_SUCC = 0,
+       NSM_STAT_FAIL = 1,
+};
+typedef enum nsmstat1 nsmstat1;
+
+struct nsm_my_id {
+       char *my_name;
+       int my_prog;
+       int my_vers;
+       int my_proc;
+};
+typedef struct nsm_my_id nsm_my_id;
+
+struct nsm_mon_id {
+       char *mon_name;
+       struct nsm_my_id my_id;
+};
+typedef struct nsm_mon_id nsm_mon_id;
+
+struct NSM1_STATres {
+       nsmstat1 res;
+       int state;
+};
+typedef struct NSM1_STATres NSM1_STATres;
+
+struct NSM1_STATargs {
+       char *mon_name;
+};
+typedef struct NSM1_STATargs NSM1_STATargs;
+
+struct NSM1_MONres {
+       nsmstat1 res;
+       int state;
+};
+typedef struct NSM1_MONres NSM1_MONres;
+
+struct NSM1_MONargs {
+       struct nsm_mon_id mon_id;
+       char priv[16];
+};
+typedef struct NSM1_MONargs NSM1_MONargs;
+
+struct NSM1_UNMONres {
+       int state;
+};
+typedef struct NSM1_UNMONres NSM1_UNMONres;
+
+struct NSM1_UNMONargs {
+       struct nsm_mon_id mon_id;
+};
+typedef struct NSM1_UNMONargs NSM1_UNMONargs;
+
+struct NSM1_UNMONALLres {
+       int state;
+};
+typedef struct NSM1_UNMONALLres NSM1_UNMONALLres;
+
+struct NSM1_UNMONALLargs {
+       struct nsm_my_id my_id;
+};
+typedef struct NSM1_UNMONALLargs NSM1_UNMONALLargs;
+
+struct NSM1_NOTIFYargs {
+       char *mon_name;
+       int state;
+};
+typedef struct NSM1_NOTIFYargs NSM1_NOTIFYargs;
+
+#define NSM_PROGRAM 100024
+#define NSM_V1 1
+
+#if defined(__STDC__) || defined(__cplusplus)
+#define NSM1_NULL 0
+extern  void * nsm1_null_1(void *, CLIENT *);
+extern  void * nsm1_null_1_svc(void *, struct svc_req *);
+#define NSM1_STAT 1
+extern  struct NSM1_STATres * nsm1_stat_1(struct NSM1_STATargs *, CLIENT *);
+extern  struct NSM1_STATres * nsm1_stat_1_svc(struct NSM1_STATargs *, struct svc_req *);
+#define NSM1_MON 2
+extern  struct NSM1_MONres * nsm1_mon_1(struct NSM1_MONargs *, CLIENT *);
+extern  struct NSM1_MONres * nsm1_mon_1_svc(struct NSM1_MONargs *, struct svc_req *);
+#define NSM1_UNMON 3
+extern  struct NSM1_UNMONres * nsm1_unmon_1(struct NSM1_UNMONargs *, CLIENT *);
+extern  struct NSM1_UNMONres * nsm1_unmon_1_svc(struct NSM1_UNMONargs *, struct svc_req *);
+#define NSM1_UNMON_ALL 4
+extern  struct NSM1_UNMONALLres * nsm1_unmon_all_1(struct NSM1_UNMONALLargs *, CLIENT *);
+extern  struct NSM1_UNMONALLres * nsm1_unmon_all_1_svc(struct NSM1_UNMONALLargs *, struct svc_req *);
+#define NSM1_SIMU_CRASH 5
+extern  void * nsm1_simu_crash_1(void *, CLIENT *);
+extern  void * nsm1_simu_crash_1_svc(void *, struct svc_req *);
+#define NSM1_NOTIFY 6
+extern  void * nsm1_notify_1(struct NSM1_NOTIFYargs *, CLIENT *);
+extern  void * nsm1_notify_1_svc(struct NSM1_NOTIFYargs *, struct svc_req *);
+extern int nsm_program_1_freeresult (SVCXPRT *, zdrproc_t, caddr_t);
+
+#else /* K&R C */
+#define NSM1_NULL 0
+extern  void * nsm1_null_1();
+extern  void * nsm1_null_1_svc();
+#define NSM1_STAT 1
+extern  struct NSM1_STATres * nsm1_stat_1();
+extern  struct NSM1_STATres * nsm1_stat_1_svc();
+#define NSM1_MON 2
+extern  struct NSM1_MONres * nsm1_mon_1();
+extern  struct NSM1_MONres * nsm1_mon_1_svc();
+#define NSM1_UNMON 3
+extern  struct NSM1_UNMONres * nsm1_unmon_1();
+extern  struct NSM1_UNMONres * nsm1_unmon_1_svc();
+#define NSM1_UNMON_ALL 4
+extern  struct NSM1_UNMONALLres * nsm1_unmon_all_1();
+extern  struct NSM1_UNMONALLres * nsm1_unmon_all_1_svc();
+#define NSM1_SIMU_CRASH 5
+extern  void * nsm1_simu_crash_1();
+extern  void * nsm1_simu_crash_1_svc();
+#define NSM1_NOTIFY 6
+extern  void * nsm1_notify_1();
+extern  void * nsm1_notify_1_svc();
+extern int nsm_program_1_freeresult ();
+#endif /* K&R C */
+
+/* the zdr functions */
+
+#if defined(__STDC__) || defined(__cplusplus)
+extern  bool_t zdr_nsmstat1 (ZDR *, nsmstat1*);
+extern  bool_t zdr_nsm_my_id (ZDR *, nsm_my_id*);
+extern  bool_t zdr_nsm_mon_id (ZDR *, nsm_mon_id*);
+extern  bool_t zdr_NSM1_STATres (ZDR *, NSM1_STATres*);
+extern  bool_t zdr_NSM1_STATargs (ZDR *, NSM1_STATargs*);
+extern  bool_t zdr_NSM1_MONres (ZDR *, NSM1_MONres*);
+extern  bool_t zdr_NSM1_MONargs (ZDR *, NSM1_MONargs*);
+extern  bool_t zdr_NSM1_UNMONres (ZDR *, NSM1_UNMONres*);
+extern  bool_t zdr_NSM1_UNMONargs (ZDR *, NSM1_UNMONargs*);
+extern  bool_t zdr_NSM1_UNMONALLres (ZDR *, NSM1_UNMONALLres*);
+extern  bool_t zdr_NSM1_UNMONALLargs (ZDR *, NSM1_UNMONALLargs*);
+extern  bool_t zdr_NSM1_NOTIFYargs (ZDR *, NSM1_NOTIFYargs*);
+
+#else /* K&R C */
+extern bool_t zdr_nsmstat1 ();
+extern bool_t zdr_nsm_my_id ();
+extern bool_t zdr_nsm_mon_id ();
+extern bool_t zdr_NSM1_STATres ();
+extern bool_t zdr_NSM1_STATargs ();
+extern bool_t zdr_NSM1_MONres ();
+extern bool_t zdr_NSM1_MONargs ();
+extern bool_t zdr_NSM1_UNMONres ();
+extern bool_t zdr_NSM1_UNMONargs ();
+extern bool_t zdr_NSM1_UNMONALLres ();
+extern bool_t zdr_NSM1_UNMONALLargs ();
+extern bool_t zdr_NSM1_NOTIFYargs ();
+
+#endif /* K&R C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_NSM_H_RPCGEN */
diff --git a/nsm/nsm.c b/nsm/nsm.c
new file mode 100644 (file)
index 0000000..2a6f9ec
--- /dev/null
+++ b/nsm/nsm.c
@@ -0,0 +1,203 @@
+/*
+   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/>.
+*/
+
+#ifdef WIN32
+#include "win32_compat.h"
+#endif/*WIN32*/
+
+#include <stdio.h>
+#include <errno.h>
+#include "libnfs-zdr.h"
+#include "libnfs.h"
+#include "libnfs-raw.h"
+#include "libnfs-private.h"
+#include "libnfs-raw-nsm.h"
+
+int rpc_nsm1_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NSM_PROGRAM, NSM_V1, NSM1_NULL, cb, private_data, (zdrproc_t)zdr_void, 0);
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nsm/null call");
+               return -1;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nsm/null call");
+               rpc_free_pdu(rpc, pdu);
+               return -1;
+       }
+
+       return 0;
+}
+
+int rpc_nsm1_stat_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_STATargs *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NSM_PROGRAM, NSM_V1, NSM1_STAT, cb, private_data, (zdrproc_t)zdr_NSM1_STATres, sizeof(NSM1_STATres));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nsm/stat call");
+               return -1;
+       }
+
+       if (zdr_NSM1_STATargs(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode NSM1_STATargs");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nsm/stat call");
+               rpc_free_pdu(rpc, pdu);
+               return -1;
+       }
+
+       return 0;
+}
+
+int rpc_nsm1_mon_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_MONargs *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NSM_PROGRAM, NSM_V1, NSM1_MON, cb, private_data, (zdrproc_t)zdr_NSM1_MONres, sizeof(NSM1_MONres));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nsm/mon call");
+               return -1;
+       }
+
+       if (zdr_NSM1_MONargs(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode NSM1_MONargs");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nsm/mon call");
+               rpc_free_pdu(rpc, pdu);
+               return -1;
+       }
+
+       return 0;
+}
+
+int rpc_nsm1_unmon_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_UNMONargs *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NSM_PROGRAM, NSM_V1, NSM1_UNMON, cb, private_data, (zdrproc_t)zdr_NSM1_UNMONres, sizeof(NSM1_UNMONres));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nsm/unmon call");
+               return -1;
+       }
+
+       if (zdr_NSM1_UNMONargs(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode NSM1_UNMONargs");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nsm/unmon call");
+               rpc_free_pdu(rpc, pdu);
+               return -1;
+       }
+
+       return 0;
+}
+
+int rpc_nsm1_unmonall_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_UNMONALLargs *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NSM_PROGRAM, NSM_V1, NSM1_UNMON_ALL, cb, private_data, (zdrproc_t)zdr_NSM1_UNMONALLres, sizeof(NSM1_UNMONALLres));
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nsm/unmonall call");
+               return -1;
+       }
+
+       if (zdr_NSM1_UNMONALLargs(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode NSM1_UNMONALLargs");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nsm/unmonall call");
+               rpc_free_pdu(rpc, pdu);
+               return -1;
+       }
+
+       return 0;
+}
+
+int rpc_nsm1_simucrash_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NSM_PROGRAM, NSM_V1, NSM1_SIMU_CRASH, cb, private_data, (zdrproc_t)zdr_void, 0);
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nsm/simucrash call");
+               return -1;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nsm/simucrash call");
+               rpc_free_pdu(rpc, pdu);
+               return -1;
+       }
+
+       return 0;
+}
+
+int rpc_nsm1_notify_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_NOTIFYargs *args, void *private_data)
+{
+       struct rpc_pdu *pdu;
+
+       pdu = rpc_allocate_pdu(rpc, NSM_PROGRAM, NSM_V1, NSM1_NOTIFY, cb, private_data, (zdrproc_t)zdr_void, 0);
+       if (pdu == NULL) {
+               rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nsm/notify call");
+               return -1;
+       }
+
+       if (zdr_NSM1_NOTIFYargs(&pdu->zdr, args) == 0) {
+               rpc_set_error(rpc, "ZDR error: Failed to encode NSM1_NOTIFYargs");
+               rpc_free_pdu(rpc, pdu);
+               return -2;
+       }
+
+       if (rpc_queue_pdu(rpc, pdu) != 0) {
+               rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nsm/notify call");
+               rpc_free_pdu(rpc, pdu);
+               return -1;
+       }
+
+       return 0;
+}
+
+char *nsmstat1_to_str(int st)
+{
+       enum nsmstat1 stat = st;
+
+       char *str = "unknown n1m stat";
+       switch (stat) {
+       case NSM_STAT_SUCC: str="NSM_STAT_SUCC";break;
+       case NSM_STAT_FAIL: str="NSM_STAT_FAIL";break;
+       }
+       return str;
+}
diff --git a/nsm/nsm.x b/nsm/nsm.x
new file mode 100644 (file)
index 0000000..43fbc14
--- /dev/null
+++ b/nsm/nsm.x
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+/*
+ * This defines the maximum length of the string
+ * identifying the caller.
+ */
+const NSM_MAXSTRLEN = 1024;
+
+enum nsmstat1 {
+    NSM_STAT_SUCC = 0,   /*  NSM agrees to monitor.  */
+    NSM_STAT_FAIL = 1    /*  NSM cannot monitor.  */
+};
+
+struct nsm_my_id {
+    string my_name<NSM_MAXSTRLEN>; /*  hostname  */
+    int    my_prog;                /*  RPC program number  */
+    int    my_vers;                /*  program version number  */
+    int    my_proc;                /*  procedure number  */
+};
+
+struct nsm_mon_id {
+    string mon_name<NSM_MAXSTRLEN>; /* name of the host to be monitored */
+    struct nsm_my_id my_id;
+};
+
+struct NSM1_STATres {
+    nsmstat1 res;
+    int      state;
+};
+
+struct NSM1_STATargs {
+    string mon_name<NSM_MAXSTRLEN>;
+};
+
+struct NSM1_MONres {
+    nsmstat1 res;
+    int      state;
+};
+
+struct NSM1_MONargs {
+    struct nsm_mon_id mon_id;
+    opaque priv[16];        /*  private information  */
+};
+
+struct NSM1_UNMONres {
+    int state;    /*  state number of NSM  */
+};
+
+struct NSM1_UNMONargs {
+    struct nsm_mon_id mon_id;
+};
+
+struct NSM1_UNMONALLres {
+    int state;    /*  state number of NSM  */
+};
+
+struct NSM1_UNMONALLargs {
+    struct nsm_my_id my_id;
+};
+
+struct NSM1_NOTIFYargs {
+    string mon_name<NSM_MAXSTRLEN>;
+    int    state;
+};
+
+/*
+ *  Protocol description for the NSM program.
+ */
+program NSM_PROGRAM {
+    version NSM_V1 {
+        void NSM1_NULL(void) = 0;
+        struct NSM1_STATres NSM1_STAT(struct NSM1_STATargs) = 1;
+        struct NSM1_MONres NSM1_MON(struct NSM1_MONargs) = 2;
+        struct NSM1_UNMONres NSM1_UNMON(struct NSM1_UNMONargs) = 3;
+        struct NSM1_UNMONALLres NSM1_UNMON_ALL(struct NSM1_UNMONALLargs) = 4; 
+        void NSM1_SIMU_CRASH(void) = 5;
+        void NSM1_NOTIFY(struct NSM1_NOTIFYargs) = 6;
+    } = 1;
+} = 100024;
+
+
index 2497f61b29ec48ba6cf5ddc8a6741b2e6e8e1d50..450f10f8aa7168d74804cdee6f03d9ebb8955a0c 100644 (file)
@@ -95,6 +95,15 @@ development libraries for LibNFS
 %{_libdir}/pkgconfig/libnfs.pc
 
 %changelog
+* Sun Wed 30 2013 : Version 1.8
+ - Fix nasty memory leak in read_from_socket
+ - minor updates
+* Sun Oct 20 2013 : Version 1.7
+ - Allow nested eventloops so that a sync function can be called from a callback.
+ - Fix a bug in unmarshalling a uint64.
+ - Add PATHCONF support.
+ - WIN32/64 updates
+ - AROS updates
 * Mon May 27 2013 : Version 1.6
  - AROS/Amiga support
  - Chose better initial xid value to reduce the probability for collissions.