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
;
69 typedef int (*continue_func
)(struct nfs_context
*nfs
, struct nfs_cb_data
*data
);
72 struct nfs_context
*nfs
;
74 char *saved_path
, *path
;
79 continue_func continue_cb
;
81 void (*free_continue_data
)(void *);
87 static int nfs_lookup_path_async_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
, struct nfs_fh3
*fh
);
90 void nfs_set_auth(struct nfs_context
*nfs
, struct AUTH
*auth
)
92 return rpc_set_auth(nfs
->rpc
, auth
);
95 int nfs_get_fd(struct nfs_context
*nfs
)
97 return rpc_get_fd(nfs
->rpc
);
100 int nfs_which_events(struct nfs_context
*nfs
)
102 return rpc_which_events(nfs
->rpc
);
105 int nfs_service(struct nfs_context
*nfs
, int revents
)
107 return rpc_service(nfs
->rpc
, revents
);
110 char *nfs_get_error(struct nfs_context
*nfs
)
112 return rpc_get_error(nfs
->rpc
);
115 struct nfs_context
*nfs_init_context(void)
117 struct nfs_context
*nfs
;
119 nfs
= malloc(sizeof(struct nfs_context
));
121 printf("Failed to allocate nfs context\n");
124 nfs
->rpc
= rpc_init_context();
125 if (nfs
->rpc
== NULL
) {
126 printf("Failed to allocate rpc sub-context\n");
134 void nfs_destroy_context(struct nfs_context
*nfs
)
136 rpc_destroy_context(nfs
->rpc
);
149 if (nfs
->rootfh
.data
.data_val
!= NULL
) {
150 free(nfs
->rootfh
.data
.data_val
);
151 nfs
->rootfh
.data
.data_val
= NULL
;
157 void free_nfs_cb_data(struct nfs_cb_data
*data
)
159 if (data
->saved_path
!= NULL
) {
160 free(data
->saved_path
);
161 data
->saved_path
= NULL
;
164 if (data
->continue_data
!= NULL
) {
165 data
->free_continue_data(data
->continue_data
);
166 data
->continue_data
= NULL
;
169 if (data
->fh
.data
.data_val
!= NULL
) {
170 free(data
->fh
.data
.data_val
);
171 data
->fh
.data
.data_val
= NULL
;
181 static void nfs_mount_9_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
183 struct nfs_cb_data
*data
= private_data
;
184 struct nfs_context
*nfs
= data
->nfs
;
186 if (status
== RPC_STATUS_ERROR
) {
187 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
188 free_nfs_cb_data(data
);
191 if (status
== RPC_STATUS_CANCEL
) {
192 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
193 free_nfs_cb_data(data
);
197 data
->cb(0, nfs
, NULL
, data
->private_data
);
198 free_nfs_cb_data(data
);
201 static void nfs_mount_8_cb(struct rpc_context
*rpc
, 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
);
218 if (rpc_nfs_getattr_async(rpc
, nfs_mount_9_cb
, &nfs
->rootfh
, data
) != 0) {
219 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
220 free_nfs_cb_data(data
);
225 static void nfs_mount_7_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
227 struct nfs_cb_data
*data
= private_data
;
228 struct nfs_context
*nfs
= data
->nfs
;
230 if (status
== RPC_STATUS_ERROR
) {
231 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
232 free_nfs_cb_data(data
);
235 if (status
== RPC_STATUS_CANCEL
) {
236 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
237 free_nfs_cb_data(data
);
241 if (rpc_nfs_null_async(rpc
, nfs_mount_8_cb
, data
) != 0) {
242 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
243 free_nfs_cb_data(data
);
249 static void nfs_mount_6_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
251 struct nfs_cb_data
*data
= private_data
;
252 struct nfs_context
*nfs
= data
->nfs
;
255 if (status
== RPC_STATUS_ERROR
) {
256 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
257 free_nfs_cb_data(data
);
260 if (status
== RPC_STATUS_CANCEL
) {
261 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
262 free_nfs_cb_data(data
);
267 if (res
->fhs_status
!= MNT3_OK
) {
268 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
));
269 data
->cb(mountstat3_to_errno(res
->fhs_status
), nfs
, rpc_get_error(rpc
), data
->private_data
);
270 free_nfs_cb_data(data
);
274 nfs
->rootfh
.data
.data_len
= res
->mountres3_u
.mountinfo
.fhandle
.fhandle3_len
;
275 nfs
->rootfh
.data
.data_val
= malloc(nfs
->rootfh
.data
.data_len
);
276 if (nfs
->rootfh
.data
.data_val
== NULL
) {
277 rpc_set_error(rpc
, "Out of memory. Could not allocate memory to store root filehandle");
278 data
->cb(-ENOMEM
, nfs
, rpc_get_error(rpc
), data
->private_data
);
279 free_nfs_cb_data(data
);
282 memcpy(nfs
->rootfh
.data
.data_val
, res
->mountres3_u
.mountinfo
.fhandle
.fhandle3_val
, nfs
->rootfh
.data
.data_len
);
284 rpc_disconnect(rpc
, "normal disconnect");
285 if (rpc_connect_async(rpc
, nfs
->server
, 2049, nfs_mount_7_cb
, data
) != 0) {
286 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
287 free_nfs_cb_data(data
);
293 static void nfs_mount_5_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
295 struct nfs_cb_data
*data
= private_data
;
296 struct nfs_context
*nfs
= data
->nfs
;
298 if (status
== RPC_STATUS_ERROR
) {
299 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
300 free_nfs_cb_data(data
);
303 if (status
== RPC_STATUS_CANCEL
) {
304 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
305 free_nfs_cb_data(data
);
309 if (rpc_mount_mnt_async(rpc
, nfs_mount_6_cb
, nfs
->export
, data
) != 0) {
310 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
311 free_nfs_cb_data(data
);
316 static void nfs_mount_4_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
318 struct nfs_cb_data
*data
= private_data
;
319 struct nfs_context
*nfs
= data
->nfs
;
321 if (status
== RPC_STATUS_ERROR
) {
322 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
323 free_nfs_cb_data(data
);
326 if (status
== RPC_STATUS_CANCEL
) {
327 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
328 free_nfs_cb_data(data
);
332 if (rpc_mount_null_async(rpc
, nfs_mount_5_cb
, data
) != 0) {
333 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
334 free_nfs_cb_data(data
);
339 static void nfs_mount_3_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
341 struct nfs_cb_data
*data
= private_data
;
342 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 mount_port
= *(uint32_t *)command_data
;
357 if (mount_port
== 0) {
358 rpc_set_error(rpc
, "RPC error. Mount program is not available on %s", nfs
->server
);
359 data
->cb(-ENOENT
, nfs
, command_data
, data
->private_data
);
360 free_nfs_cb_data(data
);
364 rpc_disconnect(rpc
, "normal disconnect");
365 if (rpc_connect_async(rpc
, nfs
->server
, mount_port
, nfs_mount_4_cb
, data
) != 0) {
366 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
367 free_nfs_cb_data(data
);
373 static void nfs_mount_2_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
375 struct nfs_cb_data
*data
= private_data
;
376 struct nfs_context
*nfs
= data
->nfs
;
378 if (status
== RPC_STATUS_ERROR
) {
379 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
380 free_nfs_cb_data(data
);
383 if (status
== RPC_STATUS_CANCEL
) {
384 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
385 free_nfs_cb_data(data
);
389 if (rpc_pmap_getport_async(rpc
, MOUNT_PROGRAM
, MOUNT_V3
, nfs_mount_3_cb
, private_data
) != 0) {
390 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
391 free_nfs_cb_data(data
);
396 static void nfs_mount_1_cb(struct rpc_context
*rpc
, int status
, void *command_data
, void *private_data
)
398 struct nfs_cb_data
*data
= private_data
;
399 struct nfs_context
*nfs
= data
->nfs
;
401 if (status
== RPC_STATUS_ERROR
) {
402 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
403 free_nfs_cb_data(data
);
406 if (status
== RPC_STATUS_CANCEL
) {
407 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
408 free_nfs_cb_data(data
);
412 if (rpc_pmap_null_async(rpc
, nfs_mount_2_cb
, data
) != 0) {
413 data
->cb(-ENOMEM
, nfs
, command_data
, data
->private_data
);
414 free_nfs_cb_data(data
);
420 * Async call for mounting an nfs share and geting the root filehandle
422 int nfs_mount_async(struct nfs_context
*nfs
, const char *server
, const char *export
, nfs_cb cb
, void *private_data
)
424 struct nfs_cb_data
*data
;
426 data
= malloc(sizeof(struct nfs_cb_data
));
428 rpc_set_error(nfs
->rpc
, "out of memory");
429 printf("failed to allocate memory for nfs mount data\n");
432 bzero(data
, sizeof(struct nfs_cb_data
));
433 nfs
->server
= strdup(server
);
434 nfs
->export
= strdup(export
);
437 data
->private_data
= private_data
;
439 if (rpc_connect_async(nfs
->rpc
, server
, 111, nfs_mount_1_cb
, data
) != 0) {
440 printf("Failed to start connection\n");
441 free_nfs_cb_data(data
);
451 * Functions to first look up a path, component by component, and then finally call a specific function once
452 * the filehandle for the final component is found.
454 static void nfs_lookup_path_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
456 struct nfs_cb_data
*data
= private_data
;
457 struct nfs_context
*nfs
= data
->nfs
;
460 if (status
== RPC_STATUS_ERROR
) {
461 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
462 free_nfs_cb_data(data
);
465 if (status
== RPC_STATUS_CANCEL
) {
466 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
467 free_nfs_cb_data(data
);
472 if (res
->status
!= NFS3_OK
) {
473 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
));
474 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
475 free_nfs_cb_data(data
);
479 if (nfs_lookup_path_async_internal(nfs
, data
, &res
->LOOKUP3res_u
.resok
.object
) != 0) {
480 rpc_set_error(nfs
->rpc
, "Failed to create lookup pdu");
481 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
482 free_nfs_cb_data(data
);
487 static int nfs_lookup_path_async_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
, struct nfs_fh3
*fh
)
491 while (*data
->path
== '/') {
496 str
= index(path
, '/');
501 while (*data
->path
!= 0) {
507 data
->fh
.data
.data_len
= fh
->data
.data_len
;
508 data
->fh
.data
.data_val
= malloc(data
->fh
.data
.data_len
);
509 if (data
->fh
.data
.data_val
== NULL
) {
510 rpc_set_error(nfs
->rpc
, "Out of memory: Failed to allocate fh for %s", data
->path
);
511 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
512 free_nfs_cb_data(data
);
515 memcpy(data
->fh
.data
.data_val
, fh
->data
.data_val
, data
->fh
.data
.data_len
);
516 data
->continue_cb(nfs
, data
);
520 if (rpc_nfs_lookup_async(nfs
->rpc
, nfs_lookup_path_1_cb
, fh
, path
, data
) != 0) {
521 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send lookup call for %s", data
->path
);
522 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
523 free_nfs_cb_data(data
);
529 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
)
531 struct nfs_cb_data
*data
;
533 if (path
[0] != '/') {
534 rpc_set_error(nfs
->rpc
, "Pathname is not absulute %s", path
);
538 data
= malloc(sizeof(struct nfs_cb_data
));
540 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
541 printf("failed to allocate memory for nfs cb data\n");
542 free_nfs_cb_data(data
);
545 bzero(data
, sizeof(struct nfs_cb_data
));
548 data
->continue_cb
= continue_cb
;
549 data
->continue_data
= continue_data
;
550 data
->free_continue_data
= free_continue_data
;
551 data
->continue_int
= continue_int
;
552 data
->private_data
= private_data
;
553 data
->saved_path
= strdup(path
);
554 if (data
->saved_path
== NULL
) {
555 rpc_set_error(nfs
->rpc
, "out of memory: failed to copy path string");
556 printf("failed to allocate memory for path string\n");
557 free_nfs_cb_data(data
);
560 data
->path
= data
->saved_path
;
562 if (nfs_lookup_path_async_internal(nfs
, data
, &nfs
->rootfh
) != 0) {
563 printf("failed to lookup path\n");
564 /* return 0 here since the callback will be invoked if there is a failure */
577 static void nfs_stat_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
580 struct nfs_cb_data
*data
= private_data
;
581 struct nfs_context
*nfs
= data
->nfs
;
584 if (status
== RPC_STATUS_ERROR
) {
585 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
586 free_nfs_cb_data(data
);
589 if (status
== RPC_STATUS_CANCEL
) {
590 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
591 free_nfs_cb_data(data
);
596 if (res
->status
!= NFS3_OK
) {
597 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
));
598 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
599 free_nfs_cb_data(data
);
604 st
.st_ino
= res
->GETATTR3res_u
.resok
.obj_attributes
.fileid
;
605 st
.st_mode
= res
->GETATTR3res_u
.resok
.obj_attributes
.mode
;
606 st
.st_nlink
= res
->GETATTR3res_u
.resok
.obj_attributes
.nlink
;
607 st
.st_uid
= res
->GETATTR3res_u
.resok
.obj_attributes
.uid
;
608 st
.st_gid
= res
->GETATTR3res_u
.resok
.obj_attributes
.gid
;
610 st
.st_size
= res
->GETATTR3res_u
.resok
.obj_attributes
.size
;
611 st
.st_blksize
= 4096;
612 st
.st_blocks
= res
->GETATTR3res_u
.resok
.obj_attributes
.size
/ 4096;
613 st
.st_atime
= res
->GETATTR3res_u
.resok
.obj_attributes
.atime
.seconds
;
614 st
.st_mtime
= res
->GETATTR3res_u
.resok
.obj_attributes
.mtime
.seconds
;
615 st
.st_ctime
= res
->GETATTR3res_u
.resok
.obj_attributes
.ctime
.seconds
;
617 data
->cb(0, nfs
, &st
, data
->private_data
);
618 free_nfs_cb_data(data
);
621 static int nfs_stat_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
623 if (rpc_nfs_getattr_async(nfs
->rpc
, nfs_stat_1_cb
, &data
->fh
, data
) != 0) {
624 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send STAT GETATTR call for %s", data
->path
);
625 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
626 free_nfs_cb_data(data
);
632 int nfs_stat_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
634 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_stat_continue_internal
, NULL
, NULL
, 0) != 0) {
635 printf("Out of memory: failed to start parsing the path components\n");
649 static void nfs_open_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
652 struct nfs_cb_data
*data
= private_data
;
653 struct nfs_context
*nfs
= data
->nfs
;
655 unsigned int nfsmode
= 0;
657 if (status
== RPC_STATUS_ERROR
) {
658 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
659 free_nfs_cb_data(data
);
662 if (status
== RPC_STATUS_CANCEL
) {
663 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
664 free_nfs_cb_data(data
);
669 if (res
->status
!= NFS3_OK
) {
670 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
));
671 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
672 free_nfs_cb_data(data
);
676 if (data
->continue_int
& O_WRONLY
) {
677 nfsmode
|= ACCESS3_MODIFY
;
679 if (data
->continue_int
& O_RDWR
) {
680 nfsmode
|= ACCESS3_READ
|ACCESS3_MODIFY
;
682 if (!(data
->continue_int
& (O_WRONLY
|O_RDWR
))) {
683 nfsmode
|= ACCESS3_READ
;
687 if (res
->ACCESS3res_u
.resok
.access
!= nfsmode
) {
688 rpc_set_error(nfs
->rpc
, "NFS: ACCESS denied. Required access %c%c%c. Allowed access %c%c%c",
689 nfsmode
&ACCESS3_READ
?'r':'-',
690 nfsmode
&ACCESS3_MODIFY
?'w':'-',
691 nfsmode
&ACCESS3_EXECUTE
?'x':'-',
692 res
->ACCESS3res_u
.resok
.access
&ACCESS3_READ
?'r':'-',
693 res
->ACCESS3res_u
.resok
.access
&ACCESS3_MODIFY
?'w':'-',
694 res
->ACCESS3res_u
.resok
.access
&ACCESS3_EXECUTE
?'x':'-');
695 data
->cb(-EACCES
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
696 free_nfs_cb_data(data
);
700 nfsfh
= malloc(sizeof(struct nfsfh
));
702 rpc_set_error(nfs
->rpc
, "NFS: Failed to allocate nfsfh structure");
703 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
704 free_nfs_cb_data(data
);
707 bzero(nfsfh
, sizeof(struct nfsfh
));
709 if (data
->continue_int
& O_SYNC
) {
713 /* steal the filehandle */
714 nfsfh
->fh
.data
.data_len
= data
->fh
.data
.data_len
;
715 nfsfh
->fh
.data
.data_val
= data
->fh
.data
.data_val
;
716 data
->fh
.data
.data_val
= NULL
;
718 data
->cb(0, nfs
, nfsfh
, data
->private_data
);
719 free_nfs_cb_data(data
);
722 static int nfs_open_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
726 if (data
->continue_int
& O_WRONLY
) {
727 nfsmode
|= ACCESS3_MODIFY
;
729 if (data
->continue_int
& O_RDWR
) {
730 nfsmode
|= ACCESS3_READ
|ACCESS3_MODIFY
;
732 if (!(data
->continue_int
& (O_WRONLY
|O_RDWR
))) {
733 nfsmode
|= ACCESS3_READ
;
736 if (rpc_nfs_access_async(nfs
->rpc
, nfs_open_cb
, &data
->fh
, nfsmode
, data
) != 0) {
737 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send OPEN ACCESS call for %s", data
->path
);
738 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
739 free_nfs_cb_data(data
);
745 int nfs_open_async(struct nfs_context
*nfs
, const char *path
, int mode
, nfs_cb cb
, void *private_data
)
747 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_open_continue_internal
, NULL
, NULL
, mode
) != 0) {
748 printf("Out of memory: failed to start parsing the path components\n");
762 static void nfs_pread_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
764 struct nfs_cb_data
*data
= private_data
;
765 struct nfs_context
*nfs
= data
->nfs
;
768 if (status
== RPC_STATUS_ERROR
) {
769 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
770 free_nfs_cb_data(data
);
773 if (status
== RPC_STATUS_CANCEL
) {
774 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
775 free_nfs_cb_data(data
);
780 if (res
->status
!= NFS3_OK
) {
781 rpc_set_error(nfs
->rpc
, "NFS: Read failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
782 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
783 free_nfs_cb_data(data
);
787 data
->nfsfh
->offset
+= res
->READ3res_u
.resok
.count
;
788 data
->cb(res
->READ3res_u
.resok
.count
, nfs
, res
->READ3res_u
.resok
.data
.data_val
, data
->private_data
);
789 free_nfs_cb_data(data
);
792 int nfs_pread_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, size_t count
, nfs_cb cb
, void *private_data
)
794 struct nfs_cb_data
*data
;
796 data
= malloc(sizeof(struct nfs_cb_data
));
798 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
799 printf("failed to allocate memory for nfs cb data\n");
800 free_nfs_cb_data(data
);
803 bzero(data
, sizeof(struct nfs_cb_data
));
806 data
->private_data
= private_data
;
809 nfsfh
->offset
= offset
;
810 if (rpc_nfs_read_async(nfs
->rpc
, nfs_pread_cb
, &nfsfh
->fh
, offset
, count
, data
) != 0) {
811 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send READ call for %s", data
->path
);
812 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
813 free_nfs_cb_data(data
);
822 int nfs_read_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, size_t count
, nfs_cb cb
, void *private_data
)
824 return nfs_pread_async(nfs
, nfsfh
, nfsfh
->offset
, count
, cb
, private_data
);
832 static void nfs_pwrite_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
834 struct nfs_cb_data
*data
= private_data
;
835 struct nfs_context
*nfs
= data
->nfs
;
838 if (status
== RPC_STATUS_ERROR
) {
839 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
840 free_nfs_cb_data(data
);
843 if (status
== RPC_STATUS_CANCEL
) {
844 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
845 free_nfs_cb_data(data
);
850 if (res
->status
!= NFS3_OK
) {
851 rpc_set_error(nfs
->rpc
, "NFS: Write failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
852 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
853 free_nfs_cb_data(data
);
857 data
->nfsfh
->offset
+= res
->WRITE3res_u
.resok
.count
;
858 data
->cb(res
->WRITE3res_u
.resok
.count
, nfs
, NULL
, data
->private_data
);
859 free_nfs_cb_data(data
);
862 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
)
864 struct nfs_cb_data
*data
;
866 data
= malloc(sizeof(struct nfs_cb_data
));
868 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
869 printf("failed to allocate memory for nfs cb data\n");
870 free_nfs_cb_data(data
);
873 bzero(data
, sizeof(struct nfs_cb_data
));
876 data
->private_data
= private_data
;
879 nfsfh
->offset
= offset
;
880 if (rpc_nfs_write_async(nfs
->rpc
, nfs_pwrite_cb
, &nfsfh
->fh
, buf
, offset
, count
, nfsfh
->is_sync
?FILE_SYNC
:UNSTABLE
, data
) != 0) {
881 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send WRITE call for %s", data
->path
);
882 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
883 free_nfs_cb_data(data
);
892 int nfs_write_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, size_t count
, char *buf
, nfs_cb cb
, void *private_data
)
894 return nfs_pwrite_async(nfs
, nfsfh
, nfsfh
->offset
, count
, buf
, cb
, private_data
);
904 int nfs_close_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, nfs_cb cb
, void *private_data
)
906 if (nfsfh
->fh
.data
.data_val
!= NULL
){
907 free(nfsfh
->fh
.data
.data_val
);
908 nfsfh
->fh
.data
.data_val
= NULL
;
912 cb(0, nfs
, NULL
, private_data
);
923 int nfs_fstat_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, 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");
930 printf("failed to allocate memory for nfs cb data\n");
931 free_nfs_cb_data(data
);
934 bzero(data
, sizeof(struct nfs_cb_data
));
937 data
->private_data
= private_data
;
939 if (rpc_nfs_getattr_async(nfs
->rpc
, nfs_stat_1_cb
, &nfsfh
->fh
, data
) != 0) {
940 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send STAT GETATTR call for %s", data
->path
);
941 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
942 free_nfs_cb_data(data
);
953 static void nfs_fsync_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
955 struct nfs_cb_data
*data
= private_data
;
956 struct nfs_context
*nfs
= data
->nfs
;
959 if (status
== RPC_STATUS_ERROR
) {
960 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
961 free_nfs_cb_data(data
);
964 if (status
== RPC_STATUS_CANCEL
) {
965 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
966 free_nfs_cb_data(data
);
971 if (res
->status
!= NFS3_OK
) {
972 rpc_set_error(nfs
->rpc
, "NFS: Commit failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
973 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
974 free_nfs_cb_data(data
);
978 data
->cb(0, nfs
, NULL
, data
->private_data
);
979 free_nfs_cb_data(data
);
982 int nfs_fsync_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, nfs_cb cb
, void *private_data
)
984 struct nfs_cb_data
*data
;
986 data
= malloc(sizeof(struct nfs_cb_data
));
988 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
989 printf("failed to allocate memory for nfs cb data\n");
990 free_nfs_cb_data(data
);
993 bzero(data
, sizeof(struct nfs_cb_data
));
996 data
->private_data
= private_data
;
998 if (rpc_nfs_commit_async(nfs
->rpc
, nfs_fsync_cb
, &nfsfh
->fh
, data
) != 0) {
999 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send COMMIT call for %s", data
->path
);
1000 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1001 free_nfs_cb_data(data
);
1013 static void nfs_ftruncate_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1015 struct nfs_cb_data
*data
= private_data
;
1016 struct nfs_context
*nfs
= data
->nfs
;
1019 if (status
== RPC_STATUS_ERROR
) {
1020 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1021 free_nfs_cb_data(data
);
1024 if (status
== RPC_STATUS_CANCEL
) {
1025 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1026 free_nfs_cb_data(data
);
1031 if (res
->status
!= NFS3_OK
) {
1032 rpc_set_error(nfs
->rpc
, "NFS: Setattr failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
1033 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1034 free_nfs_cb_data(data
);
1038 data
->cb(0, nfs
, NULL
, data
->private_data
);
1039 free_nfs_cb_data(data
);
1042 int nfs_ftruncate_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t length
, nfs_cb cb
, void *private_data
)
1044 struct nfs_cb_data
*data
;
1047 data
= malloc(sizeof(struct nfs_cb_data
));
1049 rpc_set_error(nfs
->rpc
, "out of memory: failed to allocate nfs_cb_data structure");
1050 printf("failed to allocate memory for nfs cb data\n");
1051 free_nfs_cb_data(data
);
1054 bzero(data
, sizeof(struct nfs_cb_data
));
1057 data
->private_data
= private_data
;
1059 bzero(&args
, sizeof(SETATTR3args
));
1060 args
.object
.data
.data_len
= nfsfh
->fh
.data
.data_len
;
1061 args
.object
.data
.data_val
= nfsfh
->fh
.data
.data_val
;
1062 args
.new_attributes
.size
.set_it
= 1;
1063 args
.new_attributes
.size
.set_size3_u
.size
= length
;
1065 if (rpc_nfs_setattr_async(nfs
->rpc
, nfs_ftruncate_cb
, &args
, data
) != 0) {
1066 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SETATTR call for %s", data
->path
);
1067 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1068 free_nfs_cb_data(data
);
1078 static int nfs_truncate_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1080 off_t offset
= data
->continue_int
;
1083 nfsfh
.fh
.data
.data_val
= data
->fh
.data
.data_val
;
1084 nfsfh
.fh
.data
.data_len
= data
->fh
.data
.data_len
;
1086 if (nfs_ftruncate_async(nfs
, &nfsfh
, offset
, data
->cb
, data
->private_data
) != 0) {
1087 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SETATTR call for %s", data
->path
);
1088 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1089 free_nfs_cb_data(data
);
1092 free_nfs_cb_data(data
);
1096 int nfs_truncate_async(struct nfs_context
*nfs
, const char *path
, off_t length
, nfs_cb cb
, void *private_data
)
1102 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_truncate_continue_internal
, NULL
, NULL
, offset
) != 0) {
1103 printf("Out of memory: failed to start parsing the path components\n");
1116 static void nfs_mkdir_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1119 struct nfs_cb_data
*data
= private_data
;
1120 struct nfs_context
*nfs
= data
->nfs
;
1121 char *str
= data
->continue_data
;
1123 str
= &str
[strlen(str
) + 1];
1125 if (status
== RPC_STATUS_ERROR
) {
1126 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1127 free_nfs_cb_data(data
);
1130 if (status
== RPC_STATUS_CANCEL
) {
1131 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1132 free_nfs_cb_data(data
);
1137 if (res
->status
!= NFS3_OK
) {
1138 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
));
1139 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1140 free_nfs_cb_data(data
);
1144 data
->cb(0, nfs
, NULL
, data
->private_data
);
1145 free_nfs_cb_data(data
);
1148 static int nfs_mkdir_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1150 char *str
= data
->continue_data
;
1152 str
= &str
[strlen(str
) + 1];
1154 if (rpc_nfs_mkdir_async(nfs
->rpc
, nfs_mkdir_cb
, &data
->fh
, str
, data
) != 0) {
1155 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send MKDIR call for %s", data
->path
);
1156 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1157 free_nfs_cb_data(data
);
1163 int nfs_mkdir_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1168 new_path
= strdup(path
);
1169 if (new_path
== NULL
) {
1170 printf("Out of memory, failed to allocate mode buffer for path\n");
1174 ptr
= rindex(new_path
, '/');
1176 printf("Invalid path %s\n", path
);
1181 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1182 if (nfs_lookuppath_async(nfs
, new_path
, cb
, private_data
, nfs_mkdir_continue_internal
, new_path
, free
, 0) != 0) {
1183 printf("Out of memory: failed to start parsing the path components\n");
1197 static void nfs_rmdir_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1200 struct nfs_cb_data
*data
= private_data
;
1201 struct nfs_context
*nfs
= data
->nfs
;
1202 char *str
= data
->continue_data
;
1204 str
= &str
[strlen(str
) + 1];
1206 if (status
== RPC_STATUS_ERROR
) {
1207 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1208 free_nfs_cb_data(data
);
1211 if (status
== RPC_STATUS_CANCEL
) {
1212 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1213 free_nfs_cb_data(data
);
1218 if (res
->status
!= NFS3_OK
) {
1219 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
));
1220 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1221 free_nfs_cb_data(data
);
1225 data
->cb(0, nfs
, NULL
, data
->private_data
);
1226 free_nfs_cb_data(data
);
1229 static int nfs_rmdir_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1231 char *str
= data
->continue_data
;
1233 str
= &str
[strlen(str
) + 1];
1235 if (rpc_nfs_rmdir_async(nfs
->rpc
, nfs_rmdir_cb
, &data
->fh
, str
, data
) != 0) {
1236 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send RMDIR call for %s", data
->path
);
1237 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1238 free_nfs_cb_data(data
);
1244 int nfs_rmdir_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1249 new_path
= strdup(path
);
1250 if (new_path
== NULL
) {
1251 printf("Out of memory, failed to allocate mode buffer for path\n");
1255 ptr
= rindex(new_path
, '/');
1257 printf("Invalid path %s\n", path
);
1262 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1263 if (nfs_lookuppath_async(nfs
, new_path
, cb
, private_data
, nfs_rmdir_continue_internal
, new_path
, free
, 0) != 0) {
1264 printf("Out of memory: failed to start parsing the path components\n");
1277 static void nfs_create_2_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1280 struct nfs_cb_data
*data
= private_data
;
1281 struct nfs_context
*nfs
= data
->nfs
;
1282 struct nfsfh
*nfsfh
;
1283 char *str
= data
->continue_data
;
1285 if (status
== RPC_STATUS_ERROR
) {
1286 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1287 free_nfs_cb_data(data
);
1290 if (status
== RPC_STATUS_CANCEL
) {
1291 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1292 free_nfs_cb_data(data
);
1296 str
= &str
[strlen(str
) + 1];
1298 if (res
->status
!= NFS3_OK
) {
1299 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
));
1300 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1305 nfsfh
= malloc(sizeof(struct nfsfh
));
1306 if (nfsfh
== NULL
) {
1307 rpc_set_error(nfs
->rpc
, "NFS: Failed to allocate nfsfh structure");
1308 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1309 free_nfs_cb_data(data
);
1312 bzero(nfsfh
, sizeof(struct nfsfh
));
1314 /* steal the filehandle */
1315 nfsfh
->fh
.data
.data_len
= data
->fh
.data
.data_len
;
1316 nfsfh
->fh
.data
.data_val
= data
->fh
.data
.data_val
;
1317 data
->fh
.data
.data_val
= NULL
;
1319 data
->cb(0, nfs
, nfsfh
, data
->private_data
);
1320 free_nfs_cb_data(data
);
1325 static void nfs_creat_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1328 struct nfs_cb_data
*data
= private_data
;
1329 struct nfs_context
*nfs
= data
->nfs
;
1330 char *str
= data
->continue_data
;
1332 if (status
== RPC_STATUS_ERROR
) {
1333 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1334 free_nfs_cb_data(data
);
1337 if (status
== RPC_STATUS_CANCEL
) {
1338 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1339 free_nfs_cb_data(data
);
1343 str
= &str
[strlen(str
) + 1];
1345 if (res
->status
!= NFS3_OK
) {
1346 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
));
1347 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1352 if (rpc_nfs_lookup_async(nfs
->rpc
, nfs_create_2_cb
, &data
->fh
, str
, data
) != 0) {
1353 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send lookup call for %s/%s", data
->saved_path
, str
);
1354 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1355 free_nfs_cb_data(data
);
1361 static int nfs_creat_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1363 char *str
= data
->continue_data
;
1365 str
= &str
[strlen(str
) + 1];
1367 if (rpc_nfs_create_async(nfs
->rpc
, nfs_creat_1_cb
, &data
->fh
, str
, data
->continue_int
, data
) != 0) {
1368 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send CREATE call for %s/%s", data
->path
, str
);
1369 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1370 free_nfs_cb_data(data
);
1376 int nfs_creat_async(struct nfs_context
*nfs
, const char *path
, int mode
, nfs_cb cb
, void *private_data
)
1381 new_path
= strdup(path
);
1382 if (new_path
== NULL
) {
1383 printf("Out of memory, failed to allocate mode buffer for path\n");
1387 ptr
= rindex(new_path
, '/');
1389 printf("Invalid path %s\n", path
);
1394 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1395 if (nfs_lookuppath_async(nfs
, new_path
, cb
, private_data
, nfs_creat_continue_internal
, new_path
, free
, mode
) != 0) {
1396 printf("Out of memory: failed to start parsing the path components\n");
1409 static void nfs_unlink_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1412 struct nfs_cb_data
*data
= private_data
;
1413 struct nfs_context
*nfs
= data
->nfs
;
1414 char *str
= data
->continue_data
;
1416 str
= &str
[strlen(str
) + 1];
1418 if (status
== RPC_STATUS_ERROR
) {
1419 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1420 free_nfs_cb_data(data
);
1423 if (status
== RPC_STATUS_CANCEL
) {
1424 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1425 free_nfs_cb_data(data
);
1430 if (res
->status
!= NFS3_OK
) {
1431 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
));
1432 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1433 free_nfs_cb_data(data
);
1437 data
->cb(0, nfs
, NULL
, data
->private_data
);
1438 free_nfs_cb_data(data
);
1441 static int nfs_unlink_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1443 char *str
= data
->continue_data
;
1445 str
= &str
[strlen(str
) + 1];
1447 if (rpc_nfs_remove_async(nfs
->rpc
, nfs_unlink_cb
, &data
->fh
, str
, data
) != 0) {
1448 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send REMOVE call for %s", data
->path
);
1449 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1450 free_nfs_cb_data(data
);
1456 int nfs_unlink_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1461 new_path
= strdup(path
);
1462 if (new_path
== NULL
) {
1463 printf("Out of memory, failed to allocate mode buffer for path\n");
1467 ptr
= rindex(new_path
, '/');
1469 printf("Invalid path %s\n", path
);
1474 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1475 if (nfs_lookuppath_async(nfs
, new_path
, cb
, private_data
, nfs_unlink_continue_internal
, new_path
, free
, 0) != 0) {
1476 printf("Out of memory: failed to start parsing the path components\n");
1490 static void nfs_opendir_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1493 struct nfs_cb_data
*data
= private_data
;
1494 struct nfs_context
*nfs
= data
->nfs
;
1495 struct nfsdir
*nfsdir
= data
->continue_data
;;
1496 struct entry3
*entry
;
1499 if (status
== RPC_STATUS_ERROR
) {
1500 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1501 nfs_free_nfsdir(nfsdir
);
1502 data
->continue_data
= NULL
;
1503 free_nfs_cb_data(data
);
1506 if (status
== RPC_STATUS_CANCEL
) {
1507 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1508 nfs_free_nfsdir(nfsdir
);
1509 data
->continue_data
= NULL
;
1510 free_nfs_cb_data(data
);
1515 if (res
->status
!= NFS3_OK
) {
1516 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
));
1517 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1518 nfs_free_nfsdir(nfsdir
);
1519 data
->continue_data
= NULL
;
1520 free_nfs_cb_data(data
);
1524 entry
=res
->READDIR3res_u
.resok
.reply
.entries
;
1525 while (entry
!= NULL
) {
1526 struct nfsdirent
*nfsdirent
;
1528 nfsdirent
= malloc(sizeof(struct nfsdirent
));
1529 if (nfsdirent
== NULL
) {
1530 data
->cb(-ENOMEM
, nfs
, "Failed to allocate dirent", data
->private_data
);
1531 nfs_free_nfsdir(nfsdir
);
1532 data
->continue_data
= NULL
;
1533 free_nfs_cb_data(data
);
1536 bzero(nfsdirent
, sizeof(struct nfsdirent
));
1537 nfsdirent
->name
= strdup(entry
->name
);
1538 if (nfsdirent
->name
== NULL
) {
1539 data
->cb(-ENOMEM
, nfs
, "Failed to allocate dirent->name", data
->private_data
);
1540 nfs_free_nfsdir(nfsdir
);
1541 data
->continue_data
= NULL
;
1542 free_nfs_cb_data(data
);
1545 nfsdirent
->inode
= entry
->fileid
;
1546 nfsdirent
->next
= nfsdir
->entries
;
1547 nfsdir
->entries
= nfsdirent
;
1549 cookie
= entry
->cookie
;
1550 entry
= entry
->nextentry
;
1553 if (res
->READDIR3res_u
.resok
.reply
.eof
== 0) {
1554 if (rpc_nfs_readdir_async(nfs
->rpc
, nfs_opendir_cb
, &data
->fh
, cookie
, res
->READDIR3res_u
.resok
.cookieverf
, 20000, data
) != 0) {
1555 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send READDIR call for %s", data
->path
);
1556 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1557 nfs_free_nfsdir(nfsdir
);
1558 data
->continue_data
= NULL
;
1559 free_nfs_cb_data(data
);
1565 /* steal the dirhandle */
1566 data
->continue_data
= NULL
;
1567 nfsdir
->current
= nfsdir
->entries
;
1569 data
->cb(0, nfs
, nfsdir
, data
->private_data
);
1570 free_nfs_cb_data(data
);
1573 static int nfs_opendir_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1577 bzero(cv
, sizeof(cookieverf3
));
1578 if (rpc_nfs_readdir_async(nfs
->rpc
, nfs_opendir_cb
, &data
->fh
, 0, (char *)&cv
, 20000, data
) != 0) {
1579 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send READDIR call for %s", data
->path
);
1580 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1581 free_nfs_cb_data(data
);
1587 int nfs_opendir_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1589 struct nfsdir
*nfsdir
;
1591 nfsdir
= malloc(sizeof(struct nfsdir
));
1592 if (nfsdir
== NULL
) {
1593 printf("failed to allocate buffer for nfsdir\n");
1596 bzero(nfsdir
, sizeof(struct nfsdir
));
1598 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_opendir_continue_internal
, nfsdir
, free
, 0) != 0) {
1599 printf("Out of memory: failed to start parsing the path components\n");
1607 struct nfsdirent
*nfs_readdir(struct nfs_context
*nfs _U_
, struct nfsdir
*nfsdir
)
1609 struct nfsdirent
*nfsdirent
= nfsdir
->current
;
1611 if (nfsdir
->current
!= NULL
) {
1612 nfsdir
->current
= nfsdir
->current
->next
;
1618 void nfs_closedir(struct nfs_context
*nfs _U_
, struct nfsdir
*nfsdir
)
1620 nfs_free_nfsdir(nfsdir
);
1632 struct lseek_cb_data
{
1633 struct nfs_context
*nfs
;
1634 struct nfsfh
*nfsfh
;
1640 static void nfs_lseek_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1643 struct lseek_cb_data
*data
= private_data
;
1644 struct nfs_context
*nfs
= data
->nfs
;
1646 if (status
== RPC_STATUS_ERROR
) {
1647 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1651 if (status
== RPC_STATUS_CANCEL
) {
1652 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1658 if (res
->status
!= NFS3_OK
) {
1659 rpc_set_error(nfs
->rpc
, "NFS: GETATTR failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
1660 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1665 data
->nfsfh
->offset
= data
->offset
+ res
->GETATTR3res_u
.resok
.obj_attributes
.size
;
1666 data
->cb(0, nfs
, &data
->nfsfh
->offset
, data
->private_data
);
1670 int nfs_lseek_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, int whence
, nfs_cb cb
, void *private_data
)
1672 struct lseek_cb_data
*data
;
1674 if (whence
== SEEK_SET
) {
1675 nfsfh
->offset
= offset
;
1676 cb(0, nfs
, &nfsfh
->offset
, private_data
);
1679 if (whence
== SEEK_CUR
) {
1680 nfsfh
->offset
+= offset
;
1681 cb(0, nfs
, &nfsfh
->offset
, private_data
);
1685 data
= malloc(sizeof(struct lseek_cb_data
));
1687 rpc_set_error(nfs
->rpc
, "Out Of Memory: Failed to malloc lseek cb data");
1692 data
->nfsfh
= nfsfh
;
1693 data
->offset
= offset
;
1695 data
->private_data
= private_data
;
1697 if (rpc_nfs_getattr_async(nfs
->rpc
, nfs_lseek_1_cb
, &nfsfh
->fh
, data
) != 0) {
1698 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send LSEEK GETATTR call");
1711 static void nfs_statvfs_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1714 struct nfs_cb_data
*data
= private_data
;
1715 struct nfs_context
*nfs
= data
->nfs
;
1716 struct statvfs svfs
;
1718 if (status
== RPC_STATUS_ERROR
) {
1719 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1720 free_nfs_cb_data(data
);
1723 if (status
== RPC_STATUS_CANCEL
) {
1724 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1725 free_nfs_cb_data(data
);
1730 if (res
->status
!= NFS3_OK
) {
1731 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
));
1732 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1733 free_nfs_cb_data(data
);
1737 svfs
.f_bsize
= 4096;
1738 svfs
.f_frsize
= 4096;
1739 svfs
.f_blocks
= res
->FSSTAT3res_u
.resok
.tbytes
/4096;
1740 svfs
.f_bfree
= res
->FSSTAT3res_u
.resok
.fbytes
/4096;
1741 svfs
.f_bavail
= res
->FSSTAT3res_u
.resok
.abytes
/4096;
1742 svfs
.f_files
= res
->FSSTAT3res_u
.resok
.tfiles
;
1743 svfs
.f_ffree
= res
->FSSTAT3res_u
.resok
.ffiles
;
1744 svfs
.f_favail
= res
->FSSTAT3res_u
.resok
.afiles
;
1747 svfs
.f_namemax
= 256;
1749 data
->cb(0, nfs
, &svfs
, data
->private_data
);
1750 free_nfs_cb_data(data
);
1753 static int nfs_statvfs_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1755 if (rpc_nfs_fsstat_async(nfs
->rpc
, nfs_statvfs_1_cb
, &data
->fh
, data
) != 0) {
1756 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send FSSTAT call for %s", data
->path
);
1757 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1758 free_nfs_cb_data(data
);
1764 int nfs_statvfs_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1766 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_statvfs_continue_internal
, NULL
, NULL
, 0) != 0) {
1767 printf("Out of memory: failed to start parsing the path components\n");
1780 static void nfs_readlink_1_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1783 struct nfs_cb_data
*data
= private_data
;
1784 struct nfs_context
*nfs
= data
->nfs
;
1786 if (status
== RPC_STATUS_ERROR
) {
1787 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1788 free_nfs_cb_data(data
);
1791 if (status
== RPC_STATUS_CANCEL
) {
1792 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1793 free_nfs_cb_data(data
);
1798 if (res
->status
!= NFS3_OK
) {
1799 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
));
1800 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1801 free_nfs_cb_data(data
);
1806 data
->cb(0, nfs
, res
->READLINK3res_u
.resok
.data
, data
->private_data
);
1807 free_nfs_cb_data(data
);
1810 static int nfs_readlink_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1812 if (rpc_nfs_readlink_async(nfs
->rpc
, nfs_readlink_1_cb
, &data
->fh
, data
) != 0) {
1813 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send READLINK call for %s", data
->path
);
1814 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1815 free_nfs_cb_data(data
);
1821 int nfs_readlink_async(struct nfs_context
*nfs
, const char *path
, nfs_cb cb
, void *private_data
)
1823 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_readlink_continue_internal
, NULL
, NULL
, 0) != 0) {
1824 printf("Out of memory: failed to start parsing the path components\n");
1837 static void nfs_chmod_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1839 struct nfs_cb_data
*data
= private_data
;
1840 struct nfs_context
*nfs
= data
->nfs
;
1843 if (status
== RPC_STATUS_ERROR
) {
1844 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1845 free_nfs_cb_data(data
);
1848 if (status
== RPC_STATUS_CANCEL
) {
1849 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1850 free_nfs_cb_data(data
);
1855 if (res
->status
!= NFS3_OK
) {
1856 rpc_set_error(nfs
->rpc
, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
1857 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1858 free_nfs_cb_data(data
);
1862 data
->cb(0, nfs
, NULL
, data
->private_data
);
1863 free_nfs_cb_data(data
);
1866 static int nfs_chmod_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1870 bzero(&args
, sizeof(SETATTR3args
));
1871 args
.object
.data
.data_len
= data
->fh
.data
.data_len
;
1872 args
.object
.data
.data_val
= data
->fh
.data
.data_val
;
1873 args
.new_attributes
.mode
.set_it
= 1;
1874 args
.new_attributes
.mode
.set_mode3_u
.mode
= data
->continue_int
;
1876 if (rpc_nfs_setattr_async(nfs
->rpc
, nfs_chmod_cb
, &args
, data
) != 0) {
1877 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SETATTR call for %s", data
->path
);
1878 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1879 free_nfs_cb_data(data
);
1886 int nfs_chmod_async(struct nfs_context
*nfs
, const char *path
, int mode
, nfs_cb cb
, void *private_data
)
1888 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_chmod_continue_internal
, NULL
, NULL
, mode
) != 0) {
1889 printf("Out of memory: failed to start parsing the path components\n");
1899 int nfs_fchmod_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
, nfs_cb cb
, void *private_data
)
1901 struct nfs_cb_data
*data
;
1903 data
= malloc(sizeof(struct nfs_cb_data
));
1905 rpc_set_error(nfs
->rpc
, "out of memory");
1906 printf("failed to allocate memory for nfs mount data\n");
1909 bzero(data
, sizeof(struct nfs_cb_data
));
1912 data
->private_data
= private_data
;
1913 data
->continue_int
= mode
;
1914 data
->fh
.data
.data_len
= nfsfh
->fh
.data
.data_len
;
1915 data
->fh
.data
.data_val
= malloc(data
->fh
.data
.data_len
);
1916 if (data
->fh
.data
.data_val
== NULL
) {
1917 rpc_set_error(nfs
->rpc
, "Out of memory: Failed to allocate fh");
1918 free_nfs_cb_data(data
);
1921 memcpy(data
->fh
.data
.data_val
, nfsfh
->fh
.data
.data_val
, data
->fh
.data
.data_len
);
1923 if (nfs_chmod_continue_internal(nfs
, data
) != 0) {
1924 free_nfs_cb_data(data
);
1936 static void nfs_chown_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
1938 struct nfs_cb_data
*data
= private_data
;
1939 struct nfs_context
*nfs
= data
->nfs
;
1942 if (status
== RPC_STATUS_ERROR
) {
1943 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
1944 free_nfs_cb_data(data
);
1947 if (status
== RPC_STATUS_CANCEL
) {
1948 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
1949 free_nfs_cb_data(data
);
1954 if (res
->status
!= NFS3_OK
) {
1955 rpc_set_error(nfs
->rpc
, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
1956 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1957 free_nfs_cb_data(data
);
1961 data
->cb(0, nfs
, NULL
, data
->private_data
);
1962 free_nfs_cb_data(data
);
1965 struct nfs_chown_data
{
1970 static int nfs_chown_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
1973 struct nfs_chown_data
*chown_data
= data
->continue_data
;
1975 bzero(&args
, sizeof(SETATTR3args
));
1976 args
.object
.data
.data_len
= data
->fh
.data
.data_len
;
1977 args
.object
.data
.data_val
= data
->fh
.data
.data_val
;
1978 if (chown_data
->uid
!= (uid_t
)-1) {
1979 args
.new_attributes
.uid
.set_it
= 1;
1980 args
.new_attributes
.uid
.set_uid3_u
.uid
= chown_data
->uid
;
1982 if (chown_data
->gid
!= (gid_t
)-1) {
1983 args
.new_attributes
.gid
.set_it
= 1;
1984 args
.new_attributes
.gid
.set_gid3_u
.gid
= chown_data
->gid
;
1987 if (rpc_nfs_setattr_async(nfs
->rpc
, nfs_chown_cb
, &args
, data
) != 0) {
1988 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SETATTR call for %s", data
->path
);
1989 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
1990 free_nfs_cb_data(data
);
1997 int nfs_chown_async(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
, nfs_cb cb
, void *private_data
)
1999 struct nfs_chown_data
*chown_data
;
2001 chown_data
= malloc(sizeof(struct nfs_chown_data
));
2002 if (chown_data
== NULL
) {
2003 printf("Failed to allocate memory for chown data structure\n");
2007 chown_data
->uid
= uid
;
2008 chown_data
->gid
= gid
;
2010 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_chown_continue_internal
, chown_data
, free
, 0) != 0) {
2011 printf("Out of memory: failed to start parsing the path components\n");
2022 int nfs_fchown_async(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
, nfs_cb cb
, void *private_data
)
2024 struct nfs_cb_data
*data
;
2025 struct nfs_chown_data
*chown_data
;
2027 chown_data
= malloc(sizeof(struct nfs_chown_data
));
2028 if (chown_data
== NULL
) {
2029 printf("Failed to allocate memory for chown data structure\n");
2033 chown_data
->uid
= uid
;
2034 chown_data
->gid
= gid
;
2037 data
= malloc(sizeof(struct nfs_cb_data
));
2039 rpc_set_error(nfs
->rpc
, "out of memory");
2040 printf("failed to allocate memory for fchown data\n");
2043 bzero(data
, sizeof(struct nfs_cb_data
));
2046 data
->private_data
= private_data
;
2047 data
->continue_data
= chown_data
;
2048 data
->fh
.data
.data_len
= nfsfh
->fh
.data
.data_len
;
2049 data
->fh
.data
.data_val
= malloc(data
->fh
.data
.data_len
);
2050 if (data
->fh
.data
.data_val
== NULL
) {
2051 rpc_set_error(nfs
->rpc
, "Out of memory: Failed to allocate fh");
2052 free_nfs_cb_data(data
);
2055 memcpy(data
->fh
.data
.data_val
, nfsfh
->fh
.data
.data_val
, data
->fh
.data
.data_len
);
2058 if (nfs_chown_continue_internal(nfs
, data
) != 0) {
2059 free_nfs_cb_data(data
);
2073 static void nfs_utimes_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2075 struct nfs_cb_data
*data
= private_data
;
2076 struct nfs_context
*nfs
= data
->nfs
;
2079 if (status
== RPC_STATUS_ERROR
) {
2080 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2081 free_nfs_cb_data(data
);
2084 if (status
== RPC_STATUS_CANCEL
) {
2085 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2086 free_nfs_cb_data(data
);
2091 if (res
->status
!= NFS3_OK
) {
2092 rpc_set_error(nfs
->rpc
, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res
->status
), nfsstat3_to_errno(res
->status
));
2093 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2094 free_nfs_cb_data(data
);
2098 data
->cb(0, nfs
, NULL
, data
->private_data
);
2099 free_nfs_cb_data(data
);
2102 static int nfs_utimes_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2105 struct timeval
*utimes_data
= data
->continue_data
;
2107 bzero(&args
, sizeof(SETATTR3args
));
2108 args
.object
.data
.data_len
= data
->fh
.data
.data_len
;
2109 args
.object
.data
.data_val
= data
->fh
.data
.data_val
;
2110 if (utimes_data
!= NULL
) {
2111 args
.new_attributes
.atime
.set_it
= SET_TO_CLIENT_TIME
;
2112 args
.new_attributes
.atime
.set_atime_u
.atime
.seconds
= utimes_data
[0].tv_sec
;
2113 args
.new_attributes
.atime
.set_atime_u
.atime
.nseconds
= utimes_data
[0].tv_usec
* 1000;
2114 args
.new_attributes
.mtime
.set_it
= SET_TO_CLIENT_TIME
;
2115 args
.new_attributes
.mtime
.set_mtime_u
.mtime
.seconds
= utimes_data
[1].tv_sec
;
2116 args
.new_attributes
.mtime
.set_mtime_u
.mtime
.nseconds
= utimes_data
[1].tv_usec
* 1000;
2118 args
.new_attributes
.atime
.set_it
= SET_TO_SERVER_TIME
;
2119 args
.new_attributes
.mtime
.set_it
= SET_TO_SERVER_TIME
;
2122 if (rpc_nfs_setattr_async(nfs
->rpc
, nfs_utimes_cb
, &args
, data
) != 0) {
2123 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SETATTR call for %s", data
->path
);
2124 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2125 free_nfs_cb_data(data
);
2132 int nfs_utimes_async(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
, nfs_cb cb
, void *private_data
)
2134 struct timeval
*new_times
= NULL
;
2136 if (times
!= NULL
) {
2137 new_times
= malloc(sizeof(struct timeval
)*2);
2138 if (new_times
== NULL
) {
2139 printf("Failed to allocate memory for timeval structure\n");
2143 memcpy(new_times
, times
, sizeof(struct timeval
)*2);
2146 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_utimes_continue_internal
, new_times
, free
, 0) != 0) {
2147 printf("Out of memory: failed to start parsing the path components\n");
2157 int nfs_utime_async(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
, nfs_cb cb
, void *private_data
)
2159 struct timeval
*new_times
= NULL
;
2161 if (times
!= NULL
) {
2162 new_times
= malloc(sizeof(struct timeval
)*2);
2163 if (new_times
== NULL
) {
2164 printf("Failed to allocate memory for timeval structure\n");
2168 new_times
[0].tv_sec
= times
->actime
;
2169 new_times
[0].tv_usec
= 0;
2170 new_times
[1].tv_sec
= times
->modtime
;
2171 new_times
[1].tv_usec
= 0;
2174 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_utimes_continue_internal
, new_times
, free
, 0) != 0) {
2175 printf("Out of memory: failed to start parsing the path components\n");
2189 static void nfs_access_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2192 struct nfs_cb_data
*data
= private_data
;
2193 struct nfs_context
*nfs
= data
->nfs
;
2194 unsigned int nfsmode
= 0;
2196 if (status
== RPC_STATUS_ERROR
) {
2197 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2198 free_nfs_cb_data(data
);
2201 if (status
== RPC_STATUS_CANCEL
) {
2202 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2203 free_nfs_cb_data(data
);
2208 if (res
->status
!= NFS3_OK
) {
2209 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
));
2210 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2211 free_nfs_cb_data(data
);
2215 if (data
->continue_int
& R_OK
) {
2216 nfsmode
|= ACCESS3_READ
;
2218 if (data
->continue_int
& W_OK
) {
2219 nfsmode
|= ACCESS3_MODIFY
;
2221 if (data
->continue_int
& X_OK
) {
2222 nfsmode
|= ACCESS3_EXECUTE
;
2225 if (res
->ACCESS3res_u
.resok
.access
!= nfsmode
) {
2226 rpc_set_error(nfs
->rpc
, "NFS: ACCESS denied. Required access %c%c%c. Allowed access %c%c%c",
2227 nfsmode
&ACCESS3_READ
?'r':'-',
2228 nfsmode
&ACCESS3_MODIFY
?'w':'-',
2229 nfsmode
&ACCESS3_EXECUTE
?'x':'-',
2230 res
->ACCESS3res_u
.resok
.access
&ACCESS3_READ
?'r':'-',
2231 res
->ACCESS3res_u
.resok
.access
&ACCESS3_MODIFY
?'w':'-',
2232 res
->ACCESS3res_u
.resok
.access
&ACCESS3_EXECUTE
?'x':'-');
2233 data
->cb(-EACCES
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2234 free_nfs_cb_data(data
);
2238 data
->cb(0, nfs
, NULL
, data
->private_data
);
2239 free_nfs_cb_data(data
);
2242 static int nfs_access_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2246 if (data
->continue_int
& R_OK
) {
2247 nfsmode
|= ACCESS3_READ
;
2249 if (data
->continue_int
& W_OK
) {
2250 nfsmode
|= ACCESS3_MODIFY
;
2252 if (data
->continue_int
& X_OK
) {
2253 nfsmode
|= ACCESS3_EXECUTE
;
2256 if (rpc_nfs_access_async(nfs
->rpc
, nfs_access_cb
, &data
->fh
, nfsmode
, data
) != 0) {
2257 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send OPEN ACCESS call for %s", data
->path
);
2258 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2259 free_nfs_cb_data(data
);
2265 int nfs_access_async(struct nfs_context
*nfs
, const char *path
, int mode
, nfs_cb cb
, void *private_data
)
2267 if (nfs_lookuppath_async(nfs
, path
, cb
, private_data
, nfs_access_continue_internal
, NULL
, NULL
, mode
) != 0) {
2268 printf("Out of memory: failed to start parsing the path components\n");
2280 struct nfs_symlink_data
{
2282 char *newpathparent
;
2283 char *newpathobject
;
2286 static void free_nfs_symlink_data(void *mem
)
2288 struct nfs_symlink_data
*data
= mem
;
2290 if (data
->oldpath
!= NULL
) {
2291 free(data
->oldpath
);
2293 if (data
->newpathparent
!= NULL
) {
2294 free(data
->newpathparent
);
2296 if (data
->newpathobject
!= NULL
) {
2297 free(data
->newpathobject
);
2302 static void nfs_symlink_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2305 struct nfs_cb_data
*data
= private_data
;
2306 struct nfs_context
*nfs
= data
->nfs
;
2307 struct nfs_symlink_data
*symlink_data
= data
->continue_data
;
2309 if (status
== RPC_STATUS_ERROR
) {
2310 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2311 free_nfs_cb_data(data
);
2314 if (status
== RPC_STATUS_CANCEL
) {
2315 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2316 free_nfs_cb_data(data
);
2321 if (res
->status
!= NFS3_OK
) {
2322 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
));
2323 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2324 free_nfs_cb_data(data
);
2328 data
->cb(0, nfs
, NULL
, data
->private_data
);
2329 free_nfs_cb_data(data
);
2332 static int nfs_symlink_continue_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2334 struct nfs_symlink_data
*symlink_data
= data
->continue_data
;
2336 if (rpc_nfs_symlink_async(nfs
->rpc
, nfs_symlink_cb
, &data
->fh
, symlink_data
->newpathobject
, symlink_data
->oldpath
, data
) != 0) {
2337 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send SYMLINK call for %s", data
->path
);
2338 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2339 free_nfs_cb_data(data
);
2345 int nfs_symlink_async(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
, nfs_cb cb
, void *private_data
)
2348 struct nfs_symlink_data
*symlink_data
;
2350 symlink_data
= malloc(sizeof(struct nfs_symlink_data
));
2351 if (symlink_data
== NULL
) {
2352 printf("Out of memory, failed to allocate buffer for symlink data\n");
2355 bzero(symlink_data
, sizeof(struct nfs_symlink_data
));
2357 symlink_data
->oldpath
= strdup(oldpath
);
2358 if (symlink_data
->oldpath
== NULL
) {
2359 printf("Out of memory, failed to allocate buffer for oldpath\n");
2360 free_nfs_symlink_data(symlink_data
);
2364 symlink_data
->newpathparent
= strdup(newpath
);
2365 if (symlink_data
->newpathparent
== NULL
) {
2366 printf("Out of memory, failed to allocate mode buffer for new path\n");
2367 free_nfs_symlink_data(symlink_data
);
2371 ptr
= rindex(symlink_data
->newpathparent
, '/');
2373 printf("Invalid path %s\n", oldpath
);
2374 free_nfs_symlink_data(symlink_data
);
2380 symlink_data
->newpathobject
= strdup(ptr
);
2381 if (symlink_data
->newpathobject
== NULL
) {
2382 printf("Out of memory, failed to allocate mode buffer for new path\n");
2383 free_nfs_symlink_data(symlink_data
);
2387 if (nfs_lookuppath_async(nfs
, symlink_data
->newpathparent
, cb
, private_data
, nfs_symlink_continue_internal
, symlink_data
, free_nfs_symlink_data
, 0) != 0) {
2388 printf("Out of memory: failed to start parsing the path components\n");
2400 struct nfs_rename_data
{
2403 struct nfs_fh3 olddir
;
2406 struct nfs_fh3 newdir
;
2409 static void free_nfs_rename_data(void *mem
)
2411 struct nfs_rename_data
*data
= mem
;
2413 if (data
->oldpath
!= NULL
) {
2414 free(data
->oldpath
);
2416 if (data
->olddir
.data
.data_val
!= NULL
) {
2417 free(data
->olddir
.data
.data_val
);
2419 if (data
->newpath
!= NULL
) {
2420 free(data
->newpath
);
2422 if (data
->newdir
.data
.data_val
!= NULL
) {
2423 free(data
->newdir
.data
.data_val
);
2428 static void nfs_rename_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2431 struct nfs_cb_data
*data
= private_data
;
2432 struct nfs_context
*nfs
= data
->nfs
;
2433 struct nfs_rename_data
*rename_data
= data
->continue_data
;
2435 if (status
== RPC_STATUS_ERROR
) {
2436 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2437 free_nfs_cb_data(data
);
2440 if (status
== RPC_STATUS_CANCEL
) {
2441 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2442 free_nfs_cb_data(data
);
2447 if (res
->status
!= NFS3_OK
) {
2448 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
));
2449 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2450 free_nfs_cb_data(data
);
2454 data
->cb(0, nfs
, NULL
, data
->private_data
);
2455 free_nfs_cb_data(data
);
2458 static int nfs_rename_continue_2_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2460 struct nfs_rename_data
*rename_data
= data
->continue_data
;
2462 /* steal the filehandle */
2463 rename_data
->newdir
.data
.data_len
= data
->fh
.data
.data_len
;
2464 rename_data
->newdir
.data
.data_val
= data
->fh
.data
.data_val
;
2465 data
->fh
.data
.data_val
= NULL
;
2467 if (rpc_nfs_rename_async(nfs
->rpc
, nfs_rename_cb
, &rename_data
->olddir
, rename_data
->oldobject
, &rename_data
->newdir
, rename_data
->newobject
, data
) != 0) {
2468 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send RENAME call for %s", data
->path
);
2469 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2470 free_nfs_cb_data(data
);
2477 static int nfs_rename_continue_1_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2479 struct nfs_rename_data
*rename_data
= data
->continue_data
;
2481 /* steal the filehandle */
2482 rename_data
->olddir
.data
.data_len
= data
->fh
.data
.data_len
;
2483 rename_data
->olddir
.data
.data_val
= data
->fh
.data
.data_val
;
2484 data
->fh
.data
.data_val
= NULL
;
2486 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) {
2487 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send LOOKUP call for %s", rename_data
->newpath
);
2488 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2489 free_nfs_cb_data(data
);
2492 data
->continue_data
= NULL
;
2493 free_nfs_cb_data(data
);
2499 int nfs_rename_async(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
, nfs_cb cb
, void *private_data
)
2502 struct nfs_rename_data
*rename_data
;
2504 rename_data
= malloc(sizeof(struct nfs_rename_data
));
2505 if (rename_data
== NULL
) {
2506 printf("Out of memory, failed to allocate buffer for rename data\n");
2509 bzero(rename_data
, sizeof(struct nfs_rename_data
));
2511 rename_data
->oldpath
= strdup(oldpath
);
2512 if (rename_data
->oldpath
== NULL
) {
2513 printf("Out of memory, failed to allocate buffer for oldpath\n");
2514 free_nfs_rename_data(rename_data
);
2517 ptr
= rindex(rename_data
->oldpath
, '/');
2519 printf("Invalid path %s\n", oldpath
);
2520 free_nfs_rename_data(rename_data
);
2525 rename_data
->oldobject
= ptr
;
2528 rename_data
->newpath
= strdup(newpath
);
2529 if (rename_data
->newpath
== NULL
) {
2530 printf("Out of memory, failed to allocate buffer for newpath\n");
2531 free_nfs_rename_data(rename_data
);
2534 ptr
= rindex(rename_data
->newpath
, '/');
2536 printf("Invalid path %s\n", newpath
);
2537 free_nfs_rename_data(rename_data
);
2542 rename_data
->newobject
= ptr
;
2545 if (nfs_lookuppath_async(nfs
, rename_data
->oldpath
, cb
, private_data
, nfs_rename_continue_1_internal
, rename_data
, free_nfs_rename_data
, 0) != 0) {
2546 printf("Out of memory: failed to start parsing the path components\n");
2557 struct nfs_link_data
{
2559 struct nfs_fh3 oldfh
;
2562 struct nfs_fh3 newdir
;
2565 static void free_nfs_link_data(void *mem
)
2567 struct nfs_link_data
*data
= mem
;
2569 if (data
->oldpath
!= NULL
) {
2570 free(data
->oldpath
);
2572 if (data
->oldfh
.data
.data_val
!= NULL
) {
2573 free(data
->oldfh
.data
.data_val
);
2575 if (data
->newpath
!= NULL
) {
2576 free(data
->newpath
);
2578 if (data
->newdir
.data
.data_val
!= NULL
) {
2579 free(data
->newdir
.data
.data_val
);
2584 static void nfs_link_cb(struct rpc_context
*rpc _U_
, int status
, void *command_data
, void *private_data
)
2587 struct nfs_cb_data
*data
= private_data
;
2588 struct nfs_context
*nfs
= data
->nfs
;
2589 struct nfs_link_data
*link_data
= data
->continue_data
;
2591 if (status
== RPC_STATUS_ERROR
) {
2592 data
->cb(-EFAULT
, nfs
, command_data
, data
->private_data
);
2593 free_nfs_cb_data(data
);
2596 if (status
== RPC_STATUS_CANCEL
) {
2597 data
->cb(-EINTR
, nfs
, "Command was cancelled", data
->private_data
);
2598 free_nfs_cb_data(data
);
2603 if (res
->status
!= NFS3_OK
) {
2604 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
));
2605 data
->cb(nfsstat3_to_errno(res
->status
), nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2606 free_nfs_cb_data(data
);
2610 data
->cb(0, nfs
, NULL
, data
->private_data
);
2611 free_nfs_cb_data(data
);
2614 static int nfs_link_continue_2_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2616 struct nfs_link_data
*link_data
= data
->continue_data
;
2618 /* steal the filehandle */
2619 link_data
->newdir
.data
.data_len
= data
->fh
.data
.data_len
;
2620 link_data
->newdir
.data
.data_val
= data
->fh
.data
.data_val
;
2621 data
->fh
.data
.data_val
= NULL
;
2623 if (rpc_nfs_link_async(nfs
->rpc
, nfs_link_cb
, &link_data
->oldfh
, &link_data
->newdir
, link_data
->newobject
, data
) != 0) {
2624 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send LINK call for %s", data
->path
);
2625 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2626 free_nfs_cb_data(data
);
2633 static int nfs_link_continue_1_internal(struct nfs_context
*nfs
, struct nfs_cb_data
*data
)
2635 struct nfs_link_data
*link_data
= data
->continue_data
;
2637 /* steal the filehandle */
2638 link_data
->oldfh
.data
.data_len
= data
->fh
.data
.data_len
;
2639 link_data
->oldfh
.data
.data_val
= data
->fh
.data
.data_val
;
2640 data
->fh
.data
.data_val
= NULL
;
2642 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) {
2643 rpc_set_error(nfs
->rpc
, "RPC error: Failed to send LOOKUP call for %s", link_data
->newpath
);
2644 data
->cb(-ENOMEM
, nfs
, rpc_get_error(nfs
->rpc
), data
->private_data
);
2645 free_nfs_cb_data(data
);
2648 data
->continue_data
= NULL
;
2649 free_nfs_cb_data(data
);
2655 int nfs_link_async(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
, nfs_cb cb
, void *private_data
)
2658 struct nfs_link_data
*link_data
;
2660 link_data
= malloc(sizeof(struct nfs_link_data
));
2661 if (link_data
== NULL
) {
2662 printf("Out of memory, failed to allocate buffer for link data\n");
2665 bzero(link_data
, sizeof(struct nfs_link_data
));
2667 link_data
->oldpath
= strdup(oldpath
);
2668 if (link_data
->oldpath
== NULL
) {
2669 printf("Out of memory, failed to allocate buffer for oldpath\n");
2670 free_nfs_link_data(link_data
);
2674 link_data
->newpath
= strdup(newpath
);
2675 if (link_data
->newpath
== NULL
) {
2676 printf("Out of memory, failed to allocate buffer for newpath\n");
2677 free_nfs_link_data(link_data
);
2680 ptr
= rindex(link_data
->newpath
, '/');
2682 printf("Invalid path %s\n", newpath
);
2683 free_nfs_link_data(link_data
);
2688 link_data
->newobject
= ptr
;
2691 if (nfs_lookuppath_async(nfs
, link_data
->oldpath
, cb
, private_data
, nfs_link_continue_1_internal
, link_data
, free_nfs_link_data
, 0) != 0) {
2692 printf("Out of memory: failed to start parsing the path components\n");
2700 //qqq replace later with lseek()
2701 off_t
nfs_get_current_offset(struct nfsfh
*nfsfh
)
2703 return nfsfh
->offset
;