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
21 #include "win32_compat.h"
25 #include <sys/ioctl.h>
27 #include <sys/socket.h>
31 #include "aros_compat.h"
34 #include <netinet/in.h>
36 #define statvfs statfs
38 #include <sys/statvfs.h>
55 #include <sys/types.h>
60 #ifdef HAVE_SYS_SOCKIO_H
61 #include <sys/sockio.h>
64 #include "libnfs-zdr.h"
66 #include "libnfs-raw.h"
67 #include "libnfs-raw-mount.h"
68 #include "libnfs-raw-nfs.h"
69 #include "libnfs-private.h"
80 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
84 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
86 while (!cb_data
->is_finished
) {
88 pfd
.fd
= rpc_get_fd(rpc
);
89 pfd
.events
= rpc_which_events(rpc
);
90 if (poll(&pfd
, 1, -1) < 0) {
91 rpc_set_error(rpc
, "Poll failed");
92 cb_data
->status
= -EIO
;
95 if (rpc_service(rpc
, pfd
.revents
) < 0) {
96 rpc_set_error(rpc
, "rpc_service failed");
97 cb_data
->status
= -EIO
;
100 if (rpc_get_fd(rpc
) == -1) {
101 rpc_set_error(rpc
, "Socket closed\n");
107 static void wait_for_nfs_reply(struct nfs_context
*nfs
, struct sync_cb_data
*cb_data
)
111 while (!cb_data
->is_finished
) {
113 pfd
.fd
= nfs_get_fd(nfs
);
114 pfd
.events
= nfs_which_events(nfs
);
115 if (poll(&pfd
, 1, -1) < 0) {
116 nfs_set_error(nfs
, "Poll failed");
117 cb_data
->status
= -EIO
;
120 if (nfs_service(nfs
, pfd
.revents
) < 0) {
121 nfs_set_error(nfs
, "nfs_service failed");
122 cb_data
->status
= -EIO
;
134 * connect to the server and mount the export
136 static void mount_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
138 struct sync_cb_data
*cb_data
= private_data
;
140 cb_data
->is_finished
= 1;
141 cb_data
->status
= status
;
144 nfs_set_error(nfs
, "mount/mnt call failed with \"%s\"", (char *)data
);
149 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
151 struct sync_cb_data cb_data
;
152 struct rpc_context
*rpc
= nfs_get_rpc_context(nfs
);
154 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
156 cb_data
.is_finished
= 0;
158 if (nfs_mount_async(nfs
, server
, export
, mount_cb
, &cb_data
) != 0) {
159 nfs_set_error(nfs
, "nfs_mount_async failed");
163 wait_for_nfs_reply(nfs
, &cb_data
);
165 /* Dont want any more callbacks even if the socket is closed */
166 rpc
->connect_cb
= NULL
;
168 return cb_data
.status
;
175 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
177 struct sync_cb_data
*cb_data
= private_data
;
179 cb_data
->is_finished
= 1;
180 cb_data
->status
= status
;
183 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
187 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
190 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
192 struct sync_cb_data cb_data
;
194 cb_data
.is_finished
= 0;
195 cb_data
.return_data
= st
;
197 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
198 nfs_set_error(nfs
, "nfs_stat_async failed");
202 wait_for_nfs_reply(nfs
, &cb_data
);
204 return cb_data
.status
;
213 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
215 struct sync_cb_data
*cb_data
= private_data
;
216 struct nfsfh
*fh
, **nfsfh
;
218 cb_data
->is_finished
= 1;
219 cb_data
->status
= status
;
222 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
227 nfsfh
= cb_data
->return_data
;
231 int nfs_open(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
233 struct sync_cb_data cb_data
;
235 cb_data
.is_finished
= 0;
236 cb_data
.return_data
= nfsfh
;
238 if (nfs_open_async(nfs
, path
, mode
, open_cb
, &cb_data
) != 0) {
239 nfs_set_error(nfs
, "nfs_open_async failed");
243 wait_for_nfs_reply(nfs
, &cb_data
);
245 return cb_data
.status
;
254 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
256 struct sync_cb_data
*cb_data
= private_data
;
258 cb_data
->is_finished
= 1;
259 cb_data
->status
= status
;
262 nfs_set_error(nfs
, "pread call failed with \"%s\"", (char *)data
);
266 buffer
= cb_data
->return_data
;
267 memcpy(buffer
, (char *)data
, status
);
270 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buffer
)
272 struct sync_cb_data cb_data
;
274 cb_data
.is_finished
= 0;
275 cb_data
.return_data
= buffer
;
277 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
278 nfs_set_error(nfs
, "nfs_pread_async failed");
282 wait_for_nfs_reply(nfs
, &cb_data
);
284 return cb_data
.status
;
290 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buffer
)
292 return nfs_pread(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buffer
);
298 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
300 struct sync_cb_data
*cb_data
= private_data
;
301 cb_data
->is_finished
= 1;
302 cb_data
->status
= status
;
305 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
310 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
312 struct sync_cb_data cb_data
;
314 cb_data
.is_finished
= 0;
316 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
317 nfs_set_error(nfs
, "nfs_close_async failed");
321 wait_for_nfs_reply(nfs
, &cb_data
);
323 return cb_data
.status
;
332 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
334 struct sync_cb_data cb_data
;
336 cb_data
.is_finished
= 0;
337 cb_data
.return_data
= st
;
339 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
340 nfs_set_error(nfs
, "nfs_fstat_async failed");
344 wait_for_nfs_reply(nfs
, &cb_data
);
346 return cb_data
.status
;
353 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
355 struct sync_cb_data
*cb_data
= private_data
;
356 cb_data
->is_finished
= 1;
357 cb_data
->status
= status
;
360 nfs_set_error(nfs
, "pwrite call failed with \"%s\"", (char *)data
);
365 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buf
)
367 struct sync_cb_data cb_data
;
369 cb_data
.is_finished
= 0;
371 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
372 nfs_set_error(nfs
, "nfs_pwrite_async failed");
376 wait_for_nfs_reply(nfs
, &cb_data
);
378 return cb_data
.status
;
384 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buf
)
386 return nfs_pwrite(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buf
);
393 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
395 struct sync_cb_data
*cb_data
= private_data
;
396 cb_data
->is_finished
= 1;
397 cb_data
->status
= status
;
400 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
405 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
407 struct sync_cb_data cb_data
;
409 cb_data
.is_finished
= 0;
411 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
412 nfs_set_error(nfs
, "nfs_fsync_async failed");
416 wait_for_nfs_reply(nfs
, &cb_data
);
418 return cb_data
.status
;
427 static void ftruncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
429 struct sync_cb_data
*cb_data
= private_data
;
430 cb_data
->is_finished
= 1;
431 cb_data
->status
= status
;
434 nfs_set_error(nfs
, "ftruncate call failed with \"%s\"", (char *)data
);
439 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t length
)
441 struct sync_cb_data cb_data
;
443 cb_data
.is_finished
= 0;
445 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_cb
, &cb_data
) != 0) {
446 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
450 wait_for_nfs_reply(nfs
, &cb_data
);
452 return cb_data
.status
;
460 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
462 struct sync_cb_data
*cb_data
= private_data
;
463 cb_data
->is_finished
= 1;
464 cb_data
->status
= status
;
467 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
472 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, uint64_t length
)
474 struct sync_cb_data cb_data
;
476 cb_data
.is_finished
= 0;
478 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
479 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
483 wait_for_nfs_reply(nfs
, &cb_data
);
485 return cb_data
.status
;
495 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
497 struct sync_cb_data
*cb_data
= private_data
;
498 cb_data
->is_finished
= 1;
499 cb_data
->status
= status
;
502 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
507 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
509 struct sync_cb_data cb_data
;
511 cb_data
.is_finished
= 0;
513 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
514 nfs_set_error(nfs
, "nfs_mkdir_async failed");
518 wait_for_nfs_reply(nfs
, &cb_data
);
520 return cb_data
.status
;
530 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
532 struct sync_cb_data
*cb_data
= private_data
;
533 cb_data
->is_finished
= 1;
534 cb_data
->status
= status
;
537 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
542 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
544 struct sync_cb_data cb_data
;
546 cb_data
.is_finished
= 0;
548 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
549 nfs_set_error(nfs
, "nfs_rmdir_async failed");
553 wait_for_nfs_reply(nfs
, &cb_data
);
555 return cb_data
.status
;
563 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
565 struct sync_cb_data
*cb_data
= private_data
;
566 struct nfsfh
*fh
, **nfsfh
;
568 cb_data
->is_finished
= 1;
569 cb_data
->status
= status
;
572 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
577 nfsfh
= cb_data
->return_data
;
581 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
583 struct sync_cb_data cb_data
;
585 cb_data
.is_finished
= 0;
586 cb_data
.return_data
= nfsfh
;
588 if (nfs_creat_async(nfs
, path
, mode
, creat_cb
, &cb_data
) != 0) {
589 nfs_set_error(nfs
, "nfs_creat_async failed");
593 wait_for_nfs_reply(nfs
, &cb_data
);
595 return cb_data
.status
;
601 static void mknod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
603 struct sync_cb_data
*cb_data
= private_data
;
605 cb_data
->is_finished
= 1;
606 cb_data
->status
= status
;
609 nfs_set_error(nfs
, "mknod call failed with \"%s\"", (char *)data
);
614 int nfs_mknod(struct nfs_context
*nfs
, const char *path
, int mode
, int dev
)
616 struct sync_cb_data cb_data
;
618 cb_data
.is_finished
= 0;
620 if (nfs_mknod_async(nfs
, path
, mode
, dev
, mknod_cb
, &cb_data
) != 0) {
621 nfs_set_error(nfs
, "nfs_creat_async failed");
625 wait_for_nfs_reply(nfs
, &cb_data
);
627 return cb_data
.status
;
634 static void unlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
636 struct sync_cb_data
*cb_data
= private_data
;
638 cb_data
->is_finished
= 1;
639 cb_data
->status
= status
;
642 nfs_set_error(nfs
, "unlink call failed with \"%s\"", (char *)data
);
647 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
649 struct sync_cb_data cb_data
;
651 cb_data
.is_finished
= 0;
653 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
654 nfs_set_error(nfs
, "nfs_unlink_async failed");
658 wait_for_nfs_reply(nfs
, &cb_data
);
660 return cb_data
.status
;
668 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
670 struct sync_cb_data
*cb_data
= private_data
;
671 struct nfsdir
*dir
, **nfsdir
;
673 cb_data
->is_finished
= 1;
674 cb_data
->status
= status
;
677 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
682 nfsdir
= cb_data
->return_data
;
686 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
688 struct sync_cb_data cb_data
;
690 cb_data
.is_finished
= 0;
691 cb_data
.return_data
= nfsdir
;
693 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
694 nfs_set_error(nfs
, "nfs_opendir_async failed");
698 wait_for_nfs_reply(nfs
, &cb_data
);
700 return cb_data
.status
;
707 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
709 struct sync_cb_data
*cb_data
= private_data
;
711 cb_data
->is_finished
= 1;
712 cb_data
->status
= status
;
715 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
719 if (cb_data
->return_data
!= NULL
) {
720 memcpy(cb_data
->return_data
, data
, sizeof(uint64_t));
724 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, int whence
, uint64_t *current_offset
)
726 struct sync_cb_data cb_data
;
728 cb_data
.is_finished
= 0;
729 cb_data
.return_data
= current_offset
;
731 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
732 nfs_set_error(nfs
, "nfs_lseek_async failed");
736 wait_for_nfs_reply(nfs
, &cb_data
);
738 return cb_data
.status
;
746 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
748 struct sync_cb_data
*cb_data
= private_data
;
750 cb_data
->is_finished
= 1;
751 cb_data
->status
= status
;
754 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
758 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
761 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
763 struct sync_cb_data cb_data
;
765 cb_data
.is_finished
= 0;
766 cb_data
.return_data
= svfs
;
768 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
769 nfs_set_error(nfs
, "nfs_statvfs_async failed");
773 wait_for_nfs_reply(nfs
, &cb_data
);
775 return cb_data
.status
;
785 static void readlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
787 struct sync_cb_data
*cb_data
= private_data
;
789 cb_data
->is_finished
= 1;
790 cb_data
->status
= status
;
793 nfs_set_error(nfs
, "readlink call failed with \"%s\"", (char *)data
);
797 if (strlen(data
) > (size_t)cb_data
->return_int
) {
798 nfs_set_error(nfs
, "Too small buffer for readlink");
799 cb_data
->status
= -ENAMETOOLONG
;
803 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
806 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
808 struct sync_cb_data cb_data
;
810 cb_data
.is_finished
= 0;
811 cb_data
.return_data
= buf
;
812 cb_data
.return_int
= bufsize
;
814 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
815 nfs_set_error(nfs
, "nfs_readlink_async failed");
819 wait_for_nfs_reply(nfs
, &cb_data
);
821 return cb_data
.status
;
829 static void chmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
831 struct sync_cb_data
*cb_data
= private_data
;
833 cb_data
->is_finished
= 1;
834 cb_data
->status
= status
;
837 nfs_set_error(nfs
, "chmod call failed with \"%s\"", (char *)data
);
842 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
844 struct sync_cb_data cb_data
;
846 cb_data
.is_finished
= 0;
848 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
849 nfs_set_error(nfs
, "nfs_chmod_async failed");
853 wait_for_nfs_reply(nfs
, &cb_data
);
855 return cb_data
.status
;
864 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
866 struct sync_cb_data
*cb_data
= private_data
;
868 cb_data
->is_finished
= 1;
869 cb_data
->status
= status
;
872 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
877 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
879 struct sync_cb_data cb_data
;
881 cb_data
.is_finished
= 0;
883 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
884 nfs_set_error(nfs
, "nfs_fchmod_async failed");
888 wait_for_nfs_reply(nfs
, &cb_data
);
890 return cb_data
.status
;
899 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
901 struct sync_cb_data
*cb_data
= private_data
;
903 cb_data
->is_finished
= 1;
904 cb_data
->status
= status
;
907 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
912 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
914 struct sync_cb_data cb_data
;
916 cb_data
.is_finished
= 0;
918 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
919 nfs_set_error(nfs
, "nfs_chown_async failed");
923 wait_for_nfs_reply(nfs
, &cb_data
);
925 return cb_data
.status
;
931 static void fchown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
933 struct sync_cb_data
*cb_data
= private_data
;
935 cb_data
->is_finished
= 1;
936 cb_data
->status
= status
;
939 nfs_set_error(nfs
, "fchown call failed with \"%s\"", (char *)data
);
944 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
946 struct sync_cb_data cb_data
;
948 cb_data
.is_finished
= 0;
950 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
951 nfs_set_error(nfs
, "nfs_fchown_async failed");
955 wait_for_nfs_reply(nfs
, &cb_data
);
957 return cb_data
.status
;
965 static void utimes_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
967 struct sync_cb_data
*cb_data
= private_data
;
969 cb_data
->is_finished
= 1;
970 cb_data
->status
= status
;
973 nfs_set_error(nfs
, "utimes call failed with \"%s\"", (char *)data
);
978 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
980 struct sync_cb_data cb_data
;
982 cb_data
.is_finished
= 0;
984 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
985 nfs_set_error(nfs
, "nfs_utimes_async failed");
989 wait_for_nfs_reply(nfs
, &cb_data
);
991 return cb_data
.status
;
999 static void utime_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1001 struct sync_cb_data
*cb_data
= private_data
;
1003 cb_data
->is_finished
= 1;
1004 cb_data
->status
= status
;
1007 nfs_set_error(nfs
, "utime call failed with \"%s\"", (char *)data
);
1012 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
1014 struct sync_cb_data cb_data
;
1016 cb_data
.is_finished
= 0;
1018 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
1019 nfs_set_error(nfs
, "nfs_utimes_async failed");
1023 wait_for_nfs_reply(nfs
, &cb_data
);
1025 return cb_data
.status
;
1034 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1036 struct sync_cb_data
*cb_data
= private_data
;
1038 cb_data
->is_finished
= 1;
1039 cb_data
->status
= status
;
1042 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
1047 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
1049 struct sync_cb_data cb_data
;
1051 cb_data
.is_finished
= 0;
1053 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
1054 nfs_set_error(nfs
, "nfs_access_async failed");
1058 wait_for_nfs_reply(nfs
, &cb_data
);
1060 return cb_data
.status
;
1068 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1070 struct sync_cb_data
*cb_data
= private_data
;
1072 cb_data
->is_finished
= 1;
1073 cb_data
->status
= status
;
1076 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
1081 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1083 struct sync_cb_data cb_data
;
1085 cb_data
.is_finished
= 0;
1087 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
1088 nfs_set_error(nfs
, "nfs_symlink_async failed");
1092 wait_for_nfs_reply(nfs
, &cb_data
);
1094 return cb_data
.status
;
1102 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1104 struct sync_cb_data
*cb_data
= private_data
;
1106 cb_data
->is_finished
= 1;
1107 cb_data
->status
= status
;
1110 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1115 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1117 struct sync_cb_data cb_data
;
1119 cb_data
.is_finished
= 0;
1121 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1122 nfs_set_error(nfs
, "nfs_rename_async failed");
1126 wait_for_nfs_reply(nfs
, &cb_data
);
1128 return cb_data
.status
;
1136 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1138 struct sync_cb_data
*cb_data
= private_data
;
1140 cb_data
->is_finished
= 1;
1141 cb_data
->status
= status
;
1144 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1149 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1151 struct sync_cb_data cb_data
;
1153 cb_data
.is_finished
= 0;
1155 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1156 nfs_set_error(nfs
, "nfs_link_async failed");
1160 wait_for_nfs_reply(nfs
, &cb_data
);
1162 return cb_data
.status
;
1165 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1167 struct sync_cb_data
*cb_data
= private_data
;
1170 assert(mount_context
->magic
== RPC_CONTEXT_MAGIC
);
1172 cb_data
->is_finished
= 1;
1173 cb_data
->status
= status
;
1174 cb_data
->return_data
= NULL
;
1177 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1181 export
= *(exports
*)data
;
1182 while (export
!= NULL
) {
1185 new_export
= malloc(sizeof(*new_export
));
1186 memset(new_export
, 0, sizeof(*new_export
));
1187 new_export
->ex_dir
= strdup(export
->ex_dir
);
1188 new_export
->ex_next
= cb_data
->return_data
;
1190 cb_data
->return_data
= new_export
;
1192 export
= export
->ex_next
;
1196 struct exportnode
*mount_getexports(const char *server
)
1198 struct sync_cb_data cb_data
;
1199 struct rpc_context
*rpc
;
1202 cb_data
.is_finished
= 0;
1203 cb_data
.return_data
= NULL
;
1205 rpc
= rpc_init_context();
1206 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1207 rpc_destroy_context(rpc
);
1211 wait_for_reply(rpc
, &cb_data
);
1212 rpc_destroy_context(rpc
);
1214 return cb_data
.return_data
;
1217 void mount_free_export_list(struct exportnode
*exports
)
1219 struct exportnode
*tmp
;
1221 while ((tmp
= exports
)) {
1222 exports
= exports
->ex_next
;
1230 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1232 while (srv
!= NULL
) {
1233 struct nfs_server_list
*next
= srv
->next
;
1241 struct nfs_list_data
{
1243 struct nfs_server_list
*srvrs
;
1246 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1248 struct nfs_list_data
*srv_data
= private_data
;
1249 struct sockaddr
*sin
;
1251 struct nfs_server_list
*srvr
;
1253 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1255 if (status
== RPC_STATUS_CANCEL
) {
1259 srv_data
->status
= -1;
1263 sin
= rpc_get_recv_sockaddr(rpc
);
1265 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1266 srv_data
->status
= -1;
1270 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1271 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1272 srv_data
->status
= -1;
1276 /* check for dupes */
1277 for (srvr
= srv_data
->srvrs
; srvr
; srvr
= srvr
->next
) {
1278 if (!strcmp(hostdd
, srvr
->addr
)) {
1283 srvr
= malloc(sizeof(struct nfs_server_list
));
1285 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1286 srv_data
->status
= -1;
1290 srvr
->addr
= strdup(hostdd
);
1291 if (srvr
->addr
== NULL
) {
1292 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1294 srv_data
->status
= -1;
1298 srvr
->next
= srv_data
->srvrs
;
1299 srv_data
->srvrs
= srvr
;
1304 static int send_nfsd_probes(struct rpc_context
*rpc
, INTERFACE_INFO
*InterfaceList
, int numIfs
, struct nfs_list_data
*data
)
1308 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1310 for(i
= 0; i
< numIfs
; i
++)
1314 unsigned long nFlags
= 0;
1316 pAddress
= (SOCKADDR
*) & (InterfaceList
[i
].iiBroadcastAddress
);
1318 if(pAddress
->sa_family
!= AF_INET
)
1321 nFlags
= InterfaceList
[i
].iiFlags
;
1323 if (!(nFlags
& IFF_UP
))
1328 if (nFlags
& IFF_LOOPBACK
)
1333 if (!(nFlags
& IFF_BROADCAST
))
1338 if (getnameinfo(pAddress
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0)
1343 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0)
1348 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0)
1356 struct nfs_server_list
*nfs_find_local_servers(void)
1358 struct rpc_context
*rpc
;
1359 struct nfs_list_data data
= {0, NULL
};
1360 struct timeval tv_start
, tv_current
;
1363 INTERFACE_INFO InterfaceList
[20];
1364 unsigned long nBytesReturned
;
1365 int nNumInterfaces
= 0;
1367 rpc
= rpc_init_udp_context();
1373 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0)
1375 rpc_destroy_context(rpc
);
1379 if (WSAIoctl(rpc_get_fd(rpc
), SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
, sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
1384 nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
1386 for (loop
=0; loop
<3; loop
++)
1388 if (send_nfsd_probes(rpc
, InterfaceList
, nNumInterfaces
, &data
) != 0)
1390 rpc_destroy_context(rpc
);
1394 win32_gettimeofday(&tv_start
, NULL
);
1399 pfd
.fd
= rpc_get_fd(rpc
);
1400 pfd
.events
= rpc_which_events(rpc
);
1402 win32_gettimeofday(&tv_current
, NULL
);
1404 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1405 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1407 if (poll(&pfd
, 1, mpt
) < 0)
1409 free_nfs_srvr_list(data
.srvrs
);
1410 rpc_destroy_context(rpc
);
1413 if (pfd
.revents
== 0)
1418 if (rpc_service(rpc
, pfd
.revents
) < 0)
1425 rpc_destroy_context(rpc
);
1427 if (data
.status
!= 0)
1429 free_nfs_srvr_list(data
.srvrs
);
1436 static int send_nfsd_probes(struct rpc_context
*rpc
, struct ifconf
*ifc
, struct nfs_list_data
*data
)
1440 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1442 for (ptr
=(char *)(ifc
->ifc_buf
); ptr
< (char *)(ifc
->ifc_buf
) + ifc
->ifc_len
; ) {
1446 ifr
= (struct ifreq
*)ptr
;
1447 #ifdef HAVE_SOCKADDR_LEN
1448 if (ifr
->ifr_addr
.sa_len
> sizeof(struct sockaddr
)) {
1449 ptr
+= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
1451 ptr
+= sizeof(ifr
->ifr_name
) + sizeof(struct sockaddr
);
1454 ptr
+= sizeof(struct ifreq
);
1457 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) {
1460 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, ifr
) < 0) {
1463 if (!(ifr
->ifr_flags
& IFF_UP
)) {
1466 if (ifr
->ifr_flags
& IFF_LOOPBACK
) {
1469 if (!(ifr
->ifr_flags
& IFF_BROADCAST
)) {
1472 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, ifr
) < 0) {
1475 if (getnameinfo(&ifr
->ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1478 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1482 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0) {
1490 struct nfs_server_list
*nfs_find_local_servers(void)
1492 struct rpc_context
*rpc
;
1493 struct nfs_list_data data
= {0, NULL
};
1494 struct timeval tv_start
, tv_current
;
1499 rpc
= rpc_init_udp_context();
1504 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1505 rpc_destroy_context(rpc
);
1510 /* get list of all interfaces */
1511 size
= sizeof(struct ifreq
);
1515 while(ifc
.ifc_len
> (size
- sizeof(struct ifreq
))) {
1520 ifc
.ifc_buf
= malloc(size
);
1521 memset(ifc
.ifc_buf
, 0, size
);
1522 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1523 rpc_destroy_context(rpc
);
1529 for (loop
=0; loop
<3; loop
++) {
1530 if (send_nfsd_probes(rpc
, &ifc
, &data
) != 0) {
1531 rpc_destroy_context(rpc
);
1536 gettimeofday(&tv_start
, NULL
);
1540 pfd
.fd
= rpc_get_fd(rpc
);
1541 pfd
.events
= rpc_which_events(rpc
);
1543 gettimeofday(&tv_current
, NULL
);
1545 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1546 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1548 if (poll(&pfd
, 1, mpt
) < 0) {
1549 free_nfs_srvr_list(data
.srvrs
);
1550 rpc_destroy_context(rpc
);
1553 if (pfd
.revents
== 0) {
1557 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1564 rpc_destroy_context(rpc
);
1566 if (data
.status
!= 0) {
1567 free_nfs_srvr_list(data
.srvrs
);