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"
26 #include <sys/statvfs.h>
28 #include <sys/ioctl.h>
30 #include <sys/socket.h>
42 #include <sys/types.h>
47 #ifdef HAVE_SYS_SOCKIO_H
48 #include <sys/sockio.h>
52 #include "libnfs-raw.h"
53 #include "libnfs-raw-mount.h"
54 #include "libnfs-raw-nfs.h"
55 #include "libnfs-private.h"
66 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
70 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
72 while (!cb_data
->is_finished
) {
74 pfd
.fd
= rpc_get_fd(rpc
);
75 pfd
.events
= rpc_which_events(rpc
);
76 if (poll(&pfd
, 1, -1) < 0) {
77 rpc_set_error(rpc
, "Poll failed");
78 cb_data
->status
= -EIO
;
81 if (rpc_service(rpc
, pfd
.revents
) < 0) {
82 rpc_set_error(rpc
, "rpc_service failed");
83 cb_data
->status
= -EIO
;
86 if (rpc_get_fd(rpc
) == -1) {
87 rpc_set_error(rpc
, "Socket closed\n");
93 static void wait_for_nfs_reply(struct nfs_context
*nfs
, struct sync_cb_data
*cb_data
)
97 while (!cb_data
->is_finished
) {
99 pfd
.fd
= nfs_get_fd(nfs
);
100 pfd
.events
= nfs_which_events(nfs
);
101 if (poll(&pfd
, 1, -1) < 0) {
102 nfs_set_error(nfs
, "Poll failed");
103 cb_data
->status
= -EIO
;
106 if (nfs_service(nfs
, pfd
.revents
) < 0) {
107 nfs_set_error(nfs
, "nfs_service failed");
108 cb_data
->status
= -EIO
;
120 * connect to the server and mount the export
122 static void mount_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
124 struct sync_cb_data
*cb_data
= private_data
;
126 cb_data
->is_finished
= 1;
127 cb_data
->status
= status
;
130 nfs_set_error(nfs
, "mount/mnt call failed with \"%s\"", (char *)data
);
135 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
137 struct sync_cb_data cb_data
;
138 struct rpc_context
*rpc
= nfs_get_rpc_context(nfs
);
140 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
142 cb_data
.is_finished
= 0;
144 if (nfs_mount_async(nfs
, server
, export
, mount_cb
, &cb_data
) != 0) {
145 nfs_set_error(nfs
, "nfs_mount_async failed");
149 wait_for_nfs_reply(nfs
, &cb_data
);
151 /* Dont want any more callbacks even if the socket is closed */
152 rpc
->connect_cb
= NULL
;
154 return cb_data
.status
;
161 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
163 struct sync_cb_data
*cb_data
= private_data
;
165 cb_data
->is_finished
= 1;
166 cb_data
->status
= status
;
169 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
173 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
176 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
178 struct sync_cb_data cb_data
;
180 cb_data
.is_finished
= 0;
181 cb_data
.return_data
= st
;
183 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
184 nfs_set_error(nfs
, "nfs_stat_async failed");
188 wait_for_nfs_reply(nfs
, &cb_data
);
190 return cb_data
.status
;
199 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
201 struct sync_cb_data
*cb_data
= private_data
;
202 struct nfsfh
*fh
, **nfsfh
;
204 cb_data
->is_finished
= 1;
205 cb_data
->status
= status
;
208 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
213 nfsfh
= cb_data
->return_data
;
217 int nfs_open(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
219 struct sync_cb_data cb_data
;
221 cb_data
.is_finished
= 0;
222 cb_data
.return_data
= nfsfh
;
224 if (nfs_open_async(nfs
, path
, mode
, open_cb
, &cb_data
) != 0) {
225 nfs_set_error(nfs
, "nfs_open_async failed");
229 wait_for_nfs_reply(nfs
, &cb_data
);
231 return cb_data
.status
;
240 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
242 struct sync_cb_data
*cb_data
= private_data
;
244 cb_data
->is_finished
= 1;
245 cb_data
->status
= status
;
248 nfs_set_error(nfs
, "pread call failed with \"%s\"", (char *)data
);
252 buffer
= cb_data
->return_data
;
253 memcpy(buffer
, (char *)data
, status
);
256 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buffer
)
258 struct sync_cb_data cb_data
;
260 cb_data
.is_finished
= 0;
261 cb_data
.return_data
= buffer
;
263 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
264 nfs_set_error(nfs
, "nfs_pread_async failed");
268 wait_for_nfs_reply(nfs
, &cb_data
);
270 return cb_data
.status
;
276 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buffer
)
278 return nfs_pread(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buffer
);
284 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
286 struct sync_cb_data
*cb_data
= private_data
;
287 cb_data
->is_finished
= 1;
288 cb_data
->status
= status
;
291 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
296 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
298 struct sync_cb_data cb_data
;
300 cb_data
.is_finished
= 0;
302 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
303 nfs_set_error(nfs
, "nfs_close_async failed");
307 wait_for_nfs_reply(nfs
, &cb_data
);
309 return cb_data
.status
;
318 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
320 struct sync_cb_data cb_data
;
322 cb_data
.is_finished
= 0;
323 cb_data
.return_data
= st
;
325 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
326 nfs_set_error(nfs
, "nfs_fstat_async failed");
330 wait_for_nfs_reply(nfs
, &cb_data
);
332 return cb_data
.status
;
339 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
341 struct sync_cb_data
*cb_data
= private_data
;
342 cb_data
->is_finished
= 1;
343 cb_data
->status
= status
;
346 nfs_set_error(nfs
, "pwrite call failed with \"%s\"", (char *)data
);
351 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buf
)
353 struct sync_cb_data cb_data
;
355 cb_data
.is_finished
= 0;
357 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
358 nfs_set_error(nfs
, "nfs_pwrite_async failed");
362 wait_for_nfs_reply(nfs
, &cb_data
);
364 return cb_data
.status
;
370 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buf
)
372 return nfs_pwrite(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buf
);
379 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
381 struct sync_cb_data
*cb_data
= private_data
;
382 cb_data
->is_finished
= 1;
383 cb_data
->status
= status
;
386 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
391 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
393 struct sync_cb_data cb_data
;
395 cb_data
.is_finished
= 0;
397 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
398 nfs_set_error(nfs
, "nfs_fsync_async failed");
402 wait_for_nfs_reply(nfs
, &cb_data
);
404 return cb_data
.status
;
413 static void ftruncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
415 struct sync_cb_data
*cb_data
= private_data
;
416 cb_data
->is_finished
= 1;
417 cb_data
->status
= status
;
420 nfs_set_error(nfs
, "ftruncate call failed with \"%s\"", (char *)data
);
425 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t length
)
427 struct sync_cb_data cb_data
;
429 cb_data
.is_finished
= 0;
431 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_cb
, &cb_data
) != 0) {
432 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
436 wait_for_nfs_reply(nfs
, &cb_data
);
438 return cb_data
.status
;
446 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
448 struct sync_cb_data
*cb_data
= private_data
;
449 cb_data
->is_finished
= 1;
450 cb_data
->status
= status
;
453 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
458 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, uint64_t length
)
460 struct sync_cb_data cb_data
;
462 cb_data
.is_finished
= 0;
464 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
465 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
469 wait_for_nfs_reply(nfs
, &cb_data
);
471 return cb_data
.status
;
481 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
483 struct sync_cb_data
*cb_data
= private_data
;
484 cb_data
->is_finished
= 1;
485 cb_data
->status
= status
;
488 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
493 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
495 struct sync_cb_data cb_data
;
497 cb_data
.is_finished
= 0;
499 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
500 nfs_set_error(nfs
, "nfs_mkdir_async failed");
504 wait_for_nfs_reply(nfs
, &cb_data
);
506 return cb_data
.status
;
516 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
518 struct sync_cb_data
*cb_data
= private_data
;
519 cb_data
->is_finished
= 1;
520 cb_data
->status
= status
;
523 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
528 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
530 struct sync_cb_data cb_data
;
532 cb_data
.is_finished
= 0;
534 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
535 nfs_set_error(nfs
, "nfs_rmdir_async failed");
539 wait_for_nfs_reply(nfs
, &cb_data
);
541 return cb_data
.status
;
549 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
551 struct sync_cb_data
*cb_data
= private_data
;
552 struct nfsfh
*fh
, **nfsfh
;
554 cb_data
->is_finished
= 1;
555 cb_data
->status
= status
;
558 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
563 nfsfh
= cb_data
->return_data
;
567 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
569 struct sync_cb_data cb_data
;
571 cb_data
.is_finished
= 0;
572 cb_data
.return_data
= nfsfh
;
574 if (nfs_creat_async(nfs
, path
, mode
, creat_cb
, &cb_data
) != 0) {
575 nfs_set_error(nfs
, "nfs_creat_async failed");
579 wait_for_nfs_reply(nfs
, &cb_data
);
581 return cb_data
.status
;
587 static void mknod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
589 struct sync_cb_data
*cb_data
= private_data
;
591 cb_data
->is_finished
= 1;
592 cb_data
->status
= status
;
595 nfs_set_error(nfs
, "mknod call failed with \"%s\"", (char *)data
);
600 int nfs_mknod(struct nfs_context
*nfs
, const char *path
, int mode
, int dev
)
602 struct sync_cb_data cb_data
;
604 cb_data
.is_finished
= 0;
606 if (nfs_mknod_async(nfs
, path
, mode
, dev
, mknod_cb
, &cb_data
) != 0) {
607 nfs_set_error(nfs
, "nfs_creat_async failed");
611 wait_for_nfs_reply(nfs
, &cb_data
);
613 return cb_data
.status
;
620 static void unlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
622 struct sync_cb_data
*cb_data
= private_data
;
624 cb_data
->is_finished
= 1;
625 cb_data
->status
= status
;
628 nfs_set_error(nfs
, "unlink call failed with \"%s\"", (char *)data
);
633 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
635 struct sync_cb_data cb_data
;
637 cb_data
.is_finished
= 0;
639 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
640 nfs_set_error(nfs
, "nfs_unlink_async failed");
644 wait_for_nfs_reply(nfs
, &cb_data
);
646 return cb_data
.status
;
654 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
656 struct sync_cb_data
*cb_data
= private_data
;
657 struct nfsdir
*dir
, **nfsdir
;
659 cb_data
->is_finished
= 1;
660 cb_data
->status
= status
;
663 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
668 nfsdir
= cb_data
->return_data
;
672 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
674 struct sync_cb_data cb_data
;
676 cb_data
.is_finished
= 0;
677 cb_data
.return_data
= nfsdir
;
679 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
680 nfs_set_error(nfs
, "nfs_opendir_async failed");
684 wait_for_nfs_reply(nfs
, &cb_data
);
686 return cb_data
.status
;
693 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
695 struct sync_cb_data
*cb_data
= private_data
;
697 cb_data
->is_finished
= 1;
698 cb_data
->status
= status
;
701 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
705 if (cb_data
->return_data
!= NULL
) {
706 memcpy(cb_data
->return_data
, data
, sizeof(uint64_t));
710 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, int whence
, uint64_t *current_offset
)
712 struct sync_cb_data cb_data
;
714 cb_data
.is_finished
= 0;
715 cb_data
.return_data
= current_offset
;
717 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
718 nfs_set_error(nfs
, "nfs_lseek_async failed");
722 wait_for_nfs_reply(nfs
, &cb_data
);
724 return cb_data
.status
;
732 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
734 struct sync_cb_data
*cb_data
= private_data
;
736 cb_data
->is_finished
= 1;
737 cb_data
->status
= status
;
740 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
744 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
747 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
749 struct sync_cb_data cb_data
;
751 cb_data
.is_finished
= 0;
752 cb_data
.return_data
= svfs
;
754 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
755 nfs_set_error(nfs
, "nfs_statvfs_async failed");
759 wait_for_nfs_reply(nfs
, &cb_data
);
761 return cb_data
.status
;
771 static void readlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
773 struct sync_cb_data
*cb_data
= private_data
;
775 cb_data
->is_finished
= 1;
776 cb_data
->status
= status
;
779 nfs_set_error(nfs
, "readlink call failed with \"%s\"", (char *)data
);
783 if (strlen(data
) > (size_t)cb_data
->return_int
) {
784 nfs_set_error(nfs
, "Too small buffer for readlink");
785 cb_data
->status
= -ENAMETOOLONG
;
789 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
792 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
794 struct sync_cb_data cb_data
;
796 cb_data
.is_finished
= 0;
797 cb_data
.return_data
= buf
;
798 cb_data
.return_int
= bufsize
;
800 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
801 nfs_set_error(nfs
, "nfs_readlink_async failed");
805 wait_for_nfs_reply(nfs
, &cb_data
);
807 return cb_data
.status
;
815 static void chmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
817 struct sync_cb_data
*cb_data
= private_data
;
819 cb_data
->is_finished
= 1;
820 cb_data
->status
= status
;
823 nfs_set_error(nfs
, "chmod call failed with \"%s\"", (char *)data
);
828 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
830 struct sync_cb_data cb_data
;
832 cb_data
.is_finished
= 0;
834 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
835 nfs_set_error(nfs
, "nfs_chmod_async failed");
839 wait_for_nfs_reply(nfs
, &cb_data
);
841 return cb_data
.status
;
850 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
852 struct sync_cb_data
*cb_data
= private_data
;
854 cb_data
->is_finished
= 1;
855 cb_data
->status
= status
;
858 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
863 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
865 struct sync_cb_data cb_data
;
867 cb_data
.is_finished
= 0;
869 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
870 nfs_set_error(nfs
, "nfs_fchmod_async failed");
874 wait_for_nfs_reply(nfs
, &cb_data
);
876 return cb_data
.status
;
885 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
887 struct sync_cb_data
*cb_data
= private_data
;
889 cb_data
->is_finished
= 1;
890 cb_data
->status
= status
;
893 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
898 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
900 struct sync_cb_data cb_data
;
902 cb_data
.is_finished
= 0;
904 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
905 nfs_set_error(nfs
, "nfs_chown_async failed");
909 wait_for_nfs_reply(nfs
, &cb_data
);
911 return cb_data
.status
;
917 static void fchown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
919 struct sync_cb_data
*cb_data
= private_data
;
921 cb_data
->is_finished
= 1;
922 cb_data
->status
= status
;
925 nfs_set_error(nfs
, "fchown call failed with \"%s\"", (char *)data
);
930 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
932 struct sync_cb_data cb_data
;
934 cb_data
.is_finished
= 0;
936 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
937 nfs_set_error(nfs
, "nfs_fchown_async failed");
941 wait_for_nfs_reply(nfs
, &cb_data
);
943 return cb_data
.status
;
951 static void utimes_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
953 struct sync_cb_data
*cb_data
= private_data
;
955 cb_data
->is_finished
= 1;
956 cb_data
->status
= status
;
959 nfs_set_error(nfs
, "utimes call failed with \"%s\"", (char *)data
);
964 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
966 struct sync_cb_data cb_data
;
968 cb_data
.is_finished
= 0;
970 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
971 nfs_set_error(nfs
, "nfs_utimes_async failed");
975 wait_for_nfs_reply(nfs
, &cb_data
);
977 return cb_data
.status
;
985 static void utime_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
987 struct sync_cb_data
*cb_data
= private_data
;
989 cb_data
->is_finished
= 1;
990 cb_data
->status
= status
;
993 nfs_set_error(nfs
, "utime call failed with \"%s\"", (char *)data
);
998 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
1000 struct sync_cb_data cb_data
;
1002 cb_data
.is_finished
= 0;
1004 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
1005 nfs_set_error(nfs
, "nfs_utimes_async failed");
1009 wait_for_nfs_reply(nfs
, &cb_data
);
1011 return cb_data
.status
;
1020 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1022 struct sync_cb_data
*cb_data
= private_data
;
1024 cb_data
->is_finished
= 1;
1025 cb_data
->status
= status
;
1028 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
1033 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
1035 struct sync_cb_data cb_data
;
1037 cb_data
.is_finished
= 0;
1039 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
1040 nfs_set_error(nfs
, "nfs_access_async failed");
1044 wait_for_nfs_reply(nfs
, &cb_data
);
1046 return cb_data
.status
;
1054 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1056 struct sync_cb_data
*cb_data
= private_data
;
1058 cb_data
->is_finished
= 1;
1059 cb_data
->status
= status
;
1062 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
1067 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1069 struct sync_cb_data cb_data
;
1071 cb_data
.is_finished
= 0;
1073 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
1074 nfs_set_error(nfs
, "nfs_symlink_async failed");
1078 wait_for_nfs_reply(nfs
, &cb_data
);
1080 return cb_data
.status
;
1088 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1090 struct sync_cb_data
*cb_data
= private_data
;
1092 cb_data
->is_finished
= 1;
1093 cb_data
->status
= status
;
1096 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1101 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1103 struct sync_cb_data cb_data
;
1105 cb_data
.is_finished
= 0;
1107 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1108 nfs_set_error(nfs
, "nfs_rename_async failed");
1112 wait_for_nfs_reply(nfs
, &cb_data
);
1114 return cb_data
.status
;
1122 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1124 struct sync_cb_data
*cb_data
= private_data
;
1126 cb_data
->is_finished
= 1;
1127 cb_data
->status
= status
;
1130 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1135 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1137 struct sync_cb_data cb_data
;
1139 cb_data
.is_finished
= 0;
1141 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1142 nfs_set_error(nfs
, "nfs_link_async failed");
1146 wait_for_nfs_reply(nfs
, &cb_data
);
1148 return cb_data
.status
;
1151 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1153 struct sync_cb_data
*cb_data
= private_data
;
1156 assert(mount_context
->magic
== RPC_CONTEXT_MAGIC
);
1158 cb_data
->is_finished
= 1;
1159 cb_data
->status
= status
;
1160 cb_data
->return_data
= NULL
;
1163 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1167 export
= *(exports
*)data
;
1168 while (export
!= NULL
) {
1171 new_export
= malloc(sizeof(*new_export
));
1172 memset(new_export
, 0, sizeof(*new_export
));
1173 new_export
->ex_dir
= strdup(export
->ex_dir
);
1174 new_export
->ex_next
= cb_data
->return_data
;
1176 cb_data
->return_data
= new_export
;
1178 export
= export
->ex_next
;
1182 struct exportnode
*mount_getexports(const char *server
)
1184 struct sync_cb_data cb_data
;
1185 struct rpc_context
*rpc
;
1188 cb_data
.is_finished
= 0;
1189 cb_data
.return_data
= NULL
;
1191 rpc
= rpc_init_context();
1192 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1193 rpc_destroy_context(rpc
);
1197 wait_for_reply(rpc
, &cb_data
);
1198 rpc_destroy_context(rpc
);
1200 return cb_data
.return_data
;
1203 void mount_free_export_list(struct exportnode
*exports
)
1205 struct exportnode
*tmp
;
1207 while ((tmp
= exports
)) {
1208 exports
= exports
->ex_next
;
1216 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1218 while (srv
!= NULL
) {
1219 struct nfs_server_list
*next
= srv
->next
;
1227 struct nfs_list_data
{
1229 struct nfs_server_list
*srvrs
;
1232 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1234 struct nfs_list_data
*srv_data
= private_data
;
1235 struct sockaddr
*sin
;
1237 struct nfs_server_list
*srvr
;
1239 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1241 if (status
== RPC_STATUS_CANCEL
) {
1245 srv_data
->status
= -1;
1249 sin
= rpc_get_recv_sockaddr(rpc
);
1251 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1252 srv_data
->status
= -1;
1256 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1257 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1258 srv_data
->status
= -1;
1262 /* check for dupes */
1263 for (srvr
= srv_data
->srvrs
; srvr
; srvr
= srvr
->next
) {
1264 if (!strcmp(hostdd
, srvr
->addr
)) {
1269 srvr
= malloc(sizeof(struct nfs_server_list
));
1271 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1272 srv_data
->status
= -1;
1276 srvr
->addr
= strdup(hostdd
);
1277 if (srvr
->addr
== NULL
) {
1278 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1280 srv_data
->status
= -1;
1284 srvr
->next
= srv_data
->srvrs
;
1285 srv_data
->srvrs
= srvr
;
1290 static int send_nfsd_probes(struct rpc_context
*rpc
, INTERFACE_INFO
*InterfaceList
, int numIfs
, struct nfs_list_data
*data
)
1294 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1296 for(i
= 0; i
< numIfs
; i
++)
1300 unsigned long nFlags
= 0;
1302 pAddress
= (SOCKADDR
*) & (InterfaceList
[i
].iiBroadcastAddress
);
1304 if(pAddress
->sa_family
!= AF_INET
)
1307 nFlags
= InterfaceList
[i
].iiFlags
;
1309 if (!(nFlags
& IFF_UP
))
1314 if (nFlags
& IFF_LOOPBACK
)
1319 if (!(nFlags
& IFF_BROADCAST
))
1324 if (getnameinfo(pAddress
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0)
1329 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0)
1334 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0)
1342 struct nfs_server_list
*nfs_find_local_servers(void)
1344 struct rpc_context
*rpc
;
1345 struct nfs_list_data data
= {0, NULL
};
1346 struct timeval tv_start
, tv_current
;
1349 INTERFACE_INFO InterfaceList
[20];
1350 unsigned long nBytesReturned
;
1351 int nNumInterfaces
= 0;
1353 rpc
= rpc_init_udp_context();
1359 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0)
1361 rpc_destroy_context(rpc
);
1365 if (WSAIoctl(rpc_get_fd(rpc
), SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
, sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
1370 nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
1372 for (loop
=0; loop
<3; loop
++)
1374 if (send_nfsd_probes(rpc
, InterfaceList
, nNumInterfaces
, &data
) != 0)
1376 rpc_destroy_context(rpc
);
1380 win32_gettimeofday(&tv_start
, NULL
);
1385 pfd
.fd
= rpc_get_fd(rpc
);
1386 pfd
.events
= rpc_which_events(rpc
);
1388 win32_gettimeofday(&tv_current
, NULL
);
1390 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1391 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1393 if (poll(&pfd
, 1, mpt
) < 0)
1395 free_nfs_srvr_list(data
.srvrs
);
1396 rpc_destroy_context(rpc
);
1399 if (pfd
.revents
== 0)
1404 if (rpc_service(rpc
, pfd
.revents
) < 0)
1411 rpc_destroy_context(rpc
);
1413 if (data
.status
!= 0)
1415 free_nfs_srvr_list(data
.srvrs
);
1422 static int send_nfsd_probes(struct rpc_context
*rpc
, struct ifconf
*ifc
, struct nfs_list_data
*data
)
1426 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1428 for (ptr
=(char *)(ifc
->ifc_buf
); ptr
< (char *)(ifc
->ifc_buf
) + ifc
->ifc_len
; ) {
1432 ifr
= (struct ifreq
*)ptr
;
1433 #ifdef HAVE_SOCKADDR_LEN
1434 if (ifr
->ifr_addr
.sa_len
> sizeof(struct sockaddr
)) {
1435 ptr
+= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
1437 ptr
+= sizeof(ifr
->ifr_name
) + sizeof(struct sockaddr
);
1440 ptr
+= sizeof(struct ifreq
);
1443 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) {
1446 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, ifr
) < 0) {
1449 if (!(ifr
->ifr_flags
& IFF_UP
)) {
1452 if (ifr
->ifr_flags
& IFF_LOOPBACK
) {
1455 if (!(ifr
->ifr_flags
& IFF_BROADCAST
)) {
1458 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, ifr
) < 0) {
1461 if (getnameinfo(&ifr
->ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1464 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1468 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0) {
1476 struct nfs_server_list
*nfs_find_local_servers(void)
1478 struct rpc_context
*rpc
;
1479 struct nfs_list_data data
= {0, NULL
};
1480 struct timeval tv_start
, tv_current
;
1485 rpc
= rpc_init_udp_context();
1490 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1491 rpc_destroy_context(rpc
);
1496 /* get list of all interfaces */
1497 size
= sizeof(struct ifreq
);
1501 while(ifc
.ifc_len
> (size
- sizeof(struct ifreq
))) {
1506 ifc
.ifc_buf
= malloc(size
);
1507 memset(ifc
.ifc_buf
, 0, size
);
1508 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1509 rpc_destroy_context(rpc
);
1515 for (loop
=0; loop
<3; loop
++) {
1516 if (send_nfsd_probes(rpc
, &ifc
, &data
) != 0) {
1517 rpc_destroy_context(rpc
);
1522 gettimeofday(&tv_start
, NULL
);
1526 pfd
.fd
= rpc_get_fd(rpc
);
1527 pfd
.events
= rpc_which_events(rpc
);
1529 gettimeofday(&tv_current
, NULL
);
1531 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1532 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1534 if (poll(&pfd
, 1, mpt
) < 0) {
1535 free_nfs_srvr_list(data
.srvrs
);
1536 rpc_destroy_context(rpc
);
1539 if (pfd
.revents
== 0) {
1543 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1550 rpc_destroy_context(rpc
);
1552 if (data
.status
!= 0) {
1553 free_nfs_srvr_list(data
.srvrs
);