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>
51 #include "libnfs-zdr.h"
53 #include "libnfs-raw.h"
54 #include "libnfs-raw-mount.h"
55 #include "libnfs-raw-nfs.h"
56 #include "libnfs-private.h"
67 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
71 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
73 while (!cb_data
->is_finished
) {
75 pfd
.fd
= rpc_get_fd(rpc
);
76 pfd
.events
= rpc_which_events(rpc
);
77 if (poll(&pfd
, 1, -1) < 0) {
78 rpc_set_error(rpc
, "Poll failed");
79 cb_data
->status
= -EIO
;
82 if (rpc_service(rpc
, pfd
.revents
) < 0) {
83 rpc_set_error(rpc
, "rpc_service failed");
84 cb_data
->status
= -EIO
;
87 if (rpc_get_fd(rpc
) == -1) {
88 rpc_set_error(rpc
, "Socket closed\n");
94 static void wait_for_nfs_reply(struct nfs_context
*nfs
, struct sync_cb_data
*cb_data
)
98 while (!cb_data
->is_finished
) {
100 pfd
.fd
= nfs_get_fd(nfs
);
101 pfd
.events
= nfs_which_events(nfs
);
102 if (poll(&pfd
, 1, -1) < 0) {
103 nfs_set_error(nfs
, "Poll failed");
104 cb_data
->status
= -EIO
;
107 if (nfs_service(nfs
, pfd
.revents
) < 0) {
108 nfs_set_error(nfs
, "nfs_service failed");
109 cb_data
->status
= -EIO
;
121 * connect to the server and mount the export
123 static void mount_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
125 struct sync_cb_data
*cb_data
= private_data
;
127 cb_data
->is_finished
= 1;
128 cb_data
->status
= status
;
131 nfs_set_error(nfs
, "mount/mnt call failed with \"%s\"", (char *)data
);
136 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
138 struct sync_cb_data cb_data
;
139 struct rpc_context
*rpc
= nfs_get_rpc_context(nfs
);
141 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
143 cb_data
.is_finished
= 0;
145 if (nfs_mount_async(nfs
, server
, export
, mount_cb
, &cb_data
) != 0) {
146 nfs_set_error(nfs
, "nfs_mount_async failed");
150 wait_for_nfs_reply(nfs
, &cb_data
);
152 /* Dont want any more callbacks even if the socket is closed */
153 rpc
->connect_cb
= NULL
;
155 return cb_data
.status
;
162 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
164 struct sync_cb_data
*cb_data
= private_data
;
166 cb_data
->is_finished
= 1;
167 cb_data
->status
= status
;
170 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
174 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
177 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
179 struct sync_cb_data cb_data
;
181 cb_data
.is_finished
= 0;
182 cb_data
.return_data
= st
;
184 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
185 nfs_set_error(nfs
, "nfs_stat_async failed");
189 wait_for_nfs_reply(nfs
, &cb_data
);
191 return cb_data
.status
;
200 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
202 struct sync_cb_data
*cb_data
= private_data
;
203 struct nfsfh
*fh
, **nfsfh
;
205 cb_data
->is_finished
= 1;
206 cb_data
->status
= status
;
209 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
214 nfsfh
= cb_data
->return_data
;
218 int nfs_open(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
220 struct sync_cb_data cb_data
;
222 cb_data
.is_finished
= 0;
223 cb_data
.return_data
= nfsfh
;
225 if (nfs_open_async(nfs
, path
, mode
, open_cb
, &cb_data
) != 0) {
226 nfs_set_error(nfs
, "nfs_open_async failed");
230 wait_for_nfs_reply(nfs
, &cb_data
);
232 return cb_data
.status
;
241 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
243 struct sync_cb_data
*cb_data
= private_data
;
245 cb_data
->is_finished
= 1;
246 cb_data
->status
= status
;
249 nfs_set_error(nfs
, "pread call failed with \"%s\"", (char *)data
);
253 buffer
= cb_data
->return_data
;
254 memcpy(buffer
, (char *)data
, status
);
257 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buffer
)
259 struct sync_cb_data cb_data
;
261 cb_data
.is_finished
= 0;
262 cb_data
.return_data
= buffer
;
264 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
265 nfs_set_error(nfs
, "nfs_pread_async failed");
269 wait_for_nfs_reply(nfs
, &cb_data
);
271 return cb_data
.status
;
277 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buffer
)
279 return nfs_pread(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buffer
);
285 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
287 struct sync_cb_data
*cb_data
= private_data
;
288 cb_data
->is_finished
= 1;
289 cb_data
->status
= status
;
292 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
297 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
299 struct sync_cb_data cb_data
;
301 cb_data
.is_finished
= 0;
303 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
304 nfs_set_error(nfs
, "nfs_close_async failed");
308 wait_for_nfs_reply(nfs
, &cb_data
);
310 return cb_data
.status
;
319 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
321 struct sync_cb_data cb_data
;
323 cb_data
.is_finished
= 0;
324 cb_data
.return_data
= st
;
326 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
327 nfs_set_error(nfs
, "nfs_fstat_async failed");
331 wait_for_nfs_reply(nfs
, &cb_data
);
333 return cb_data
.status
;
340 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
342 struct sync_cb_data
*cb_data
= private_data
;
343 cb_data
->is_finished
= 1;
344 cb_data
->status
= status
;
347 nfs_set_error(nfs
, "pwrite call failed with \"%s\"", (char *)data
);
352 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buf
)
354 struct sync_cb_data cb_data
;
356 cb_data
.is_finished
= 0;
358 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
359 nfs_set_error(nfs
, "nfs_pwrite_async failed");
363 wait_for_nfs_reply(nfs
, &cb_data
);
365 return cb_data
.status
;
371 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buf
)
373 return nfs_pwrite(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buf
);
380 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
382 struct sync_cb_data
*cb_data
= private_data
;
383 cb_data
->is_finished
= 1;
384 cb_data
->status
= status
;
387 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
392 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
394 struct sync_cb_data cb_data
;
396 cb_data
.is_finished
= 0;
398 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
399 nfs_set_error(nfs
, "nfs_fsync_async failed");
403 wait_for_nfs_reply(nfs
, &cb_data
);
405 return cb_data
.status
;
414 static void ftruncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
416 struct sync_cb_data
*cb_data
= private_data
;
417 cb_data
->is_finished
= 1;
418 cb_data
->status
= status
;
421 nfs_set_error(nfs
, "ftruncate call failed with \"%s\"", (char *)data
);
426 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t length
)
428 struct sync_cb_data cb_data
;
430 cb_data
.is_finished
= 0;
432 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_cb
, &cb_data
) != 0) {
433 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
437 wait_for_nfs_reply(nfs
, &cb_data
);
439 return cb_data
.status
;
447 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
449 struct sync_cb_data
*cb_data
= private_data
;
450 cb_data
->is_finished
= 1;
451 cb_data
->status
= status
;
454 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
459 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, uint64_t length
)
461 struct sync_cb_data cb_data
;
463 cb_data
.is_finished
= 0;
465 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
466 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
470 wait_for_nfs_reply(nfs
, &cb_data
);
472 return cb_data
.status
;
482 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
484 struct sync_cb_data
*cb_data
= private_data
;
485 cb_data
->is_finished
= 1;
486 cb_data
->status
= status
;
489 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
494 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
496 struct sync_cb_data cb_data
;
498 cb_data
.is_finished
= 0;
500 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
501 nfs_set_error(nfs
, "nfs_mkdir_async failed");
505 wait_for_nfs_reply(nfs
, &cb_data
);
507 return cb_data
.status
;
517 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
519 struct sync_cb_data
*cb_data
= private_data
;
520 cb_data
->is_finished
= 1;
521 cb_data
->status
= status
;
524 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
529 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
531 struct sync_cb_data cb_data
;
533 cb_data
.is_finished
= 0;
535 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
536 nfs_set_error(nfs
, "nfs_rmdir_async failed");
540 wait_for_nfs_reply(nfs
, &cb_data
);
542 return cb_data
.status
;
550 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
552 struct sync_cb_data
*cb_data
= private_data
;
553 struct nfsfh
*fh
, **nfsfh
;
555 cb_data
->is_finished
= 1;
556 cb_data
->status
= status
;
559 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
564 nfsfh
= cb_data
->return_data
;
568 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
570 struct sync_cb_data cb_data
;
572 cb_data
.is_finished
= 0;
573 cb_data
.return_data
= nfsfh
;
575 if (nfs_creat_async(nfs
, path
, mode
, creat_cb
, &cb_data
) != 0) {
576 nfs_set_error(nfs
, "nfs_creat_async failed");
580 wait_for_nfs_reply(nfs
, &cb_data
);
582 return cb_data
.status
;
588 static void mknod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
590 struct sync_cb_data
*cb_data
= private_data
;
592 cb_data
->is_finished
= 1;
593 cb_data
->status
= status
;
596 nfs_set_error(nfs
, "mknod call failed with \"%s\"", (char *)data
);
601 int nfs_mknod(struct nfs_context
*nfs
, const char *path
, int mode
, int dev
)
603 struct sync_cb_data cb_data
;
605 cb_data
.is_finished
= 0;
607 if (nfs_mknod_async(nfs
, path
, mode
, dev
, mknod_cb
, &cb_data
) != 0) {
608 nfs_set_error(nfs
, "nfs_creat_async failed");
612 wait_for_nfs_reply(nfs
, &cb_data
);
614 return cb_data
.status
;
621 static void unlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
623 struct sync_cb_data
*cb_data
= private_data
;
625 cb_data
->is_finished
= 1;
626 cb_data
->status
= status
;
629 nfs_set_error(nfs
, "unlink call failed with \"%s\"", (char *)data
);
634 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
636 struct sync_cb_data cb_data
;
638 cb_data
.is_finished
= 0;
640 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
641 nfs_set_error(nfs
, "nfs_unlink_async failed");
645 wait_for_nfs_reply(nfs
, &cb_data
);
647 return cb_data
.status
;
655 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
657 struct sync_cb_data
*cb_data
= private_data
;
658 struct nfsdir
*dir
, **nfsdir
;
660 cb_data
->is_finished
= 1;
661 cb_data
->status
= status
;
664 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
669 nfsdir
= cb_data
->return_data
;
673 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
675 struct sync_cb_data cb_data
;
677 cb_data
.is_finished
= 0;
678 cb_data
.return_data
= nfsdir
;
680 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
681 nfs_set_error(nfs
, "nfs_opendir_async failed");
685 wait_for_nfs_reply(nfs
, &cb_data
);
687 return cb_data
.status
;
694 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
696 struct sync_cb_data
*cb_data
= private_data
;
698 cb_data
->is_finished
= 1;
699 cb_data
->status
= status
;
702 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
706 if (cb_data
->return_data
!= NULL
) {
707 memcpy(cb_data
->return_data
, data
, sizeof(uint64_t));
711 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, int whence
, uint64_t *current_offset
)
713 struct sync_cb_data cb_data
;
715 cb_data
.is_finished
= 0;
716 cb_data
.return_data
= current_offset
;
718 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
719 nfs_set_error(nfs
, "nfs_lseek_async failed");
723 wait_for_nfs_reply(nfs
, &cb_data
);
725 return cb_data
.status
;
733 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
735 struct sync_cb_data
*cb_data
= private_data
;
737 cb_data
->is_finished
= 1;
738 cb_data
->status
= status
;
741 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
745 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
748 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
750 struct sync_cb_data cb_data
;
752 cb_data
.is_finished
= 0;
753 cb_data
.return_data
= svfs
;
755 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
756 nfs_set_error(nfs
, "nfs_statvfs_async failed");
760 wait_for_nfs_reply(nfs
, &cb_data
);
762 return cb_data
.status
;
772 static void readlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
774 struct sync_cb_data
*cb_data
= private_data
;
776 cb_data
->is_finished
= 1;
777 cb_data
->status
= status
;
780 nfs_set_error(nfs
, "readlink call failed with \"%s\"", (char *)data
);
784 if (strlen(data
) > (size_t)cb_data
->return_int
) {
785 nfs_set_error(nfs
, "Too small buffer for readlink");
786 cb_data
->status
= -ENAMETOOLONG
;
790 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
793 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
795 struct sync_cb_data cb_data
;
797 cb_data
.is_finished
= 0;
798 cb_data
.return_data
= buf
;
799 cb_data
.return_int
= bufsize
;
801 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
802 nfs_set_error(nfs
, "nfs_readlink_async failed");
806 wait_for_nfs_reply(nfs
, &cb_data
);
808 return cb_data
.status
;
816 static void chmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
818 struct sync_cb_data
*cb_data
= private_data
;
820 cb_data
->is_finished
= 1;
821 cb_data
->status
= status
;
824 nfs_set_error(nfs
, "chmod call failed with \"%s\"", (char *)data
);
829 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
831 struct sync_cb_data cb_data
;
833 cb_data
.is_finished
= 0;
835 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
836 nfs_set_error(nfs
, "nfs_chmod_async failed");
840 wait_for_nfs_reply(nfs
, &cb_data
);
842 return cb_data
.status
;
851 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
853 struct sync_cb_data
*cb_data
= private_data
;
855 cb_data
->is_finished
= 1;
856 cb_data
->status
= status
;
859 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
864 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
866 struct sync_cb_data cb_data
;
868 cb_data
.is_finished
= 0;
870 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
871 nfs_set_error(nfs
, "nfs_fchmod_async failed");
875 wait_for_nfs_reply(nfs
, &cb_data
);
877 return cb_data
.status
;
886 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
888 struct sync_cb_data
*cb_data
= private_data
;
890 cb_data
->is_finished
= 1;
891 cb_data
->status
= status
;
894 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
899 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
901 struct sync_cb_data cb_data
;
903 cb_data
.is_finished
= 0;
905 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
906 nfs_set_error(nfs
, "nfs_chown_async failed");
910 wait_for_nfs_reply(nfs
, &cb_data
);
912 return cb_data
.status
;
918 static void fchown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
920 struct sync_cb_data
*cb_data
= private_data
;
922 cb_data
->is_finished
= 1;
923 cb_data
->status
= status
;
926 nfs_set_error(nfs
, "fchown call failed with \"%s\"", (char *)data
);
931 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
933 struct sync_cb_data cb_data
;
935 cb_data
.is_finished
= 0;
937 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
938 nfs_set_error(nfs
, "nfs_fchown_async failed");
942 wait_for_nfs_reply(nfs
, &cb_data
);
944 return cb_data
.status
;
952 static void utimes_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
954 struct sync_cb_data
*cb_data
= private_data
;
956 cb_data
->is_finished
= 1;
957 cb_data
->status
= status
;
960 nfs_set_error(nfs
, "utimes call failed with \"%s\"", (char *)data
);
965 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
967 struct sync_cb_data cb_data
;
969 cb_data
.is_finished
= 0;
971 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
972 nfs_set_error(nfs
, "nfs_utimes_async failed");
976 wait_for_nfs_reply(nfs
, &cb_data
);
978 return cb_data
.status
;
986 static void utime_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
988 struct sync_cb_data
*cb_data
= private_data
;
990 cb_data
->is_finished
= 1;
991 cb_data
->status
= status
;
994 nfs_set_error(nfs
, "utime call failed with \"%s\"", (char *)data
);
999 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
1001 struct sync_cb_data cb_data
;
1003 cb_data
.is_finished
= 0;
1005 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
1006 nfs_set_error(nfs
, "nfs_utimes_async failed");
1010 wait_for_nfs_reply(nfs
, &cb_data
);
1012 return cb_data
.status
;
1021 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1023 struct sync_cb_data
*cb_data
= private_data
;
1025 cb_data
->is_finished
= 1;
1026 cb_data
->status
= status
;
1029 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
1034 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
1036 struct sync_cb_data cb_data
;
1038 cb_data
.is_finished
= 0;
1040 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
1041 nfs_set_error(nfs
, "nfs_access_async failed");
1045 wait_for_nfs_reply(nfs
, &cb_data
);
1047 return cb_data
.status
;
1055 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1057 struct sync_cb_data
*cb_data
= private_data
;
1059 cb_data
->is_finished
= 1;
1060 cb_data
->status
= status
;
1063 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
1068 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1070 struct sync_cb_data cb_data
;
1072 cb_data
.is_finished
= 0;
1074 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
1075 nfs_set_error(nfs
, "nfs_symlink_async failed");
1079 wait_for_nfs_reply(nfs
, &cb_data
);
1081 return cb_data
.status
;
1089 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1091 struct sync_cb_data
*cb_data
= private_data
;
1093 cb_data
->is_finished
= 1;
1094 cb_data
->status
= status
;
1097 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1102 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1104 struct sync_cb_data cb_data
;
1106 cb_data
.is_finished
= 0;
1108 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1109 nfs_set_error(nfs
, "nfs_rename_async failed");
1113 wait_for_nfs_reply(nfs
, &cb_data
);
1115 return cb_data
.status
;
1123 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1125 struct sync_cb_data
*cb_data
= private_data
;
1127 cb_data
->is_finished
= 1;
1128 cb_data
->status
= status
;
1131 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1136 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1138 struct sync_cb_data cb_data
;
1140 cb_data
.is_finished
= 0;
1142 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1143 nfs_set_error(nfs
, "nfs_link_async failed");
1147 wait_for_nfs_reply(nfs
, &cb_data
);
1149 return cb_data
.status
;
1152 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1154 struct sync_cb_data
*cb_data
= private_data
;
1157 assert(mount_context
->magic
== RPC_CONTEXT_MAGIC
);
1159 cb_data
->is_finished
= 1;
1160 cb_data
->status
= status
;
1161 cb_data
->return_data
= NULL
;
1164 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1168 export
= *(exports
*)data
;
1169 while (export
!= NULL
) {
1172 new_export
= malloc(sizeof(*new_export
));
1173 memset(new_export
, 0, sizeof(*new_export
));
1174 new_export
->ex_dir
= strdup(export
->ex_dir
);
1175 new_export
->ex_next
= cb_data
->return_data
;
1177 cb_data
->return_data
= new_export
;
1179 export
= export
->ex_next
;
1183 struct exportnode
*mount_getexports(const char *server
)
1185 struct sync_cb_data cb_data
;
1186 struct rpc_context
*rpc
;
1189 cb_data
.is_finished
= 0;
1190 cb_data
.return_data
= NULL
;
1192 rpc
= rpc_init_context();
1193 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1194 rpc_destroy_context(rpc
);
1198 wait_for_reply(rpc
, &cb_data
);
1199 rpc_destroy_context(rpc
);
1201 return cb_data
.return_data
;
1204 void mount_free_export_list(struct exportnode
*exports
)
1206 struct exportnode
*tmp
;
1208 while ((tmp
= exports
)) {
1209 exports
= exports
->ex_next
;
1217 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1219 while (srv
!= NULL
) {
1220 struct nfs_server_list
*next
= srv
->next
;
1228 struct nfs_list_data
{
1230 struct nfs_server_list
*srvrs
;
1233 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1235 struct nfs_list_data
*srv_data
= private_data
;
1236 struct sockaddr
*sin
;
1238 struct nfs_server_list
*srvr
;
1240 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1242 if (status
== RPC_STATUS_CANCEL
) {
1246 srv_data
->status
= -1;
1250 sin
= rpc_get_recv_sockaddr(rpc
);
1252 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1253 srv_data
->status
= -1;
1257 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1258 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1259 srv_data
->status
= -1;
1263 /* check for dupes */
1264 for (srvr
= srv_data
->srvrs
; srvr
; srvr
= srvr
->next
) {
1265 if (!strcmp(hostdd
, srvr
->addr
)) {
1270 srvr
= malloc(sizeof(struct nfs_server_list
));
1272 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1273 srv_data
->status
= -1;
1277 srvr
->addr
= strdup(hostdd
);
1278 if (srvr
->addr
== NULL
) {
1279 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1281 srv_data
->status
= -1;
1285 srvr
->next
= srv_data
->srvrs
;
1286 srv_data
->srvrs
= srvr
;
1291 static int send_nfsd_probes(struct rpc_context
*rpc
, INTERFACE_INFO
*InterfaceList
, int numIfs
, struct nfs_list_data
*data
)
1295 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1297 for(i
= 0; i
< numIfs
; i
++)
1301 unsigned long nFlags
= 0;
1303 pAddress
= (SOCKADDR
*) & (InterfaceList
[i
].iiBroadcastAddress
);
1305 if(pAddress
->sa_family
!= AF_INET
)
1308 nFlags
= InterfaceList
[i
].iiFlags
;
1310 if (!(nFlags
& IFF_UP
))
1315 if (nFlags
& IFF_LOOPBACK
)
1320 if (!(nFlags
& IFF_BROADCAST
))
1325 if (getnameinfo(pAddress
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0)
1330 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0)
1335 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0)
1343 struct nfs_server_list
*nfs_find_local_servers(void)
1345 struct rpc_context
*rpc
;
1346 struct nfs_list_data data
= {0, NULL
};
1347 struct timeval tv_start
, tv_current
;
1350 INTERFACE_INFO InterfaceList
[20];
1351 unsigned long nBytesReturned
;
1352 int nNumInterfaces
= 0;
1354 rpc
= rpc_init_udp_context();
1360 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0)
1362 rpc_destroy_context(rpc
);
1366 if (WSAIoctl(rpc_get_fd(rpc
), SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
, sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
1371 nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
1373 for (loop
=0; loop
<3; loop
++)
1375 if (send_nfsd_probes(rpc
, InterfaceList
, nNumInterfaces
, &data
) != 0)
1377 rpc_destroy_context(rpc
);
1381 win32_gettimeofday(&tv_start
, NULL
);
1386 pfd
.fd
= rpc_get_fd(rpc
);
1387 pfd
.events
= rpc_which_events(rpc
);
1389 win32_gettimeofday(&tv_current
, NULL
);
1391 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1392 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1394 if (poll(&pfd
, 1, mpt
) < 0)
1396 free_nfs_srvr_list(data
.srvrs
);
1397 rpc_destroy_context(rpc
);
1400 if (pfd
.revents
== 0)
1405 if (rpc_service(rpc
, pfd
.revents
) < 0)
1412 rpc_destroy_context(rpc
);
1414 if (data
.status
!= 0)
1416 free_nfs_srvr_list(data
.srvrs
);
1423 static int send_nfsd_probes(struct rpc_context
*rpc
, struct ifconf
*ifc
, struct nfs_list_data
*data
)
1427 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1429 for (ptr
=(char *)(ifc
->ifc_buf
); ptr
< (char *)(ifc
->ifc_buf
) + ifc
->ifc_len
; ) {
1433 ifr
= (struct ifreq
*)ptr
;
1434 #ifdef HAVE_SOCKADDR_LEN
1435 if (ifr
->ifr_addr
.sa_len
> sizeof(struct sockaddr
)) {
1436 ptr
+= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
1438 ptr
+= sizeof(ifr
->ifr_name
) + sizeof(struct sockaddr
);
1441 ptr
+= sizeof(struct ifreq
);
1444 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) {
1447 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, ifr
) < 0) {
1450 if (!(ifr
->ifr_flags
& IFF_UP
)) {
1453 if (ifr
->ifr_flags
& IFF_LOOPBACK
) {
1456 if (!(ifr
->ifr_flags
& IFF_BROADCAST
)) {
1459 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, ifr
) < 0) {
1462 if (getnameinfo(&ifr
->ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1465 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1469 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0) {
1477 struct nfs_server_list
*nfs_find_local_servers(void)
1479 struct rpc_context
*rpc
;
1480 struct nfs_list_data data
= {0, NULL
};
1481 struct timeval tv_start
, tv_current
;
1486 rpc
= rpc_init_udp_context();
1491 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1492 rpc_destroy_context(rpc
);
1497 /* get list of all interfaces */
1498 size
= sizeof(struct ifreq
);
1502 while(ifc
.ifc_len
> (size
- sizeof(struct ifreq
))) {
1507 ifc
.ifc_buf
= malloc(size
);
1508 memset(ifc
.ifc_buf
, 0, size
);
1509 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1510 rpc_destroy_context(rpc
);
1516 for (loop
=0; loop
<3; loop
++) {
1517 if (send_nfsd_probes(rpc
, &ifc
, &data
) != 0) {
1518 rpc_destroy_context(rpc
);
1523 gettimeofday(&tv_start
, NULL
);
1527 pfd
.fd
= rpc_get_fd(rpc
);
1528 pfd
.events
= rpc_which_events(rpc
);
1530 gettimeofday(&tv_current
, NULL
);
1532 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1533 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1535 if (poll(&pfd
, 1, mpt
) < 0) {
1536 free_nfs_srvr_list(data
.srvrs
);
1537 rpc_destroy_context(rpc
);
1540 if (pfd
.revents
== 0) {
1544 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1551 rpc_destroy_context(rpc
);
1553 if (data
.status
!= 0) {
1554 free_nfs_srvr_list(data
.srvrs
);