Redo the buffer handling for input buffers and make sure we only read one PDU at...
[deb_libnfs.git] / lib / libnfs.c
CommitLineData
84004dbf
RS
1/*
2 Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>.
16*/
17/*
18 * High level api to nfs filesystems
19 */
20
7f0242ca 21#define _GNU_SOURCE
84004dbf 22#include <stdio.h>
1896d37b 23#include <stdarg.h>
84004dbf
RS
24#include <stdlib.h>
25#include <string.h>
26#include <strings.h>
27#include <errno.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <sys/statvfs.h>
31#include <utime.h>
32#include <unistd.h>
33#include <fcntl.h>
34#include "libnfs.h"
35#include "libnfs-raw.h"
36#include "libnfs-raw-mount.h"
37#include "libnfs-raw-nfs.h"
1896d37b
RS
38#include "libnfs-private.h"
39
40struct nfsdir {
41 struct nfsdirent *entries;
42 struct nfsdirent *current;
43};
84004dbf
RS
44
45struct nfsfh {
46 struct nfs_fh3 fh;
47 int is_sync;
48 off_t offset;
49};
50
1896d37b
RS
51struct nfs_context {
52 struct rpc_context *rpc;
53 char *server;
54 char *export;
55 struct nfs_fh3 rootfh;
56 size_t readmax;
57 size_t writemax;
84004dbf
RS
58};
59
60void nfs_free_nfsdir(struct nfsdir *nfsdir)
61{
62 while (nfsdir->entries) {
63 struct nfsdirent *dirent = nfsdir->entries->next;
64 if (nfsdir->entries->name != NULL) {
65 free(nfsdir->entries->name);
66 }
67 free(nfsdir->entries);
68 nfsdir->entries = dirent;
69 }
70 free(nfsdir);
71}
72
84004dbf
RS
73struct nfs_cb_data;
74typedef int (*continue_func)(struct nfs_context *nfs, struct nfs_cb_data *data);
75
76struct nfs_cb_data {
77 struct nfs_context *nfs;
78 struct nfsfh *nfsfh;
79 char *saved_path, *path;
80
81 nfs_cb cb;
82 void *private_data;
83
84 continue_func continue_cb;
85 void *continue_data;
86 void (*free_continue_data)(void *);
87 int continue_int;
88
89 struct nfs_fh3 fh;
921f877b
RS
90
91 /* for multi-read/write calls. */
92 int error;
93 int cancel;
94 int num_calls;
95 off_t start_offset, max_offset;
96 char *buffer;
97};
98
99struct nfs_mcb_data {
100 struct nfs_cb_data *data;
101 off_t offset;
102 size_t count;
84004dbf
RS
103};
104
105static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh);
106
107
108void nfs_set_auth(struct nfs_context *nfs, struct AUTH *auth)
109{
110 return rpc_set_auth(nfs->rpc, auth);
111}
112
113int nfs_get_fd(struct nfs_context *nfs)
114{
115 return rpc_get_fd(nfs->rpc);
116}
117
118int nfs_which_events(struct nfs_context *nfs)
119{
120 return rpc_which_events(nfs->rpc);
121}
122
123int nfs_service(struct nfs_context *nfs, int revents)
124{
125 return rpc_service(nfs->rpc, revents);
126}
127
128char *nfs_get_error(struct nfs_context *nfs)
129{
130 return rpc_get_error(nfs->rpc);
131};
132
133struct nfs_context *nfs_init_context(void)
134{
135 struct nfs_context *nfs;
136
137 nfs = malloc(sizeof(struct nfs_context));
138 if (nfs == NULL) {
84004dbf
RS
139 return NULL;
140 }
141 nfs->rpc = rpc_init_context();
142 if (nfs->rpc == NULL) {
84004dbf
RS
143 free(nfs);
144 return NULL;
145 }
146
147 return nfs;
148}
149
150void nfs_destroy_context(struct nfs_context *nfs)
151{
152 rpc_destroy_context(nfs->rpc);
153 nfs->rpc = NULL;
154
155 if (nfs->server) {
156 free(nfs->server);
157 nfs->server = NULL;
158 }
159
160 if (nfs->export) {
161 free(nfs->export);
162 nfs->export = NULL;
163 }
164
165 if (nfs->rootfh.data.data_val != NULL) {
166 free(nfs->rootfh.data.data_val);
167 nfs->rootfh.data.data_val = NULL;
168 }
169
170 free(nfs);
171}
172
173void free_nfs_cb_data(struct nfs_cb_data *data)
174{
175 if (data->saved_path != NULL) {
176 free(data->saved_path);
177 data->saved_path = NULL;
178 }
179
180 if (data->continue_data != NULL) {
181 data->free_continue_data(data->continue_data);
182 data->continue_data = NULL;
183 }
184
185 if (data->fh.data.data_val != NULL) {
186 free(data->fh.data.data_val);
187 data->fh.data.data_val = NULL;
188 }
189
921f877b
RS
190 if (data->buffer != NULL) {
191 free(data->buffer);
192 data->buffer = NULL;
193 }
194
84004dbf
RS
195 free(data);
196}
197
198
199
200
201
17ef62fa 202static void nfs_mount_10_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
84004dbf
RS
203{
204 struct nfs_cb_data *data = private_data;
205 struct nfs_context *nfs = data->nfs;
206
207 if (status == RPC_STATUS_ERROR) {
208 data->cb(-EFAULT, nfs, command_data, data->private_data);
209 free_nfs_cb_data(data);
210 return;
211 }
212 if (status == RPC_STATUS_CANCEL) {
213 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
214 free_nfs_cb_data(data);
215 return;
216 }
217
218 data->cb(0, nfs, NULL, data->private_data);
219 free_nfs_cb_data(data);
220}
221
17ef62fa 222static void nfs_mount_9_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
84004dbf
RS
223{
224 struct nfs_cb_data *data = private_data;
225 struct nfs_context *nfs = data->nfs;
17ef62fa 226 FSINFO3res *res = command_data;
84004dbf
RS
227
228 if (status == RPC_STATUS_ERROR) {
229 data->cb(-EFAULT, nfs, command_data, data->private_data);
230 free_nfs_cb_data(data);
231 return;
232 }
233 if (status == RPC_STATUS_CANCEL) {
234 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
235 free_nfs_cb_data(data);
236 return;
237 }
238
17ef62fa
RS
239 nfs->readmax = res->FSINFO3res_u.resok.rtmax;
240 nfs->writemax = res->FSINFO3res_u.resok.wtmax;
84004dbf 241
17ef62fa 242 if (rpc_nfs_getattr_async(rpc, nfs_mount_10_cb, &nfs->rootfh, data) != 0) {
84004dbf
RS
243 data->cb(-ENOMEM, nfs, command_data, data->private_data);
244 free_nfs_cb_data(data);
245 return;
246 }
247}
248
17ef62fa
RS
249static void nfs_mount_8_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
250{
251 struct nfs_cb_data *data = private_data;
252 struct nfs_context *nfs = data->nfs;
253
254 if (status == RPC_STATUS_ERROR) {
255 data->cb(-EFAULT, nfs, command_data, data->private_data);
256 free_nfs_cb_data(data);
257 return;
258 }
259 if (status == RPC_STATUS_CANCEL) {
260 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
261 free_nfs_cb_data(data);
262 return;
263 }
264
265 if (rpc_nfs_fsinfo_async(rpc, nfs_mount_9_cb, &nfs->rootfh, data) != 0) {
266 data->cb(-ENOMEM, nfs, command_data, data->private_data);
267 free_nfs_cb_data(data);
268 return;
269 }
270}
271
272
84004dbf
RS
273static void nfs_mount_7_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
274{
275 struct nfs_cb_data *data = private_data;
276 struct nfs_context *nfs = data->nfs;
277
278 if (status == RPC_STATUS_ERROR) {
279 data->cb(-EFAULT, nfs, command_data, data->private_data);
280 free_nfs_cb_data(data);
281 return;
282 }
283 if (status == RPC_STATUS_CANCEL) {
284 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
285 free_nfs_cb_data(data);
286 return;
287 }
288
289 if (rpc_nfs_null_async(rpc, nfs_mount_8_cb, data) != 0) {
290 data->cb(-ENOMEM, nfs, command_data, data->private_data);
291 free_nfs_cb_data(data);
292 return;
293 }
294}
295
296
297static void nfs_mount_6_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
298{
299 struct nfs_cb_data *data = private_data;
300 struct nfs_context *nfs = data->nfs;
301 mountres3 *res;
302
303 if (status == RPC_STATUS_ERROR) {
304 data->cb(-EFAULT, nfs, command_data, data->private_data);
305 free_nfs_cb_data(data);
306 return;
307 }
308 if (status == RPC_STATUS_CANCEL) {
309 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
310 free_nfs_cb_data(data);
311 return;
312 }
313
314 res = command_data;
315 if (res->fhs_status != MNT3_OK) {
316 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));
317 data->cb(mountstat3_to_errno(res->fhs_status), nfs, rpc_get_error(rpc), data->private_data);
318 free_nfs_cb_data(data);
319 return;
320 }
321
322 nfs->rootfh.data.data_len = res->mountres3_u.mountinfo.fhandle.fhandle3_len;
323 nfs->rootfh.data.data_val = malloc(nfs->rootfh.data.data_len);
324 if (nfs->rootfh.data.data_val == NULL) {
325 rpc_set_error(rpc, "Out of memory. Could not allocate memory to store root filehandle");
326 data->cb(-ENOMEM, nfs, rpc_get_error(rpc), data->private_data);
327 free_nfs_cb_data(data);
328 return;
329 }
330 memcpy(nfs->rootfh.data.data_val, res->mountres3_u.mountinfo.fhandle.fhandle3_val, nfs->rootfh.data.data_len);
331
332 rpc_disconnect(rpc, "normal disconnect");
333 if (rpc_connect_async(rpc, nfs->server, 2049, nfs_mount_7_cb, data) != 0) {
334 data->cb(-ENOMEM, nfs, command_data, data->private_data);
335 free_nfs_cb_data(data);
336 return;
337 }
338}
339
340
341static void nfs_mount_5_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
342{
343 struct nfs_cb_data *data = private_data;
344 struct nfs_context *nfs = data->nfs;
345
346 if (status == RPC_STATUS_ERROR) {
347 data->cb(-EFAULT, nfs, command_data, data->private_data);
348 free_nfs_cb_data(data);
349 return;
350 }
351 if (status == RPC_STATUS_CANCEL) {
352 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
353 free_nfs_cb_data(data);
354 return;
355 }
356
357 if (rpc_mount_mnt_async(rpc, nfs_mount_6_cb, nfs->export, data) != 0) {
358 data->cb(-ENOMEM, nfs, command_data, data->private_data);
359 free_nfs_cb_data(data);
360 return;
361 }
362}
363
364static void nfs_mount_4_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
365{
366 struct nfs_cb_data *data = private_data;
367 struct nfs_context *nfs = data->nfs;
368
369 if (status == RPC_STATUS_ERROR) {
370 data->cb(-EFAULT, nfs, command_data, data->private_data);
371 free_nfs_cb_data(data);
372 return;
373 }
374 if (status == RPC_STATUS_CANCEL) {
375 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
376 free_nfs_cb_data(data);
377 return;
378 }
379
380 if (rpc_mount_null_async(rpc, nfs_mount_5_cb, data) != 0) {
381 data->cb(-ENOMEM, nfs, command_data, data->private_data);
382 free_nfs_cb_data(data);
383 return;
384 }
385}
386
387static void nfs_mount_3_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
388{
389 struct nfs_cb_data *data = private_data;
390 struct nfs_context *nfs = data->nfs;
391 uint32_t mount_port;
392
393 if (status == RPC_STATUS_ERROR) {
394 data->cb(-EFAULT, nfs, command_data, data->private_data);
395 free_nfs_cb_data(data);
396 return;
397 }
398 if (status == RPC_STATUS_CANCEL) {
399 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
400 free_nfs_cb_data(data);
401 return;
402 }
403
404 mount_port = *(uint32_t *)command_data;
405 if (mount_port == 0) {
406 rpc_set_error(rpc, "RPC error. Mount program is not available on %s", nfs->server);
407 data->cb(-ENOENT, nfs, command_data, data->private_data);
408 free_nfs_cb_data(data);
409 return;
410 }
411
412 rpc_disconnect(rpc, "normal disconnect");
413 if (rpc_connect_async(rpc, nfs->server, mount_port, nfs_mount_4_cb, data) != 0) {
414 data->cb(-ENOMEM, nfs, command_data, data->private_data);
415 free_nfs_cb_data(data);
416 return;
417 }
418}
419
420
421static void nfs_mount_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
422{
423 struct nfs_cb_data *data = private_data;
424 struct nfs_context *nfs = data->nfs;
425
426 if (status == RPC_STATUS_ERROR) {
427 data->cb(-EFAULT, nfs, command_data, data->private_data);
428 free_nfs_cb_data(data);
429 return;
430 }
431 if (status == RPC_STATUS_CANCEL) {
432 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
433 free_nfs_cb_data(data);
434 return;
435 }
436
437 if (rpc_pmap_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, nfs_mount_3_cb, private_data) != 0) {
438 data->cb(-ENOMEM, nfs, command_data, data->private_data);
439 free_nfs_cb_data(data);
440 return;
441 }
442}
443
444static void nfs_mount_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
445{
446 struct nfs_cb_data *data = private_data;
447 struct nfs_context *nfs = data->nfs;
448
449 if (status == RPC_STATUS_ERROR) {
450 data->cb(-EFAULT, nfs, command_data, data->private_data);
451 free_nfs_cb_data(data);
452 return;
453 }
454 if (status == RPC_STATUS_CANCEL) {
455 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
456 free_nfs_cb_data(data);
457 return;
458 }
459
460 if (rpc_pmap_null_async(rpc, nfs_mount_2_cb, data) != 0) {
461 data->cb(-ENOMEM, nfs, command_data, data->private_data);
462 free_nfs_cb_data(data);
463 return;
464 }
465}
466
467/*
468 * Async call for mounting an nfs share and geting the root filehandle
469 */
470int nfs_mount_async(struct nfs_context *nfs, const char *server, const char *export, nfs_cb cb, void *private_data)
471{
472 struct nfs_cb_data *data;
473
474 data = malloc(sizeof(struct nfs_cb_data));
475 if (data == NULL) {
cbbf9d3e 476 rpc_set_error(nfs->rpc, "out of memory. failed to allocate memory for nfs mount data");
84004dbf
RS
477 return -1;
478 }
479 bzero(data, sizeof(struct nfs_cb_data));
480 nfs->server = strdup(server);
481 nfs->export = strdup(export);
482 data->nfs = nfs;
483 data->cb = cb;
484 data->private_data = private_data;
485
486 if (rpc_connect_async(nfs->rpc, server, 111, nfs_mount_1_cb, data) != 0) {
cbbf9d3e 487 rpc_set_error(nfs->rpc, "Failed to start connection");
84004dbf 488 free_nfs_cb_data(data);
cbbf9d3e 489 return -1;
84004dbf
RS
490 }
491
492 return 0;
493}
494
495
496
497/*
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.
500 */
501static void nfs_lookup_path_1_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
502{
503 struct nfs_cb_data *data = private_data;
504 struct nfs_context *nfs = data->nfs;
505 LOOKUP3res *res;
506
507 if (status == RPC_STATUS_ERROR) {
508 data->cb(-EFAULT, nfs, command_data, data->private_data);
509 free_nfs_cb_data(data);
510 return;
511 }
512 if (status == RPC_STATUS_CANCEL) {
513 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
514 free_nfs_cb_data(data);
515 return;
516 }
517
518 res = command_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);
523 return;
524 }
525
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);
530 return;
531 }
532}
533
534static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh)
535{
536 char *path, *str;
537
538 while (*data->path == '/') {
539 data->path++;
540 }
541
542 path = data->path;
543 str = index(path, '/');
544 if (str != NULL) {
545 *str = 0;
546 data->path = str+1;
547 } else {
548 while (*data->path != 0) {
549 data->path++;
550 }
551 }
552
553 if (*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);
560 return -1;
561 }
562 memcpy(data->fh.data.data_val, fh->data.data_val, data->fh.data.data_len);
563 data->continue_cb(nfs, data);
564 return 0;
565 }
566
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);
571 return -1;
572 }
573 return 0;
574}
575
576static 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)
577{
578 struct nfs_cb_data *data;
579
580 if (path[0] != '/') {
581 rpc_set_error(nfs->rpc, "Pathname is not absulute %s", path);
582 return -1;
583 }
584
585 data = malloc(sizeof(struct nfs_cb_data));
586 if (data == NULL) {
587 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
cbbf9d3e 588 return -1;
84004dbf
RS
589 }
590 bzero(data, sizeof(struct nfs_cb_data));
591 data->nfs = nfs;
592 data->cb = cb;
593 data->continue_cb = continue_cb;
594 data->continue_data = continue_data;
595 data->free_continue_data = free_continue_data;
596 data->continue_int = continue_int;
597 data->private_data = private_data;
598 data->saved_path = strdup(path);
599 if (data->saved_path == NULL) {
600 rpc_set_error(nfs->rpc, "out of memory: failed to copy path string");
84004dbf 601 free_nfs_cb_data(data);
cbbf9d3e 602 return -1;
84004dbf
RS
603 }
604 data->path = data->saved_path;
605
606 if (nfs_lookup_path_async_internal(nfs, data, &nfs->rootfh) != 0) {
84004dbf
RS
607 /* return 0 here since the callback will be invoked if there is a failure */
608 return 0;
609 }
610 return 0;
611}
612
613
614
615
616
617/*
618 * Async stat()
619 */
620static void nfs_stat_1_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
621{
622 GETATTR3res *res;
623 struct nfs_cb_data *data = private_data;
624 struct nfs_context *nfs = data->nfs;
625 struct stat st;
626
627 if (status == RPC_STATUS_ERROR) {
628 data->cb(-EFAULT, nfs, command_data, data->private_data);
629 free_nfs_cb_data(data);
630 return;
631 }
632 if (status == RPC_STATUS_CANCEL) {
633 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
634 free_nfs_cb_data(data);
635 return;
636 }
637
638 res = command_data;
639 if (res->status != NFS3_OK) {
640 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));
641 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
642 free_nfs_cb_data(data);
643 return;
644 }
645
646 st.st_dev = -1;
647 st.st_ino = res->GETATTR3res_u.resok.obj_attributes.fileid;
648 st.st_mode = res->GETATTR3res_u.resok.obj_attributes.mode;
649 st.st_nlink = res->GETATTR3res_u.resok.obj_attributes.nlink;
650 st.st_uid = res->GETATTR3res_u.resok.obj_attributes.uid;
651 st.st_gid = res->GETATTR3res_u.resok.obj_attributes.gid;
652 st.st_rdev = 0;
653 st.st_size = res->GETATTR3res_u.resok.obj_attributes.size;
654 st.st_blksize = 4096;
655 st.st_blocks = res->GETATTR3res_u.resok.obj_attributes.size / 4096;
656 st.st_atime = res->GETATTR3res_u.resok.obj_attributes.atime.seconds;
657 st.st_mtime = res->GETATTR3res_u.resok.obj_attributes.mtime.seconds;
658 st.st_ctime = res->GETATTR3res_u.resok.obj_attributes.ctime.seconds;
659
660 data->cb(0, nfs, &st, data->private_data);
661 free_nfs_cb_data(data);
662}
663
664static int nfs_stat_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
665{
666 if (rpc_nfs_getattr_async(nfs->rpc, nfs_stat_1_cb, &data->fh, data) != 0) {
667 rpc_set_error(nfs->rpc, "RPC error: Failed to send STAT GETATTR call for %s", data->path);
668 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
669 free_nfs_cb_data(data);
670 return -1;
671 }
672 return 0;
673}
674
675int nfs_stat_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
676{
677 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_stat_continue_internal, NULL, NULL, 0) != 0) {
cbbf9d3e 678 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
84004dbf
RS
679 return -1;
680 }
681
682 return 0;
683}
684
685
686
687
688
689/*
690 * Async open()
691 */
692static void nfs_open_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
693{
694 ACCESS3res *res;
695 struct nfs_cb_data *data = private_data;
696 struct nfs_context *nfs = data->nfs;
697 struct nfsfh *nfsfh;
698 unsigned int nfsmode = 0;
699
700 if (status == RPC_STATUS_ERROR) {
701 data->cb(-EFAULT, nfs, command_data, data->private_data);
702 free_nfs_cb_data(data);
703 return;
704 }
705 if (status == RPC_STATUS_CANCEL) {
706 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
707 free_nfs_cb_data(data);
708 return;
709 }
710
711 res = command_data;
712 if (res->status != NFS3_OK) {
713 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));
714 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
715 free_nfs_cb_data(data);
716 return;
717 }
718
719 if (data->continue_int & O_WRONLY) {
720 nfsmode |= ACCESS3_MODIFY;
721 }
722 if (data->continue_int & O_RDWR) {
723 nfsmode |= ACCESS3_READ|ACCESS3_MODIFY;
724 }
725 if (!(data->continue_int & (O_WRONLY|O_RDWR))) {
726 nfsmode |= ACCESS3_READ;
727 }
728
729
730 if (res->ACCESS3res_u.resok.access != nfsmode) {
731 rpc_set_error(nfs->rpc, "NFS: ACCESS denied. Required access %c%c%c. Allowed access %c%c%c",
732 nfsmode&ACCESS3_READ?'r':'-',
733 nfsmode&ACCESS3_MODIFY?'w':'-',
734 nfsmode&ACCESS3_EXECUTE?'x':'-',
735 res->ACCESS3res_u.resok.access&ACCESS3_READ?'r':'-',
736 res->ACCESS3res_u.resok.access&ACCESS3_MODIFY?'w':'-',
737 res->ACCESS3res_u.resok.access&ACCESS3_EXECUTE?'x':'-');
738 data->cb(-EACCES, nfs, rpc_get_error(nfs->rpc), data->private_data);
739 free_nfs_cb_data(data);
740 return;
741 }
742
743 nfsfh = malloc(sizeof(struct nfsfh));
744 if (nfsfh == NULL) {
745 rpc_set_error(nfs->rpc, "NFS: Failed to allocate nfsfh structure");
746 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
747 free_nfs_cb_data(data);
748 return;
749 }
750 bzero(nfsfh, sizeof(struct nfsfh));
751
752 if (data->continue_int & O_SYNC) {
753 nfsfh->is_sync = 1;
754 }
755
756 /* steal the filehandle */
757 nfsfh->fh.data.data_len = data->fh.data.data_len;
758 nfsfh->fh.data.data_val = data->fh.data.data_val;
759 data->fh.data.data_val = NULL;
760
761 data->cb(0, nfs, nfsfh, data->private_data);
762 free_nfs_cb_data(data);
763}
764
765static int nfs_open_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
766{
767 int nfsmode = 0;
768
769 if (data->continue_int & O_WRONLY) {
770 nfsmode |= ACCESS3_MODIFY;
771 }
772 if (data->continue_int & O_RDWR) {
773 nfsmode |= ACCESS3_READ|ACCESS3_MODIFY;
774 }
775 if (!(data->continue_int & (O_WRONLY|O_RDWR))) {
776 nfsmode |= ACCESS3_READ;
777 }
778
779 if (rpc_nfs_access_async(nfs->rpc, nfs_open_cb, &data->fh, nfsmode, data) != 0) {
780 rpc_set_error(nfs->rpc, "RPC error: Failed to send OPEN ACCESS call for %s", data->path);
781 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
782 free_nfs_cb_data(data);
783 return -1;
784 }
785 return 0;
786}
787
788int nfs_open_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data)
789{
790 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_open_continue_internal, NULL, NULL, mode) != 0) {
cbbf9d3e
RS
791 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
792 return -1;
84004dbf
RS
793 }
794
795 return 0;
796}
797
798
799
800
801
802/*
803 * Async pread()
804 */
805static void nfs_pread_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
806{
807 struct nfs_cb_data *data = private_data;
808 struct nfs_context *nfs = data->nfs;
809 READ3res *res;
810
811 if (status == RPC_STATUS_ERROR) {
812 data->cb(-EFAULT, nfs, command_data, data->private_data);
813 free_nfs_cb_data(data);
814 return;
815 }
816 if (status == RPC_STATUS_CANCEL) {
817 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
818 free_nfs_cb_data(data);
819 return;
820 }
821
822 res = command_data;
823 if (res->status != NFS3_OK) {
824 rpc_set_error(nfs->rpc, "NFS: Read failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
825 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
826 free_nfs_cb_data(data);
827 return;
828 }
829
830 data->nfsfh->offset += res->READ3res_u.resok.count;
831 data->cb(res->READ3res_u.resok.count, nfs, res->READ3res_u.resok.data.data_val, data->private_data);
832 free_nfs_cb_data(data);
833}
834
921f877b
RS
835static void nfs_pread_mcb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
836{
837 struct nfs_mcb_data *mdata = private_data;
838 struct nfs_cb_data *data = mdata->data;
839 struct nfs_context *nfs = data->nfs;
840 READ3res *res;
841
842 data->num_calls--;
843
844 if (status == RPC_STATUS_ERROR) {
845 /* flag the failure but do not invoke callback until we have received all responses */
846 data->error = 1;
847 }
848 if (status == RPC_STATUS_CANCEL) {
849 /* flag the cancellation but do not invoke callback until we have received all responses */
850 data->cancel = 1;
851 }
852
853 /* reassemble the data into the buffer */
854 if (status == RPC_STATUS_SUCCESS) {
855 res = command_data;
856 if (res->status != NFS3_OK) {
857 rpc_set_error(nfs->rpc, "NFS: Read failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
858 data->error = 1;
859 } else {
cdb19ec1 860 memcpy(&data->buffer[mdata->offset - data->start_offset], res->READ3res_u.resok.data.data_val, res->READ3res_u.resok.count);
5f9d02f8 861 if ((unsigned)data->max_offset < mdata->offset + res->READ3res_u.resok.count) {
921f877b
RS
862 data->max_offset = mdata->offset + res->READ3res_u.resok.count;
863 }
864 }
865 }
866
867 if (data->num_calls > 0) {
868 /* still waiting for more replies */
869 free(mdata);
870 return;
871 }
872
921f877b
RS
873 if (data->error != 0) {
874 data->cb(-EFAULT, nfs, command_data, data->private_data);
875 free_nfs_cb_data(data);
876 free(mdata);
877 return;
878 }
879 if (data->cancel != 0) {
880 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
881 free_nfs_cb_data(data);
882 free(mdata);
883 return;
884 }
885
886 data->nfsfh->offset = data->max_offset;
887 data->cb(data->max_offset - data->start_offset, nfs, data->buffer, data->private_data);
888 free_nfs_cb_data(data);
889 free(mdata);
890}
891
84004dbf
RS
892int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, size_t count, nfs_cb cb, void *private_data)
893{
894 struct nfs_cb_data *data;
895
896 data = malloc(sizeof(struct nfs_cb_data));
897 if (data == NULL) {
898 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
84004dbf
RS
899 return -1;
900 }
901 bzero(data, sizeof(struct nfs_cb_data));
902 data->nfs = nfs;
903 data->cb = cb;
904 data->private_data = private_data;
905 data->nfsfh = nfsfh;
906
907 nfsfh->offset = offset;
921f877b
RS
908
909 if (count <= nfs_get_readmax(nfs)) {
910 if (rpc_nfs_read_async(nfs->rpc, nfs_pread_cb, &nfsfh->fh, offset, count, data) != 0) {
911 rpc_set_error(nfs->rpc, "RPC error: Failed to send READ call for %s", data->path);
912 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
913 free_nfs_cb_data(data);
914 return -1;
915 }
916 return 0;
917 }
918
919 /* trying to read more than maximum server read size, we has to chop it up into smaller
920 * reads and collect into a reassembly buffer.
921 * we send all reads in parallell so that performance is still good.
922 */
923 data->start_offset = offset;
924
925 data->buffer = malloc(count);
926 if (data->buffer == NULL) {
927 rpc_set_error(nfs->rpc, "Out-Of-Memory: Failed to allocate reassembly buffer for %d bytes", (int)count);
84004dbf
RS
928 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
929 free_nfs_cb_data(data);
930 return -1;
931 }
921f877b
RS
932
933 while (count > 0) {
934 size_t readcount = count;
935 struct nfs_mcb_data *mdata;
936
937 if (readcount > nfs_get_readmax(nfs)) {
938 readcount = nfs_get_readmax(nfs);
939 }
940
941 mdata = malloc(sizeof(struct nfs_mcb_data));
942 if (mdata == NULL) {
943 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_mcb_data structure");
921f877b
RS
944 return -1;
945 }
946 bzero(mdata, sizeof(struct nfs_mcb_data));
947 mdata->data = data;
948 mdata->offset = offset;
949 mdata->count = readcount;
921f877b
RS
950 if (rpc_nfs_read_async(nfs->rpc, nfs_pread_mcb, &nfsfh->fh, offset, readcount, mdata) != 0) {
951 rpc_set_error(nfs->rpc, "RPC error: Failed to send READ call for %s", data->path);
952 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
953 free(mdata);
954 return -1;
955 }
956
957 count -= readcount;
958 offset += readcount;
959 data->num_calls++;
960 }
961
962 return 0;
84004dbf
RS
963}
964
965/*
966 * Async read()
967 */
968int nfs_read_async(struct nfs_context *nfs, struct nfsfh *nfsfh, size_t count, nfs_cb cb, void *private_data)
969{
970 return nfs_pread_async(nfs, nfsfh, nfsfh->offset, count, cb, private_data);
971}
972
973
974
975/*
976 * Async pwrite()
977 */
978static void nfs_pwrite_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
979{
980 struct nfs_cb_data *data = private_data;
981 struct nfs_context *nfs = data->nfs;
982 WRITE3res *res;
983
984 if (status == RPC_STATUS_ERROR) {
985 data->cb(-EFAULT, nfs, command_data, data->private_data);
986 free_nfs_cb_data(data);
987 return;
988 }
989 if (status == RPC_STATUS_CANCEL) {
990 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
991 free_nfs_cb_data(data);
992 return;
993 }
994
995 res = command_data;
996 if (res->status != NFS3_OK) {
997 rpc_set_error(nfs->rpc, "NFS: Write failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
998 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
999 free_nfs_cb_data(data);
1000 return;
1001 }
1002
1003 data->nfsfh->offset += res->WRITE3res_u.resok.count;
1004 data->cb(res->WRITE3res_u.resok.count, nfs, NULL, data->private_data);
1005 free_nfs_cb_data(data);
1006}
1007
1008int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, size_t count, char *buf, nfs_cb cb, void *private_data)
1009{
1010 struct nfs_cb_data *data;
1011
1012 data = malloc(sizeof(struct nfs_cb_data));
1013 if (data == NULL) {
1014 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
84004dbf
RS
1015 return -1;
1016 }
1017 bzero(data, sizeof(struct nfs_cb_data));
1018 data->nfs = nfs;
1019 data->cb = cb;
1020 data->private_data = private_data;
1021 data->nfsfh = nfsfh;
1022
1023 nfsfh->offset = offset;
1024 if (rpc_nfs_write_async(nfs->rpc, nfs_pwrite_cb, &nfsfh->fh, buf, offset, count, nfsfh->is_sync?FILE_SYNC:UNSTABLE, data) != 0) {
1025 rpc_set_error(nfs->rpc, "RPC error: Failed to send WRITE call for %s", data->path);
1026 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1027 free_nfs_cb_data(data);
1028 return -1;
1029 }
1030 return 0;
1031}
1032
1033/*
1034 * Async write()
1035 */
1036int nfs_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, size_t count, char *buf, nfs_cb cb, void *private_data)
1037{
1038 return nfs_pwrite_async(nfs, nfsfh, nfsfh->offset, count, buf, cb, private_data);
1039}
1040
1041
1042
1043
1044/*
1045 * close
1046 */
1047
1048int nfs_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data)
1049{
1050 if (nfsfh->fh.data.data_val != NULL){
1051 free(nfsfh->fh.data.data_val);
1052 nfsfh->fh.data.data_val = NULL;
1053 }
1054 free(nfsfh);
1055
1056 cb(0, nfs, NULL, private_data);
1057 return 0;
1058};
1059
1060
1061
1062
1063
1064/*
1065 * Async fstat()
1066 */
1067int nfs_fstat_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data)
1068{
1069 struct nfs_cb_data *data;
1070
1071 data = malloc(sizeof(struct nfs_cb_data));
1072 if (data == NULL) {
1073 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
84004dbf
RS
1074 return -1;
1075 }
1076 bzero(data, sizeof(struct nfs_cb_data));
1077 data->nfs = nfs;
1078 data->cb = cb;
1079 data->private_data = private_data;
1080
1081 if (rpc_nfs_getattr_async(nfs->rpc, nfs_stat_1_cb, &nfsfh->fh, data) != 0) {
1082 rpc_set_error(nfs->rpc, "RPC error: Failed to send STAT GETATTR call for %s", data->path);
1083 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1084 free_nfs_cb_data(data);
1085 return -1;
1086 }
1087 return 0;
1088}
1089
1090
1091
1092/*
1093 * Async fsync()
1094 */
1095static void nfs_fsync_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1096{
1097 struct nfs_cb_data *data = private_data;
1098 struct nfs_context *nfs = data->nfs;
1099 COMMIT3res *res;
1100
1101 if (status == RPC_STATUS_ERROR) {
1102 data->cb(-EFAULT, nfs, command_data, data->private_data);
1103 free_nfs_cb_data(data);
1104 return;
1105 }
1106 if (status == RPC_STATUS_CANCEL) {
1107 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1108 free_nfs_cb_data(data);
1109 return;
1110 }
1111
1112 res = command_data;
1113 if (res->status != NFS3_OK) {
1114 rpc_set_error(nfs->rpc, "NFS: Commit failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1115 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1116 free_nfs_cb_data(data);
1117 return;
1118 }
1119
1120 data->cb(0, nfs, NULL, data->private_data);
1121 free_nfs_cb_data(data);
1122}
1123
1124int nfs_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data)
1125{
1126 struct nfs_cb_data *data;
1127
1128 data = malloc(sizeof(struct nfs_cb_data));
1129 if (data == NULL) {
1130 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
84004dbf
RS
1131 return -1;
1132 }
1133 bzero(data, sizeof(struct nfs_cb_data));
1134 data->nfs = nfs;
1135 data->cb = cb;
1136 data->private_data = private_data;
1137
1138 if (rpc_nfs_commit_async(nfs->rpc, nfs_fsync_cb, &nfsfh->fh, data) != 0) {
1139 rpc_set_error(nfs->rpc, "RPC error: Failed to send COMMIT call for %s", data->path);
1140 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1141 free_nfs_cb_data(data);
1142 return -1;
1143 }
1144 return 0;
1145}
1146
1147
1148
1149
1150/*
1151 * Async ftruncate()
1152 */
1153static void nfs_ftruncate_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1154{
1155 struct nfs_cb_data *data = private_data;
1156 struct nfs_context *nfs = data->nfs;
1157 SETATTR3res *res;
1158
1159 if (status == RPC_STATUS_ERROR) {
1160 data->cb(-EFAULT, nfs, command_data, data->private_data);
1161 free_nfs_cb_data(data);
1162 return;
1163 }
1164 if (status == RPC_STATUS_CANCEL) {
1165 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1166 free_nfs_cb_data(data);
1167 return;
1168 }
1169
1170 res = command_data;
1171 if (res->status != NFS3_OK) {
1172 rpc_set_error(nfs->rpc, "NFS: Setattr failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1173 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1174 free_nfs_cb_data(data);
1175 return;
1176 }
1177
1178 data->cb(0, nfs, NULL, data->private_data);
1179 free_nfs_cb_data(data);
1180}
1181
1182int nfs_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t length, nfs_cb cb, void *private_data)
1183{
1184 struct nfs_cb_data *data;
1185 SETATTR3args args;
1186
1187 data = malloc(sizeof(struct nfs_cb_data));
1188 if (data == NULL) {
1189 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
84004dbf
RS
1190 return -1;
1191 }
1192 bzero(data, sizeof(struct nfs_cb_data));
1193 data->nfs = nfs;
1194 data->cb = cb;
1195 data->private_data = private_data;
1196
1197 bzero(&args, sizeof(SETATTR3args));
1198 args.object.data.data_len = nfsfh->fh.data.data_len;
1199 args.object.data.data_val = nfsfh->fh.data.data_val;
1200 args.new_attributes.size.set_it = 1;
1201 args.new_attributes.size.set_size3_u.size = length;
1202
1203 if (rpc_nfs_setattr_async(nfs->rpc, nfs_ftruncate_cb, &args, data) != 0) {
1204 rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
1205 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1206 free_nfs_cb_data(data);
1207 return -1;
1208 }
1209 return 0;
1210}
1211
1212
1213/*
1214 * Async truncate()
1215 */
1216static int nfs_truncate_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1217{
1218 off_t offset = data->continue_int;
1219 struct nfsfh nfsfh;
1220
1221 nfsfh.fh.data.data_val = data->fh.data.data_val;
1222 nfsfh.fh.data.data_len = data->fh.data.data_len;
1223
1224 if (nfs_ftruncate_async(nfs, &nfsfh, offset, data->cb, data->private_data) != 0) {
1225 rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
1226 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1227 free_nfs_cb_data(data);
1228 return -1;
1229 }
1230 free_nfs_cb_data(data);
1231 return 0;
1232}
1233
1234int nfs_truncate_async(struct nfs_context *nfs, const char *path, off_t length, nfs_cb cb, void *private_data)
1235{
1236 off_t offset;
1237
1238 offset = length;
1239
1240 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_truncate_continue_internal, NULL, NULL, offset) != 0) {
cbbf9d3e
RS
1241 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1242 return -1;
84004dbf
RS
1243 }
1244
1245 return 0;
1246}
1247
1248
1249
1250
1251/*
1252 * Async mkdir()
1253 */
1254static void nfs_mkdir_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1255{
1256 MKDIR3res *res;
1257 struct nfs_cb_data *data = private_data;
1258 struct nfs_context *nfs = data->nfs;
1259 char *str = data->continue_data;
1260
1261 str = &str[strlen(str) + 1];
1262
1263 if (status == RPC_STATUS_ERROR) {
1264 data->cb(-EFAULT, nfs, command_data, data->private_data);
1265 free_nfs_cb_data(data);
1266 return;
1267 }
1268 if (status == RPC_STATUS_CANCEL) {
1269 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1270 free_nfs_cb_data(data);
1271 return;
1272 }
1273
1274 res = command_data;
1275 if (res->status != NFS3_OK) {
1276 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));
1277 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1278 free_nfs_cb_data(data);
1279 return;
1280 }
1281
1282 data->cb(0, nfs, NULL, data->private_data);
1283 free_nfs_cb_data(data);
1284}
1285
1286static int nfs_mkdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1287{
1288 char *str = data->continue_data;
1289
1290 str = &str[strlen(str) + 1];
1291
1292 if (rpc_nfs_mkdir_async(nfs->rpc, nfs_mkdir_cb, &data->fh, str, data) != 0) {
1293 rpc_set_error(nfs->rpc, "RPC error: Failed to send MKDIR call for %s", data->path);
1294 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1295 free_nfs_cb_data(data);
1296 return -1;
1297 }
1298 return 0;
1299}
1300
1301int nfs_mkdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
1302{
1303 char *new_path;
1304 char *ptr;
1305
1306 new_path = strdup(path);
1307 if (new_path == NULL) {
cbbf9d3e 1308 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path");
84004dbf
RS
1309 return -1;
1310 }
1311
1312 ptr = rindex(new_path, '/');
1313 if (ptr == NULL) {
cbbf9d3e
RS
1314 rpc_set_error(nfs->rpc, "Invalid path %s", path);
1315 return -1;
84004dbf
RS
1316 }
1317 *ptr = 0;
1318
1319 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1320 if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_mkdir_continue_internal, new_path, free, 0) != 0) {
cbbf9d3e
RS
1321 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path component");
1322 return -1;
84004dbf
RS
1323 }
1324
1325 return 0;
1326}
1327
1328
1329
1330
1331
1332/*
1333 * Async rmdir()
1334 */
1335static void nfs_rmdir_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1336{
1337 RMDIR3res *res;
1338 struct nfs_cb_data *data = private_data;
1339 struct nfs_context *nfs = data->nfs;
1340 char *str = data->continue_data;
1341
1342 str = &str[strlen(str) + 1];
1343
1344 if (status == RPC_STATUS_ERROR) {
1345 data->cb(-EFAULT, nfs, command_data, data->private_data);
1346 free_nfs_cb_data(data);
1347 return;
1348 }
1349 if (status == RPC_STATUS_CANCEL) {
1350 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1351 free_nfs_cb_data(data);
1352 return;
1353 }
1354
1355 res = command_data;
1356 if (res->status != NFS3_OK) {
1357 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));
1358 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1359 free_nfs_cb_data(data);
1360 return;
1361 }
1362
1363 data->cb(0, nfs, NULL, data->private_data);
1364 free_nfs_cb_data(data);
1365}
1366
1367static int nfs_rmdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1368{
1369 char *str = data->continue_data;
1370
1371 str = &str[strlen(str) + 1];
1372
1373 if (rpc_nfs_rmdir_async(nfs->rpc, nfs_rmdir_cb, &data->fh, str, data) != 0) {
1374 rpc_set_error(nfs->rpc, "RPC error: Failed to send RMDIR call for %s", data->path);
1375 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1376 free_nfs_cb_data(data);
1377 return -1;
1378 }
1379 return 0;
1380}
1381
1382int nfs_rmdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
1383{
1384 char *new_path;
1385 char *ptr;
1386
1387 new_path = strdup(path);
1388 if (new_path == NULL) {
cbbf9d3e 1389 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path");
84004dbf
RS
1390 return -1;
1391 }
1392
1393 ptr = rindex(new_path, '/');
1394 if (ptr == NULL) {
cbbf9d3e
RS
1395 rpc_set_error(nfs->rpc, "Invalid path %s", path);
1396 return -1;
84004dbf
RS
1397 }
1398 *ptr = 0;
1399
1400 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1401 if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_rmdir_continue_internal, new_path, free, 0) != 0) {
cbbf9d3e
RS
1402 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1403 return -1;
84004dbf
RS
1404 }
1405
1406 return 0;
1407}
1408
1409
1410
1411
1412/*
1413 * Async creat()
1414 */
1415static void nfs_create_2_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1416{
1417 LOOKUP3res *res;
1418 struct nfs_cb_data *data = private_data;
1419 struct nfs_context *nfs = data->nfs;
1420 struct nfsfh *nfsfh;
1421 char *str = data->continue_data;
1422
1423 if (status == RPC_STATUS_ERROR) {
1424 data->cb(-EFAULT, nfs, command_data, data->private_data);
1425 free_nfs_cb_data(data);
1426 return;
1427 }
1428 if (status == RPC_STATUS_CANCEL) {
1429 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1430 free_nfs_cb_data(data);
1431 return;
1432 }
1433
1434 str = &str[strlen(str) + 1];
1435 res = command_data;
1436 if (res->status != NFS3_OK) {
1437 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));
1438 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1439
1440 return;
1441 }
1442
1443 nfsfh = malloc(sizeof(struct nfsfh));
1444 if (nfsfh == NULL) {
1445 rpc_set_error(nfs->rpc, "NFS: Failed to allocate nfsfh structure");
1446 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1447 free_nfs_cb_data(data);
1448 return;
1449 }
1450 bzero(nfsfh, sizeof(struct nfsfh));
1451
1452 /* steal the filehandle */
1453 nfsfh->fh.data.data_len = data->fh.data.data_len;
1454 nfsfh->fh.data.data_val = data->fh.data.data_val;
1455 data->fh.data.data_val = NULL;
1456
1457 data->cb(0, nfs, nfsfh, data->private_data);
1458 free_nfs_cb_data(data);
1459}
1460
1461
1462
1463static void nfs_creat_1_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1464{
1465 CREATE3res *res;
1466 struct nfs_cb_data *data = private_data;
1467 struct nfs_context *nfs = data->nfs;
1468 char *str = data->continue_data;
1469
1470 if (status == RPC_STATUS_ERROR) {
1471 data->cb(-EFAULT, nfs, command_data, data->private_data);
1472 free_nfs_cb_data(data);
1473 return;
1474 }
1475 if (status == RPC_STATUS_CANCEL) {
1476 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1477 free_nfs_cb_data(data);
1478 return;
1479 }
1480
1481 str = &str[strlen(str) + 1];
1482 res = command_data;
1483 if (res->status != NFS3_OK) {
1484 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));
1485 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1486
1487 return;
1488 }
1489
1490 if (rpc_nfs_lookup_async(nfs->rpc, nfs_create_2_cb, &data->fh, str, data) != 0) {
1491 rpc_set_error(nfs->rpc, "RPC error: Failed to send lookup call for %s/%s", data->saved_path, str);
1492 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1493 free_nfs_cb_data(data);
1494 return;
1495 }
1496 return;
1497}
1498
1499static int nfs_creat_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1500{
1501 char *str = data->continue_data;
1502
1503 str = &str[strlen(str) + 1];
1504
1505 if (rpc_nfs_create_async(nfs->rpc, nfs_creat_1_cb, &data->fh, str, data->continue_int, data) != 0) {
1506 rpc_set_error(nfs->rpc, "RPC error: Failed to send CREATE call for %s/%s", data->path, str);
1507 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1508 free_nfs_cb_data(data);
1509 return -1;
1510 }
1511 return 0;
1512}
1513
1514int nfs_creat_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data)
1515{
1516 char *new_path;
1517 char *ptr;
1518
1519 new_path = strdup(path);
1520 if (new_path == NULL) {
cbbf9d3e 1521 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path");
84004dbf
RS
1522 return -1;
1523 }
1524
1525 ptr = rindex(new_path, '/');
1526 if (ptr == NULL) {
cbbf9d3e
RS
1527 rpc_set_error(nfs->rpc, "Invalid path %s", path);
1528 return -1;
84004dbf
RS
1529 }
1530 *ptr = 0;
1531
1532 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1533 if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_creat_continue_internal, new_path, free, mode) != 0) {
cbbf9d3e
RS
1534 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1535 return -1;
84004dbf
RS
1536 }
1537
1538 return 0;
1539}
1540
1541
1542
1543
1544/*
1545 * Async unlink()
1546 */
1547static void nfs_unlink_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1548{
1549 REMOVE3res *res;
1550 struct nfs_cb_data *data = private_data;
1551 struct nfs_context *nfs = data->nfs;
1552 char *str = data->continue_data;
1553
1554 str = &str[strlen(str) + 1];
1555
1556 if (status == RPC_STATUS_ERROR) {
1557 data->cb(-EFAULT, nfs, command_data, data->private_data);
1558 free_nfs_cb_data(data);
1559 return;
1560 }
1561 if (status == RPC_STATUS_CANCEL) {
1562 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1563 free_nfs_cb_data(data);
1564 return;
1565 }
1566
1567 res = command_data;
1568 if (res->status != NFS3_OK) {
1569 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));
1570 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1571 free_nfs_cb_data(data);
1572 return;
1573 }
1574
1575 data->cb(0, nfs, NULL, data->private_data);
1576 free_nfs_cb_data(data);
1577}
1578
1579static int nfs_unlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1580{
1581 char *str = data->continue_data;
1582
1583 str = &str[strlen(str) + 1];
1584
1585 if (rpc_nfs_remove_async(nfs->rpc, nfs_unlink_cb, &data->fh, str, data) != 0) {
1586 rpc_set_error(nfs->rpc, "RPC error: Failed to send REMOVE call for %s", data->path);
1587 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1588 free_nfs_cb_data(data);
1589 return -1;
1590 }
1591 return 0;
1592}
1593
1594int nfs_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
1595{
1596 char *new_path;
1597 char *ptr;
1598
1599 new_path = strdup(path);
1600 if (new_path == NULL) {
cbbf9d3e 1601 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path");
84004dbf
RS
1602 return -1;
1603 }
1604
1605 ptr = rindex(new_path, '/');
1606 if (ptr == NULL) {
cbbf9d3e
RS
1607 rpc_set_error(nfs->rpc, "Invalid path %s", path);
1608 return -1;
84004dbf
RS
1609 }
1610 *ptr = 0;
1611
1612 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1613 if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_unlink_continue_internal, new_path, free, 0) != 0) {
cbbf9d3e
RS
1614 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1615 return -1;
84004dbf
RS
1616 }
1617
1618 return 0;
1619}
1620
1621
1622
1623
1624
1625/*
1626 * Async opendir()
1627 */
1628static void nfs_opendir_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1629{
1630 READDIR3res *res;
1631 struct nfs_cb_data *data = private_data;
1632 struct nfs_context *nfs = data->nfs;
1633 struct nfsdir *nfsdir = data->continue_data;;
1634 struct entry3 *entry;
1635 uint64_t cookie;
1636
1637 if (status == RPC_STATUS_ERROR) {
1638 data->cb(-EFAULT, nfs, command_data, data->private_data);
1639 nfs_free_nfsdir(nfsdir);
1640 data->continue_data = NULL;
1641 free_nfs_cb_data(data);
1642 return;
1643 }
1644 if (status == RPC_STATUS_CANCEL) {
1645 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1646 nfs_free_nfsdir(nfsdir);
1647 data->continue_data = NULL;
1648 free_nfs_cb_data(data);
1649 return;
1650 }
1651
1652 res = command_data;
1653 if (res->status != NFS3_OK) {
1654 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));
1655 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1656 nfs_free_nfsdir(nfsdir);
1657 data->continue_data = NULL;
1658 free_nfs_cb_data(data);
1659 return;
1660 }
1661
1662 entry =res->READDIR3res_u.resok.reply.entries;
1663 while (entry != NULL) {
1664 struct nfsdirent *nfsdirent;
1665
1666 nfsdirent = malloc(sizeof(struct nfsdirent));
1667 if (nfsdirent == NULL) {
1668 data->cb(-ENOMEM, nfs, "Failed to allocate dirent", data->private_data);
1669 nfs_free_nfsdir(nfsdir);
1670 data->continue_data = NULL;
1671 free_nfs_cb_data(data);
1672 return;
1673 }
1674 bzero(nfsdirent, sizeof(struct nfsdirent));
1675 nfsdirent->name = strdup(entry->name);
1676 if (nfsdirent->name == NULL) {
1677 data->cb(-ENOMEM, nfs, "Failed to allocate dirent->name", data->private_data);
1678 nfs_free_nfsdir(nfsdir);
1679 data->continue_data = NULL;
1680 free_nfs_cb_data(data);
1681 return;
1682 }
1683 nfsdirent->inode = entry->fileid;
1684 nfsdirent->next = nfsdir->entries;
1685 nfsdir->entries = nfsdirent;
1686
1687 cookie = entry->cookie;
1688 entry = entry->nextentry;
1689 }
1690
1691 if (res->READDIR3res_u.resok.reply.eof == 0) {
1692 if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir_cb, &data->fh, cookie, res->READDIR3res_u.resok.cookieverf, 20000, data) != 0) {
1693 rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR call for %s", data->path);
1694 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1695 nfs_free_nfsdir(nfsdir);
1696 data->continue_data = NULL;
1697 free_nfs_cb_data(data);
1698 return;
1699 }
1700 return;
1701 }
1702
1703 /* steal the dirhandle */
1704 data->continue_data = NULL;
1705 nfsdir->current = nfsdir->entries;
1706
1707 data->cb(0, nfs, nfsdir, data->private_data);
1708 free_nfs_cb_data(data);
1709}
1710
1711static int nfs_opendir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1712{
1713 cookieverf3 cv;
1714
1715 bzero(cv, sizeof(cookieverf3));
1716 if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir_cb, &data->fh, 0, (char *)&cv, 20000, data) != 0) {
1717 rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR call for %s", data->path);
1718 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1719 free_nfs_cb_data(data);
1720 return -1;
1721 }
1722 return 0;
1723}
1724
1725int nfs_opendir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
1726{
1727 struct nfsdir *nfsdir;
1728
1729 nfsdir = malloc(sizeof(struct nfsdir));
1730 if (nfsdir == NULL) {
cbbf9d3e 1731 rpc_set_error(nfs->rpc, "failed to allocate buffer for nfsdir");
84004dbf
RS
1732 return -1;
1733 }
1734 bzero(nfsdir, sizeof(struct nfsdir));
1735
1736 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_opendir_continue_internal, nfsdir, free, 0) != 0) {
cbbf9d3e
RS
1737 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1738 return -1;
84004dbf
RS
1739 }
1740
1741 return 0;
1742}
1743
1744
1745struct nfsdirent *nfs_readdir(struct nfs_context *nfs _U_, struct nfsdir *nfsdir)
1746{
1747 struct nfsdirent *nfsdirent = nfsdir->current;
1748
1749 if (nfsdir->current != NULL) {
1750 nfsdir->current = nfsdir->current->next;
1751 }
1752 return nfsdirent;
1753}
1754
1755
1756void nfs_closedir(struct nfs_context *nfs _U_, struct nfsdir *nfsdir)
1757{
1758 nfs_free_nfsdir(nfsdir);
1759}
1760
1761
1762
1763
1764
1765
1766
1767/*
1768 * Async lseek()
1769 */
1770struct lseek_cb_data {
1771 struct nfs_context *nfs;
1772 struct nfsfh *nfsfh;
1773 off_t offset;
1774 nfs_cb cb;
1775 void *private_data;
1776};
1777
1778static void nfs_lseek_1_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1779{
1780 GETATTR3res *res;
1781 struct lseek_cb_data *data = private_data;
1782 struct nfs_context *nfs = data->nfs;
1783
1784 if (status == RPC_STATUS_ERROR) {
1785 data->cb(-EFAULT, nfs, command_data, data->private_data);
1786 free(data);
1787 return;
1788 }
1789 if (status == RPC_STATUS_CANCEL) {
1790 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1791 free(data);
1792 return;
1793 }
1794
1795 res = command_data;
1796 if (res->status != NFS3_OK) {
1797 rpc_set_error(nfs->rpc, "NFS: GETATTR failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1798 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1799 free(data);
1800 return;
1801 }
1802
1803 data->nfsfh->offset = data->offset + res->GETATTR3res_u.resok.obj_attributes.size;
1804 data->cb(0, nfs, &data->nfsfh->offset, data->private_data);
1805 free(data);
1806}
1807
1808int nfs_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, int whence, nfs_cb cb, void *private_data)
1809{
1810 struct lseek_cb_data *data;
1811
1812 if (whence == SEEK_SET) {
1813 nfsfh->offset = offset;
1814 cb(0, nfs, &nfsfh->offset, private_data);
1815 return 0;
1816 }
1817 if (whence == SEEK_CUR) {
1818 nfsfh->offset += offset;
1819 cb(0, nfs, &nfsfh->offset, private_data);
1820 return 0;
1821 }
1822
1823 data = malloc(sizeof(struct lseek_cb_data));
1824 if (data == NULL) {
1825 rpc_set_error(nfs->rpc, "Out Of Memory: Failed to malloc lseek cb data");
1826 return -1;
1827 }
1828
1829 data->nfs = nfs;
1830 data->nfsfh = nfsfh;
1831 data->offset = offset;
1832 data->cb = cb;
1833 data->private_data = private_data;
1834
1835 if (rpc_nfs_getattr_async(nfs->rpc, nfs_lseek_1_cb, &nfsfh->fh, data) != 0) {
1836 rpc_set_error(nfs->rpc, "RPC error: Failed to send LSEEK GETATTR call");
1837 free(data);
cbbf9d3e 1838 return -1;
84004dbf
RS
1839 }
1840 return 0;
1841}
1842
1843
1844
1845
1846/*
1847 * Async statvfs()
1848 */
1849static void nfs_statvfs_1_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1850{
1851 FSSTAT3res *res;
1852 struct nfs_cb_data *data = private_data;
1853 struct nfs_context *nfs = data->nfs;
1854 struct statvfs svfs;
1855
1856 if (status == RPC_STATUS_ERROR) {
1857 data->cb(-EFAULT, nfs, command_data, data->private_data);
1858 free_nfs_cb_data(data);
1859 return;
1860 }
1861 if (status == RPC_STATUS_CANCEL) {
1862 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1863 free_nfs_cb_data(data);
1864 return;
1865 }
1866
1867 res = command_data;
1868 if (res->status != NFS3_OK) {
1869 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));
1870 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1871 free_nfs_cb_data(data);
1872 return;
1873 }
1874
1875 svfs.f_bsize = 4096;
1876 svfs.f_frsize = 4096;
1877 svfs.f_blocks = res->FSSTAT3res_u.resok.tbytes/4096;
1878 svfs.f_bfree = res->FSSTAT3res_u.resok.fbytes/4096;
1879 svfs.f_bavail = res->FSSTAT3res_u.resok.abytes/4096;
1880 svfs.f_files = res->FSSTAT3res_u.resok.tfiles;
1881 svfs.f_ffree = res->FSSTAT3res_u.resok.ffiles;
1882 svfs.f_favail = res->FSSTAT3res_u.resok.afiles;
1883 svfs.f_fsid = 0;
1884 svfs.f_flag = 0;
1885 svfs.f_namemax = 256;
1886
1887 data->cb(0, nfs, &svfs, data->private_data);
1888 free_nfs_cb_data(data);
1889}
1890
1891static int nfs_statvfs_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1892{
1893 if (rpc_nfs_fsstat_async(nfs->rpc, nfs_statvfs_1_cb, &data->fh, data) != 0) {
1894 rpc_set_error(nfs->rpc, "RPC error: Failed to send FSSTAT call for %s", data->path);
1895 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1896 free_nfs_cb_data(data);
1897 return -1;
1898 }
1899 return 0;
1900}
1901
1902int nfs_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
1903{
1904 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_statvfs_continue_internal, NULL, NULL, 0) != 0) {
cbbf9d3e 1905 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
84004dbf
RS
1906 return -1;
1907 }
1908
1909 return 0;
1910}
1911
1912
1913
1914
1915/*
1916 * Async readlink()
1917 */
1918static void nfs_readlink_1_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1919{
1920 READLINK3res *res;
1921 struct nfs_cb_data *data = private_data;
1922 struct nfs_context *nfs = data->nfs;
1923
1924 if (status == RPC_STATUS_ERROR) {
1925 data->cb(-EFAULT, nfs, command_data, data->private_data);
1926 free_nfs_cb_data(data);
1927 return;
1928 }
1929 if (status == RPC_STATUS_CANCEL) {
1930 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1931 free_nfs_cb_data(data);
1932 return;
1933 }
1934
1935 res = command_data;
1936 if (res->status != NFS3_OK) {
1937 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));
1938 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1939 free_nfs_cb_data(data);
1940 return;
1941 }
1942
1943
1944 data->cb(0, nfs, res->READLINK3res_u.resok.data, data->private_data);
1945 free_nfs_cb_data(data);
1946}
1947
1948static int nfs_readlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1949{
1950 if (rpc_nfs_readlink_async(nfs->rpc, nfs_readlink_1_cb, &data->fh, data) != 0) {
1951 rpc_set_error(nfs->rpc, "RPC error: Failed to send READLINK call for %s", data->path);
1952 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1953 free_nfs_cb_data(data);
1954 return -1;
1955 }
1956 return 0;
1957}
1958
1959int nfs_readlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
1960{
1961 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_readlink_continue_internal, NULL, NULL, 0) != 0) {
cbbf9d3e 1962 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
84004dbf
RS
1963 return -1;
1964 }
1965
1966 return 0;
1967}
1968
1969
1970
1971
1972/*
1973 * Async chmod()
1974 */
1975static void nfs_chmod_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1976{
1977 struct nfs_cb_data *data = private_data;
1978 struct nfs_context *nfs = data->nfs;
1979 SETATTR3res *res;
1980
1981 if (status == RPC_STATUS_ERROR) {
1982 data->cb(-EFAULT, nfs, command_data, data->private_data);
1983 free_nfs_cb_data(data);
1984 return;
1985 }
1986 if (status == RPC_STATUS_CANCEL) {
1987 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1988 free_nfs_cb_data(data);
1989 return;
1990 }
1991
1992 res = command_data;
1993 if (res->status != NFS3_OK) {
1994 rpc_set_error(nfs->rpc, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1995 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1996 free_nfs_cb_data(data);
1997 return;
1998 }
1999
2000 data->cb(0, nfs, NULL, data->private_data);
2001 free_nfs_cb_data(data);
2002}
2003
2004static int nfs_chmod_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2005{
2006 SETATTR3args args;
2007
2008 bzero(&args, sizeof(SETATTR3args));
2009 args.object.data.data_len = data->fh.data.data_len;
2010 args.object.data.data_val = data->fh.data.data_val;
2011 args.new_attributes.mode.set_it = 1;
2012 args.new_attributes.mode.set_mode3_u.mode = data->continue_int;
2013
2014 if (rpc_nfs_setattr_async(nfs->rpc, nfs_chmod_cb, &args, data) != 0) {
2015 rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
2016 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2017 free_nfs_cb_data(data);
2018 return -1;
2019 }
2020 return 0;
2021}
2022
2023
2024int nfs_chmod_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data)
2025{
2026 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_chmod_continue_internal, NULL, NULL, mode) != 0) {
cbbf9d3e 2027 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
84004dbf
RS
2028 return -1;
2029 }
2030
2031 return 0;
2032}
2033
2034/*
2035 * Async fchmod()
2036 */
2037int nfs_fchmod_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode, nfs_cb cb, void *private_data)
2038{
2039 struct nfs_cb_data *data;
2040
2041 data = malloc(sizeof(struct nfs_cb_data));
2042 if (data == NULL) {
cbbf9d3e 2043 rpc_set_error(nfs->rpc, "out of memory. failed to allocate memory for nfs mount data");
84004dbf
RS
2044 return -1;
2045 }
2046 bzero(data, sizeof(struct nfs_cb_data));
2047 data->nfs = nfs;
2048 data->cb = cb;
2049 data->private_data = private_data;
2050 data->continue_int = mode;
2051 data->fh.data.data_len = nfsfh->fh.data.data_len;
2052 data->fh.data.data_val = malloc(data->fh.data.data_len);
2053 if (data->fh.data.data_val == NULL) {
2054 rpc_set_error(nfs->rpc, "Out of memory: Failed to allocate fh");
2055 free_nfs_cb_data(data);
2056 return -1;
2057 }
2058 memcpy(data->fh.data.data_val, nfsfh->fh.data.data_val, data->fh.data.data_len);
2059
2060 if (nfs_chmod_continue_internal(nfs, data) != 0) {
2061 free_nfs_cb_data(data);
2062 return -1;
2063 }
2064
2065 return 0;
2066}
2067
2068
2069
2070/*
2071 * Async chown()
2072 */
2073static void nfs_chown_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
2074{
2075 struct nfs_cb_data *data = private_data;
2076 struct nfs_context *nfs = data->nfs;
2077 SETATTR3res *res;
2078
2079 if (status == RPC_STATUS_ERROR) {
2080 data->cb(-EFAULT, nfs, command_data, data->private_data);
2081 free_nfs_cb_data(data);
2082 return;
2083 }
2084 if (status == RPC_STATUS_CANCEL) {
2085 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2086 free_nfs_cb_data(data);
2087 return;
2088 }
2089
2090 res = command_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);
2095 return;
2096 }
2097
2098 data->cb(0, nfs, NULL, data->private_data);
2099 free_nfs_cb_data(data);
2100}
2101
2102struct nfs_chown_data {
2103 uid_t uid;
2104 gid_t gid;
2105};
2106
2107static int nfs_chown_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2108{
2109 SETATTR3args args;
2110 struct nfs_chown_data *chown_data = data->continue_data;
2111
2112 bzero(&args, sizeof(SETATTR3args));
2113 args.object.data.data_len = data->fh.data.data_len;
2114 args.object.data.data_val = data->fh.data.data_val;
2115 if (chown_data->uid != (uid_t)-1) {
2116 args.new_attributes.uid.set_it = 1;
2117 args.new_attributes.uid.set_uid3_u.uid = chown_data->uid;
2118 }
2119 if (chown_data->gid != (gid_t)-1) {
2120 args.new_attributes.gid.set_it = 1;
2121 args.new_attributes.gid.set_gid3_u.gid = chown_data->gid;
2122 }
2123
2124 if (rpc_nfs_setattr_async(nfs->rpc, nfs_chown_cb, &args, data) != 0) {
2125 rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
2126 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2127 free_nfs_cb_data(data);
2128 return -1;
2129 }
2130 return 0;
2131}
2132
2133
2134int nfs_chown_async(struct nfs_context *nfs, const char *path, int uid, int gid, nfs_cb cb, void *private_data)
2135{
2136 struct nfs_chown_data *chown_data;
2137
2138 chown_data = malloc(sizeof(struct nfs_chown_data));
2139 if (chown_data == NULL) {
cbbf9d3e 2140 rpc_set_error(nfs->rpc, "Failed to allocate memory for chown data structure");
84004dbf
RS
2141 return -1;
2142 }
2143
2144 chown_data->uid = uid;
2145 chown_data->gid = gid;
2146
2147 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_chown_continue_internal, chown_data, free, 0) != 0) {
cbbf9d3e 2148 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
84004dbf
RS
2149 return -1;
2150 }
2151
2152 return 0;
2153}
2154
2155
2156/*
2157 * Async fchown()
2158 */
2159int nfs_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid, nfs_cb cb, void *private_data)
2160{
2161 struct nfs_cb_data *data;
2162 struct nfs_chown_data *chown_data;
2163
2164 chown_data = malloc(sizeof(struct nfs_chown_data));
2165 if (chown_data == NULL) {
cbbf9d3e 2166 rpc_set_error(nfs->rpc, "Failed to allocate memory for chown data structure");
84004dbf
RS
2167 return -1;
2168 }
2169
2170 chown_data->uid = uid;
2171 chown_data->gid = gid;
2172
2173
2174 data = malloc(sizeof(struct nfs_cb_data));
2175 if (data == NULL) {
cbbf9d3e 2176 rpc_set_error(nfs->rpc, "out of memory. failed to allocate memory for fchown data");
84004dbf
RS
2177 return -1;
2178 }
2179 bzero(data, sizeof(struct nfs_cb_data));
2180 data->nfs = nfs;
2181 data->cb = cb;
2182 data->private_data = private_data;
2183 data->continue_data = chown_data;
2184 data->fh.data.data_len = nfsfh->fh.data.data_len;
2185 data->fh.data.data_val = malloc(data->fh.data.data_len);
2186 if (data->fh.data.data_val == NULL) {
2187 rpc_set_error(nfs->rpc, "Out of memory: Failed to allocate fh");
2188 free_nfs_cb_data(data);
2189 return -1;
2190 }
2191 memcpy(data->fh.data.data_val, nfsfh->fh.data.data_val, data->fh.data.data_len);
2192
2193
2194 if (nfs_chown_continue_internal(nfs, data) != 0) {
2195 free_nfs_cb_data(data);
2196 return -1;
2197 }
2198
2199 return 0;
2200}
2201
2202
2203
2204
2205
2206/*
2207 * Async utimes()
2208 */
2209static void nfs_utimes_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
2210{
2211 struct nfs_cb_data *data = private_data;
2212 struct nfs_context *nfs = data->nfs;
2213 SETATTR3res *res;
2214
2215 if (status == RPC_STATUS_ERROR) {
2216 data->cb(-EFAULT, nfs, command_data, data->private_data);
2217 free_nfs_cb_data(data);
2218 return;
2219 }
2220 if (status == RPC_STATUS_CANCEL) {
2221 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2222 free_nfs_cb_data(data);
2223 return;
2224 }
2225
2226 res = command_data;
2227 if (res->status != NFS3_OK) {
2228 rpc_set_error(nfs->rpc, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
2229 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2230 free_nfs_cb_data(data);
2231 return;
2232 }
2233
2234 data->cb(0, nfs, NULL, data->private_data);
2235 free_nfs_cb_data(data);
2236}
2237
2238static int nfs_utimes_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2239{
2240 SETATTR3args args;
2241 struct timeval *utimes_data = data->continue_data;
2242
2243 bzero(&args, sizeof(SETATTR3args));
2244 args.object.data.data_len = data->fh.data.data_len;
2245 args.object.data.data_val = data->fh.data.data_val;
2246 if (utimes_data != NULL) {
2247 args.new_attributes.atime.set_it = SET_TO_CLIENT_TIME;
2248 args.new_attributes.atime.set_atime_u.atime.seconds = utimes_data[0].tv_sec;
2249 args.new_attributes.atime.set_atime_u.atime.nseconds = utimes_data[0].tv_usec * 1000;
2250 args.new_attributes.mtime.set_it = SET_TO_CLIENT_TIME;
2251 args.new_attributes.mtime.set_mtime_u.mtime.seconds = utimes_data[1].tv_sec;
2252 args.new_attributes.mtime.set_mtime_u.mtime.nseconds = utimes_data[1].tv_usec * 1000;
2253 } else {
2254 args.new_attributes.atime.set_it = SET_TO_SERVER_TIME;
2255 args.new_attributes.mtime.set_it = SET_TO_SERVER_TIME;
2256 }
2257
2258 if (rpc_nfs_setattr_async(nfs->rpc, nfs_utimes_cb, &args, data) != 0) {
2259 rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
2260 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2261 free_nfs_cb_data(data);
2262 return -1;
2263 }
2264 return 0;
2265}
2266
2267
2268int nfs_utimes_async(struct nfs_context *nfs, const char *path, struct timeval *times, nfs_cb cb, void *private_data)
2269{
2270 struct timeval *new_times = NULL;
2271
2272 if (times != NULL) {
2273 new_times = malloc(sizeof(struct timeval)*2);
2274 if (new_times == NULL) {
cbbf9d3e 2275 rpc_set_error(nfs->rpc, "Failed to allocate memory for timeval structure");
84004dbf
RS
2276 return -1;
2277 }
2278
2279 memcpy(new_times, times, sizeof(struct timeval)*2);
2280 }
2281
2282 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_utimes_continue_internal, new_times, free, 0) != 0) {
cbbf9d3e 2283 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
84004dbf
RS
2284 return -1;
2285 }
2286
2287 return 0;
2288}
2289
2290/*
2291 * Async utime()
2292 */
2293int nfs_utime_async(struct nfs_context *nfs, const char *path, struct utimbuf *times, nfs_cb cb, void *private_data)
2294{
2295 struct timeval *new_times = NULL;
2296
2297 if (times != NULL) {
2298 new_times = malloc(sizeof(struct timeval)*2);
2299 if (new_times == NULL) {
cbbf9d3e 2300 rpc_set_error(nfs->rpc, "Failed to allocate memory for timeval structure");
84004dbf
RS
2301 return -1;
2302 }
2303
2304 new_times[0].tv_sec = times->actime;
2305 new_times[0].tv_usec = 0;
2306 new_times[1].tv_sec = times->modtime;
2307 new_times[1].tv_usec = 0;
2308 }
2309
2310 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_utimes_continue_internal, new_times, free, 0) != 0) {
cbbf9d3e 2311 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
84004dbf
RS
2312 return -1;
2313 }
2314
2315 return 0;
2316}
2317
2318
2319
2320
2321
2322/*
2323 * Async access()
2324 */
2325static void nfs_access_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
2326{
2327 ACCESS3res *res;
2328 struct nfs_cb_data *data = private_data;
2329 struct nfs_context *nfs = data->nfs;
2330 unsigned int nfsmode = 0;
2331
2332 if (status == RPC_STATUS_ERROR) {
2333 data->cb(-EFAULT, nfs, command_data, data->private_data);
2334 free_nfs_cb_data(data);
2335 return;
2336 }
2337 if (status == RPC_STATUS_CANCEL) {
2338 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2339 free_nfs_cb_data(data);
2340 return;
2341 }
2342
2343 res = command_data;
2344 if (res->status != NFS3_OK) {
2345 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));
2346 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2347 free_nfs_cb_data(data);
2348 return;
2349 }
2350
2351 if (data->continue_int & R_OK) {
2352 nfsmode |= ACCESS3_READ;
2353 }
2354 if (data->continue_int & W_OK) {
2355 nfsmode |= ACCESS3_MODIFY;
2356 }
2357 if (data->continue_int & X_OK) {
2358 nfsmode |= ACCESS3_EXECUTE;
2359 }
2360
2361 if (res->ACCESS3res_u.resok.access != nfsmode) {
2362 rpc_set_error(nfs->rpc, "NFS: ACCESS denied. Required access %c%c%c. Allowed access %c%c%c",
2363 nfsmode&ACCESS3_READ?'r':'-',
2364 nfsmode&ACCESS3_MODIFY?'w':'-',
2365 nfsmode&ACCESS3_EXECUTE?'x':'-',
2366 res->ACCESS3res_u.resok.access&ACCESS3_READ?'r':'-',
2367 res->ACCESS3res_u.resok.access&ACCESS3_MODIFY?'w':'-',
2368 res->ACCESS3res_u.resok.access&ACCESS3_EXECUTE?'x':'-');
2369 data->cb(-EACCES, nfs, rpc_get_error(nfs->rpc), data->private_data);
2370 free_nfs_cb_data(data);
2371 return;
2372 }
2373
2374 data->cb(0, nfs, NULL, data->private_data);
2375 free_nfs_cb_data(data);
2376}
2377
2378static int nfs_access_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2379{
2380 int nfsmode = 0;
2381
2382 if (data->continue_int & R_OK) {
2383 nfsmode |= ACCESS3_READ;
2384 }
2385 if (data->continue_int & W_OK) {
2386 nfsmode |= ACCESS3_MODIFY;
2387 }
2388 if (data->continue_int & X_OK) {
2389 nfsmode |= ACCESS3_EXECUTE;
2390 }
2391
2392 if (rpc_nfs_access_async(nfs->rpc, nfs_access_cb, &data->fh, nfsmode, data) != 0) {
2393 rpc_set_error(nfs->rpc, "RPC error: Failed to send OPEN ACCESS call for %s", data->path);
2394 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2395 free_nfs_cb_data(data);
2396 return -1;
2397 }
2398 return 0;
2399}
2400
2401int nfs_access_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data)
2402{
2403 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_access_continue_internal, NULL, NULL, mode) != 0) {
cbbf9d3e
RS
2404 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
2405 return -1;
84004dbf
RS
2406 }
2407
2408 return 0;
2409}
2410
2411
2412
2413/*
2414 * Async symlink()
2415 */
2416struct nfs_symlink_data {
2417 char *oldpath;
2418 char *newpathparent;
2419 char *newpathobject;
2420};
2421
2422static void free_nfs_symlink_data(void *mem)
2423{
2424 struct nfs_symlink_data *data = mem;
2425
2426 if (data->oldpath != NULL) {
2427 free(data->oldpath);
2428 }
2429 if (data->newpathparent != NULL) {
2430 free(data->newpathparent);
2431 }
2432 if (data->newpathobject != NULL) {
2433 free(data->newpathobject);
2434 }
2435 free(data);
2436}
2437
2438static void nfs_symlink_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
2439{
2440 SYMLINK3res *res;
2441 struct nfs_cb_data *data = private_data;
2442 struct nfs_context *nfs = data->nfs;
2443 struct nfs_symlink_data *symlink_data = data->continue_data;
2444
2445 if (status == RPC_STATUS_ERROR) {
2446 data->cb(-EFAULT, nfs, command_data, data->private_data);
2447 free_nfs_cb_data(data);
2448 return;
2449 }
2450 if (status == RPC_STATUS_CANCEL) {
2451 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2452 free_nfs_cb_data(data);
2453 return;
2454 }
2455
2456 res = command_data;
2457 if (res->status != NFS3_OK) {
2458 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));
2459 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2460 free_nfs_cb_data(data);
2461 return;
2462 }
2463
2464 data->cb(0, nfs, NULL, data->private_data);
2465 free_nfs_cb_data(data);
2466}
2467
2468static int nfs_symlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2469{
2470 struct nfs_symlink_data *symlink_data = data->continue_data;
2471
2472 if (rpc_nfs_symlink_async(nfs->rpc, nfs_symlink_cb, &data->fh, symlink_data->newpathobject, symlink_data->oldpath, data) != 0) {
2473 rpc_set_error(nfs->rpc, "RPC error: Failed to send SYMLINK call for %s", data->path);
2474 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2475 free_nfs_cb_data(data);
2476 return -1;
2477 }
2478 return 0;
2479}
2480
2481int nfs_symlink_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data)
2482{
2483 char *ptr;
2484 struct nfs_symlink_data *symlink_data;
2485
2486 symlink_data = malloc(sizeof(struct nfs_symlink_data));
2487 if (symlink_data == NULL) {
cbbf9d3e 2488 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for symlink data");
84004dbf
RS
2489 return -1;
2490 }
2491 bzero(symlink_data, sizeof(struct nfs_symlink_data));
2492
2493 symlink_data->oldpath = strdup(oldpath);
2494 if (symlink_data->oldpath == NULL) {
cbbf9d3e 2495 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for oldpath");
84004dbf 2496 free_nfs_symlink_data(symlink_data);
cbbf9d3e 2497 return -1;
84004dbf
RS
2498 }
2499
2500 symlink_data->newpathparent = strdup(newpath);
2501 if (symlink_data->newpathparent == NULL) {
cbbf9d3e 2502 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for new path");
84004dbf 2503 free_nfs_symlink_data(symlink_data);
cbbf9d3e 2504 return -1;
84004dbf
RS
2505 }
2506
2507 ptr = rindex(symlink_data->newpathparent, '/');
2508 if (ptr == NULL) {
cbbf9d3e 2509 rpc_set_error(nfs->rpc, "Invalid path %s", oldpath);
84004dbf 2510 free_nfs_symlink_data(symlink_data);
cbbf9d3e 2511 return -1;
84004dbf
RS
2512 }
2513 *ptr = 0;
2514 ptr++;
2515
2516 symlink_data->newpathobject = strdup(ptr);
2517 if (symlink_data->newpathobject == NULL) {
cbbf9d3e 2518 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for new path");
84004dbf 2519 free_nfs_symlink_data(symlink_data);
cbbf9d3e 2520 return -1;
84004dbf
RS
2521 }
2522
2523 if (nfs_lookuppath_async(nfs, symlink_data->newpathparent, cb, private_data, nfs_symlink_continue_internal, symlink_data, free_nfs_symlink_data, 0) != 0) {
cbbf9d3e
RS
2524 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
2525 return -1;
84004dbf
RS
2526 }
2527
2528 return 0;
2529}
2530
2531
2532
2533/*
2534 * Async rename()
2535 */
2536struct nfs_rename_data {
2537 char *oldpath;
2538 char *oldobject;
2539 struct nfs_fh3 olddir;
2540 char *newpath;
2541 char *newobject;
2542 struct nfs_fh3 newdir;
2543};
2544
2545static void free_nfs_rename_data(void *mem)
2546{
2547 struct nfs_rename_data *data = mem;
2548
2549 if (data->oldpath != NULL) {
2550 free(data->oldpath);
2551 }
2552 if (data->olddir.data.data_val != NULL) {
2553 free(data->olddir.data.data_val);
2554 }
2555 if (data->newpath != NULL) {
2556 free(data->newpath);
2557 }
2558 if (data->newdir.data.data_val != NULL) {
2559 free(data->newdir.data.data_val);
2560 }
2561 free(data);
2562}
2563
2564static void nfs_rename_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
2565{
2566 RENAME3res *res;
2567 struct nfs_cb_data *data = private_data;
2568 struct nfs_context *nfs = data->nfs;
2569 struct nfs_rename_data *rename_data = data->continue_data;
2570
2571 if (status == RPC_STATUS_ERROR) {
2572 data->cb(-EFAULT, nfs, command_data, data->private_data);
2573 free_nfs_cb_data(data);
2574 return;
2575 }
2576 if (status == RPC_STATUS_CANCEL) {
2577 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2578 free_nfs_cb_data(data);
2579 return;
2580 }
2581
2582 res = command_data;
2583 if (res->status != NFS3_OK) {
2584 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));
2585 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2586 free_nfs_cb_data(data);
2587 return;
2588 }
2589
2590 data->cb(0, nfs, NULL, data->private_data);
2591 free_nfs_cb_data(data);
2592}
2593
2594static int nfs_rename_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2595{
2596 struct nfs_rename_data *rename_data = data->continue_data;
2597
2598 /* steal the filehandle */
2599 rename_data->newdir.data.data_len = data->fh.data.data_len;
2600 rename_data->newdir.data.data_val = data->fh.data.data_val;
2601 data->fh.data.data_val = NULL;
2602
2603 if (rpc_nfs_rename_async(nfs->rpc, nfs_rename_cb, &rename_data->olddir, rename_data->oldobject, &rename_data->newdir, rename_data->newobject, data) != 0) {
2604 rpc_set_error(nfs->rpc, "RPC error: Failed to send RENAME call for %s", data->path);
2605 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2606 free_nfs_cb_data(data);
2607 return -1;
2608 }
2609 return 0;
2610}
2611
2612
2613static int nfs_rename_continue_1_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2614{
2615 struct nfs_rename_data *rename_data = data->continue_data;
2616
2617 /* steal the filehandle */
2618 rename_data->olddir.data.data_len = data->fh.data.data_len;
2619 rename_data->olddir.data.data_val = data->fh.data.data_val;
2620 data->fh.data.data_val = NULL;
2621
2622 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) {
2623 rpc_set_error(nfs->rpc, "RPC error: Failed to send LOOKUP call for %s", rename_data->newpath);
2624 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2625 free_nfs_cb_data(data);
2626 return -1;
2627 }
2628 data->continue_data = NULL;
2629 free_nfs_cb_data(data);
2630
2631 return 0;
2632}
2633
2634
2635int nfs_rename_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data)
2636{
2637 char *ptr;
2638 struct nfs_rename_data *rename_data;
2639
2640 rename_data = malloc(sizeof(struct nfs_rename_data));
2641 if (rename_data == NULL) {
cbbf9d3e 2642 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for rename data");
84004dbf
RS
2643 return -1;
2644 }
2645 bzero(rename_data, sizeof(struct nfs_rename_data));
2646
2647 rename_data->oldpath = strdup(oldpath);
2648 if (rename_data->oldpath == NULL) {
cbbf9d3e 2649 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for oldpath");
84004dbf 2650 free_nfs_rename_data(rename_data);
cbbf9d3e 2651 return -1;
84004dbf
RS
2652 }
2653 ptr = rindex(rename_data->oldpath, '/');
2654 if (ptr == NULL) {
cbbf9d3e 2655 rpc_set_error(nfs->rpc, "Invalid path %s", oldpath);
84004dbf 2656 free_nfs_rename_data(rename_data);
cbbf9d3e 2657 return -1;
84004dbf
RS
2658 }
2659 *ptr = 0;
2660 ptr++;
2661 rename_data->oldobject = ptr;
2662
2663
2664 rename_data->newpath = strdup(newpath);
2665 if (rename_data->newpath == NULL) {
cbbf9d3e 2666 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for newpath");
84004dbf 2667 free_nfs_rename_data(rename_data);
cbbf9d3e 2668 return -1;
84004dbf
RS
2669 }
2670 ptr = rindex(rename_data->newpath, '/');
2671 if (ptr == NULL) {
cbbf9d3e 2672 rpc_set_error(nfs->rpc, "Invalid path %s", newpath);
84004dbf 2673 free_nfs_rename_data(rename_data);
cbbf9d3e 2674 return -1;
84004dbf
RS
2675 }
2676 *ptr = 0;
2677 ptr++;
2678 rename_data->newobject = ptr;
2679
2680
2681 if (nfs_lookuppath_async(nfs, rename_data->oldpath, cb, private_data, nfs_rename_continue_1_internal, rename_data, free_nfs_rename_data, 0) != 0) {
cbbf9d3e
RS
2682 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
2683 return -1;
84004dbf
RS
2684 }
2685
2686 return 0;
2687}
2688
2689
2690/*
2691 * Async link()
2692 */
2693struct nfs_link_data {
2694 char *oldpath;
2695 struct nfs_fh3 oldfh;
2696 char *newpath;
2697 char *newobject;
2698 struct nfs_fh3 newdir;
2699};
2700
2701static void free_nfs_link_data(void *mem)
2702{
2703 struct nfs_link_data *data = mem;
2704
2705 if (data->oldpath != NULL) {
2706 free(data->oldpath);
2707 }
2708 if (data->oldfh.data.data_val != NULL) {
2709 free(data->oldfh.data.data_val);
2710 }
2711 if (data->newpath != NULL) {
2712 free(data->newpath);
2713 }
2714 if (data->newdir.data.data_val != NULL) {
2715 free(data->newdir.data.data_val);
2716 }
2717 free(data);
2718}
2719
2720static void nfs_link_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
2721{
2722 LINK3res *res;
2723 struct nfs_cb_data *data = private_data;
2724 struct nfs_context *nfs = data->nfs;
2725 struct nfs_link_data *link_data = data->continue_data;
2726
2727 if (status == RPC_STATUS_ERROR) {
2728 data->cb(-EFAULT, nfs, command_data, data->private_data);
2729 free_nfs_cb_data(data);
2730 return;
2731 }
2732 if (status == RPC_STATUS_CANCEL) {
2733 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2734 free_nfs_cb_data(data);
2735 return;
2736 }
2737
2738 res = command_data;
2739 if (res->status != NFS3_OK) {
2740 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));
2741 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2742 free_nfs_cb_data(data);
2743 return;
2744 }
2745
2746 data->cb(0, nfs, NULL, data->private_data);
2747 free_nfs_cb_data(data);
2748}
2749
2750static int nfs_link_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2751{
2752 struct nfs_link_data *link_data = data->continue_data;
2753
2754 /* steal the filehandle */
2755 link_data->newdir.data.data_len = data->fh.data.data_len;
2756 link_data->newdir.data.data_val = data->fh.data.data_val;
2757 data->fh.data.data_val = NULL;
2758
2759 if (rpc_nfs_link_async(nfs->rpc, nfs_link_cb, &link_data->oldfh, &link_data->newdir, link_data->newobject, data) != 0) {
2760 rpc_set_error(nfs->rpc, "RPC error: Failed to send LINK call for %s", data->path);
2761 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2762 free_nfs_cb_data(data);
2763 return -1;
2764 }
2765 return 0;
2766}
2767
2768
2769static int nfs_link_continue_1_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2770{
2771 struct nfs_link_data *link_data = data->continue_data;
2772
2773 /* steal the filehandle */
2774 link_data->oldfh.data.data_len = data->fh.data.data_len;
2775 link_data->oldfh.data.data_val = data->fh.data.data_val;
2776 data->fh.data.data_val = NULL;
2777
2778 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) {
2779 rpc_set_error(nfs->rpc, "RPC error: Failed to send LOOKUP call for %s", link_data->newpath);
2780 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2781 free_nfs_cb_data(data);
2782 return -1;
2783 }
2784 data->continue_data = NULL;
2785 free_nfs_cb_data(data);
2786
2787 return 0;
2788}
2789
2790
2791int nfs_link_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data)
2792{
2793 char *ptr;
2794 struct nfs_link_data *link_data;
2795
2796 link_data = malloc(sizeof(struct nfs_link_data));
2797 if (link_data == NULL) {
cbbf9d3e 2798 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for link data");
84004dbf
RS
2799 return -1;
2800 }
2801 bzero(link_data, sizeof(struct nfs_link_data));
2802
2803 link_data->oldpath = strdup(oldpath);
2804 if (link_data->oldpath == NULL) {
cbbf9d3e 2805 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for oldpath");
84004dbf 2806 free_nfs_link_data(link_data);
cbbf9d3e 2807 return -1;
84004dbf
RS
2808 }
2809
2810 link_data->newpath = strdup(newpath);
2811 if (link_data->newpath == NULL) {
cbbf9d3e 2812 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for newpath");
84004dbf 2813 free_nfs_link_data(link_data);
cbbf9d3e 2814 return -1;
84004dbf
RS
2815 }
2816 ptr = rindex(link_data->newpath, '/');
2817 if (ptr == NULL) {
cbbf9d3e 2818 rpc_set_error(nfs->rpc, "Invalid path %s", newpath);
84004dbf 2819 free_nfs_link_data(link_data);
cbbf9d3e 2820 return -1;
84004dbf
RS
2821 }
2822 *ptr = 0;
2823 ptr++;
2824 link_data->newobject = ptr;
2825
2826
2827 if (nfs_lookuppath_async(nfs, link_data->oldpath, cb, private_data, nfs_link_continue_1_internal, link_data, free_nfs_link_data, 0) != 0) {
cbbf9d3e
RS
2828 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
2829 return -1;
84004dbf
RS
2830 }
2831
2832 return 0;
2833}
2834
2835
2836//qqq replace later with lseek()
2837off_t nfs_get_current_offset(struct nfsfh *nfsfh)
2838{
2839 return nfsfh->offset;
2840}
2841
17ef62fa
RS
2842
2843
2844/*
2845 * Get the maximum supported READ3 size by the server
2846 */
2847size_t nfs_get_readmax(struct nfs_context *nfs)
2848{
2849 return nfs->readmax;
2850}
2851
2852/*
2853 * Get the maximum supported WRITE3 size by the server
2854 */
2855size_t nfs_get_writemax(struct nfs_context *nfs)
2856{
2857 return nfs->writemax;
2858}
1896d37b
RS
2859
2860void nfs_set_error(struct nfs_context *nfs, char *error_string, ...)
2861{
2862 va_list ap;
2863 char *str;
2864
2865 if (nfs->rpc->error_string != NULL) {
2866 free(nfs->rpc->error_string);
2867 }
2868 va_start(ap, error_string);
2869 vasprintf(&str, error_string, ap);
2870 nfs->rpc->error_string = str;
2871 va_end(ap);
2872}
7f0242ca
RS
2873
2874
2875
2876struct mount_cb_data {
2877 rpc_cb cb;
2878 void *private_data;
2879 char *server;
2880};
2881
2882static void free_mount_cb_data(struct mount_cb_data *data)
2883{
2884 if (data->server != NULL) {
2885 free(data->server);
2886 data->server = NULL;
2887 }
2888
2889 free(data);
2890}
2891
2892static void mount_export_5_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
2893{
2894 struct mount_cb_data *data = private_data;
2895
2896 if (status == RPC_STATUS_ERROR) {
2897 data->cb(rpc, -EFAULT, command_data, data->private_data);
2898 free_mount_cb_data(data);
2899 return;
2900 }
2901 if (status == RPC_STATUS_CANCEL) {
2902 data->cb(rpc, -EINTR, "Command was cancelled", data->private_data);
2903 free_mount_cb_data(data);
2904 return;
2905 }
2906
2907 data->cb(rpc, 0, command_data, data->private_data);
2908 if (rpc_disconnect(rpc, "normal disconnect") != 0) {
2909 rpc_set_error(rpc, "Failed to disconnect\n");
2910 }
2911 free_mount_cb_data(data);
2912}
2913
2914static void mount_export_4_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
2915{
2916 struct mount_cb_data *data = private_data;
2917
2918 if (status == RPC_STATUS_ERROR) {
2919 data->cb(rpc, -EFAULT, command_data, data->private_data);
2920 free_mount_cb_data(data);
2921 return;
2922 }
2923 if (status == RPC_STATUS_CANCEL) {
2924 data->cb(rpc, -EINTR, "Command was cancelled", data->private_data);
2925 free_mount_cb_data(data);
2926 return;
2927 }
2928
2929 if (rpc_mount_export_async(rpc, mount_export_5_cb, data) != 0) {
2930 data->cb(rpc, -ENOMEM, command_data, data->private_data);
2931 free_mount_cb_data(data);
2932 return;
2933 }
2934}
2935
2936static void mount_export_3_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
2937{
2938 struct mount_cb_data *data = private_data;
2939 uint32_t mount_port;
2940
2941 if (status == RPC_STATUS_ERROR) {
2942 data->cb(rpc, -EFAULT, command_data, data->private_data);
2943 free_mount_cb_data(data);
2944 return;
2945 }
2946 if (status == RPC_STATUS_CANCEL) {
2947 data->cb(rpc, -EINTR, "Command was cancelled", data->private_data);
2948 free_mount_cb_data(data);
2949 return;
2950 }
2951
2952 mount_port = *(uint32_t *)command_data;
2953 if (mount_port == 0) {
2954 rpc_set_error(rpc, "RPC error. Mount program is not available");
2955 data->cb(rpc, -ENOENT, command_data, data->private_data);
2956 free_mount_cb_data(data);
2957 return;
2958 }
2959
2960 rpc_disconnect(rpc, "normal disconnect");
2961 if (rpc_connect_async(rpc, data->server, mount_port, mount_export_4_cb, data) != 0) {
2962 data->cb(rpc, -ENOMEM, command_data, data->private_data);
2963 free_mount_cb_data(data);
2964 return;
2965 }
2966}
2967
2968static void mount_export_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
2969{
2970 struct mount_cb_data *data = private_data;
2971
2972 if (status == RPC_STATUS_ERROR) {
2973 data->cb(rpc, -EFAULT, command_data, data->private_data);
2974 free_mount_cb_data(data);
2975 return;
2976 }
2977 if (status == RPC_STATUS_CANCEL) {
2978 data->cb(rpc, -EINTR, "Command was cancelled", data->private_data);
2979 free_mount_cb_data(data);
2980 return;
2981 }
2982
2983 if (rpc_pmap_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, mount_export_3_cb, private_data) != 0) {
2984 data->cb(rpc, -ENOMEM, command_data, data->private_data);
2985 free_mount_cb_data(data);
2986 return;
2987 }
2988}
2989
2990static void mount_export_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
2991{
2992 struct mount_cb_data *data = private_data;
2993
2994 if (status == RPC_STATUS_ERROR) {
2995 data->cb(rpc, -EFAULT, command_data, data->private_data);
2996 free_mount_cb_data(data);
2997 return;
2998 }
2999 if (status == RPC_STATUS_CANCEL) {
3000 data->cb(rpc, -EINTR, "Command was cancelled", data->private_data);
3001 free_mount_cb_data(data);
3002 return;
3003 }
3004
3005 if (rpc_pmap_null_async(rpc, mount_export_2_cb, data) != 0) {
3006 data->cb(rpc, -ENOMEM, command_data, data->private_data);
3007 free_mount_cb_data(data);
3008 return;
3009 }
3010}
3011
3012int mount_getexports_async(struct rpc_context *rpc, const char *server, rpc_cb cb, void *private_data)
3013{
3014 struct mount_cb_data *data;
3015
3016 data = malloc(sizeof(struct mount_cb_data));
3017 if (data == NULL) {
3018 return -1;
3019 }
3020 bzero(data, sizeof(struct mount_cb_data));
3021 data->cb = cb;
3022 data->private_data = private_data;
3023 data->server = strdup(server);
3024 if (data->server == NULL) {
3025 free_mount_cb_data(data);
3026 return -1;
3027 }
3028 if (rpc_connect_async(rpc, data->server, 111, mount_export_1_cb, data) != 0) {
3029 free_mount_cb_data(data);
3030 return -1;
3031 }
3032
3033 return 0;
3034}
3035
df5af25f
RS
3036struct rpc_context *nfs_get_rpc_context(struct nfs_context *nfs)
3037{
3038 return nfs->rpc;
3039}
3040