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