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