Add a high-level async function to read the export list
[deb_libnfs.git] / lib / libnfs.c
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
21 #define _GNU_SOURCE
22 #include <stdio.h>
23 #include <stdarg.h>
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"
38 #include "libnfs-private.h"
39
40 struct nfsdir {
41 struct nfsdirent *entries;
42 struct nfsdirent *current;
43 };
44
45 struct nfsfh {
46 struct nfs_fh3 fh;
47 int is_sync;
48 off_t offset;
49 };
50
51 struct 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;
58 };
59
60 void 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
73 struct nfs_cb_data;
74 typedef int (*continue_func)(struct nfs_context *nfs, struct nfs_cb_data *data);
75
76 struct 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;
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
99 struct nfs_mcb_data {
100 struct nfs_cb_data *data;
101 off_t offset;
102 size_t count;
103 };
104
105 static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh);
106
107
108 void nfs_set_auth(struct nfs_context *nfs, struct AUTH *auth)
109 {
110 return rpc_set_auth(nfs->rpc, auth);
111 }
112
113 int nfs_get_fd(struct nfs_context *nfs)
114 {
115 return rpc_get_fd(nfs->rpc);
116 }
117
118 int nfs_which_events(struct nfs_context *nfs)
119 {
120 return rpc_which_events(nfs->rpc);
121 }
122
123 int nfs_service(struct nfs_context *nfs, int revents)
124 {
125 return rpc_service(nfs->rpc, revents);
126 }
127
128 char *nfs_get_error(struct nfs_context *nfs)
129 {
130 return rpc_get_error(nfs->rpc);
131 };
132
133 struct nfs_context *nfs_init_context(void)
134 {
135 struct nfs_context *nfs;
136
137 nfs = malloc(sizeof(struct nfs_context));
138 if (nfs == NULL) {
139 return NULL;
140 }
141 nfs->rpc = rpc_init_context();
142 if (nfs->rpc == NULL) {
143 free(nfs);
144 return NULL;
145 }
146
147 return nfs;
148 }
149
150 void 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
173 void 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
190 if (data->buffer != NULL) {
191 free(data->buffer);
192 data->buffer = NULL;
193 }
194
195 free(data);
196 }
197
198
199
200
201
202 static void nfs_mount_10_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
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
222 static void nfs_mount_9_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
223 {
224 struct nfs_cb_data *data = private_data;
225 struct nfs_context *nfs = data->nfs;
226 FSINFO3res *res = command_data;
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
239 nfs->readmax = res->FSINFO3res_u.resok.rtmax;
240 nfs->writemax = res->FSINFO3res_u.resok.wtmax;
241
242 if (rpc_nfs_getattr_async(rpc, nfs_mount_10_cb, &nfs->rootfh, data) != 0) {
243 data->cb(-ENOMEM, nfs, command_data, data->private_data);
244 free_nfs_cb_data(data);
245 return;
246 }
247 }
248
249 static 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
273 static 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
297 static 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
341 static 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
364 static 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
387 static 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
421 static 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
444 static 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 */
470 int 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) {
476 rpc_set_error(nfs->rpc, "out of memory. failed to allocate memory for nfs mount data");
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) {
487 rpc_set_error(nfs->rpc, "Failed to start connection");
488 free_nfs_cb_data(data);
489 return -1;
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 */
501 static 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
534 static 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
576 static int nfs_lookuppath_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data, continue_func continue_cb, void *continue_data, void (*free_continue_data)(void *), int continue_int)
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");
588 return -1;
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");
601 free_nfs_cb_data(data);
602 return -1;
603 }
604 data->path = data->saved_path;
605
606 if (nfs_lookup_path_async_internal(nfs, data, &nfs->rootfh) != 0) {
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 */
620 static 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
664 static 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
675 int 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) {
678 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
679 return -1;
680 }
681
682 return 0;
683 }
684
685
686
687
688
689 /*
690 * Async open()
691 */
692 static 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
765 static 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
788 int 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) {
791 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
792 return -1;
793 }
794
795 return 0;
796 }
797
798
799
800
801
802 /*
803 * Async pread()
804 */
805 static 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
835 static 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 {
860 memcpy(&data->buffer[mdata->offset], res->READ3res_u.resok.data.data_val, res->READ3res_u.resok.count);
861 if ((unsigned)data->max_offset < mdata->offset + res->READ3res_u.resok.count) {
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
873
874 if (data->error != 0) {
875 data->cb(-EFAULT, nfs, command_data, data->private_data);
876 free_nfs_cb_data(data);
877 free(mdata);
878 return;
879 }
880 if (data->cancel != 0) {
881 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
882 free_nfs_cb_data(data);
883 free(mdata);
884 return;
885 }
886
887 data->nfsfh->offset = data->max_offset;
888 data->cb(data->max_offset - data->start_offset, nfs, data->buffer, data->private_data);
889 free_nfs_cb_data(data);
890 free(mdata);
891 }
892
893 int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, size_t count, nfs_cb cb, void *private_data)
894 {
895 struct nfs_cb_data *data;
896
897 data = malloc(sizeof(struct nfs_cb_data));
898 if (data == NULL) {
899 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
900 return -1;
901 }
902 bzero(data, sizeof(struct nfs_cb_data));
903 data->nfs = nfs;
904 data->cb = cb;
905 data->private_data = private_data;
906 data->nfsfh = nfsfh;
907
908 nfsfh->offset = offset;
909
910 if (count <= nfs_get_readmax(nfs)) {
911 if (rpc_nfs_read_async(nfs->rpc, nfs_pread_cb, &nfsfh->fh, offset, count, data) != 0) {
912 rpc_set_error(nfs->rpc, "RPC error: Failed to send READ call for %s", data->path);
913 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
914 free_nfs_cb_data(data);
915 return -1;
916 }
917 return 0;
918 }
919
920 /* trying to read more than maximum server read size, we has to chop it up into smaller
921 * reads and collect into a reassembly buffer.
922 * we send all reads in parallell so that performance is still good.
923 */
924 data->start_offset = offset;
925
926 data->buffer = malloc(count);
927 if (data->buffer == NULL) {
928 rpc_set_error(nfs->rpc, "Out-Of-Memory: Failed to allocate reassembly buffer for %d bytes", (int)count);
929 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
930 free_nfs_cb_data(data);
931 return -1;
932 }
933
934 while (count > 0) {
935 size_t readcount = count;
936 struct nfs_mcb_data *mdata;
937
938 if (readcount > nfs_get_readmax(nfs)) {
939 readcount = nfs_get_readmax(nfs);
940 }
941
942 mdata = malloc(sizeof(struct nfs_mcb_data));
943 if (mdata == NULL) {
944 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_mcb_data structure");
945 return -1;
946 }
947 bzero(mdata, sizeof(struct nfs_mcb_data));
948 mdata->data = data;
949 mdata->offset = offset;
950 mdata->count = readcount;
951
952 if (rpc_nfs_read_async(nfs->rpc, nfs_pread_mcb, &nfsfh->fh, offset, readcount, mdata) != 0) {
953 rpc_set_error(nfs->rpc, "RPC error: Failed to send READ call for %s", data->path);
954 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
955 free(mdata);
956 return -1;
957 }
958
959 count -= readcount;
960 offset += readcount;
961 data->num_calls++;
962 }
963
964 return 0;
965 }
966
967 /*
968 * Async read()
969 */
970 int nfs_read_async(struct nfs_context *nfs, struct nfsfh *nfsfh, size_t count, nfs_cb cb, void *private_data)
971 {
972 return nfs_pread_async(nfs, nfsfh, nfsfh->offset, count, cb, private_data);
973 }
974
975
976
977 /*
978 * Async pwrite()
979 */
980 static void nfs_pwrite_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
981 {
982 struct nfs_cb_data *data = private_data;
983 struct nfs_context *nfs = data->nfs;
984 WRITE3res *res;
985
986 if (status == RPC_STATUS_ERROR) {
987 data->cb(-EFAULT, nfs, command_data, data->private_data);
988 free_nfs_cb_data(data);
989 return;
990 }
991 if (status == RPC_STATUS_CANCEL) {
992 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
993 free_nfs_cb_data(data);
994 return;
995 }
996
997 res = command_data;
998 if (res->status != NFS3_OK) {
999 rpc_set_error(nfs->rpc, "NFS: Write failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1000 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1001 free_nfs_cb_data(data);
1002 return;
1003 }
1004
1005 data->nfsfh->offset += res->WRITE3res_u.resok.count;
1006 data->cb(res->WRITE3res_u.resok.count, nfs, NULL, data->private_data);
1007 free_nfs_cb_data(data);
1008 }
1009
1010 int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, size_t count, char *buf, nfs_cb cb, void *private_data)
1011 {
1012 struct nfs_cb_data *data;
1013
1014 data = malloc(sizeof(struct nfs_cb_data));
1015 if (data == NULL) {
1016 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
1017 return -1;
1018 }
1019 bzero(data, sizeof(struct nfs_cb_data));
1020 data->nfs = nfs;
1021 data->cb = cb;
1022 data->private_data = private_data;
1023 data->nfsfh = nfsfh;
1024
1025 nfsfh->offset = offset;
1026 if (rpc_nfs_write_async(nfs->rpc, nfs_pwrite_cb, &nfsfh->fh, buf, offset, count, nfsfh->is_sync?FILE_SYNC:UNSTABLE, data) != 0) {
1027 rpc_set_error(nfs->rpc, "RPC error: Failed to send WRITE call for %s", data->path);
1028 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1029 free_nfs_cb_data(data);
1030 return -1;
1031 }
1032 return 0;
1033 }
1034
1035 /*
1036 * Async write()
1037 */
1038 int nfs_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, size_t count, char *buf, nfs_cb cb, void *private_data)
1039 {
1040 return nfs_pwrite_async(nfs, nfsfh, nfsfh->offset, count, buf, cb, private_data);
1041 }
1042
1043
1044
1045
1046 /*
1047 * close
1048 */
1049
1050 int nfs_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data)
1051 {
1052 if (nfsfh->fh.data.data_val != NULL){
1053 free(nfsfh->fh.data.data_val);
1054 nfsfh->fh.data.data_val = NULL;
1055 }
1056 free(nfsfh);
1057
1058 cb(0, nfs, NULL, private_data);
1059 return 0;
1060 };
1061
1062
1063
1064
1065
1066 /*
1067 * Async fstat()
1068 */
1069 int nfs_fstat_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data)
1070 {
1071 struct nfs_cb_data *data;
1072
1073 data = malloc(sizeof(struct nfs_cb_data));
1074 if (data == NULL) {
1075 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
1076 return -1;
1077 }
1078 bzero(data, sizeof(struct nfs_cb_data));
1079 data->nfs = nfs;
1080 data->cb = cb;
1081 data->private_data = private_data;
1082
1083 if (rpc_nfs_getattr_async(nfs->rpc, nfs_stat_1_cb, &nfsfh->fh, data) != 0) {
1084 rpc_set_error(nfs->rpc, "RPC error: Failed to send STAT GETATTR call for %s", data->path);
1085 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1086 free_nfs_cb_data(data);
1087 return -1;
1088 }
1089 return 0;
1090 }
1091
1092
1093
1094 /*
1095 * Async fsync()
1096 */
1097 static void nfs_fsync_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1098 {
1099 struct nfs_cb_data *data = private_data;
1100 struct nfs_context *nfs = data->nfs;
1101 COMMIT3res *res;
1102
1103 if (status == RPC_STATUS_ERROR) {
1104 data->cb(-EFAULT, nfs, command_data, data->private_data);
1105 free_nfs_cb_data(data);
1106 return;
1107 }
1108 if (status == RPC_STATUS_CANCEL) {
1109 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1110 free_nfs_cb_data(data);
1111 return;
1112 }
1113
1114 res = command_data;
1115 if (res->status != NFS3_OK) {
1116 rpc_set_error(nfs->rpc, "NFS: Commit failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1117 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1118 free_nfs_cb_data(data);
1119 return;
1120 }
1121
1122 data->cb(0, nfs, NULL, data->private_data);
1123 free_nfs_cb_data(data);
1124 }
1125
1126 int nfs_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data)
1127 {
1128 struct nfs_cb_data *data;
1129
1130 data = malloc(sizeof(struct nfs_cb_data));
1131 if (data == NULL) {
1132 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
1133 return -1;
1134 }
1135 bzero(data, sizeof(struct nfs_cb_data));
1136 data->nfs = nfs;
1137 data->cb = cb;
1138 data->private_data = private_data;
1139
1140 if (rpc_nfs_commit_async(nfs->rpc, nfs_fsync_cb, &nfsfh->fh, data) != 0) {
1141 rpc_set_error(nfs->rpc, "RPC error: Failed to send COMMIT call for %s", data->path);
1142 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1143 free_nfs_cb_data(data);
1144 return -1;
1145 }
1146 return 0;
1147 }
1148
1149
1150
1151
1152 /*
1153 * Async ftruncate()
1154 */
1155 static void nfs_ftruncate_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1156 {
1157 struct nfs_cb_data *data = private_data;
1158 struct nfs_context *nfs = data->nfs;
1159 SETATTR3res *res;
1160
1161 if (status == RPC_STATUS_ERROR) {
1162 data->cb(-EFAULT, nfs, command_data, data->private_data);
1163 free_nfs_cb_data(data);
1164 return;
1165 }
1166 if (status == RPC_STATUS_CANCEL) {
1167 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1168 free_nfs_cb_data(data);
1169 return;
1170 }
1171
1172 res = command_data;
1173 if (res->status != NFS3_OK) {
1174 rpc_set_error(nfs->rpc, "NFS: Setattr failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1175 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1176 free_nfs_cb_data(data);
1177 return;
1178 }
1179
1180 data->cb(0, nfs, NULL, data->private_data);
1181 free_nfs_cb_data(data);
1182 }
1183
1184 int nfs_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t length, nfs_cb cb, void *private_data)
1185 {
1186 struct nfs_cb_data *data;
1187 SETATTR3args args;
1188
1189 data = malloc(sizeof(struct nfs_cb_data));
1190 if (data == NULL) {
1191 rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
1192 return -1;
1193 }
1194 bzero(data, sizeof(struct nfs_cb_data));
1195 data->nfs = nfs;
1196 data->cb = cb;
1197 data->private_data = private_data;
1198
1199 bzero(&args, sizeof(SETATTR3args));
1200 args.object.data.data_len = nfsfh->fh.data.data_len;
1201 args.object.data.data_val = nfsfh->fh.data.data_val;
1202 args.new_attributes.size.set_it = 1;
1203 args.new_attributes.size.set_size3_u.size = length;
1204
1205 if (rpc_nfs_setattr_async(nfs->rpc, nfs_ftruncate_cb, &args, data) != 0) {
1206 rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
1207 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1208 free_nfs_cb_data(data);
1209 return -1;
1210 }
1211 return 0;
1212 }
1213
1214
1215 /*
1216 * Async truncate()
1217 */
1218 static int nfs_truncate_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1219 {
1220 off_t offset = data->continue_int;
1221 struct nfsfh nfsfh;
1222
1223 nfsfh.fh.data.data_val = data->fh.data.data_val;
1224 nfsfh.fh.data.data_len = data->fh.data.data_len;
1225
1226 if (nfs_ftruncate_async(nfs, &nfsfh, offset, data->cb, data->private_data) != 0) {
1227 rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
1228 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1229 free_nfs_cb_data(data);
1230 return -1;
1231 }
1232 free_nfs_cb_data(data);
1233 return 0;
1234 }
1235
1236 int nfs_truncate_async(struct nfs_context *nfs, const char *path, off_t length, nfs_cb cb, void *private_data)
1237 {
1238 off_t offset;
1239
1240 offset = length;
1241
1242 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_truncate_continue_internal, NULL, NULL, offset) != 0) {
1243 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1244 return -1;
1245 }
1246
1247 return 0;
1248 }
1249
1250
1251
1252
1253 /*
1254 * Async mkdir()
1255 */
1256 static void nfs_mkdir_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1257 {
1258 MKDIR3res *res;
1259 struct nfs_cb_data *data = private_data;
1260 struct nfs_context *nfs = data->nfs;
1261 char *str = data->continue_data;
1262
1263 str = &str[strlen(str) + 1];
1264
1265 if (status == RPC_STATUS_ERROR) {
1266 data->cb(-EFAULT, nfs, command_data, data->private_data);
1267 free_nfs_cb_data(data);
1268 return;
1269 }
1270 if (status == RPC_STATUS_CANCEL) {
1271 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1272 free_nfs_cb_data(data);
1273 return;
1274 }
1275
1276 res = command_data;
1277 if (res->status != NFS3_OK) {
1278 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));
1279 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1280 free_nfs_cb_data(data);
1281 return;
1282 }
1283
1284 data->cb(0, nfs, NULL, data->private_data);
1285 free_nfs_cb_data(data);
1286 }
1287
1288 static int nfs_mkdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1289 {
1290 char *str = data->continue_data;
1291
1292 str = &str[strlen(str) + 1];
1293
1294 if (rpc_nfs_mkdir_async(nfs->rpc, nfs_mkdir_cb, &data->fh, str, data) != 0) {
1295 rpc_set_error(nfs->rpc, "RPC error: Failed to send MKDIR call for %s", data->path);
1296 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1297 free_nfs_cb_data(data);
1298 return -1;
1299 }
1300 return 0;
1301 }
1302
1303 int nfs_mkdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
1304 {
1305 char *new_path;
1306 char *ptr;
1307
1308 new_path = strdup(path);
1309 if (new_path == NULL) {
1310 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path");
1311 return -1;
1312 }
1313
1314 ptr = rindex(new_path, '/');
1315 if (ptr == NULL) {
1316 rpc_set_error(nfs->rpc, "Invalid path %s", path);
1317 return -1;
1318 }
1319 *ptr = 0;
1320
1321 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1322 if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_mkdir_continue_internal, new_path, free, 0) != 0) {
1323 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path component");
1324 return -1;
1325 }
1326
1327 return 0;
1328 }
1329
1330
1331
1332
1333
1334 /*
1335 * Async rmdir()
1336 */
1337 static void nfs_rmdir_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1338 {
1339 RMDIR3res *res;
1340 struct nfs_cb_data *data = private_data;
1341 struct nfs_context *nfs = data->nfs;
1342 char *str = data->continue_data;
1343
1344 str = &str[strlen(str) + 1];
1345
1346 if (status == RPC_STATUS_ERROR) {
1347 data->cb(-EFAULT, nfs, command_data, data->private_data);
1348 free_nfs_cb_data(data);
1349 return;
1350 }
1351 if (status == RPC_STATUS_CANCEL) {
1352 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1353 free_nfs_cb_data(data);
1354 return;
1355 }
1356
1357 res = command_data;
1358 if (res->status != NFS3_OK) {
1359 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));
1360 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1361 free_nfs_cb_data(data);
1362 return;
1363 }
1364
1365 data->cb(0, nfs, NULL, data->private_data);
1366 free_nfs_cb_data(data);
1367 }
1368
1369 static int nfs_rmdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1370 {
1371 char *str = data->continue_data;
1372
1373 str = &str[strlen(str) + 1];
1374
1375 if (rpc_nfs_rmdir_async(nfs->rpc, nfs_rmdir_cb, &data->fh, str, data) != 0) {
1376 rpc_set_error(nfs->rpc, "RPC error: Failed to send RMDIR call for %s", data->path);
1377 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1378 free_nfs_cb_data(data);
1379 return -1;
1380 }
1381 return 0;
1382 }
1383
1384 int nfs_rmdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
1385 {
1386 char *new_path;
1387 char *ptr;
1388
1389 new_path = strdup(path);
1390 if (new_path == NULL) {
1391 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path");
1392 return -1;
1393 }
1394
1395 ptr = rindex(new_path, '/');
1396 if (ptr == NULL) {
1397 rpc_set_error(nfs->rpc, "Invalid path %s", path);
1398 return -1;
1399 }
1400 *ptr = 0;
1401
1402 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1403 if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_rmdir_continue_internal, new_path, free, 0) != 0) {
1404 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1405 return -1;
1406 }
1407
1408 return 0;
1409 }
1410
1411
1412
1413
1414 /*
1415 * Async creat()
1416 */
1417 static void nfs_create_2_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1418 {
1419 LOOKUP3res *res;
1420 struct nfs_cb_data *data = private_data;
1421 struct nfs_context *nfs = data->nfs;
1422 struct nfsfh *nfsfh;
1423 char *str = data->continue_data;
1424
1425 if (status == RPC_STATUS_ERROR) {
1426 data->cb(-EFAULT, nfs, command_data, data->private_data);
1427 free_nfs_cb_data(data);
1428 return;
1429 }
1430 if (status == RPC_STATUS_CANCEL) {
1431 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1432 free_nfs_cb_data(data);
1433 return;
1434 }
1435
1436 str = &str[strlen(str) + 1];
1437 res = command_data;
1438 if (res->status != NFS3_OK) {
1439 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));
1440 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1441
1442 return;
1443 }
1444
1445 nfsfh = malloc(sizeof(struct nfsfh));
1446 if (nfsfh == NULL) {
1447 rpc_set_error(nfs->rpc, "NFS: Failed to allocate nfsfh structure");
1448 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1449 free_nfs_cb_data(data);
1450 return;
1451 }
1452 bzero(nfsfh, sizeof(struct nfsfh));
1453
1454 /* steal the filehandle */
1455 nfsfh->fh.data.data_len = data->fh.data.data_len;
1456 nfsfh->fh.data.data_val = data->fh.data.data_val;
1457 data->fh.data.data_val = NULL;
1458
1459 data->cb(0, nfs, nfsfh, data->private_data);
1460 free_nfs_cb_data(data);
1461 }
1462
1463
1464
1465 static void nfs_creat_1_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1466 {
1467 CREATE3res *res;
1468 struct nfs_cb_data *data = private_data;
1469 struct nfs_context *nfs = data->nfs;
1470 char *str = data->continue_data;
1471
1472 if (status == RPC_STATUS_ERROR) {
1473 data->cb(-EFAULT, nfs, command_data, data->private_data);
1474 free_nfs_cb_data(data);
1475 return;
1476 }
1477 if (status == RPC_STATUS_CANCEL) {
1478 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1479 free_nfs_cb_data(data);
1480 return;
1481 }
1482
1483 str = &str[strlen(str) + 1];
1484 res = command_data;
1485 if (res->status != NFS3_OK) {
1486 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));
1487 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1488
1489 return;
1490 }
1491
1492 if (rpc_nfs_lookup_async(nfs->rpc, nfs_create_2_cb, &data->fh, str, data) != 0) {
1493 rpc_set_error(nfs->rpc, "RPC error: Failed to send lookup call for %s/%s", data->saved_path, str);
1494 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1495 free_nfs_cb_data(data);
1496 return;
1497 }
1498 return;
1499 }
1500
1501 static int nfs_creat_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1502 {
1503 char *str = data->continue_data;
1504
1505 str = &str[strlen(str) + 1];
1506
1507 if (rpc_nfs_create_async(nfs->rpc, nfs_creat_1_cb, &data->fh, str, data->continue_int, data) != 0) {
1508 rpc_set_error(nfs->rpc, "RPC error: Failed to send CREATE call for %s/%s", data->path, str);
1509 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1510 free_nfs_cb_data(data);
1511 return -1;
1512 }
1513 return 0;
1514 }
1515
1516 int nfs_creat_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data)
1517 {
1518 char *new_path;
1519 char *ptr;
1520
1521 new_path = strdup(path);
1522 if (new_path == NULL) {
1523 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path");
1524 return -1;
1525 }
1526
1527 ptr = rindex(new_path, '/');
1528 if (ptr == NULL) {
1529 rpc_set_error(nfs->rpc, "Invalid path %s", path);
1530 return -1;
1531 }
1532 *ptr = 0;
1533
1534 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1535 if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_creat_continue_internal, new_path, free, mode) != 0) {
1536 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1537 return -1;
1538 }
1539
1540 return 0;
1541 }
1542
1543
1544
1545
1546 /*
1547 * Async unlink()
1548 */
1549 static void nfs_unlink_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1550 {
1551 REMOVE3res *res;
1552 struct nfs_cb_data *data = private_data;
1553 struct nfs_context *nfs = data->nfs;
1554 char *str = data->continue_data;
1555
1556 str = &str[strlen(str) + 1];
1557
1558 if (status == RPC_STATUS_ERROR) {
1559 data->cb(-EFAULT, nfs, command_data, data->private_data);
1560 free_nfs_cb_data(data);
1561 return;
1562 }
1563 if (status == RPC_STATUS_CANCEL) {
1564 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1565 free_nfs_cb_data(data);
1566 return;
1567 }
1568
1569 res = command_data;
1570 if (res->status != NFS3_OK) {
1571 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));
1572 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1573 free_nfs_cb_data(data);
1574 return;
1575 }
1576
1577 data->cb(0, nfs, NULL, data->private_data);
1578 free_nfs_cb_data(data);
1579 }
1580
1581 static int nfs_unlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1582 {
1583 char *str = data->continue_data;
1584
1585 str = &str[strlen(str) + 1];
1586
1587 if (rpc_nfs_remove_async(nfs->rpc, nfs_unlink_cb, &data->fh, str, data) != 0) {
1588 rpc_set_error(nfs->rpc, "RPC error: Failed to send REMOVE call for %s", data->path);
1589 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1590 free_nfs_cb_data(data);
1591 return -1;
1592 }
1593 return 0;
1594 }
1595
1596 int nfs_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
1597 {
1598 char *new_path;
1599 char *ptr;
1600
1601 new_path = strdup(path);
1602 if (new_path == NULL) {
1603 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path");
1604 return -1;
1605 }
1606
1607 ptr = rindex(new_path, '/');
1608 if (ptr == NULL) {
1609 rpc_set_error(nfs->rpc, "Invalid path %s", path);
1610 return -1;
1611 }
1612 *ptr = 0;
1613
1614 /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */
1615 if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_unlink_continue_internal, new_path, free, 0) != 0) {
1616 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1617 return -1;
1618 }
1619
1620 return 0;
1621 }
1622
1623
1624
1625
1626
1627 /*
1628 * Async opendir()
1629 */
1630 static void nfs_opendir_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1631 {
1632 READDIR3res *res;
1633 struct nfs_cb_data *data = private_data;
1634 struct nfs_context *nfs = data->nfs;
1635 struct nfsdir *nfsdir = data->continue_data;;
1636 struct entry3 *entry;
1637 uint64_t cookie;
1638
1639 if (status == RPC_STATUS_ERROR) {
1640 data->cb(-EFAULT, nfs, command_data, data->private_data);
1641 nfs_free_nfsdir(nfsdir);
1642 data->continue_data = NULL;
1643 free_nfs_cb_data(data);
1644 return;
1645 }
1646 if (status == RPC_STATUS_CANCEL) {
1647 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1648 nfs_free_nfsdir(nfsdir);
1649 data->continue_data = NULL;
1650 free_nfs_cb_data(data);
1651 return;
1652 }
1653
1654 res = command_data;
1655 if (res->status != NFS3_OK) {
1656 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));
1657 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1658 nfs_free_nfsdir(nfsdir);
1659 data->continue_data = NULL;
1660 free_nfs_cb_data(data);
1661 return;
1662 }
1663
1664 entry =res->READDIR3res_u.resok.reply.entries;
1665 while (entry != NULL) {
1666 struct nfsdirent *nfsdirent;
1667
1668 nfsdirent = malloc(sizeof(struct nfsdirent));
1669 if (nfsdirent == NULL) {
1670 data->cb(-ENOMEM, nfs, "Failed to allocate dirent", data->private_data);
1671 nfs_free_nfsdir(nfsdir);
1672 data->continue_data = NULL;
1673 free_nfs_cb_data(data);
1674 return;
1675 }
1676 bzero(nfsdirent, sizeof(struct nfsdirent));
1677 nfsdirent->name = strdup(entry->name);
1678 if (nfsdirent->name == NULL) {
1679 data->cb(-ENOMEM, nfs, "Failed to allocate dirent->name", data->private_data);
1680 nfs_free_nfsdir(nfsdir);
1681 data->continue_data = NULL;
1682 free_nfs_cb_data(data);
1683 return;
1684 }
1685 nfsdirent->inode = entry->fileid;
1686 nfsdirent->next = nfsdir->entries;
1687 nfsdir->entries = nfsdirent;
1688
1689 cookie = entry->cookie;
1690 entry = entry->nextentry;
1691 }
1692
1693 if (res->READDIR3res_u.resok.reply.eof == 0) {
1694 if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir_cb, &data->fh, cookie, res->READDIR3res_u.resok.cookieverf, 20000, data) != 0) {
1695 rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR call for %s", data->path);
1696 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1697 nfs_free_nfsdir(nfsdir);
1698 data->continue_data = NULL;
1699 free_nfs_cb_data(data);
1700 return;
1701 }
1702 return;
1703 }
1704
1705 /* steal the dirhandle */
1706 data->continue_data = NULL;
1707 nfsdir->current = nfsdir->entries;
1708
1709 data->cb(0, nfs, nfsdir, data->private_data);
1710 free_nfs_cb_data(data);
1711 }
1712
1713 static int nfs_opendir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1714 {
1715 cookieverf3 cv;
1716
1717 bzero(cv, sizeof(cookieverf3));
1718 if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir_cb, &data->fh, 0, (char *)&cv, 20000, data) != 0) {
1719 rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR call for %s", data->path);
1720 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1721 free_nfs_cb_data(data);
1722 return -1;
1723 }
1724 return 0;
1725 }
1726
1727 int nfs_opendir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
1728 {
1729 struct nfsdir *nfsdir;
1730
1731 nfsdir = malloc(sizeof(struct nfsdir));
1732 if (nfsdir == NULL) {
1733 rpc_set_error(nfs->rpc, "failed to allocate buffer for nfsdir");
1734 return -1;
1735 }
1736 bzero(nfsdir, sizeof(struct nfsdir));
1737
1738 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_opendir_continue_internal, nfsdir, free, 0) != 0) {
1739 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1740 return -1;
1741 }
1742
1743 return 0;
1744 }
1745
1746
1747 struct nfsdirent *nfs_readdir(struct nfs_context *nfs _U_, struct nfsdir *nfsdir)
1748 {
1749 struct nfsdirent *nfsdirent = nfsdir->current;
1750
1751 if (nfsdir->current != NULL) {
1752 nfsdir->current = nfsdir->current->next;
1753 }
1754 return nfsdirent;
1755 }
1756
1757
1758 void nfs_closedir(struct nfs_context *nfs _U_, struct nfsdir *nfsdir)
1759 {
1760 nfs_free_nfsdir(nfsdir);
1761 }
1762
1763
1764
1765
1766
1767
1768
1769 /*
1770 * Async lseek()
1771 */
1772 struct lseek_cb_data {
1773 struct nfs_context *nfs;
1774 struct nfsfh *nfsfh;
1775 off_t offset;
1776 nfs_cb cb;
1777 void *private_data;
1778 };
1779
1780 static void nfs_lseek_1_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1781 {
1782 GETATTR3res *res;
1783 struct lseek_cb_data *data = private_data;
1784 struct nfs_context *nfs = data->nfs;
1785
1786 if (status == RPC_STATUS_ERROR) {
1787 data->cb(-EFAULT, nfs, command_data, data->private_data);
1788 free(data);
1789 return;
1790 }
1791 if (status == RPC_STATUS_CANCEL) {
1792 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1793 free(data);
1794 return;
1795 }
1796
1797 res = command_data;
1798 if (res->status != NFS3_OK) {
1799 rpc_set_error(nfs->rpc, "NFS: GETATTR failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1800 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1801 free(data);
1802 return;
1803 }
1804
1805 data->nfsfh->offset = data->offset + res->GETATTR3res_u.resok.obj_attributes.size;
1806 data->cb(0, nfs, &data->nfsfh->offset, data->private_data);
1807 free(data);
1808 }
1809
1810 int nfs_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, int whence, nfs_cb cb, void *private_data)
1811 {
1812 struct lseek_cb_data *data;
1813
1814 if (whence == SEEK_SET) {
1815 nfsfh->offset = offset;
1816 cb(0, nfs, &nfsfh->offset, private_data);
1817 return 0;
1818 }
1819 if (whence == SEEK_CUR) {
1820 nfsfh->offset += offset;
1821 cb(0, nfs, &nfsfh->offset, private_data);
1822 return 0;
1823 }
1824
1825 data = malloc(sizeof(struct lseek_cb_data));
1826 if (data == NULL) {
1827 rpc_set_error(nfs->rpc, "Out Of Memory: Failed to malloc lseek cb data");
1828 return -1;
1829 }
1830
1831 data->nfs = nfs;
1832 data->nfsfh = nfsfh;
1833 data->offset = offset;
1834 data->cb = cb;
1835 data->private_data = private_data;
1836
1837 if (rpc_nfs_getattr_async(nfs->rpc, nfs_lseek_1_cb, &nfsfh->fh, data) != 0) {
1838 rpc_set_error(nfs->rpc, "RPC error: Failed to send LSEEK GETATTR call");
1839 free(data);
1840 return -1;
1841 }
1842 return 0;
1843 }
1844
1845
1846
1847
1848 /*
1849 * Async statvfs()
1850 */
1851 static void nfs_statvfs_1_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1852 {
1853 FSSTAT3res *res;
1854 struct nfs_cb_data *data = private_data;
1855 struct nfs_context *nfs = data->nfs;
1856 struct statvfs svfs;
1857
1858 if (status == RPC_STATUS_ERROR) {
1859 data->cb(-EFAULT, nfs, command_data, data->private_data);
1860 free_nfs_cb_data(data);
1861 return;
1862 }
1863 if (status == RPC_STATUS_CANCEL) {
1864 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1865 free_nfs_cb_data(data);
1866 return;
1867 }
1868
1869 res = command_data;
1870 if (res->status != NFS3_OK) {
1871 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));
1872 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1873 free_nfs_cb_data(data);
1874 return;
1875 }
1876
1877 svfs.f_bsize = 4096;
1878 svfs.f_frsize = 4096;
1879 svfs.f_blocks = res->FSSTAT3res_u.resok.tbytes/4096;
1880 svfs.f_bfree = res->FSSTAT3res_u.resok.fbytes/4096;
1881 svfs.f_bavail = res->FSSTAT3res_u.resok.abytes/4096;
1882 svfs.f_files = res->FSSTAT3res_u.resok.tfiles;
1883 svfs.f_ffree = res->FSSTAT3res_u.resok.ffiles;
1884 svfs.f_favail = res->FSSTAT3res_u.resok.afiles;
1885 svfs.f_fsid = 0;
1886 svfs.f_flag = 0;
1887 svfs.f_namemax = 256;
1888
1889 data->cb(0, nfs, &svfs, data->private_data);
1890 free_nfs_cb_data(data);
1891 }
1892
1893 static int nfs_statvfs_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1894 {
1895 if (rpc_nfs_fsstat_async(nfs->rpc, nfs_statvfs_1_cb, &data->fh, data) != 0) {
1896 rpc_set_error(nfs->rpc, "RPC error: Failed to send FSSTAT call for %s", data->path);
1897 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1898 free_nfs_cb_data(data);
1899 return -1;
1900 }
1901 return 0;
1902 }
1903
1904 int nfs_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
1905 {
1906 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_statvfs_continue_internal, NULL, NULL, 0) != 0) {
1907 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1908 return -1;
1909 }
1910
1911 return 0;
1912 }
1913
1914
1915
1916
1917 /*
1918 * Async readlink()
1919 */
1920 static void nfs_readlink_1_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1921 {
1922 READLINK3res *res;
1923 struct nfs_cb_data *data = private_data;
1924 struct nfs_context *nfs = data->nfs;
1925
1926 if (status == RPC_STATUS_ERROR) {
1927 data->cb(-EFAULT, nfs, command_data, data->private_data);
1928 free_nfs_cb_data(data);
1929 return;
1930 }
1931 if (status == RPC_STATUS_CANCEL) {
1932 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1933 free_nfs_cb_data(data);
1934 return;
1935 }
1936
1937 res = command_data;
1938 if (res->status != NFS3_OK) {
1939 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));
1940 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1941 free_nfs_cb_data(data);
1942 return;
1943 }
1944
1945
1946 data->cb(0, nfs, res->READLINK3res_u.resok.data, data->private_data);
1947 free_nfs_cb_data(data);
1948 }
1949
1950 static int nfs_readlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
1951 {
1952 if (rpc_nfs_readlink_async(nfs->rpc, nfs_readlink_1_cb, &data->fh, data) != 0) {
1953 rpc_set_error(nfs->rpc, "RPC error: Failed to send READLINK call for %s", data->path);
1954 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
1955 free_nfs_cb_data(data);
1956 return -1;
1957 }
1958 return 0;
1959 }
1960
1961 int nfs_readlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
1962 {
1963 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_readlink_continue_internal, NULL, NULL, 0) != 0) {
1964 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
1965 return -1;
1966 }
1967
1968 return 0;
1969 }
1970
1971
1972
1973
1974 /*
1975 * Async chmod()
1976 */
1977 static void nfs_chmod_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
1978 {
1979 struct nfs_cb_data *data = private_data;
1980 struct nfs_context *nfs = data->nfs;
1981 SETATTR3res *res;
1982
1983 if (status == RPC_STATUS_ERROR) {
1984 data->cb(-EFAULT, nfs, command_data, data->private_data);
1985 free_nfs_cb_data(data);
1986 return;
1987 }
1988 if (status == RPC_STATUS_CANCEL) {
1989 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
1990 free_nfs_cb_data(data);
1991 return;
1992 }
1993
1994 res = command_data;
1995 if (res->status != NFS3_OK) {
1996 rpc_set_error(nfs->rpc, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
1997 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
1998 free_nfs_cb_data(data);
1999 return;
2000 }
2001
2002 data->cb(0, nfs, NULL, data->private_data);
2003 free_nfs_cb_data(data);
2004 }
2005
2006 static int nfs_chmod_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2007 {
2008 SETATTR3args args;
2009
2010 bzero(&args, sizeof(SETATTR3args));
2011 args.object.data.data_len = data->fh.data.data_len;
2012 args.object.data.data_val = data->fh.data.data_val;
2013 args.new_attributes.mode.set_it = 1;
2014 args.new_attributes.mode.set_mode3_u.mode = data->continue_int;
2015
2016 if (rpc_nfs_setattr_async(nfs->rpc, nfs_chmod_cb, &args, data) != 0) {
2017 rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
2018 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2019 free_nfs_cb_data(data);
2020 return -1;
2021 }
2022 return 0;
2023 }
2024
2025
2026 int nfs_chmod_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data)
2027 {
2028 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_chmod_continue_internal, NULL, NULL, mode) != 0) {
2029 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
2030 return -1;
2031 }
2032
2033 return 0;
2034 }
2035
2036 /*
2037 * Async fchmod()
2038 */
2039 int nfs_fchmod_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode, nfs_cb cb, void *private_data)
2040 {
2041 struct nfs_cb_data *data;
2042
2043 data = malloc(sizeof(struct nfs_cb_data));
2044 if (data == NULL) {
2045 rpc_set_error(nfs->rpc, "out of memory. failed to allocate memory for nfs mount data");
2046 return -1;
2047 }
2048 bzero(data, sizeof(struct nfs_cb_data));
2049 data->nfs = nfs;
2050 data->cb = cb;
2051 data->private_data = private_data;
2052 data->continue_int = mode;
2053 data->fh.data.data_len = nfsfh->fh.data.data_len;
2054 data->fh.data.data_val = malloc(data->fh.data.data_len);
2055 if (data->fh.data.data_val == NULL) {
2056 rpc_set_error(nfs->rpc, "Out of memory: Failed to allocate fh");
2057 free_nfs_cb_data(data);
2058 return -1;
2059 }
2060 memcpy(data->fh.data.data_val, nfsfh->fh.data.data_val, data->fh.data.data_len);
2061
2062 if (nfs_chmod_continue_internal(nfs, data) != 0) {
2063 free_nfs_cb_data(data);
2064 return -1;
2065 }
2066
2067 return 0;
2068 }
2069
2070
2071
2072 /*
2073 * Async chown()
2074 */
2075 static void nfs_chown_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
2076 {
2077 struct nfs_cb_data *data = private_data;
2078 struct nfs_context *nfs = data->nfs;
2079 SETATTR3res *res;
2080
2081 if (status == RPC_STATUS_ERROR) {
2082 data->cb(-EFAULT, nfs, command_data, data->private_data);
2083 free_nfs_cb_data(data);
2084 return;
2085 }
2086 if (status == RPC_STATUS_CANCEL) {
2087 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2088 free_nfs_cb_data(data);
2089 return;
2090 }
2091
2092 res = command_data;
2093 if (res->status != NFS3_OK) {
2094 rpc_set_error(nfs->rpc, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
2095 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2096 free_nfs_cb_data(data);
2097 return;
2098 }
2099
2100 data->cb(0, nfs, NULL, data->private_data);
2101 free_nfs_cb_data(data);
2102 }
2103
2104 struct nfs_chown_data {
2105 uid_t uid;
2106 gid_t gid;
2107 };
2108
2109 static int nfs_chown_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2110 {
2111 SETATTR3args args;
2112 struct nfs_chown_data *chown_data = data->continue_data;
2113
2114 bzero(&args, sizeof(SETATTR3args));
2115 args.object.data.data_len = data->fh.data.data_len;
2116 args.object.data.data_val = data->fh.data.data_val;
2117 if (chown_data->uid != (uid_t)-1) {
2118 args.new_attributes.uid.set_it = 1;
2119 args.new_attributes.uid.set_uid3_u.uid = chown_data->uid;
2120 }
2121 if (chown_data->gid != (gid_t)-1) {
2122 args.new_attributes.gid.set_it = 1;
2123 args.new_attributes.gid.set_gid3_u.gid = chown_data->gid;
2124 }
2125
2126 if (rpc_nfs_setattr_async(nfs->rpc, nfs_chown_cb, &args, data) != 0) {
2127 rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
2128 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2129 free_nfs_cb_data(data);
2130 return -1;
2131 }
2132 return 0;
2133 }
2134
2135
2136 int nfs_chown_async(struct nfs_context *nfs, const char *path, int uid, int gid, nfs_cb cb, void *private_data)
2137 {
2138 struct nfs_chown_data *chown_data;
2139
2140 chown_data = malloc(sizeof(struct nfs_chown_data));
2141 if (chown_data == NULL) {
2142 rpc_set_error(nfs->rpc, "Failed to allocate memory for chown data structure");
2143 return -1;
2144 }
2145
2146 chown_data->uid = uid;
2147 chown_data->gid = gid;
2148
2149 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_chown_continue_internal, chown_data, free, 0) != 0) {
2150 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
2151 return -1;
2152 }
2153
2154 return 0;
2155 }
2156
2157
2158 /*
2159 * Async fchown()
2160 */
2161 int nfs_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid, nfs_cb cb, void *private_data)
2162 {
2163 struct nfs_cb_data *data;
2164 struct nfs_chown_data *chown_data;
2165
2166 chown_data = malloc(sizeof(struct nfs_chown_data));
2167 if (chown_data == NULL) {
2168 rpc_set_error(nfs->rpc, "Failed to allocate memory for chown data structure");
2169 return -1;
2170 }
2171
2172 chown_data->uid = uid;
2173 chown_data->gid = gid;
2174
2175
2176 data = malloc(sizeof(struct nfs_cb_data));
2177 if (data == NULL) {
2178 rpc_set_error(nfs->rpc, "out of memory. failed to allocate memory for fchown data");
2179 return -1;
2180 }
2181 bzero(data, sizeof(struct nfs_cb_data));
2182 data->nfs = nfs;
2183 data->cb = cb;
2184 data->private_data = private_data;
2185 data->continue_data = chown_data;
2186 data->fh.data.data_len = nfsfh->fh.data.data_len;
2187 data->fh.data.data_val = malloc(data->fh.data.data_len);
2188 if (data->fh.data.data_val == NULL) {
2189 rpc_set_error(nfs->rpc, "Out of memory: Failed to allocate fh");
2190 free_nfs_cb_data(data);
2191 return -1;
2192 }
2193 memcpy(data->fh.data.data_val, nfsfh->fh.data.data_val, data->fh.data.data_len);
2194
2195
2196 if (nfs_chown_continue_internal(nfs, data) != 0) {
2197 free_nfs_cb_data(data);
2198 return -1;
2199 }
2200
2201 return 0;
2202 }
2203
2204
2205
2206
2207
2208 /*
2209 * Async utimes()
2210 */
2211 static void nfs_utimes_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
2212 {
2213 struct nfs_cb_data *data = private_data;
2214 struct nfs_context *nfs = data->nfs;
2215 SETATTR3res *res;
2216
2217 if (status == RPC_STATUS_ERROR) {
2218 data->cb(-EFAULT, nfs, command_data, data->private_data);
2219 free_nfs_cb_data(data);
2220 return;
2221 }
2222 if (status == RPC_STATUS_CANCEL) {
2223 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2224 free_nfs_cb_data(data);
2225 return;
2226 }
2227
2228 res = command_data;
2229 if (res->status != NFS3_OK) {
2230 rpc_set_error(nfs->rpc, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
2231 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2232 free_nfs_cb_data(data);
2233 return;
2234 }
2235
2236 data->cb(0, nfs, NULL, data->private_data);
2237 free_nfs_cb_data(data);
2238 }
2239
2240 static int nfs_utimes_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2241 {
2242 SETATTR3args args;
2243 struct timeval *utimes_data = data->continue_data;
2244
2245 bzero(&args, sizeof(SETATTR3args));
2246 args.object.data.data_len = data->fh.data.data_len;
2247 args.object.data.data_val = data->fh.data.data_val;
2248 if (utimes_data != NULL) {
2249 args.new_attributes.atime.set_it = SET_TO_CLIENT_TIME;
2250 args.new_attributes.atime.set_atime_u.atime.seconds = utimes_data[0].tv_sec;
2251 args.new_attributes.atime.set_atime_u.atime.nseconds = utimes_data[0].tv_usec * 1000;
2252 args.new_attributes.mtime.set_it = SET_TO_CLIENT_TIME;
2253 args.new_attributes.mtime.set_mtime_u.mtime.seconds = utimes_data[1].tv_sec;
2254 args.new_attributes.mtime.set_mtime_u.mtime.nseconds = utimes_data[1].tv_usec * 1000;
2255 } else {
2256 args.new_attributes.atime.set_it = SET_TO_SERVER_TIME;
2257 args.new_attributes.mtime.set_it = SET_TO_SERVER_TIME;
2258 }
2259
2260 if (rpc_nfs_setattr_async(nfs->rpc, nfs_utimes_cb, &args, data) != 0) {
2261 rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
2262 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2263 free_nfs_cb_data(data);
2264 return -1;
2265 }
2266 return 0;
2267 }
2268
2269
2270 int nfs_utimes_async(struct nfs_context *nfs, const char *path, struct timeval *times, nfs_cb cb, void *private_data)
2271 {
2272 struct timeval *new_times = NULL;
2273
2274 if (times != NULL) {
2275 new_times = malloc(sizeof(struct timeval)*2);
2276 if (new_times == NULL) {
2277 rpc_set_error(nfs->rpc, "Failed to allocate memory for timeval structure");
2278 return -1;
2279 }
2280
2281 memcpy(new_times, times, sizeof(struct timeval)*2);
2282 }
2283
2284 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_utimes_continue_internal, new_times, free, 0) != 0) {
2285 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
2286 return -1;
2287 }
2288
2289 return 0;
2290 }
2291
2292 /*
2293 * Async utime()
2294 */
2295 int nfs_utime_async(struct nfs_context *nfs, const char *path, struct utimbuf *times, nfs_cb cb, void *private_data)
2296 {
2297 struct timeval *new_times = NULL;
2298
2299 if (times != NULL) {
2300 new_times = malloc(sizeof(struct timeval)*2);
2301 if (new_times == NULL) {
2302 rpc_set_error(nfs->rpc, "Failed to allocate memory for timeval structure");
2303 return -1;
2304 }
2305
2306 new_times[0].tv_sec = times->actime;
2307 new_times[0].tv_usec = 0;
2308 new_times[1].tv_sec = times->modtime;
2309 new_times[1].tv_usec = 0;
2310 }
2311
2312 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_utimes_continue_internal, new_times, free, 0) != 0) {
2313 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
2314 return -1;
2315 }
2316
2317 return 0;
2318 }
2319
2320
2321
2322
2323
2324 /*
2325 * Async access()
2326 */
2327 static void nfs_access_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
2328 {
2329 ACCESS3res *res;
2330 struct nfs_cb_data *data = private_data;
2331 struct nfs_context *nfs = data->nfs;
2332 unsigned int nfsmode = 0;
2333
2334 if (status == RPC_STATUS_ERROR) {
2335 data->cb(-EFAULT, nfs, command_data, data->private_data);
2336 free_nfs_cb_data(data);
2337 return;
2338 }
2339 if (status == RPC_STATUS_CANCEL) {
2340 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2341 free_nfs_cb_data(data);
2342 return;
2343 }
2344
2345 res = command_data;
2346 if (res->status != NFS3_OK) {
2347 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));
2348 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2349 free_nfs_cb_data(data);
2350 return;
2351 }
2352
2353 if (data->continue_int & R_OK) {
2354 nfsmode |= ACCESS3_READ;
2355 }
2356 if (data->continue_int & W_OK) {
2357 nfsmode |= ACCESS3_MODIFY;
2358 }
2359 if (data->continue_int & X_OK) {
2360 nfsmode |= ACCESS3_EXECUTE;
2361 }
2362
2363 if (res->ACCESS3res_u.resok.access != nfsmode) {
2364 rpc_set_error(nfs->rpc, "NFS: ACCESS denied. Required access %c%c%c. Allowed access %c%c%c",
2365 nfsmode&ACCESS3_READ?'r':'-',
2366 nfsmode&ACCESS3_MODIFY?'w':'-',
2367 nfsmode&ACCESS3_EXECUTE?'x':'-',
2368 res->ACCESS3res_u.resok.access&ACCESS3_READ?'r':'-',
2369 res->ACCESS3res_u.resok.access&ACCESS3_MODIFY?'w':'-',
2370 res->ACCESS3res_u.resok.access&ACCESS3_EXECUTE?'x':'-');
2371 data->cb(-EACCES, nfs, rpc_get_error(nfs->rpc), data->private_data);
2372 free_nfs_cb_data(data);
2373 return;
2374 }
2375
2376 data->cb(0, nfs, NULL, data->private_data);
2377 free_nfs_cb_data(data);
2378 }
2379
2380 static int nfs_access_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2381 {
2382 int nfsmode = 0;
2383
2384 if (data->continue_int & R_OK) {
2385 nfsmode |= ACCESS3_READ;
2386 }
2387 if (data->continue_int & W_OK) {
2388 nfsmode |= ACCESS3_MODIFY;
2389 }
2390 if (data->continue_int & X_OK) {
2391 nfsmode |= ACCESS3_EXECUTE;
2392 }
2393
2394 if (rpc_nfs_access_async(nfs->rpc, nfs_access_cb, &data->fh, nfsmode, data) != 0) {
2395 rpc_set_error(nfs->rpc, "RPC error: Failed to send OPEN ACCESS call for %s", data->path);
2396 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2397 free_nfs_cb_data(data);
2398 return -1;
2399 }
2400 return 0;
2401 }
2402
2403 int nfs_access_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data)
2404 {
2405 if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_access_continue_internal, NULL, NULL, mode) != 0) {
2406 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
2407 return -1;
2408 }
2409
2410 return 0;
2411 }
2412
2413
2414
2415 /*
2416 * Async symlink()
2417 */
2418 struct nfs_symlink_data {
2419 char *oldpath;
2420 char *newpathparent;
2421 char *newpathobject;
2422 };
2423
2424 static void free_nfs_symlink_data(void *mem)
2425 {
2426 struct nfs_symlink_data *data = mem;
2427
2428 if (data->oldpath != NULL) {
2429 free(data->oldpath);
2430 }
2431 if (data->newpathparent != NULL) {
2432 free(data->newpathparent);
2433 }
2434 if (data->newpathobject != NULL) {
2435 free(data->newpathobject);
2436 }
2437 free(data);
2438 }
2439
2440 static void nfs_symlink_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
2441 {
2442 SYMLINK3res *res;
2443 struct nfs_cb_data *data = private_data;
2444 struct nfs_context *nfs = data->nfs;
2445 struct nfs_symlink_data *symlink_data = data->continue_data;
2446
2447 if (status == RPC_STATUS_ERROR) {
2448 data->cb(-EFAULT, nfs, command_data, data->private_data);
2449 free_nfs_cb_data(data);
2450 return;
2451 }
2452 if (status == RPC_STATUS_CANCEL) {
2453 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2454 free_nfs_cb_data(data);
2455 return;
2456 }
2457
2458 res = command_data;
2459 if (res->status != NFS3_OK) {
2460 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));
2461 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2462 free_nfs_cb_data(data);
2463 return;
2464 }
2465
2466 data->cb(0, nfs, NULL, data->private_data);
2467 free_nfs_cb_data(data);
2468 }
2469
2470 static int nfs_symlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2471 {
2472 struct nfs_symlink_data *symlink_data = data->continue_data;
2473
2474 if (rpc_nfs_symlink_async(nfs->rpc, nfs_symlink_cb, &data->fh, symlink_data->newpathobject, symlink_data->oldpath, data) != 0) {
2475 rpc_set_error(nfs->rpc, "RPC error: Failed to send SYMLINK call for %s", data->path);
2476 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2477 free_nfs_cb_data(data);
2478 return -1;
2479 }
2480 return 0;
2481 }
2482
2483 int nfs_symlink_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data)
2484 {
2485 char *ptr;
2486 struct nfs_symlink_data *symlink_data;
2487
2488 symlink_data = malloc(sizeof(struct nfs_symlink_data));
2489 if (symlink_data == NULL) {
2490 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for symlink data");
2491 return -1;
2492 }
2493 bzero(symlink_data, sizeof(struct nfs_symlink_data));
2494
2495 symlink_data->oldpath = strdup(oldpath);
2496 if (symlink_data->oldpath == NULL) {
2497 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for oldpath");
2498 free_nfs_symlink_data(symlink_data);
2499 return -1;
2500 }
2501
2502 symlink_data->newpathparent = strdup(newpath);
2503 if (symlink_data->newpathparent == NULL) {
2504 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for new path");
2505 free_nfs_symlink_data(symlink_data);
2506 return -1;
2507 }
2508
2509 ptr = rindex(symlink_data->newpathparent, '/');
2510 if (ptr == NULL) {
2511 rpc_set_error(nfs->rpc, "Invalid path %s", oldpath);
2512 free_nfs_symlink_data(symlink_data);
2513 return -1;
2514 }
2515 *ptr = 0;
2516 ptr++;
2517
2518 symlink_data->newpathobject = strdup(ptr);
2519 if (symlink_data->newpathobject == NULL) {
2520 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for new path");
2521 free_nfs_symlink_data(symlink_data);
2522 return -1;
2523 }
2524
2525 if (nfs_lookuppath_async(nfs, symlink_data->newpathparent, cb, private_data, nfs_symlink_continue_internal, symlink_data, free_nfs_symlink_data, 0) != 0) {
2526 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
2527 return -1;
2528 }
2529
2530 return 0;
2531 }
2532
2533
2534
2535 /*
2536 * Async rename()
2537 */
2538 struct nfs_rename_data {
2539 char *oldpath;
2540 char *oldobject;
2541 struct nfs_fh3 olddir;
2542 char *newpath;
2543 char *newobject;
2544 struct nfs_fh3 newdir;
2545 };
2546
2547 static void free_nfs_rename_data(void *mem)
2548 {
2549 struct nfs_rename_data *data = mem;
2550
2551 if (data->oldpath != NULL) {
2552 free(data->oldpath);
2553 }
2554 if (data->olddir.data.data_val != NULL) {
2555 free(data->olddir.data.data_val);
2556 }
2557 if (data->newpath != NULL) {
2558 free(data->newpath);
2559 }
2560 if (data->newdir.data.data_val != NULL) {
2561 free(data->newdir.data.data_val);
2562 }
2563 free(data);
2564 }
2565
2566 static void nfs_rename_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
2567 {
2568 RENAME3res *res;
2569 struct nfs_cb_data *data = private_data;
2570 struct nfs_context *nfs = data->nfs;
2571 struct nfs_rename_data *rename_data = data->continue_data;
2572
2573 if (status == RPC_STATUS_ERROR) {
2574 data->cb(-EFAULT, nfs, command_data, data->private_data);
2575 free_nfs_cb_data(data);
2576 return;
2577 }
2578 if (status == RPC_STATUS_CANCEL) {
2579 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2580 free_nfs_cb_data(data);
2581 return;
2582 }
2583
2584 res = command_data;
2585 if (res->status != NFS3_OK) {
2586 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));
2587 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2588 free_nfs_cb_data(data);
2589 return;
2590 }
2591
2592 data->cb(0, nfs, NULL, data->private_data);
2593 free_nfs_cb_data(data);
2594 }
2595
2596 static int nfs_rename_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2597 {
2598 struct nfs_rename_data *rename_data = data->continue_data;
2599
2600 /* steal the filehandle */
2601 rename_data->newdir.data.data_len = data->fh.data.data_len;
2602 rename_data->newdir.data.data_val = data->fh.data.data_val;
2603 data->fh.data.data_val = NULL;
2604
2605 if (rpc_nfs_rename_async(nfs->rpc, nfs_rename_cb, &rename_data->olddir, rename_data->oldobject, &rename_data->newdir, rename_data->newobject, data) != 0) {
2606 rpc_set_error(nfs->rpc, "RPC error: Failed to send RENAME call for %s", data->path);
2607 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2608 free_nfs_cb_data(data);
2609 return -1;
2610 }
2611 return 0;
2612 }
2613
2614
2615 static int nfs_rename_continue_1_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2616 {
2617 struct nfs_rename_data *rename_data = data->continue_data;
2618
2619 /* steal the filehandle */
2620 rename_data->olddir.data.data_len = data->fh.data.data_len;
2621 rename_data->olddir.data.data_val = data->fh.data.data_val;
2622 data->fh.data.data_val = NULL;
2623
2624 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) {
2625 rpc_set_error(nfs->rpc, "RPC error: Failed to send LOOKUP call for %s", rename_data->newpath);
2626 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2627 free_nfs_cb_data(data);
2628 return -1;
2629 }
2630 data->continue_data = NULL;
2631 free_nfs_cb_data(data);
2632
2633 return 0;
2634 }
2635
2636
2637 int nfs_rename_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data)
2638 {
2639 char *ptr;
2640 struct nfs_rename_data *rename_data;
2641
2642 rename_data = malloc(sizeof(struct nfs_rename_data));
2643 if (rename_data == NULL) {
2644 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for rename data");
2645 return -1;
2646 }
2647 bzero(rename_data, sizeof(struct nfs_rename_data));
2648
2649 rename_data->oldpath = strdup(oldpath);
2650 if (rename_data->oldpath == NULL) {
2651 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for oldpath");
2652 free_nfs_rename_data(rename_data);
2653 return -1;
2654 }
2655 ptr = rindex(rename_data->oldpath, '/');
2656 if (ptr == NULL) {
2657 rpc_set_error(nfs->rpc, "Invalid path %s", oldpath);
2658 free_nfs_rename_data(rename_data);
2659 return -1;
2660 }
2661 *ptr = 0;
2662 ptr++;
2663 rename_data->oldobject = ptr;
2664
2665
2666 rename_data->newpath = strdup(newpath);
2667 if (rename_data->newpath == NULL) {
2668 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for newpath");
2669 free_nfs_rename_data(rename_data);
2670 return -1;
2671 }
2672 ptr = rindex(rename_data->newpath, '/');
2673 if (ptr == NULL) {
2674 rpc_set_error(nfs->rpc, "Invalid path %s", newpath);
2675 free_nfs_rename_data(rename_data);
2676 return -1;
2677 }
2678 *ptr = 0;
2679 ptr++;
2680 rename_data->newobject = ptr;
2681
2682
2683 if (nfs_lookuppath_async(nfs, rename_data->oldpath, cb, private_data, nfs_rename_continue_1_internal, rename_data, free_nfs_rename_data, 0) != 0) {
2684 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
2685 return -1;
2686 }
2687
2688 return 0;
2689 }
2690
2691
2692 /*
2693 * Async link()
2694 */
2695 struct nfs_link_data {
2696 char *oldpath;
2697 struct nfs_fh3 oldfh;
2698 char *newpath;
2699 char *newobject;
2700 struct nfs_fh3 newdir;
2701 };
2702
2703 static void free_nfs_link_data(void *mem)
2704 {
2705 struct nfs_link_data *data = mem;
2706
2707 if (data->oldpath != NULL) {
2708 free(data->oldpath);
2709 }
2710 if (data->oldfh.data.data_val != NULL) {
2711 free(data->oldfh.data.data_val);
2712 }
2713 if (data->newpath != NULL) {
2714 free(data->newpath);
2715 }
2716 if (data->newdir.data.data_val != NULL) {
2717 free(data->newdir.data.data_val);
2718 }
2719 free(data);
2720 }
2721
2722 static void nfs_link_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data)
2723 {
2724 LINK3res *res;
2725 struct nfs_cb_data *data = private_data;
2726 struct nfs_context *nfs = data->nfs;
2727 struct nfs_link_data *link_data = data->continue_data;
2728
2729 if (status == RPC_STATUS_ERROR) {
2730 data->cb(-EFAULT, nfs, command_data, data->private_data);
2731 free_nfs_cb_data(data);
2732 return;
2733 }
2734 if (status == RPC_STATUS_CANCEL) {
2735 data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
2736 free_nfs_cb_data(data);
2737 return;
2738 }
2739
2740 res = command_data;
2741 if (res->status != NFS3_OK) {
2742 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));
2743 data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
2744 free_nfs_cb_data(data);
2745 return;
2746 }
2747
2748 data->cb(0, nfs, NULL, data->private_data);
2749 free_nfs_cb_data(data);
2750 }
2751
2752 static int nfs_link_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2753 {
2754 struct nfs_link_data *link_data = data->continue_data;
2755
2756 /* steal the filehandle */
2757 link_data->newdir.data.data_len = data->fh.data.data_len;
2758 link_data->newdir.data.data_val = data->fh.data.data_val;
2759 data->fh.data.data_val = NULL;
2760
2761 if (rpc_nfs_link_async(nfs->rpc, nfs_link_cb, &link_data->oldfh, &link_data->newdir, link_data->newobject, data) != 0) {
2762 rpc_set_error(nfs->rpc, "RPC error: Failed to send LINK call for %s", data->path);
2763 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2764 free_nfs_cb_data(data);
2765 return -1;
2766 }
2767 return 0;
2768 }
2769
2770
2771 static int nfs_link_continue_1_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
2772 {
2773 struct nfs_link_data *link_data = data->continue_data;
2774
2775 /* steal the filehandle */
2776 link_data->oldfh.data.data_len = data->fh.data.data_len;
2777 link_data->oldfh.data.data_val = data->fh.data.data_val;
2778 data->fh.data.data_val = NULL;
2779
2780 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) {
2781 rpc_set_error(nfs->rpc, "RPC error: Failed to send LOOKUP call for %s", link_data->newpath);
2782 data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
2783 free_nfs_cb_data(data);
2784 return -1;
2785 }
2786 data->continue_data = NULL;
2787 free_nfs_cb_data(data);
2788
2789 return 0;
2790 }
2791
2792
2793 int nfs_link_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data)
2794 {
2795 char *ptr;
2796 struct nfs_link_data *link_data;
2797
2798 link_data = malloc(sizeof(struct nfs_link_data));
2799 if (link_data == NULL) {
2800 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for link data");
2801 return -1;
2802 }
2803 bzero(link_data, sizeof(struct nfs_link_data));
2804
2805 link_data->oldpath = strdup(oldpath);
2806 if (link_data->oldpath == NULL) {
2807 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for oldpath");
2808 free_nfs_link_data(link_data);
2809 return -1;
2810 }
2811
2812 link_data->newpath = strdup(newpath);
2813 if (link_data->newpath == NULL) {
2814 rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for newpath");
2815 free_nfs_link_data(link_data);
2816 return -1;
2817 }
2818 ptr = rindex(link_data->newpath, '/');
2819 if (ptr == NULL) {
2820 rpc_set_error(nfs->rpc, "Invalid path %s", newpath);
2821 free_nfs_link_data(link_data);
2822 return -1;
2823 }
2824 *ptr = 0;
2825 ptr++;
2826 link_data->newobject = ptr;
2827
2828
2829 if (nfs_lookuppath_async(nfs, link_data->oldpath, cb, private_data, nfs_link_continue_1_internal, link_data, free_nfs_link_data, 0) != 0) {
2830 rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
2831 return -1;
2832 }
2833
2834 return 0;
2835 }
2836
2837
2838 //qqq replace later with lseek()
2839 off_t nfs_get_current_offset(struct nfsfh *nfsfh)
2840 {
2841 return nfsfh->offset;
2842 }
2843
2844
2845
2846 /*
2847 * Get the maximum supported READ3 size by the server
2848 */
2849 size_t nfs_get_readmax(struct nfs_context *nfs)
2850 {
2851 return nfs->readmax;
2852 }
2853
2854 /*
2855 * Get the maximum supported WRITE3 size by the server
2856 */
2857 size_t nfs_get_writemax(struct nfs_context *nfs)
2858 {
2859 return nfs->writemax;
2860 }
2861
2862 void nfs_set_error(struct nfs_context *nfs, char *error_string, ...)
2863 {
2864 va_list ap;
2865 char *str;
2866
2867 if (nfs->rpc->error_string != NULL) {
2868 free(nfs->rpc->error_string);
2869 }
2870 va_start(ap, error_string);
2871 vasprintf(&str, error_string, ap);
2872 nfs->rpc->error_string = str;
2873 va_end(ap);
2874 }
2875
2876
2877
2878 struct mount_cb_data {
2879 rpc_cb cb;
2880 void *private_data;
2881 char *server;
2882 };
2883
2884 static void free_mount_cb_data(struct mount_cb_data *data)
2885 {
2886 if (data->server != NULL) {
2887 free(data->server);
2888 data->server = NULL;
2889 }
2890
2891 free(data);
2892 }
2893
2894 static void mount_export_5_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
2895 {
2896 struct mount_cb_data *data = private_data;
2897
2898 if (status == RPC_STATUS_ERROR) {
2899 data->cb(rpc, -EFAULT, command_data, data->private_data);
2900 free_mount_cb_data(data);
2901 return;
2902 }
2903 if (status == RPC_STATUS_CANCEL) {
2904 data->cb(rpc, -EINTR, "Command was cancelled", data->private_data);
2905 free_mount_cb_data(data);
2906 return;
2907 }
2908
2909 data->cb(rpc, 0, command_data, data->private_data);
2910 if (rpc_disconnect(rpc, "normal disconnect") != 0) {
2911 rpc_set_error(rpc, "Failed to disconnect\n");
2912 }
2913 free_mount_cb_data(data);
2914 }
2915
2916 static void mount_export_4_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
2917 {
2918 struct mount_cb_data *data = private_data;
2919
2920 if (status == RPC_STATUS_ERROR) {
2921 data->cb(rpc, -EFAULT, command_data, data->private_data);
2922 free_mount_cb_data(data);
2923 return;
2924 }
2925 if (status == RPC_STATUS_CANCEL) {
2926 data->cb(rpc, -EINTR, "Command was cancelled", data->private_data);
2927 free_mount_cb_data(data);
2928 return;
2929 }
2930
2931 if (rpc_mount_export_async(rpc, mount_export_5_cb, data) != 0) {
2932 data->cb(rpc, -ENOMEM, command_data, data->private_data);
2933 free_mount_cb_data(data);
2934 return;
2935 }
2936 }
2937
2938 static void mount_export_3_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
2939 {
2940 struct mount_cb_data *data = private_data;
2941 uint32_t mount_port;
2942
2943 if (status == RPC_STATUS_ERROR) {
2944 data->cb(rpc, -EFAULT, command_data, data->private_data);
2945 free_mount_cb_data(data);
2946 return;
2947 }
2948 if (status == RPC_STATUS_CANCEL) {
2949 data->cb(rpc, -EINTR, "Command was cancelled", data->private_data);
2950 free_mount_cb_data(data);
2951 return;
2952 }
2953
2954 mount_port = *(uint32_t *)command_data;
2955 if (mount_port == 0) {
2956 rpc_set_error(rpc, "RPC error. Mount program is not available");
2957 data->cb(rpc, -ENOENT, command_data, data->private_data);
2958 free_mount_cb_data(data);
2959 return;
2960 }
2961
2962 rpc_disconnect(rpc, "normal disconnect");
2963 if (rpc_connect_async(rpc, data->server, mount_port, mount_export_4_cb, data) != 0) {
2964 data->cb(rpc, -ENOMEM, command_data, data->private_data);
2965 free_mount_cb_data(data);
2966 return;
2967 }
2968 }
2969
2970 static void mount_export_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
2971 {
2972 struct mount_cb_data *data = private_data;
2973
2974 if (status == RPC_STATUS_ERROR) {
2975 data->cb(rpc, -EFAULT, command_data, data->private_data);
2976 free_mount_cb_data(data);
2977 return;
2978 }
2979 if (status == RPC_STATUS_CANCEL) {
2980 data->cb(rpc, -EINTR, "Command was cancelled", data->private_data);
2981 free_mount_cb_data(data);
2982 return;
2983 }
2984
2985 if (rpc_pmap_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, mount_export_3_cb, private_data) != 0) {
2986 data->cb(rpc, -ENOMEM, command_data, data->private_data);
2987 free_mount_cb_data(data);
2988 return;
2989 }
2990 }
2991
2992 static void mount_export_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
2993 {
2994 struct mount_cb_data *data = private_data;
2995
2996 if (status == RPC_STATUS_ERROR) {
2997 data->cb(rpc, -EFAULT, command_data, data->private_data);
2998 free_mount_cb_data(data);
2999 return;
3000 }
3001 if (status == RPC_STATUS_CANCEL) {
3002 data->cb(rpc, -EINTR, "Command was cancelled", data->private_data);
3003 free_mount_cb_data(data);
3004 return;
3005 }
3006
3007 if (rpc_pmap_null_async(rpc, mount_export_2_cb, data) != 0) {
3008 data->cb(rpc, -ENOMEM, command_data, data->private_data);
3009 free_mount_cb_data(data);
3010 return;
3011 }
3012 }
3013
3014 int mount_getexports_async(struct rpc_context *rpc, const char *server, rpc_cb cb, void *private_data)
3015 {
3016 struct mount_cb_data *data;
3017
3018 data = malloc(sizeof(struct mount_cb_data));
3019 if (data == NULL) {
3020 return -1;
3021 }
3022 bzero(data, sizeof(struct mount_cb_data));
3023 data->cb = cb;
3024 data->private_data = private_data;
3025 data->server = strdup(server);
3026 if (data->server == NULL) {
3027 free_mount_cb_data(data);
3028 return -1;
3029 }
3030 if (rpc_connect_async(rpc, data->server, 111, mount_export_1_cb, data) != 0) {
3031 free_mount_cb_data(data);
3032 return -1;
3033 }
3034
3035 return 0;
3036 }
3037