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