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
26 #include <sys/types.h>
28 #include <sys/statvfs.h>
33 #include "libnfs-raw.h"
34 #include "libnfs-raw-mount.h"
35 #include "libnfs-raw-nfs.h"
44 struct nfsdirent
*entries
;
45 struct nfsdirent
*current
;
48 void nfs_free_nfsdir(struct nfsdir
*nfsdir
)
50 while (nfsdir
->entries
) {
51 struct nfsdirent
*dirent
= nfsdir
->entries
->next
;
52 if (nfsdir
->entries
->name
!= NULL
) {
53 free(nfsdir
->entries
->name
);
55 free(nfsdir
->entries
);
56 nfsdir
->entries
= dirent
;
62 struct rpc_context
*rpc
;
65 struct nfs_fh3 rootfh
;
71 typedef int (*continue_func
)(struct nfs_context
*nfs
, struct nfs_cb_data
*data
);
74 struct nfs_context
*nfs
;
76 char *saved_path
, *path
;
81 continue_func continue_cb
;
83 void (*free_continue_data
)(void *);
88 /* for multi-read/write calls. */
92 off_t start_offset
, max_offset
;
97 struct nfs_cb_data
*data
;
102 static int nfs_lookup_path_async_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
, struct nfs_fh3
*fh
);
105 void nfs_set_auth(struct nfs_context
*nfs
, struct AUTH
*auth
)
107 return rpc_set_auth(nfs
->rpc
, auth
);
110 int nfs_get_fd(struct nfs_context
*nfs
)
112 return rpc_get_fd(nfs
->rpc
);
115 int nfs_which_events(struct nfs_context
*nfs
)
117 return rpc_which_events(nfs
->rpc
);
120 int nfs_service(struct nfs_context
*nfs
, int revents
)
122 return rpc_service(nfs
->rpc
, revents
);
125 char *nfs_get_error(struct nfs_context
*nfs
)
127 return rpc_get_error(nfs
->rpc
);
130 struct nfs_context
*nfs_init_context(void)
132 struct nfs_context
*nfs
;
134 nfs
= malloc(sizeof(struct nfs_context
));
136 printf("Failed to allocate nfs context\n");
139 nfs
->rpc
= rpc_init_context();
140 if (nfs
->rpc
== NULL
) {
141 printf("Failed to allocate rpc sub-context\n");
149 void nfs_destroy_context(struct nfs_context
*nfs
)
151 rpc_destroy_context(nfs
->rpc
);
164 if (nfs
->rootfh
.data
.data_val
!= NULL
) {
165 free(nfs
->rootfh
.data
.data_val
);
166 nfs
->rootfh
.data
.data_val
= NULL
;
172 void free_nfs_cb_data(struct nfs_cb_data
*data
)
174 if (data
->saved_path
!= NULL
) {
175 free(data
->saved_path
);
176 data
->saved_path
= NULL
;
179 if (data
->continue_data
!= NULL
) {
180 data
->free_continue_data(data
->continue_data
);
181 data
->continue_data
= NULL
;
184 if (data
->fh
.data
.data_val
!= NULL
) {
185 free(data
->fh
.data
.data_val
);
186 data
->fh
.data
.data_val
= NULL
;
189 if (data
->buffer
!= NULL
) {
201 static void nfs_mount_10_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
203 struct nfs_cb_data
*data
= private_data
;
204 struct nfs_context
*nfs
= data
->nfs
;
206 if (status
== RPC_STATUS_ERROR
) {
207 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
208 free_nfs_cb_data(data
);
211 if (status
== RPC_STATUS_CANCEL
) {
212 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
213 free_nfs_cb_data(data
);
217 data
->cb(0, nfs
, NULL
, data
->private_data
);
218 free_nfs_cb_data(data
);
221 static void nfs_mount_9_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
223 struct nfs_cb_data
*data
= private_data
;
224 struct nfs_context
*nfs
= data
->nfs
;
225 FSINFO3res
*res
= command_data
;
227 if (status
== RPC_STATUS_ERROR
) {
228 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
229 free_nfs_cb_data(data
);
232 if (status
== RPC_STATUS_CANCEL
) {
233 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
234 free_nfs_cb_data(data
);
238 nfs
->readmax
= res
->FSINFO3res_u
.resok
.rtmax
;
239 nfs
->writemax
= res
->FSINFO3res_u
.resok
.wtmax
;
241 if (rpc_nfs_getattr_async(rpc
, nfs_mount_10_cb
, &nfs
->rootfh
, data
) != 0) {
242 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
243 free_nfs_cb_data(data
);
248 static void nfs_mount_8_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
250 struct nfs_cb_data
*data
= private_data
;
251 struct nfs_context
*nfs
= data
->nfs
;
253 if (status
== RPC_STATUS_ERROR
) {
254 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
255 free_nfs_cb_data(data
);
258 if (status
== RPC_STATUS_CANCEL
) {
259 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
260 free_nfs_cb_data(data
);
264 if (rpc_nfs_fsinfo_async(rpc
, nfs_mount_9_cb
, &nfs
->rootfh
, data
) != 0) {
265 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
266 free_nfs_cb_data(data
);
272 static void nfs_mount_7_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
274 struct nfs_cb_data
*data
= private_data
;
275 struct nfs_context
*nfs
= data
->nfs
;
277 if (status
== RPC_STATUS_ERROR
) {
278 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
279 free_nfs_cb_data(data
);
282 if (status
== RPC_STATUS_CANCEL
) {
283 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
284 free_nfs_cb_data(data
);
288 if (rpc_nfs_null_async(rpc
, nfs_mount_8_cb
, data
) != 0) {
289 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
290 free_nfs_cb_data(data
);
296 static void nfs_mount_6_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
298 struct nfs_cb_data
*data
= private_data
;
299 struct nfs_context
*nfs
= data
->nfs
;
302 if (status
== RPC_STATUS_ERROR
) {
303 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
304 free_nfs_cb_data(data
);
307 if (status
== RPC_STATUS_CANCEL
) {
308 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
309 free_nfs_cb_data(data
);
314 if (res
->fhs_status
!= MNT3_OK
) {
315 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
));
316 data
->cb(mountstat3_to_errno(res
->fhs_status
), nfs
, rpc_get_error(rpc
), data
->private_data
);
317 free_nfs_cb_data(data
);
321 nfs
->rootfh
.data
.data_len
= res
->mountres3_u
.mountinfo
.fhandle
.fhandle3_len
;
322 nfs
->rootfh
.data
.data_val
= malloc(nfs
->rootfh
.data
.data_len
);
323 if (nfs
->rootfh
.data
.data_val
== NULL
) {
324 rpc_set_error(rpc
, "Out of memory. Could not allocate memory to store root filehandle");
325 data
->cb(-ENOMEM
, nfs
, rpc_get_error(rpc
), data
->private_data
);
326 free_nfs_cb_data(data
);
329 memcpy(nfs
->rootfh
.data
.data_val
, res
->mountres3_u
.mountinfo
.fhandle
.fhandle3_val
, nfs
->rootfh
.data
.data_len
);
331 rpc_disconnect(rpc
, "normal disconnect");
332 if (rpc_connect_async(rpc
, nfs
->server
, 2049, nfs_mount_7_cb
, data
) != 0) {
333 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
334 free_nfs_cb_data(data
);
340 static void nfs_mount_5_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
342 struct nfs_cb_data
*data
= private_data
;
343 struct nfs_context
*nfs
= data
->nfs
;
345 if (status
== RPC_STATUS_ERROR
) {
346 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
347 free_nfs_cb_data(data
);
350 if (status
== RPC_STATUS_CANCEL
) {
351 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
352 free_nfs_cb_data(data
);
356 if (rpc_mount_mnt_async(rpc
, nfs_mount_6_cb
, nfs
->export
, data
) != 0) {
357 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
358 free_nfs_cb_data(data
);
363 static void nfs_mount_4_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
365 struct nfs_cb_data
*data
= private_data
;
366 struct nfs_context
*nfs
= data
->nfs
;
368 if (status
== RPC_STATUS_ERROR
) {
369 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
370 free_nfs_cb_data(data
);
373 if (status
== RPC_STATUS_CANCEL
) {
374 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
375 free_nfs_cb_data(data
);
379 if (rpc_mount_null_async(rpc
, nfs_mount_5_cb
, data
) != 0) {
380 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
381 free_nfs_cb_data(data
);
386 static void nfs_mount_3_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
388 struct nfs_cb_data
*data
= private_data
;
389 struct nfs_context
*nfs
= data
->nfs
;
392 if (status
== RPC_STATUS_ERROR
) {
393 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
394 free_nfs_cb_data(data
);
397 if (status
== RPC_STATUS_CANCEL
) {
398 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
399 free_nfs_cb_data(data
);
403 mount_port
= *(uint32_t *)command_data
;
404 if (mount_port
== 0) {
405 rpc_set_error(rpc
, "RPC error. Mount program is not available on %s", nfs
->server
);
406 data
->cb(-ENOENT
, nfs
, command_data
, data
->private_data
);
407 free_nfs_cb_data(data
);
411 rpc_disconnect(rpc
, "normal disconnect");
412 if (rpc_connect_async(rpc
, nfs
->server
, mount_port
, nfs_mount_4_cb
, data
) != 0) {
413 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
414 free_nfs_cb_data(data
);
420 static void nfs_mount_2_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
422 struct nfs_cb_data
*data
= private_data
;
423 struct nfs_context
*nfs
= data
->nfs
;
425 if (status
== RPC_STATUS_ERROR
) {
426 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
427 free_nfs_cb_data(data
);
430 if (status
== RPC_STATUS_CANCEL
) {
431 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
432 free_nfs_cb_data(data
);
436 if (rpc_pmap_getport_async(rpc
, MOUNT_PROGRAM
, MOUNT_V3
, nfs_mount_3_cb
, private_data
) != 0) {
437 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
438 free_nfs_cb_data(data
);
443 static void nfs_mount_1_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
445 struct nfs_cb_data
*data
= private_data
;
446 struct nfs_context
*nfs
= data
->nfs
;
448 if (status
== RPC_STATUS_ERROR
) {
449 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
450 free_nfs_cb_data(data
);
453 if (status
== RPC_STATUS_CANCEL
) {
454 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
455 free_nfs_cb_data(data
);
459 if (rpc_pmap_null_async(rpc
, nfs_mount_2_cb
, data
) != 0) {
460 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
461 free_nfs_cb_data(data
);
467 * Async call for mounting an nfs share and geting the root filehandle
469 int nfs_mount_async(struct nfs_context
*nfs
, const char *server
, const char *export
, nfs_cb cb
, void *private_data
)
471 struct nfs_cb_data
*data
;
473 data
= malloc(sizeof(struct nfs_cb_data
));
475 rpc_set_error(nfs
->rpc
, "out of memory");
476 printf("failed to allocate memory for nfs mount data\n");
479 bzero(data
, sizeof(struct nfs_cb_data
));
480 nfs
->server
= strdup(server
);
481 nfs
->export
= strdup(export
);
484 data
->private_data
= private_data
;
486 if (rpc_connect_async(nfs
->rpc
, server
, 111, nfs_mount_1_cb
, data
) != 0) {
487 printf("Failed to start connection\n");
488 free_nfs_cb_data(data
);
498 * Functions to first look up a path, component by component, and then finally call a specific function once
499 * the filehandle for the final component is found.
501 static void nfs_lookup_path_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
503 struct nfs_cb_data
*data
= private_data
;
504 struct nfs_context
*nfs
= data
->nfs
;
507 if (status
== RPC_STATUS_ERROR
) {
508 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
509 free_nfs_cb_data(data
);
512 if (status
== RPC_STATUS_CANCEL
) {
513 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
514 free_nfs_cb_data(data
);
519 if (res
->status
!= NFS3_OK
) {
520 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
));
521 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
522 free_nfs_cb_data(data
);
526 if (nfs_lookup_path_async_internal(nfs
, data
, &res
->LOOKUP3res_u
.resok
.object
) != 0) {
527 rpc_set_error(nfs
->rpc
, "Failed to create lookup pdu");
528 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
529 free_nfs_cb_data(data
);
534 static int nfs_lookup_path_async_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
, struct nfs_fh3
*fh
)
538 while (*data
->path
== '/') {
543 str
= index(path
, '/');
548 while (*data
->path
!= 0) {
554 data
->fh
.data
.data_len
= fh
->data
.data_len
;
555 data
->fh
.data
.data_val
= malloc(data
->fh
.data
.data_len
);
556 if (data
->fh
.data
.data_val
== NULL
) {
557 rpc_set_error(nfs
->rpc
, "Out of memory: Failed to allocate fh for %s", data
->path
);
558 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
559 free_nfs_cb_data(data
);
562 memcpy(data
->fh
.data
.data_val
, fh
->data
.data_val
, data
->fh
.data
.data_len
);
563 data
->continue_cb(nfs
, data
);
567 if (rpc_nfs_lookup_async(nfs
->rpc
, nfs_lookup_path_1_cb
, fh
, path
, data
) != 0) {
568 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send lookup call for %s", data
->path
);
569 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
570 free_nfs_cb_data(data
);
576 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
)
578 struct nfs_cb_data
*data
;
580 if (path
[0] != '/') {
581 rpc_set_error(nfs
->rpc
, "Pathname is not absulute %s", path
);
585 data
= malloc(sizeof(struct nfs_cb_data
));
587 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
588 printf("failed to allocate memory for nfs cb data\n");
591 bzero(data
, sizeof(struct nfs_cb_data
));
594 data
->continue_cb
= continue_cb
;
595 data
->continue_data
= continue_data
;
596 data
->free_continue_data
= free_continue_data
;
597 data
->continue_int
= continue_int
;
598 data
->private_data
= private_data
;
599 data
->saved_path
= strdup(path
);
600 if (data
->saved_path
== NULL
) {
601 rpc_set_error(nfs
->rpc
, "out of memory: failed to copy path string");
602 printf("failed to allocate memory for path string\n");
603 free_nfs_cb_data(data
);
606 data
->path
= data
->saved_path
;
608 if (nfs_lookup_path_async_internal(nfs
, data
, &nfs
->rootfh
) != 0) {
609 printf("failed to lookup path\n");
610 /* return 0 here since the callback will be invoked if there is a failure */
623 static void nfs_stat_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
626 struct nfs_cb_data
*data
= private_data
;
627 struct nfs_context
*nfs
= data
->nfs
;
630 if (status
== RPC_STATUS_ERROR
) {
631 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
632 free_nfs_cb_data(data
);
635 if (status
== RPC_STATUS_CANCEL
) {
636 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
637 free_nfs_cb_data(data
);
642 if (res
->status
!= NFS3_OK
) {
643 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
));
644 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
645 free_nfs_cb_data(data
);
650 st
.st_ino
= res
->GETATTR3res_u
.resok
.obj_attributes
.fileid
;
651 st
.st_mode
= res
->GETATTR3res_u
.resok
.obj_attributes
.mode
;
652 st
.st_nlink
= res
->GETATTR3res_u
.resok
.obj_attributes
.nlink
;
653 st
.st_uid
= res
->GETATTR3res_u
.resok
.obj_attributes
.uid
;
654 st
.st_gid
= res
->GETATTR3res_u
.resok
.obj_attributes
.gid
;
656 st
.st_size
= res
->GETATTR3res_u
.resok
.obj_attributes
.size
;
657 st
.st_blksize
= 4096;
658 st
.st_blocks
= res
->GETATTR3res_u
.resok
.obj_attributes
.size
/ 4096;
659 st
.st_atime
= res
->GETATTR3res_u
.resok
.obj_attributes
.atime
.seconds
;
660 st
.st_mtime
= res
->GETATTR3res_u
.resok
.obj_attributes
.mtime
.seconds
;
661 st
.st_ctime
= res
->GETATTR3res_u
.resok
.obj_attributes
.ctime
.seconds
;
663 data
->cb(0, nfs
, &st
, data
->private_data
);
664 free_nfs_cb_data(data
);
667 static int nfs_stat_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
669 if (rpc_nfs_getattr_async(nfs
->rpc
, nfs_stat_1_cb
, &data
->fh
, data
) != 0) {
670 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send STAT GETATTR call for %s", data
->path
);
671 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
672 free_nfs_cb_data(data
);
678 int nfs_stat_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
680 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_stat_continue_internal
, NULL
, NULL
, 0) != 0) {
681 printf("Out of memory: failed to start parsing the path components\n");
695 static void nfs_open_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
698 struct nfs_cb_data
*data
= private_data
;
699 struct nfs_context
*nfs
= data
->nfs
;
701 unsigned int nfsmode
= 0;
703 if (status
== RPC_STATUS_ERROR
) {
704 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
705 free_nfs_cb_data(data
);
708 if (status
== RPC_STATUS_CANCEL
) {
709 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
710 free_nfs_cb_data(data
);
715 if (res
->status
!= NFS3_OK
) {
716 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
));
717 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
718 free_nfs_cb_data(data
);
722 if (data
->continue_int
& O_WRONLY
) {
723 nfsmode
|= ACCESS3_MODIFY
;
725 if (data
->continue_int
& O_RDWR
) {
726 nfsmode
|= ACCESS3_READ
|ACCESS3_MODIFY
;
728 if (!(data
->continue_int
& (O_WRONLY
|O_RDWR
))) {
729 nfsmode
|= ACCESS3_READ
;
733 if (res
->ACCESS3res_u
.resok
.access
!= nfsmode
) {
734 rpc_set_error(nfs
->rpc
, "NFS: ACCESS denied. Required access %c%c%c. Allowed access %c%c%c",
735 nfsmode
&ACCESS3_READ
?'r':'-',
736 nfsmode
&ACCESS3_MODIFY
?'w':'-',
737 nfsmode
&ACCESS3_EXECUTE
?'x':'-',
738 res
->ACCESS3res_u
.resok
.access
&ACCESS3_READ
?'r':'-',
739 res
->ACCESS3res_u
.resok
.access
&ACCESS3_MODIFY
?'w':'-',
740 res
->ACCESS3res_u
.resok
.access
&ACCESS3_EXECUTE
?'x':'-');
741 data
->cb(-EACCES
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
742 free_nfs_cb_data(data
);
746 nfsfh
= malloc(sizeof(struct nfsfh
));
748 rpc_set_error(nfs
->rpc
, "NFS: Failed to allocate nfsfh structure");
749 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
750 free_nfs_cb_data(data
);
753 bzero(nfsfh
, sizeof(struct nfsfh
));
755 if (data
->continue_int
& O_SYNC
) {
759 /* steal the filehandle */
760 nfsfh
->fh
.data
.data_len
= data
->fh
.data
.data_len
;
761 nfsfh
->fh
.data
.data_val
= data
->fh
.data
.data_val
;
762 data
->fh
.data
.data_val
= NULL
;
764 data
->cb(0, nfs
, nfsfh
, data
->private_data
);
765 free_nfs_cb_data(data
);
768 static int nfs_open_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
772 if (data
->continue_int
& O_WRONLY
) {
773 nfsmode
|= ACCESS3_MODIFY
;
775 if (data
->continue_int
& O_RDWR
) {
776 nfsmode
|= ACCESS3_READ
|ACCESS3_MODIFY
;
778 if (!(data
->continue_int
& (O_WRONLY
|O_RDWR
))) {
779 nfsmode
|= ACCESS3_READ
;
782 if (rpc_nfs_access_async(nfs
->rpc
, nfs_open_cb
, &data
->fh
, nfsmode
, data
) != 0) {
783 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send OPEN ACCESS call for %s", data
->path
);
784 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
785 free_nfs_cb_data(data
);
791 int nfs_open_async(struct nfs_context
*nfs
, const char *path
, int mode
, nfs_cb cb
, void *private_data
)
793 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_open_continue_internal
, NULL
, NULL
, mode
) != 0) {
794 printf("Out of memory: failed to start parsing the path components\n");
808 static void nfs_pread_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
810 struct nfs_cb_data
*data
= private_data
;
811 struct nfs_context
*nfs
= data
->nfs
;
814 if (status
== RPC_STATUS_ERROR
) {
815 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
816 free_nfs_cb_data(data
);
819 if (status
== RPC_STATUS_CANCEL
) {
820 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
821 free_nfs_cb_data(data
);
826 if (res
->status
!= NFS3_OK
) {
827 rpc_set_error(nfs
->rpc
, "NFS: Read failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
828 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
829 free_nfs_cb_data(data
);
833 data
->nfsfh
->offset
+= res
->READ3res_u
.resok
.count
;
834 data
->cb(res
->READ3res_u
.resok
.count
, nfs
, res
->READ3res_u
.resok
.data
.data_val
, data
->private_data
);
835 free_nfs_cb_data(data
);
838 static void nfs_pread_mcb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
840 struct nfs_mcb_data
*mdata
= private_data
;
841 struct nfs_cb_data
*data
= mdata
->data
;
842 struct nfs_context
*nfs
= data
->nfs
;
847 if (status
== RPC_STATUS_ERROR
) {
848 /* flag the failure but do not invoke callback until we have received all responses */
851 if (status
== RPC_STATUS_CANCEL
) {
852 /* flag the cancellation but do not invoke callback until we have received all responses */
856 /* reassemble the data into the buffer */
857 if (status
== RPC_STATUS_SUCCESS
) {
859 if (res
->status
!= NFS3_OK
) {
860 rpc_set_error(nfs
->rpc
, "NFS: Read failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
863 memcpy(&data
->buffer
[mdata
->offset
], res
->READ3res_u
.resok
.data
.data_val
, res
->READ3res_u
.resok
.count
);
864 if (data
->max_offset
< mdata
->offset
+ res
->READ3res_u
.resok
.count
) {
865 data
->max_offset
= mdata
->offset
+ res
->READ3res_u
.resok
.count
;
870 if (data
->num_calls
> 0) {
871 /* still waiting for more replies */
877 if (data
->error
!= 0) {
878 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
879 free_nfs_cb_data(data
);
883 if (data
->cancel
!= 0) {
884 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
885 free_nfs_cb_data(data
);
890 data
->nfsfh
->offset
= data
->max_offset
;
891 data
->cb(data
->max_offset
- data
->start_offset
, nfs
, data
->buffer
, data
->private_data
);
892 free_nfs_cb_data(data
);
896 int nfs_pread_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, size_t count
, nfs_cb cb
, void *private_data
)
898 struct nfs_cb_data
*data
;
900 data
= malloc(sizeof(struct nfs_cb_data
));
902 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
903 printf("failed to allocate memory for nfs cb data\n");
906 bzero(data
, sizeof(struct nfs_cb_data
));
909 data
->private_data
= private_data
;
912 nfsfh
->offset
= offset
;
914 if (count
<= nfs_get_readmax(nfs
)) {
915 if (rpc_nfs_read_async(nfs
->rpc
, nfs_pread_cb
, &nfsfh
->fh
, offset
, count
, data
) != 0) {
916 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send READ call for %s", data
->path
);
917 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
918 free_nfs_cb_data(data
);
924 /* trying to read more than maximum server read size, we has to chop it up into smaller
925 * reads and collect into a reassembly buffer.
926 * we send all reads in parallell so that performance is still good.
928 data
->start_offset
= offset
;
930 data
->buffer
= malloc(count
);
931 if (data
->buffer
== NULL
) {
932 rpc_set_error(nfs
->rpc
, "Out-Of-Memory: Failed to allocate reassembly buffer for %d bytes", (int)count
);
933 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
934 free_nfs_cb_data(data
);
939 size_t readcount
= count
;
940 struct nfs_mcb_data
*mdata
;
942 if (readcount
> nfs_get_readmax(nfs
)) {
943 readcount
= nfs_get_readmax(nfs
);
946 mdata
= malloc(sizeof(struct nfs_mcb_data
));
948 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_mcb_data structure");
949 printf("failed to allocate memory for nfs mcb data\n");
952 bzero(mdata
, sizeof(struct nfs_mcb_data
));
954 mdata
->offset
= offset
;
955 mdata
->count
= readcount
;
957 if (rpc_nfs_read_async(nfs
->rpc
, nfs_pread_mcb
, &nfsfh
->fh
, offset
, readcount
, mdata
) != 0) {
958 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send READ call for %s", data
->path
);
959 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
975 int nfs_read_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, size_t count
, nfs_cb cb
, void *private_data
)
977 return nfs_pread_async(nfs
, nfsfh
, nfsfh
->offset
, count
, cb
, private_data
);
985 static void nfs_pwrite_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
987 struct nfs_cb_data
*data
= private_data
;
988 struct nfs_context
*nfs
= data
->nfs
;
991 if (status
== RPC_STATUS_ERROR
) {
992 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
993 free_nfs_cb_data(data
);
996 if (status
== RPC_STATUS_CANCEL
) {
997 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
998 free_nfs_cb_data(data
);
1003 if (res
->status
!= NFS3_OK
) {
1004 rpc_set_error(nfs
->rpc
, "NFS: Write failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
1005 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1006 free_nfs_cb_data(data
);
1010 data
->nfsfh
->offset
+= res
->WRITE3res_u
.resok
.count
;
1011 data
->cb(res
->WRITE3res_u
.resok
.count
, nfs
, NULL
, data
->private_data
);
1012 free_nfs_cb_data(data
);
1015 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
)
1017 struct nfs_cb_data
*data
;
1019 data
= malloc(sizeof(struct nfs_cb_data
));
1021 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
1022 printf("failed to allocate memory for nfs cb data\n");
1025 bzero(data
, sizeof(struct nfs_cb_data
));
1028 data
->private_data
= private_data
;
1029 data
->nfsfh
= nfsfh
;
1031 nfsfh
->offset
= offset
;
1032 if (rpc_nfs_write_async(nfs
->rpc
, nfs_pwrite_cb
, &nfsfh
->fh
, buf
, offset
, count
, nfsfh
->is_sync
?FILE_SYNC
:UNSTABLE
, data
) != 0) {
1033 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send WRITE call for %s", data
->path
);
1034 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1035 free_nfs_cb_data(data
);
1044 int nfs_write_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, size_t count
, char *buf
, nfs_cb cb
, void *private_data
)
1046 return nfs_pwrite_async(nfs
, nfsfh
, nfsfh
->offset
, count
, buf
, cb
, private_data
);
1056 int nfs_close_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, nfs_cb cb
, void *private_data
)
1058 if (nfsfh
->fh
.data
.data_val
!= NULL
){
1059 free(nfsfh
->fh
.data
.data_val
);
1060 nfsfh
->fh
.data
.data_val
= NULL
;
1064 cb(0, nfs
, NULL
, private_data
);
1075 int nfs_fstat_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, nfs_cb cb
, void *private_data
)
1077 struct nfs_cb_data
*data
;
1079 data
= malloc(sizeof(struct nfs_cb_data
));
1081 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
1082 printf("failed to allocate memory for nfs cb data\n");
1085 bzero(data
, sizeof(struct nfs_cb_data
));
1088 data
->private_data
= private_data
;
1090 if (rpc_nfs_getattr_async(nfs
->rpc
, nfs_stat_1_cb
, &nfsfh
->fh
, data
) != 0) {
1091 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send STAT GETATTR call for %s", data
->path
);
1092 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1093 free_nfs_cb_data(data
);
1104 static void nfs_fsync_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1106 struct nfs_cb_data
*data
= private_data
;
1107 struct nfs_context
*nfs
= data
->nfs
;
1110 if (status
== RPC_STATUS_ERROR
) {
1111 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1112 free_nfs_cb_data(data
);
1115 if (status
== RPC_STATUS_CANCEL
) {
1116 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1117 free_nfs_cb_data(data
);
1122 if (res
->status
!= NFS3_OK
) {
1123 rpc_set_error(nfs
->rpc
, "NFS: Commit failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
1124 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1125 free_nfs_cb_data(data
);
1129 data
->cb(0, nfs
, NULL
, data
->private_data
);
1130 free_nfs_cb_data(data
);
1133 int nfs_fsync_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, nfs_cb cb
, void *private_data
)
1135 struct nfs_cb_data
*data
;
1137 data
= malloc(sizeof(struct nfs_cb_data
));
1139 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
1140 printf("failed to allocate memory for nfs cb data\n");
1143 bzero(data
, sizeof(struct nfs_cb_data
));
1146 data
->private_data
= private_data
;
1148 if (rpc_nfs_commit_async(nfs
->rpc
, nfs_fsync_cb
, &nfsfh
->fh
, data
) != 0) {
1149 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send COMMIT call for %s", data
->path
);
1150 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1151 free_nfs_cb_data(data
);
1163 static void nfs_ftruncate_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1165 struct nfs_cb_data
*data
= private_data
;
1166 struct nfs_context
*nfs
= data
->nfs
;
1169 if (status
== RPC_STATUS_ERROR
) {
1170 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1171 free_nfs_cb_data(data
);
1174 if (status
== RPC_STATUS_CANCEL
) {
1175 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1176 free_nfs_cb_data(data
);
1181 if (res
->status
!= NFS3_OK
) {
1182 rpc_set_error(nfs
->rpc
, "NFS: Setattr failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
1183 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1184 free_nfs_cb_data(data
);
1188 data
->cb(0, nfs
, NULL
, data
->private_data
);
1189 free_nfs_cb_data(data
);
1192 int nfs_ftruncate_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t length
, nfs_cb cb
, void *private_data
)
1194 struct nfs_cb_data
*data
;
1197 data
= malloc(sizeof(struct nfs_cb_data
));
1199 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
1200 printf("failed to allocate memory for nfs cb data\n");
1203 bzero(data
, sizeof(struct nfs_cb_data
));
1206 data
->private_data
= private_data
;
1208 bzero(&args
, sizeof(SETATTR3args
));
1209 args
.object
.data
.data_len
= nfsfh
->fh
.data
.data_len
;
1210 args
.object
.data
.data_val
= nfsfh
->fh
.data
.data_val
;
1211 args
.new_attributes
.size
.set_it
= 1;
1212 args
.new_attributes
.size
.set_size3_u
.size
= length
;
1214 if (rpc_nfs_setattr_async(nfs
->rpc
, nfs_ftruncate_cb
, &args
, data
) != 0) {
1215 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SETATTR call for %s", data
->path
);
1216 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1217 free_nfs_cb_data(data
);
1227 static int nfs_truncate_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1229 off_t offset
= data
->continue_int
;
1232 nfsfh
.fh
.data
.data_val
= data
->fh
.data
.data_val
;
1233 nfsfh
.fh
.data
.data_len
= data
->fh
.data
.data_len
;
1235 if (nfs_ftruncate_async(nfs
, &nfsfh
, offset
, data
->cb
, data
->private_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
);
1241 free_nfs_cb_data(data
);
1245 int nfs_truncate_async(struct nfs_context
*nfs
, const char *path
, off_t length
, nfs_cb cb
, void *private_data
)
1251 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_truncate_continue_internal
, NULL
, NULL
, offset
) != 0) {
1252 printf("Out of memory: failed to start parsing the path components\n");
1265 static void nfs_mkdir_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1268 struct nfs_cb_data
*data
= private_data
;
1269 struct nfs_context
*nfs
= data
->nfs
;
1270 char *str
= data
->continue_data
;
1272 str
= &str
[strlen(str
) + 1];
1274 if (status
== RPC_STATUS_ERROR
) {
1275 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1276 free_nfs_cb_data(data
);
1279 if (status
== RPC_STATUS_CANCEL
) {
1280 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1281 free_nfs_cb_data(data
);
1286 if (res
->status
!= NFS3_OK
) {
1287 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
));
1288 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1289 free_nfs_cb_data(data
);
1293 data
->cb(0, nfs
, NULL
, data
->private_data
);
1294 free_nfs_cb_data(data
);
1297 static int nfs_mkdir_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1299 char *str
= data
->continue_data
;
1301 str
= &str
[strlen(str
) + 1];
1303 if (rpc_nfs_mkdir_async(nfs
->rpc
, nfs_mkdir_cb
, &data
->fh
, str
, data
) != 0) {
1304 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send MKDIR call for %s", data
->path
);
1305 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1306 free_nfs_cb_data(data
);
1312 int nfs_mkdir_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1317 new_path
= strdup(path
);
1318 if (new_path
== NULL
) {
1319 printf("Out of memory, failed to allocate mode buffer for path\n");
1323 ptr
= rindex(new_path
, '/');
1325 printf("Invalid path %s\n", path
);
1330 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1331 if (nfs_lookuppath_async(nfs
, new_path
, cb
, private_data
, nfs_mkdir_continue_internal
, new_path
, free
, 0) != 0) {
1332 printf("Out of memory: failed to start parsing the path components\n");
1346 static void nfs_rmdir_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1349 struct nfs_cb_data
*data
= private_data
;
1350 struct nfs_context
*nfs
= data
->nfs
;
1351 char *str
= data
->continue_data
;
1353 str
= &str
[strlen(str
) + 1];
1355 if (status
== RPC_STATUS_ERROR
) {
1356 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1357 free_nfs_cb_data(data
);
1360 if (status
== RPC_STATUS_CANCEL
) {
1361 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1362 free_nfs_cb_data(data
);
1367 if (res
->status
!= NFS3_OK
) {
1368 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
));
1369 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1370 free_nfs_cb_data(data
);
1374 data
->cb(0, nfs
, NULL
, data
->private_data
);
1375 free_nfs_cb_data(data
);
1378 static int nfs_rmdir_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1380 char *str
= data
->continue_data
;
1382 str
= &str
[strlen(str
) + 1];
1384 if (rpc_nfs_rmdir_async(nfs
->rpc
, nfs_rmdir_cb
, &data
->fh
, str
, data
) != 0) {
1385 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send RMDIR call for %s", data
->path
);
1386 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1387 free_nfs_cb_data(data
);
1393 int nfs_rmdir_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1398 new_path
= strdup(path
);
1399 if (new_path
== NULL
) {
1400 printf("Out of memory, failed to allocate mode buffer for path\n");
1404 ptr
= rindex(new_path
, '/');
1406 printf("Invalid path %s\n", path
);
1411 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1412 if (nfs_lookuppath_async(nfs
, new_path
, cb
, private_data
, nfs_rmdir_continue_internal
, new_path
, free
, 0) != 0) {
1413 printf("Out of memory: failed to start parsing the path components\n");
1426 static void nfs_create_2_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1429 struct nfs_cb_data
*data
= private_data
;
1430 struct nfs_context
*nfs
= data
->nfs
;
1431 struct nfsfh
*nfsfh
;
1432 char *str
= data
->continue_data
;
1434 if (status
== RPC_STATUS_ERROR
) {
1435 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1436 free_nfs_cb_data(data
);
1439 if (status
== RPC_STATUS_CANCEL
) {
1440 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1441 free_nfs_cb_data(data
);
1445 str
= &str
[strlen(str
) + 1];
1447 if (res
->status
!= NFS3_OK
) {
1448 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
));
1449 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1454 nfsfh
= malloc(sizeof(struct nfsfh
));
1455 if (nfsfh
== NULL
) {
1456 rpc_set_error(nfs
->rpc
, "NFS: Failed to allocate nfsfh structure");
1457 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1458 free_nfs_cb_data(data
);
1461 bzero(nfsfh
, sizeof(struct nfsfh
));
1463 /* steal the filehandle */
1464 nfsfh
->fh
.data
.data_len
= data
->fh
.data
.data_len
;
1465 nfsfh
->fh
.data
.data_val
= data
->fh
.data
.data_val
;
1466 data
->fh
.data
.data_val
= NULL
;
1468 data
->cb(0, nfs
, nfsfh
, data
->private_data
);
1469 free_nfs_cb_data(data
);
1474 static void nfs_creat_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1477 struct nfs_cb_data
*data
= private_data
;
1478 struct nfs_context
*nfs
= data
->nfs
;
1479 char *str
= data
->continue_data
;
1481 if (status
== RPC_STATUS_ERROR
) {
1482 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1483 free_nfs_cb_data(data
);
1486 if (status
== RPC_STATUS_CANCEL
) {
1487 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1488 free_nfs_cb_data(data
);
1492 str
= &str
[strlen(str
) + 1];
1494 if (res
->status
!= NFS3_OK
) {
1495 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
));
1496 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1501 if (rpc_nfs_lookup_async(nfs
->rpc
, nfs_create_2_cb
, &data
->fh
, str
, data
) != 0) {
1502 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send lookup call for %s/%s", data
->saved_path
, str
);
1503 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1504 free_nfs_cb_data(data
);
1510 static int nfs_creat_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1512 char *str
= data
->continue_data
;
1514 str
= &str
[strlen(str
) + 1];
1516 if (rpc_nfs_create_async(nfs
->rpc
, nfs_creat_1_cb
, &data
->fh
, str
, data
->continue_int
, data
) != 0) {
1517 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send CREATE call for %s/%s", data
->path
, str
);
1518 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1519 free_nfs_cb_data(data
);
1525 int nfs_creat_async(struct nfs_context
*nfs
, const char *path
, int mode
, nfs_cb cb
, void *private_data
)
1530 new_path
= strdup(path
);
1531 if (new_path
== NULL
) {
1532 printf("Out of memory, failed to allocate mode buffer for path\n");
1536 ptr
= rindex(new_path
, '/');
1538 printf("Invalid path %s\n", path
);
1543 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1544 if (nfs_lookuppath_async(nfs
, new_path
, cb
, private_data
, nfs_creat_continue_internal
, new_path
, free
, mode
) != 0) {
1545 printf("Out of memory: failed to start parsing the path components\n");
1558 static void nfs_unlink_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1561 struct nfs_cb_data
*data
= private_data
;
1562 struct nfs_context
*nfs
= data
->nfs
;
1563 char *str
= data
->continue_data
;
1565 str
= &str
[strlen(str
) + 1];
1567 if (status
== RPC_STATUS_ERROR
) {
1568 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1569 free_nfs_cb_data(data
);
1572 if (status
== RPC_STATUS_CANCEL
) {
1573 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1574 free_nfs_cb_data(data
);
1579 if (res
->status
!= NFS3_OK
) {
1580 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
));
1581 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1582 free_nfs_cb_data(data
);
1586 data
->cb(0, nfs
, NULL
, data
->private_data
);
1587 free_nfs_cb_data(data
);
1590 static int nfs_unlink_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1592 char *str
= data
->continue_data
;
1594 str
= &str
[strlen(str
) + 1];
1596 if (rpc_nfs_remove_async(nfs
->rpc
, nfs_unlink_cb
, &data
->fh
, str
, data
) != 0) {
1597 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send REMOVE call for %s", data
->path
);
1598 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1599 free_nfs_cb_data(data
);
1605 int nfs_unlink_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1610 new_path
= strdup(path
);
1611 if (new_path
== NULL
) {
1612 printf("Out of memory, failed to allocate mode buffer for path\n");
1616 ptr
= rindex(new_path
, '/');
1618 printf("Invalid path %s\n", path
);
1623 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1624 if (nfs_lookuppath_async(nfs
, new_path
, cb
, private_data
, nfs_unlink_continue_internal
, new_path
, free
, 0) != 0) {
1625 printf("Out of memory: failed to start parsing the path components\n");
1639 static void nfs_opendir_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1642 struct nfs_cb_data
*data
= private_data
;
1643 struct nfs_context
*nfs
= data
->nfs
;
1644 struct nfsdir
*nfsdir
= data
->continue_data
;;
1645 struct entry3
*entry
;
1648 if (status
== RPC_STATUS_ERROR
) {
1649 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1650 nfs_free_nfsdir(nfsdir
);
1651 data
->continue_data
= NULL
;
1652 free_nfs_cb_data(data
);
1655 if (status
== RPC_STATUS_CANCEL
) {
1656 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1657 nfs_free_nfsdir(nfsdir
);
1658 data
->continue_data
= NULL
;
1659 free_nfs_cb_data(data
);
1664 if (res
->status
!= NFS3_OK
) {
1665 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
));
1666 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1667 nfs_free_nfsdir(nfsdir
);
1668 data
->continue_data
= NULL
;
1669 free_nfs_cb_data(data
);
1673 entry
=res
->READDIR3res_u
.resok
.reply
.entries
;
1674 while (entry
!= NULL
) {
1675 struct nfsdirent
*nfsdirent
;
1677 nfsdirent
= malloc(sizeof(struct nfsdirent
));
1678 if (nfsdirent
== NULL
) {
1679 data
->cb(-ENOMEM
, nfs
, "Failed to allocate dirent", data
->private_data
);
1680 nfs_free_nfsdir(nfsdir
);
1681 data
->continue_data
= NULL
;
1682 free_nfs_cb_data(data
);
1685 bzero(nfsdirent
, sizeof(struct nfsdirent
));
1686 nfsdirent
->name
= strdup(entry
->name
);
1687 if (nfsdirent
->name
== NULL
) {
1688 data
->cb(-ENOMEM
, nfs
, "Failed to allocate dirent->name", data
->private_data
);
1689 nfs_free_nfsdir(nfsdir
);
1690 data
->continue_data
= NULL
;
1691 free_nfs_cb_data(data
);
1694 nfsdirent
->inode
= entry
->fileid
;
1695 nfsdirent
->next
= nfsdir
->entries
;
1696 nfsdir
->entries
= nfsdirent
;
1698 cookie
= entry
->cookie
;
1699 entry
= entry
->nextentry
;
1702 if (res
->READDIR3res_u
.resok
.reply
.eof
== 0) {
1703 if (rpc_nfs_readdir_async(nfs
->rpc
, nfs_opendir_cb
, &data
->fh
, cookie
, res
->READDIR3res_u
.resok
.cookieverf
, 20000, data
) != 0) {
1704 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send READDIR call for %s", data
->path
);
1705 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1706 nfs_free_nfsdir(nfsdir
);
1707 data
->continue_data
= NULL
;
1708 free_nfs_cb_data(data
);
1714 /* steal the dirhandle */
1715 data
->continue_data
= NULL
;
1716 nfsdir
->current
= nfsdir
->entries
;
1718 data
->cb(0, nfs
, nfsdir
, data
->private_data
);
1719 free_nfs_cb_data(data
);
1722 static int nfs_opendir_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1726 bzero(cv
, sizeof(cookieverf3
));
1727 if (rpc_nfs_readdir_async(nfs
->rpc
, nfs_opendir_cb
, &data
->fh
, 0, (char *)&cv
, 20000, data
) != 0) {
1728 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send READDIR call for %s", data
->path
);
1729 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1730 free_nfs_cb_data(data
);
1736 int nfs_opendir_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1738 struct nfsdir
*nfsdir
;
1740 nfsdir
= malloc(sizeof(struct nfsdir
));
1741 if (nfsdir
== NULL
) {
1742 printf("failed to allocate buffer for nfsdir\n");
1745 bzero(nfsdir
, sizeof(struct nfsdir
));
1747 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_opendir_continue_internal
, nfsdir
, free
, 0) != 0) {
1748 printf("Out of memory: failed to start parsing the path components\n");
1756 struct nfsdirent
*nfs_readdir(struct nfs_context
*nfs _U_
, struct nfsdir
*nfsdir
)
1758 struct nfsdirent
*nfsdirent
= nfsdir
->current
;
1760 if (nfsdir
->current
!= NULL
) {
1761 nfsdir
->current
= nfsdir
->current
->next
;
1767 void nfs_closedir(struct nfs_context
*nfs _U_
, struct nfsdir
*nfsdir
)
1769 nfs_free_nfsdir(nfsdir
);
1781 struct lseek_cb_data
{
1782 struct nfs_context
*nfs
;
1783 struct nfsfh
*nfsfh
;
1789 static void nfs_lseek_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1792 struct lseek_cb_data
*data
= private_data
;
1793 struct nfs_context
*nfs
= data
->nfs
;
1795 if (status
== RPC_STATUS_ERROR
) {
1796 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1800 if (status
== RPC_STATUS_CANCEL
) {
1801 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1807 if (res
->status
!= NFS3_OK
) {
1808 rpc_set_error(nfs
->rpc
, "NFS: GETATTR failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
1809 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1814 data
->nfsfh
->offset
= data
->offset
+ res
->GETATTR3res_u
.resok
.obj_attributes
.size
;
1815 data
->cb(0, nfs
, &data
->nfsfh
->offset
, data
->private_data
);
1819 int nfs_lseek_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, int whence
, nfs_cb cb
, void *private_data
)
1821 struct lseek_cb_data
*data
;
1823 if (whence
== SEEK_SET
) {
1824 nfsfh
->offset
= offset
;
1825 cb(0, nfs
, &nfsfh
->offset
, private_data
);
1828 if (whence
== SEEK_CUR
) {
1829 nfsfh
->offset
+= offset
;
1830 cb(0, nfs
, &nfsfh
->offset
, private_data
);
1834 data
= malloc(sizeof(struct lseek_cb_data
));
1836 rpc_set_error(nfs
->rpc
, "Out Of Memory: Failed to malloc lseek cb data");
1841 data
->nfsfh
= nfsfh
;
1842 data
->offset
= offset
;
1844 data
->private_data
= private_data
;
1846 if (rpc_nfs_getattr_async(nfs
->rpc
, nfs_lseek_1_cb
, &nfsfh
->fh
, data
) != 0) {
1847 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send LSEEK GETATTR call");
1860 static void nfs_statvfs_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1863 struct nfs_cb_data
*data
= private_data
;
1864 struct nfs_context
*nfs
= data
->nfs
;
1865 struct statvfs svfs
;
1867 if (status
== RPC_STATUS_ERROR
) {
1868 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1869 free_nfs_cb_data(data
);
1872 if (status
== RPC_STATUS_CANCEL
) {
1873 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1874 free_nfs_cb_data(data
);
1879 if (res
->status
!= NFS3_OK
) {
1880 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
));
1881 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1882 free_nfs_cb_data(data
);
1886 svfs
.f_bsize
= 4096;
1887 svfs
.f_frsize
= 4096;
1888 svfs
.f_blocks
= res
->FSSTAT3res_u
.resok
.tbytes
/4096;
1889 svfs
.f_bfree
= res
->FSSTAT3res_u
.resok
.fbytes
/4096;
1890 svfs
.f_bavail
= res
->FSSTAT3res_u
.resok
.abytes
/4096;
1891 svfs
.f_files
= res
->FSSTAT3res_u
.resok
.tfiles
;
1892 svfs
.f_ffree
= res
->FSSTAT3res_u
.resok
.ffiles
;
1893 svfs
.f_favail
= res
->FSSTAT3res_u
.resok
.afiles
;
1896 svfs
.f_namemax
= 256;
1898 data
->cb(0, nfs
, &svfs
, data
->private_data
);
1899 free_nfs_cb_data(data
);
1902 static int nfs_statvfs_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1904 if (rpc_nfs_fsstat_async(nfs
->rpc
, nfs_statvfs_1_cb
, &data
->fh
, data
) != 0) {
1905 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send FSSTAT call for %s", data
->path
);
1906 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1907 free_nfs_cb_data(data
);
1913 int nfs_statvfs_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1915 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_statvfs_continue_internal
, NULL
, NULL
, 0) != 0) {
1916 printf("Out of memory: failed to start parsing the path components\n");
1929 static void nfs_readlink_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1932 struct nfs_cb_data
*data
= private_data
;
1933 struct nfs_context
*nfs
= data
->nfs
;
1935 if (status
== RPC_STATUS_ERROR
) {
1936 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1937 free_nfs_cb_data(data
);
1940 if (status
== RPC_STATUS_CANCEL
) {
1941 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1942 free_nfs_cb_data(data
);
1947 if (res
->status
!= NFS3_OK
) {
1948 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
));
1949 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1950 free_nfs_cb_data(data
);
1955 data
->cb(0, nfs
, res
->READLINK3res_u
.resok
.data
, data
->private_data
);
1956 free_nfs_cb_data(data
);
1959 static int nfs_readlink_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1961 if (rpc_nfs_readlink_async(nfs
->rpc
, nfs_readlink_1_cb
, &data
->fh
, data
) != 0) {
1962 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send READLINK call for %s", data
->path
);
1963 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1964 free_nfs_cb_data(data
);
1970 int nfs_readlink_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1972 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_readlink_continue_internal
, NULL
, NULL
, 0) != 0) {
1973 printf("Out of memory: failed to start parsing the path components\n");
1986 static void nfs_chmod_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1988 struct nfs_cb_data
*data
= private_data
;
1989 struct nfs_context
*nfs
= data
->nfs
;
1992 if (status
== RPC_STATUS_ERROR
) {
1993 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1994 free_nfs_cb_data(data
);
1997 if (status
== RPC_STATUS_CANCEL
) {
1998 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1999 free_nfs_cb_data(data
);
2004 if (res
->status
!= NFS3_OK
) {
2005 rpc_set_error(nfs
->rpc
, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
2006 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2007 free_nfs_cb_data(data
);
2011 data
->cb(0, nfs
, NULL
, data
->private_data
);
2012 free_nfs_cb_data(data
);
2015 static int nfs_chmod_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2019 bzero(&args
, sizeof(SETATTR3args
));
2020 args
.object
.data
.data_len
= data
->fh
.data
.data_len
;
2021 args
.object
.data
.data_val
= data
->fh
.data
.data_val
;
2022 args
.new_attributes
.mode
.set_it
= 1;
2023 args
.new_attributes
.mode
.set_mode3_u
.mode
= data
->continue_int
;
2025 if (rpc_nfs_setattr_async(nfs
->rpc
, nfs_chmod_cb
, &args
, data
) != 0) {
2026 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SETATTR call for %s", data
->path
);
2027 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2028 free_nfs_cb_data(data
);
2035 int nfs_chmod_async(struct nfs_context
*nfs
, const char *path
, int mode
, nfs_cb cb
, void *private_data
)
2037 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_chmod_continue_internal
, NULL
, NULL
, mode
) != 0) {
2038 printf("Out of memory: failed to start parsing the path components\n");
2048 int nfs_fchmod_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
, nfs_cb cb
, void *private_data
)
2050 struct nfs_cb_data
*data
;
2052 data
= malloc(sizeof(struct nfs_cb_data
));
2054 rpc_set_error(nfs
->rpc
, "out of memory");
2055 printf("failed to allocate memory for nfs mount data\n");
2058 bzero(data
, sizeof(struct nfs_cb_data
));
2061 data
->private_data
= private_data
;
2062 data
->continue_int
= mode
;
2063 data
->fh
.data
.data_len
= nfsfh
->fh
.data
.data_len
;
2064 data
->fh
.data
.data_val
= malloc(data
->fh
.data
.data_len
);
2065 if (data
->fh
.data
.data_val
== NULL
) {
2066 rpc_set_error(nfs
->rpc
, "Out of memory: Failed to allocate fh");
2067 free_nfs_cb_data(data
);
2070 memcpy(data
->fh
.data
.data_val
, nfsfh
->fh
.data
.data_val
, data
->fh
.data
.data_len
);
2072 if (nfs_chmod_continue_internal(nfs
, data
) != 0) {
2073 free_nfs_cb_data(data
);
2085 static void nfs_chown_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2087 struct nfs_cb_data
*data
= private_data
;
2088 struct nfs_context
*nfs
= data
->nfs
;
2091 if (status
== RPC_STATUS_ERROR
) {
2092 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2093 free_nfs_cb_data(data
);
2096 if (status
== RPC_STATUS_CANCEL
) {
2097 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2098 free_nfs_cb_data(data
);
2103 if (res
->status
!= NFS3_OK
) {
2104 rpc_set_error(nfs
->rpc
, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
2105 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2106 free_nfs_cb_data(data
);
2110 data
->cb(0, nfs
, NULL
, data
->private_data
);
2111 free_nfs_cb_data(data
);
2114 struct nfs_chown_data
{
2119 static int nfs_chown_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2122 struct nfs_chown_data
*chown_data
= data
->continue_data
;
2124 bzero(&args
, sizeof(SETATTR3args
));
2125 args
.object
.data
.data_len
= data
->fh
.data
.data_len
;
2126 args
.object
.data
.data_val
= data
->fh
.data
.data_val
;
2127 if (chown_data
->uid
!= (uid_t
)-1) {
2128 args
.new_attributes
.uid
.set_it
= 1;
2129 args
.new_attributes
.uid
.set_uid3_u
.uid
= chown_data
->uid
;
2131 if (chown_data
->gid
!= (gid_t
)-1) {
2132 args
.new_attributes
.gid
.set_it
= 1;
2133 args
.new_attributes
.gid
.set_gid3_u
.gid
= chown_data
->gid
;
2136 if (rpc_nfs_setattr_async(nfs
->rpc
, nfs_chown_cb
, &args
, data
) != 0) {
2137 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SETATTR call for %s", data
->path
);
2138 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2139 free_nfs_cb_data(data
);
2146 int nfs_chown_async(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
, nfs_cb cb
, void *private_data
)
2148 struct nfs_chown_data
*chown_data
;
2150 chown_data
= malloc(sizeof(struct nfs_chown_data
));
2151 if (chown_data
== NULL
) {
2152 printf("Failed to allocate memory for chown data structure\n");
2156 chown_data
->uid
= uid
;
2157 chown_data
->gid
= gid
;
2159 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_chown_continue_internal
, chown_data
, free
, 0) != 0) {
2160 printf("Out of memory: failed to start parsing the path components\n");
2171 int nfs_fchown_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
, nfs_cb cb
, void *private_data
)
2173 struct nfs_cb_data
*data
;
2174 struct nfs_chown_data
*chown_data
;
2176 chown_data
= malloc(sizeof(struct nfs_chown_data
));
2177 if (chown_data
== NULL
) {
2178 printf("Failed to allocate memory for chown data structure\n");
2182 chown_data
->uid
= uid
;
2183 chown_data
->gid
= gid
;
2186 data
= malloc(sizeof(struct nfs_cb_data
));
2188 rpc_set_error(nfs
->rpc
, "out of memory");
2189 printf("failed to allocate memory for fchown data\n");
2192 bzero(data
, sizeof(struct nfs_cb_data
));
2195 data
->private_data
= private_data
;
2196 data
->continue_data
= chown_data
;
2197 data
->fh
.data
.data_len
= nfsfh
->fh
.data
.data_len
;
2198 data
->fh
.data
.data_val
= malloc(data
->fh
.data
.data_len
);
2199 if (data
->fh
.data
.data_val
== NULL
) {
2200 rpc_set_error(nfs
->rpc
, "Out of memory: Failed to allocate fh");
2201 free_nfs_cb_data(data
);
2204 memcpy(data
->fh
.data
.data_val
, nfsfh
->fh
.data
.data_val
, data
->fh
.data
.data_len
);
2207 if (nfs_chown_continue_internal(nfs
, data
) != 0) {
2208 free_nfs_cb_data(data
);
2222 static void nfs_utimes_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2224 struct nfs_cb_data
*data
= private_data
;
2225 struct nfs_context
*nfs
= data
->nfs
;
2228 if (status
== RPC_STATUS_ERROR
) {
2229 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2230 free_nfs_cb_data(data
);
2233 if (status
== RPC_STATUS_CANCEL
) {
2234 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2235 free_nfs_cb_data(data
);
2240 if (res
->status
!= NFS3_OK
) {
2241 rpc_set_error(nfs
->rpc
, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
2242 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2243 free_nfs_cb_data(data
);
2247 data
->cb(0, nfs
, NULL
, data
->private_data
);
2248 free_nfs_cb_data(data
);
2251 static int nfs_utimes_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2254 struct timeval
*utimes_data
= data
->continue_data
;
2256 bzero(&args
, sizeof(SETATTR3args
));
2257 args
.object
.data
.data_len
= data
->fh
.data
.data_len
;
2258 args
.object
.data
.data_val
= data
->fh
.data
.data_val
;
2259 if (utimes_data
!= NULL
) {
2260 args
.new_attributes
.atime
.set_it
= SET_TO_CLIENT_TIME
;
2261 args
.new_attributes
.atime
.set_atime_u
.atime
.seconds
= utimes_data
[0].tv_sec
;
2262 args
.new_attributes
.atime
.set_atime_u
.atime
.nseconds
= utimes_data
[0].tv_usec
* 1000;
2263 args
.new_attributes
.mtime
.set_it
= SET_TO_CLIENT_TIME
;
2264 args
.new_attributes
.mtime
.set_mtime_u
.mtime
.seconds
= utimes_data
[1].tv_sec
;
2265 args
.new_attributes
.mtime
.set_mtime_u
.mtime
.nseconds
= utimes_data
[1].tv_usec
* 1000;
2267 args
.new_attributes
.atime
.set_it
= SET_TO_SERVER_TIME
;
2268 args
.new_attributes
.mtime
.set_it
= SET_TO_SERVER_TIME
;
2271 if (rpc_nfs_setattr_async(nfs
->rpc
, nfs_utimes_cb
, &args
, data
) != 0) {
2272 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SETATTR call for %s", data
->path
);
2273 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2274 free_nfs_cb_data(data
);
2281 int nfs_utimes_async(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
, nfs_cb cb
, void *private_data
)
2283 struct timeval
*new_times
= NULL
;
2285 if (times
!= NULL
) {
2286 new_times
= malloc(sizeof(struct timeval
)*2);
2287 if (new_times
== NULL
) {
2288 printf("Failed to allocate memory for timeval structure\n");
2292 memcpy(new_times
, times
, sizeof(struct timeval
)*2);
2295 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_utimes_continue_internal
, new_times
, free
, 0) != 0) {
2296 printf("Out of memory: failed to start parsing the path components\n");
2306 int nfs_utime_async(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
, nfs_cb cb
, void *private_data
)
2308 struct timeval
*new_times
= NULL
;
2310 if (times
!= NULL
) {
2311 new_times
= malloc(sizeof(struct timeval
)*2);
2312 if (new_times
== NULL
) {
2313 printf("Failed to allocate memory for timeval structure\n");
2317 new_times
[0].tv_sec
= times
->actime
;
2318 new_times
[0].tv_usec
= 0;
2319 new_times
[1].tv_sec
= times
->modtime
;
2320 new_times
[1].tv_usec
= 0;
2323 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_utimes_continue_internal
, new_times
, free
, 0) != 0) {
2324 printf("Out of memory: failed to start parsing the path components\n");
2338 static void nfs_access_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2341 struct nfs_cb_data
*data
= private_data
;
2342 struct nfs_context
*nfs
= data
->nfs
;
2343 unsigned int nfsmode
= 0;
2345 if (status
== RPC_STATUS_ERROR
) {
2346 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2347 free_nfs_cb_data(data
);
2350 if (status
== RPC_STATUS_CANCEL
) {
2351 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2352 free_nfs_cb_data(data
);
2357 if (res
->status
!= NFS3_OK
) {
2358 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
));
2359 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2360 free_nfs_cb_data(data
);
2364 if (data
->continue_int
& R_OK
) {
2365 nfsmode
|= ACCESS3_READ
;
2367 if (data
->continue_int
& W_OK
) {
2368 nfsmode
|= ACCESS3_MODIFY
;
2370 if (data
->continue_int
& X_OK
) {
2371 nfsmode
|= ACCESS3_EXECUTE
;
2374 if (res
->ACCESS3res_u
.resok
.access
!= nfsmode
) {
2375 rpc_set_error(nfs
->rpc
, "NFS: ACCESS denied. Required access %c%c%c. Allowed access %c%c%c",
2376 nfsmode
&ACCESS3_READ
?'r':'-',
2377 nfsmode
&ACCESS3_MODIFY
?'w':'-',
2378 nfsmode
&ACCESS3_EXECUTE
?'x':'-',
2379 res
->ACCESS3res_u
.resok
.access
&ACCESS3_READ
?'r':'-',
2380 res
->ACCESS3res_u
.resok
.access
&ACCESS3_MODIFY
?'w':'-',
2381 res
->ACCESS3res_u
.resok
.access
&ACCESS3_EXECUTE
?'x':'-');
2382 data
->cb(-EACCES
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2383 free_nfs_cb_data(data
);
2387 data
->cb(0, nfs
, NULL
, data
->private_data
);
2388 free_nfs_cb_data(data
);
2391 static int nfs_access_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2395 if (data
->continue_int
& R_OK
) {
2396 nfsmode
|= ACCESS3_READ
;
2398 if (data
->continue_int
& W_OK
) {
2399 nfsmode
|= ACCESS3_MODIFY
;
2401 if (data
->continue_int
& X_OK
) {
2402 nfsmode
|= ACCESS3_EXECUTE
;
2405 if (rpc_nfs_access_async(nfs
->rpc
, nfs_access_cb
, &data
->fh
, nfsmode
, data
) != 0) {
2406 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send OPEN ACCESS call for %s", data
->path
);
2407 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2408 free_nfs_cb_data(data
);
2414 int nfs_access_async(struct nfs_context
*nfs
, const char *path
, int mode
, nfs_cb cb
, void *private_data
)
2416 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_access_continue_internal
, NULL
, NULL
, mode
) != 0) {
2417 printf("Out of memory: failed to start parsing the path components\n");
2429 struct nfs_symlink_data
{
2431 char *newpathparent
;
2432 char *newpathobject
;
2435 static void free_nfs_symlink_data(void *mem
)
2437 struct nfs_symlink_data
*data
= mem
;
2439 if (data
->oldpath
!= NULL
) {
2440 free(data
->oldpath
);
2442 if (data
->newpathparent
!= NULL
) {
2443 free(data
->newpathparent
);
2445 if (data
->newpathobject
!= NULL
) {
2446 free(data
->newpathobject
);
2451 static void nfs_symlink_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2454 struct nfs_cb_data
*data
= private_data
;
2455 struct nfs_context
*nfs
= data
->nfs
;
2456 struct nfs_symlink_data
*symlink_data
= data
->continue_data
;
2458 if (status
== RPC_STATUS_ERROR
) {
2459 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2460 free_nfs_cb_data(data
);
2463 if (status
== RPC_STATUS_CANCEL
) {
2464 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2465 free_nfs_cb_data(data
);
2470 if (res
->status
!= NFS3_OK
) {
2471 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
));
2472 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2473 free_nfs_cb_data(data
);
2477 data
->cb(0, nfs
, NULL
, data
->private_data
);
2478 free_nfs_cb_data(data
);
2481 static int nfs_symlink_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2483 struct nfs_symlink_data
*symlink_data
= data
->continue_data
;
2485 if (rpc_nfs_symlink_async(nfs
->rpc
, nfs_symlink_cb
, &data
->fh
, symlink_data
->newpathobject
, symlink_data
->oldpath
, data
) != 0) {
2486 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SYMLINK call for %s", data
->path
);
2487 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2488 free_nfs_cb_data(data
);
2494 int nfs_symlink_async(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
, nfs_cb cb
, void *private_data
)
2497 struct nfs_symlink_data
*symlink_data
;
2499 symlink_data
= malloc(sizeof(struct nfs_symlink_data
));
2500 if (symlink_data
== NULL
) {
2501 printf("Out of memory, failed to allocate buffer for symlink data\n");
2504 bzero(symlink_data
, sizeof(struct nfs_symlink_data
));
2506 symlink_data
->oldpath
= strdup(oldpath
);
2507 if (symlink_data
->oldpath
== NULL
) {
2508 printf("Out of memory, failed to allocate buffer for oldpath\n");
2509 free_nfs_symlink_data(symlink_data
);
2513 symlink_data
->newpathparent
= strdup(newpath
);
2514 if (symlink_data
->newpathparent
== NULL
) {
2515 printf("Out of memory, failed to allocate mode buffer for new path\n");
2516 free_nfs_symlink_data(symlink_data
);
2520 ptr
= rindex(symlink_data
->newpathparent
, '/');
2522 printf("Invalid path %s\n", oldpath
);
2523 free_nfs_symlink_data(symlink_data
);
2529 symlink_data
->newpathobject
= strdup(ptr
);
2530 if (symlink_data
->newpathobject
== NULL
) {
2531 printf("Out of memory, failed to allocate mode buffer for new path\n");
2532 free_nfs_symlink_data(symlink_data
);
2536 if (nfs_lookuppath_async(nfs
, symlink_data
->newpathparent
, cb
, private_data
, nfs_symlink_continue_internal
, symlink_data
, free_nfs_symlink_data
, 0) != 0) {
2537 printf("Out of memory: failed to start parsing the path components\n");
2549 struct nfs_rename_data
{
2552 struct nfs_fh3 olddir
;
2555 struct nfs_fh3 newdir
;
2558 static void free_nfs_rename_data(void *mem
)
2560 struct nfs_rename_data
*data
= mem
;
2562 if (data
->oldpath
!= NULL
) {
2563 free(data
->oldpath
);
2565 if (data
->olddir
.data
.data_val
!= NULL
) {
2566 free(data
->olddir
.data
.data_val
);
2568 if (data
->newpath
!= NULL
) {
2569 free(data
->newpath
);
2571 if (data
->newdir
.data
.data_val
!= NULL
) {
2572 free(data
->newdir
.data
.data_val
);
2577 static void nfs_rename_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2580 struct nfs_cb_data
*data
= private_data
;
2581 struct nfs_context
*nfs
= data
->nfs
;
2582 struct nfs_rename_data
*rename_data
= data
->continue_data
;
2584 if (status
== RPC_STATUS_ERROR
) {
2585 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2586 free_nfs_cb_data(data
);
2589 if (status
== RPC_STATUS_CANCEL
) {
2590 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2591 free_nfs_cb_data(data
);
2596 if (res
->status
!= NFS3_OK
) {
2597 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
));
2598 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2599 free_nfs_cb_data(data
);
2603 data
->cb(0, nfs
, NULL
, data
->private_data
);
2604 free_nfs_cb_data(data
);
2607 static int nfs_rename_continue_2_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2609 struct nfs_rename_data
*rename_data
= data
->continue_data
;
2611 /* steal the filehandle */
2612 rename_data
->newdir
.data
.data_len
= data
->fh
.data
.data_len
;
2613 rename_data
->newdir
.data
.data_val
= data
->fh
.data
.data_val
;
2614 data
->fh
.data
.data_val
= NULL
;
2616 if (rpc_nfs_rename_async(nfs
->rpc
, nfs_rename_cb
, &rename_data
->olddir
, rename_data
->oldobject
, &rename_data
->newdir
, rename_data
->newobject
, data
) != 0) {
2617 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send RENAME call for %s", data
->path
);
2618 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2619 free_nfs_cb_data(data
);
2626 static int nfs_rename_continue_1_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2628 struct nfs_rename_data
*rename_data
= data
->continue_data
;
2630 /* steal the filehandle */
2631 rename_data
->olddir
.data
.data_len
= data
->fh
.data
.data_len
;
2632 rename_data
->olddir
.data
.data_val
= data
->fh
.data
.data_val
;
2633 data
->fh
.data
.data_val
= NULL
;
2635 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) {
2636 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send LOOKUP call for %s", rename_data
->newpath
);
2637 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2638 free_nfs_cb_data(data
);
2641 data
->continue_data
= NULL
;
2642 free_nfs_cb_data(data
);
2648 int nfs_rename_async(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
, nfs_cb cb
, void *private_data
)
2651 struct nfs_rename_data
*rename_data
;
2653 rename_data
= malloc(sizeof(struct nfs_rename_data
));
2654 if (rename_data
== NULL
) {
2655 printf("Out of memory, failed to allocate buffer for rename data\n");
2658 bzero(rename_data
, sizeof(struct nfs_rename_data
));
2660 rename_data
->oldpath
= strdup(oldpath
);
2661 if (rename_data
->oldpath
== NULL
) {
2662 printf("Out of memory, failed to allocate buffer for oldpath\n");
2663 free_nfs_rename_data(rename_data
);
2666 ptr
= rindex(rename_data
->oldpath
, '/');
2668 printf("Invalid path %s\n", oldpath
);
2669 free_nfs_rename_data(rename_data
);
2674 rename_data
->oldobject
= ptr
;
2677 rename_data
->newpath
= strdup(newpath
);
2678 if (rename_data
->newpath
== NULL
) {
2679 printf("Out of memory, failed to allocate buffer for newpath\n");
2680 free_nfs_rename_data(rename_data
);
2683 ptr
= rindex(rename_data
->newpath
, '/');
2685 printf("Invalid path %s\n", newpath
);
2686 free_nfs_rename_data(rename_data
);
2691 rename_data
->newobject
= ptr
;
2694 if (nfs_lookuppath_async(nfs
, rename_data
->oldpath
, cb
, private_data
, nfs_rename_continue_1_internal
, rename_data
, free_nfs_rename_data
, 0) != 0) {
2695 printf("Out of memory: failed to start parsing the path components\n");
2706 struct nfs_link_data
{
2708 struct nfs_fh3 oldfh
;
2711 struct nfs_fh3 newdir
;
2714 static void free_nfs_link_data(void *mem
)
2716 struct nfs_link_data
*data
= mem
;
2718 if (data
->oldpath
!= NULL
) {
2719 free(data
->oldpath
);
2721 if (data
->oldfh
.data
.data_val
!= NULL
) {
2722 free(data
->oldfh
.data
.data_val
);
2724 if (data
->newpath
!= NULL
) {
2725 free(data
->newpath
);
2727 if (data
->newdir
.data
.data_val
!= NULL
) {
2728 free(data
->newdir
.data
.data_val
);
2733 static void nfs_link_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2736 struct nfs_cb_data
*data
= private_data
;
2737 struct nfs_context
*nfs
= data
->nfs
;
2738 struct nfs_link_data
*link_data
= data
->continue_data
;
2740 if (status
== RPC_STATUS_ERROR
) {
2741 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2742 free_nfs_cb_data(data
);
2745 if (status
== RPC_STATUS_CANCEL
) {
2746 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2747 free_nfs_cb_data(data
);
2752 if (res
->status
!= NFS3_OK
) {
2753 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
));
2754 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2755 free_nfs_cb_data(data
);
2759 data
->cb(0, nfs
, NULL
, data
->private_data
);
2760 free_nfs_cb_data(data
);
2763 static int nfs_link_continue_2_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2765 struct nfs_link_data
*link_data
= data
->continue_data
;
2767 /* steal the filehandle */
2768 link_data
->newdir
.data
.data_len
= data
->fh
.data
.data_len
;
2769 link_data
->newdir
.data
.data_val
= data
->fh
.data
.data_val
;
2770 data
->fh
.data
.data_val
= NULL
;
2772 if (rpc_nfs_link_async(nfs
->rpc
, nfs_link_cb
, &link_data
->oldfh
, &link_data
->newdir
, link_data
->newobject
, data
) != 0) {
2773 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send LINK call for %s", data
->path
);
2774 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2775 free_nfs_cb_data(data
);
2782 static int nfs_link_continue_1_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2784 struct nfs_link_data
*link_data
= data
->continue_data
;
2786 /* steal the filehandle */
2787 link_data
->oldfh
.data
.data_len
= data
->fh
.data
.data_len
;
2788 link_data
->oldfh
.data
.data_val
= data
->fh
.data
.data_val
;
2789 data
->fh
.data
.data_val
= NULL
;
2791 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) {
2792 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send LOOKUP call for %s", link_data
->newpath
);
2793 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2794 free_nfs_cb_data(data
);
2797 data
->continue_data
= NULL
;
2798 free_nfs_cb_data(data
);
2804 int nfs_link_async(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
, nfs_cb cb
, void *private_data
)
2807 struct nfs_link_data
*link_data
;
2809 link_data
= malloc(sizeof(struct nfs_link_data
));
2810 if (link_data
== NULL
) {
2811 printf("Out of memory, failed to allocate buffer for link data\n");
2814 bzero(link_data
, sizeof(struct nfs_link_data
));
2816 link_data
->oldpath
= strdup(oldpath
);
2817 if (link_data
->oldpath
== NULL
) {
2818 printf("Out of memory, failed to allocate buffer for oldpath\n");
2819 free_nfs_link_data(link_data
);
2823 link_data
->newpath
= strdup(newpath
);
2824 if (link_data
->newpath
== NULL
) {
2825 printf("Out of memory, failed to allocate buffer for newpath\n");
2826 free_nfs_link_data(link_data
);
2829 ptr
= rindex(link_data
->newpath
, '/');
2831 printf("Invalid path %s\n", newpath
);
2832 free_nfs_link_data(link_data
);
2837 link_data
->newobject
= ptr
;
2840 if (nfs_lookuppath_async(nfs
, link_data
->oldpath
, cb
, private_data
, nfs_link_continue_1_internal
, link_data
, free_nfs_link_data
, 0) != 0) {
2841 printf("Out of memory: failed to start parsing the path components\n");
2849 //qqq replace later with lseek()
2850 off_t
nfs_get_current_offset(struct nfsfh
*nfsfh
)
2852 return nfsfh
->offset
;
2858 * Get the maximum supported READ3 size by the server
2860 size_t nfs_get_readmax(struct nfs_context
*nfs
)
2862 return nfs
->readmax
;
2866 * Get the maximum supported WRITE3 size by the server
2868 size_t nfs_get_writemax(struct nfs_context
*nfs
)
2870 return nfs
->writemax
;