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"
27 #include <sys/ioctl.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>
57 #include <sys/types.h>
62 #ifdef HAVE_SYS_SOCKIO_H
63 #include <sys/sockio.h>
66 #include "libnfs-zdr.h"
68 #include "libnfs-raw.h"
69 #include "libnfs-raw-mount.h"
70 #include "libnfs-raw-nfs.h"
71 #include "libnfs-private.h"
82 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
86 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
88 while (!cb_data
->is_finished
) {
90 pfd
.fd
= rpc_get_fd(rpc
);
91 pfd
.events
= rpc_which_events(rpc
);
92 if (poll(&pfd
, 1, -1) < 0) {
93 rpc_set_error(rpc
, "Poll failed");
94 cb_data
->status
= -EIO
;
97 if (rpc_service(rpc
, pfd
.revents
) < 0) {
98 rpc_set_error(rpc
, "rpc_service failed");
99 cb_data
->status
= -EIO
;
102 if (rpc_get_fd(rpc
) == -1) {
103 rpc_set_error(rpc
, "Socket closed\n");
109 static void wait_for_nfs_reply(struct nfs_context
*nfs
, struct sync_cb_data
*cb_data
)
113 while (!cb_data
->is_finished
) {
115 pfd
.fd
= nfs_get_fd(nfs
);
116 pfd
.events
= nfs_which_events(nfs
);
117 if (poll(&pfd
, 1, -1) < 0) {
118 nfs_set_error(nfs
, "Poll failed");
119 cb_data
->status
= -EIO
;
122 if (nfs_service(nfs
, pfd
.revents
) < 0) {
123 nfs_set_error(nfs
, "nfs_service failed");
124 cb_data
->status
= -EIO
;
136 * connect to the server and mount the export
138 static void mount_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
140 struct sync_cb_data
*cb_data
= private_data
;
142 cb_data
->is_finished
= 1;
143 cb_data
->status
= status
;
146 nfs_set_error(nfs
, "mount/mnt call failed with \"%s\"", (char *)data
);
151 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
153 struct sync_cb_data cb_data
;
154 struct rpc_context
*rpc
= nfs_get_rpc_context(nfs
);
156 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
158 cb_data
.is_finished
= 0;
160 if (nfs_mount_async(nfs
, server
, export
, mount_cb
, &cb_data
) != 0) {
161 nfs_set_error(nfs
, "nfs_mount_async failed");
165 wait_for_nfs_reply(nfs
, &cb_data
);
167 /* Dont want any more callbacks even if the socket is closed */
168 rpc
->connect_cb
= NULL
;
170 return cb_data
.status
;
177 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
179 struct sync_cb_data
*cb_data
= private_data
;
181 cb_data
->is_finished
= 1;
182 cb_data
->status
= status
;
185 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
189 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
192 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
194 struct sync_cb_data cb_data
;
196 cb_data
.is_finished
= 0;
197 cb_data
.return_data
= st
;
199 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
200 nfs_set_error(nfs
, "nfs_stat_async failed");
204 wait_for_nfs_reply(nfs
, &cb_data
);
206 return cb_data
.status
;
215 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
217 struct sync_cb_data
*cb_data
= private_data
;
218 struct nfsfh
*fh
, **nfsfh
;
220 cb_data
->is_finished
= 1;
221 cb_data
->status
= status
;
224 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
229 nfsfh
= cb_data
->return_data
;
233 int nfs_open(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
235 struct sync_cb_data cb_data
;
237 cb_data
.is_finished
= 0;
238 cb_data
.return_data
= nfsfh
;
240 if (nfs_open_async(nfs
, path
, mode
, open_cb
, &cb_data
) != 0) {
241 nfs_set_error(nfs
, "nfs_open_async failed");
245 wait_for_nfs_reply(nfs
, &cb_data
);
247 return cb_data
.status
;
256 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
258 struct sync_cb_data
*cb_data
= private_data
;
260 cb_data
->is_finished
= 1;
261 cb_data
->status
= status
;
264 nfs_set_error(nfs
, "pread call failed with \"%s\"", (char *)data
);
268 buffer
= cb_data
->return_data
;
269 memcpy(buffer
, (char *)data
, status
);
272 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buffer
)
274 struct sync_cb_data cb_data
;
276 cb_data
.is_finished
= 0;
277 cb_data
.return_data
= buffer
;
279 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
280 nfs_set_error(nfs
, "nfs_pread_async failed");
284 wait_for_nfs_reply(nfs
, &cb_data
);
286 return cb_data
.status
;
292 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buffer
)
294 return nfs_pread(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buffer
);
300 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
302 struct sync_cb_data
*cb_data
= private_data
;
303 cb_data
->is_finished
= 1;
304 cb_data
->status
= status
;
307 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
312 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
314 struct sync_cb_data cb_data
;
316 cb_data
.is_finished
= 0;
318 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
319 nfs_set_error(nfs
, "nfs_close_async failed");
323 wait_for_nfs_reply(nfs
, &cb_data
);
325 return cb_data
.status
;
334 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
336 struct sync_cb_data cb_data
;
338 cb_data
.is_finished
= 0;
339 cb_data
.return_data
= st
;
341 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
342 nfs_set_error(nfs
, "nfs_fstat_async failed");
346 wait_for_nfs_reply(nfs
, &cb_data
);
348 return cb_data
.status
;
355 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
357 struct sync_cb_data
*cb_data
= private_data
;
358 cb_data
->is_finished
= 1;
359 cb_data
->status
= status
;
362 nfs_set_error(nfs
, "pwrite call failed with \"%s\"", (char *)data
);
367 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buf
)
369 struct sync_cb_data cb_data
;
371 cb_data
.is_finished
= 0;
373 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
374 nfs_set_error(nfs
, "nfs_pwrite_async failed");
378 wait_for_nfs_reply(nfs
, &cb_data
);
380 return cb_data
.status
;
386 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buf
)
388 return nfs_pwrite(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buf
);
395 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
397 struct sync_cb_data
*cb_data
= private_data
;
398 cb_data
->is_finished
= 1;
399 cb_data
->status
= status
;
402 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
407 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
409 struct sync_cb_data cb_data
;
411 cb_data
.is_finished
= 0;
413 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
414 nfs_set_error(nfs
, "nfs_fsync_async failed");
418 wait_for_nfs_reply(nfs
, &cb_data
);
420 return cb_data
.status
;
429 static void ftruncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
431 struct sync_cb_data
*cb_data
= private_data
;
432 cb_data
->is_finished
= 1;
433 cb_data
->status
= status
;
436 nfs_set_error(nfs
, "ftruncate call failed with \"%s\"", (char *)data
);
441 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t length
)
443 struct sync_cb_data cb_data
;
445 cb_data
.is_finished
= 0;
447 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_cb
, &cb_data
) != 0) {
448 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
452 wait_for_nfs_reply(nfs
, &cb_data
);
454 return cb_data
.status
;
462 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
464 struct sync_cb_data
*cb_data
= private_data
;
465 cb_data
->is_finished
= 1;
466 cb_data
->status
= status
;
469 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
474 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, uint64_t length
)
476 struct sync_cb_data cb_data
;
478 cb_data
.is_finished
= 0;
480 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
481 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
485 wait_for_nfs_reply(nfs
, &cb_data
);
487 return cb_data
.status
;
497 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
499 struct sync_cb_data
*cb_data
= private_data
;
500 cb_data
->is_finished
= 1;
501 cb_data
->status
= status
;
504 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
509 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
511 struct sync_cb_data cb_data
;
513 cb_data
.is_finished
= 0;
515 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
516 nfs_set_error(nfs
, "nfs_mkdir_async failed");
520 wait_for_nfs_reply(nfs
, &cb_data
);
522 return cb_data
.status
;
532 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
534 struct sync_cb_data
*cb_data
= private_data
;
535 cb_data
->is_finished
= 1;
536 cb_data
->status
= status
;
539 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
544 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
546 struct sync_cb_data cb_data
;
548 cb_data
.is_finished
= 0;
550 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
551 nfs_set_error(nfs
, "nfs_rmdir_async failed");
555 wait_for_nfs_reply(nfs
, &cb_data
);
557 return cb_data
.status
;
565 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
567 struct sync_cb_data
*cb_data
= private_data
;
568 struct nfsfh
*fh
, **nfsfh
;
570 cb_data
->is_finished
= 1;
571 cb_data
->status
= status
;
574 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
579 nfsfh
= cb_data
->return_data
;
583 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
585 struct sync_cb_data cb_data
;
587 cb_data
.is_finished
= 0;
588 cb_data
.return_data
= nfsfh
;
590 if (nfs_creat_async(nfs
, path
, mode
, creat_cb
, &cb_data
) != 0) {
591 nfs_set_error(nfs
, "nfs_creat_async failed");
595 wait_for_nfs_reply(nfs
, &cb_data
);
597 return cb_data
.status
;
603 static void mknod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
605 struct sync_cb_data
*cb_data
= private_data
;
607 cb_data
->is_finished
= 1;
608 cb_data
->status
= status
;
611 nfs_set_error(nfs
, "mknod call failed with \"%s\"", (char *)data
);
616 int nfs_mknod(struct nfs_context
*nfs
, const char *path
, int mode
, int dev
)
618 struct sync_cb_data cb_data
;
620 cb_data
.is_finished
= 0;
622 if (nfs_mknod_async(nfs
, path
, mode
, dev
, mknod_cb
, &cb_data
) != 0) {
623 nfs_set_error(nfs
, "nfs_creat_async failed");
627 wait_for_nfs_reply(nfs
, &cb_data
);
629 return cb_data
.status
;
636 static void unlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
638 struct sync_cb_data
*cb_data
= private_data
;
640 cb_data
->is_finished
= 1;
641 cb_data
->status
= status
;
644 nfs_set_error(nfs
, "unlink call failed with \"%s\"", (char *)data
);
649 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
651 struct sync_cb_data cb_data
;
653 cb_data
.is_finished
= 0;
655 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
656 nfs_set_error(nfs
, "nfs_unlink_async failed");
660 wait_for_nfs_reply(nfs
, &cb_data
);
662 return cb_data
.status
;
670 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
672 struct sync_cb_data
*cb_data
= private_data
;
673 struct nfsdir
*dir
, **nfsdir
;
675 cb_data
->is_finished
= 1;
676 cb_data
->status
= status
;
679 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
684 nfsdir
= cb_data
->return_data
;
688 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
690 struct sync_cb_data cb_data
;
692 cb_data
.is_finished
= 0;
693 cb_data
.return_data
= nfsdir
;
695 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
696 nfs_set_error(nfs
, "nfs_opendir_async failed");
700 wait_for_nfs_reply(nfs
, &cb_data
);
702 return cb_data
.status
;
709 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
711 struct sync_cb_data
*cb_data
= private_data
;
713 cb_data
->is_finished
= 1;
714 cb_data
->status
= status
;
717 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
721 if (cb_data
->return_data
!= NULL
) {
722 memcpy(cb_data
->return_data
, data
, sizeof(uint64_t));
726 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, int whence
, uint64_t *current_offset
)
728 struct sync_cb_data cb_data
;
730 cb_data
.is_finished
= 0;
731 cb_data
.return_data
= current_offset
;
733 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
734 nfs_set_error(nfs
, "nfs_lseek_async failed");
738 wait_for_nfs_reply(nfs
, &cb_data
);
740 return cb_data
.status
;
748 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
750 struct sync_cb_data
*cb_data
= private_data
;
752 cb_data
->is_finished
= 1;
753 cb_data
->status
= status
;
756 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
760 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
763 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
765 struct sync_cb_data cb_data
;
767 cb_data
.is_finished
= 0;
768 cb_data
.return_data
= svfs
;
770 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
771 nfs_set_error(nfs
, "nfs_statvfs_async failed");
775 wait_for_nfs_reply(nfs
, &cb_data
);
777 return cb_data
.status
;
787 static void readlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
789 struct sync_cb_data
*cb_data
= private_data
;
791 cb_data
->is_finished
= 1;
792 cb_data
->status
= status
;
795 nfs_set_error(nfs
, "readlink call failed with \"%s\"", (char *)data
);
799 if (strlen(data
) > (size_t)cb_data
->return_int
) {
800 nfs_set_error(nfs
, "Too small buffer for readlink");
801 cb_data
->status
= -ENAMETOOLONG
;
805 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
808 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
810 struct sync_cb_data cb_data
;
812 cb_data
.is_finished
= 0;
813 cb_data
.return_data
= buf
;
814 cb_data
.return_int
= bufsize
;
816 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
817 nfs_set_error(nfs
, "nfs_readlink_async failed");
821 wait_for_nfs_reply(nfs
, &cb_data
);
823 return cb_data
.status
;
831 static void chmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
833 struct sync_cb_data
*cb_data
= private_data
;
835 cb_data
->is_finished
= 1;
836 cb_data
->status
= status
;
839 nfs_set_error(nfs
, "chmod call failed with \"%s\"", (char *)data
);
844 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
846 struct sync_cb_data cb_data
;
848 cb_data
.is_finished
= 0;
850 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
851 nfs_set_error(nfs
, "nfs_chmod_async failed");
855 wait_for_nfs_reply(nfs
, &cb_data
);
857 return cb_data
.status
;
866 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
868 struct sync_cb_data
*cb_data
= private_data
;
870 cb_data
->is_finished
= 1;
871 cb_data
->status
= status
;
874 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
879 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
881 struct sync_cb_data cb_data
;
883 cb_data
.is_finished
= 0;
885 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
886 nfs_set_error(nfs
, "nfs_fchmod_async failed");
890 wait_for_nfs_reply(nfs
, &cb_data
);
892 return cb_data
.status
;
901 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
903 struct sync_cb_data
*cb_data
= private_data
;
905 cb_data
->is_finished
= 1;
906 cb_data
->status
= status
;
909 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
914 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
916 struct sync_cb_data cb_data
;
918 cb_data
.is_finished
= 0;
920 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
921 nfs_set_error(nfs
, "nfs_chown_async failed");
925 wait_for_nfs_reply(nfs
, &cb_data
);
927 return cb_data
.status
;
933 static void fchown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
935 struct sync_cb_data
*cb_data
= private_data
;
937 cb_data
->is_finished
= 1;
938 cb_data
->status
= status
;
941 nfs_set_error(nfs
, "fchown call failed with \"%s\"", (char *)data
);
946 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
948 struct sync_cb_data cb_data
;
950 cb_data
.is_finished
= 0;
952 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
953 nfs_set_error(nfs
, "nfs_fchown_async failed");
957 wait_for_nfs_reply(nfs
, &cb_data
);
959 return cb_data
.status
;
967 static void utimes_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
969 struct sync_cb_data
*cb_data
= private_data
;
971 cb_data
->is_finished
= 1;
972 cb_data
->status
= status
;
975 nfs_set_error(nfs
, "utimes call failed with \"%s\"", (char *)data
);
980 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
982 struct sync_cb_data cb_data
;
984 cb_data
.is_finished
= 0;
986 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
987 nfs_set_error(nfs
, "nfs_utimes_async failed");
991 wait_for_nfs_reply(nfs
, &cb_data
);
993 return cb_data
.status
;
1001 static void utime_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1003 struct sync_cb_data
*cb_data
= private_data
;
1005 cb_data
->is_finished
= 1;
1006 cb_data
->status
= status
;
1009 nfs_set_error(nfs
, "utime call failed with \"%s\"", (char *)data
);
1014 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
1016 struct sync_cb_data cb_data
;
1018 cb_data
.is_finished
= 0;
1020 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
1021 nfs_set_error(nfs
, "nfs_utimes_async failed");
1025 wait_for_nfs_reply(nfs
, &cb_data
);
1027 return cb_data
.status
;
1036 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1038 struct sync_cb_data
*cb_data
= private_data
;
1040 cb_data
->is_finished
= 1;
1041 cb_data
->status
= status
;
1044 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
1049 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
1051 struct sync_cb_data cb_data
;
1053 cb_data
.is_finished
= 0;
1055 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
1056 nfs_set_error(nfs
, "nfs_access_async failed");
1060 wait_for_nfs_reply(nfs
, &cb_data
);
1062 return cb_data
.status
;
1070 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1072 struct sync_cb_data
*cb_data
= private_data
;
1074 cb_data
->is_finished
= 1;
1075 cb_data
->status
= status
;
1078 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
1083 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1085 struct sync_cb_data cb_data
;
1087 cb_data
.is_finished
= 0;
1089 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
1090 nfs_set_error(nfs
, "nfs_symlink_async failed");
1094 wait_for_nfs_reply(nfs
, &cb_data
);
1096 return cb_data
.status
;
1104 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1106 struct sync_cb_data
*cb_data
= private_data
;
1108 cb_data
->is_finished
= 1;
1109 cb_data
->status
= status
;
1112 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1117 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1119 struct sync_cb_data cb_data
;
1121 cb_data
.is_finished
= 0;
1123 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1124 nfs_set_error(nfs
, "nfs_rename_async failed");
1128 wait_for_nfs_reply(nfs
, &cb_data
);
1130 return cb_data
.status
;
1138 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1140 struct sync_cb_data
*cb_data
= private_data
;
1142 cb_data
->is_finished
= 1;
1143 cb_data
->status
= status
;
1146 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1151 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1153 struct sync_cb_data cb_data
;
1155 cb_data
.is_finished
= 0;
1157 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1158 nfs_set_error(nfs
, "nfs_link_async failed");
1162 wait_for_nfs_reply(nfs
, &cb_data
);
1164 return cb_data
.status
;
1167 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1169 struct sync_cb_data
*cb_data
= private_data
;
1172 assert(mount_context
->magic
== RPC_CONTEXT_MAGIC
);
1174 cb_data
->is_finished
= 1;
1175 cb_data
->status
= status
;
1176 cb_data
->return_data
= NULL
;
1179 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1183 export
= *(exports
*)data
;
1184 while (export
!= NULL
) {
1187 new_export
= malloc(sizeof(*new_export
));
1188 memset(new_export
, 0, sizeof(*new_export
));
1189 new_export
->ex_dir
= strdup(export
->ex_dir
);
1190 new_export
->ex_next
= cb_data
->return_data
;
1192 cb_data
->return_data
= new_export
;
1194 export
= export
->ex_next
;
1198 struct exportnode
*mount_getexports(const char *server
)
1200 struct sync_cb_data cb_data
;
1201 struct rpc_context
*rpc
;
1204 cb_data
.is_finished
= 0;
1205 cb_data
.return_data
= NULL
;
1207 rpc
= rpc_init_context();
1208 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1209 rpc_destroy_context(rpc
);
1213 wait_for_reply(rpc
, &cb_data
);
1214 rpc_destroy_context(rpc
);
1216 return cb_data
.return_data
;
1219 void mount_free_export_list(struct exportnode
*exports
)
1221 struct exportnode
*tmp
;
1223 while ((tmp
= exports
)) {
1224 exports
= exports
->ex_next
;
1232 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1234 while (srv
!= NULL
) {
1235 struct nfs_server_list
*next
= srv
->next
;
1243 struct nfs_list_data
{
1245 struct nfs_server_list
*srvrs
;
1248 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1250 struct nfs_list_data
*srv_data
= private_data
;
1251 struct sockaddr
*sin
;
1253 struct nfs_server_list
*srvr
;
1255 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1257 if (status
== RPC_STATUS_CANCEL
) {
1261 srv_data
->status
= -1;
1265 sin
= rpc_get_recv_sockaddr(rpc
);
1267 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1268 srv_data
->status
= -1;
1272 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1273 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1274 srv_data
->status
= -1;
1278 /* check for dupes */
1279 for (srvr
= srv_data
->srvrs
; srvr
; srvr
= srvr
->next
) {
1280 if (!strcmp(hostdd
, srvr
->addr
)) {
1285 srvr
= malloc(sizeof(struct nfs_server_list
));
1287 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1288 srv_data
->status
= -1;
1292 srvr
->addr
= strdup(hostdd
);
1293 if (srvr
->addr
== NULL
) {
1294 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1296 srv_data
->status
= -1;
1300 srvr
->next
= srv_data
->srvrs
;
1301 srv_data
->srvrs
= srvr
;
1306 static int send_nfsd_probes(struct rpc_context
*rpc
, INTERFACE_INFO
*InterfaceList
, int numIfs
, struct nfs_list_data
*data
)
1310 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1312 for(i
= 0; i
< numIfs
; i
++)
1316 unsigned long nFlags
= 0;
1318 pAddress
= (SOCKADDR
*) & (InterfaceList
[i
].iiBroadcastAddress
);
1320 if(pAddress
->sa_family
!= AF_INET
)
1323 nFlags
= InterfaceList
[i
].iiFlags
;
1325 if (!(nFlags
& IFF_UP
))
1330 if (nFlags
& IFF_LOOPBACK
)
1335 if (!(nFlags
& IFF_BROADCAST
))
1340 if (getnameinfo(pAddress
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0)
1345 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0)
1350 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0)
1358 struct nfs_server_list
*nfs_find_local_servers(void)
1360 struct rpc_context
*rpc
;
1361 struct nfs_list_data data
= {0, NULL
};
1362 struct timeval tv_start
, tv_current
;
1365 INTERFACE_INFO InterfaceList
[20];
1366 unsigned long nBytesReturned
;
1367 int nNumInterfaces
= 0;
1369 rpc
= rpc_init_udp_context();
1375 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0)
1377 rpc_destroy_context(rpc
);
1381 if (WSAIoctl(rpc_get_fd(rpc
), SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
, sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
1386 nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
1388 for (loop
=0; loop
<3; loop
++)
1390 if (send_nfsd_probes(rpc
, InterfaceList
, nNumInterfaces
, &data
) != 0)
1392 rpc_destroy_context(rpc
);
1396 win32_gettimeofday(&tv_start
, NULL
);
1401 pfd
.fd
= rpc_get_fd(rpc
);
1402 pfd
.events
= rpc_which_events(rpc
);
1404 win32_gettimeofday(&tv_current
, NULL
);
1406 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1407 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1409 if (poll(&pfd
, 1, mpt
) < 0)
1411 free_nfs_srvr_list(data
.srvrs
);
1412 rpc_destroy_context(rpc
);
1415 if (pfd
.revents
== 0)
1420 if (rpc_service(rpc
, pfd
.revents
) < 0)
1427 rpc_destroy_context(rpc
);
1429 if (data
.status
!= 0)
1431 free_nfs_srvr_list(data
.srvrs
);
1438 static int send_nfsd_probes(struct rpc_context
*rpc
, struct ifconf
*ifc
, struct nfs_list_data
*data
)
1442 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1444 for (ptr
=(char *)(ifc
->ifc_buf
); ptr
< (char *)(ifc
->ifc_buf
) + ifc
->ifc_len
; ) {
1448 ifr
= (struct ifreq
*)ptr
;
1449 #ifdef HAVE_SOCKADDR_LEN
1450 if (ifr
->ifr_addr
.sa_len
> sizeof(struct sockaddr
)) {
1451 ptr
+= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
1453 ptr
+= sizeof(ifr
->ifr_name
) + sizeof(struct sockaddr
);
1456 ptr
+= sizeof(struct ifreq
);
1459 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) {
1462 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, ifr
) < 0) {
1465 if (!(ifr
->ifr_flags
& IFF_UP
)) {
1468 if (ifr
->ifr_flags
& IFF_LOOPBACK
) {
1471 if (!(ifr
->ifr_flags
& IFF_BROADCAST
)) {
1474 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, ifr
) < 0) {
1477 if (getnameinfo(&ifr
->ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1480 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1484 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0) {
1492 struct nfs_server_list
*nfs_find_local_servers(void)
1494 struct rpc_context
*rpc
;
1495 struct nfs_list_data data
= {0, NULL
};
1496 struct timeval tv_start
, tv_current
;
1501 rpc
= rpc_init_udp_context();
1506 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1507 rpc_destroy_context(rpc
);
1512 /* get list of all interfaces */
1513 size
= sizeof(struct ifreq
);
1517 while(ifc
.ifc_len
> (size
- sizeof(struct ifreq
))) {
1522 ifc
.ifc_buf
= malloc(size
);
1523 memset(ifc
.ifc_buf
, 0, size
);
1524 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1525 rpc_destroy_context(rpc
);
1531 for (loop
=0; loop
<3; loop
++) {
1532 if (send_nfsd_probes(rpc
, &ifc
, &data
) != 0) {
1533 rpc_destroy_context(rpc
);
1538 gettimeofday(&tv_start
, NULL
);
1542 pfd
.fd
= rpc_get_fd(rpc
);
1543 pfd
.events
= rpc_which_events(rpc
);
1545 gettimeofday(&tv_current
, NULL
);
1547 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1548 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1550 if (poll(&pfd
, 1, mpt
) < 0) {
1551 free_nfs_srvr_list(data
.srvrs
);
1552 rpc_destroy_context(rpc
);
1555 if (pfd
.revents
== 0) {
1559 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1566 rpc_destroy_context(rpc
);
1568 if (data
.status
!= 0) {
1569 free_nfs_srvr_list(data
.srvrs
);