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>
41 #include <sys/types.h>
46 #ifdef HAVE_SYS_SOCKIO_H
47 #include <sys/sockio.h>
51 #include "libnfs-raw.h"
52 #include "libnfs-raw-mount.h"
53 #include "libnfs-raw-nfs.h"
54 #include "libnfs-private.h"
65 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
69 while (!cb_data
->is_finished
) {
71 pfd
.fd
= rpc_get_fd(rpc
);
72 pfd
.events
= rpc_which_events(rpc
);
73 if (poll(&pfd
, 1, -1) < 0) {
74 rpc_set_error(rpc
, "Poll failed");
75 cb_data
->status
= -EIO
;
78 if (rpc_service(rpc
, pfd
.revents
) < 0) {
79 rpc_set_error(rpc
, "rpc_service failed");
80 cb_data
->status
= -EIO
;
83 if (rpc_get_fd(rpc
) == -1) {
84 rpc_set_error(rpc
, "Socket closed\n");
90 static void wait_for_nfs_reply(struct nfs_context
*nfs
, struct sync_cb_data
*cb_data
)
94 while (!cb_data
->is_finished
) {
96 pfd
.fd
= nfs_get_fd(nfs
);
97 pfd
.events
= nfs_which_events(nfs
);
98 if (poll(&pfd
, 1, -1) < 0) {
99 nfs_set_error(nfs
, "Poll failed");
100 cb_data
->status
= -EIO
;
103 if (nfs_service(nfs
, pfd
.revents
) < 0) {
104 nfs_set_error(nfs
, "nfs_service failed");
105 cb_data
->status
= -EIO
;
117 * connect to the server and mount the export
119 static void mount_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
121 struct sync_cb_data
*cb_data
= private_data
;
123 cb_data
->is_finished
= 1;
124 cb_data
->status
= status
;
127 nfs_set_error(nfs
, "mount/mnt call failed with \"%s\"", (char *)data
);
132 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
134 struct sync_cb_data cb_data
;
135 struct rpc_context
*rpc
= nfs_get_rpc_context(nfs
);
137 cb_data
.is_finished
= 0;
139 if (nfs_mount_async(nfs
, server
, export
, mount_cb
, &cb_data
) != 0) {
140 nfs_set_error(nfs
, "nfs_mount_async failed");
144 wait_for_nfs_reply(nfs
, &cb_data
);
146 /* Dont want any more callbacks even if the socket is closed */
147 rpc
->connect_cb
= NULL
;
149 return cb_data
.status
;
156 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
158 struct sync_cb_data
*cb_data
= private_data
;
160 cb_data
->is_finished
= 1;
161 cb_data
->status
= status
;
164 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
168 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
171 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
173 struct sync_cb_data cb_data
;
175 cb_data
.is_finished
= 0;
176 cb_data
.return_data
= st
;
178 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
179 nfs_set_error(nfs
, "nfs_stat_async failed");
183 wait_for_nfs_reply(nfs
, &cb_data
);
185 return cb_data
.status
;
194 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
196 struct sync_cb_data
*cb_data
= private_data
;
197 struct nfsfh
*fh
, **nfsfh
;
199 cb_data
->is_finished
= 1;
200 cb_data
->status
= status
;
203 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
208 nfsfh
= cb_data
->return_data
;
212 int nfs_open(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
214 struct sync_cb_data cb_data
;
216 cb_data
.is_finished
= 0;
217 cb_data
.return_data
= nfsfh
;
219 if (nfs_open_async(nfs
, path
, mode
, open_cb
, &cb_data
) != 0) {
220 nfs_set_error(nfs
, "nfs_open_async failed");
224 wait_for_nfs_reply(nfs
, &cb_data
);
226 return cb_data
.status
;
235 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
237 struct sync_cb_data
*cb_data
= private_data
;
239 cb_data
->is_finished
= 1;
240 cb_data
->status
= status
;
243 nfs_set_error(nfs
, "pread call failed with \"%s\"", (char *)data
);
247 buffer
= cb_data
->return_data
;
248 memcpy(buffer
, (char *)data
, status
);
251 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buffer
)
253 struct sync_cb_data cb_data
;
255 cb_data
.is_finished
= 0;
256 cb_data
.return_data
= buffer
;
258 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
259 nfs_set_error(nfs
, "nfs_pread_async failed");
263 wait_for_nfs_reply(nfs
, &cb_data
);
265 return cb_data
.status
;
271 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buffer
)
273 return nfs_pread(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buffer
);
279 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
281 struct sync_cb_data
*cb_data
= private_data
;
282 cb_data
->is_finished
= 1;
283 cb_data
->status
= status
;
286 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
291 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
293 struct sync_cb_data cb_data
;
295 cb_data
.is_finished
= 0;
297 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
298 nfs_set_error(nfs
, "nfs_close_async failed");
302 wait_for_nfs_reply(nfs
, &cb_data
);
304 return cb_data
.status
;
313 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
315 struct sync_cb_data cb_data
;
317 cb_data
.is_finished
= 0;
318 cb_data
.return_data
= st
;
320 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
321 nfs_set_error(nfs
, "nfs_fstat_async failed");
325 wait_for_nfs_reply(nfs
, &cb_data
);
327 return cb_data
.status
;
334 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
336 struct sync_cb_data
*cb_data
= private_data
;
337 cb_data
->is_finished
= 1;
338 cb_data
->status
= status
;
341 nfs_set_error(nfs
, "pwrite call failed with \"%s\"", (char *)data
);
346 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buf
)
348 struct sync_cb_data cb_data
;
350 cb_data
.is_finished
= 0;
352 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
353 nfs_set_error(nfs
, "nfs_pwrite_async failed");
357 wait_for_nfs_reply(nfs
, &cb_data
);
359 return cb_data
.status
;
365 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buf
)
367 return nfs_pwrite(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buf
);
374 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
376 struct sync_cb_data
*cb_data
= private_data
;
377 cb_data
->is_finished
= 1;
378 cb_data
->status
= status
;
381 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
386 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
388 struct sync_cb_data cb_data
;
390 cb_data
.is_finished
= 0;
392 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
393 nfs_set_error(nfs
, "nfs_fsync_async failed");
397 wait_for_nfs_reply(nfs
, &cb_data
);
399 return cb_data
.status
;
408 static void ftruncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
410 struct sync_cb_data
*cb_data
= private_data
;
411 cb_data
->is_finished
= 1;
412 cb_data
->status
= status
;
415 nfs_set_error(nfs
, "ftruncate call failed with \"%s\"", (char *)data
);
420 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t length
)
422 struct sync_cb_data cb_data
;
424 cb_data
.is_finished
= 0;
426 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_cb
, &cb_data
) != 0) {
427 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
431 wait_for_nfs_reply(nfs
, &cb_data
);
433 return cb_data
.status
;
441 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
443 struct sync_cb_data
*cb_data
= private_data
;
444 cb_data
->is_finished
= 1;
445 cb_data
->status
= status
;
448 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
453 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, uint64_t length
)
455 struct sync_cb_data cb_data
;
457 cb_data
.is_finished
= 0;
459 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
460 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
464 wait_for_nfs_reply(nfs
, &cb_data
);
466 return cb_data
.status
;
476 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
478 struct sync_cb_data
*cb_data
= private_data
;
479 cb_data
->is_finished
= 1;
480 cb_data
->status
= status
;
483 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
488 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
490 struct sync_cb_data cb_data
;
492 cb_data
.is_finished
= 0;
494 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
495 nfs_set_error(nfs
, "nfs_mkdir_async failed");
499 wait_for_nfs_reply(nfs
, &cb_data
);
501 return cb_data
.status
;
511 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
513 struct sync_cb_data
*cb_data
= private_data
;
514 cb_data
->is_finished
= 1;
515 cb_data
->status
= status
;
518 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
523 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
525 struct sync_cb_data cb_data
;
527 cb_data
.is_finished
= 0;
529 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
530 nfs_set_error(nfs
, "nfs_rmdir_async failed");
534 wait_for_nfs_reply(nfs
, &cb_data
);
536 return cb_data
.status
;
544 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
546 struct sync_cb_data
*cb_data
= private_data
;
547 struct nfsfh
*fh
, **nfsfh
;
549 cb_data
->is_finished
= 1;
550 cb_data
->status
= status
;
553 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
558 nfsfh
= cb_data
->return_data
;
562 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
564 struct sync_cb_data cb_data
;
566 cb_data
.is_finished
= 0;
567 cb_data
.return_data
= nfsfh
;
569 if (nfs_creat_async(nfs
, path
, mode
, creat_cb
, &cb_data
) != 0) {
570 nfs_set_error(nfs
, "nfs_creat_async failed");
574 wait_for_nfs_reply(nfs
, &cb_data
);
576 return cb_data
.status
;
582 static void mknod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
584 struct sync_cb_data
*cb_data
= private_data
;
586 cb_data
->is_finished
= 1;
587 cb_data
->status
= status
;
590 nfs_set_error(nfs
, "mknod call failed with \"%s\"", (char *)data
);
595 int nfs_mknod(struct nfs_context
*nfs
, const char *path
, int mode
, int dev
)
597 struct sync_cb_data cb_data
;
599 cb_data
.is_finished
= 0;
601 if (nfs_mknod_async(nfs
, path
, mode
, dev
, mknod_cb
, &cb_data
) != 0) {
602 nfs_set_error(nfs
, "nfs_creat_async failed");
606 wait_for_nfs_reply(nfs
, &cb_data
);
608 return cb_data
.status
;
615 static void unlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
617 struct sync_cb_data
*cb_data
= private_data
;
619 cb_data
->is_finished
= 1;
620 cb_data
->status
= status
;
623 nfs_set_error(nfs
, "unlink call failed with \"%s\"", (char *)data
);
628 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
630 struct sync_cb_data cb_data
;
632 cb_data
.is_finished
= 0;
634 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
635 nfs_set_error(nfs
, "nfs_unlink_async failed");
639 wait_for_nfs_reply(nfs
, &cb_data
);
641 return cb_data
.status
;
649 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
651 struct sync_cb_data
*cb_data
= private_data
;
652 struct nfsdir
*dir
, **nfsdir
;
654 cb_data
->is_finished
= 1;
655 cb_data
->status
= status
;
658 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
663 nfsdir
= cb_data
->return_data
;
667 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
669 struct sync_cb_data cb_data
;
671 cb_data
.is_finished
= 0;
672 cb_data
.return_data
= nfsdir
;
674 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
675 nfs_set_error(nfs
, "nfs_opendir_async failed");
679 wait_for_nfs_reply(nfs
, &cb_data
);
681 return cb_data
.status
;
688 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
690 struct sync_cb_data
*cb_data
= private_data
;
692 cb_data
->is_finished
= 1;
693 cb_data
->status
= status
;
696 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
700 if (cb_data
->return_data
!= NULL
) {
701 memcpy(cb_data
->return_data
, data
, sizeof(uint64_t));
705 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, int whence
, uint64_t *current_offset
)
707 struct sync_cb_data cb_data
;
709 cb_data
.is_finished
= 0;
710 cb_data
.return_data
= current_offset
;
712 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
713 nfs_set_error(nfs
, "nfs_lseek_async failed");
717 wait_for_nfs_reply(nfs
, &cb_data
);
719 return cb_data
.status
;
727 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
729 struct sync_cb_data
*cb_data
= private_data
;
731 cb_data
->is_finished
= 1;
732 cb_data
->status
= status
;
735 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
739 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
742 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
744 struct sync_cb_data cb_data
;
746 cb_data
.is_finished
= 0;
747 cb_data
.return_data
= svfs
;
749 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
750 nfs_set_error(nfs
, "nfs_statvfs_async failed");
754 wait_for_nfs_reply(nfs
, &cb_data
);
756 return cb_data
.status
;
766 static void readlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
768 struct sync_cb_data
*cb_data
= private_data
;
770 cb_data
->is_finished
= 1;
771 cb_data
->status
= status
;
774 nfs_set_error(nfs
, "readlink call failed with \"%s\"", (char *)data
);
778 if (strlen(data
) > (size_t)cb_data
->return_int
) {
779 nfs_set_error(nfs
, "Too small buffer for readlink");
780 cb_data
->status
= -ENAMETOOLONG
;
784 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
787 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
789 struct sync_cb_data cb_data
;
791 cb_data
.is_finished
= 0;
792 cb_data
.return_data
= buf
;
793 cb_data
.return_int
= bufsize
;
795 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
796 nfs_set_error(nfs
, "nfs_readlink_async failed");
800 wait_for_nfs_reply(nfs
, &cb_data
);
802 return cb_data
.status
;
810 static void chmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
812 struct sync_cb_data
*cb_data
= private_data
;
814 cb_data
->is_finished
= 1;
815 cb_data
->status
= status
;
818 nfs_set_error(nfs
, "chmod call failed with \"%s\"", (char *)data
);
823 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
825 struct sync_cb_data cb_data
;
827 cb_data
.is_finished
= 0;
829 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
830 nfs_set_error(nfs
, "nfs_chmod_async failed");
834 wait_for_nfs_reply(nfs
, &cb_data
);
836 return cb_data
.status
;
845 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
847 struct sync_cb_data
*cb_data
= private_data
;
849 cb_data
->is_finished
= 1;
850 cb_data
->status
= status
;
853 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
858 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
860 struct sync_cb_data cb_data
;
862 cb_data
.is_finished
= 0;
864 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
865 nfs_set_error(nfs
, "nfs_fchmod_async failed");
869 wait_for_nfs_reply(nfs
, &cb_data
);
871 return cb_data
.status
;
880 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
882 struct sync_cb_data
*cb_data
= private_data
;
884 cb_data
->is_finished
= 1;
885 cb_data
->status
= status
;
888 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
893 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
895 struct sync_cb_data cb_data
;
897 cb_data
.is_finished
= 0;
899 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
900 nfs_set_error(nfs
, "nfs_chown_async failed");
904 wait_for_nfs_reply(nfs
, &cb_data
);
906 return cb_data
.status
;
912 static void fchown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
914 struct sync_cb_data
*cb_data
= private_data
;
916 cb_data
->is_finished
= 1;
917 cb_data
->status
= status
;
920 nfs_set_error(nfs
, "fchown call failed with \"%s\"", (char *)data
);
925 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
927 struct sync_cb_data cb_data
;
929 cb_data
.is_finished
= 0;
931 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
932 nfs_set_error(nfs
, "nfs_fchown_async failed");
936 wait_for_nfs_reply(nfs
, &cb_data
);
938 return cb_data
.status
;
946 static void utimes_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
948 struct sync_cb_data
*cb_data
= private_data
;
950 cb_data
->is_finished
= 1;
951 cb_data
->status
= status
;
954 nfs_set_error(nfs
, "utimes call failed with \"%s\"", (char *)data
);
959 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
961 struct sync_cb_data cb_data
;
963 cb_data
.is_finished
= 0;
965 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
966 nfs_set_error(nfs
, "nfs_utimes_async failed");
970 wait_for_nfs_reply(nfs
, &cb_data
);
972 return cb_data
.status
;
980 static void utime_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
982 struct sync_cb_data
*cb_data
= private_data
;
984 cb_data
->is_finished
= 1;
985 cb_data
->status
= status
;
988 nfs_set_error(nfs
, "utime call failed with \"%s\"", (char *)data
);
993 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
995 struct sync_cb_data cb_data
;
997 cb_data
.is_finished
= 0;
999 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
1000 nfs_set_error(nfs
, "nfs_utimes_async failed");
1004 wait_for_nfs_reply(nfs
, &cb_data
);
1006 return cb_data
.status
;
1015 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1017 struct sync_cb_data
*cb_data
= private_data
;
1019 cb_data
->is_finished
= 1;
1020 cb_data
->status
= status
;
1023 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
1028 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
1030 struct sync_cb_data cb_data
;
1032 cb_data
.is_finished
= 0;
1034 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
1035 nfs_set_error(nfs
, "nfs_access_async failed");
1039 wait_for_nfs_reply(nfs
, &cb_data
);
1041 return cb_data
.status
;
1049 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1051 struct sync_cb_data
*cb_data
= private_data
;
1053 cb_data
->is_finished
= 1;
1054 cb_data
->status
= status
;
1057 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
1062 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1064 struct sync_cb_data cb_data
;
1066 cb_data
.is_finished
= 0;
1068 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
1069 nfs_set_error(nfs
, "nfs_symlink_async failed");
1073 wait_for_nfs_reply(nfs
, &cb_data
);
1075 return cb_data
.status
;
1083 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1085 struct sync_cb_data
*cb_data
= private_data
;
1087 cb_data
->is_finished
= 1;
1088 cb_data
->status
= status
;
1091 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1096 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1098 struct sync_cb_data cb_data
;
1100 cb_data
.is_finished
= 0;
1102 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1103 nfs_set_error(nfs
, "nfs_rename_async failed");
1107 wait_for_nfs_reply(nfs
, &cb_data
);
1109 return cb_data
.status
;
1117 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1119 struct sync_cb_data
*cb_data
= private_data
;
1121 cb_data
->is_finished
= 1;
1122 cb_data
->status
= status
;
1125 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1130 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1132 struct sync_cb_data cb_data
;
1134 cb_data
.is_finished
= 0;
1136 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1137 nfs_set_error(nfs
, "nfs_link_async failed");
1141 wait_for_nfs_reply(nfs
, &cb_data
);
1143 return cb_data
.status
;
1146 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1148 struct sync_cb_data
*cb_data
= private_data
;
1151 cb_data
->is_finished
= 1;
1152 cb_data
->status
= status
;
1153 cb_data
->return_data
= NULL
;
1156 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1160 export
= *(exports
*)data
;
1161 while (export
!= NULL
) {
1164 new_export
= malloc(sizeof(*new_export
));
1165 memset(new_export
, 0, sizeof(*new_export
));
1166 new_export
->ex_dir
= strdup(export
->ex_dir
);
1167 new_export
->ex_next
= cb_data
->return_data
;
1169 cb_data
->return_data
= new_export
;
1171 export
= export
->ex_next
;
1175 struct exportnode
*mount_getexports(const char *server
)
1177 struct sync_cb_data cb_data
;
1178 struct rpc_context
*rpc
;
1181 cb_data
.is_finished
= 0;
1182 cb_data
.return_data
= NULL
;
1184 rpc
= rpc_init_context();
1185 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1186 rpc_destroy_context(rpc
);
1190 wait_for_reply(rpc
, &cb_data
);
1191 rpc_destroy_context(rpc
);
1193 return cb_data
.return_data
;
1196 void mount_free_export_list(struct exportnode
*exports
)
1198 struct exportnode
*tmp
;
1200 while ((tmp
= exports
)) {
1201 exports
= exports
->ex_next
;
1209 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1211 while (srv
!= NULL
) {
1212 struct nfs_server_list
*next
= srv
->next
;
1220 struct nfs_list_data
{
1222 struct nfs_server_list
*srvrs
;
1225 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1227 struct nfs_list_data
*srv_data
= private_data
;
1228 struct sockaddr
*sin
;
1230 struct nfs_server_list
*srvr
;
1232 if (status
== RPC_STATUS_CANCEL
) {
1236 srv_data
->status
= -1;
1240 sin
= rpc_get_recv_sockaddr(rpc
);
1242 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1243 srv_data
->status
= -1;
1247 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1248 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1249 srv_data
->status
= -1;
1253 /* check for dupes */
1254 for (srvr
= srv_data
->srvrs
; srvr
; srvr
= srvr
->next
) {
1255 if (!strcmp(hostdd
, srvr
->addr
)) {
1260 srvr
= malloc(sizeof(struct nfs_server_list
));
1262 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1263 srv_data
->status
= -1;
1267 srvr
->addr
= strdup(hostdd
);
1268 if (srvr
->addr
== NULL
) {
1269 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1271 srv_data
->status
= -1;
1275 srvr
->next
= srv_data
->srvrs
;
1276 srv_data
->srvrs
= srvr
;
1281 static int send_nfsd_probes(struct rpc_context
*rpc
, INTERFACE_INFO
*InterfaceList
, int numIfs
, struct nfs_list_data
*data
)
1285 for(i
= 0; i
< numIfs
; i
++)
1289 unsigned long nFlags
= 0;
1291 pAddress
= (SOCKADDR
*) & (InterfaceList
[i
].iiBroadcastAddress
);
1293 if(pAddress
->sa_family
!= AF_INET
)
1296 nFlags
= InterfaceList
[i
].iiFlags
;
1298 if (!(nFlags
& IFF_UP
))
1303 if (nFlags
& IFF_LOOPBACK
)
1308 if (!(nFlags
& IFF_BROADCAST
))
1313 if (getnameinfo(pAddress
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0)
1318 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0)
1323 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0)
1331 struct nfs_server_list
*nfs_find_local_servers(void)
1333 struct rpc_context
*rpc
;
1334 struct nfs_list_data data
= {0, NULL
};
1335 struct timeval tv_start
, tv_current
;
1338 INTERFACE_INFO InterfaceList
[20];
1339 unsigned long nBytesReturned
;
1340 int nNumInterfaces
= 0;
1342 rpc
= rpc_init_udp_context();
1348 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0)
1350 rpc_destroy_context(rpc
);
1354 if (WSAIoctl(rpc_get_fd(rpc
), SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
, sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
1359 nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
1361 for (loop
=0; loop
<3; loop
++)
1363 if (send_nfsd_probes(rpc
, InterfaceList
, nNumInterfaces
, &data
) != 0)
1365 rpc_destroy_context(rpc
);
1369 win32_gettimeofday(&tv_start
, NULL
);
1374 pfd
.fd
= rpc_get_fd(rpc
);
1375 pfd
.events
= rpc_which_events(rpc
);
1377 win32_gettimeofday(&tv_current
, NULL
);
1379 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1380 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1382 if (poll(&pfd
, 1, mpt
) < 0)
1384 free_nfs_srvr_list(data
.srvrs
);
1385 rpc_destroy_context(rpc
);
1388 if (pfd
.revents
== 0)
1393 if (rpc_service(rpc
, pfd
.revents
) < 0)
1400 rpc_destroy_context(rpc
);
1402 if (data
.status
!= 0)
1404 free_nfs_srvr_list(data
.srvrs
);
1411 static int send_nfsd_probes(struct rpc_context
*rpc
, struct ifconf
*ifc
, struct nfs_list_data
*data
)
1415 for (ptr
=(char *)(ifc
->ifc_buf
); ptr
< (char *)(ifc
->ifc_buf
) + ifc
->ifc_len
; ) {
1419 ifr
= (struct ifreq
*)ptr
;
1420 #ifdef HAVE_SOCKADDR_LEN
1421 if (ifr
->ifr_addr
.sa_len
> sizeof(struct sockaddr
)) {
1422 ptr
+= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
1424 ptr
+= sizeof(ifr
->ifr_name
) + sizeof(struct sockaddr
);
1427 ptr
+= sizeof(struct ifreq
);
1430 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) {
1433 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, ifr
) < 0) {
1436 if (!(ifr
->ifr_flags
& IFF_UP
)) {
1439 if (ifr
->ifr_flags
& IFF_LOOPBACK
) {
1442 if (!(ifr
->ifr_flags
& IFF_BROADCAST
)) {
1445 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, ifr
) < 0) {
1448 if (getnameinfo(&ifr
->ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1451 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1455 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0) {
1463 struct nfs_server_list
*nfs_find_local_servers(void)
1465 struct rpc_context
*rpc
;
1466 struct nfs_list_data data
= {0, NULL
};
1467 struct timeval tv_start
, tv_current
;
1472 rpc
= rpc_init_udp_context();
1477 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1478 rpc_destroy_context(rpc
);
1483 /* get list of all interfaces */
1484 size
= sizeof(struct ifreq
);
1488 while(ifc
.ifc_len
> (size
- sizeof(struct ifreq
))) {
1493 ifc
.ifc_buf
= malloc(size
);
1494 memset(ifc
.ifc_buf
, 0, size
);
1495 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1496 rpc_destroy_context(rpc
);
1502 for (loop
=0; loop
<3; loop
++) {
1503 if (send_nfsd_probes(rpc
, &ifc
, &data
) != 0) {
1504 rpc_destroy_context(rpc
);
1509 gettimeofday(&tv_start
, NULL
);
1513 pfd
.fd
= rpc_get_fd(rpc
);
1514 pfd
.events
= rpc_which_events(rpc
);
1516 gettimeofday(&tv_current
, NULL
);
1518 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1519 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1521 if (poll(&pfd
, 1, mpt
) < 0) {
1522 free_nfs_srvr_list(data
.srvrs
);
1523 rpc_destroy_context(rpc
);
1526 if (pfd
.revents
== 0) {
1530 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1537 rpc_destroy_context(rpc
);
1539 if (data
.status
!= 0) {
1540 free_nfs_srvr_list(data
.srvrs
);