Merge pull request #43 from plieven/master
authorRonnie Sahlberg <ronniesahlberg@gmail.com>
Thu, 26 Dec 2013 00:11:29 +0000 (16:11 -0800)
committerRonnie Sahlberg <ronniesahlberg@gmail.com>
Thu, 26 Dec 2013 00:11:29 +0000 (16:11 -0800)
URL parsing functions and minor fixes + enhancements

1  2 
examples/nfs-cp.c
lib/init.c
lib/libnfs.c

diff --combined examples/nfs-cp.c
index bedc9bb9ab525be3115ce72bdf1e65ab930e0624,62724dfefe4ed00c3dd1bcfb79b7726ef8e57d89..4456747059fc9c338b6fd55c2665a37847d1ec28
@@@ -59,6 -59,7 +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 +82,7 @@@ free_file_context(struct 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 +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) {
        file_context->nfs    = NULL;
        file_context->nfsfh  = NULL;
        
        if (strncmp(url, "nfs://", 6)) {
                file_context->is_nfs = 0;
                file_context->fd = open(url, flags, 0660);
                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 -260,7 +260,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 --combined lib/init.c
index 7f4a8db190649d19c4386842955cc6c9b4574382,df3c2aa2bd90cc25a7302907428c362648f7b85e..93d1db8b088b3780601d5251b63fb30d71a0e28e
@@@ -57,9 -57,7 +57,9 @@@ struct rpc_context *rpc_init_context(vo
        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);
        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;
  }
@@@ -102,6 -108,24 +110,24 @@@ void rpc_set_auth(struct rpc_context *r
        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, ...)
  {
diff --combined lib/libnfs.c
index e99c561054b116914727e868fba83a9f513e9ec4,e2c2c029354d49cdbae85188c66c580d7b3c4b53..b6bd822ebabf2eda89eef9b04ecee4a845055c91
@@@ -173,6 -173,152 +173,152 @@@ char *nfs_get_error(struct nfs_context 
        return rpc_get_error(nfs->rpc);
  };
  
+ 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;
+       }
+       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;
+               }
+       }
+       if (urls->server && strlen(urls->server) <= 1) {
+               free(urls->server);
+               urls->server = 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++;
+                       if (!strncmp(strp, "tcp-syncnt", 10)) {
+                               rpc_set_tcp_syncnt(nfs->rpc, atoi(strp2));
+                       } else if (!strncmp(strp, "uid", 3)) {
+                               rpc_set_uid(nfs->rpc, atoi(strp2));
+                       } else if (!strncmp(strp, "gid", 3)) {
+                               rpc_set_gid(nfs->rpc, atoi(strp2));
+                       }
+               }
+       }
+       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;
@@@ -424,7 -570,6 +570,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.data.data_len = nfs->rootfh.data.data_len; 
 +      args.object.data.data_val = nfs->rootfh.data.data_val; 
 +
 +      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;
@@@ -779,7 -920,6 +925,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.data.data_len = fh->data.data_len; 
 +      args.what.dir.data.data_val = fh->data.data_val; 
 +      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);
@@@ -925,13 -1059,7 +1071,13 @@@ static void nfs_stat_1_cb(struct rpc_co
  
  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.data_len = data->fh.data.data_len; 
 +      args.object.data.data_val = data->fh.data.data_val; 
 +
 +      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);
@@@ -1035,7 -1163,6 +1181,7 @@@ static void nfs_open_cb(struct rpc_cont
  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.data_len = data->fh.data.data_len;
 +      args.object.data.data_val = data->fh.data.data_val;
 +      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);
@@@ -1190,15 -1312,7 +1336,15 @@@ 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.data.data_len = nfsfh->fh.data.data_len;
 +              args.file.data.data_val = nfsfh->fh.data.data_val;
 +              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);
        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.data.data_len = nfsfh->fh.data.data_len;
 +              args.file.data.data_val = nfsfh->fh.data.data_val;
 +              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);
@@@ -1386,18 -1492,7 +1532,18 @@@ 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.data.data_len = nfsfh->fh.data.data_len;
 +              args.file.data.data_val = nfsfh->fh.data.data_val;
 +              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);
        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.data.data_len = nfsfh->fh.data.data_len;
 +              args.file.data.data_val = nfsfh->fh.data.data_val;
 +              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);
@@@ -1493,7 -1578,6 +1639,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.data.data_len = nfsfh->fh.data.data_len; 
 +      args.object.data.data_val = nfsfh->fh.data.data_val; 
 +
 +      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);
@@@ -1915,7 -1995,6 +2061,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);
  
                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.data_len = data->fh.data.data_len; 
 +      args.what.dir.data.data_val = data->fh.data.data_val; 
 +      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);
@@@ -2354,18 -2428,12 +2500,18 @@@ static void nfs_opendir2_cb(struct rpc_
        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.data_len = data->fh.data.data_len; 
 +              args.what.dir.data.data_val = data->fh.data.data_val; 
 +              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
@@@ -2596,7 -2664,6 +2742,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.data.data_len = nfsfh->fh.data.data_len; 
 +      args.object.data.data_val = nfsfh->fh.data.data_val; 
 +
 +      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;
@@@ -3187,7 -3250,6 +3333,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.data_len = data->fh.data.data_len;
 +      args.object.data.data_val = data->fh.data.data_val;
 +      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);