2 Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
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.
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.
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/>.
18 * High level api to nfs filesystems
25 #include "win32_compat.h"
29 #include <sys/socket.h>
33 #include "aros_compat.h"
36 #include <netinet/in.h>
38 #define statvfs statfs
40 #include <sys/statvfs.h>
45 #ifdef HAVE_SYS_IOCTL_H
46 #include <sys/ioctl.h>
61 #include <sys/types.h>
66 #ifdef HAVE_SYS_SOCKIO_H
67 #include <sys/sockio.h>
70 #include "libnfs-zdr.h"
72 #include "libnfs-raw.h"
73 #include "libnfs-raw-mount.h"
74 #include "libnfs-raw-nfs.h"
75 #include "libnfs-private.h"
86 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
90 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
92 while (!cb_data
->is_finished
) {
94 pfd
.fd
= rpc_get_fd(rpc
);
95 pfd
.events
= rpc_which_events(rpc
);
96 if (poll(&pfd
, 1, -1) < 0) {
97 rpc_set_error(rpc
, "Poll failed");
98 cb_data
->status
= -EIO
;
101 if (rpc_service(rpc
, pfd
.revents
) < 0) {
102 rpc_set_error(rpc
, "rpc_service failed");
103 cb_data
->status
= -EIO
;
106 if (rpc_get_fd(rpc
) == -1) {
107 rpc_set_error(rpc
, "Socket closed\n");
113 static void wait_for_nfs_reply(struct nfs_context
*nfs
, struct sync_cb_data
*cb_data
)
117 while (!cb_data
->is_finished
) {
119 pfd
.fd
= nfs_get_fd(nfs
);
120 pfd
.events
= nfs_which_events(nfs
);
121 if (poll(&pfd
, 1, -1) < 0) {
122 nfs_set_error(nfs
, "Poll failed");
123 cb_data
->status
= -EIO
;
126 if (nfs_service(nfs
, pfd
.revents
) < 0) {
127 nfs_set_error(nfs
, "nfs_service failed");
128 cb_data
->status
= -EIO
;
140 * connect to the server and mount the export
142 static void mount_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
144 struct sync_cb_data
*cb_data
= private_data
;
146 cb_data
->is_finished
= 1;
147 cb_data
->status
= status
;
150 nfs_set_error(nfs
, "mount/mnt call failed with \"%s\"", (char *)data
);
155 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
157 struct sync_cb_data cb_data
;
158 struct rpc_context
*rpc
= nfs_get_rpc_context(nfs
);
160 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
162 cb_data
.is_finished
= 0;
164 if (nfs_mount_async(nfs
, server
, export
, mount_cb
, &cb_data
) != 0) {
165 nfs_set_error(nfs
, "nfs_mount_async failed");
169 wait_for_nfs_reply(nfs
, &cb_data
);
171 /* Dont want any more callbacks even if the socket is closed */
172 rpc
->connect_cb
= NULL
;
174 return cb_data
.status
;
181 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
183 struct sync_cb_data
*cb_data
= private_data
;
185 cb_data
->is_finished
= 1;
186 cb_data
->status
= status
;
189 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
193 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
196 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
198 struct sync_cb_data cb_data
;
200 cb_data
.is_finished
= 0;
201 cb_data
.return_data
= st
;
203 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
204 nfs_set_error(nfs
, "nfs_stat_async failed");
208 wait_for_nfs_reply(nfs
, &cb_data
);
210 return cb_data
.status
;
219 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
221 struct sync_cb_data
*cb_data
= private_data
;
222 struct nfsfh
*fh
, **nfsfh
;
224 cb_data
->is_finished
= 1;
225 cb_data
->status
= status
;
228 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
233 nfsfh
= cb_data
->return_data
;
237 int nfs_open(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
239 struct sync_cb_data cb_data
;
241 cb_data
.is_finished
= 0;
242 cb_data
.return_data
= nfsfh
;
244 if (nfs_open_async(nfs
, path
, mode
, open_cb
, &cb_data
) != 0) {
245 nfs_set_error(nfs
, "nfs_open_async failed");
249 wait_for_nfs_reply(nfs
, &cb_data
);
251 return cb_data
.status
;
260 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
262 struct sync_cb_data
*cb_data
= private_data
;
264 cb_data
->is_finished
= 1;
265 cb_data
->status
= status
;
268 nfs_set_error(nfs
, "pread call failed with \"%s\"", (char *)data
);
272 buffer
= cb_data
->return_data
;
273 memcpy(buffer
, (char *)data
, status
);
276 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buffer
)
278 struct sync_cb_data cb_data
;
280 cb_data
.is_finished
= 0;
281 cb_data
.return_data
= buffer
;
283 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
284 nfs_set_error(nfs
, "nfs_pread_async failed");
288 wait_for_nfs_reply(nfs
, &cb_data
);
290 return cb_data
.status
;
296 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buffer
)
298 return nfs_pread(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buffer
);
304 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
306 struct sync_cb_data
*cb_data
= private_data
;
307 cb_data
->is_finished
= 1;
308 cb_data
->status
= status
;
311 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
316 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
318 struct sync_cb_data cb_data
;
320 cb_data
.is_finished
= 0;
322 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
323 nfs_set_error(nfs
, "nfs_close_async failed");
327 wait_for_nfs_reply(nfs
, &cb_data
);
329 return cb_data
.status
;
338 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
340 struct sync_cb_data cb_data
;
342 cb_data
.is_finished
= 0;
343 cb_data
.return_data
= st
;
345 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
346 nfs_set_error(nfs
, "nfs_fstat_async failed");
350 wait_for_nfs_reply(nfs
, &cb_data
);
352 return cb_data
.status
;
359 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
361 struct sync_cb_data
*cb_data
= private_data
;
362 cb_data
->is_finished
= 1;
363 cb_data
->status
= status
;
366 nfs_set_error(nfs
, "pwrite call failed with \"%s\"", (char *)data
);
371 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buf
)
373 struct sync_cb_data cb_data
;
375 cb_data
.is_finished
= 0;
377 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
378 nfs_set_error(nfs
, "nfs_pwrite_async failed");
382 wait_for_nfs_reply(nfs
, &cb_data
);
384 return cb_data
.status
;
390 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buf
)
392 return nfs_pwrite(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buf
);
399 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
401 struct sync_cb_data
*cb_data
= private_data
;
402 cb_data
->is_finished
= 1;
403 cb_data
->status
= status
;
406 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
411 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
413 struct sync_cb_data cb_data
;
415 cb_data
.is_finished
= 0;
417 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
418 nfs_set_error(nfs
, "nfs_fsync_async failed");
422 wait_for_nfs_reply(nfs
, &cb_data
);
424 return cb_data
.status
;
433 static void ftruncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
435 struct sync_cb_data
*cb_data
= private_data
;
436 cb_data
->is_finished
= 1;
437 cb_data
->status
= status
;
440 nfs_set_error(nfs
, "ftruncate call failed with \"%s\"", (char *)data
);
445 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t length
)
447 struct sync_cb_data cb_data
;
449 cb_data
.is_finished
= 0;
451 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_cb
, &cb_data
) != 0) {
452 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
456 wait_for_nfs_reply(nfs
, &cb_data
);
458 return cb_data
.status
;
466 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
468 struct sync_cb_data
*cb_data
= private_data
;
469 cb_data
->is_finished
= 1;
470 cb_data
->status
= status
;
473 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
478 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, uint64_t length
)
480 struct sync_cb_data cb_data
;
482 cb_data
.is_finished
= 0;
484 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
485 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
489 wait_for_nfs_reply(nfs
, &cb_data
);
491 return cb_data
.status
;
501 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
503 struct sync_cb_data
*cb_data
= private_data
;
504 cb_data
->is_finished
= 1;
505 cb_data
->status
= status
;
508 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
513 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
515 struct sync_cb_data cb_data
;
517 cb_data
.is_finished
= 0;
519 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
520 nfs_set_error(nfs
, "nfs_mkdir_async failed");
524 wait_for_nfs_reply(nfs
, &cb_data
);
526 return cb_data
.status
;
536 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
538 struct sync_cb_data
*cb_data
= private_data
;
539 cb_data
->is_finished
= 1;
540 cb_data
->status
= status
;
543 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
548 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
550 struct sync_cb_data cb_data
;
552 cb_data
.is_finished
= 0;
554 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
555 nfs_set_error(nfs
, "nfs_rmdir_async failed");
559 wait_for_nfs_reply(nfs
, &cb_data
);
561 return cb_data
.status
;
569 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
571 struct sync_cb_data
*cb_data
= private_data
;
572 struct nfsfh
*fh
, **nfsfh
;
574 cb_data
->is_finished
= 1;
575 cb_data
->status
= status
;
578 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
583 nfsfh
= cb_data
->return_data
;
587 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
589 struct sync_cb_data cb_data
;
591 cb_data
.is_finished
= 0;
592 cb_data
.return_data
= nfsfh
;
594 if (nfs_creat_async(nfs
, path
, mode
, creat_cb
, &cb_data
) != 0) {
595 nfs_set_error(nfs
, "nfs_creat_async failed");
599 wait_for_nfs_reply(nfs
, &cb_data
);
601 return cb_data
.status
;
607 static void mknod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
609 struct sync_cb_data
*cb_data
= private_data
;
611 cb_data
->is_finished
= 1;
612 cb_data
->status
= status
;
615 nfs_set_error(nfs
, "mknod call failed with \"%s\"", (char *)data
);
620 int nfs_mknod(struct nfs_context
*nfs
, const char *path
, int mode
, int dev
)
622 struct sync_cb_data cb_data
;
624 cb_data
.is_finished
= 0;
626 if (nfs_mknod_async(nfs
, path
, mode
, dev
, mknod_cb
, &cb_data
) != 0) {
627 nfs_set_error(nfs
, "nfs_creat_async failed");
631 wait_for_nfs_reply(nfs
, &cb_data
);
633 return cb_data
.status
;
640 static void unlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
642 struct sync_cb_data
*cb_data
= private_data
;
644 cb_data
->is_finished
= 1;
645 cb_data
->status
= status
;
648 nfs_set_error(nfs
, "unlink call failed with \"%s\"", (char *)data
);
653 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
655 struct sync_cb_data cb_data
;
657 cb_data
.is_finished
= 0;
659 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
660 nfs_set_error(nfs
, "nfs_unlink_async failed");
664 wait_for_nfs_reply(nfs
, &cb_data
);
666 return cb_data
.status
;
674 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
676 struct sync_cb_data
*cb_data
= private_data
;
677 struct nfsdir
*dir
, **nfsdir
;
679 cb_data
->is_finished
= 1;
680 cb_data
->status
= status
;
683 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
688 nfsdir
= cb_data
->return_data
;
692 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
694 struct sync_cb_data cb_data
;
696 cb_data
.is_finished
= 0;
697 cb_data
.return_data
= nfsdir
;
699 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
700 nfs_set_error(nfs
, "nfs_opendir_async failed");
704 wait_for_nfs_reply(nfs
, &cb_data
);
706 return cb_data
.status
;
713 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
715 struct sync_cb_data
*cb_data
= private_data
;
717 cb_data
->is_finished
= 1;
718 cb_data
->status
= status
;
721 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
725 if (cb_data
->return_data
!= NULL
) {
726 memcpy(cb_data
->return_data
, data
, sizeof(uint64_t));
730 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, int whence
, uint64_t *current_offset
)
732 struct sync_cb_data cb_data
;
734 cb_data
.is_finished
= 0;
735 cb_data
.return_data
= current_offset
;
737 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
738 nfs_set_error(nfs
, "nfs_lseek_async failed");
742 wait_for_nfs_reply(nfs
, &cb_data
);
744 return cb_data
.status
;
752 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
754 struct sync_cb_data
*cb_data
= private_data
;
756 cb_data
->is_finished
= 1;
757 cb_data
->status
= status
;
760 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
764 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
767 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
769 struct sync_cb_data cb_data
;
771 cb_data
.is_finished
= 0;
772 cb_data
.return_data
= svfs
;
774 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
775 nfs_set_error(nfs
, "nfs_statvfs_async failed");
779 wait_for_nfs_reply(nfs
, &cb_data
);
781 return cb_data
.status
;
791 static void readlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
793 struct sync_cb_data
*cb_data
= private_data
;
795 cb_data
->is_finished
= 1;
796 cb_data
->status
= status
;
799 nfs_set_error(nfs
, "readlink call failed with \"%s\"", (char *)data
);
803 if (strlen(data
) > (size_t)cb_data
->return_int
) {
804 nfs_set_error(nfs
, "Too small buffer for readlink");
805 cb_data
->status
= -ENAMETOOLONG
;
809 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
812 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
814 struct sync_cb_data cb_data
;
816 cb_data
.is_finished
= 0;
817 cb_data
.return_data
= buf
;
818 cb_data
.return_int
= bufsize
;
820 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
821 nfs_set_error(nfs
, "nfs_readlink_async failed");
825 wait_for_nfs_reply(nfs
, &cb_data
);
827 return cb_data
.status
;
835 static void chmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
837 struct sync_cb_data
*cb_data
= private_data
;
839 cb_data
->is_finished
= 1;
840 cb_data
->status
= status
;
843 nfs_set_error(nfs
, "chmod call failed with \"%s\"", (char *)data
);
848 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
850 struct sync_cb_data cb_data
;
852 cb_data
.is_finished
= 0;
854 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
855 nfs_set_error(nfs
, "nfs_chmod_async failed");
859 wait_for_nfs_reply(nfs
, &cb_data
);
861 return cb_data
.status
;
870 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
872 struct sync_cb_data
*cb_data
= private_data
;
874 cb_data
->is_finished
= 1;
875 cb_data
->status
= status
;
878 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
883 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
885 struct sync_cb_data cb_data
;
887 cb_data
.is_finished
= 0;
889 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
890 nfs_set_error(nfs
, "nfs_fchmod_async failed");
894 wait_for_nfs_reply(nfs
, &cb_data
);
896 return cb_data
.status
;
905 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
907 struct sync_cb_data
*cb_data
= private_data
;
909 cb_data
->is_finished
= 1;
910 cb_data
->status
= status
;
913 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
918 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
920 struct sync_cb_data cb_data
;
922 cb_data
.is_finished
= 0;
924 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
925 nfs_set_error(nfs
, "nfs_chown_async failed");
929 wait_for_nfs_reply(nfs
, &cb_data
);
931 return cb_data
.status
;
937 static void fchown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
939 struct sync_cb_data
*cb_data
= private_data
;
941 cb_data
->is_finished
= 1;
942 cb_data
->status
= status
;
945 nfs_set_error(nfs
, "fchown call failed with \"%s\"", (char *)data
);
950 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
952 struct sync_cb_data cb_data
;
954 cb_data
.is_finished
= 0;
956 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
957 nfs_set_error(nfs
, "nfs_fchown_async failed");
961 wait_for_nfs_reply(nfs
, &cb_data
);
963 return cb_data
.status
;
971 static void utimes_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
973 struct sync_cb_data
*cb_data
= private_data
;
975 cb_data
->is_finished
= 1;
976 cb_data
->status
= status
;
979 nfs_set_error(nfs
, "utimes call failed with \"%s\"", (char *)data
);
984 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
986 struct sync_cb_data cb_data
;
988 cb_data
.is_finished
= 0;
990 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
991 nfs_set_error(nfs
, "nfs_utimes_async failed");
995 wait_for_nfs_reply(nfs
, &cb_data
);
997 return cb_data
.status
;
1005 static void utime_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1007 struct sync_cb_data
*cb_data
= private_data
;
1009 cb_data
->is_finished
= 1;
1010 cb_data
->status
= status
;
1013 nfs_set_error(nfs
, "utime call failed with \"%s\"", (char *)data
);
1018 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
1020 struct sync_cb_data cb_data
;
1022 cb_data
.is_finished
= 0;
1024 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
1025 nfs_set_error(nfs
, "nfs_utimes_async failed");
1029 wait_for_nfs_reply(nfs
, &cb_data
);
1031 return cb_data
.status
;
1040 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1042 struct sync_cb_data
*cb_data
= private_data
;
1044 cb_data
->is_finished
= 1;
1045 cb_data
->status
= status
;
1048 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
1053 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
1055 struct sync_cb_data cb_data
;
1057 cb_data
.is_finished
= 0;
1059 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
1060 nfs_set_error(nfs
, "nfs_access_async failed");
1064 wait_for_nfs_reply(nfs
, &cb_data
);
1066 return cb_data
.status
;
1074 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1076 struct sync_cb_data
*cb_data
= private_data
;
1078 cb_data
->is_finished
= 1;
1079 cb_data
->status
= status
;
1082 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
1087 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1089 struct sync_cb_data cb_data
;
1091 cb_data
.is_finished
= 0;
1093 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
1094 nfs_set_error(nfs
, "nfs_symlink_async failed");
1098 wait_for_nfs_reply(nfs
, &cb_data
);
1100 return cb_data
.status
;
1108 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1110 struct sync_cb_data
*cb_data
= private_data
;
1112 cb_data
->is_finished
= 1;
1113 cb_data
->status
= status
;
1116 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1121 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1123 struct sync_cb_data cb_data
;
1125 cb_data
.is_finished
= 0;
1127 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1128 nfs_set_error(nfs
, "nfs_rename_async failed");
1132 wait_for_nfs_reply(nfs
, &cb_data
);
1134 return cb_data
.status
;
1142 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1144 struct sync_cb_data
*cb_data
= private_data
;
1146 cb_data
->is_finished
= 1;
1147 cb_data
->status
= status
;
1150 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1155 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1157 struct sync_cb_data cb_data
;
1159 cb_data
.is_finished
= 0;
1161 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1162 nfs_set_error(nfs
, "nfs_link_async failed");
1166 wait_for_nfs_reply(nfs
, &cb_data
);
1168 return cb_data
.status
;
1171 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1173 struct sync_cb_data
*cb_data
= private_data
;
1176 assert(mount_context
->magic
== RPC_CONTEXT_MAGIC
);
1178 cb_data
->is_finished
= 1;
1179 cb_data
->status
= status
;
1180 cb_data
->return_data
= NULL
;
1183 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1187 export
= *(exports
*)data
;
1188 while (export
!= NULL
) {
1191 new_export
= malloc(sizeof(*new_export
));
1192 memset(new_export
, 0, sizeof(*new_export
));
1193 new_export
->ex_dir
= strdup(export
->ex_dir
);
1194 new_export
->ex_next
= cb_data
->return_data
;
1196 cb_data
->return_data
= new_export
;
1198 export
= export
->ex_next
;
1202 struct exportnode
*mount_getexports(const char *server
)
1204 struct sync_cb_data cb_data
;
1205 struct rpc_context
*rpc
;
1208 cb_data
.is_finished
= 0;
1209 cb_data
.return_data
= NULL
;
1211 rpc
= rpc_init_context();
1212 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1213 rpc_destroy_context(rpc
);
1217 wait_for_reply(rpc
, &cb_data
);
1218 rpc_destroy_context(rpc
);
1220 return cb_data
.return_data
;
1223 void mount_free_export_list(struct exportnode
*exports
)
1225 struct exportnode
*tmp
;
1227 while ((tmp
= exports
)) {
1228 exports
= exports
->ex_next
;
1236 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1238 while (srv
!= NULL
) {
1239 struct nfs_server_list
*next
= srv
->next
;
1247 struct nfs_list_data
{
1249 struct nfs_server_list
*srvrs
;
1252 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1254 struct nfs_list_data
*srv_data
= private_data
;
1255 struct sockaddr
*sin
;
1257 struct nfs_server_list
*srvr
;
1259 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1261 if (status
== RPC_STATUS_CANCEL
) {
1265 srv_data
->status
= -1;
1269 sin
= rpc_get_recv_sockaddr(rpc
);
1271 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1272 srv_data
->status
= -1;
1276 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1277 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1278 srv_data
->status
= -1;
1282 /* check for dupes */
1283 for (srvr
= srv_data
->srvrs
; srvr
; srvr
= srvr
->next
) {
1284 if (!strcmp(hostdd
, srvr
->addr
)) {
1289 srvr
= malloc(sizeof(struct nfs_server_list
));
1291 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1292 srv_data
->status
= -1;
1296 srvr
->addr
= strdup(hostdd
);
1297 if (srvr
->addr
== NULL
) {
1298 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1300 srv_data
->status
= -1;
1304 srvr
->next
= srv_data
->srvrs
;
1305 srv_data
->srvrs
= srvr
;
1310 static int send_nfsd_probes(struct rpc_context
*rpc
, INTERFACE_INFO
*InterfaceList
, int numIfs
, struct nfs_list_data
*data
)
1314 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1316 for(i
= 0; i
< numIfs
; i
++)
1320 unsigned long nFlags
= 0;
1322 pAddress
= (SOCKADDR
*) & (InterfaceList
[i
].iiBroadcastAddress
);
1324 if(pAddress
->sa_family
!= AF_INET
)
1327 nFlags
= InterfaceList
[i
].iiFlags
;
1329 if (!(nFlags
& IFF_UP
))
1334 if (nFlags
& IFF_LOOPBACK
)
1339 if (!(nFlags
& IFF_BROADCAST
))
1344 if (getnameinfo(pAddress
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0)
1349 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0)
1354 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0)
1362 struct nfs_server_list
*nfs_find_local_servers(void)
1364 struct rpc_context
*rpc
;
1365 struct nfs_list_data data
= {0, NULL
};
1366 struct timeval tv_start
, tv_current
;
1369 INTERFACE_INFO InterfaceList
[20];
1370 unsigned long nBytesReturned
;
1371 int nNumInterfaces
= 0;
1373 rpc
= rpc_init_udp_context();
1379 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0)
1381 rpc_destroy_context(rpc
);
1385 if (WSAIoctl(rpc_get_fd(rpc
), SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
, sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
1390 nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
1392 for (loop
=0; loop
<3; loop
++)
1394 if (send_nfsd_probes(rpc
, InterfaceList
, nNumInterfaces
, &data
) != 0)
1396 rpc_destroy_context(rpc
);
1400 win32_gettimeofday(&tv_start
, NULL
);
1405 pfd
.fd
= rpc_get_fd(rpc
);
1406 pfd
.events
= rpc_which_events(rpc
);
1408 win32_gettimeofday(&tv_current
, NULL
);
1410 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1411 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1413 if (poll(&pfd
, 1, mpt
) < 0)
1415 free_nfs_srvr_list(data
.srvrs
);
1416 rpc_destroy_context(rpc
);
1419 if (pfd
.revents
== 0)
1424 if (rpc_service(rpc
, pfd
.revents
) < 0)
1431 rpc_destroy_context(rpc
);
1433 if (data
.status
!= 0)
1435 free_nfs_srvr_list(data
.srvrs
);
1442 static int send_nfsd_probes(struct rpc_context
*rpc
, struct ifconf
*ifc
, struct nfs_list_data
*data
)
1446 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1448 for (ptr
=(char *)(ifc
->ifc_buf
); ptr
< (char *)(ifc
->ifc_buf
) + ifc
->ifc_len
; ) {
1452 ifr
= (struct ifreq
*)ptr
;
1453 #ifdef HAVE_SOCKADDR_LEN
1454 if (ifr
->ifr_addr
.sa_len
> sizeof(struct sockaddr
)) {
1455 ptr
+= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
1457 ptr
+= sizeof(ifr
->ifr_name
) + sizeof(struct sockaddr
);
1460 ptr
+= sizeof(struct ifreq
);
1463 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) {
1466 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, ifr
) < 0) {
1469 if (!(ifr
->ifr_flags
& IFF_UP
)) {
1472 if (ifr
->ifr_flags
& IFF_LOOPBACK
) {
1475 if (!(ifr
->ifr_flags
& IFF_BROADCAST
)) {
1478 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, ifr
) < 0) {
1481 if (getnameinfo(&ifr
->ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1484 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1488 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0) {
1496 struct nfs_server_list
*nfs_find_local_servers(void)
1498 struct rpc_context
*rpc
;
1499 struct nfs_list_data data
= {0, NULL
};
1500 struct timeval tv_start
, tv_current
;
1505 rpc
= rpc_init_udp_context();
1510 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1511 rpc_destroy_context(rpc
);
1516 /* get list of all interfaces */
1517 size
= sizeof(struct ifreq
);
1521 while(ifc
.ifc_len
> (size
- sizeof(struct ifreq
))) {
1526 ifc
.ifc_buf
= malloc(size
);
1527 memset(ifc
.ifc_buf
, 0, size
);
1528 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1529 rpc_destroy_context(rpc
);
1535 for (loop
=0; loop
<3; loop
++) {
1536 if (send_nfsd_probes(rpc
, &ifc
, &data
) != 0) {
1537 rpc_destroy_context(rpc
);
1542 gettimeofday(&tv_start
, NULL
);
1546 pfd
.fd
= rpc_get_fd(rpc
);
1547 pfd
.events
= rpc_which_events(rpc
);
1549 gettimeofday(&tv_current
, NULL
);
1551 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1552 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1554 if (poll(&pfd
, 1, mpt
) < 0) {
1555 free_nfs_srvr_list(data
.srvrs
);
1556 rpc_destroy_context(rpc
);
1559 if (pfd
.revents
== 0) {
1563 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1570 rpc_destroy_context(rpc
);
1572 if (data
.status
!= 0) {
1573 free_nfs_srvr_list(data
.srvrs
);