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