Merge pull request #32 from hulu/master
[deb_libnfs.git] / lib / libnfs.c
CommitLineData
84004dbf
RS
1/*
2 Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>.
16*/
17/*
18 * High level api to nfs filesystems
19 */
a8a1b858
M
20#ifdef WIN32
21#include "win32_compat.h"
6874f61e 22#define DllExport
6874f61e
RS
23#else
24#include <strings.h>
252aa90d 25#ifndef ANDROID
6874f61e 26#include <sys/statvfs.h>
252aa90d
CF
27#else
28#include <sys/vfs.h>
29#define statvfs statfs
30#endif
6874f61e
RS
31#include <utime.h>
32#include <unistd.h>
a8a1b858
M
33#endif/*WIN32*/
34
35#define _GNU_SOURCE
6874f61e 36
84004dbf 37#include <stdio.h>
1896d37b 38#include <stdarg.h>
84004dbf
RS
39#include <stdlib.h>
40#include <string.h>
f3a75078 41#include <assert.h>
84004dbf
RS
42#include <errno.h>
43#include <sys/types.h>
44#include <sys/stat.h>
84004dbf 45#include <fcntl.h>
763cd6e3
RS
46#include <netinet/in.h>
47#include "libnfs-zdr.h"
84004dbf
RS
48#include "libnfs.h"
49#include "libnfs-raw.h"
50#include "libnfs-raw-mount.h"
51#include "libnfs-raw-nfs.h"
1896d37b
RS
52#include "libnfs-private.h"
53
54struct nfsdir {
55 struct nfsdirent *entries;
56 struct nfsdirent *current;
57};
84004dbf
RS
58
59struct nfsfh {
60 struct nfs_fh3 fh;
61 int is_sync;
183451cf 62 uint64_t offset;
84004dbf
RS
63};
64
1896d37b
RS
65struct nfs_context {
66 struct rpc_context *rpc;
67 char *server;
68 char *export;
69 struct nfs_fh3 rootfh;
183451cf
RS
70 uint64_t readmax;
71 uint64_t writemax;
84004dbf
RS
72};
73
74void nfs_free_nfsdir(struct nfsdir *nfsdir)
75{
76 while (nfsdir->entries) {
77 struct nfsdirent *dirent = nfsdir->entries->next;
78 if (nfsdir->entries->name != NULL) {
79 free(nfsdir->entries->name);
80 }
81 free(nfsdir->entries);
82 nfsdir->entries = dirent;
83 }
84 free(nfsdir);
85}
86
84004dbf
RS
87struct nfs_cb_data;
88typedef int (*continue_func)(struct nfs_context *nfs, struct nfs_cb_data *data);
89
90struct nfs_cb_data {
91 struct nfs_context *nfs;
92 struct nfsfh *nfsfh;
93 char *saved_path, *path;
94
95 nfs_cb cb;
96 void *private_data;
97
98 continue_func continue_cb;
99 void *continue_data;
100 void (*free_continue_data)(void *);
101 int continue_int;
102
103 struct nfs_fh3 fh;
921f877b
RS
104
105 /* for multi-read/write calls. */
106 int error;
107 int cancel;
108 int num_calls;
183451cf 109 uint64_t start_offset, max_offset;
921f877b
RS
110 char *buffer;
111};
112
113struct nfs_mcb_data {
114 struct nfs_cb_data *data;
183451cf
RS
115 uint64_t offset;
116 uint64_t count;
84004dbf
RS
117};
118
119static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh);
120
121
67ba2239 122void nfs_set_auth(struct nfs_context *nfs, struct AUTH *auth)
84004dbf 123{
9896c715 124 rpc_set_auth(nfs->rpc, auth);
84004dbf
RS
125}
126
127int nfs_get_fd(struct nfs_context *nfs)
128{
129 return rpc_get_fd(nfs->rpc);
130}
131
83aa785d
RS
132int nfs_queue_length(struct nfs_context *nfs)
133{
134 return rpc_queue_length(nfs->rpc);
135}
136
84004dbf
RS
137int nfs_which_events(struct nfs_context *nfs)
138{
139 return rpc_which_events(nfs->rpc);
140}
141
142int nfs_service(struct nfs_context *nfs, int revents)
143{
144 return rpc_service(nfs->rpc, revents);
145}
146
147char *nfs_get_error(struct nfs_context *nfs)
148{
149 return rpc_get_error(nfs->rpc);
150};
151
152struct nfs_context *nfs_init_context(void)
153{
154 struct nfs_context *nfs;
155
156 nfs = malloc(sizeof(struct nfs_context));
157 if (nfs == NULL) {
84004dbf
RS
158 return NULL;
159 }
160 nfs->rpc = rpc_init_context();
161 if (nfs->rpc == NULL) {
84004dbf
RS
162 free(nfs);
163 return NULL;
164 }
165
b077fdeb
RS
166 nfs->server = NULL;
167 nfs->export = NULL;
168
963c2f83
RS
169 nfs->rootfh.data.data_len = 0;
170 nfs->rootfh.data.data_val = NULL;
171
84004dbf
RS
172 return nfs;
173}
174
175void nfs_destroy_context(struct nfs_context *nfs)
176{
177 rpc_destroy_context(nfs->rpc);
178 nfs->rpc = NULL;
179
180 if (nfs->server) {
181 free(nfs->server);
182 nfs->server = NULL;
183 }
184
185 if (nfs->export) {
186 free(nfs->export);
187 nfs->export = NULL;
188 }
189
190 if (nfs->rootfh.data.data_val != NULL) {
191 free(nfs->rootfh.data.data_val);
192 nfs->rootfh.data.data_val = NULL;
193 }
194
195 free(nfs);
196}
197
198void free_nfs_cb_data(struct nfs_cb_data *data)
199{
200 if (data->saved_path != NULL) {
201 free(data->saved_path);
202 data->saved_path = NULL;
203 }
204
205 if (data->continue_data != NULL) {
206 data->free_continue_data(data->continue_data);
207 data->continue_data = NULL;
208 }
209
210 if (data->fh.data.data_val != NULL) {
211 free(data->fh.data.data_val);
212 data->fh.data.data_val = NULL;
213 }
214
921f877b
RS
215 if (data->buffer != NULL) {
216 free(data->buffer);
217 data->buffer = NULL;
218 }
219
84004dbf
RS
220 free(data);
221}
222
223
224
225
226
f3a75078 227static void nfs_mount_10_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
228{
229 struct nfs_cb_data *data = private_data;
230 struct nfs_context *nfs = data->nfs;
231
f3a75078
RS
232 assert(rpc->magic == RPC_CONTEXT_MAGIC);
233
84004dbf
RS
234 if (status == RPC_STATUS_ERROR) {
235 data->cb(-EFAULT, nfs, command_data, data->private_data);
236 free_nfs_cb_data(data);
237 return;
238 }
239 if (status == RPC_STATUS_CANCEL) {
240 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
241 free_nfs_cb_data(data);
242 return;
243 }
244
245 data->cb(0, nfs, NULL, data->private_data);
246 free_nfs_cb_data(data);
247}
248
17ef62fa 249static void nfs_mount_9_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
250{
251 struct nfs_cb_data *data = private_data;
252 struct nfs_context *nfs = data->nfs;
17ef62fa 253 FSINFO3res *res = command_data;
84004dbf 254
f3a75078
RS
255 assert(rpc->magic == RPC_CONTEXT_MAGIC);
256
84004dbf
RS
257 if (status == RPC_STATUS_ERROR) {
258 data->cb(-EFAULT, nfs, command_data, data->private_data);
259 free_nfs_cb_data(data);
260 return;
261 }
262 if (status == RPC_STATUS_CANCEL) {
263 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
264 free_nfs_cb_data(data);
265 return;
266 }
267
17ef62fa
RS
268 nfs->readmax = res->FSINFO3res_u.resok.rtmax;
269 nfs->writemax = res->FSINFO3res_u.resok.wtmax;
84004dbf 270
17ef62fa 271 if (rpc_nfs_getattr_async(rpc, nfs_mount_10_cb, &nfs->rootfh, data) != 0) {
84004dbf
RS
272 data->cb(-ENOMEM, nfs, command_data, data->private_data);
273 free_nfs_cb_data(data);
274 return;
275 }
276}
277
17ef62fa
RS
278static void nfs_mount_8_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
279{
280 struct nfs_cb_data *data = private_data;
281 struct nfs_context *nfs = data->nfs;
282
f3a75078
RS
283 assert(rpc->magic == RPC_CONTEXT_MAGIC);
284
17ef62fa
RS
285 if (status == RPC_STATUS_ERROR) {
286 data->cb(-EFAULT, nfs, command_data, data->private_data);
287 free_nfs_cb_data(data);
288 return;
289 }
290 if (status == RPC_STATUS_CANCEL) {
291 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
292 free_nfs_cb_data(data);
293 return;
294 }
295
296 if (rpc_nfs_fsinfo_async(rpc, nfs_mount_9_cb, &nfs->rootfh, data) != 0) {
297 data->cb(-ENOMEM, nfs, command_data, data->private_data);
298 free_nfs_cb_data(data);
299 return;
300 }
301}
302
303
84004dbf
RS
304static void nfs_mount_7_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
305{
306 struct nfs_cb_data *data = private_data;
307 struct nfs_context *nfs = data->nfs;
308
f3a75078
RS
309 assert(rpc->magic == RPC_CONTEXT_MAGIC);
310
14a062eb
RS
311 /* Dont want any more callbacks even if the socket is closed */
312 rpc->connect_cb = NULL;
313
84004dbf
RS
314 if (status == RPC_STATUS_ERROR) {
315 data->cb(-EFAULT, nfs, command_data, data->private_data);
316 free_nfs_cb_data(data);
317 return;
318 }
319 if (status == RPC_STATUS_CANCEL) {
320 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
321 free_nfs_cb_data(data);
322 return;
323 }
324
325 if (rpc_nfs_null_async(rpc, nfs_mount_8_cb, data) != 0) {
326 data->cb(-ENOMEM, nfs, command_data, data->private_data);
327 free_nfs_cb_data(data);
328 return;
329 }
330}
331
332
333static void nfs_mount_6_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
334{
335 struct nfs_cb_data *data = private_data;
336 struct nfs_context *nfs = data->nfs;
337 mountres3 *res;
338
f3a75078
RS
339 assert(rpc->magic == RPC_CONTEXT_MAGIC);
340
84004dbf
RS
341 if (status == RPC_STATUS_ERROR) {
342 data->cb(-EFAULT, nfs, command_data, data->private_data);
343 free_nfs_cb_data(data);
344 return;
345 }
346 if (status == RPC_STATUS_CANCEL) {
347 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
348 free_nfs_cb_data(data);
349 return;
350 }
351
352 res = command_data;
353 if (res->fhs_status != MNT3_OK) {
354 rpc_set_error(rpc, "RPC error: Mount failed with error %s(%d) %s(%d)", mountstat3_to_str(res->fhs_status), res->fhs_status, strerror(-mountstat3_to_errno(res->fhs_status)), -mountstat3_to_errno(res->fhs_status));
355 data->cb(mountstat3_to_errno(res->fhs_status), nfs, rpc_get_error(rpc), data->private_data);
356 free_nfs_cb_data(data);
357 return;
358 }
359
360 nfs->rootfh.data.data_len = res->mountres3_u.mountinfo.fhandle.fhandle3_len;
361 nfs->rootfh.data.data_val = malloc(nfs->rootfh.data.data_len);
362 if (nfs->rootfh.data.data_val == NULL) {
363 rpc_set_error(rpc, "Out of memory. Could not allocate memory to store root filehandle");
364 data->cb(-ENOMEM, nfs, rpc_get_error(rpc), data->private_data);
365 free_nfs_cb_data(data);
366 return;
367 }
368 memcpy(nfs->rootfh.data.data_val, res->mountres3_u.mountinfo.fhandle.fhandle3_val, nfs->rootfh.data.data_len);
369
370 rpc_disconnect(rpc, "normal disconnect");
371 if (rpc_connect_async(rpc, nfs->server, 2049, nfs_mount_7_cb, data) != 0) {
372 data->cb(-ENOMEM, nfs, command_data, data->private_data);
373 free_nfs_cb_data(data);
374 return;
375 }
1744ef90
RS
376 /* NFS TCP connections we want to autoreconnect after sessions are torn down (due to inactivity or error) */
377 rpc_set_autoreconnect(rpc);
84004dbf
RS
378}
379
380
381static void nfs_mount_5_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
382{
383 struct nfs_cb_data *data = private_data;
384 struct nfs_context *nfs = data->nfs;
385
f3a75078
RS
386 assert(rpc->magic == RPC_CONTEXT_MAGIC);
387
84004dbf
RS
388 if (status == RPC_STATUS_ERROR) {
389 data->cb(-EFAULT, nfs, command_data, data->private_data);
390 free_nfs_cb_data(data);
391 return;
392 }
393 if (status == RPC_STATUS_CANCEL) {
394 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
395 free_nfs_cb_data(data);
396 return;
397 }
398
399 if (rpc_mount_mnt_async(rpc, nfs_mount_6_cb, nfs->export, data) != 0) {
400 data->cb(-ENOMEM, nfs, command_data, data->private_data);
401 free_nfs_cb_data(data);
402 return;
403 }
404}
405
406static void nfs_mount_4_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
407{
408 struct nfs_cb_data *data = private_data;
409 struct nfs_context *nfs = data->nfs;
410
f3a75078
RS
411 assert(rpc->magic == RPC_CONTEXT_MAGIC);
412
14a062eb
RS
413 /* Dont want any more callbacks even if the socket is closed */
414 rpc->connect_cb = NULL;
415
84004dbf
RS
416 if (status == RPC_STATUS_ERROR) {
417 data->cb(-EFAULT, nfs, command_data, data->private_data);
418 free_nfs_cb_data(data);
419 return;
420 }
421 if (status == RPC_STATUS_CANCEL) {
422 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
423 free_nfs_cb_data(data);
424 return;
425 }
426
427 if (rpc_mount_null_async(rpc, nfs_mount_5_cb, data) != 0) {
428 data->cb(-ENOMEM, nfs, command_data, data->private_data);
429 free_nfs_cb_data(data);
430 return;
431 }
432}
433
434static void nfs_mount_3_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
435{
436 struct nfs_cb_data *data = private_data;
437 struct nfs_context *nfs = data->nfs;
438 uint32_t mount_port;
439
f3a75078
RS
440 assert(rpc->magic == RPC_CONTEXT_MAGIC);
441
84004dbf
RS
442 if (status == RPC_STATUS_ERROR) {
443 data->cb(-EFAULT, nfs, command_data, data->private_data);
444 free_nfs_cb_data(data);
445 return;
446 }
447 if (status == RPC_STATUS_CANCEL) {
448 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
449 free_nfs_cb_data(data);
450 return;
451 }
452
453 mount_port = *(uint32_t *)command_data;
454 if (mount_port == 0) {
455 rpc_set_error(rpc, "RPC error. Mount program is not available on %s", nfs->server);
456 data->cb(-ENOENT, nfs, command_data, data->private_data);
457 free_nfs_cb_data(data);
458 return;
459 }
460
461 rpc_disconnect(rpc, "normal disconnect");
462 if (rpc_connect_async(rpc, nfs->server, mount_port, nfs_mount_4_cb, data) != 0) {
463 data->cb(-ENOMEM, nfs, command_data, data->private_data);
464 free_nfs_cb_data(data);
465 return;
466 }
467}
468
469
470static void nfs_mount_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
471{
472 struct nfs_cb_data *data = private_data;
473 struct nfs_context *nfs = data->nfs;
474
f3a75078
RS
475 assert(rpc->magic == RPC_CONTEXT_MAGIC);
476
84004dbf
RS
477 if (status == RPC_STATUS_ERROR) {
478 data->cb(-EFAULT, nfs, command_data, data->private_data);
479 free_nfs_cb_data(data);
480 return;
481 }
482 if (status == RPC_STATUS_CANCEL) {
483 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
484 free_nfs_cb_data(data);
485 return;
486 }
487
5c6b1176 488 if (rpc_pmap_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, IPPROTO_TCP, nfs_mount_3_cb, private_data) != 0) {
84004dbf
RS
489 data->cb(-ENOMEM, nfs, command_data, data->private_data);
490 free_nfs_cb_data(data);
491 return;
492 }
493}
494
495static void nfs_mount_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
496{
497 struct nfs_cb_data *data = private_data;
498 struct nfs_context *nfs = data->nfs;
499
f3a75078
RS
500 assert(rpc->magic == RPC_CONTEXT_MAGIC);
501
14a062eb
RS
502 /* Dont want any more callbacks even if the socket is closed */
503 rpc->connect_cb = NULL;
504
84004dbf
RS
505 if (status == RPC_STATUS_ERROR) {
506 data->cb(-EFAULT, nfs, command_data, data->private_data);
507 free_nfs_cb_data(data);
508 return;
509 }
510 if (status == RPC_STATUS_CANCEL) {
511 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
512 free_nfs_cb_data(data);
513 return;
514 }
515
516 if (rpc_pmap_null_async(rpc, nfs_mount_2_cb, data) != 0) {
517 data->cb(-ENOMEM, nfs, command_data, data->private_data);
518 free_nfs_cb_data(data);
519 return;
520 }
521}
522
523/*
524 * Async call for mounting an nfs share and geting the root filehandle
525 */
526int nfs_mount_async(struct nfs_context *nfs, const char *server, const char *export, nfs_cb cb, void *private_data)
527{
528 struct nfs_cb_data *data;
b077fdeb 529 char *new_server, *new_export;
84004dbf
RS
530
531 data = malloc(sizeof(struct nfs_cb_data));
532 if (data == NULL) {
cbbf9d3e 533 rpc_set_error(nfs->rpc, "out of memory. failed to allocate memory for nfs mount data");
84004dbf
RS
534 return -1;
535 }
ea98629a 536 memset(data, 0, sizeof(struct nfs_cb_data));
b077fdeb
RS
537 new_server = strdup(server);
538 new_export = strdup(export);
539 if (nfs->server != NULL) {
540 free(nfs->server);
b077fdeb
RS
541 }
542 nfs->server = new_server;
543 if (nfs->export != NULL) {
544 free(nfs->export);
b077fdeb
RS
545 }
546 nfs->export = new_export;
84004dbf
RS
547 data->nfs = nfs;
548 data->cb = cb;
549 data->private_data = private_data;
550
551 if (rpc_connect_async(nfs->rpc, server, 111, nfs_mount_1_cb, data) != 0) {
cbbf9d3e 552 rpc_set_error(nfs->rpc, "Failed to start connection");
84004dbf 553 free_nfs_cb_data(data);
cbbf9d3e 554 return -1;
84004dbf
RS
555 }
556
557 return 0;
558}
559
560
561
562/*
563 * Functions to first look up a path, component by component, and then finally call a specific function once
564 * the filehandle for the final component is found.
565 */
f3a75078 566static void nfs_lookup_path_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
567{
568 struct nfs_cb_data *data = private_data;
569 struct nfs_context *nfs = data->nfs;
570 LOOKUP3res *res;
571
f3a75078
RS
572 assert(rpc->magic == RPC_CONTEXT_MAGIC);
573
84004dbf
RS
574 if (status == RPC_STATUS_ERROR) {
575 data->cb(-EFAULT, nfs, command_data, data->private_data);
576 free_nfs_cb_data(data);
577 return;
578 }
579 if (status == RPC_STATUS_CANCEL) {
580 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
581 free_nfs_cb_data(data);
582 return;
583 }
584
585 res = command_data;
586 if (res->status != NFS3_OK) {
587 rpc_set_error(nfs->rpc, "NFS: Lookup of %s failed with %s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
588 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
589 free_nfs_cb_data(data);
590 return;
591 }
592
593 if (nfs_lookup_path_async_internal(nfs, data, &res->LOOKUP3res_u.resok.object) != 0) {
594 rpc_set_error(nfs->rpc, "Failed to create lookup pdu");
595 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
596 free_nfs_cb_data(data);
597 return;
598 }
599}
600
601static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh)
602{
603 char *path, *str;
604
605 while (*data->path == '/') {
606 data->path++;
607 }
608
609 path = data->path;
93e9306f 610 str = strchr(path, '/');
84004dbf
RS
611 if (str != NULL) {
612 *str = 0;
613 data->path = str+1;
614 } else {
615 while (*data->path != 0) {
616 data->path++;
617 }
618 }
619
620 if (*path == 0) {
621 data->fh.data.data_len = fh->data.data_len;
622 data->fh.data.data_val = malloc(data->fh.data.data_len);
623 if (data->fh.data.data_val == NULL) {
624 rpc_set_error(nfs->rpc, "Out of memory: Failed to allocate fh for %s", data->path);
625 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
626 free_nfs_cb_data(data);
627 return -1;
628 }
629 memcpy(data->fh.data.data_val, fh->data.data_val, data->fh.data.data_len);
630 data->continue_cb(nfs, data);
631 return 0;
632 }
633
634 if (rpc_nfs_lookup_async(nfs->rpc, nfs_lookup_path_1_cb, fh, path, data) != 0) {
635 rpc_set_error(nfs->rpc, "RPC error: Failed to send lookup call for %s", data->path);
636 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
637 free_nfs_cb_data(data);
638 return -1;
639 }
640 return 0;
641}
642
643static int nfs_lookuppath_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data, continue_func continue_cb, void *continue_data, void (*free_continue_data)(void *), int continue_int)
644{
645 struct nfs_cb_data *data;
646
647 if (path[0] != '/') {
648 rpc_set_error(nfs->rpc, "Pathname is not absulute %s", path);
649 return -1;
650 }
651
652 data = malloc(sizeof(struct nfs_cb_data));
653 if (data == NULL) {
654 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
cbbf9d3e 655 return -1;
84004dbf 656 }
ea98629a 657 memset(data, 0, sizeof(struct nfs_cb_data));
84004dbf
RS
658 data->nfs = nfs;
659 data->cb = cb;
660 data->continue_cb = continue_cb;
661 data->continue_data = continue_data;
662 data->free_continue_data = free_continue_data;
663 data->continue_int = continue_int;
664 data->private_data = private_data;
665 data->saved_path = strdup(path);
666 if (data->saved_path == NULL) {
667 rpc_set_error(nfs->rpc, "out of memory: failed to copy path string");
84004dbf 668 free_nfs_cb_data(data);
cbbf9d3e 669 return -1;
84004dbf
RS
670 }
671 data->path = data->saved_path;
672
673 if (nfs_lookup_path_async_internal(nfs, data, &nfs->rootfh) != 0) {
84004dbf
RS
674 /* return 0 here since the callback will be invoked if there is a failure */
675 return 0;
676 }
677 return 0;
678}
679
680
681
682
683
684/*
685 * Async stat()
686 */
f3a75078 687static void nfs_stat_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
688{
689 GETATTR3res *res;
690 struct nfs_cb_data *data = private_data;
691 struct nfs_context *nfs = data->nfs;
692 struct stat st;
693
f3a75078
RS
694 assert(rpc->magic == RPC_CONTEXT_MAGIC);
695
84004dbf
RS
696 if (status == RPC_STATUS_ERROR) {
697 data->cb(-EFAULT, nfs, command_data, data->private_data);
698 free_nfs_cb_data(data);
699 return;
700 }
701 if (status == RPC_STATUS_CANCEL) {
702 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
703 free_nfs_cb_data(data);
704 return;
705 }
706
707 res = command_data;
708 if (res->status != NFS3_OK) {
709 rpc_set_error(nfs->rpc, "NFS: GETATTR of %s failed with %s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
710 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
711 free_nfs_cb_data(data);
712 return;
713 }
714
715 st.st_dev = -1;
716 st.st_ino = res->GETATTR3res_u.resok.obj_attributes.fileid;
717 st.st_mode = res->GETATTR3res_u.resok.obj_attributes.mode;
e8cab72a
RS
718 if (res->GETATTR3res_u.resok.obj_attributes.type == NF3DIR) {
719 st.st_mode |= S_IFDIR ;
720 }
d7ec001f
RS
721 if (res->GETATTR3res_u.resok.obj_attributes.type == NF3REG) {
722 st.st_mode |= S_IFREG ;
723 }
84004dbf
RS
724 st.st_nlink = res->GETATTR3res_u.resok.obj_attributes.nlink;
725 st.st_uid = res->GETATTR3res_u.resok.obj_attributes.uid;
726 st.st_gid = res->GETATTR3res_u.resok.obj_attributes.gid;
727 st.st_rdev = 0;
728 st.st_size = res->GETATTR3res_u.resok.obj_attributes.size;
a8a1b858 729#ifndef WIN32
84004dbf
RS
730 st.st_blksize = 4096;
731 st.st_blocks = res->GETATTR3res_u.resok.obj_attributes.size / 4096;
a8a1b858 732#endif//WIN32
84004dbf
RS
733 st.st_atime = res->GETATTR3res_u.resok.obj_attributes.atime.seconds;
734 st.st_mtime = res->GETATTR3res_u.resok.obj_attributes.mtime.seconds;
735 st.st_ctime = res->GETATTR3res_u.resok.obj_attributes.ctime.seconds;
736
737 data->cb(0, nfs, &st, data->private_data);
738 free_nfs_cb_data(data);
739}
740
741static int nfs_stat_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
742{
743 if (rpc_nfs_getattr_async(nfs->rpc, nfs_stat_1_cb, &data->fh, data) != 0) {
744 rpc_set_error(nfs->rpc, "RPC error: Failed to send STAT GETATTR call for %s", data->path);
745 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
746 free_nfs_cb_data(data);
747 return -1;
748 }
749 return 0;
750}
751
752int nfs_stat_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
753{
754 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_stat_continue_internal, NULL, NULL, 0) != 0) {
cbbf9d3e 755 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
84004dbf
RS
756 return -1;
757 }
758
759 return 0;
760}
761
762
763
764
765
766/*
767 * Async open()
768 */
f3a75078 769static void nfs_open_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
770{
771 ACCESS3res *res;
772 struct nfs_cb_data *data = private_data;
773 struct nfs_context *nfs = data->nfs;
774 struct nfsfh *nfsfh;
775 unsigned int nfsmode = 0;
776
f3a75078
RS
777 assert(rpc->magic == RPC_CONTEXT_MAGIC);
778
84004dbf
RS
779 if (status == RPC_STATUS_ERROR) {
780 data->cb(-EFAULT, nfs, command_data, data->private_data);
781 free_nfs_cb_data(data);
782 return;
783 }
784 if (status == RPC_STATUS_CANCEL) {
785 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
786 free_nfs_cb_data(data);
787 return;
788 }
789
790 res = command_data;
791 if (res->status != NFS3_OK) {
792 rpc_set_error(nfs->rpc, "NFS: ACCESS of %s failed with %s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
793 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
794 free_nfs_cb_data(data);
795 return;
796 }
797
798 if (data->continue_int & O_WRONLY) {
799 nfsmode |= ACCESS3_MODIFY;
800 }
801 if (data->continue_int & O_RDWR) {
802 nfsmode |= ACCESS3_READ|ACCESS3_MODIFY;
803 }
804 if (!(data->continue_int & (O_WRONLY|O_RDWR))) {
805 nfsmode |= ACCESS3_READ;
806 }
807
808
809 if (res->ACCESS3res_u.resok.access != nfsmode) {
810 rpc_set_error(nfs->rpc, "NFS: ACCESS denied. Required access %c%c%c. Allowed access %c%c%c",
811 nfsmode&ACCESS3_READ?'r':'-',
812 nfsmode&ACCESS3_MODIFY?'w':'-',
813 nfsmode&ACCESS3_EXECUTE?'x':'-',
814 res->ACCESS3res_u.resok.access&ACCESS3_READ?'r':'-',
815 res->ACCESS3res_u.resok.access&ACCESS3_MODIFY?'w':'-',
816 res->ACCESS3res_u.resok.access&ACCESS3_EXECUTE?'x':'-');
817 data->cb(-EACCES, nfs, rpc_get_error(nfs->rpc), data->private_data);
818 free_nfs_cb_data(data);
819 return;
820 }
821
822 nfsfh = malloc(sizeof(struct nfsfh));
823 if (nfsfh == NULL) {
824 rpc_set_error(nfs->rpc, "NFS: Failed to allocate nfsfh structure");
825 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
826 free_nfs_cb_data(data);
827 return;
828 }
ea98629a 829 memset(nfsfh, 0, sizeof(struct nfsfh));
84004dbf
RS
830
831 if (data->continue_int & O_SYNC) {
832 nfsfh->is_sync = 1;
833 }
834
835 /* steal the filehandle */
836 nfsfh->fh.data.data_len = data->fh.data.data_len;
837 nfsfh->fh.data.data_val = data->fh.data.data_val;
838 data->fh.data.data_val = NULL;
839
840 data->cb(0, nfs, nfsfh, data->private_data);
841 free_nfs_cb_data(data);
842}
843
844static int nfs_open_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
845{
846 int nfsmode = 0;
847
848 if (data->continue_int & O_WRONLY) {
849 nfsmode |= ACCESS3_MODIFY;
850 }
851 if (data->continue_int & O_RDWR) {
852 nfsmode |= ACCESS3_READ|ACCESS3_MODIFY;
853 }
854 if (!(data->continue_int & (O_WRONLY|O_RDWR))) {
855 nfsmode |= ACCESS3_READ;
856 }
857
858 if (rpc_nfs_access_async(nfs->rpc, nfs_open_cb, &data->fh, nfsmode, data) != 0) {
859 rpc_set_error(nfs->rpc, "RPC error: Failed to send OPEN ACCESS call for %s", data->path);
860 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
861 free_nfs_cb_data(data);
862 return -1;
863 }
864 return 0;
865}
866
867int nfs_open_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data)
868{
869 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_open_continue_internal, NULL, NULL, mode) != 0) {
cbbf9d3e
RS
870 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
871 return -1;
84004dbf
RS
872 }
873
874 return 0;
875}
876
877
878
879
880
881/*
882 * Async pread()
883 */
f3a75078 884static void nfs_pread_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
885{
886 struct nfs_cb_data *data = private_data;
887 struct nfs_context *nfs = data->nfs;
888 READ3res *res;
889
f3a75078
RS
890 assert(rpc->magic == RPC_CONTEXT_MAGIC);
891
84004dbf
RS
892 if (status == RPC_STATUS_ERROR) {
893 data->cb(-EFAULT, nfs, command_data, data->private_data);
894 free_nfs_cb_data(data);
895 return;
896 }
897 if (status == RPC_STATUS_CANCEL) {
898 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
899 free_nfs_cb_data(data);
900 return;
901 }
902
903 res = command_data;
904 if (res->status != NFS3_OK) {
905 rpc_set_error(nfs->rpc, "NFS: Read failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
906 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
907 free_nfs_cb_data(data);
908 return;
909 }
910
911 data->nfsfh->offset += res->READ3res_u.resok.count;
912 data->cb(res->READ3res_u.resok.count, nfs, res->READ3res_u.resok.data.data_val, data->private_data);
913 free_nfs_cb_data(data);
914}
915
f3a75078 916static void nfs_pread_mcb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
921f877b
RS
917{
918 struct nfs_mcb_data *mdata = private_data;
919 struct nfs_cb_data *data = mdata->data;
920 struct nfs_context *nfs = data->nfs;
921 READ3res *res;
922
f3a75078
RS
923 assert(rpc->magic == RPC_CONTEXT_MAGIC);
924
921f877b
RS
925 data->num_calls--;
926
927 if (status == RPC_STATUS_ERROR) {
928 /* flag the failure but do not invoke callback until we have received all responses */
929 data->error = 1;
930 }
931 if (status == RPC_STATUS_CANCEL) {
932 /* flag the cancellation but do not invoke callback until we have received all responses */
933 data->cancel = 1;
934 }
935
936 /* reassemble the data into the buffer */
937 if (status == RPC_STATUS_SUCCESS) {
938 res = command_data;
939 if (res->status != NFS3_OK) {
940 rpc_set_error(nfs->rpc, "NFS: Read failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
941 data->error = 1;
e4a5ba42
RS
942 } else {
943 if (res->READ3res_u.resok.count > 0) {
944 memcpy(&data->buffer[mdata->offset - data->start_offset], res->READ3res_u.resok.data.data_val, res->READ3res_u.resok.count);
945 if ((unsigned)data->max_offset < mdata->offset + res->READ3res_u.resok.count) {
946 data->max_offset = mdata->offset + res->READ3res_u.resok.count;
947 }
921f877b
RS
948 }
949 }
950 }
951
952 if (data->num_calls > 0) {
953 /* still waiting for more replies */
954 free(mdata);
955 return;
956 }
957
921f877b
RS
958 if (data->error != 0) {
959 data->cb(-EFAULT, nfs, command_data, data->private_data);
960 free_nfs_cb_data(data);
961 free(mdata);
962 return;
963 }
964 if (data->cancel != 0) {
965 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
966 free_nfs_cb_data(data);
967 free(mdata);
968 return;
969 }
970
971 data->nfsfh->offset = data->max_offset;
7ed9d87a
RS
972 data->cb(data->max_offset - data->start_offset, nfs, data->buffer, data->private_data);
973
921f877b
RS
974 free_nfs_cb_data(data);
975 free(mdata);
976}
977
183451cf 978int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, nfs_cb cb, void *private_data)
84004dbf
RS
979{
980 struct nfs_cb_data *data;
981
982 data = malloc(sizeof(struct nfs_cb_data));
983 if (data == NULL) {
984 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
84004dbf
RS
985 return -1;
986 }
ea98629a 987 memset(data, 0, sizeof(struct nfs_cb_data));
84004dbf
RS
988 data->nfs = nfs;
989 data->cb = cb;
990 data->private_data = private_data;
991 data->nfsfh = nfsfh;
992
993 nfsfh->offset = offset;
921f877b
RS
994
995 if (count <= nfs_get_readmax(nfs)) {
996 if (rpc_nfs_read_async(nfs->rpc, nfs_pread_cb, &nfsfh->fh, offset, count, data) != 0) {
997 rpc_set_error(nfs->rpc, "RPC error: Failed to send READ call for %s", data->path);
998 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
999 free_nfs_cb_data(data);
1000 return -1;
1001 }
1002 return 0;
1003 }
1004
1005 /* trying to read more than maximum server read size, we has to chop it up into smaller
1006 * reads and collect into a reassembly buffer.
1007 * we send all reads in parallell so that performance is still good.
1008 */
7ed9d87a 1009 data->max_offset = offset;
921f877b
RS
1010 data->start_offset = offset;
1011
1012 data->buffer = malloc(count);
1013 if (data->buffer == NULL) {
1014 rpc_set_error(nfs->rpc, "Out-Of-Memory: Failed to allocate reassembly buffer for %d bytes", (int)count);
84004dbf
RS
1015 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1016 free_nfs_cb_data(data);
1017 return -1;
1018 }
921f877b
RS
1019
1020 while (count > 0) {
183451cf 1021 uint64_t readcount = count;
921f877b
RS
1022 struct nfs_mcb_data *mdata;
1023
1024 if (readcount > nfs_get_readmax(nfs)) {
1025 readcount = nfs_get_readmax(nfs);
1026 }
1027
1028 mdata = malloc(sizeof(struct nfs_mcb_data));
1029 if (mdata == NULL) {
1030 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_mcb_data structure");
921f877b
RS
1031 return -1;
1032 }
ea98629a 1033 memset(mdata, 0, sizeof(struct nfs_mcb_data));
921f877b
RS
1034 mdata->data = data;
1035 mdata->offset = offset;
1036 mdata->count = readcount;
921f877b
RS
1037 if (rpc_nfs_read_async(nfs->rpc, nfs_pread_mcb, &nfsfh->fh, offset, readcount, mdata) != 0) {
1038 rpc_set_error(nfs->rpc, "RPC error: Failed to send READ call for %s", data->path);
1039 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1040 free(mdata);
1041 return -1;
1042 }
1043
1044 count -= readcount;
1045 offset += readcount;
1046 data->num_calls++;
1047 }
1048
1049 return 0;
84004dbf
RS
1050}
1051
1052/*
1053 * Async read()
1054 */
183451cf 1055int nfs_read_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, nfs_cb cb, void *private_data)
84004dbf
RS
1056{
1057 return nfs_pread_async(nfs, nfsfh, nfsfh->offset, count, cb, private_data);
1058}
1059
1060
1061
1062/*
1063 * Async pwrite()
1064 */
f3a75078 1065static void nfs_pwrite_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
1066{
1067 struct nfs_cb_data *data = private_data;
1068 struct nfs_context *nfs = data->nfs;
1069 WRITE3res *res;
1070
f3a75078
RS
1071 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1072
84004dbf
RS
1073 if (status == RPC_STATUS_ERROR) {
1074 data->cb(-EFAULT, nfs, command_data, data->private_data);
1075 free_nfs_cb_data(data);
1076 return;
1077 }
1078 if (status == RPC_STATUS_CANCEL) {
1079 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1080 free_nfs_cb_data(data);
1081 return;
1082 }
1083
1084 res = command_data;
1085 if (res->status != NFS3_OK) {
1086 rpc_set_error(nfs->rpc, "NFS: Write failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1087 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1088 free_nfs_cb_data(data);
1089 return;
1090 }
1091
1092 data->nfsfh->offset += res->WRITE3res_u.resok.count;
1093 data->cb(res->WRITE3res_u.resok.count, nfs, NULL, data->private_data);
1094 free_nfs_cb_data(data);
1095}
1096
f3a75078 1097static void nfs_pwrite_mcb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
18c27b73
RS
1098{
1099 struct nfs_mcb_data *mdata = private_data;
1100 struct nfs_cb_data *data = mdata->data;
1101 struct nfs_context *nfs = data->nfs;
1102 WRITE3res *res;
1103
f3a75078
RS
1104 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1105
18c27b73
RS
1106 data->num_calls--;
1107
1108 if (status == RPC_STATUS_ERROR) {
1109 /* flag the failure but do not invoke callback until we have received all responses */
1110 data->error = 1;
1111 }
1112 if (status == RPC_STATUS_CANCEL) {
1113 /* flag the cancellation but do not invoke callback until we have received all responses */
1114 data->cancel = 1;
1115 }
1116
1117 if (status == RPC_STATUS_SUCCESS) {
1118 res = command_data;
1119 if (res->status != NFS3_OK) {
1120 rpc_set_error(nfs->rpc, "NFS: Write failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1121 data->error = 1;
1122 } else {
1123 if (res->WRITE3res_u.resok.count > 0) {
1124 if ((unsigned)data->max_offset < mdata->offset + res->WRITE3res_u.resok.count) {
1125 data->max_offset = mdata->offset + res->WRITE3res_u.resok.count;
1126 }
1127 }
1128 }
1129 }
1130
1131 if (data->num_calls > 0) {
1132 /* still waiting for more replies */
1133 free(mdata);
1134 return;
1135 }
1136
1137 if (data->error != 0) {
1138 data->cb(-EFAULT, nfs, command_data, data->private_data);
1139 free_nfs_cb_data(data);
1140 free(mdata);
1141 return;
1142 }
1143 if (data->cancel != 0) {
1144 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1145 free_nfs_cb_data(data);
1146 free(mdata);
1147 return;
1148 }
1149
1150 data->nfsfh->offset = data->max_offset;
1151 data->cb(data->max_offset - data->start_offset, nfs, NULL, data->private_data);
1152
1153 free_nfs_cb_data(data);
1154 free(mdata);
1155}
1156
1157
183451cf 1158int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, char *buf, nfs_cb cb, void *private_data)
84004dbf
RS
1159{
1160 struct nfs_cb_data *data;
1161
1162 data = malloc(sizeof(struct nfs_cb_data));
1163 if (data == NULL) {
1164 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
84004dbf
RS
1165 return -1;
1166 }
ea98629a 1167 memset(data, 0, sizeof(struct nfs_cb_data));
84004dbf
RS
1168 data->nfs = nfs;
1169 data->cb = cb;
1170 data->private_data = private_data;
1171 data->nfsfh = nfsfh;
1172
1173 nfsfh->offset = offset;
18c27b73
RS
1174
1175 if (count <= nfs_get_writemax(nfs)) {
1176 if (rpc_nfs_write_async(nfs->rpc, nfs_pwrite_cb, &nfsfh->fh, buf, offset, count, nfsfh->is_sync?FILE_SYNC:UNSTABLE, data) != 0) {
1177 rpc_set_error(nfs->rpc, "RPC error: Failed to send WRITE call for %s", data->path);
1178 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1179 free_nfs_cb_data(data);
1180 return -1;
1181 }
1182 return 0;
84004dbf 1183 }
18c27b73
RS
1184
1185 /* trying to write more than maximum server write size, we has to chop it up into smaller
1186 * chunks.
1187 * we send all writes in parallell so that performance is still good.
1188 */
1189 data->max_offset = offset;
1190 data->start_offset = offset;
1191
1192 while (count > 0) {
183451cf 1193 uint64_t writecount = count;
18c27b73
RS
1194 struct nfs_mcb_data *mdata;
1195
1196 if (writecount > nfs_get_writemax(nfs)) {
1197 writecount = nfs_get_writemax(nfs);
1198 }
1199
1200 mdata = malloc(sizeof(struct nfs_mcb_data));
1201 if (mdata == NULL) {
1202 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_mcb_data structure");
1203 return -1;
1204 }
1205 memset(mdata, 0, sizeof(struct nfs_mcb_data));
1206 mdata->data = data;
1207 mdata->offset = offset;
1208 mdata->count = writecount;
1209
1210 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) {
1211 rpc_set_error(nfs->rpc, "RPC error: Failed to send WRITE call for %s", data->path);
1212 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1213 free(mdata);
1214 return -1;
1215 }
1216
1217 count -= writecount;
1218 offset += writecount;
1219 data->num_calls++;
1220 }
1221
84004dbf
RS
1222 return 0;
1223}
1224
1225/*
1226 * Async write()
1227 */
183451cf 1228int nfs_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, char *buf, nfs_cb cb, void *private_data)
84004dbf
RS
1229{
1230 return nfs_pwrite_async(nfs, nfsfh, nfsfh->offset, count, buf, cb, private_data);
1231}
1232
1233
1234
1235
1236/*
1237 * close
1238 */
1239
1240int nfs_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data)
1241{
1242 if (nfsfh->fh.data.data_val != NULL){
1243 free(nfsfh->fh.data.data_val);
1244 nfsfh->fh.data.data_val = NULL;
1245 }
1246 free(nfsfh);
1247
1248 cb(0, nfs, NULL, private_data);
1249 return 0;
1250};
1251
1252
1253
1254
1255
1256/*
1257 * Async fstat()
1258 */
1259int nfs_fstat_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data)
1260{
1261 struct nfs_cb_data *data;
1262
1263 data = malloc(sizeof(struct nfs_cb_data));
1264 if (data == NULL) {
1265 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
84004dbf
RS
1266 return -1;
1267 }
ea98629a 1268 memset(data, 0, sizeof(struct nfs_cb_data));
84004dbf
RS
1269 data->nfs = nfs;
1270 data->cb = cb;
1271 data->private_data = private_data;
1272
1273 if (rpc_nfs_getattr_async(nfs->rpc, nfs_stat_1_cb, &nfsfh->fh, data) != 0) {
1274 rpc_set_error(nfs->rpc, "RPC error: Failed to send STAT GETATTR call for %s", data->path);
1275 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1276 free_nfs_cb_data(data);
1277 return -1;
1278 }
1279 return 0;
1280}
1281
1282
1283
1284/*
1285 * Async fsync()
1286 */
f3a75078 1287static void nfs_fsync_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
1288{
1289 struct nfs_cb_data *data = private_data;
1290 struct nfs_context *nfs = data->nfs;
1291 COMMIT3res *res;
1292
f3a75078
RS
1293 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1294
84004dbf
RS
1295 if (status == RPC_STATUS_ERROR) {
1296 data->cb(-EFAULT, nfs, command_data, data->private_data);
1297 free_nfs_cb_data(data);
1298 return;
1299 }
1300 if (status == RPC_STATUS_CANCEL) {
1301 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1302 free_nfs_cb_data(data);
1303 return;
1304 }
1305
1306 res = command_data;
1307 if (res->status != NFS3_OK) {
1308 rpc_set_error(nfs->rpc, "NFS: Commit failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1309 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1310 free_nfs_cb_data(data);
1311 return;
1312 }
1313
1314 data->cb(0, nfs, NULL, data->private_data);
1315 free_nfs_cb_data(data);
1316}
1317
1318int nfs_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data)
1319{
1320 struct nfs_cb_data *data;
1321
1322 data = malloc(sizeof(struct nfs_cb_data));
1323 if (data == NULL) {
1324 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
84004dbf
RS
1325 return -1;
1326 }
ea98629a 1327 memset(data, 0, sizeof(struct nfs_cb_data));
84004dbf
RS
1328 data->nfs = nfs;
1329 data->cb = cb;
1330 data->private_data = private_data;
1331
1332 if (rpc_nfs_commit_async(nfs->rpc, nfs_fsync_cb, &nfsfh->fh, data) != 0) {
1333 rpc_set_error(nfs->rpc, "RPC error: Failed to send COMMIT call for %s", data->path);
1334 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1335 free_nfs_cb_data(data);
1336 return -1;
1337 }
1338 return 0;
1339}
1340
1341
1342
1343
1344/*
1345 * Async ftruncate()
1346 */
f3a75078 1347static void nfs_ftruncate_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
1348{
1349 struct nfs_cb_data *data = private_data;
1350 struct nfs_context *nfs = data->nfs;
1351 SETATTR3res *res;
1352
f3a75078
RS
1353 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1354
84004dbf
RS
1355 if (status == RPC_STATUS_ERROR) {
1356 data->cb(-EFAULT, nfs, command_data, data->private_data);
1357 free_nfs_cb_data(data);
1358 return;
1359 }
1360 if (status == RPC_STATUS_CANCEL) {
1361 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1362 free_nfs_cb_data(data);
1363 return;
1364 }
1365
1366 res = command_data;
1367 if (res->status != NFS3_OK) {
1368 rpc_set_error(nfs->rpc, "NFS: Setattr failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1369 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1370 free_nfs_cb_data(data);
1371 return;
1372 }
1373
1374 data->cb(0, nfs, NULL, data->private_data);
1375 free_nfs_cb_data(data);
1376}
1377
183451cf 1378int nfs_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t length, nfs_cb cb, void *private_data)
84004dbf
RS
1379{
1380 struct nfs_cb_data *data;
1381 SETATTR3args args;
1382
1383 data = malloc(sizeof(struct nfs_cb_data));
1384 if (data == NULL) {
1385 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
84004dbf
RS
1386 return -1;
1387 }
ea98629a 1388 memset(data, 0, sizeof(struct nfs_cb_data));
84004dbf
RS
1389 data->nfs = nfs;
1390 data->cb = cb;
1391 data->private_data = private_data;
1392
ea98629a 1393 memset(&args, 0, sizeof(SETATTR3args));
84004dbf
RS
1394 args.object.data.data_len = nfsfh->fh.data.data_len;
1395 args.object.data.data_val = nfsfh->fh.data.data_val;
1396 args.new_attributes.size.set_it = 1;
1397 args.new_attributes.size.set_size3_u.size = length;
1398
1399 if (rpc_nfs_setattr_async(nfs->rpc, nfs_ftruncate_cb, &args, data) != 0) {
1400 rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
1401 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1402 free_nfs_cb_data(data);
1403 return -1;
1404 }
1405 return 0;
1406}
1407
1408
1409/*
1410 * Async truncate()
1411 */
1412static int nfs_truncate_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1413{
183451cf 1414 uint64_t offset = data->continue_int;
84004dbf
RS
1415 struct nfsfh nfsfh;
1416
1417 nfsfh.fh.data.data_val = data->fh.data.data_val;
1418 nfsfh.fh.data.data_len = data->fh.data.data_len;
1419
1420 if (nfs_ftruncate_async(nfs, &nfsfh, offset, data->cb, data->private_data) != 0) {
1421 rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
1422 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1423 free_nfs_cb_data(data);
1424 return -1;
1425 }
1426 free_nfs_cb_data(data);
1427 return 0;
1428}
1429
183451cf 1430int nfs_truncate_async(struct nfs_context *nfs, const char *path, uint64_t length, nfs_cb cb, void *private_data)
84004dbf 1431{
183451cf 1432 uint64_t offset;
84004dbf
RS
1433
1434 offset = length;
1435
1436 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_truncate_continue_internal, NULL, NULL, offset) != 0) {
cbbf9d3e
RS
1437 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1438 return -1;
84004dbf
RS
1439 }
1440
1441 return 0;
1442}
1443
1444
1445
1446
1447/*
1448 * Async mkdir()
1449 */
f3a75078 1450static void nfs_mkdir_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
1451{
1452 MKDIR3res *res;
1453 struct nfs_cb_data *data = private_data;
1454 struct nfs_context *nfs = data->nfs;
1455 char *str = data->continue_data;
1456
f3a75078
RS
1457 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1458
84004dbf
RS
1459 str = &str[strlen(str) + 1];
1460
1461 if (status == RPC_STATUS_ERROR) {
1462 data->cb(-EFAULT, nfs, command_data, data->private_data);
1463 free_nfs_cb_data(data);
1464 return;
1465 }
1466 if (status == RPC_STATUS_CANCEL) {
1467 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1468 free_nfs_cb_data(data);
1469 return;
1470 }
1471
1472 res = command_data;
1473 if (res->status != NFS3_OK) {
1474 rpc_set_error(nfs->rpc, "NFS: MKDIR of %s/%s failed with %s(%d)", data->saved_path, str, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1475 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1476 free_nfs_cb_data(data);
1477 return;
1478 }
1479
1480 data->cb(0, nfs, NULL, data->private_data);
1481 free_nfs_cb_data(data);
1482}
1483
1484static int nfs_mkdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1485{
1486 char *str = data->continue_data;
7edc9026
RS
1487 MKDIR3args args;
1488
84004dbf
RS
1489 str = &str[strlen(str) + 1];
1490
7edc9026
RS
1491 memset(&args, 0, sizeof(MKDIR3args));
1492 args.where.dir.data.data_len = data->fh.data.data_len;
1493 args.where.dir.data.data_val = data->fh.data.data_val;
1494 args.where.name = str;
1495 args.attributes.mode.set_it = 1;
1496 args.attributes.mode.set_mode3_u.mode = 0755;
1497
1498 if (rpc_nfs_mkdir_async(nfs->rpc, nfs_mkdir_cb, &args, data) != 0) {
84004dbf
RS
1499 rpc_set_error(nfs->rpc, "RPC error: Failed to send MKDIR call for %s", data->path);
1500 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1501 free_nfs_cb_data(data);
1502 return -1;
1503 }
1504 return 0;
1505}
1506
1507int nfs_mkdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
1508{
1509 char *new_path;
1510 char *ptr;
1511
1512 new_path = strdup(path);
1513 if (new_path == NULL) {
cbbf9d3e 1514 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path");
84004dbf
RS
1515 return -1;
1516 }
1517
93e9306f 1518 ptr = strrchr(new_path, '/');
84004dbf 1519 if (ptr == NULL) {
cbbf9d3e
RS
1520 rpc_set_error(nfs->rpc, "Invalid path %s", path);
1521 return -1;
84004dbf
RS
1522 }
1523 *ptr = 0;
1524
1525 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1526 if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_mkdir_continue_internal, new_path, free, 0) != 0) {
cbbf9d3e
RS
1527 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path component");
1528 return -1;
84004dbf
RS
1529 }
1530
1531 return 0;
1532}
1533
1534
1535
1536
1537
1538/*
1539 * Async rmdir()
1540 */
f3a75078 1541static void nfs_rmdir_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
1542{
1543 RMDIR3res *res;
1544 struct nfs_cb_data *data = private_data;
1545 struct nfs_context *nfs = data->nfs;
1546 char *str = data->continue_data;
1547
f3a75078
RS
1548 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1549
84004dbf
RS
1550 str = &str[strlen(str) + 1];
1551
1552 if (status == RPC_STATUS_ERROR) {
1553 data->cb(-EFAULT, nfs, command_data, data->private_data);
1554 free_nfs_cb_data(data);
1555 return;
1556 }
1557 if (status == RPC_STATUS_CANCEL) {
1558 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1559 free_nfs_cb_data(data);
1560 return;
1561 }
1562
1563 res = command_data;
1564 if (res->status != NFS3_OK) {
1565 rpc_set_error(nfs->rpc, "NFS: RMDIR of %s/%s failed with %s(%d)", data->saved_path, str, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1566 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1567 free_nfs_cb_data(data);
1568 return;
1569 }
1570
1571 data->cb(0, nfs, NULL, data->private_data);
1572 free_nfs_cb_data(data);
1573}
1574
1575static int nfs_rmdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1576{
1577 char *str = data->continue_data;
1578
1579 str = &str[strlen(str) + 1];
1580
1581 if (rpc_nfs_rmdir_async(nfs->rpc, nfs_rmdir_cb, &data->fh, str, data) != 0) {
1582 rpc_set_error(nfs->rpc, "RPC error: Failed to send RMDIR call for %s", data->path);
1583 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1584 free_nfs_cb_data(data);
1585 return -1;
1586 }
1587 return 0;
1588}
1589
1590int nfs_rmdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
1591{
1592 char *new_path;
1593 char *ptr;
1594
1595 new_path = strdup(path);
1596 if (new_path == NULL) {
cbbf9d3e 1597 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path");
84004dbf
RS
1598 return -1;
1599 }
1600
93e9306f 1601 ptr = strrchr(new_path, '/');
84004dbf 1602 if (ptr == NULL) {
cbbf9d3e
RS
1603 rpc_set_error(nfs->rpc, "Invalid path %s", path);
1604 return -1;
84004dbf
RS
1605 }
1606 *ptr = 0;
1607
1608 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1609 if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_rmdir_continue_internal, new_path, free, 0) != 0) {
cbbf9d3e
RS
1610 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1611 return -1;
84004dbf
RS
1612 }
1613
1614 return 0;
1615}
1616
1617
1618
1619
1620/*
1621 * Async creat()
1622 */
f3a75078 1623static void nfs_create_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
1624{
1625 LOOKUP3res *res;
1626 struct nfs_cb_data *data = private_data;
1627 struct nfs_context *nfs = data->nfs;
1628 struct nfsfh *nfsfh;
1629 char *str = data->continue_data;
1630
f3a75078
RS
1631 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1632
84004dbf
RS
1633 if (status == RPC_STATUS_ERROR) {
1634 data->cb(-EFAULT, nfs, command_data, data->private_data);
1635 free_nfs_cb_data(data);
1636 return;
1637 }
1638 if (status == RPC_STATUS_CANCEL) {
1639 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1640 free_nfs_cb_data(data);
1641 return;
1642 }
1643
1644 str = &str[strlen(str) + 1];
1645 res = command_data;
1646 if (res->status != NFS3_OK) {
1647 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));
1648 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1649
1650 return;
1651 }
1652
1653 nfsfh = malloc(sizeof(struct nfsfh));
1654 if (nfsfh == NULL) {
1655 rpc_set_error(nfs->rpc, "NFS: Failed to allocate nfsfh structure");
1656 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1657 free_nfs_cb_data(data);
1658 return;
1659 }
ea98629a 1660 memset(nfsfh, 0, sizeof(struct nfsfh));
84004dbf
RS
1661
1662 /* steal the filehandle */
1663 nfsfh->fh.data.data_len = data->fh.data.data_len;
1664 nfsfh->fh.data.data_val = data->fh.data.data_val;
1665 data->fh.data.data_val = NULL;
1666
1667 data->cb(0, nfs, nfsfh, data->private_data);
1668 free_nfs_cb_data(data);
1669}
1670
1671
1672
f3a75078 1673static void nfs_creat_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
1674{
1675 CREATE3res *res;
1676 struct nfs_cb_data *data = private_data;
1677 struct nfs_context *nfs = data->nfs;
1678 char *str = data->continue_data;
1679
f3a75078
RS
1680 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1681
84004dbf
RS
1682 if (status == RPC_STATUS_ERROR) {
1683 data->cb(-EFAULT, nfs, command_data, data->private_data);
1684 free_nfs_cb_data(data);
1685 return;
1686 }
1687 if (status == RPC_STATUS_CANCEL) {
1688 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1689 free_nfs_cb_data(data);
1690 return;
1691 }
1692
1693 str = &str[strlen(str) + 1];
1694 res = command_data;
1695 if (res->status != NFS3_OK) {
1696 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));
1697 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1698
1699 return;
1700 }
1701
1702 if (rpc_nfs_lookup_async(nfs->rpc, nfs_create_2_cb, &data->fh, str, data) != 0) {
1703 rpc_set_error(nfs->rpc, "RPC error: Failed to send lookup call for %s/%s", data->saved_path, str);
1704 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1705 free_nfs_cb_data(data);
1706 return;
1707 }
1708 return;
1709}
1710
1711static int nfs_creat_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1712{
1713 char *str = data->continue_data;
c985c015
RS
1714 CREATE3args args;
1715
84004dbf
RS
1716 str = &str[strlen(str) + 1];
1717
c985c015
RS
1718
1719 memset(&args, 0, sizeof(CREATE3args));
1720 args.where.dir.data.data_len = data->fh.data.data_len;
1721 args.where.dir.data.data_val = data->fh.data.data_val;
1722 args.where.name = str;
1723 args.how.mode = UNCHECKED;
1724 args.how.createhow3_u.obj_attributes.mode.set_it = 1;
1725 args.how.createhow3_u.obj_attributes.mode.set_mode3_u.mode = data->continue_int;
1726
1727 if (rpc_nfs_create_async(nfs->rpc, nfs_creat_1_cb, &args, data) != 0) {
84004dbf
RS
1728 rpc_set_error(nfs->rpc, "RPC error: Failed to send CREATE call for %s/%s", data->path, str);
1729 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1730 free_nfs_cb_data(data);
1731 return -1;
1732 }
1733 return 0;
1734}
1735
1736int nfs_creat_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data)
1737{
1738 char *new_path;
1739 char *ptr;
1740
1741 new_path = strdup(path);
1742 if (new_path == NULL) {
cbbf9d3e 1743 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path");
84004dbf
RS
1744 return -1;
1745 }
1746
93e9306f 1747 ptr = strrchr(new_path, '/');
84004dbf 1748 if (ptr == NULL) {
cbbf9d3e
RS
1749 rpc_set_error(nfs->rpc, "Invalid path %s", path);
1750 return -1;
84004dbf
RS
1751 }
1752 *ptr = 0;
1753
1754 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1755 if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_creat_continue_internal, new_path, free, mode) != 0) {
cbbf9d3e
RS
1756 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1757 return -1;
84004dbf
RS
1758 }
1759
1760 return 0;
1761}
1762
1763
1764
1765
1766/*
1767 * Async unlink()
1768 */
f3a75078 1769static void nfs_unlink_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
1770{
1771 REMOVE3res *res;
1772 struct nfs_cb_data *data = private_data;
1773 struct nfs_context *nfs = data->nfs;
1774 char *str = data->continue_data;
1775
f3a75078
RS
1776 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1777
84004dbf
RS
1778 str = &str[strlen(str) + 1];
1779
1780 if (status == RPC_STATUS_ERROR) {
1781 data->cb(-EFAULT, nfs, command_data, data->private_data);
1782 free_nfs_cb_data(data);
1783 return;
1784 }
1785 if (status == RPC_STATUS_CANCEL) {
1786 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1787 free_nfs_cb_data(data);
1788 return;
1789 }
1790
1791 res = command_data;
1792 if (res->status != NFS3_OK) {
1793 rpc_set_error(nfs->rpc, "NFS: REMOVE of %s/%s failed with %s(%d)", data->saved_path, str, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1794 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1795 free_nfs_cb_data(data);
1796 return;
1797 }
1798
1799 data->cb(0, nfs, NULL, data->private_data);
1800 free_nfs_cb_data(data);
1801}
1802
1803static int nfs_unlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1804{
1805 char *str = data->continue_data;
1806
1807 str = &str[strlen(str) + 1];
1808
1809 if (rpc_nfs_remove_async(nfs->rpc, nfs_unlink_cb, &data->fh, str, data) != 0) {
1810 rpc_set_error(nfs->rpc, "RPC error: Failed to send REMOVE call for %s", data->path);
1811 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1812 free_nfs_cb_data(data);
1813 return -1;
1814 }
1815 return 0;
1816}
1817
1818int nfs_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
1819{
1820 char *new_path;
1821 char *ptr;
1822
1823 new_path = strdup(path);
1824 if (new_path == NULL) {
cbbf9d3e 1825 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path");
84004dbf
RS
1826 return -1;
1827 }
1828
93e9306f 1829 ptr = strrchr(new_path, '/');
84004dbf 1830 if (ptr == NULL) {
cbbf9d3e
RS
1831 rpc_set_error(nfs->rpc, "Invalid path %s", path);
1832 return -1;
84004dbf
RS
1833 }
1834 *ptr = 0;
1835
1836 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1837 if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_unlink_continue_internal, new_path, free, 0) != 0) {
cbbf9d3e
RS
1838 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1839 return -1;
84004dbf
RS
1840 }
1841
1842 return 0;
1843}
1844
1845
1ec6b50a
RS
1846/*
1847 * Async mknod()
1848 */
1849struct mknod_cb_data {
1850 char *path;
1851 int mode;
1852 int major;
1853 int minor;
1854};
1855
1856static void free_mknod_cb_data(void *ptr)
1857{
1858 struct mknod_cb_data *data = ptr;
1859
1860 free(data->path);
1861 free(data);
1862}
1863
f3a75078 1864static void nfs_mknod_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
1ec6b50a
RS
1865{
1866 MKNOD3res *res;
1867 struct nfs_cb_data *data = private_data;
1868 struct nfs_context *nfs = data->nfs;
1869 char *str = data->continue_data;
1870
f3a75078
RS
1871 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1872
1ec6b50a
RS
1873 str = &str[strlen(str) + 1];
1874
1875 if (status == RPC_STATUS_ERROR) {
1876 data->cb(-EFAULT, nfs, command_data, data->private_data);
1877 free_nfs_cb_data(data);
1878 return;
1879 }
1880 if (status == RPC_STATUS_CANCEL) {
1881 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1882 free_nfs_cb_data(data);
1883 return;
1884 }
1885
1886 res = command_data;
1887 if (res->status != NFS3_OK) {
1888 rpc_set_error(nfs->rpc, "NFS: MKNOD of %s/%s failed with %s(%d)", data->saved_path, str, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1889 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1890 free_nfs_cb_data(data);
1891 return;
1892 }
1893
1894 data->cb(0, nfs, NULL, data->private_data);
1895 free_nfs_cb_data(data);
1896}
1897
1898static int nfs_mknod_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1899{
1900 struct mknod_cb_data *cb_data = data->continue_data;
1901 char *str = cb_data->path;
1902
1903 str = &str[strlen(str) + 1];
1904
1905 if (rpc_nfs_mknod_async(nfs->rpc, nfs_mknod_cb, &data->fh, str, cb_data->mode, cb_data->major, cb_data->minor, data) != 0) {
1906 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1907 free_nfs_cb_data(data);
1908 return -1;
1909 }
1910 return 0;
1911}
1912
1913int nfs_mknod_async(struct nfs_context *nfs, const char *path, int mode, int dev, nfs_cb cb, void *private_data)
1914{
1915 char *ptr;
1916 struct mknod_cb_data *cb_data;
1917
1918 cb_data = malloc(sizeof(struct mknod_cb_data));
1919 if (cb_data == NULL) {
1920 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for cb data");
1921 return -1;
1922 }
1923
1924 cb_data->path = strdup(path);
1925 if (cb_data->path == NULL) {
1926 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path");
1927 free(cb_data);
1928 return -1;
1929 }
1930
1931 ptr = strrchr(cb_data->path, '/');
1932 if (ptr == NULL) {
1933 rpc_set_error(nfs->rpc, "Invalid path %s", path);
1934 return -1;
1935 }
1936 *ptr = 0;
1937
1938 cb_data->mode = mode;
1939 cb_data->major = major(dev);
1940 cb_data->minor = minor(dev);
1941
1942 /* data->path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1943 if (nfs_lookuppath_async(nfs, cb_data->path, cb, private_data, nfs_mknod_continue_internal, cb_data, free_mknod_cb_data, 0) != 0) {
1944 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1945 free_mknod_cb_data(cb_data);
1946 return -1;
1947 }
1948
1949 return 0;
1950}
84004dbf 1951
84004dbf
RS
1952/*
1953 * Async opendir()
1954 */
fb69c64c
RS
1955
1956/* ReadDirPlus Emulation Callback data */
1957struct rdpe_cb_data {
1958 int getattrcount;
1959 int status;
1960 struct nfs_cb_data *data;
1961};
1962
1963/* ReadDirPlus Emulation LOOKUP Callback data */
1964struct rdpe_lookup_cb_data {
1965 struct rdpe_cb_data *rdpe_cb_data;
1966 struct nfsdirent *nfsdirent;
1967};
1968
1969/* Workaround for servers lacking READDIRPLUS, use READDIR instead and a GETATTR-loop */
f3a75078 1970static void nfs_opendir3_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf 1971{
fb69c64c
RS
1972 LOOKUP3res *res = command_data;
1973 struct rdpe_lookup_cb_data *rdpe_lookup_cb_data = private_data;
1974 struct rdpe_cb_data *rdpe_cb_data = rdpe_lookup_cb_data->rdpe_cb_data;
1975 struct nfs_cb_data *data = rdpe_cb_data->data;
1976 struct nfsdir *nfsdir = data->continue_data;
1977 struct nfs_context *nfs = data->nfs;
1978 struct nfsdirent *nfsdirent = rdpe_lookup_cb_data->nfsdirent;
1979
f3a75078
RS
1980 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1981
fb69c64c
RS
1982 free(rdpe_lookup_cb_data);
1983
1984 rdpe_cb_data->getattrcount--;
1985
1986 if (status == RPC_STATUS_ERROR) {
1987 rdpe_cb_data->status = RPC_STATUS_ERROR;
1988 }
1989 if (status == RPC_STATUS_CANCEL) {
1990 rdpe_cb_data->status = RPC_STATUS_CANCEL;
1991 }
1992 if (status == RPC_STATUS_SUCCESS && res->status != NFS3_OK) {
1993 rdpe_cb_data->status = RPC_STATUS_ERROR;
1994 }
1995 if (status == RPC_STATUS_SUCCESS && res->status == NFS3_OK) {
1996 if (res->LOOKUP3res_u.resok.obj_attributes.attributes_follow) {
1997 fattr3 *attributes = &res->LOOKUP3res_u.resok.obj_attributes.post_op_attr_u.attributes;
1998
1999 nfsdirent->type = attributes->type;
2000 nfsdirent->mode = attributes->mode;
2001 nfsdirent->size = attributes->size;
2002
2003 nfsdirent->atime.tv_sec = attributes->atime.seconds;
2004 nfsdirent->atime.tv_usec = attributes->atime.nseconds/1000;
2005 nfsdirent->mtime.tv_sec = attributes->mtime.seconds;
2006 nfsdirent->mtime.tv_usec = attributes->mtime.nseconds/1000;
2007 nfsdirent->ctime.tv_sec = attributes->ctime.seconds;
2008 nfsdirent->ctime.tv_usec = attributes->ctime.nseconds/1000;
2009 }
2010 }
2011
2012 if (rdpe_cb_data->getattrcount == 0) {
2013 if (rdpe_cb_data->status != RPC_STATUS_SUCCESS) {
2014 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2015 nfs_free_nfsdir(nfsdir);
2016 } else {
2017 data->cb(0, nfs, nfsdir, data->private_data);
2018 }
2019 free(rdpe_cb_data);
2020
2021 data->continue_data = NULL;
2022 free_nfs_cb_data(data);
2023 }
2024}
2025
f3a75078 2026static void nfs_opendir2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
fb69c64c
RS
2027{
2028 READDIR3res *res = command_data;
84004dbf
RS
2029 struct nfs_cb_data *data = private_data;
2030 struct nfs_context *nfs = data->nfs;
fb6510bb 2031 struct nfsdir *nfsdir = data->continue_data;
fb69c64c
RS
2032 struct nfsdirent *nfsdirent;
2033 struct entry3 *entry;
84004dbf 2034 uint64_t cookie;
fb69c64c
RS
2035 struct rdpe_cb_data *rdpe_cb_data;
2036
f3a75078
RS
2037 assert(rpc->magic == RPC_CONTEXT_MAGIC);
2038
84004dbf
RS
2039 if (status == RPC_STATUS_ERROR) {
2040 data->cb(-EFAULT, nfs, command_data, data->private_data);
2041 nfs_free_nfsdir(nfsdir);
2042 data->continue_data = NULL;
2043 free_nfs_cb_data(data);
2044 return;
2045 }
fb69c64c 2046
84004dbf
RS
2047 if (status == RPC_STATUS_CANCEL) {
2048 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2049 nfs_free_nfsdir(nfsdir);
2050 data->continue_data = NULL;
2051 free_nfs_cb_data(data);
2052 return;
2053 }
2054
84004dbf
RS
2055 if (res->status != NFS3_OK) {
2056 rpc_set_error(nfs->rpc, "NFS: READDIR of %s failed with %s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
2057 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2058 nfs_free_nfsdir(nfsdir);
2059 data->continue_data = NULL;
2060 free_nfs_cb_data(data);
2061 return;
fb69c64c
RS
2062 }
2063
2064 entry =res->READDIR3res_u.resok.reply.entries;
2065 while (entry != NULL) {
2066 nfsdirent = malloc(sizeof(struct nfsdirent));
2067 if (nfsdirent == NULL) {
2068 data->cb(-ENOMEM, nfs, "Failed to allocate dirent", data->private_data);
2069 nfs_free_nfsdir(nfsdir);
2070 data->continue_data = NULL;
2071 free_nfs_cb_data(data);
2072 return;
2073 }
2074 memset(nfsdirent, 0, sizeof(struct nfsdirent));
2075 nfsdirent->name = strdup(entry->name);
2076 if (nfsdirent->name == NULL) {
2077 data->cb(-ENOMEM, nfs, "Failed to allocate dirent->name", data->private_data);
2078 nfs_free_nfsdir(nfsdir);
2079 data->continue_data = NULL;
2080 free_nfs_cb_data(data);
2081 return;
2082 }
2083 nfsdirent->inode = entry->fileid;
2084
2085 nfsdirent->next = nfsdir->entries;
2086 nfsdir->entries = nfsdirent;
2087
2088 cookie = entry->cookie;
2089 entry = entry->nextentry;
2090 }
2091
2092 if (res->READDIR3res_u.resok.reply.eof == 0) {
2093 if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir2_cb, &data->fh, cookie, res->READDIR3res_u.resok.cookieverf, 8192, data) != 0) {
2094 rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR call for %s", data->path);
2095 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2096 nfs_free_nfsdir(nfsdir);
2097 data->continue_data = NULL;
2098 free_nfs_cb_data(data);
2099 return;
2100 }
2101 return;
2102 }
2103
2104 /* steal the dirhandle */
2105 nfsdir->current = nfsdir->entries;
2106
2107 rdpe_cb_data = malloc(sizeof(struct rdpe_cb_data));
2108 rdpe_cb_data->getattrcount = 0;
2109 rdpe_cb_data->status = RPC_STATUS_SUCCESS;
2110 rdpe_cb_data->data = data;
2111 for (nfsdirent = nfsdir->entries; nfsdirent; nfsdirent = nfsdirent->next) {
2112 struct rdpe_lookup_cb_data *rdpe_lookup_cb_data;
2113
2114 rdpe_lookup_cb_data = malloc(sizeof(struct rdpe_lookup_cb_data));
2115 rdpe_lookup_cb_data->rdpe_cb_data = rdpe_cb_data;
2116 rdpe_lookup_cb_data->nfsdirent = nfsdirent;
2117
2118 if (rpc_nfs_lookup_async(nfs->rpc, nfs_opendir3_cb, &data->fh, nfsdirent->name, rdpe_lookup_cb_data) != 0) {
2119 rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR LOOKUP call");
2120
2121 /* if we have already commands in flight, we cant just stop, we have to wait for the
2122 * commands in flight to complete
2123 */
2124 if (rdpe_cb_data->getattrcount > 0) {
2125 rdpe_cb_data->status = RPC_STATUS_ERROR;
2126 free(rdpe_lookup_cb_data);
2127 return;
2128 }
2129
2130 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2131 nfs_free_nfsdir(nfsdir);
2132 data->continue_data = NULL;
2133 free_nfs_cb_data(data);
2134 free(rdpe_lookup_cb_data);
2135 free(rdpe_cb_data);
2136 return;
2137 }
2138 rdpe_cb_data->getattrcount++;
2139 }
2140}
2141
2142
f3a75078 2143static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
fb69c64c
RS
2144{
2145 READDIRPLUS3res *res = command_data;
2146 struct nfs_cb_data *data = private_data;
2147 struct nfs_context *nfs = data->nfs;
2148 struct nfsdir *nfsdir = data->continue_data;
2149 struct entryplus3 *entry;
2150 uint64_t cookie;
2151
f3a75078 2152 assert(rpc->magic == RPC_CONTEXT_MAGIC);
fb69c64c
RS
2153
2154 if (status == RPC_STATUS_ERROR || (status == RPC_STATUS_SUCCESS && res->status == NFS3ERR_NOTSUPP) ){
2155 cookieverf3 cv;
2156
2157 if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir2_cb, &data->fh, 0, (char *)&cv, 8192, data) != 0) {
2158 rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR call for %s", data->path);
2159 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2160 nfs_free_nfsdir(nfsdir);
2161 data->continue_data = NULL;
2162 free_nfs_cb_data(data);
2163 return;
2164 }
2165 return;
2166 }
2167
2168 if (status == RPC_STATUS_CANCEL) {
2169 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2170 nfs_free_nfsdir(nfsdir);
2171 data->continue_data = NULL;
2172 free_nfs_cb_data(data);
2173 return;
2174 }
2175
2176 if (res->status != NFS3_OK) {
2177 rpc_set_error(nfs->rpc, "NFS: READDIRPLUS of %s failed with %s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
2178 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2179 nfs_free_nfsdir(nfsdir);
2180 data->continue_data = NULL;
2181 free_nfs_cb_data(data);
2182 return;
84004dbf
RS
2183 }
2184
f390f181 2185 entry =res->READDIRPLUS3res_u.resok.reply.entries;
84004dbf
RS
2186 while (entry != NULL) {
2187 struct nfsdirent *nfsdirent;
2188
2189 nfsdirent = malloc(sizeof(struct nfsdirent));
2190 if (nfsdirent == NULL) {
2191 data->cb(-ENOMEM, nfs, "Failed to allocate dirent", data->private_data);
2192 nfs_free_nfsdir(nfsdir);
2193 data->continue_data = NULL;
2194 free_nfs_cb_data(data);
2195 return;
2196 }
ea98629a 2197 memset(nfsdirent, 0, sizeof(struct nfsdirent));
84004dbf
RS
2198 nfsdirent->name = strdup(entry->name);
2199 if (nfsdirent->name == NULL) {
2200 data->cb(-ENOMEM, nfs, "Failed to allocate dirent->name", data->private_data);
2201 nfs_free_nfsdir(nfsdir);
2202 data->continue_data = NULL;
2203 free_nfs_cb_data(data);
2204 return;
2205 }
2206 nfsdirent->inode = entry->fileid;
0804e67d
RS
2207 if (entry->name_attributes.attributes_follow) {
2208 nfsdirent->type = entry->name_attributes.post_op_attr_u.attributes.type;
2209 nfsdirent->mode = entry->name_attributes.post_op_attr_u.attributes.mode;
2210 nfsdirent->size = entry->name_attributes.post_op_attr_u.attributes.size;
2211
2212 nfsdirent->atime.tv_sec = entry->name_attributes.post_op_attr_u.attributes.atime.seconds;
2213 nfsdirent->atime.tv_usec = entry->name_attributes.post_op_attr_u.attributes.atime.nseconds/1000;
2214 nfsdirent->mtime.tv_sec = entry->name_attributes.post_op_attr_u.attributes.mtime.seconds;
2215 nfsdirent->mtime.tv_usec = entry->name_attributes.post_op_attr_u.attributes.mtime.nseconds/1000;
2216 nfsdirent->ctime.tv_sec = entry->name_attributes.post_op_attr_u.attributes.ctime.seconds;
2217 nfsdirent->ctime.tv_usec = entry->name_attributes.post_op_attr_u.attributes.ctime.nseconds/1000;
2218 }
2219
84004dbf
RS
2220 nfsdirent->next = nfsdir->entries;
2221 nfsdir->entries = nfsdirent;
2222
2223 cookie = entry->cookie;
2224 entry = entry->nextentry;
2225 }
2226
f390f181
RS
2227 if (res->READDIRPLUS3res_u.resok.reply.eof == 0) {
2228 if (rpc_nfs_readdirplus_async(nfs->rpc, nfs_opendir_cb, &data->fh, cookie, res->READDIRPLUS3res_u.resok.cookieverf, 8192, data) != 0) {
2229 rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIRPLUS call for %s", data->path);
84004dbf
RS
2230 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2231 nfs_free_nfsdir(nfsdir);
2232 data->continue_data = NULL;
2233 free_nfs_cb_data(data);
2234 return;
2235 }
2236 return;
2237 }
2238
2239 /* steal the dirhandle */
2240 data->continue_data = NULL;
2241 nfsdir->current = nfsdir->entries;
2242
2243 data->cb(0, nfs, nfsdir, data->private_data);
2244 free_nfs_cb_data(data);
2245}
2246
2247static int nfs_opendir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2248{
2249 cookieverf3 cv;
2250
ea98629a 2251 memset(cv, 0, sizeof(cookieverf3));
f390f181
RS
2252 if (rpc_nfs_readdirplus_async(nfs->rpc, nfs_opendir_cb, &data->fh, 0, (char *)&cv, 8192, data) != 0) {
2253 rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIRPLUS call for %s", data->path);
84004dbf
RS
2254 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2255 free_nfs_cb_data(data);
2256 return -1;
2257 }
2258 return 0;
2259}
2260
2261int nfs_opendir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
2262{
2263 struct nfsdir *nfsdir;
2264
2265 nfsdir = malloc(sizeof(struct nfsdir));
2266 if (nfsdir == NULL) {
cbbf9d3e 2267 rpc_set_error(nfs->rpc, "failed to allocate buffer for nfsdir");
84004dbf
RS
2268 return -1;
2269 }
ea98629a 2270 memset(nfsdir, 0, sizeof(struct nfsdir));
84004dbf
RS
2271
2272 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_opendir_continue_internal, nfsdir, free, 0) != 0) {
cbbf9d3e
RS
2273 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
2274 return -1;
84004dbf
RS
2275 }
2276
2277 return 0;
2278}
2279
2280
2281struct nfsdirent *nfs_readdir(struct nfs_context *nfs _U_, struct nfsdir *nfsdir)
2282{
2283 struct nfsdirent *nfsdirent = nfsdir->current;
2284
2285 if (nfsdir->current != NULL) {
2286 nfsdir->current = nfsdir->current->next;
2287 }
2288 return nfsdirent;
2289}
2290
2291
2292void nfs_closedir(struct nfs_context *nfs _U_, struct nfsdir *nfsdir)
2293{
2294 nfs_free_nfsdir(nfsdir);
2295}
2296
2297
2298
2299
2300
2301
2302
2303/*
2304 * Async lseek()
2305 */
2306struct lseek_cb_data {
2307 struct nfs_context *nfs;
2308 struct nfsfh *nfsfh;
183451cf 2309 uint64_t offset;
84004dbf
RS
2310 nfs_cb cb;
2311 void *private_data;
2312};
2313
f3a75078 2314static void nfs_lseek_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
2315{
2316 GETATTR3res *res;
2317 struct lseek_cb_data *data = private_data;
2318 struct nfs_context *nfs = data->nfs;
2319
f3a75078
RS
2320 assert(rpc->magic == RPC_CONTEXT_MAGIC);
2321
84004dbf
RS
2322 if (status == RPC_STATUS_ERROR) {
2323 data->cb(-EFAULT, nfs, command_data, data->private_data);
2324 free(data);
2325 return;
2326 }
2327 if (status == RPC_STATUS_CANCEL) {
2328 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2329 free(data);
2330 return;
2331 }
2332
2333 res = command_data;
2334 if (res->status != NFS3_OK) {
2335 rpc_set_error(nfs->rpc, "NFS: GETATTR failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
2336 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2337 free(data);
2338 return;
2339 }
2340
2341 data->nfsfh->offset = data->offset + res->GETATTR3res_u.resok.obj_attributes.size;
2342 data->cb(0, nfs, &data->nfsfh->offset, data->private_data);
2343 free(data);
2344}
2345
183451cf 2346int nfs_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, int whence, nfs_cb cb, void *private_data)
84004dbf
RS
2347{
2348 struct lseek_cb_data *data;
2349
2350 if (whence == SEEK_SET) {
2351 nfsfh->offset = offset;
2352 cb(0, nfs, &nfsfh->offset, private_data);
2353 return 0;
2354 }
2355 if (whence == SEEK_CUR) {
2356 nfsfh->offset += offset;
2357 cb(0, nfs, &nfsfh->offset, private_data);
2358 return 0;
2359 }
2360
2361 data = malloc(sizeof(struct lseek_cb_data));
2362 if (data == NULL) {
2363 rpc_set_error(nfs->rpc, "Out Of Memory: Failed to malloc lseek cb data");
2364 return -1;
2365 }
2366
2367 data->nfs = nfs;
2368 data->nfsfh = nfsfh;
2369 data->offset = offset;
2370 data->cb = cb;
2371 data->private_data = private_data;
2372
2373 if (rpc_nfs_getattr_async(nfs->rpc, nfs_lseek_1_cb, &nfsfh->fh, data) != 0) {
2374 rpc_set_error(nfs->rpc, "RPC error: Failed to send LSEEK GETATTR call");
2375 free(data);
cbbf9d3e 2376 return -1;
84004dbf
RS
2377 }
2378 return 0;
2379}
2380
2381
2382
2383
2384/*
2385 * Async statvfs()
2386 */
f3a75078 2387static void nfs_statvfs_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
2388{
2389 FSSTAT3res *res;
2390 struct nfs_cb_data *data = private_data;
2391 struct nfs_context *nfs = data->nfs;
2392 struct statvfs svfs;
2393
f3a75078
RS
2394 assert(rpc->magic == RPC_CONTEXT_MAGIC);
2395
84004dbf
RS
2396 if (status == RPC_STATUS_ERROR) {
2397 data->cb(-EFAULT, nfs, command_data, data->private_data);
2398 free_nfs_cb_data(data);
2399 return;
2400 }
2401 if (status == RPC_STATUS_CANCEL) {
2402 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2403 free_nfs_cb_data(data);
2404 return;
2405 }
2406
2407 res = command_data;
2408 if (res->status != NFS3_OK) {
2409 rpc_set_error(nfs->rpc, "NFS: FSSTAT of %s failed with %s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
2410 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2411 free_nfs_cb_data(data);
2412 return;
2413 }
2414
2415 svfs.f_bsize = 4096;
2416 svfs.f_frsize = 4096;
2417 svfs.f_blocks = res->FSSTAT3res_u.resok.tbytes/4096;
2418 svfs.f_bfree = res->FSSTAT3res_u.resok.fbytes/4096;
2419 svfs.f_bavail = res->FSSTAT3res_u.resok.abytes/4096;
2420 svfs.f_files = res->FSSTAT3res_u.resok.tfiles;
2421 svfs.f_ffree = res->FSSTAT3res_u.resok.ffiles;
252aa90d 2422#if !defined(ANDROID)
84004dbf
RS
2423 svfs.f_favail = res->FSSTAT3res_u.resok.afiles;
2424 svfs.f_fsid = 0;
2425 svfs.f_flag = 0;
2426 svfs.f_namemax = 256;
252aa90d 2427#endif
84004dbf
RS
2428
2429 data->cb(0, nfs, &svfs, data->private_data);
2430 free_nfs_cb_data(data);
2431}
2432
2433static int nfs_statvfs_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2434{
2435 if (rpc_nfs_fsstat_async(nfs->rpc, nfs_statvfs_1_cb, &data->fh, data) != 0) {
2436 rpc_set_error(nfs->rpc, "RPC error: Failed to send FSSTAT call for %s", data->path);
2437 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2438 free_nfs_cb_data(data);
2439 return -1;
2440 }
2441 return 0;
2442}
2443
2444int nfs_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
2445{
2446 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_statvfs_continue_internal, NULL, NULL, 0) != 0) {
cbbf9d3e 2447 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
84004dbf
RS
2448 return -1;
2449 }
2450
2451 return 0;
2452}
2453
2454
2455
2456
2457/*
2458 * Async readlink()
2459 */
f3a75078 2460static void nfs_readlink_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
2461{
2462 READLINK3res *res;
2463 struct nfs_cb_data *data = private_data;
2464 struct nfs_context *nfs = data->nfs;
2465
f3a75078
RS
2466 assert(rpc->magic == RPC_CONTEXT_MAGIC);
2467
84004dbf
RS
2468 if (status == RPC_STATUS_ERROR) {
2469 data->cb(-EFAULT, nfs, command_data, data->private_data);
2470 free_nfs_cb_data(data);
2471 return;
2472 }
2473 if (status == RPC_STATUS_CANCEL) {
2474 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2475 free_nfs_cb_data(data);
2476 return;
2477 }
2478
2479 res = command_data;
2480 if (res->status != NFS3_OK) {
2481 rpc_set_error(nfs->rpc, "NFS: READLINK of %s failed with %s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
2482 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2483 free_nfs_cb_data(data);
2484 return;
2485 }
2486
2487
2488 data->cb(0, nfs, res->READLINK3res_u.resok.data, data->private_data);
2489 free_nfs_cb_data(data);
2490}
2491
2492static int nfs_readlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2493{
16104b27
RS
2494 READLINK3args args;
2495
2496 args.symlink.data.data_len = data->fh.data.data_len;
2497 args.symlink.data.data_val = data->fh.data.data_val;
2498
2499 if (rpc_nfs_readlink_async(nfs->rpc, nfs_readlink_1_cb, &args, data) != 0) {
84004dbf
RS
2500 rpc_set_error(nfs->rpc, "RPC error: Failed to send READLINK call for %s", data->path);
2501 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2502 free_nfs_cb_data(data);
2503 return -1;
2504 }
2505 return 0;
2506}
2507
2508int nfs_readlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
2509{
2510 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_readlink_continue_internal, NULL, NULL, 0) != 0) {
cbbf9d3e 2511 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
84004dbf
RS
2512 return -1;
2513 }
2514
2515 return 0;
2516}
2517
2518
2519
2520
2521/*
2522 * Async chmod()
2523 */
f3a75078 2524static void nfs_chmod_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
2525{
2526 struct nfs_cb_data *data = private_data;
2527 struct nfs_context *nfs = data->nfs;
2528 SETATTR3res *res;
2529
f3a75078
RS
2530 assert(rpc->magic == RPC_CONTEXT_MAGIC);
2531
84004dbf
RS
2532 if (status == RPC_STATUS_ERROR) {
2533 data->cb(-EFAULT, nfs, command_data, data->private_data);
2534 free_nfs_cb_data(data);
2535 return;
2536 }
2537 if (status == RPC_STATUS_CANCEL) {
2538 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2539 free_nfs_cb_data(data);
2540 return;
2541 }
2542
2543 res = command_data;
2544 if (res->status != NFS3_OK) {
2545 rpc_set_error(nfs->rpc, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
2546 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2547 free_nfs_cb_data(data);
2548 return;
2549 }
2550
2551 data->cb(0, nfs, NULL, data->private_data);
2552 free_nfs_cb_data(data);
2553}
2554
2555static int nfs_chmod_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2556{
2557 SETATTR3args args;
2558
ea98629a 2559 memset(&args, 0, sizeof(SETATTR3args));
84004dbf
RS
2560 args.object.data.data_len = data->fh.data.data_len;
2561 args.object.data.data_val = data->fh.data.data_val;
2562 args.new_attributes.mode.set_it = 1;
2563 args.new_attributes.mode.set_mode3_u.mode = data->continue_int;
2564
2565 if (rpc_nfs_setattr_async(nfs->rpc, nfs_chmod_cb, &args, data) != 0) {
2566 rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
2567 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2568 free_nfs_cb_data(data);
2569 return -1;
2570 }
2571 return 0;
2572}
2573
2574
2575int nfs_chmod_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data)
2576{
2577 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_chmod_continue_internal, NULL, NULL, mode) != 0) {
cbbf9d3e 2578 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
84004dbf
RS
2579 return -1;
2580 }
2581
2582 return 0;
2583}
2584
2585/*
2586 * Async fchmod()
2587 */
2588int nfs_fchmod_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode, nfs_cb cb, void *private_data)
2589{
2590 struct nfs_cb_data *data;
2591
2592 data = malloc(sizeof(struct nfs_cb_data));
2593 if (data == NULL) {
cbbf9d3e 2594 rpc_set_error(nfs->rpc, "out of memory. failed to allocate memory for nfs mount data");
84004dbf
RS
2595 return -1;
2596 }
ea98629a 2597 memset(data, 0, sizeof(struct nfs_cb_data));
84004dbf
RS
2598 data->nfs = nfs;
2599 data->cb = cb;
2600 data->private_data = private_data;
2601 data->continue_int = mode;
2602 data->fh.data.data_len = nfsfh->fh.data.data_len;
2603 data->fh.data.data_val = malloc(data->fh.data.data_len);
2604 if (data->fh.data.data_val == NULL) {
2605 rpc_set_error(nfs->rpc, "Out of memory: Failed to allocate fh");
2606 free_nfs_cb_data(data);
2607 return -1;
2608 }
2609 memcpy(data->fh.data.data_val, nfsfh->fh.data.data_val, data->fh.data.data_len);
2610
2611 if (nfs_chmod_continue_internal(nfs, data) != 0) {
2612 free_nfs_cb_data(data);
2613 return -1;
2614 }
2615
2616 return 0;
2617}
2618
2619
2620
2621/*
2622 * Async chown()
2623 */
f3a75078 2624static void nfs_chown_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
2625{
2626 struct nfs_cb_data *data = private_data;
2627 struct nfs_context *nfs = data->nfs;
2628 SETATTR3res *res;
2629
f3a75078
RS
2630 assert(rpc->magic == RPC_CONTEXT_MAGIC);
2631
84004dbf
RS
2632 if (status == RPC_STATUS_ERROR) {
2633 data->cb(-EFAULT, nfs, command_data, data->private_data);
2634 free_nfs_cb_data(data);
2635 return;
2636 }
2637 if (status == RPC_STATUS_CANCEL) {
2638 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2639 free_nfs_cb_data(data);
2640 return;
2641 }
2642
2643 res = command_data;
2644 if (res->status != NFS3_OK) {
2645 rpc_set_error(nfs->rpc, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
2646 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2647 free_nfs_cb_data(data);
2648 return;
2649 }
2650
2651 data->cb(0, nfs, NULL, data->private_data);
2652 free_nfs_cb_data(data);
2653}
2654
2655struct nfs_chown_data {
2656 uid_t uid;
2657 gid_t gid;
2658};
2659
2660static int nfs_chown_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2661{
2662 SETATTR3args args;
2663 struct nfs_chown_data *chown_data = data->continue_data;
2664
ea98629a 2665 memset(&args, 0, sizeof(SETATTR3args));
84004dbf
RS
2666 args.object.data.data_len = data->fh.data.data_len;
2667 args.object.data.data_val = data->fh.data.data_val;
2668 if (chown_data->uid != (uid_t)-1) {
2669 args.new_attributes.uid.set_it = 1;
2670 args.new_attributes.uid.set_uid3_u.uid = chown_data->uid;
2671 }
2672 if (chown_data->gid != (gid_t)-1) {
2673 args.new_attributes.gid.set_it = 1;
2674 args.new_attributes.gid.set_gid3_u.gid = chown_data->gid;
2675 }
2676
2677 if (rpc_nfs_setattr_async(nfs->rpc, nfs_chown_cb, &args, data) != 0) {
2678 rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
2679 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2680 free_nfs_cb_data(data);
2681 return -1;
2682 }
2683 return 0;
2684}
2685
2686
2687int nfs_chown_async(struct nfs_context *nfs, const char *path, int uid, int gid, nfs_cb cb, void *private_data)
2688{
2689 struct nfs_chown_data *chown_data;
2690
2691 chown_data = malloc(sizeof(struct nfs_chown_data));
2692 if (chown_data == NULL) {
cbbf9d3e 2693 rpc_set_error(nfs->rpc, "Failed to allocate memory for chown data structure");
84004dbf
RS
2694 return -1;
2695 }
2696
2697 chown_data->uid = uid;
2698 chown_data->gid = gid;
2699
2700 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_chown_continue_internal, chown_data, free, 0) != 0) {
cbbf9d3e 2701 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
84004dbf
RS
2702 return -1;
2703 }
2704
2705 return 0;
2706}
2707
2708
2709/*
2710 * Async fchown()
2711 */
2712int nfs_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid, nfs_cb cb, void *private_data)
2713{
2714 struct nfs_cb_data *data;
2715 struct nfs_chown_data *chown_data;
2716
2717 chown_data = malloc(sizeof(struct nfs_chown_data));
2718 if (chown_data == NULL) {
cbbf9d3e 2719 rpc_set_error(nfs->rpc, "Failed to allocate memory for chown data structure");
84004dbf
RS
2720 return -1;
2721 }
2722
2723 chown_data->uid = uid;
2724 chown_data->gid = gid;
2725
2726
2727 data = malloc(sizeof(struct nfs_cb_data));
2728 if (data == NULL) {
cbbf9d3e 2729 rpc_set_error(nfs->rpc, "out of memory. failed to allocate memory for fchown data");
84004dbf
RS
2730 return -1;
2731 }
ea98629a 2732 memset(data, 0, sizeof(struct nfs_cb_data));
84004dbf
RS
2733 data->nfs = nfs;
2734 data->cb = cb;
2735 data->private_data = private_data;
2736 data->continue_data = chown_data;
2737 data->fh.data.data_len = nfsfh->fh.data.data_len;
2738 data->fh.data.data_val = malloc(data->fh.data.data_len);
2739 if (data->fh.data.data_val == NULL) {
2740 rpc_set_error(nfs->rpc, "Out of memory: Failed to allocate fh");
2741 free_nfs_cb_data(data);
2742 return -1;
2743 }
2744 memcpy(data->fh.data.data_val, nfsfh->fh.data.data_val, data->fh.data.data_len);
2745
2746
2747 if (nfs_chown_continue_internal(nfs, data) != 0) {
2748 free_nfs_cb_data(data);
2749 return -1;
2750 }
2751
2752 return 0;
2753}
2754
2755
2756
2757
2758
2759/*
2760 * Async utimes()
2761 */
f3a75078 2762static void nfs_utimes_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
2763{
2764 struct nfs_cb_data *data = private_data;
2765 struct nfs_context *nfs = data->nfs;
2766 SETATTR3res *res;
2767
f3a75078
RS
2768 assert(rpc->magic == RPC_CONTEXT_MAGIC);
2769
84004dbf
RS
2770 if (status == RPC_STATUS_ERROR) {
2771 data->cb(-EFAULT, nfs, command_data, data->private_data);
2772 free_nfs_cb_data(data);
2773 return;
2774 }
2775 if (status == RPC_STATUS_CANCEL) {
2776 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2777 free_nfs_cb_data(data);
2778 return;
2779 }
2780
2781 res = command_data;
2782 if (res->status != NFS3_OK) {
2783 rpc_set_error(nfs->rpc, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
2784 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2785 free_nfs_cb_data(data);
2786 return;
2787 }
2788
2789 data->cb(0, nfs, NULL, data->private_data);
2790 free_nfs_cb_data(data);
2791}
2792
2793static int nfs_utimes_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2794{
2795 SETATTR3args args;
2796 struct timeval *utimes_data = data->continue_data;
2797
ea98629a 2798 memset(&args, 0, sizeof(SETATTR3args));
84004dbf
RS
2799 args.object.data.data_len = data->fh.data.data_len;
2800 args.object.data.data_val = data->fh.data.data_val;
2801 if (utimes_data != NULL) {
2802 args.new_attributes.atime.set_it = SET_TO_CLIENT_TIME;
2803 args.new_attributes.atime.set_atime_u.atime.seconds = utimes_data[0].tv_sec;
2804 args.new_attributes.atime.set_atime_u.atime.nseconds = utimes_data[0].tv_usec * 1000;
2805 args.new_attributes.mtime.set_it = SET_TO_CLIENT_TIME;
2806 args.new_attributes.mtime.set_mtime_u.mtime.seconds = utimes_data[1].tv_sec;
2807 args.new_attributes.mtime.set_mtime_u.mtime.nseconds = utimes_data[1].tv_usec * 1000;
2808 } else {
2809 args.new_attributes.atime.set_it = SET_TO_SERVER_TIME;
2810 args.new_attributes.mtime.set_it = SET_TO_SERVER_TIME;
2811 }
2812
2813 if (rpc_nfs_setattr_async(nfs->rpc, nfs_utimes_cb, &args, data) != 0) {
2814 rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
2815 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2816 free_nfs_cb_data(data);
2817 return -1;
2818 }
2819 return 0;
2820}
2821
2822
2823int nfs_utimes_async(struct nfs_context *nfs, const char *path, struct timeval *times, nfs_cb cb, void *private_data)
2824{
2825 struct timeval *new_times = NULL;
2826
2827 if (times != NULL) {
2828 new_times = malloc(sizeof(struct timeval)*2);
2829 if (new_times == NULL) {
cbbf9d3e 2830 rpc_set_error(nfs->rpc, "Failed to allocate memory for timeval structure");
84004dbf
RS
2831 return -1;
2832 }
2833
2834 memcpy(new_times, times, sizeof(struct timeval)*2);
2835 }
2836
2837 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_utimes_continue_internal, new_times, free, 0) != 0) {
cbbf9d3e 2838 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
84004dbf
RS
2839 return -1;
2840 }
2841
2842 return 0;
2843}
2844
2845/*
2846 * Async utime()
2847 */
2848int nfs_utime_async(struct nfs_context *nfs, const char *path, struct utimbuf *times, nfs_cb cb, void *private_data)
2849{
2850 struct timeval *new_times = NULL;
2851
2852 if (times != NULL) {
2853 new_times = malloc(sizeof(struct timeval)*2);
2854 if (new_times == NULL) {
cbbf9d3e 2855 rpc_set_error(nfs->rpc, "Failed to allocate memory for timeval structure");
84004dbf
RS
2856 return -1;
2857 }
2858
2859 new_times[0].tv_sec = times->actime;
2860 new_times[0].tv_usec = 0;
2861 new_times[1].tv_sec = times->modtime;
2862 new_times[1].tv_usec = 0;
2863 }
2864
2865 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_utimes_continue_internal, new_times, free, 0) != 0) {
cbbf9d3e 2866 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
84004dbf
RS
2867 return -1;
2868 }
2869
2870 return 0;
2871}
2872
2873
2874
2875
2876
2877/*
2878 * Async access()
2879 */
f3a75078 2880static void nfs_access_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
2881{
2882 ACCESS3res *res;
2883 struct nfs_cb_data *data = private_data;
2884 struct nfs_context *nfs = data->nfs;
2885 unsigned int nfsmode = 0;
2886
f3a75078
RS
2887 assert(rpc->magic == RPC_CONTEXT_MAGIC);
2888
84004dbf
RS
2889 if (status == RPC_STATUS_ERROR) {
2890 data->cb(-EFAULT, nfs, command_data, data->private_data);
2891 free_nfs_cb_data(data);
2892 return;
2893 }
2894 if (status == RPC_STATUS_CANCEL) {
2895 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2896 free_nfs_cb_data(data);
2897 return;
2898 }
2899
2900 res = command_data;
2901 if (res->status != NFS3_OK) {
2902 rpc_set_error(nfs->rpc, "NFS: ACCESS of %s failed with %s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
2903 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2904 free_nfs_cb_data(data);
2905 return;
2906 }
2907
2908 if (data->continue_int & R_OK) {
2909 nfsmode |= ACCESS3_READ;
2910 }
2911 if (data->continue_int & W_OK) {
2912 nfsmode |= ACCESS3_MODIFY;
2913 }
2914 if (data->continue_int & X_OK) {
2915 nfsmode |= ACCESS3_EXECUTE;
2916 }
2917
2918 if (res->ACCESS3res_u.resok.access != nfsmode) {
2919 rpc_set_error(nfs->rpc, "NFS: ACCESS denied. Required access %c%c%c. Allowed access %c%c%c",
2920 nfsmode&ACCESS3_READ?'r':'-',
2921 nfsmode&ACCESS3_MODIFY?'w':'-',
2922 nfsmode&ACCESS3_EXECUTE?'x':'-',
2923 res->ACCESS3res_u.resok.access&ACCESS3_READ?'r':'-',
2924 res->ACCESS3res_u.resok.access&ACCESS3_MODIFY?'w':'-',
2925 res->ACCESS3res_u.resok.access&ACCESS3_EXECUTE?'x':'-');
2926 data->cb(-EACCES, nfs, rpc_get_error(nfs->rpc), data->private_data);
2927 free_nfs_cb_data(data);
2928 return;
2929 }
2930
2931 data->cb(0, nfs, NULL, data->private_data);
2932 free_nfs_cb_data(data);
2933}
2934
2935static int nfs_access_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2936{
2937 int nfsmode = 0;
2938
2939 if (data->continue_int & R_OK) {
2940 nfsmode |= ACCESS3_READ;
2941 }
2942 if (data->continue_int & W_OK) {
2943 nfsmode |= ACCESS3_MODIFY;
2944 }
2945 if (data->continue_int & X_OK) {
2946 nfsmode |= ACCESS3_EXECUTE;
2947 }
2948
2949 if (rpc_nfs_access_async(nfs->rpc, nfs_access_cb, &data->fh, nfsmode, data) != 0) {
2950 rpc_set_error(nfs->rpc, "RPC error: Failed to send OPEN ACCESS call for %s", data->path);
2951 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2952 free_nfs_cb_data(data);
2953 return -1;
2954 }
2955 return 0;
2956}
2957
2958int nfs_access_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data)
2959{
2960 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_access_continue_internal, NULL, NULL, mode) != 0) {
cbbf9d3e
RS
2961 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
2962 return -1;
84004dbf
RS
2963 }
2964
2965 return 0;
2966}
2967
2968
2969
2970/*
2971 * Async symlink()
2972 */
2973struct nfs_symlink_data {
2974 char *oldpath;
2975 char *newpathparent;
2976 char *newpathobject;
2977};
2978
2979static void free_nfs_symlink_data(void *mem)
2980{
2981 struct nfs_symlink_data *data = mem;
2982
2983 if (data->oldpath != NULL) {
2984 free(data->oldpath);
2985 }
2986 if (data->newpathparent != NULL) {
2987 free(data->newpathparent);
2988 }
2989 if (data->newpathobject != NULL) {
2990 free(data->newpathobject);
2991 }
2992 free(data);
2993}
2994
f3a75078 2995static void nfs_symlink_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
2996{
2997 SYMLINK3res *res;
2998 struct nfs_cb_data *data = private_data;
2999 struct nfs_context *nfs = data->nfs;
3000 struct nfs_symlink_data *symlink_data = data->continue_data;
3001
f3a75078
RS
3002 assert(rpc->magic == RPC_CONTEXT_MAGIC);
3003
84004dbf
RS
3004 if (status == RPC_STATUS_ERROR) {
3005 data->cb(-EFAULT, nfs, command_data, data->private_data);
3006 free_nfs_cb_data(data);
3007 return;
3008 }
3009 if (status == RPC_STATUS_CANCEL) {
3010 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
3011 free_nfs_cb_data(data);
3012 return;
3013 }
3014
3015 res = command_data;
3016 if (res->status != NFS3_OK) {
3017 rpc_set_error(nfs->rpc, "NFS: SYMLINK %s/%s -> %s failed with %s(%d)", symlink_data->newpathparent, symlink_data->newpathobject, symlink_data->oldpath, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
3018 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
3019 free_nfs_cb_data(data);
3020 return;
3021 }
3022
3023 data->cb(0, nfs, NULL, data->private_data);
3024 free_nfs_cb_data(data);
3025}
3026
3027static int nfs_symlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
3028{
3029 struct nfs_symlink_data *symlink_data = data->continue_data;
8e255816 3030 SYMLINK3args sa;
84004dbf 3031
8e255816
RS
3032 memset(&sa, 0, sizeof(SYMLINK3args));
3033 sa.where.dir.data.data_len = data->fh.data.data_len;
3034 sa.where.dir.data.data_val = data->fh.data.data_val;
3035 sa.where.name = symlink_data->newpathobject;
3036 sa.symlink.symlink_attributes.mode.set_it = 1;
3037 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;
3038 sa.symlink.symlink_data = symlink_data->oldpath;
3039
3040 if (rpc_nfs_symlink_async(nfs->rpc, nfs_symlink_cb, &sa, data) != 0) {
84004dbf
RS
3041 rpc_set_error(nfs->rpc, "RPC error: Failed to send SYMLINK call for %s", data->path);
3042 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
3043 free_nfs_cb_data(data);
3044 return -1;
3045 }
3046 return 0;
3047}
3048
3049int nfs_symlink_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data)
3050{
3051 char *ptr;
3052 struct nfs_symlink_data *symlink_data;
3053
3054 symlink_data = malloc(sizeof(struct nfs_symlink_data));
3055 if (symlink_data == NULL) {
cbbf9d3e 3056 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for symlink data");
84004dbf
RS
3057 return -1;
3058 }
ea98629a 3059 memset(symlink_data, 0, sizeof(struct nfs_symlink_data));
84004dbf
RS
3060
3061 symlink_data->oldpath = strdup(oldpath);
3062 if (symlink_data->oldpath == NULL) {
cbbf9d3e 3063 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for oldpath");
84004dbf 3064 free_nfs_symlink_data(symlink_data);
cbbf9d3e 3065 return -1;
84004dbf
RS
3066 }
3067
3068 symlink_data->newpathparent = strdup(newpath);
3069 if (symlink_data->newpathparent == NULL) {
cbbf9d3e 3070 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for new path");
84004dbf 3071 free_nfs_symlink_data(symlink_data);
cbbf9d3e 3072 return -1;
84004dbf
RS
3073 }
3074
93e9306f 3075 ptr = strrchr(symlink_data->newpathparent, '/');
84004dbf 3076 if (ptr == NULL) {
cbbf9d3e 3077 rpc_set_error(nfs->rpc, "Invalid path %s", oldpath);
84004dbf 3078 free_nfs_symlink_data(symlink_data);
cbbf9d3e 3079 return -1;
84004dbf
RS
3080 }
3081 *ptr = 0;
3082 ptr++;
3083
3084 symlink_data->newpathobject = strdup(ptr);
3085 if (symlink_data->newpathobject == NULL) {
cbbf9d3e 3086 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for new path");
84004dbf 3087 free_nfs_symlink_data(symlink_data);
cbbf9d3e 3088 return -1;
84004dbf
RS
3089 }
3090
3091 if (nfs_lookuppath_async(nfs, symlink_data->newpathparent, cb, private_data, nfs_symlink_continue_internal, symlink_data, free_nfs_symlink_data, 0) != 0) {
cbbf9d3e
RS
3092 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
3093 return -1;
84004dbf
RS
3094 }
3095
3096 return 0;
3097}
3098
3099
3100
3101/*
3102 * Async rename()
3103 */
3104struct nfs_rename_data {
3105 char *oldpath;
3106 char *oldobject;
3107 struct nfs_fh3 olddir;
3108 char *newpath;
3109 char *newobject;
3110 struct nfs_fh3 newdir;
3111};
3112
3113static void free_nfs_rename_data(void *mem)
3114{
3115 struct nfs_rename_data *data = mem;
3116
3117 if (data->oldpath != NULL) {
3118 free(data->oldpath);
3119 }
3120 if (data->olddir.data.data_val != NULL) {
3121 free(data->olddir.data.data_val);
3122 }
3123 if (data->newpath != NULL) {
3124 free(data->newpath);
3125 }
3126 if (data->newdir.data.data_val != NULL) {
3127 free(data->newdir.data.data_val);
3128 }
3129 free(data);
3130}
3131
f3a75078 3132static void nfs_rename_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
3133{
3134 RENAME3res *res;
3135 struct nfs_cb_data *data = private_data;
3136 struct nfs_context *nfs = data->nfs;
3137 struct nfs_rename_data *rename_data = data->continue_data;
3138
f3a75078
RS
3139 assert(rpc->magic == RPC_CONTEXT_MAGIC);
3140
84004dbf
RS
3141 if (status == RPC_STATUS_ERROR) {
3142 data->cb(-EFAULT, nfs, command_data, data->private_data);
3143 free_nfs_cb_data(data);
3144 return;
3145 }
3146 if (status == RPC_STATUS_CANCEL) {
3147 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
3148 free_nfs_cb_data(data);
3149 return;
3150 }
3151
3152 res = command_data;
3153 if (res->status != NFS3_OK) {
3154 rpc_set_error(nfs->rpc, "NFS: RENAME %s/%s -> %s/%s failed with %s(%d)", rename_data->oldpath, rename_data->oldobject, rename_data->newpath, rename_data->newobject, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
3155 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
3156 free_nfs_cb_data(data);
3157 return;
3158 }
3159
3160 data->cb(0, nfs, NULL, data->private_data);
3161 free_nfs_cb_data(data);
3162}
3163
3164static int nfs_rename_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
3165{
3166 struct nfs_rename_data *rename_data = data->continue_data;
3167
3168 /* steal the filehandle */
3169 rename_data->newdir.data.data_len = data->fh.data.data_len;
3170 rename_data->newdir.data.data_val = data->fh.data.data_val;
3171 data->fh.data.data_val = NULL;
3172
3173 if (rpc_nfs_rename_async(nfs->rpc, nfs_rename_cb, &rename_data->olddir, rename_data->oldobject, &rename_data->newdir, rename_data->newobject, data) != 0) {
3174 rpc_set_error(nfs->rpc, "RPC error: Failed to send RENAME call for %s", data->path);
3175 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
3176 free_nfs_cb_data(data);
3177 return -1;
3178 }
3179 return 0;
3180}
3181
3182
3183static int nfs_rename_continue_1_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
3184{
3185 struct nfs_rename_data *rename_data = data->continue_data;
3186
3187 /* steal the filehandle */
3188 rename_data->olddir.data.data_len = data->fh.data.data_len;
3189 rename_data->olddir.data.data_val = data->fh.data.data_val;
3190 data->fh.data.data_val = NULL;
3191
3192 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) {
3193 rpc_set_error(nfs->rpc, "RPC error: Failed to send LOOKUP call for %s", rename_data->newpath);
3194 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
3195 free_nfs_cb_data(data);
3196 return -1;
3197 }
3198 data->continue_data = NULL;
3199 free_nfs_cb_data(data);
3200
3201 return 0;
3202}
3203
3204
3205int nfs_rename_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data)
3206{
3207 char *ptr;
3208 struct nfs_rename_data *rename_data;
3209
3210 rename_data = malloc(sizeof(struct nfs_rename_data));
3211 if (rename_data == NULL) {
cbbf9d3e 3212 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for rename data");
84004dbf
RS
3213 return -1;
3214 }
ea98629a 3215 memset(rename_data, 0, sizeof(struct nfs_rename_data));
84004dbf
RS
3216
3217 rename_data->oldpath = strdup(oldpath);
3218 if (rename_data->oldpath == NULL) {
cbbf9d3e 3219 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for oldpath");
84004dbf 3220 free_nfs_rename_data(rename_data);
cbbf9d3e 3221 return -1;
84004dbf 3222 }
93e9306f 3223 ptr = strrchr(rename_data->oldpath, '/');
84004dbf 3224 if (ptr == NULL) {
cbbf9d3e 3225 rpc_set_error(nfs->rpc, "Invalid path %s", oldpath);
84004dbf 3226 free_nfs_rename_data(rename_data);
cbbf9d3e 3227 return -1;
84004dbf
RS
3228 }
3229 *ptr = 0;
3230 ptr++;
3231 rename_data->oldobject = ptr;
3232
3233
3234 rename_data->newpath = strdup(newpath);
3235 if (rename_data->newpath == NULL) {
cbbf9d3e 3236 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for newpath");
84004dbf 3237 free_nfs_rename_data(rename_data);
cbbf9d3e 3238 return -1;
84004dbf 3239 }
93e9306f 3240 ptr = strrchr(rename_data->newpath, '/');
84004dbf 3241 if (ptr == NULL) {
cbbf9d3e 3242 rpc_set_error(nfs->rpc, "Invalid path %s", newpath);
84004dbf 3243 free_nfs_rename_data(rename_data);
cbbf9d3e 3244 return -1;
84004dbf
RS
3245 }
3246 *ptr = 0;
3247 ptr++;
3248 rename_data->newobject = ptr;
3249
3250
3251 if (nfs_lookuppath_async(nfs, rename_data->oldpath, cb, private_data, nfs_rename_continue_1_internal, rename_data, free_nfs_rename_data, 0) != 0) {
cbbf9d3e
RS
3252 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
3253 return -1;
84004dbf
RS
3254 }
3255
3256 return 0;
3257}
3258
3259
3260/*
3261 * Async link()
3262 */
3263struct nfs_link_data {
3264 char *oldpath;
3265 struct nfs_fh3 oldfh;
3266 char *newpath;
3267 char *newobject;
3268 struct nfs_fh3 newdir;
3269};
3270
3271static void free_nfs_link_data(void *mem)
3272{
3273 struct nfs_link_data *data = mem;
3274
3275 if (data->oldpath != NULL) {
3276 free(data->oldpath);
3277 }
3278 if (data->oldfh.data.data_val != NULL) {
3279 free(data->oldfh.data.data_val);
3280 }
3281 if (data->newpath != NULL) {
3282 free(data->newpath);
3283 }
3284 if (data->newdir.data.data_val != NULL) {
3285 free(data->newdir.data.data_val);
3286 }
3287 free(data);
3288}
3289
f3a75078 3290static void nfs_link_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
3291{
3292 LINK3res *res;
3293 struct nfs_cb_data *data = private_data;
3294 struct nfs_context *nfs = data->nfs;
3295 struct nfs_link_data *link_data = data->continue_data;
3296
f3a75078
RS
3297 assert(rpc->magic == RPC_CONTEXT_MAGIC);
3298
84004dbf
RS
3299 if (status == RPC_STATUS_ERROR) {
3300 data->cb(-EFAULT, nfs, command_data, data->private_data);
3301 free_nfs_cb_data(data);
3302 return;
3303 }
3304 if (status == RPC_STATUS_CANCEL) {
3305 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
3306 free_nfs_cb_data(data);
3307 return;
3308 }
3309
3310 res = command_data;
3311 if (res->status != NFS3_OK) {
3312 rpc_set_error(nfs->rpc, "NFS: LINK %s -> %s/%s failed with %s(%d)", link_data->oldpath, link_data->newpath, link_data->newobject, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
3313 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
3314 free_nfs_cb_data(data);
3315 return;
3316 }
3317
3318 data->cb(0, nfs, NULL, data->private_data);
3319 free_nfs_cb_data(data);
3320}
3321
3322static int nfs_link_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
3323{
3324 struct nfs_link_data *link_data = data->continue_data;
3325
3326 /* steal the filehandle */
3327 link_data->newdir.data.data_len = data->fh.data.data_len;
3328 link_data->newdir.data.data_val = data->fh.data.data_val;
3329 data->fh.data.data_val = NULL;
3330
3331 if (rpc_nfs_link_async(nfs->rpc, nfs_link_cb, &link_data->oldfh, &link_data->newdir, link_data->newobject, data) != 0) {
3332 rpc_set_error(nfs->rpc, "RPC error: Failed to send LINK call for %s", data->path);
3333 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
3334 free_nfs_cb_data(data);
3335 return -1;
3336 }
3337 return 0;
3338}
3339
3340
3341static int nfs_link_continue_1_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
3342{
3343 struct nfs_link_data *link_data = data->continue_data;
3344
3345 /* steal the filehandle */
3346 link_data->oldfh.data.data_len = data->fh.data.data_len;
3347 link_data->oldfh.data.data_val = data->fh.data.data_val;
3348 data->fh.data.data_val = NULL;
3349
3350 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) {
3351 rpc_set_error(nfs->rpc, "RPC error: Failed to send LOOKUP call for %s", link_data->newpath);
3352 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
3353 free_nfs_cb_data(data);
3354 return -1;
3355 }
3356 data->continue_data = NULL;
3357 free_nfs_cb_data(data);
3358
3359 return 0;
3360}
3361
3362
3363int nfs_link_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data)
3364{
3365 char *ptr;
3366 struct nfs_link_data *link_data;
3367
3368 link_data = malloc(sizeof(struct nfs_link_data));
3369 if (link_data == NULL) {
cbbf9d3e 3370 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for link data");
84004dbf
RS
3371 return -1;
3372 }
ea98629a 3373 memset(link_data, 0, sizeof(struct nfs_link_data));
84004dbf
RS
3374
3375 link_data->oldpath = strdup(oldpath);
3376 if (link_data->oldpath == NULL) {
cbbf9d3e 3377 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for oldpath");
84004dbf 3378 free_nfs_link_data(link_data);
cbbf9d3e 3379 return -1;
84004dbf
RS
3380 }
3381
3382 link_data->newpath = strdup(newpath);
3383 if (link_data->newpath == NULL) {
cbbf9d3e 3384 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for newpath");
84004dbf 3385 free_nfs_link_data(link_data);
cbbf9d3e 3386 return -1;
84004dbf 3387 }
93e9306f 3388 ptr = strrchr(link_data->newpath, '/');
84004dbf 3389 if (ptr == NULL) {
cbbf9d3e 3390 rpc_set_error(nfs->rpc, "Invalid path %s", newpath);
84004dbf 3391 free_nfs_link_data(link_data);
cbbf9d3e 3392 return -1;
84004dbf
RS
3393 }
3394 *ptr = 0;
3395 ptr++;
3396 link_data->newobject = ptr;
3397
3398
3399 if (nfs_lookuppath_async(nfs, link_data->oldpath, cb, private_data, nfs_link_continue_1_internal, link_data, free_nfs_link_data, 0) != 0) {
cbbf9d3e
RS
3400 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
3401 return -1;
84004dbf
RS
3402 }
3403
3404 return 0;
3405}
3406
3407
3408//qqq replace later with lseek()
183451cf 3409uint64_t nfs_get_current_offset(struct nfsfh *nfsfh)
84004dbf
RS
3410{
3411 return nfsfh->offset;
3412}
3413
17ef62fa
RS
3414
3415
3416/*
3417 * Get the maximum supported READ3 size by the server
3418 */
183451cf 3419uint64_t nfs_get_readmax(struct nfs_context *nfs)
17ef62fa
RS
3420{
3421 return nfs->readmax;
3422}
3423
3424/*
3425 * Get the maximum supported WRITE3 size by the server
3426 */
183451cf 3427uint64_t nfs_get_writemax(struct nfs_context *nfs)
17ef62fa 3428{
763cd6e3 3429 /* Some ZDR libraries can not marshall PDUs bigger than this */
18c27b73
RS
3430 if (nfs->writemax < 32768) {
3431 return nfs->writemax;
3432 }
3433 return 32768;
17ef62fa 3434}
1896d37b
RS
3435
3436void nfs_set_error(struct nfs_context *nfs, char *error_string, ...)
3437{
3438 va_list ap;
1e8994af 3439 char *str = NULL;
1896d37b 3440
1e8994af 3441 va_start(ap, error_string);
2606f9bb
RS
3442 str = malloc(1024);
3443 vsnprintf(str, 1024, error_string, ap);
1896d37b
RS
3444 if (nfs->rpc->error_string != NULL) {
3445 free(nfs->rpc->error_string);
3446 }
1896d37b 3447 nfs->rpc->error_string = str;
a8a1b858 3448 va_end(ap);
1896d37b 3449}
7f0242ca
RS
3450
3451
3452
3453struct mount_cb_data {
3454 rpc_cb cb;
3455 void *private_data;
3456 char *server;
3457};
3458
3459static void free_mount_cb_data(struct mount_cb_data *data)
3460{
3461 if (data->server != NULL) {
3462 free(data->server);
3463 data->server = NULL;
3464 }
3465
3466 free(data);
3467}
3468
3469static void mount_export_5_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
3470{
3471 struct mount_cb_data *data = private_data;
3472
f3a75078
RS
3473 assert(rpc->magic == RPC_CONTEXT_MAGIC);
3474
3475 if (status == RPC_STATUS_ERROR) {
7f0242ca
RS
3476 data->cb(rpc, -EFAULT, command_data, data->private_data);
3477 free_mount_cb_data(data);
3478 return;
3479 }
3480 if (status == RPC_STATUS_CANCEL) {
3481 data->cb(rpc, -EINTR, "Command was cancelled", data->private_data);
3482 free_mount_cb_data(data);
3483 return;
3484 }
3485
3486 data->cb(rpc, 0, command_data, data->private_data);
3487 if (rpc_disconnect(rpc, "normal disconnect") != 0) {
3488 rpc_set_error(rpc, "Failed to disconnect\n");
3489 }
3490 free_mount_cb_data(data);
3491}
3492
3493static void mount_export_4_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
3494{
3495 struct mount_cb_data *data = private_data;
3496
f3a75078
RS
3497 assert(rpc->magic == RPC_CONTEXT_MAGIC);
3498
14a062eb
RS
3499 /* Dont want any more callbacks even if the socket is closed */
3500 rpc->connect_cb = NULL;
3501
7f0242ca
RS
3502 if (status == RPC_STATUS_ERROR) {
3503 data->cb(rpc, -EFAULT, command_data, data->private_data);
3504 free_mount_cb_data(data);
3505 return;
3506 }
3507 if (status == RPC_STATUS_CANCEL) {
3508 data->cb(rpc, -EINTR, "Command was cancelled", data->private_data);
3509 free_mount_cb_data(data);
3510 return;
3511 }
3512
3513 if (rpc_mount_export_async(rpc, mount_export_5_cb, data) != 0) {
3514 data->cb(rpc, -ENOMEM, command_data, data->private_data);
3515 free_mount_cb_data(data);
3516 return;
3517 }
3518}
3519
3520static void mount_export_3_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
3521{
3522 struct mount_cb_data *data = private_data;
3523 uint32_t mount_port;
3524
f3a75078
RS
3525 assert(rpc->magic == RPC_CONTEXT_MAGIC);
3526
3527 if (status == RPC_STATUS_ERROR) {
7f0242ca
RS
3528 data->cb(rpc, -EFAULT, command_data, data->private_data);
3529 free_mount_cb_data(data);
3530 return;
3531 }
3532 if (status == RPC_STATUS_CANCEL) {
3533 data->cb(rpc, -EINTR, "Command was cancelled", data->private_data);
3534 free_mount_cb_data(data);
3535 return;
3536 }
3537
3538 mount_port = *(uint32_t *)command_data;
3539 if (mount_port == 0) {
3540 rpc_set_error(rpc, "RPC error. Mount program is not available");
3541 data->cb(rpc, -ENOENT, command_data, data->private_data);
3542 free_mount_cb_data(data);
3543 return;
3544 }
3545
3546 rpc_disconnect(rpc, "normal disconnect");
3547 if (rpc_connect_async(rpc, data->server, mount_port, mount_export_4_cb, data) != 0) {
3548 data->cb(rpc, -ENOMEM, command_data, data->private_data);
3549 free_mount_cb_data(data);
3550 return;
3551 }
3552}
3553
3554static void mount_export_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
3555{
3556 struct mount_cb_data *data = private_data;
3557
f3a75078
RS
3558 assert(rpc->magic == RPC_CONTEXT_MAGIC);
3559
7f0242ca
RS
3560 if (status == RPC_STATUS_ERROR) {
3561 data->cb(rpc, -EFAULT, command_data, data->private_data);
3562 free_mount_cb_data(data);
3563 return;
3564 }
3565 if (status == RPC_STATUS_CANCEL) {
3566 data->cb(rpc, -EINTR, "Command was cancelled", data->private_data);
3567 free_mount_cb_data(data);
3568 return;
3569 }
3570
5c6b1176 3571 if (rpc_pmap_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, IPPROTO_TCP, mount_export_3_cb, private_data) != 0) {
7f0242ca
RS
3572 data->cb(rpc, -ENOMEM, command_data, data->private_data);
3573 free_mount_cb_data(data);
3574 return;
3575 }
3576}
3577
3578static void mount_export_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
3579{
3580 struct mount_cb_data *data = private_data;
3581
f3a75078
RS
3582 assert(rpc->magic == RPC_CONTEXT_MAGIC);
3583
14a062eb
RS
3584 /* Dont want any more callbacks even if the socket is closed */
3585 rpc->connect_cb = NULL;
3586
7f0242ca
RS
3587 if (status == RPC_STATUS_ERROR) {
3588 data->cb(rpc, -EFAULT, command_data, data->private_data);
3589 free_mount_cb_data(data);
3590 return;
3591 }
3592 if (status == RPC_STATUS_CANCEL) {
3593 data->cb(rpc, -EINTR, "Command was cancelled", data->private_data);
3594 free_mount_cb_data(data);
3595 return;
3596 }
3597
3598 if (rpc_pmap_null_async(rpc, mount_export_2_cb, data) != 0) {
3599 data->cb(rpc, -ENOMEM, command_data, data->private_data);
3600 free_mount_cb_data(data);
3601 return;
3602 }
3603}
3604
3605int mount_getexports_async(struct rpc_context *rpc, const char *server, rpc_cb cb, void *private_data)
3606{
3607 struct mount_cb_data *data;
3608
f3a75078
RS
3609 assert(rpc->magic == RPC_CONTEXT_MAGIC);
3610
7f0242ca
RS
3611 data = malloc(sizeof(struct mount_cb_data));
3612 if (data == NULL) {
3613 return -1;
3614 }
ea98629a 3615 memset(data, 0, sizeof(struct mount_cb_data));
7f0242ca
RS
3616 data->cb = cb;
3617 data->private_data = private_data;
3618 data->server = strdup(server);
3619 if (data->server == NULL) {
3620 free_mount_cb_data(data);
3621 return -1;
3622 }
3623 if (rpc_connect_async(rpc, data->server, 111, mount_export_1_cb, data) != 0) {
3624 free_mount_cb_data(data);
3625 return -1;
3626 }
3627
3628 return 0;
3629}
3630
df5af25f
RS
3631struct rpc_context *nfs_get_rpc_context(struct nfs_context *nfs)
3632{
f3a75078 3633 assert(nfs->rpc->magic == RPC_CONTEXT_MAGIC);
df5af25f
RS
3634 return nfs->rpc;
3635}
3636
b077fdeb
RS
3637const char *nfs_get_server(struct nfs_context *nfs) {
3638 return nfs->server;
3639}
3640
3641const char *nfs_get_export(struct nfs_context *nfs) {
3642 return nfs->export;
3643}
0ad9a1f1 3644
8724c833
RS
3645const struct nfs_fh3 *nfs_get_rootfh(struct nfs_context *nfs) {
3646 return &nfs->rootfh;
3647}
fa3c25be
RS
3648
3649struct nfs_fh3 *nfs_get_fh(struct nfsfh *nfsfh) {
3650 return &nfsfh->fh;
3651}