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 "aros_compat.h"
29 #include "win32_compat.h"
37 #define statvfs statfs
44 #ifdef HAVE_SYS_STATVFS_H
45 #include <sys/statvfs.h>
48 #ifdef HAVE_SYS_IOCTL_H
49 #include <sys/ioctl.h>
52 #ifdef HAVE_SYS_SOCKET_H
53 #include <sys/socket.h>
64 #ifdef HAVE_NETINET_IN_H
65 #include <netinet/in.h>
72 #include <sys/types.h>
77 #ifdef HAVE_SYS_SOCKIO_H
78 #include <sys/sockio.h>
81 #include "libnfs-zdr.h"
83 #include "libnfs-raw.h"
84 #include "libnfs-raw-mount.h"
85 #include "libnfs-raw-nfs.h"
86 #include "libnfs-private.h"
97 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
101 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
103 while (!cb_data
->is_finished
) {
105 pfd
.fd
= rpc_get_fd(rpc
);
106 pfd
.events
= rpc_which_events(rpc
);
107 if (poll(&pfd
, 1, -1) < 0) {
108 rpc_set_error(rpc
, "Poll failed");
109 cb_data
->status
= -EIO
;
112 if (rpc_service(rpc
, pfd
.revents
) < 0) {
113 rpc_set_error(rpc
, "rpc_service failed");
114 cb_data
->status
= -EIO
;
117 if (rpc_get_fd(rpc
) == -1) {
118 rpc_set_error(rpc
, "Socket closed\n");
124 static void wait_for_nfs_reply(struct nfs_context
*nfs
, struct sync_cb_data
*cb_data
)
128 while (!cb_data
->is_finished
) {
130 pfd
.fd
= nfs_get_fd(nfs
);
131 pfd
.events
= nfs_which_events(nfs
);
132 if (poll(&pfd
, 1, -1) < 0) {
133 nfs_set_error(nfs
, "Poll failed");
134 cb_data
->status
= -EIO
;
137 if (nfs_service(nfs
, pfd
.revents
) < 0) {
138 nfs_set_error(nfs
, "nfs_service failed");
139 cb_data
->status
= -EIO
;
151 * connect to the server and mount the export
153 static void mount_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
155 struct sync_cb_data
*cb_data
= private_data
;
157 cb_data
->is_finished
= 1;
158 cb_data
->status
= status
;
161 nfs_set_error(nfs
, "mount/mnt call failed with \"%s\"", (char *)data
);
166 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
168 struct sync_cb_data cb_data
;
169 struct rpc_context
*rpc
= nfs_get_rpc_context(nfs
);
171 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
173 cb_data
.is_finished
= 0;
175 if (nfs_mount_async(nfs
, server
, export
, mount_cb
, &cb_data
) != 0) {
176 nfs_set_error(nfs
, "nfs_mount_async failed");
180 wait_for_nfs_reply(nfs
, &cb_data
);
182 /* Dont want any more callbacks even if the socket is closed */
183 rpc
->connect_cb
= NULL
;
185 return cb_data
.status
;
192 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
194 struct sync_cb_data
*cb_data
= private_data
;
196 cb_data
->is_finished
= 1;
197 cb_data
->status
= status
;
200 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
204 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
207 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
209 struct sync_cb_data cb_data
;
211 cb_data
.is_finished
= 0;
212 cb_data
.return_data
= st
;
214 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
215 nfs_set_error(nfs
, "nfs_stat_async failed");
219 wait_for_nfs_reply(nfs
, &cb_data
);
221 return cb_data
.status
;
230 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
232 struct sync_cb_data
*cb_data
= private_data
;
233 struct nfsfh
*fh
, **nfsfh
;
235 cb_data
->is_finished
= 1;
236 cb_data
->status
= status
;
239 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
244 nfsfh
= cb_data
->return_data
;
248 int nfs_open(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
250 struct sync_cb_data cb_data
;
252 cb_data
.is_finished
= 0;
253 cb_data
.return_data
= nfsfh
;
255 if (nfs_open_async(nfs
, path
, mode
, open_cb
, &cb_data
) != 0) {
256 nfs_set_error(nfs
, "nfs_open_async failed");
260 wait_for_nfs_reply(nfs
, &cb_data
);
262 return cb_data
.status
;
271 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
273 struct sync_cb_data
*cb_data
= private_data
;
275 cb_data
->is_finished
= 1;
276 cb_data
->status
= status
;
279 nfs_set_error(nfs
, "pread call failed with \"%s\"", (char *)data
);
283 buffer
= cb_data
->return_data
;
284 memcpy(buffer
, (char *)data
, status
);
287 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buffer
)
289 struct sync_cb_data cb_data
;
291 cb_data
.is_finished
= 0;
292 cb_data
.return_data
= buffer
;
294 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
295 nfs_set_error(nfs
, "nfs_pread_async failed");
299 wait_for_nfs_reply(nfs
, &cb_data
);
301 return cb_data
.status
;
307 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buffer
)
309 return nfs_pread(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buffer
);
315 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
317 struct sync_cb_data
*cb_data
= private_data
;
318 cb_data
->is_finished
= 1;
319 cb_data
->status
= status
;
322 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
327 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
329 struct sync_cb_data cb_data
;
331 cb_data
.is_finished
= 0;
333 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
334 nfs_set_error(nfs
, "nfs_close_async failed");
338 wait_for_nfs_reply(nfs
, &cb_data
);
340 return cb_data
.status
;
349 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
351 struct sync_cb_data cb_data
;
353 cb_data
.is_finished
= 0;
354 cb_data
.return_data
= st
;
356 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
357 nfs_set_error(nfs
, "nfs_fstat_async failed");
361 wait_for_nfs_reply(nfs
, &cb_data
);
363 return cb_data
.status
;
370 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
372 struct sync_cb_data
*cb_data
= private_data
;
373 cb_data
->is_finished
= 1;
374 cb_data
->status
= status
;
377 nfs_set_error(nfs
, "pwrite call failed with \"%s\"", (char *)data
);
382 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buf
)
384 struct sync_cb_data cb_data
;
386 cb_data
.is_finished
= 0;
388 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
389 nfs_set_error(nfs
, "nfs_pwrite_async failed");
393 wait_for_nfs_reply(nfs
, &cb_data
);
395 return cb_data
.status
;
401 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buf
)
403 return nfs_pwrite(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buf
);
410 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
412 struct sync_cb_data
*cb_data
= private_data
;
413 cb_data
->is_finished
= 1;
414 cb_data
->status
= status
;
417 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
422 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
424 struct sync_cb_data cb_data
;
426 cb_data
.is_finished
= 0;
428 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
429 nfs_set_error(nfs
, "nfs_fsync_async failed");
433 wait_for_nfs_reply(nfs
, &cb_data
);
435 return cb_data
.status
;
444 static void ftruncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
446 struct sync_cb_data
*cb_data
= private_data
;
447 cb_data
->is_finished
= 1;
448 cb_data
->status
= status
;
451 nfs_set_error(nfs
, "ftruncate call failed with \"%s\"", (char *)data
);
456 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t length
)
458 struct sync_cb_data cb_data
;
460 cb_data
.is_finished
= 0;
462 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_cb
, &cb_data
) != 0) {
463 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
467 wait_for_nfs_reply(nfs
, &cb_data
);
469 return cb_data
.status
;
477 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
479 struct sync_cb_data
*cb_data
= private_data
;
480 cb_data
->is_finished
= 1;
481 cb_data
->status
= status
;
484 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
489 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, uint64_t length
)
491 struct sync_cb_data cb_data
;
493 cb_data
.is_finished
= 0;
495 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
496 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
500 wait_for_nfs_reply(nfs
, &cb_data
);
502 return cb_data
.status
;
512 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
514 struct sync_cb_data
*cb_data
= private_data
;
515 cb_data
->is_finished
= 1;
516 cb_data
->status
= status
;
519 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
524 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
526 struct sync_cb_data cb_data
;
528 cb_data
.is_finished
= 0;
530 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
531 nfs_set_error(nfs
, "nfs_mkdir_async failed");
535 wait_for_nfs_reply(nfs
, &cb_data
);
537 return cb_data
.status
;
547 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
549 struct sync_cb_data
*cb_data
= private_data
;
550 cb_data
->is_finished
= 1;
551 cb_data
->status
= status
;
554 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
559 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
561 struct sync_cb_data cb_data
;
563 cb_data
.is_finished
= 0;
565 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
566 nfs_set_error(nfs
, "nfs_rmdir_async failed");
570 wait_for_nfs_reply(nfs
, &cb_data
);
572 return cb_data
.status
;
580 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
582 struct sync_cb_data
*cb_data
= private_data
;
583 struct nfsfh
*fh
, **nfsfh
;
585 cb_data
->is_finished
= 1;
586 cb_data
->status
= status
;
589 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
594 nfsfh
= cb_data
->return_data
;
598 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
600 struct sync_cb_data cb_data
;
602 cb_data
.is_finished
= 0;
603 cb_data
.return_data
= nfsfh
;
605 if (nfs_creat_async(nfs
, path
, mode
, creat_cb
, &cb_data
) != 0) {
606 nfs_set_error(nfs
, "nfs_creat_async failed");
610 wait_for_nfs_reply(nfs
, &cb_data
);
612 return cb_data
.status
;
618 static void mknod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
620 struct sync_cb_data
*cb_data
= private_data
;
622 cb_data
->is_finished
= 1;
623 cb_data
->status
= status
;
626 nfs_set_error(nfs
, "mknod call failed with \"%s\"", (char *)data
);
631 int nfs_mknod(struct nfs_context
*nfs
, const char *path
, int mode
, int dev
)
633 struct sync_cb_data cb_data
;
635 cb_data
.is_finished
= 0;
637 if (nfs_mknod_async(nfs
, path
, mode
, dev
, mknod_cb
, &cb_data
) != 0) {
638 nfs_set_error(nfs
, "nfs_creat_async failed");
642 wait_for_nfs_reply(nfs
, &cb_data
);
644 return cb_data
.status
;
651 static void unlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
653 struct sync_cb_data
*cb_data
= private_data
;
655 cb_data
->is_finished
= 1;
656 cb_data
->status
= status
;
659 nfs_set_error(nfs
, "unlink call failed with \"%s\"", (char *)data
);
664 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
666 struct sync_cb_data cb_data
;
668 cb_data
.is_finished
= 0;
670 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
671 nfs_set_error(nfs
, "nfs_unlink_async failed");
675 wait_for_nfs_reply(nfs
, &cb_data
);
677 return cb_data
.status
;
685 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
687 struct sync_cb_data
*cb_data
= private_data
;
688 struct nfsdir
*dir
, **nfsdir
;
690 cb_data
->is_finished
= 1;
691 cb_data
->status
= status
;
694 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
699 nfsdir
= cb_data
->return_data
;
703 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
705 struct sync_cb_data cb_data
;
707 cb_data
.is_finished
= 0;
708 cb_data
.return_data
= nfsdir
;
710 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
711 nfs_set_error(nfs
, "nfs_opendir_async failed");
715 wait_for_nfs_reply(nfs
, &cb_data
);
717 return cb_data
.status
;
724 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
726 struct sync_cb_data
*cb_data
= private_data
;
728 cb_data
->is_finished
= 1;
729 cb_data
->status
= status
;
732 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
736 if (cb_data
->return_data
!= NULL
) {
737 memcpy(cb_data
->return_data
, data
, sizeof(uint64_t));
741 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, int whence
, uint64_t *current_offset
)
743 struct sync_cb_data cb_data
;
745 cb_data
.is_finished
= 0;
746 cb_data
.return_data
= current_offset
;
748 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
749 nfs_set_error(nfs
, "nfs_lseek_async failed");
753 wait_for_nfs_reply(nfs
, &cb_data
);
755 return cb_data
.status
;
763 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
765 struct sync_cb_data
*cb_data
= private_data
;
767 cb_data
->is_finished
= 1;
768 cb_data
->status
= status
;
771 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
775 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
778 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
780 struct sync_cb_data cb_data
;
782 cb_data
.is_finished
= 0;
783 cb_data
.return_data
= svfs
;
785 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
786 nfs_set_error(nfs
, "nfs_statvfs_async failed");
790 wait_for_nfs_reply(nfs
, &cb_data
);
792 return cb_data
.status
;
802 static void readlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
804 struct sync_cb_data
*cb_data
= private_data
;
806 cb_data
->is_finished
= 1;
807 cb_data
->status
= status
;
810 nfs_set_error(nfs
, "readlink call failed with \"%s\"", (char *)data
);
814 if (strlen(data
) > (size_t)cb_data
->return_int
) {
815 nfs_set_error(nfs
, "Too small buffer for readlink");
816 cb_data
->status
= -ENAMETOOLONG
;
820 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
823 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
825 struct sync_cb_data cb_data
;
827 cb_data
.is_finished
= 0;
828 cb_data
.return_data
= buf
;
829 cb_data
.return_int
= bufsize
;
831 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
832 nfs_set_error(nfs
, "nfs_readlink_async failed");
836 wait_for_nfs_reply(nfs
, &cb_data
);
838 return cb_data
.status
;
846 static void chmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
848 struct sync_cb_data
*cb_data
= private_data
;
850 cb_data
->is_finished
= 1;
851 cb_data
->status
= status
;
854 nfs_set_error(nfs
, "chmod call failed with \"%s\"", (char *)data
);
859 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
861 struct sync_cb_data cb_data
;
863 cb_data
.is_finished
= 0;
865 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
866 nfs_set_error(nfs
, "nfs_chmod_async failed");
870 wait_for_nfs_reply(nfs
, &cb_data
);
872 return cb_data
.status
;
881 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
883 struct sync_cb_data
*cb_data
= private_data
;
885 cb_data
->is_finished
= 1;
886 cb_data
->status
= status
;
889 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
894 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
896 struct sync_cb_data cb_data
;
898 cb_data
.is_finished
= 0;
900 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
901 nfs_set_error(nfs
, "nfs_fchmod_async failed");
905 wait_for_nfs_reply(nfs
, &cb_data
);
907 return cb_data
.status
;
916 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
918 struct sync_cb_data
*cb_data
= private_data
;
920 cb_data
->is_finished
= 1;
921 cb_data
->status
= status
;
924 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
929 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
931 struct sync_cb_data cb_data
;
933 cb_data
.is_finished
= 0;
935 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
936 nfs_set_error(nfs
, "nfs_chown_async failed");
940 wait_for_nfs_reply(nfs
, &cb_data
);
942 return cb_data
.status
;
948 static void fchown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
950 struct sync_cb_data
*cb_data
= private_data
;
952 cb_data
->is_finished
= 1;
953 cb_data
->status
= status
;
956 nfs_set_error(nfs
, "fchown call failed with \"%s\"", (char *)data
);
961 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
963 struct sync_cb_data cb_data
;
965 cb_data
.is_finished
= 0;
967 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
968 nfs_set_error(nfs
, "nfs_fchown_async failed");
972 wait_for_nfs_reply(nfs
, &cb_data
);
974 return cb_data
.status
;
982 static void utimes_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
984 struct sync_cb_data
*cb_data
= private_data
;
986 cb_data
->is_finished
= 1;
987 cb_data
->status
= status
;
990 nfs_set_error(nfs
, "utimes call failed with \"%s\"", (char *)data
);
995 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
997 struct sync_cb_data cb_data
;
999 cb_data
.is_finished
= 0;
1001 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
1002 nfs_set_error(nfs
, "nfs_utimes_async failed");
1006 wait_for_nfs_reply(nfs
, &cb_data
);
1008 return cb_data
.status
;
1016 static void utime_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1018 struct sync_cb_data
*cb_data
= private_data
;
1020 cb_data
->is_finished
= 1;
1021 cb_data
->status
= status
;
1024 nfs_set_error(nfs
, "utime call failed with \"%s\"", (char *)data
);
1029 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
1031 struct sync_cb_data cb_data
;
1033 cb_data
.is_finished
= 0;
1035 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
1036 nfs_set_error(nfs
, "nfs_utimes_async failed");
1040 wait_for_nfs_reply(nfs
, &cb_data
);
1042 return cb_data
.status
;
1051 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1053 struct sync_cb_data
*cb_data
= private_data
;
1055 cb_data
->is_finished
= 1;
1056 cb_data
->status
= status
;
1059 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
1064 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
1066 struct sync_cb_data cb_data
;
1068 cb_data
.is_finished
= 0;
1070 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
1071 nfs_set_error(nfs
, "nfs_access_async failed");
1075 wait_for_nfs_reply(nfs
, &cb_data
);
1077 return cb_data
.status
;
1085 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1087 struct sync_cb_data
*cb_data
= private_data
;
1089 cb_data
->is_finished
= 1;
1090 cb_data
->status
= status
;
1093 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
1098 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1100 struct sync_cb_data cb_data
;
1102 cb_data
.is_finished
= 0;
1104 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
1105 nfs_set_error(nfs
, "nfs_symlink_async failed");
1109 wait_for_nfs_reply(nfs
, &cb_data
);
1111 return cb_data
.status
;
1119 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1121 struct sync_cb_data
*cb_data
= private_data
;
1123 cb_data
->is_finished
= 1;
1124 cb_data
->status
= status
;
1127 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1132 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1134 struct sync_cb_data cb_data
;
1136 cb_data
.is_finished
= 0;
1138 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1139 nfs_set_error(nfs
, "nfs_rename_async failed");
1143 wait_for_nfs_reply(nfs
, &cb_data
);
1145 return cb_data
.status
;
1153 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1155 struct sync_cb_data
*cb_data
= private_data
;
1157 cb_data
->is_finished
= 1;
1158 cb_data
->status
= status
;
1161 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1166 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1168 struct sync_cb_data cb_data
;
1170 cb_data
.is_finished
= 0;
1172 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1173 nfs_set_error(nfs
, "nfs_link_async failed");
1177 wait_for_nfs_reply(nfs
, &cb_data
);
1179 return cb_data
.status
;
1182 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1184 struct sync_cb_data
*cb_data
= private_data
;
1187 assert(mount_context
->magic
== RPC_CONTEXT_MAGIC
);
1189 cb_data
->is_finished
= 1;
1190 cb_data
->status
= status
;
1191 cb_data
->return_data
= NULL
;
1194 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1198 export
= *(exports
*)data
;
1199 while (export
!= NULL
) {
1202 new_export
= malloc(sizeof(*new_export
));
1203 memset(new_export
, 0, sizeof(*new_export
));
1204 new_export
->ex_dir
= strdup(export
->ex_dir
);
1205 new_export
->ex_next
= cb_data
->return_data
;
1207 cb_data
->return_data
= new_export
;
1209 export
= export
->ex_next
;
1213 struct exportnode
*mount_getexports(const char *server
)
1215 struct sync_cb_data cb_data
;
1216 struct rpc_context
*rpc
;
1219 cb_data
.is_finished
= 0;
1220 cb_data
.return_data
= NULL
;
1222 rpc
= rpc_init_context();
1223 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1224 rpc_destroy_context(rpc
);
1228 wait_for_reply(rpc
, &cb_data
);
1229 rpc_destroy_context(rpc
);
1231 return cb_data
.return_data
;
1234 void mount_free_export_list(struct exportnode
*exports
)
1236 struct exportnode
*tmp
;
1238 while ((tmp
= exports
)) {
1239 exports
= exports
->ex_next
;
1247 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1249 while (srv
!= NULL
) {
1250 struct nfs_server_list
*next
= srv
->next
;
1258 struct nfs_list_data
{
1260 struct nfs_server_list
*srvrs
;
1263 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1265 struct nfs_list_data
*srv_data
= private_data
;
1266 struct sockaddr
*sin
;
1268 struct nfs_server_list
*srvr
;
1270 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1272 if (status
== RPC_STATUS_CANCEL
) {
1276 srv_data
->status
= -1;
1280 sin
= rpc_get_recv_sockaddr(rpc
);
1282 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1283 srv_data
->status
= -1;
1287 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1288 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1289 srv_data
->status
= -1;
1293 /* check for dupes */
1294 for (srvr
= srv_data
->srvrs
; srvr
; srvr
= srvr
->next
) {
1295 if (!strcmp(hostdd
, srvr
->addr
)) {
1300 srvr
= malloc(sizeof(struct nfs_server_list
));
1302 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1303 srv_data
->status
= -1;
1307 srvr
->addr
= strdup(hostdd
);
1308 if (srvr
->addr
== NULL
) {
1309 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1311 srv_data
->status
= -1;
1315 srvr
->next
= srv_data
->srvrs
;
1316 srv_data
->srvrs
= srvr
;
1321 static int send_nfsd_probes(struct rpc_context
*rpc
, INTERFACE_INFO
*InterfaceList
, int numIfs
, struct nfs_list_data
*data
)
1325 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1327 for(i
= 0; i
< numIfs
; i
++)
1331 unsigned long nFlags
= 0;
1333 pAddress
= (SOCKADDR
*) & (InterfaceList
[i
].iiBroadcastAddress
);
1335 if(pAddress
->sa_family
!= AF_INET
)
1338 nFlags
= InterfaceList
[i
].iiFlags
;
1340 if (!(nFlags
& IFF_UP
))
1345 if (nFlags
& IFF_LOOPBACK
)
1350 if (!(nFlags
& IFF_BROADCAST
))
1355 if (getnameinfo(pAddress
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0)
1360 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0)
1365 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0)
1373 struct nfs_server_list
*nfs_find_local_servers(void)
1375 struct rpc_context
*rpc
;
1376 struct nfs_list_data data
= {0, NULL
};
1377 struct timeval tv_start
, tv_current
;
1380 INTERFACE_INFO InterfaceList
[20];
1381 unsigned long nBytesReturned
;
1382 int nNumInterfaces
= 0;
1384 rpc
= rpc_init_udp_context();
1390 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0)
1392 rpc_destroy_context(rpc
);
1396 if (WSAIoctl(rpc_get_fd(rpc
), SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
, sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
1401 nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
1403 for (loop
=0; loop
<3; loop
++)
1405 if (send_nfsd_probes(rpc
, InterfaceList
, nNumInterfaces
, &data
) != 0)
1407 rpc_destroy_context(rpc
);
1411 win32_gettimeofday(&tv_start
, NULL
);
1416 pfd
.fd
= rpc_get_fd(rpc
);
1417 pfd
.events
= rpc_which_events(rpc
);
1419 win32_gettimeofday(&tv_current
, NULL
);
1421 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1422 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1424 if (poll(&pfd
, 1, mpt
) < 0)
1426 free_nfs_srvr_list(data
.srvrs
);
1427 rpc_destroy_context(rpc
);
1430 if (pfd
.revents
== 0)
1435 if (rpc_service(rpc
, pfd
.revents
) < 0)
1442 rpc_destroy_context(rpc
);
1444 if (data
.status
!= 0)
1446 free_nfs_srvr_list(data
.srvrs
);
1453 static int send_nfsd_probes(struct rpc_context
*rpc
, struct ifconf
*ifc
, struct nfs_list_data
*data
)
1457 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1459 for (ptr
=(char *)(ifc
->ifc_buf
); ptr
< (char *)(ifc
->ifc_buf
) + ifc
->ifc_len
; ) {
1463 ifr
= (struct ifreq
*)ptr
;
1464 #ifdef HAVE_SOCKADDR_LEN
1465 if (ifr
->ifr_addr
.sa_len
> sizeof(struct sockaddr
)) {
1466 ptr
+= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
1468 ptr
+= sizeof(ifr
->ifr_name
) + sizeof(struct sockaddr
);
1471 ptr
+= sizeof(struct ifreq
);
1474 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) {
1477 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, ifr
) < 0) {
1480 if (!(ifr
->ifr_flags
& IFF_UP
)) {
1483 if (ifr
->ifr_flags
& IFF_LOOPBACK
) {
1486 if (!(ifr
->ifr_flags
& IFF_BROADCAST
)) {
1489 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, ifr
) < 0) {
1492 if (getnameinfo(&ifr
->ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1495 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1499 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0) {
1507 struct nfs_server_list
*nfs_find_local_servers(void)
1509 struct rpc_context
*rpc
;
1510 struct nfs_list_data data
= {0, NULL
};
1511 struct timeval tv_start
, tv_current
;
1516 rpc
= rpc_init_udp_context();
1521 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1522 rpc_destroy_context(rpc
);
1527 /* get list of all interfaces */
1528 size
= sizeof(struct ifreq
);
1532 while(ifc
.ifc_len
> (size
- sizeof(struct ifreq
))) {
1537 ifc
.ifc_buf
= malloc(size
);
1538 memset(ifc
.ifc_buf
, 0, size
);
1539 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1540 rpc_destroy_context(rpc
);
1546 for (loop
=0; loop
<3; loop
++) {
1547 if (send_nfsd_probes(rpc
, &ifc
, &data
) != 0) {
1548 rpc_destroy_context(rpc
);
1553 gettimeofday(&tv_start
, NULL
);
1557 pfd
.fd
= rpc_get_fd(rpc
);
1558 pfd
.events
= rpc_which_events(rpc
);
1560 gettimeofday(&tv_current
, NULL
);
1562 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1563 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1565 if (poll(&pfd
, 1, mpt
) < 0) {
1566 free_nfs_srvr_list(data
.srvrs
);
1567 rpc_destroy_context(rpc
);
1570 if (pfd
.revents
== 0) {
1574 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1581 rpc_destroy_context(rpc
);
1583 if (data
.status
!= 0) {
1584 free_nfs_srvr_list(data
.srvrs
);