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