2 Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
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.
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.
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/>.
18 * High level api to nfs filesystems
21 #include "win32_compat.h"
25 #include <sys/statvfs.h>
37 #include <sys/types.h>
41 #include "libnfs-raw.h"
42 #include "libnfs-raw-mount.h"
43 #include "libnfs-raw-nfs.h"
44 #include "libnfs-private.h"
47 struct nfsdirent
*entries
;
48 struct nfsdirent
*current
;
58 struct rpc_context
*rpc
;
61 struct nfs_fh3 rootfh
;
66 void nfs_free_nfsdir(struct nfsdir
*nfsdir
)
68 while (nfsdir
->entries
) {
69 struct nfsdirent
*dirent
= nfsdir
->entries
->next
;
70 if (nfsdir
->entries
->name
!= NULL
) {
71 free(nfsdir
->entries
->name
);
73 free(nfsdir
->entries
);
74 nfsdir
->entries
= dirent
;
80 typedef int (*continue_func
)(struct nfs_context
*nfs
, struct nfs_cb_data
*data
);
83 struct nfs_context
*nfs
;
85 char *saved_path
, *path
;
90 continue_func continue_cb
;
92 void (*free_continue_data
)(void *);
97 /* for multi-read/write calls. */
101 off_t start_offset
, max_offset
;
105 struct nfs_mcb_data
{
106 struct nfs_cb_data
*data
;
111 static int nfs_lookup_path_async_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
, struct nfs_fh3
*fh
);
114 void nfs_set_auth(struct nfs_context
*nfs
, struct AUTH
*auth
)
116 rpc_set_auth(nfs
->rpc
, auth
);
119 int nfs_get_fd(struct nfs_context
*nfs
)
121 return rpc_get_fd(nfs
->rpc
);
124 int nfs_which_events(struct nfs_context
*nfs
)
126 return rpc_which_events(nfs
->rpc
);
129 int nfs_service(struct nfs_context
*nfs
, int revents
)
131 return rpc_service(nfs
->rpc
, revents
);
134 char *nfs_get_error(struct nfs_context
*nfs
)
136 return rpc_get_error(nfs
->rpc
);
139 struct nfs_context
*nfs_init_context(void)
141 struct nfs_context
*nfs
;
143 nfs
= malloc(sizeof(struct nfs_context
));
147 nfs
->rpc
= rpc_init_context();
148 if (nfs
->rpc
== NULL
) {
156 nfs
->rootfh
.data
.data_len
= 0;
157 nfs
->rootfh
.data
.data_val
= NULL
;
162 void nfs_destroy_context(struct nfs_context
*nfs
)
164 rpc_destroy_context(nfs
->rpc
);
177 if (nfs
->rootfh
.data
.data_val
!= NULL
) {
178 free(nfs
->rootfh
.data
.data_val
);
179 nfs
->rootfh
.data
.data_val
= NULL
;
185 void free_nfs_cb_data(struct nfs_cb_data
*data
)
187 if (data
->saved_path
!= NULL
) {
188 free(data
->saved_path
);
189 data
->saved_path
= NULL
;
192 if (data
->continue_data
!= NULL
) {
193 data
->free_continue_data(data
->continue_data
);
194 data
->continue_data
= NULL
;
197 if (data
->fh
.data
.data_val
!= NULL
) {
198 free(data
->fh
.data
.data_val
);
199 data
->fh
.data
.data_val
= NULL
;
202 if (data
->buffer
!= NULL
) {
214 static void nfs_mount_10_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
216 struct nfs_cb_data
*data
= private_data
;
217 struct nfs_context
*nfs
= data
->nfs
;
219 if (status
== RPC_STATUS_ERROR
) {
220 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
221 free_nfs_cb_data(data
);
224 if (status
== RPC_STATUS_CANCEL
) {
225 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
226 free_nfs_cb_data(data
);
230 data
->cb(0, nfs
, NULL
, data
->private_data
);
231 free_nfs_cb_data(data
);
234 static void nfs_mount_9_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
236 struct nfs_cb_data
*data
= private_data
;
237 struct nfs_context
*nfs
= data
->nfs
;
238 FSINFO3res
*res
= command_data
;
240 if (status
== RPC_STATUS_ERROR
) {
241 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
242 free_nfs_cb_data(data
);
245 if (status
== RPC_STATUS_CANCEL
) {
246 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
247 free_nfs_cb_data(data
);
251 nfs
->readmax
= res
->FSINFO3res_u
.resok
.rtmax
;
252 nfs
->writemax
= res
->FSINFO3res_u
.resok
.wtmax
;
254 if (rpc_nfs_getattr_async(rpc
, nfs_mount_10_cb
, &nfs
->rootfh
, data
) != 0) {
255 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
256 free_nfs_cb_data(data
);
261 static void nfs_mount_8_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
263 struct nfs_cb_data
*data
= private_data
;
264 struct nfs_context
*nfs
= data
->nfs
;
266 if (status
== RPC_STATUS_ERROR
) {
267 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
268 free_nfs_cb_data(data
);
271 if (status
== RPC_STATUS_CANCEL
) {
272 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
273 free_nfs_cb_data(data
);
277 if (rpc_nfs_fsinfo_async(rpc
, nfs_mount_9_cb
, &nfs
->rootfh
, data
) != 0) {
278 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
279 free_nfs_cb_data(data
);
285 static void nfs_mount_7_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
287 struct nfs_cb_data
*data
= private_data
;
288 struct nfs_context
*nfs
= data
->nfs
;
290 if (status
== RPC_STATUS_ERROR
) {
291 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
292 free_nfs_cb_data(data
);
295 if (status
== RPC_STATUS_CANCEL
) {
296 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
297 free_nfs_cb_data(data
);
301 if (rpc_nfs_null_async(rpc
, nfs_mount_8_cb
, data
) != 0) {
302 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
303 free_nfs_cb_data(data
);
309 static void nfs_mount_6_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
311 struct nfs_cb_data
*data
= private_data
;
312 struct nfs_context
*nfs
= data
->nfs
;
315 if (status
== RPC_STATUS_ERROR
) {
316 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
317 free_nfs_cb_data(data
);
320 if (status
== RPC_STATUS_CANCEL
) {
321 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
322 free_nfs_cb_data(data
);
327 if (res
->fhs_status
!= MNT3_OK
) {
328 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
));
329 data
->cb(mountstat3_to_errno(res
->fhs_status
), nfs
, rpc_get_error(rpc
), data
->private_data
);
330 free_nfs_cb_data(data
);
334 nfs
->rootfh
.data
.data_len
= res
->mountres3_u
.mountinfo
.fhandle
.fhandle3_len
;
335 nfs
->rootfh
.data
.data_val
= malloc(nfs
->rootfh
.data
.data_len
);
336 if (nfs
->rootfh
.data
.data_val
== NULL
) {
337 rpc_set_error(rpc
, "Out of memory. Could not allocate memory to store root filehandle");
338 data
->cb(-ENOMEM
, nfs
, rpc_get_error(rpc
), data
->private_data
);
339 free_nfs_cb_data(data
);
342 memcpy(nfs
->rootfh
.data
.data_val
, res
->mountres3_u
.mountinfo
.fhandle
.fhandle3_val
, nfs
->rootfh
.data
.data_len
);
344 rpc_disconnect(rpc
, "normal disconnect");
345 if (rpc_connect_async(rpc
, nfs
->server
, 2049, nfs_mount_7_cb
, data
) != 0) {
346 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
347 free_nfs_cb_data(data
);
353 static void nfs_mount_5_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
355 struct nfs_cb_data
*data
= private_data
;
356 struct nfs_context
*nfs
= data
->nfs
;
358 if (status
== RPC_STATUS_ERROR
) {
359 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
360 free_nfs_cb_data(data
);
363 if (status
== RPC_STATUS_CANCEL
) {
364 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
365 free_nfs_cb_data(data
);
369 if (rpc_mount_mnt_async(rpc
, nfs_mount_6_cb
, nfs
->export
, data
) != 0) {
370 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
371 free_nfs_cb_data(data
);
376 static void nfs_mount_4_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
378 struct nfs_cb_data
*data
= private_data
;
379 struct nfs_context
*nfs
= data
->nfs
;
381 if (status
== RPC_STATUS_ERROR
) {
382 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
383 free_nfs_cb_data(data
);
386 if (status
== RPC_STATUS_CANCEL
) {
387 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
388 free_nfs_cb_data(data
);
392 if (rpc_mount_null_async(rpc
, nfs_mount_5_cb
, data
) != 0) {
393 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
394 free_nfs_cb_data(data
);
399 static void nfs_mount_3_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
401 struct nfs_cb_data
*data
= private_data
;
402 struct nfs_context
*nfs
= data
->nfs
;
405 if (status
== RPC_STATUS_ERROR
) {
406 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
407 free_nfs_cb_data(data
);
410 if (status
== RPC_STATUS_CANCEL
) {
411 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
412 free_nfs_cb_data(data
);
416 mount_port
= *(uint32_t *)command_data
;
417 if (mount_port
== 0) {
418 rpc_set_error(rpc
, "RPC error. Mount program is not available on %s", nfs
->server
);
419 data
->cb(-ENOENT
, nfs
, command_data
, data
->private_data
);
420 free_nfs_cb_data(data
);
424 rpc_disconnect(rpc
, "normal disconnect");
425 if (rpc_connect_async(rpc
, nfs
->server
, mount_port
, nfs_mount_4_cb
, data
) != 0) {
426 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
427 free_nfs_cb_data(data
);
433 static void nfs_mount_2_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
435 struct nfs_cb_data
*data
= private_data
;
436 struct nfs_context
*nfs
= data
->nfs
;
438 if (status
== RPC_STATUS_ERROR
) {
439 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
440 free_nfs_cb_data(data
);
443 if (status
== RPC_STATUS_CANCEL
) {
444 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
445 free_nfs_cb_data(data
);
449 if (rpc_pmap_getport_async(rpc
, MOUNT_PROGRAM
, MOUNT_V3
, nfs_mount_3_cb
, private_data
) != 0) {
450 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
451 free_nfs_cb_data(data
);
456 static void nfs_mount_1_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
458 struct nfs_cb_data
*data
= private_data
;
459 struct nfs_context
*nfs
= data
->nfs
;
461 if (status
== RPC_STATUS_ERROR
) {
462 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
463 free_nfs_cb_data(data
);
466 if (status
== RPC_STATUS_CANCEL
) {
467 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
468 free_nfs_cb_data(data
);
472 if (rpc_pmap_null_async(rpc
, nfs_mount_2_cb
, data
) != 0) {
473 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
474 free_nfs_cb_data(data
);
480 * Async call for mounting an nfs share and geting the root filehandle
482 int nfs_mount_async(struct nfs_context
*nfs
, const char *server
, const char *export
, nfs_cb cb
, void *private_data
)
484 struct nfs_cb_data
*data
;
485 char *new_server
, *new_export
;
487 data
= malloc(sizeof(struct nfs_cb_data
));
489 rpc_set_error(nfs
->rpc
, "out of memory. failed to allocate memory for nfs mount data");
492 memset(data
, 0, sizeof(struct nfs_cb_data
));
493 new_server
= strdup(server
);
494 new_export
= strdup(export
);
495 if (nfs
->server
!= NULL
) {
499 nfs
->server
= new_server
;
500 if (nfs
->export
!= NULL
) {
504 nfs
->export
= new_export
;
507 data
->private_data
= private_data
;
509 if (rpc_connect_async(nfs
->rpc
, server
, 111, nfs_mount_1_cb
, data
) != 0) {
510 rpc_set_error(nfs
->rpc
, "Failed to start connection");
511 free_nfs_cb_data(data
);
521 * Functions to first look up a path, component by component, and then finally call a specific function once
522 * the filehandle for the final component is found.
524 static void nfs_lookup_path_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
526 struct nfs_cb_data
*data
= private_data
;
527 struct nfs_context
*nfs
= data
->nfs
;
530 if (status
== RPC_STATUS_ERROR
) {
531 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
532 free_nfs_cb_data(data
);
535 if (status
== RPC_STATUS_CANCEL
) {
536 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
537 free_nfs_cb_data(data
);
542 if (res
->status
!= NFS3_OK
) {
543 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
));
544 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
545 free_nfs_cb_data(data
);
549 if (nfs_lookup_path_async_internal(nfs
, data
, &res
->LOOKUP3res_u
.resok
.object
) != 0) {
550 rpc_set_error(nfs
->rpc
, "Failed to create lookup pdu");
551 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
552 free_nfs_cb_data(data
);
557 static int nfs_lookup_path_async_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
, struct nfs_fh3
*fh
)
561 while (*data
->path
== '/') {
566 str
= strchr(path
, '/');
571 while (*data
->path
!= 0) {
577 data
->fh
.data
.data_len
= fh
->data
.data_len
;
578 data
->fh
.data
.data_val
= malloc(data
->fh
.data
.data_len
);
579 if (data
->fh
.data
.data_val
== NULL
) {
580 rpc_set_error(nfs
->rpc
, "Out of memory: Failed to allocate fh for %s", data
->path
);
581 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
582 free_nfs_cb_data(data
);
585 memcpy(data
->fh
.data
.data_val
, fh
->data
.data_val
, data
->fh
.data
.data_len
);
586 data
->continue_cb(nfs
, data
);
590 if (rpc_nfs_lookup_async(nfs
->rpc
, nfs_lookup_path_1_cb
, fh
, path
, data
) != 0) {
591 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send lookup call for %s", data
->path
);
592 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
593 free_nfs_cb_data(data
);
599 static 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
)
601 struct nfs_cb_data
*data
;
603 if (path
[0] != '/') {
604 rpc_set_error(nfs
->rpc
, "Pathname is not absulute %s", path
);
608 data
= malloc(sizeof(struct nfs_cb_data
));
610 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
613 memset(data
, 0, sizeof(struct nfs_cb_data
));
616 data
->continue_cb
= continue_cb
;
617 data
->continue_data
= continue_data
;
618 data
->free_continue_data
= free_continue_data
;
619 data
->continue_int
= continue_int
;
620 data
->private_data
= private_data
;
621 data
->saved_path
= strdup(path
);
622 if (data
->saved_path
== NULL
) {
623 rpc_set_error(nfs
->rpc
, "out of memory: failed to copy path string");
624 free_nfs_cb_data(data
);
627 data
->path
= data
->saved_path
;
629 if (nfs_lookup_path_async_internal(nfs
, data
, &nfs
->rootfh
) != 0) {
630 /* return 0 here since the callback will be invoked if there is a failure */
643 static void nfs_stat_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
646 struct nfs_cb_data
*data
= private_data
;
647 struct nfs_context
*nfs
= data
->nfs
;
650 if (status
== RPC_STATUS_ERROR
) {
651 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
652 free_nfs_cb_data(data
);
655 if (status
== RPC_STATUS_CANCEL
) {
656 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
657 free_nfs_cb_data(data
);
662 if (res
->status
!= NFS3_OK
) {
663 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
));
664 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
665 free_nfs_cb_data(data
);
670 st
.st_ino
= res
->GETATTR3res_u
.resok
.obj_attributes
.fileid
;
671 st
.st_mode
= res
->GETATTR3res_u
.resok
.obj_attributes
.mode
;
672 if (res
->GETATTR3res_u
.resok
.obj_attributes
.type
== NF3DIR
) {
673 st
.st_mode
|= S_IFDIR
;
675 st
.st_nlink
= res
->GETATTR3res_u
.resok
.obj_attributes
.nlink
;
676 st
.st_uid
= res
->GETATTR3res_u
.resok
.obj_attributes
.uid
;
677 st
.st_gid
= res
->GETATTR3res_u
.resok
.obj_attributes
.gid
;
679 st
.st_size
= res
->GETATTR3res_u
.resok
.obj_attributes
.size
;
681 st
.st_blksize
= 4096;
682 st
.st_blocks
= res
->GETATTR3res_u
.resok
.obj_attributes
.size
/ 4096;
684 st
.st_atime
= res
->GETATTR3res_u
.resok
.obj_attributes
.atime
.seconds
;
685 st
.st_mtime
= res
->GETATTR3res_u
.resok
.obj_attributes
.mtime
.seconds
;
686 st
.st_ctime
= res
->GETATTR3res_u
.resok
.obj_attributes
.ctime
.seconds
;
688 data
->cb(0, nfs
, &st
, data
->private_data
);
689 free_nfs_cb_data(data
);
692 static int nfs_stat_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
694 if (rpc_nfs_getattr_async(nfs
->rpc
, nfs_stat_1_cb
, &data
->fh
, data
) != 0) {
695 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send STAT GETATTR call for %s", data
->path
);
696 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
697 free_nfs_cb_data(data
);
703 int nfs_stat_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
705 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_stat_continue_internal
, NULL
, NULL
, 0) != 0) {
706 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
720 static void nfs_open_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
723 struct nfs_cb_data
*data
= private_data
;
724 struct nfs_context
*nfs
= data
->nfs
;
726 unsigned int nfsmode
= 0;
728 if (status
== RPC_STATUS_ERROR
) {
729 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
730 free_nfs_cb_data(data
);
733 if (status
== RPC_STATUS_CANCEL
) {
734 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
735 free_nfs_cb_data(data
);
740 if (res
->status
!= NFS3_OK
) {
741 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
));
742 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
743 free_nfs_cb_data(data
);
747 if (data
->continue_int
& O_WRONLY
) {
748 nfsmode
|= ACCESS3_MODIFY
;
750 if (data
->continue_int
& O_RDWR
) {
751 nfsmode
|= ACCESS3_READ
|ACCESS3_MODIFY
;
753 if (!(data
->continue_int
& (O_WRONLY
|O_RDWR
))) {
754 nfsmode
|= ACCESS3_READ
;
758 if (res
->ACCESS3res_u
.resok
.access
!= nfsmode
) {
759 rpc_set_error(nfs
->rpc
, "NFS: ACCESS denied. Required access %c%c%c. Allowed access %c%c%c",
760 nfsmode
&ACCESS3_READ
?'r':'-',
761 nfsmode
&ACCESS3_MODIFY
?'w':'-',
762 nfsmode
&ACCESS3_EXECUTE
?'x':'-',
763 res
->ACCESS3res_u
.resok
.access
&ACCESS3_READ
?'r':'-',
764 res
->ACCESS3res_u
.resok
.access
&ACCESS3_MODIFY
?'w':'-',
765 res
->ACCESS3res_u
.resok
.access
&ACCESS3_EXECUTE
?'x':'-');
766 data
->cb(-EACCES
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
767 free_nfs_cb_data(data
);
771 nfsfh
= malloc(sizeof(struct nfsfh
));
773 rpc_set_error(nfs
->rpc
, "NFS: Failed to allocate nfsfh structure");
774 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
775 free_nfs_cb_data(data
);
778 memset(nfsfh
, 0, sizeof(struct nfsfh
));
780 if (data
->continue_int
& O_SYNC
) {
784 /* steal the filehandle */
785 nfsfh
->fh
.data
.data_len
= data
->fh
.data
.data_len
;
786 nfsfh
->fh
.data
.data_val
= data
->fh
.data
.data_val
;
787 data
->fh
.data
.data_val
= NULL
;
789 data
->cb(0, nfs
, nfsfh
, data
->private_data
);
790 free_nfs_cb_data(data
);
793 static int nfs_open_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
797 if (data
->continue_int
& O_WRONLY
) {
798 nfsmode
|= ACCESS3_MODIFY
;
800 if (data
->continue_int
& O_RDWR
) {
801 nfsmode
|= ACCESS3_READ
|ACCESS3_MODIFY
;
803 if (!(data
->continue_int
& (O_WRONLY
|O_RDWR
))) {
804 nfsmode
|= ACCESS3_READ
;
807 if (rpc_nfs_access_async(nfs
->rpc
, nfs_open_cb
, &data
->fh
, nfsmode
, data
) != 0) {
808 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send OPEN ACCESS call for %s", data
->path
);
809 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
810 free_nfs_cb_data(data
);
816 int nfs_open_async(struct nfs_context
*nfs
, const char *path
, int mode
, nfs_cb cb
, void *private_data
)
818 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_open_continue_internal
, NULL
, NULL
, mode
) != 0) {
819 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
833 static void nfs_pread_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
835 struct nfs_cb_data
*data
= private_data
;
836 struct nfs_context
*nfs
= data
->nfs
;
839 if (status
== RPC_STATUS_ERROR
) {
840 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
841 free_nfs_cb_data(data
);
844 if (status
== RPC_STATUS_CANCEL
) {
845 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
846 free_nfs_cb_data(data
);
851 if (res
->status
!= NFS3_OK
) {
852 rpc_set_error(nfs
->rpc
, "NFS: Read failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
853 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
854 free_nfs_cb_data(data
);
858 data
->nfsfh
->offset
+= res
->READ3res_u
.resok
.count
;
859 data
->cb(res
->READ3res_u
.resok
.count
, nfs
, res
->READ3res_u
.resok
.data
.data_val
, data
->private_data
);
860 free_nfs_cb_data(data
);
863 static void nfs_pread_mcb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
865 struct nfs_mcb_data
*mdata
= private_data
;
866 struct nfs_cb_data
*data
= mdata
->data
;
867 struct nfs_context
*nfs
= data
->nfs
;
872 if (status
== RPC_STATUS_ERROR
) {
873 /* flag the failure but do not invoke callback until we have received all responses */
876 if (status
== RPC_STATUS_CANCEL
) {
877 /* flag the cancellation but do not invoke callback until we have received all responses */
881 /* reassemble the data into the buffer */
882 if (status
== RPC_STATUS_SUCCESS
) {
884 if (res
->status
!= NFS3_OK
) {
885 rpc_set_error(nfs
->rpc
, "NFS: Read failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
888 if (res
->READ3res_u
.resok
.count
> 0) {
889 memcpy(&data
->buffer
[mdata
->offset
- data
->start_offset
], res
->READ3res_u
.resok
.data
.data_val
, res
->READ3res_u
.resok
.count
);
890 if ((unsigned)data
->max_offset
< mdata
->offset
+ res
->READ3res_u
.resok
.count
) {
891 data
->max_offset
= mdata
->offset
+ res
->READ3res_u
.resok
.count
;
897 if (data
->num_calls
> 0) {
898 /* still waiting for more replies */
903 if (data
->error
!= 0) {
904 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
905 free_nfs_cb_data(data
);
909 if (data
->cancel
!= 0) {
910 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
911 free_nfs_cb_data(data
);
916 data
->nfsfh
->offset
= data
->max_offset
;
917 data
->cb(data
->max_offset
- data
->start_offset
, nfs
, data
->buffer
, data
->private_data
);
919 free_nfs_cb_data(data
);
923 int nfs_pread_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, size_t count
, nfs_cb cb
, void *private_data
)
925 struct nfs_cb_data
*data
;
927 data
= malloc(sizeof(struct nfs_cb_data
));
929 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
932 memset(data
, 0, sizeof(struct nfs_cb_data
));
935 data
->private_data
= private_data
;
938 nfsfh
->offset
= offset
;
940 if (count
<= nfs_get_readmax(nfs
)) {
941 if (rpc_nfs_read_async(nfs
->rpc
, nfs_pread_cb
, &nfsfh
->fh
, offset
, count
, data
) != 0) {
942 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send READ call for %s", data
->path
);
943 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
944 free_nfs_cb_data(data
);
950 /* trying to read more than maximum server read size, we has to chop it up into smaller
951 * reads and collect into a reassembly buffer.
952 * we send all reads in parallell so that performance is still good.
954 data
->max_offset
= offset
;
955 data
->start_offset
= offset
;
957 data
->buffer
= malloc(count
);
958 if (data
->buffer
== NULL
) {
959 rpc_set_error(nfs
->rpc
, "Out-Of-Memory: Failed to allocate reassembly buffer for %d bytes", (int)count
);
960 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
961 free_nfs_cb_data(data
);
966 size_t readcount
= count
;
967 struct nfs_mcb_data
*mdata
;
969 if (readcount
> nfs_get_readmax(nfs
)) {
970 readcount
= nfs_get_readmax(nfs
);
973 mdata
= malloc(sizeof(struct nfs_mcb_data
));
975 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_mcb_data structure");
978 memset(mdata
, 0, sizeof(struct nfs_mcb_data
));
980 mdata
->offset
= offset
;
981 mdata
->count
= readcount
;
982 if (rpc_nfs_read_async(nfs
->rpc
, nfs_pread_mcb
, &nfsfh
->fh
, offset
, readcount
, mdata
) != 0) {
983 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send READ call for %s", data
->path
);
984 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1000 int nfs_read_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, size_t count
, nfs_cb cb
, void *private_data
)
1002 return nfs_pread_async(nfs
, nfsfh
, nfsfh
->offset
, count
, cb
, private_data
);
1010 static void nfs_pwrite_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1012 struct nfs_cb_data
*data
= private_data
;
1013 struct nfs_context
*nfs
= data
->nfs
;
1016 if (status
== RPC_STATUS_ERROR
) {
1017 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1018 free_nfs_cb_data(data
);
1021 if (status
== RPC_STATUS_CANCEL
) {
1022 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1023 free_nfs_cb_data(data
);
1028 if (res
->status
!= NFS3_OK
) {
1029 rpc_set_error(nfs
->rpc
, "NFS: Write failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
1030 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1031 free_nfs_cb_data(data
);
1035 data
->nfsfh
->offset
+= res
->WRITE3res_u
.resok
.count
;
1036 data
->cb(res
->WRITE3res_u
.resok
.count
, nfs
, NULL
, data
->private_data
);
1037 free_nfs_cb_data(data
);
1040 int nfs_pwrite_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, size_t count
, char *buf
, nfs_cb cb
, void *private_data
)
1042 struct nfs_cb_data
*data
;
1044 data
= malloc(sizeof(struct nfs_cb_data
));
1046 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
1049 memset(data
, 0, sizeof(struct nfs_cb_data
));
1052 data
->private_data
= private_data
;
1053 data
->nfsfh
= nfsfh
;
1055 nfsfh
->offset
= offset
;
1056 if (rpc_nfs_write_async(nfs
->rpc
, nfs_pwrite_cb
, &nfsfh
->fh
, buf
, offset
, count
, nfsfh
->is_sync
?FILE_SYNC
:UNSTABLE
, data
) != 0) {
1057 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send WRITE call for %s", data
->path
);
1058 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1059 free_nfs_cb_data(data
);
1068 int nfs_write_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, size_t count
, char *buf
, nfs_cb cb
, void *private_data
)
1070 return nfs_pwrite_async(nfs
, nfsfh
, nfsfh
->offset
, count
, buf
, cb
, private_data
);
1080 int nfs_close_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, nfs_cb cb
, void *private_data
)
1082 if (nfsfh
->fh
.data
.data_val
!= NULL
){
1083 free(nfsfh
->fh
.data
.data_val
);
1084 nfsfh
->fh
.data
.data_val
= NULL
;
1088 cb(0, nfs
, NULL
, private_data
);
1099 int nfs_fstat_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, nfs_cb cb
, void *private_data
)
1101 struct nfs_cb_data
*data
;
1103 data
= malloc(sizeof(struct nfs_cb_data
));
1105 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
1108 memset(data
, 0, sizeof(struct nfs_cb_data
));
1111 data
->private_data
= private_data
;
1113 if (rpc_nfs_getattr_async(nfs
->rpc
, nfs_stat_1_cb
, &nfsfh
->fh
, data
) != 0) {
1114 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send STAT GETATTR call for %s", data
->path
);
1115 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1116 free_nfs_cb_data(data
);
1127 static void nfs_fsync_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1129 struct nfs_cb_data
*data
= private_data
;
1130 struct nfs_context
*nfs
= data
->nfs
;
1133 if (status
== RPC_STATUS_ERROR
) {
1134 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1135 free_nfs_cb_data(data
);
1138 if (status
== RPC_STATUS_CANCEL
) {
1139 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1140 free_nfs_cb_data(data
);
1145 if (res
->status
!= NFS3_OK
) {
1146 rpc_set_error(nfs
->rpc
, "NFS: Commit failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
1147 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1148 free_nfs_cb_data(data
);
1152 data
->cb(0, nfs
, NULL
, data
->private_data
);
1153 free_nfs_cb_data(data
);
1156 int nfs_fsync_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, nfs_cb cb
, void *private_data
)
1158 struct nfs_cb_data
*data
;
1160 data
= malloc(sizeof(struct nfs_cb_data
));
1162 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
1165 memset(data
, 0, sizeof(struct nfs_cb_data
));
1168 data
->private_data
= private_data
;
1170 if (rpc_nfs_commit_async(nfs
->rpc
, nfs_fsync_cb
, &nfsfh
->fh
, data
) != 0) {
1171 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send COMMIT call for %s", data
->path
);
1172 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1173 free_nfs_cb_data(data
);
1185 static void nfs_ftruncate_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1187 struct nfs_cb_data
*data
= private_data
;
1188 struct nfs_context
*nfs
= data
->nfs
;
1191 if (status
== RPC_STATUS_ERROR
) {
1192 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1193 free_nfs_cb_data(data
);
1196 if (status
== RPC_STATUS_CANCEL
) {
1197 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1198 free_nfs_cb_data(data
);
1203 if (res
->status
!= NFS3_OK
) {
1204 rpc_set_error(nfs
->rpc
, "NFS: Setattr failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
1205 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1206 free_nfs_cb_data(data
);
1210 data
->cb(0, nfs
, NULL
, data
->private_data
);
1211 free_nfs_cb_data(data
);
1214 int nfs_ftruncate_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t length
, nfs_cb cb
, void *private_data
)
1216 struct nfs_cb_data
*data
;
1219 data
= malloc(sizeof(struct nfs_cb_data
));
1221 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
1224 memset(data
, 0, sizeof(struct nfs_cb_data
));
1227 data
->private_data
= private_data
;
1229 memset(&args
, 0, sizeof(SETATTR3args
));
1230 args
.object
.data
.data_len
= nfsfh
->fh
.data
.data_len
;
1231 args
.object
.data
.data_val
= nfsfh
->fh
.data
.data_val
;
1232 args
.new_attributes
.size
.set_it
= 1;
1233 args
.new_attributes
.size
.set_size3_u
.size
= length
;
1235 if (rpc_nfs_setattr_async(nfs
->rpc
, nfs_ftruncate_cb
, &args
, data
) != 0) {
1236 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SETATTR call for %s", data
->path
);
1237 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1238 free_nfs_cb_data(data
);
1248 static int nfs_truncate_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1250 off_t offset
= data
->continue_int
;
1253 nfsfh
.fh
.data
.data_val
= data
->fh
.data
.data_val
;
1254 nfsfh
.fh
.data
.data_len
= data
->fh
.data
.data_len
;
1256 if (nfs_ftruncate_async(nfs
, &nfsfh
, offset
, data
->cb
, data
->private_data
) != 0) {
1257 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SETATTR call for %s", data
->path
);
1258 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1259 free_nfs_cb_data(data
);
1262 free_nfs_cb_data(data
);
1266 int nfs_truncate_async(struct nfs_context
*nfs
, const char *path
, off_t length
, nfs_cb cb
, void *private_data
)
1272 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_truncate_continue_internal
, NULL
, NULL
, offset
) != 0) {
1273 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
1286 static void nfs_mkdir_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1289 struct nfs_cb_data
*data
= private_data
;
1290 struct nfs_context
*nfs
= data
->nfs
;
1291 char *str
= data
->continue_data
;
1293 str
= &str
[strlen(str
) + 1];
1295 if (status
== RPC_STATUS_ERROR
) {
1296 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1297 free_nfs_cb_data(data
);
1300 if (status
== RPC_STATUS_CANCEL
) {
1301 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1302 free_nfs_cb_data(data
);
1307 if (res
->status
!= NFS3_OK
) {
1308 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
));
1309 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1310 free_nfs_cb_data(data
);
1314 data
->cb(0, nfs
, NULL
, data
->private_data
);
1315 free_nfs_cb_data(data
);
1318 static int nfs_mkdir_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1320 char *str
= data
->continue_data
;
1322 str
= &str
[strlen(str
) + 1];
1324 if (rpc_nfs_mkdir_async(nfs
->rpc
, nfs_mkdir_cb
, &data
->fh
, str
, data
) != 0) {
1325 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send MKDIR call for %s", data
->path
);
1326 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1327 free_nfs_cb_data(data
);
1333 int nfs_mkdir_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1338 new_path
= strdup(path
);
1339 if (new_path
== NULL
) {
1340 rpc_set_error(nfs
->rpc
, "Out of memory, failed to allocate mode buffer for path");
1344 ptr
= strrchr(new_path
, '/');
1346 rpc_set_error(nfs
->rpc
, "Invalid path %s", path
);
1351 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1352 if (nfs_lookuppath_async(nfs
, new_path
, cb
, private_data
, nfs_mkdir_continue_internal
, new_path
, free
, 0) != 0) {
1353 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path component");
1367 static void nfs_rmdir_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1370 struct nfs_cb_data
*data
= private_data
;
1371 struct nfs_context
*nfs
= data
->nfs
;
1372 char *str
= data
->continue_data
;
1374 str
= &str
[strlen(str
) + 1];
1376 if (status
== RPC_STATUS_ERROR
) {
1377 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1378 free_nfs_cb_data(data
);
1381 if (status
== RPC_STATUS_CANCEL
) {
1382 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1383 free_nfs_cb_data(data
);
1388 if (res
->status
!= NFS3_OK
) {
1389 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
));
1390 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1391 free_nfs_cb_data(data
);
1395 data
->cb(0, nfs
, NULL
, data
->private_data
);
1396 free_nfs_cb_data(data
);
1399 static int nfs_rmdir_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1401 char *str
= data
->continue_data
;
1403 str
= &str
[strlen(str
) + 1];
1405 if (rpc_nfs_rmdir_async(nfs
->rpc
, nfs_rmdir_cb
, &data
->fh
, str
, data
) != 0) {
1406 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send RMDIR call for %s", data
->path
);
1407 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1408 free_nfs_cb_data(data
);
1414 int nfs_rmdir_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1419 new_path
= strdup(path
);
1420 if (new_path
== NULL
) {
1421 rpc_set_error(nfs
->rpc
, "Out of memory, failed to allocate mode buffer for path");
1425 ptr
= strrchr(new_path
, '/');
1427 rpc_set_error(nfs
->rpc
, "Invalid path %s", path
);
1432 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1433 if (nfs_lookuppath_async(nfs
, new_path
, cb
, private_data
, nfs_rmdir_continue_internal
, new_path
, free
, 0) != 0) {
1434 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
1447 static void nfs_create_2_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1450 struct nfs_cb_data
*data
= private_data
;
1451 struct nfs_context
*nfs
= data
->nfs
;
1452 struct nfsfh
*nfsfh
;
1453 char *str
= data
->continue_data
;
1455 if (status
== RPC_STATUS_ERROR
) {
1456 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1457 free_nfs_cb_data(data
);
1460 if (status
== RPC_STATUS_CANCEL
) {
1461 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1462 free_nfs_cb_data(data
);
1466 str
= &str
[strlen(str
) + 1];
1468 if (res
->status
!= NFS3_OK
) {
1469 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
));
1470 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1475 nfsfh
= malloc(sizeof(struct nfsfh
));
1476 if (nfsfh
== NULL
) {
1477 rpc_set_error(nfs
->rpc
, "NFS: Failed to allocate nfsfh structure");
1478 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1479 free_nfs_cb_data(data
);
1482 memset(nfsfh
, 0, sizeof(struct nfsfh
));
1484 /* steal the filehandle */
1485 nfsfh
->fh
.data
.data_len
= data
->fh
.data
.data_len
;
1486 nfsfh
->fh
.data
.data_val
= data
->fh
.data
.data_val
;
1487 data
->fh
.data
.data_val
= NULL
;
1489 data
->cb(0, nfs
, nfsfh
, data
->private_data
);
1490 free_nfs_cb_data(data
);
1495 static void nfs_creat_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1498 struct nfs_cb_data
*data
= private_data
;
1499 struct nfs_context
*nfs
= data
->nfs
;
1500 char *str
= data
->continue_data
;
1502 if (status
== RPC_STATUS_ERROR
) {
1503 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1504 free_nfs_cb_data(data
);
1507 if (status
== RPC_STATUS_CANCEL
) {
1508 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1509 free_nfs_cb_data(data
);
1513 str
= &str
[strlen(str
) + 1];
1515 if (res
->status
!= NFS3_OK
) {
1516 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
));
1517 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1522 if (rpc_nfs_lookup_async(nfs
->rpc
, nfs_create_2_cb
, &data
->fh
, str
, data
) != 0) {
1523 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send lookup call for %s/%s", data
->saved_path
, str
);
1524 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1525 free_nfs_cb_data(data
);
1531 static int nfs_creat_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1533 char *str
= data
->continue_data
;
1535 str
= &str
[strlen(str
) + 1];
1537 if (rpc_nfs_create_async(nfs
->rpc
, nfs_creat_1_cb
, &data
->fh
, str
, data
->continue_int
, data
) != 0) {
1538 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send CREATE call for %s/%s", data
->path
, str
);
1539 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1540 free_nfs_cb_data(data
);
1546 int nfs_creat_async(struct nfs_context
*nfs
, const char *path
, int mode
, nfs_cb cb
, void *private_data
)
1551 new_path
= strdup(path
);
1552 if (new_path
== NULL
) {
1553 rpc_set_error(nfs
->rpc
, "Out of memory, failed to allocate mode buffer for path");
1557 ptr
= strrchr(new_path
, '/');
1559 rpc_set_error(nfs
->rpc
, "Invalid path %s", path
);
1564 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1565 if (nfs_lookuppath_async(nfs
, new_path
, cb
, private_data
, nfs_creat_continue_internal
, new_path
, free
, mode
) != 0) {
1566 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
1579 static void nfs_unlink_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1582 struct nfs_cb_data
*data
= private_data
;
1583 struct nfs_context
*nfs
= data
->nfs
;
1584 char *str
= data
->continue_data
;
1586 str
= &str
[strlen(str
) + 1];
1588 if (status
== RPC_STATUS_ERROR
) {
1589 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1590 free_nfs_cb_data(data
);
1593 if (status
== RPC_STATUS_CANCEL
) {
1594 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1595 free_nfs_cb_data(data
);
1600 if (res
->status
!= NFS3_OK
) {
1601 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
));
1602 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1603 free_nfs_cb_data(data
);
1607 data
->cb(0, nfs
, NULL
, data
->private_data
);
1608 free_nfs_cb_data(data
);
1611 static int nfs_unlink_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1613 char *str
= data
->continue_data
;
1615 str
= &str
[strlen(str
) + 1];
1617 if (rpc_nfs_remove_async(nfs
->rpc
, nfs_unlink_cb
, &data
->fh
, str
, data
) != 0) {
1618 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send REMOVE call for %s", data
->path
);
1619 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1620 free_nfs_cb_data(data
);
1626 int nfs_unlink_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1631 new_path
= strdup(path
);
1632 if (new_path
== NULL
) {
1633 rpc_set_error(nfs
->rpc
, "Out of memory, failed to allocate mode buffer for path");
1637 ptr
= strrchr(new_path
, '/');
1639 rpc_set_error(nfs
->rpc
, "Invalid path %s", path
);
1644 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1645 if (nfs_lookuppath_async(nfs
, new_path
, cb
, private_data
, nfs_unlink_continue_internal
, new_path
, free
, 0) != 0) {
1646 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
1660 static void nfs_opendir_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1662 READDIRPLUS3res
*res
;
1663 struct nfs_cb_data
*data
= private_data
;
1664 struct nfs_context
*nfs
= data
->nfs
;
1665 struct nfsdir
*nfsdir
= data
->continue_data
;
1666 struct entryplus3
*entry
;
1669 if (status
== RPC_STATUS_ERROR
) {
1670 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1671 nfs_free_nfsdir(nfsdir
);
1672 data
->continue_data
= NULL
;
1673 free_nfs_cb_data(data
);
1676 if (status
== RPC_STATUS_CANCEL
) {
1677 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1678 nfs_free_nfsdir(nfsdir
);
1679 data
->continue_data
= NULL
;
1680 free_nfs_cb_data(data
);
1685 if (res
->status
!= NFS3_OK
) {
1686 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
));
1687 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1688 nfs_free_nfsdir(nfsdir
);
1689 data
->continue_data
= NULL
;
1690 free_nfs_cb_data(data
);
1694 entry
=res
->READDIRPLUS3res_u
.resok
.reply
.entries
;
1695 while (entry
!= NULL
) {
1696 struct nfsdirent
*nfsdirent
;
1698 nfsdirent
= malloc(sizeof(struct nfsdirent
));
1699 if (nfsdirent
== NULL
) {
1700 data
->cb(-ENOMEM
, nfs
, "Failed to allocate dirent", data
->private_data
);
1701 nfs_free_nfsdir(nfsdir
);
1702 data
->continue_data
= NULL
;
1703 free_nfs_cb_data(data
);
1706 memset(nfsdirent
, 0, sizeof(struct nfsdirent
));
1707 nfsdirent
->name
= strdup(entry
->name
);
1708 if (nfsdirent
->name
== NULL
) {
1709 data
->cb(-ENOMEM
, nfs
, "Failed to allocate dirent->name", data
->private_data
);
1710 nfs_free_nfsdir(nfsdir
);
1711 data
->continue_data
= NULL
;
1712 free_nfs_cb_data(data
);
1715 nfsdirent
->inode
= entry
->fileid
;
1716 if (entry
->name_attributes
.attributes_follow
) {
1717 nfsdirent
->type
= entry
->name_attributes
.post_op_attr_u
.attributes
.type
;
1718 nfsdirent
->mode
= entry
->name_attributes
.post_op_attr_u
.attributes
.mode
;
1719 nfsdirent
->size
= entry
->name_attributes
.post_op_attr_u
.attributes
.size
;
1721 nfsdirent
->atime
.tv_sec
= entry
->name_attributes
.post_op_attr_u
.attributes
.atime
.seconds
;
1722 nfsdirent
->atime
.tv_usec
= entry
->name_attributes
.post_op_attr_u
.attributes
.atime
.nseconds
/1000;
1723 nfsdirent
->mtime
.tv_sec
= entry
->name_attributes
.post_op_attr_u
.attributes
.mtime
.seconds
;
1724 nfsdirent
->mtime
.tv_usec
= entry
->name_attributes
.post_op_attr_u
.attributes
.mtime
.nseconds
/1000;
1725 nfsdirent
->ctime
.tv_sec
= entry
->name_attributes
.post_op_attr_u
.attributes
.ctime
.seconds
;
1726 nfsdirent
->ctime
.tv_usec
= entry
->name_attributes
.post_op_attr_u
.attributes
.ctime
.nseconds
/1000;
1729 nfsdirent
->next
= nfsdir
->entries
;
1730 nfsdir
->entries
= nfsdirent
;
1732 cookie
= entry
->cookie
;
1733 entry
= entry
->nextentry
;
1736 if (res
->READDIRPLUS3res_u
.resok
.reply
.eof
== 0) {
1737 if (rpc_nfs_readdirplus_async(nfs
->rpc
, nfs_opendir_cb
, &data
->fh
, cookie
, res
->READDIRPLUS3res_u
.resok
.cookieverf
, 8192, data
) != 0) {
1738 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send READDIRPLUS call for %s", data
->path
);
1739 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1740 nfs_free_nfsdir(nfsdir
);
1741 data
->continue_data
= NULL
;
1742 free_nfs_cb_data(data
);
1748 /* steal the dirhandle */
1749 data
->continue_data
= NULL
;
1750 nfsdir
->current
= nfsdir
->entries
;
1752 data
->cb(0, nfs
, nfsdir
, data
->private_data
);
1753 free_nfs_cb_data(data
);
1756 static int nfs_opendir_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1760 memset(cv
, 0, sizeof(cookieverf3
));
1761 if (rpc_nfs_readdirplus_async(nfs
->rpc
, nfs_opendir_cb
, &data
->fh
, 0, (char *)&cv
, 8192, data
) != 0) {
1762 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send READDIRPLUS call for %s", data
->path
);
1763 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1764 free_nfs_cb_data(data
);
1770 int nfs_opendir_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1772 struct nfsdir
*nfsdir
;
1774 nfsdir
= malloc(sizeof(struct nfsdir
));
1775 if (nfsdir
== NULL
) {
1776 rpc_set_error(nfs
->rpc
, "failed to allocate buffer for nfsdir");
1779 memset(nfsdir
, 0, sizeof(struct nfsdir
));
1781 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_opendir_continue_internal
, nfsdir
, free
, 0) != 0) {
1782 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
1790 struct nfsdirent
*nfs_readdir(struct nfs_context
*nfs _U_
, struct nfsdir
*nfsdir
)
1792 struct nfsdirent
*nfsdirent
= nfsdir
->current
;
1794 if (nfsdir
->current
!= NULL
) {
1795 nfsdir
->current
= nfsdir
->current
->next
;
1801 void nfs_closedir(struct nfs_context
*nfs _U_
, struct nfsdir
*nfsdir
)
1803 nfs_free_nfsdir(nfsdir
);
1815 struct lseek_cb_data
{
1816 struct nfs_context
*nfs
;
1817 struct nfsfh
*nfsfh
;
1823 static void nfs_lseek_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1826 struct lseek_cb_data
*data
= private_data
;
1827 struct nfs_context
*nfs
= data
->nfs
;
1829 if (status
== RPC_STATUS_ERROR
) {
1830 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1834 if (status
== RPC_STATUS_CANCEL
) {
1835 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1841 if (res
->status
!= NFS3_OK
) {
1842 rpc_set_error(nfs
->rpc
, "NFS: GETATTR failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
1843 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1848 data
->nfsfh
->offset
= data
->offset
+ res
->GETATTR3res_u
.resok
.obj_attributes
.size
;
1849 data
->cb(0, nfs
, &data
->nfsfh
->offset
, data
->private_data
);
1853 int nfs_lseek_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, int whence
, nfs_cb cb
, void *private_data
)
1855 struct lseek_cb_data
*data
;
1857 if (whence
== SEEK_SET
) {
1858 nfsfh
->offset
= offset
;
1859 cb(0, nfs
, &nfsfh
->offset
, private_data
);
1862 if (whence
== SEEK_CUR
) {
1863 nfsfh
->offset
+= offset
;
1864 cb(0, nfs
, &nfsfh
->offset
, private_data
);
1868 data
= malloc(sizeof(struct lseek_cb_data
));
1870 rpc_set_error(nfs
->rpc
, "Out Of Memory: Failed to malloc lseek cb data");
1875 data
->nfsfh
= nfsfh
;
1876 data
->offset
= offset
;
1878 data
->private_data
= private_data
;
1880 if (rpc_nfs_getattr_async(nfs
->rpc
, nfs_lseek_1_cb
, &nfsfh
->fh
, data
) != 0) {
1881 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send LSEEK GETATTR call");
1894 static void nfs_statvfs_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1897 struct nfs_cb_data
*data
= private_data
;
1898 struct nfs_context
*nfs
= data
->nfs
;
1900 struct statvfs svfs
;
1903 if (status
== RPC_STATUS_ERROR
) {
1904 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1905 free_nfs_cb_data(data
);
1908 if (status
== RPC_STATUS_CANCEL
) {
1909 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1910 free_nfs_cb_data(data
);
1915 if (res
->status
!= NFS3_OK
) {
1916 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
));
1917 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1918 free_nfs_cb_data(data
);
1923 svfs
.f_bsize
= 4096;
1924 svfs
.f_frsize
= 4096;
1925 svfs
.f_blocks
= res
->FSSTAT3res_u
.resok
.tbytes
/4096;
1926 svfs
.f_bfree
= res
->FSSTAT3res_u
.resok
.fbytes
/4096;
1927 svfs
.f_bavail
= res
->FSSTAT3res_u
.resok
.abytes
/4096;
1928 svfs
.f_files
= res
->FSSTAT3res_u
.resok
.tfiles
;
1929 svfs
.f_ffree
= res
->FSSTAT3res_u
.resok
.ffiles
;
1930 svfs
.f_favail
= res
->FSSTAT3res_u
.resok
.afiles
;
1933 svfs
.f_namemax
= 256;
1935 data
->cb(0, nfs
, &svfs
, data
->private_data
);
1937 data
->cb(0, nfs
,NULL
, data
->private_data
);
1939 free_nfs_cb_data(data
);
1942 static int nfs_statvfs_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1944 if (rpc_nfs_fsstat_async(nfs
->rpc
, nfs_statvfs_1_cb
, &data
->fh
, data
) != 0) {
1945 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send FSSTAT call for %s", data
->path
);
1946 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1947 free_nfs_cb_data(data
);
1953 int nfs_statvfs_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1955 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_statvfs_continue_internal
, NULL
, NULL
, 0) != 0) {
1956 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
1969 static void nfs_readlink_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1972 struct nfs_cb_data
*data
= private_data
;
1973 struct nfs_context
*nfs
= data
->nfs
;
1975 if (status
== RPC_STATUS_ERROR
) {
1976 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1977 free_nfs_cb_data(data
);
1980 if (status
== RPC_STATUS_CANCEL
) {
1981 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1982 free_nfs_cb_data(data
);
1987 if (res
->status
!= NFS3_OK
) {
1988 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
));
1989 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1990 free_nfs_cb_data(data
);
1995 data
->cb(0, nfs
, res
->READLINK3res_u
.resok
.data
, data
->private_data
);
1996 free_nfs_cb_data(data
);
1999 static int nfs_readlink_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2001 if (rpc_nfs_readlink_async(nfs
->rpc
, nfs_readlink_1_cb
, &data
->fh
, data
) != 0) {
2002 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send READLINK call for %s", data
->path
);
2003 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2004 free_nfs_cb_data(data
);
2010 int nfs_readlink_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
2012 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_readlink_continue_internal
, NULL
, NULL
, 0) != 0) {
2013 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
2026 static void nfs_chmod_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2028 struct nfs_cb_data
*data
= private_data
;
2029 struct nfs_context
*nfs
= data
->nfs
;
2032 if (status
== RPC_STATUS_ERROR
) {
2033 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2034 free_nfs_cb_data(data
);
2037 if (status
== RPC_STATUS_CANCEL
) {
2038 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2039 free_nfs_cb_data(data
);
2044 if (res
->status
!= NFS3_OK
) {
2045 rpc_set_error(nfs
->rpc
, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
2046 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2047 free_nfs_cb_data(data
);
2051 data
->cb(0, nfs
, NULL
, data
->private_data
);
2052 free_nfs_cb_data(data
);
2055 static int nfs_chmod_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2059 memset(&args
, 0, sizeof(SETATTR3args
));
2060 args
.object
.data
.data_len
= data
->fh
.data
.data_len
;
2061 args
.object
.data
.data_val
= data
->fh
.data
.data_val
;
2062 args
.new_attributes
.mode
.set_it
= 1;
2063 args
.new_attributes
.mode
.set_mode3_u
.mode
= data
->continue_int
;
2065 if (rpc_nfs_setattr_async(nfs
->rpc
, nfs_chmod_cb
, &args
, data
) != 0) {
2066 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SETATTR call for %s", data
->path
);
2067 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2068 free_nfs_cb_data(data
);
2075 int nfs_chmod_async(struct nfs_context
*nfs
, const char *path
, int mode
, nfs_cb cb
, void *private_data
)
2077 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_chmod_continue_internal
, NULL
, NULL
, mode
) != 0) {
2078 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
2088 int nfs_fchmod_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
, nfs_cb cb
, void *private_data
)
2090 struct nfs_cb_data
*data
;
2092 data
= malloc(sizeof(struct nfs_cb_data
));
2094 rpc_set_error(nfs
->rpc
, "out of memory. failed to allocate memory for nfs mount data");
2097 memset(data
, 0, sizeof(struct nfs_cb_data
));
2100 data
->private_data
= private_data
;
2101 data
->continue_int
= mode
;
2102 data
->fh
.data
.data_len
= nfsfh
->fh
.data
.data_len
;
2103 data
->fh
.data
.data_val
= malloc(data
->fh
.data
.data_len
);
2104 if (data
->fh
.data
.data_val
== NULL
) {
2105 rpc_set_error(nfs
->rpc
, "Out of memory: Failed to allocate fh");
2106 free_nfs_cb_data(data
);
2109 memcpy(data
->fh
.data
.data_val
, nfsfh
->fh
.data
.data_val
, data
->fh
.data
.data_len
);
2111 if (nfs_chmod_continue_internal(nfs
, data
) != 0) {
2112 free_nfs_cb_data(data
);
2124 static void nfs_chown_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2126 struct nfs_cb_data
*data
= private_data
;
2127 struct nfs_context
*nfs
= data
->nfs
;
2130 if (status
== RPC_STATUS_ERROR
) {
2131 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2132 free_nfs_cb_data(data
);
2135 if (status
== RPC_STATUS_CANCEL
) {
2136 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2137 free_nfs_cb_data(data
);
2142 if (res
->status
!= NFS3_OK
) {
2143 rpc_set_error(nfs
->rpc
, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
2144 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2145 free_nfs_cb_data(data
);
2149 data
->cb(0, nfs
, NULL
, data
->private_data
);
2150 free_nfs_cb_data(data
);
2153 struct nfs_chown_data
{
2158 static int nfs_chown_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2161 struct nfs_chown_data
*chown_data
= data
->continue_data
;
2163 memset(&args
, 0, sizeof(SETATTR3args
));
2164 args
.object
.data
.data_len
= data
->fh
.data
.data_len
;
2165 args
.object
.data
.data_val
= data
->fh
.data
.data_val
;
2166 if (chown_data
->uid
!= (uid_t
)-1) {
2167 args
.new_attributes
.uid
.set_it
= 1;
2168 args
.new_attributes
.uid
.set_uid3_u
.uid
= chown_data
->uid
;
2170 if (chown_data
->gid
!= (gid_t
)-1) {
2171 args
.new_attributes
.gid
.set_it
= 1;
2172 args
.new_attributes
.gid
.set_gid3_u
.gid
= chown_data
->gid
;
2175 if (rpc_nfs_setattr_async(nfs
->rpc
, nfs_chown_cb
, &args
, data
) != 0) {
2176 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SETATTR call for %s", data
->path
);
2177 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2178 free_nfs_cb_data(data
);
2185 int nfs_chown_async(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
, nfs_cb cb
, void *private_data
)
2187 struct nfs_chown_data
*chown_data
;
2189 chown_data
= malloc(sizeof(struct nfs_chown_data
));
2190 if (chown_data
== NULL
) {
2191 rpc_set_error(nfs
->rpc
, "Failed to allocate memory for chown data structure");
2195 chown_data
->uid
= uid
;
2196 chown_data
->gid
= gid
;
2198 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_chown_continue_internal
, chown_data
, free
, 0) != 0) {
2199 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
2210 int nfs_fchown_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
, nfs_cb cb
, void *private_data
)
2212 struct nfs_cb_data
*data
;
2213 struct nfs_chown_data
*chown_data
;
2215 chown_data
= malloc(sizeof(struct nfs_chown_data
));
2216 if (chown_data
== NULL
) {
2217 rpc_set_error(nfs
->rpc
, "Failed to allocate memory for chown data structure");
2221 chown_data
->uid
= uid
;
2222 chown_data
->gid
= gid
;
2225 data
= malloc(sizeof(struct nfs_cb_data
));
2227 rpc_set_error(nfs
->rpc
, "out of memory. failed to allocate memory for fchown data");
2230 memset(data
, 0, sizeof(struct nfs_cb_data
));
2233 data
->private_data
= private_data
;
2234 data
->continue_data
= chown_data
;
2235 data
->fh
.data
.data_len
= nfsfh
->fh
.data
.data_len
;
2236 data
->fh
.data
.data_val
= malloc(data
->fh
.data
.data_len
);
2237 if (data
->fh
.data
.data_val
== NULL
) {
2238 rpc_set_error(nfs
->rpc
, "Out of memory: Failed to allocate fh");
2239 free_nfs_cb_data(data
);
2242 memcpy(data
->fh
.data
.data_val
, nfsfh
->fh
.data
.data_val
, data
->fh
.data
.data_len
);
2245 if (nfs_chown_continue_internal(nfs
, data
) != 0) {
2246 free_nfs_cb_data(data
);
2260 static void nfs_utimes_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2262 struct nfs_cb_data
*data
= private_data
;
2263 struct nfs_context
*nfs
= data
->nfs
;
2266 if (status
== RPC_STATUS_ERROR
) {
2267 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2268 free_nfs_cb_data(data
);
2271 if (status
== RPC_STATUS_CANCEL
) {
2272 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2273 free_nfs_cb_data(data
);
2278 if (res
->status
!= NFS3_OK
) {
2279 rpc_set_error(nfs
->rpc
, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
2280 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2281 free_nfs_cb_data(data
);
2285 data
->cb(0, nfs
, NULL
, data
->private_data
);
2286 free_nfs_cb_data(data
);
2289 static int nfs_utimes_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2292 struct timeval
*utimes_data
= data
->continue_data
;
2294 memset(&args
, 0, sizeof(SETATTR3args
));
2295 args
.object
.data
.data_len
= data
->fh
.data
.data_len
;
2296 args
.object
.data
.data_val
= data
->fh
.data
.data_val
;
2297 if (utimes_data
!= NULL
) {
2298 args
.new_attributes
.atime
.set_it
= SET_TO_CLIENT_TIME
;
2299 args
.new_attributes
.atime
.set_atime_u
.atime
.seconds
= utimes_data
[0].tv_sec
;
2300 args
.new_attributes
.atime
.set_atime_u
.atime
.nseconds
= utimes_data
[0].tv_usec
* 1000;
2301 args
.new_attributes
.mtime
.set_it
= SET_TO_CLIENT_TIME
;
2302 args
.new_attributes
.mtime
.set_mtime_u
.mtime
.seconds
= utimes_data
[1].tv_sec
;
2303 args
.new_attributes
.mtime
.set_mtime_u
.mtime
.nseconds
= utimes_data
[1].tv_usec
* 1000;
2305 args
.new_attributes
.atime
.set_it
= SET_TO_SERVER_TIME
;
2306 args
.new_attributes
.mtime
.set_it
= SET_TO_SERVER_TIME
;
2309 if (rpc_nfs_setattr_async(nfs
->rpc
, nfs_utimes_cb
, &args
, data
) != 0) {
2310 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SETATTR call for %s", data
->path
);
2311 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2312 free_nfs_cb_data(data
);
2319 int nfs_utimes_async(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
, nfs_cb cb
, void *private_data
)
2321 struct timeval
*new_times
= NULL
;
2323 if (times
!= NULL
) {
2324 new_times
= malloc(sizeof(struct timeval
)*2);
2325 if (new_times
== NULL
) {
2326 rpc_set_error(nfs
->rpc
, "Failed to allocate memory for timeval structure");
2330 memcpy(new_times
, times
, sizeof(struct timeval
)*2);
2333 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_utimes_continue_internal
, new_times
, free
, 0) != 0) {
2334 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
2344 int nfs_utime_async(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
, nfs_cb cb
, void *private_data
)
2346 struct timeval
*new_times
= NULL
;
2348 if (times
!= NULL
) {
2349 new_times
= malloc(sizeof(struct timeval
)*2);
2350 if (new_times
== NULL
) {
2351 rpc_set_error(nfs
->rpc
, "Failed to allocate memory for timeval structure");
2355 new_times
[0].tv_sec
= times
->actime
;
2356 new_times
[0].tv_usec
= 0;
2357 new_times
[1].tv_sec
= times
->modtime
;
2358 new_times
[1].tv_usec
= 0;
2361 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_utimes_continue_internal
, new_times
, free
, 0) != 0) {
2362 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
2376 static void nfs_access_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2379 struct nfs_cb_data
*data
= private_data
;
2380 struct nfs_context
*nfs
= data
->nfs
;
2381 unsigned int nfsmode
= 0;
2383 if (status
== RPC_STATUS_ERROR
) {
2384 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2385 free_nfs_cb_data(data
);
2388 if (status
== RPC_STATUS_CANCEL
) {
2389 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2390 free_nfs_cb_data(data
);
2395 if (res
->status
!= NFS3_OK
) {
2396 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
));
2397 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2398 free_nfs_cb_data(data
);
2402 if (data
->continue_int
& R_OK
) {
2403 nfsmode
|= ACCESS3_READ
;
2405 if (data
->continue_int
& W_OK
) {
2406 nfsmode
|= ACCESS3_MODIFY
;
2408 if (data
->continue_int
& X_OK
) {
2409 nfsmode
|= ACCESS3_EXECUTE
;
2412 if (res
->ACCESS3res_u
.resok
.access
!= nfsmode
) {
2413 rpc_set_error(nfs
->rpc
, "NFS: ACCESS denied. Required access %c%c%c. Allowed access %c%c%c",
2414 nfsmode
&ACCESS3_READ
?'r':'-',
2415 nfsmode
&ACCESS3_MODIFY
?'w':'-',
2416 nfsmode
&ACCESS3_EXECUTE
?'x':'-',
2417 res
->ACCESS3res_u
.resok
.access
&ACCESS3_READ
?'r':'-',
2418 res
->ACCESS3res_u
.resok
.access
&ACCESS3_MODIFY
?'w':'-',
2419 res
->ACCESS3res_u
.resok
.access
&ACCESS3_EXECUTE
?'x':'-');
2420 data
->cb(-EACCES
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2421 free_nfs_cb_data(data
);
2425 data
->cb(0, nfs
, NULL
, data
->private_data
);
2426 free_nfs_cb_data(data
);
2429 static int nfs_access_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2433 if (data
->continue_int
& R_OK
) {
2434 nfsmode
|= ACCESS3_READ
;
2436 if (data
->continue_int
& W_OK
) {
2437 nfsmode
|= ACCESS3_MODIFY
;
2439 if (data
->continue_int
& X_OK
) {
2440 nfsmode
|= ACCESS3_EXECUTE
;
2443 if (rpc_nfs_access_async(nfs
->rpc
, nfs_access_cb
, &data
->fh
, nfsmode
, data
) != 0) {
2444 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send OPEN ACCESS call for %s", data
->path
);
2445 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2446 free_nfs_cb_data(data
);
2452 int nfs_access_async(struct nfs_context
*nfs
, const char *path
, int mode
, nfs_cb cb
, void *private_data
)
2454 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_access_continue_internal
, NULL
, NULL
, mode
) != 0) {
2455 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
2467 struct nfs_symlink_data
{
2469 char *newpathparent
;
2470 char *newpathobject
;
2473 static void free_nfs_symlink_data(void *mem
)
2475 struct nfs_symlink_data
*data
= mem
;
2477 if (data
->oldpath
!= NULL
) {
2478 free(data
->oldpath
);
2480 if (data
->newpathparent
!= NULL
) {
2481 free(data
->newpathparent
);
2483 if (data
->newpathobject
!= NULL
) {
2484 free(data
->newpathobject
);
2489 static void nfs_symlink_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2492 struct nfs_cb_data
*data
= private_data
;
2493 struct nfs_context
*nfs
= data
->nfs
;
2494 struct nfs_symlink_data
*symlink_data
= data
->continue_data
;
2496 if (status
== RPC_STATUS_ERROR
) {
2497 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2498 free_nfs_cb_data(data
);
2501 if (status
== RPC_STATUS_CANCEL
) {
2502 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2503 free_nfs_cb_data(data
);
2508 if (res
->status
!= NFS3_OK
) {
2509 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
));
2510 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2511 free_nfs_cb_data(data
);
2515 data
->cb(0, nfs
, NULL
, data
->private_data
);
2516 free_nfs_cb_data(data
);
2519 static int nfs_symlink_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2521 struct nfs_symlink_data
*symlink_data
= data
->continue_data
;
2523 if (rpc_nfs_symlink_async(nfs
->rpc
, nfs_symlink_cb
, &data
->fh
, symlink_data
->newpathobject
, symlink_data
->oldpath
, data
) != 0) {
2524 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SYMLINK call for %s", data
->path
);
2525 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2526 free_nfs_cb_data(data
);
2532 int nfs_symlink_async(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
, nfs_cb cb
, void *private_data
)
2535 struct nfs_symlink_data
*symlink_data
;
2537 symlink_data
= malloc(sizeof(struct nfs_symlink_data
));
2538 if (symlink_data
== NULL
) {
2539 rpc_set_error(nfs
->rpc
, "Out of memory, failed to allocate buffer for symlink data");
2542 memset(symlink_data
, 0, sizeof(struct nfs_symlink_data
));
2544 symlink_data
->oldpath
= strdup(oldpath
);
2545 if (symlink_data
->oldpath
== NULL
) {
2546 rpc_set_error(nfs
->rpc
, "Out of memory, failed to allocate buffer for oldpath");
2547 free_nfs_symlink_data(symlink_data
);
2551 symlink_data
->newpathparent
= strdup(newpath
);
2552 if (symlink_data
->newpathparent
== NULL
) {
2553 rpc_set_error(nfs
->rpc
, "Out of memory, failed to allocate mode buffer for new path");
2554 free_nfs_symlink_data(symlink_data
);
2558 ptr
= strrchr(symlink_data
->newpathparent
, '/');
2560 rpc_set_error(nfs
->rpc
, "Invalid path %s", oldpath
);
2561 free_nfs_symlink_data(symlink_data
);
2567 symlink_data
->newpathobject
= strdup(ptr
);
2568 if (symlink_data
->newpathobject
== NULL
) {
2569 rpc_set_error(nfs
->rpc
, "Out of memory, failed to allocate mode buffer for new path");
2570 free_nfs_symlink_data(symlink_data
);
2574 if (nfs_lookuppath_async(nfs
, symlink_data
->newpathparent
, cb
, private_data
, nfs_symlink_continue_internal
, symlink_data
, free_nfs_symlink_data
, 0) != 0) {
2575 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
2587 struct nfs_rename_data
{
2590 struct nfs_fh3 olddir
;
2593 struct nfs_fh3 newdir
;
2596 static void free_nfs_rename_data(void *mem
)
2598 struct nfs_rename_data
*data
= mem
;
2600 if (data
->oldpath
!= NULL
) {
2601 free(data
->oldpath
);
2603 if (data
->olddir
.data
.data_val
!= NULL
) {
2604 free(data
->olddir
.data
.data_val
);
2606 if (data
->newpath
!= NULL
) {
2607 free(data
->newpath
);
2609 if (data
->newdir
.data
.data_val
!= NULL
) {
2610 free(data
->newdir
.data
.data_val
);
2615 static void nfs_rename_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2618 struct nfs_cb_data
*data
= private_data
;
2619 struct nfs_context
*nfs
= data
->nfs
;
2620 struct nfs_rename_data
*rename_data
= data
->continue_data
;
2622 if (status
== RPC_STATUS_ERROR
) {
2623 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2624 free_nfs_cb_data(data
);
2627 if (status
== RPC_STATUS_CANCEL
) {
2628 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2629 free_nfs_cb_data(data
);
2634 if (res
->status
!= NFS3_OK
) {
2635 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
));
2636 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2637 free_nfs_cb_data(data
);
2641 data
->cb(0, nfs
, NULL
, data
->private_data
);
2642 free_nfs_cb_data(data
);
2645 static int nfs_rename_continue_2_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2647 struct nfs_rename_data
*rename_data
= data
->continue_data
;
2649 /* steal the filehandle */
2650 rename_data
->newdir
.data
.data_len
= data
->fh
.data
.data_len
;
2651 rename_data
->newdir
.data
.data_val
= data
->fh
.data
.data_val
;
2652 data
->fh
.data
.data_val
= NULL
;
2654 if (rpc_nfs_rename_async(nfs
->rpc
, nfs_rename_cb
, &rename_data
->olddir
, rename_data
->oldobject
, &rename_data
->newdir
, rename_data
->newobject
, data
) != 0) {
2655 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send RENAME call for %s", data
->path
);
2656 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2657 free_nfs_cb_data(data
);
2664 static int nfs_rename_continue_1_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2666 struct nfs_rename_data
*rename_data
= data
->continue_data
;
2668 /* steal the filehandle */
2669 rename_data
->olddir
.data
.data_len
= data
->fh
.data
.data_len
;
2670 rename_data
->olddir
.data
.data_val
= data
->fh
.data
.data_val
;
2671 data
->fh
.data
.data_val
= NULL
;
2673 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) {
2674 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send LOOKUP call for %s", rename_data
->newpath
);
2675 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2676 free_nfs_cb_data(data
);
2679 data
->continue_data
= NULL
;
2680 free_nfs_cb_data(data
);
2686 int nfs_rename_async(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
, nfs_cb cb
, void *private_data
)
2689 struct nfs_rename_data
*rename_data
;
2691 rename_data
= malloc(sizeof(struct nfs_rename_data
));
2692 if (rename_data
== NULL
) {
2693 rpc_set_error(nfs
->rpc
, "Out of memory, failed to allocate buffer for rename data");
2696 memset(rename_data
, 0, sizeof(struct nfs_rename_data
));
2698 rename_data
->oldpath
= strdup(oldpath
);
2699 if (rename_data
->oldpath
== NULL
) {
2700 rpc_set_error(nfs
->rpc
, "Out of memory, failed to allocate buffer for oldpath");
2701 free_nfs_rename_data(rename_data
);
2704 ptr
= strrchr(rename_data
->oldpath
, '/');
2706 rpc_set_error(nfs
->rpc
, "Invalid path %s", oldpath
);
2707 free_nfs_rename_data(rename_data
);
2712 rename_data
->oldobject
= ptr
;
2715 rename_data
->newpath
= strdup(newpath
);
2716 if (rename_data
->newpath
== NULL
) {
2717 rpc_set_error(nfs
->rpc
, "Out of memory, failed to allocate buffer for newpath");
2718 free_nfs_rename_data(rename_data
);
2721 ptr
= strrchr(rename_data
->newpath
, '/');
2723 rpc_set_error(nfs
->rpc
, "Invalid path %s", newpath
);
2724 free_nfs_rename_data(rename_data
);
2729 rename_data
->newobject
= ptr
;
2732 if (nfs_lookuppath_async(nfs
, rename_data
->oldpath
, cb
, private_data
, nfs_rename_continue_1_internal
, rename_data
, free_nfs_rename_data
, 0) != 0) {
2733 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
2744 struct nfs_link_data
{
2746 struct nfs_fh3 oldfh
;
2749 struct nfs_fh3 newdir
;
2752 static void free_nfs_link_data(void *mem
)
2754 struct nfs_link_data
*data
= mem
;
2756 if (data
->oldpath
!= NULL
) {
2757 free(data
->oldpath
);
2759 if (data
->oldfh
.data
.data_val
!= NULL
) {
2760 free(data
->oldfh
.data
.data_val
);
2762 if (data
->newpath
!= NULL
) {
2763 free(data
->newpath
);
2765 if (data
->newdir
.data
.data_val
!= NULL
) {
2766 free(data
->newdir
.data
.data_val
);
2771 static void nfs_link_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2774 struct nfs_cb_data
*data
= private_data
;
2775 struct nfs_context
*nfs
= data
->nfs
;
2776 struct nfs_link_data
*link_data
= data
->continue_data
;
2778 if (status
== RPC_STATUS_ERROR
) {
2779 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2780 free_nfs_cb_data(data
);
2783 if (status
== RPC_STATUS_CANCEL
) {
2784 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2785 free_nfs_cb_data(data
);
2790 if (res
->status
!= NFS3_OK
) {
2791 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
));
2792 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2793 free_nfs_cb_data(data
);
2797 data
->cb(0, nfs
, NULL
, data
->private_data
);
2798 free_nfs_cb_data(data
);
2801 static int nfs_link_continue_2_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2803 struct nfs_link_data
*link_data
= data
->continue_data
;
2805 /* steal the filehandle */
2806 link_data
->newdir
.data
.data_len
= data
->fh
.data
.data_len
;
2807 link_data
->newdir
.data
.data_val
= data
->fh
.data
.data_val
;
2808 data
->fh
.data
.data_val
= NULL
;
2810 if (rpc_nfs_link_async(nfs
->rpc
, nfs_link_cb
, &link_data
->oldfh
, &link_data
->newdir
, link_data
->newobject
, data
) != 0) {
2811 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send LINK call for %s", data
->path
);
2812 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2813 free_nfs_cb_data(data
);
2820 static int nfs_link_continue_1_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2822 struct nfs_link_data
*link_data
= data
->continue_data
;
2824 /* steal the filehandle */
2825 link_data
->oldfh
.data
.data_len
= data
->fh
.data
.data_len
;
2826 link_data
->oldfh
.data
.data_val
= data
->fh
.data
.data_val
;
2827 data
->fh
.data
.data_val
= NULL
;
2829 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) {
2830 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send LOOKUP call for %s", link_data
->newpath
);
2831 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2832 free_nfs_cb_data(data
);
2835 data
->continue_data
= NULL
;
2836 free_nfs_cb_data(data
);
2842 int nfs_link_async(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
, nfs_cb cb
, void *private_data
)
2845 struct nfs_link_data
*link_data
;
2847 link_data
= malloc(sizeof(struct nfs_link_data
));
2848 if (link_data
== NULL
) {
2849 rpc_set_error(nfs
->rpc
, "Out of memory, failed to allocate buffer for link data");
2852 memset(link_data
, 0, sizeof(struct nfs_link_data
));
2854 link_data
->oldpath
= strdup(oldpath
);
2855 if (link_data
->oldpath
== NULL
) {
2856 rpc_set_error(nfs
->rpc
, "Out of memory, failed to allocate buffer for oldpath");
2857 free_nfs_link_data(link_data
);
2861 link_data
->newpath
= strdup(newpath
);
2862 if (link_data
->newpath
== NULL
) {
2863 rpc_set_error(nfs
->rpc
, "Out of memory, failed to allocate buffer for newpath");
2864 free_nfs_link_data(link_data
);
2867 ptr
= strrchr(link_data
->newpath
, '/');
2869 rpc_set_error(nfs
->rpc
, "Invalid path %s", newpath
);
2870 free_nfs_link_data(link_data
);
2875 link_data
->newobject
= ptr
;
2878 if (nfs_lookuppath_async(nfs
, link_data
->oldpath
, cb
, private_data
, nfs_link_continue_1_internal
, link_data
, free_nfs_link_data
, 0) != 0) {
2879 rpc_set_error(nfs
->rpc
, "Out of memory: failed to start parsing the path components");
2887 //qqq replace later with lseek()
2888 off_t
nfs_get_current_offset(struct nfsfh
*nfsfh
)
2890 return nfsfh
->offset
;
2896 * Get the maximum supported READ3 size by the server
2898 size_t nfs_get_readmax(struct nfs_context
*nfs
)
2900 return nfs
->readmax
;
2904 * Get the maximum supported WRITE3 size by the server
2906 size_t nfs_get_writemax(struct nfs_context
*nfs
)
2908 return nfs
->writemax
;
2911 void nfs_set_error(struct nfs_context
*nfs
, char *error_string
, ...)
2916 va_start(ap
, error_string
);
2918 vsnprintf(str
, 1024, error_string
, ap
);
2919 if (nfs
->rpc
->error_string
!= NULL
) {
2920 free(nfs
->rpc
->error_string
);
2922 nfs
->rpc
->error_string
= str
;
2928 struct mount_cb_data
{
2934 static void free_mount_cb_data(struct mount_cb_data
*data
)
2936 if (data
->server
!= NULL
) {
2938 data
->server
= NULL
;
2944 static void mount_export_5_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
2946 struct mount_cb_data
*data
= private_data
;
2948 if (status
== RPC_STATUS_ERROR
) {
2949 data
->cb(rpc
, -EFAULT
, command_data
, data
->private_data
);
2950 free_mount_cb_data(data
);
2953 if (status
== RPC_STATUS_CANCEL
) {
2954 data
->cb(rpc
, -EINTR
, "Command was cancelled", data
->private_data
);
2955 free_mount_cb_data(data
);
2959 data
->cb(rpc
, 0, command_data
, data
->private_data
);
2960 if (rpc_disconnect(rpc
, "normal disconnect") != 0) {
2961 rpc_set_error(rpc
, "Failed to disconnect\n");
2963 free_mount_cb_data(data
);
2966 static void mount_export_4_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
2968 struct mount_cb_data
*data
= private_data
;
2970 if (status
== RPC_STATUS_ERROR
) {
2971 data
->cb(rpc
, -EFAULT
, command_data
, data
->private_data
);
2972 free_mount_cb_data(data
);
2975 if (status
== RPC_STATUS_CANCEL
) {
2976 data
->cb(rpc
, -EINTR
, "Command was cancelled", data
->private_data
);
2977 free_mount_cb_data(data
);
2981 if (rpc_mount_export_async(rpc
, mount_export_5_cb
, data
) != 0) {
2982 data
->cb(rpc
, -ENOMEM
, command_data
, data
->private_data
);
2983 free_mount_cb_data(data
);
2988 static void mount_export_3_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
2990 struct mount_cb_data
*data
= private_data
;
2991 uint32_t mount_port
;
2993 if (status
== RPC_STATUS_ERROR
) {
2994 data
->cb(rpc
, -EFAULT
, command_data
, data
->private_data
);
2995 free_mount_cb_data(data
);
2998 if (status
== RPC_STATUS_CANCEL
) {
2999 data
->cb(rpc
, -EINTR
, "Command was cancelled", data
->private_data
);
3000 free_mount_cb_data(data
);
3004 mount_port
= *(uint32_t *)command_data
;
3005 if (mount_port
== 0) {
3006 rpc_set_error(rpc
, "RPC error. Mount program is not available");
3007 data
->cb(rpc
, -ENOENT
, command_data
, data
->private_data
);
3008 free_mount_cb_data(data
);
3012 rpc_disconnect(rpc
, "normal disconnect");
3013 if (rpc_connect_async(rpc
, data
->server
, mount_port
, mount_export_4_cb
, data
) != 0) {
3014 data
->cb(rpc
, -ENOMEM
, command_data
, data
->private_data
);
3015 free_mount_cb_data(data
);
3020 static void mount_export_2_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
3022 struct mount_cb_data
*data
= private_data
;
3024 if (status
== RPC_STATUS_ERROR
) {
3025 data
->cb(rpc
, -EFAULT
, command_data
, data
->private_data
);
3026 free_mount_cb_data(data
);
3029 if (status
== RPC_STATUS_CANCEL
) {
3030 data
->cb(rpc
, -EINTR
, "Command was cancelled", data
->private_data
);
3031 free_mount_cb_data(data
);
3035 if (rpc_pmap_getport_async(rpc
, MOUNT_PROGRAM
, MOUNT_V3
, mount_export_3_cb
, private_data
) != 0) {
3036 data
->cb(rpc
, -ENOMEM
, command_data
, data
->private_data
);
3037 free_mount_cb_data(data
);
3042 static void mount_export_1_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
3044 struct mount_cb_data
*data
= private_data
;
3046 if (status
== RPC_STATUS_ERROR
) {
3047 data
->cb(rpc
, -EFAULT
, command_data
, data
->private_data
);
3048 free_mount_cb_data(data
);
3051 if (status
== RPC_STATUS_CANCEL
) {
3052 data
->cb(rpc
, -EINTR
, "Command was cancelled", data
->private_data
);
3053 free_mount_cb_data(data
);
3057 if (rpc_pmap_null_async(rpc
, mount_export_2_cb
, data
) != 0) {
3058 data
->cb(rpc
, -ENOMEM
, command_data
, data
->private_data
);
3059 free_mount_cb_data(data
);
3064 int mount_getexports_async(struct rpc_context
*rpc
, const char *server
, rpc_cb cb
, void *private_data
)
3066 struct mount_cb_data
*data
;
3068 data
= malloc(sizeof(struct mount_cb_data
));
3072 memset(data
, 0, sizeof(struct mount_cb_data
));
3074 data
->private_data
= private_data
;
3075 data
->server
= strdup(server
);
3076 if (data
->server
== NULL
) {
3077 free_mount_cb_data(data
);
3080 if (rpc_connect_async(rpc
, data
->server
, 111, mount_export_1_cb
, data
) != 0) {
3081 free_mount_cb_data(data
);
3088 struct rpc_context
*nfs_get_rpc_context(struct nfs_context
*nfs
)
3093 const char *nfs_get_server(struct nfs_context
*nfs
) {
3097 const char *nfs_get_export(struct nfs_context
*nfs
) {
3103 int poll(struct pollfd
*fds
, int nfsd
, int timeout
)
3105 fd_set rfds
, wfds
, efds
;
3111 if (fds
->events
& POLLIN
) {
3112 FD_SET(fds
->fd
, &rfds
);
3114 if (fds
->events
& POLLOUT
) {
3115 FD_SET(fds
->fd
, &wfds
);
3117 FD_SET(fds
->fd
, &efds
);
3118 select(fds
->fd
+ 1, &rfds
, &wfds
, &efds
, NULL
);
3120 if (FD_ISSET(fds
->fd
, &rfds
)) {
3121 fds
->revents
|= POLLIN
;
3123 if (FD_ISSET(fds
->fd
, &wfds
)) {
3124 fds
->revents
|= POLLOUT
;
3126 if (FD_ISSET(fds
->fd
, &efds
)) {
3127 fds
->revents
|= POLLHUP
;