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...

1  2 
include/nfsc/libnfs.h
lib/libnfs.c

diff --combined include/nfsc/libnfs.h
index 81750db3ec0189ba14fd1f83f82c4f05985fa739,82b4a061d4499c675fb8e92b7776c3f636837ce0..388ea78e6293685ebe5ad028fe063c8f55e33cc0
  struct nfs_context;
  struct rpc_context;
  
 +struct nfs_url {
 +      char *server;
 +      char *path;
 +      char *file;
 +};
 +
  #if defined(WIN32)
  #define EXTERN __declspec( dllexport )
  #else
@@@ -77,6 -71,7 +77,6 @@@ EXTERN int nfs_queue_length(struct 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.
   */
@@@ -111,49 -106,6 +111,49 @@@ EXTERN struct nfs_context *nfs_init_con
  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;
  
  /*
@@@ -217,8 -169,11 +217,11 @@@ EXTERN int nfs_stat_async(struct nfs_co
   *      0 : The operation was successfull.
   * -errno : The command failed.
   */
+ #ifdef WIN32
+ EXTERN int nfs_stat(struct nfs_context *nfs, const char *path, struct __stat64 *st);
+ #else
  EXTERN int nfs_stat(struct nfs_context *nfs, const char *path, struct stat *st);
+ #endif
  
  /*
   * FSTAT()
@@@ -242,7 -197,11 +245,11 @@@ EXTERN int nfs_fstat_async(struct nfs_c
   *      0 : The operation was successfull.
   * -errno : The command failed.
   */
+ #ifdef WIN32
+ EXTERN int nfs_fstat(struct nfs_context *nfs, struct nfsfh *nfsfh, struct __stat64 *st);
+ #else
  EXTERN int nfs_fstat(struct nfs_context *nfs, struct nfsfh *nfsfh, struct stat *st);
+ #endif
  
  
  
@@@ -690,16 -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
diff --combined lib/libnfs.c
index ed6cb2313e261351d7e3035f8ae51f3a14b65157,a1a62bb574dd7ef4cd8c7b280d5c6d09dea4048d..ca8ed379de8d529a9f3609e419fc740f629c37d3
@@@ -173,159 -173,6 +173,159 @@@ char *nfs_get_error(struct nfs_context 
        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;
@@@ -372,155 -219,6 +372,155 @@@ void nfs_destroy_context(struct nfs_con
        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) {
@@@ -577,7 -275,6 +577,7 @@@ static void nfs_mount_9_cb(struct rpc_c
        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);
  
        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;
@@@ -609,7 -303,6 +609,7 @@@ static void nfs_mount_8_cb(struct rpc_c
  {
        struct nfs_cb_data *data = private_data;
        struct nfs_context *nfs = data->nfs;
 +      struct FSINFO3args args;
  
        assert(rpc->magic == RPC_CONTEXT_MAGIC);
  
                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;
@@@ -654,7 -346,7 +654,7 @@@ static void nfs_mount_7_cb(struct rpc_c
                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;
@@@ -728,7 -420,7 +728,7 @@@ static void nfs_mount_5_cb(struct rpc_c
                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;
@@@ -756,7 -448,7 +756,7 @@@ static void nfs_mount_4_cb(struct rpc_c
                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;
@@@ -933,7 -625,6 +933,7 @@@ static void nfs_lookup_path_1_cb(struc
  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++;
                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);
@@@ -1027,7 -713,11 +1027,11 @@@ static void nfs_stat_1_cb(struct rpc_co
        GETATTR3res *res;
        struct nfs_cb_data *data = private_data;
        struct nfs_context *nfs = data->nfs;
+ #ifdef WIN32
+   struct __stat64 st;
+ #else
        struct stat st;
+ #endif
  
        assert(rpc->magic == RPC_CONTEXT_MAGIC);
  
  
  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);
@@@ -1176,7 -861,8 +1180,7 @@@ static void nfs_open_cb(struct rpc_cont
        }
  
        /* 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);
  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;
                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);
@@@ -1340,14 -1021,7 +1344,14 @@@ int nfs_pread_async(struct nfs_context 
        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);
  
        /* 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;
        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);
                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);
@@@ -1534,17 -1201,7 +1538,17 @@@ int nfs_pwrite_async(struct nfs_contex
        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);
  
        /* 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;
        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);
                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);
@@@ -1639,7 -1287,6 +1643,7 @@@ int nfs_close_async(struct nfs_context 
  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) {
        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);
@@@ -1702,7 -1346,6 +1706,7 @@@ static void nfs_fsync_cb(struct rpc_con
  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) {
        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);
@@@ -1779,11 -1419,12 +1783,11 @@@ int nfs_ftruncate_async(struct nfs_cont
        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);
@@@ -1801,7 -1442,8 +1805,7 @@@ static int nfs_truncate_continue_intern
        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);
@@@ -1875,12 -1517,13 +1879,12 @@@ static int nfs_mkdir_continue_internal(
        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);
@@@ -1960,13 -1603,10 +1964,13 @@@ static void nfs_rmdir_cb(struct rpc_con
  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);
@@@ -2064,7 -1704,6 +2068,7 @@@ static void nfs_creat_1_cb(struct rpc_c
        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);
  
        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);
@@@ -2109,13 -1744,14 +2113,13 @@@ static int nfs_creat_continue_internal(
        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);
@@@ -2194,13 -1830,10 +2198,13 @@@ static void nfs_unlink_cb(struct rpc_co
  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);
@@@ -2293,44 -1926,10 +2297,44 @@@ static int nfs_mknod_continue_internal(
  {
        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;
@@@ -2434,8 -2033,6 +2438,8 @@@ static void nfs_opendir3_cb(struct rpc_
                        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;
                }
        }
  
@@@ -2520,14 -2117,7 +2524,14 @@@ static void nfs_opendir2_cb(struct rpc_
        }
  
        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);
        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
@@@ -2594,14 -2179,9 +2598,14 @@@ static void nfs_opendir_cb(struct rpc_c
        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);
                        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;
        }
  
        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);
  
  static int nfs_opendir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
  {
 -      cookieverf3 cv;
 +      READDIRPLUS3args args;
  
 -      memset(cv, 0, sizeof(cookieverf3));
 -      if (rpc_nfs_readdirplus_async(nfs->rpc, nfs_opendir_cb, &data->fh, 0, (char *)&cv, 8192, data) != 0) {
 +      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);
@@@ -2807,7 -2373,6 +2811,7 @@@ static void nfs_lseek_1_cb(struct rpc_c
  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;
        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;
@@@ -2897,10 -2459,7 +2901,10 @@@ static void nfs_statvfs_1_cb(struct rpc
  
  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);
@@@ -2961,9 -2520,10 +2965,9 @@@ static int nfs_readlink_continue_intern
  {
        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);
@@@ -3024,11 -2584,12 +3028,11 @@@ static int nfs_chmod_continue_internal(
        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);
@@@ -3129,7 -2690,8 +3133,7 @@@ static int nfs_chown_continue_internal(
        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;
                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);
@@@ -3261,7 -2823,8 +3265,7 @@@ static int nfs_utimes_continue_internal
        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;
                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);
@@@ -3396,7 -2959,6 +3400,7 @@@ static void nfs_access_cb(struct rpc_co
  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;
                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);
@@@ -3493,16 -3051,17 +3497,16 @@@ static void nfs_symlink_cb(struct rpc_c
  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);
@@@ -3629,17 -3188,13 +3633,17 @@@ static void nfs_rename_cb(struct rpc_co
  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);
@@@ -3654,7 -3209,8 +3658,7 @@@ static int nfs_rename_continue_1_intern
        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) {
@@@ -3790,17 -3346,13 +3794,17 @@@ static void nfs_link_cb(struct rpc_cont
  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);
@@@ -3815,7 -3367,8 +3819,7 @@@ static int nfs_link_continue_1_internal
        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) {
@@@ -3897,7 -3450,11 +3901,7 @@@ uint64_t nfs_get_readmax(struct nfs_con
   */
  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, ...)
@@@ -3977,7 -3534,7 +3981,7 @@@ static void mount_export_4_cb(struct rp
                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;