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
25 #include "aros_compat.h"
29 #include "win32_compat.h"
37 #define statvfs statfs
44 #ifdef HAVE_SYS_STATVFS_H
45 #include <sys/statvfs.h>
48 #ifdef HAVE_SYS_IOCTL_H
49 #include <sys/ioctl.h>
52 #ifdef HAVE_SYS_SOCKET_H
53 #include <sys/socket.h>
68 #ifdef HAVE_NETINET_IN_H
69 #include <netinet/in.h>
80 #include <sys/types.h>
85 #ifdef HAVE_SYS_SOCKIO_H
86 #include <sys/sockio.h>
89 #include "libnfs-zdr.h"
91 #include "libnfs-raw.h"
92 #include "libnfs-raw-mount.h"
93 #include "libnfs-raw-nfs.h"
94 #include "libnfs-private.h"
105 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
109 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
111 while (!cb_data
->is_finished
) {
113 pfd
.fd
= rpc_get_fd(rpc
);
114 pfd
.events
= rpc_which_events(rpc
);
115 if (poll(&pfd
, 1, -1) < 0) {
116 rpc_set_error(rpc
, "Poll failed");
117 cb_data
->status
= -EIO
;
120 if (rpc_service(rpc
, pfd
.revents
) < 0) {
121 rpc_set_error(rpc
, "rpc_service failed");
122 cb_data
->status
= -EIO
;
125 if (rpc_get_fd(rpc
) == -1) {
126 rpc_set_error(rpc
, "Socket closed\n");
132 static void wait_for_nfs_reply(struct nfs_context
*nfs
, struct sync_cb_data
*cb_data
)
136 while (!cb_data
->is_finished
) {
138 pfd
.fd
= nfs_get_fd(nfs
);
139 pfd
.events
= nfs_which_events(nfs
);
140 if (poll(&pfd
, 1, -1) < 0) {
141 nfs_set_error(nfs
, "Poll failed");
142 cb_data
->status
= -EIO
;
145 if (nfs_service(nfs
, pfd
.revents
) < 0) {
146 nfs_set_error(nfs
, "nfs_service failed");
147 cb_data
->status
= -EIO
;
159 * connect to the server and mount the export
161 static void mount_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
, "mount/mnt call failed with \"%s\"", (char *)data
);
174 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
176 struct sync_cb_data cb_data
;
177 struct rpc_context
*rpc
= nfs_get_rpc_context(nfs
);
179 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
181 cb_data
.is_finished
= 0;
183 if (nfs_mount_async(nfs
, server
, export
, mount_cb
, &cb_data
) != 0) {
184 nfs_set_error(nfs
, "nfs_mount_async failed");
188 wait_for_nfs_reply(nfs
, &cb_data
);
190 /* Dont want any more callbacks even if the socket is closed */
191 rpc
->connect_cb
= NULL
;
193 return cb_data
.status
;
200 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
202 struct sync_cb_data
*cb_data
= private_data
;
204 cb_data
->is_finished
= 1;
205 cb_data
->status
= status
;
208 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
212 memcpy(cb_data
->return_data
, data
, sizeof(struct __stat64
));
214 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
219 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct __stat64
*st
)
221 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
224 struct sync_cb_data cb_data
;
226 cb_data
.is_finished
= 0;
227 cb_data
.return_data
= st
;
229 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
230 nfs_set_error(nfs
, "nfs_stat_async failed");
234 wait_for_nfs_reply(nfs
, &cb_data
);
236 return cb_data
.status
;
239 static void stat64_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
241 struct sync_cb_data
*cb_data
= private_data
;
243 cb_data
->is_finished
= 1;
244 cb_data
->status
= status
;
247 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
250 memcpy(cb_data
->return_data
, data
, sizeof(struct nfs_stat_64
));
253 int nfs_stat64(struct nfs_context
*nfs
, const char *path
, struct nfs_stat_64
*st
)
255 struct sync_cb_data cb_data
;
257 cb_data
.is_finished
= 0;
258 cb_data
.return_data
= st
;
260 if (nfs_stat64_async(nfs
, path
, stat64_cb
, &cb_data
) != 0) {
261 nfs_set_error(nfs
, "nfs_stat64_async failed");
265 wait_for_nfs_reply(nfs
, &cb_data
);
267 return cb_data
.status
;
273 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
275 struct sync_cb_data
*cb_data
= private_data
;
276 struct nfsfh
*fh
, **nfsfh
;
278 cb_data
->is_finished
= 1;
279 cb_data
->status
= status
;
282 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
287 nfsfh
= cb_data
->return_data
;
291 int nfs_open(struct nfs_context
*nfs
, const char *path
, int flags
, struct nfsfh
**nfsfh
)
293 struct sync_cb_data cb_data
;
295 cb_data
.is_finished
= 0;
296 cb_data
.return_data
= nfsfh
;
298 if (nfs_open_async(nfs
, path
, flags
, open_cb
, &cb_data
) != 0) {
299 nfs_set_error(nfs
, "nfs_open_async failed");
303 wait_for_nfs_reply(nfs
, &cb_data
);
305 return cb_data
.status
;
311 static void chdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
313 struct sync_cb_data
*cb_data
= private_data
;
315 cb_data
->is_finished
= 1;
316 cb_data
->status
= status
;
319 nfs_set_error(nfs
, "chdir call failed with \"%s\"", (char *)data
);
324 int nfs_chdir(struct nfs_context
*nfs
, const char *path
)
326 struct sync_cb_data cb_data
;
328 cb_data
.is_finished
= 0;
330 if (nfs_chdir_async(nfs
, path
, chdir_cb
, &cb_data
) != 0) {
331 nfs_set_error(nfs
, "nfs_chdir_async failed with %s",
336 wait_for_nfs_reply(nfs
, &cb_data
);
338 return cb_data
.status
;
346 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
348 struct sync_cb_data
*cb_data
= private_data
;
350 cb_data
->is_finished
= 1;
351 cb_data
->status
= status
;
354 nfs_set_error(nfs
, "pread call failed with \"%s\"", (char *)data
);
358 buffer
= cb_data
->return_data
;
359 memcpy(buffer
, (char *)data
, status
);
362 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buffer
)
364 struct sync_cb_data cb_data
;
366 cb_data
.is_finished
= 0;
367 cb_data
.return_data
= buffer
;
369 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
370 nfs_set_error(nfs
, "nfs_pread_async failed");
374 wait_for_nfs_reply(nfs
, &cb_data
);
376 return cb_data
.status
;
382 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buffer
)
384 return nfs_pread(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buffer
);
390 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
392 struct sync_cb_data
*cb_data
= private_data
;
393 cb_data
->is_finished
= 1;
394 cb_data
->status
= status
;
397 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
402 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
404 struct sync_cb_data cb_data
;
406 cb_data
.is_finished
= 0;
408 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
409 nfs_set_error(nfs
, "nfs_close_async failed");
413 wait_for_nfs_reply(nfs
, &cb_data
);
415 return cb_data
.status
;
424 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
426 struct sync_cb_data cb_data
;
428 cb_data
.is_finished
= 0;
429 cb_data
.return_data
= st
;
431 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
432 nfs_set_error(nfs
, "nfs_fstat_async failed");
436 wait_for_nfs_reply(nfs
, &cb_data
);
438 return cb_data
.status
;
445 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
447 struct sync_cb_data
*cb_data
= private_data
;
448 cb_data
->is_finished
= 1;
449 cb_data
->status
= status
;
452 nfs_set_error(nfs
, "pwrite call failed with \"%s\"", (char *)data
);
457 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buf
)
459 struct sync_cb_data cb_data
;
461 cb_data
.is_finished
= 0;
463 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
464 nfs_set_error(nfs
, "nfs_pwrite_async failed");
468 wait_for_nfs_reply(nfs
, &cb_data
);
470 return cb_data
.status
;
476 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buf
)
478 return nfs_pwrite(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buf
);
485 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
487 struct sync_cb_data
*cb_data
= private_data
;
488 cb_data
->is_finished
= 1;
489 cb_data
->status
= status
;
492 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
497 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
499 struct sync_cb_data cb_data
;
501 cb_data
.is_finished
= 0;
503 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
504 nfs_set_error(nfs
, "nfs_fsync_async failed");
508 wait_for_nfs_reply(nfs
, &cb_data
);
510 return cb_data
.status
;
519 static void ftruncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
521 struct sync_cb_data
*cb_data
= private_data
;
522 cb_data
->is_finished
= 1;
523 cb_data
->status
= status
;
526 nfs_set_error(nfs
, "ftruncate call failed with \"%s\"", (char *)data
);
531 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t length
)
533 struct sync_cb_data cb_data
;
535 cb_data
.is_finished
= 0;
537 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_cb
, &cb_data
) != 0) {
538 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
542 wait_for_nfs_reply(nfs
, &cb_data
);
544 return cb_data
.status
;
552 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
554 struct sync_cb_data
*cb_data
= private_data
;
555 cb_data
->is_finished
= 1;
556 cb_data
->status
= status
;
559 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
564 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, uint64_t length
)
566 struct sync_cb_data cb_data
;
568 cb_data
.is_finished
= 0;
570 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
571 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
575 wait_for_nfs_reply(nfs
, &cb_data
);
577 return cb_data
.status
;
587 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
589 struct sync_cb_data
*cb_data
= private_data
;
590 cb_data
->is_finished
= 1;
591 cb_data
->status
= status
;
594 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
599 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
601 struct sync_cb_data cb_data
;
603 cb_data
.is_finished
= 0;
605 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
606 nfs_set_error(nfs
, "nfs_mkdir_async failed");
610 wait_for_nfs_reply(nfs
, &cb_data
);
612 return cb_data
.status
;
622 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
624 struct sync_cb_data
*cb_data
= private_data
;
625 cb_data
->is_finished
= 1;
626 cb_data
->status
= status
;
629 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
634 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
636 struct sync_cb_data cb_data
;
638 cb_data
.is_finished
= 0;
640 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
641 nfs_set_error(nfs
, "nfs_rmdir_async failed");
645 wait_for_nfs_reply(nfs
, &cb_data
);
647 return cb_data
.status
;
655 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
657 struct sync_cb_data
*cb_data
= private_data
;
658 struct nfsfh
*fh
, **nfsfh
;
660 cb_data
->is_finished
= 1;
661 cb_data
->status
= status
;
664 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
669 nfsfh
= cb_data
->return_data
;
673 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
675 struct sync_cb_data cb_data
;
677 cb_data
.is_finished
= 0;
678 cb_data
.return_data
= nfsfh
;
680 if (nfs_creat_async(nfs
, path
, mode
, creat_cb
, &cb_data
) != 0) {
681 nfs_set_error(nfs
, "nfs_creat_async failed");
685 wait_for_nfs_reply(nfs
, &cb_data
);
687 return cb_data
.status
;
693 static void mknod_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
, "mknod call failed with \"%s\"", (char *)data
);
706 int nfs_mknod(struct nfs_context
*nfs
, const char *path
, int mode
, int dev
)
708 struct sync_cb_data cb_data
;
710 cb_data
.is_finished
= 0;
712 if (nfs_mknod_async(nfs
, path
, mode
, dev
, mknod_cb
, &cb_data
) != 0) {
713 nfs_set_error(nfs
, "nfs_creat_async failed");
717 wait_for_nfs_reply(nfs
, &cb_data
);
719 return cb_data
.status
;
726 static void unlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
728 struct sync_cb_data
*cb_data
= private_data
;
730 cb_data
->is_finished
= 1;
731 cb_data
->status
= status
;
734 nfs_set_error(nfs
, "unlink call failed with \"%s\"", (char *)data
);
739 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
741 struct sync_cb_data cb_data
;
743 cb_data
.is_finished
= 0;
745 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
746 nfs_set_error(nfs
, "nfs_unlink_async failed");
750 wait_for_nfs_reply(nfs
, &cb_data
);
752 return cb_data
.status
;
760 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
762 struct sync_cb_data
*cb_data
= private_data
;
763 struct nfsdir
*dir
, **nfsdir
;
765 cb_data
->is_finished
= 1;
766 cb_data
->status
= status
;
769 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
774 nfsdir
= cb_data
->return_data
;
778 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
780 struct sync_cb_data cb_data
;
782 cb_data
.is_finished
= 0;
783 cb_data
.return_data
= nfsdir
;
785 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
786 nfs_set_error(nfs
, "nfs_opendir_async failed");
790 wait_for_nfs_reply(nfs
, &cb_data
);
792 return cb_data
.status
;
799 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
801 struct sync_cb_data
*cb_data
= private_data
;
803 cb_data
->is_finished
= 1;
804 cb_data
->status
= status
;
807 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
811 if (cb_data
->return_data
!= NULL
) {
812 memcpy(cb_data
->return_data
, data
, sizeof(uint64_t));
816 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, int whence
, uint64_t *current_offset
)
818 struct sync_cb_data cb_data
;
820 cb_data
.is_finished
= 0;
821 cb_data
.return_data
= current_offset
;
823 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
824 nfs_set_error(nfs
, "nfs_lseek_async failed");
828 wait_for_nfs_reply(nfs
, &cb_data
);
830 return cb_data
.status
;
838 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
840 struct sync_cb_data
*cb_data
= private_data
;
842 cb_data
->is_finished
= 1;
843 cb_data
->status
= status
;
846 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
850 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
853 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
855 struct sync_cb_data cb_data
;
857 cb_data
.is_finished
= 0;
858 cb_data
.return_data
= svfs
;
860 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
861 nfs_set_error(nfs
, "nfs_statvfs_async failed");
865 wait_for_nfs_reply(nfs
, &cb_data
);
867 return cb_data
.status
;
877 static void readlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
879 struct sync_cb_data
*cb_data
= private_data
;
881 cb_data
->is_finished
= 1;
882 cb_data
->status
= status
;
885 nfs_set_error(nfs
, "readlink call failed with \"%s\"", (char *)data
);
889 if (strlen(data
) > (size_t)cb_data
->return_int
) {
890 nfs_set_error(nfs
, "Too small buffer for readlink");
891 cb_data
->status
= -ENAMETOOLONG
;
895 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
898 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
900 struct sync_cb_data cb_data
;
902 cb_data
.is_finished
= 0;
903 cb_data
.return_data
= buf
;
904 cb_data
.return_int
= bufsize
;
906 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
907 nfs_set_error(nfs
, "nfs_readlink_async failed");
911 wait_for_nfs_reply(nfs
, &cb_data
);
913 return cb_data
.status
;
921 static void chmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
923 struct sync_cb_data
*cb_data
= private_data
;
925 cb_data
->is_finished
= 1;
926 cb_data
->status
= status
;
929 nfs_set_error(nfs
, "chmod call failed with \"%s\"", (char *)data
);
934 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
936 struct sync_cb_data cb_data
;
938 cb_data
.is_finished
= 0;
940 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
941 nfs_set_error(nfs
, "nfs_chmod_async failed");
945 wait_for_nfs_reply(nfs
, &cb_data
);
947 return cb_data
.status
;
956 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
958 struct sync_cb_data
*cb_data
= private_data
;
960 cb_data
->is_finished
= 1;
961 cb_data
->status
= status
;
964 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
969 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
971 struct sync_cb_data cb_data
;
973 cb_data
.is_finished
= 0;
975 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
976 nfs_set_error(nfs
, "nfs_fchmod_async failed");
980 wait_for_nfs_reply(nfs
, &cb_data
);
982 return cb_data
.status
;
991 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
993 struct sync_cb_data
*cb_data
= private_data
;
995 cb_data
->is_finished
= 1;
996 cb_data
->status
= status
;
999 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
1004 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
1006 struct sync_cb_data cb_data
;
1008 cb_data
.is_finished
= 0;
1010 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
1011 nfs_set_error(nfs
, "nfs_chown_async failed");
1015 wait_for_nfs_reply(nfs
, &cb_data
);
1017 return cb_data
.status
;
1023 static void fchown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1025 struct sync_cb_data
*cb_data
= private_data
;
1027 cb_data
->is_finished
= 1;
1028 cb_data
->status
= status
;
1031 nfs_set_error(nfs
, "fchown call failed with \"%s\"", (char *)data
);
1036 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
1038 struct sync_cb_data cb_data
;
1040 cb_data
.is_finished
= 0;
1042 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
1043 nfs_set_error(nfs
, "nfs_fchown_async failed");
1047 wait_for_nfs_reply(nfs
, &cb_data
);
1049 return cb_data
.status
;
1057 static void utimes_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1059 struct sync_cb_data
*cb_data
= private_data
;
1061 cb_data
->is_finished
= 1;
1062 cb_data
->status
= status
;
1065 nfs_set_error(nfs
, "utimes call failed with \"%s\"", (char *)data
);
1070 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
1072 struct sync_cb_data cb_data
;
1074 cb_data
.is_finished
= 0;
1076 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
1077 nfs_set_error(nfs
, "nfs_utimes_async failed");
1081 wait_for_nfs_reply(nfs
, &cb_data
);
1083 return cb_data
.status
;
1091 static void utime_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1093 struct sync_cb_data
*cb_data
= private_data
;
1095 cb_data
->is_finished
= 1;
1096 cb_data
->status
= status
;
1099 nfs_set_error(nfs
, "utime call failed with \"%s\"", (char *)data
);
1104 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
1106 struct sync_cb_data cb_data
;
1108 cb_data
.is_finished
= 0;
1110 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
1111 nfs_set_error(nfs
, "nfs_utimes_async failed");
1115 wait_for_nfs_reply(nfs
, &cb_data
);
1117 return cb_data
.status
;
1126 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1128 struct sync_cb_data
*cb_data
= private_data
;
1130 cb_data
->is_finished
= 1;
1131 cb_data
->status
= status
;
1134 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
1139 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
1141 struct sync_cb_data cb_data
;
1143 cb_data
.is_finished
= 0;
1145 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
1146 nfs_set_error(nfs
, "nfs_access_async failed");
1150 wait_for_nfs_reply(nfs
, &cb_data
);
1152 return cb_data
.status
;
1160 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1162 struct sync_cb_data
*cb_data
= private_data
;
1164 cb_data
->is_finished
= 1;
1165 cb_data
->status
= status
;
1168 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
1173 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1175 struct sync_cb_data cb_data
;
1177 cb_data
.is_finished
= 0;
1179 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
1180 nfs_set_error(nfs
, "nfs_symlink_async failed");
1184 wait_for_nfs_reply(nfs
, &cb_data
);
1186 return cb_data
.status
;
1194 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1196 struct sync_cb_data
*cb_data
= private_data
;
1198 cb_data
->is_finished
= 1;
1199 cb_data
->status
= status
;
1202 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1207 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1209 struct sync_cb_data cb_data
;
1211 cb_data
.is_finished
= 0;
1213 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1214 nfs_set_error(nfs
, "nfs_rename_async failed");
1218 wait_for_nfs_reply(nfs
, &cb_data
);
1220 return cb_data
.status
;
1228 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1230 struct sync_cb_data
*cb_data
= private_data
;
1232 cb_data
->is_finished
= 1;
1233 cb_data
->status
= status
;
1236 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1241 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1243 struct sync_cb_data cb_data
;
1245 cb_data
.is_finished
= 0;
1247 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1248 nfs_set_error(nfs
, "nfs_link_async failed");
1252 wait_for_nfs_reply(nfs
, &cb_data
);
1254 return cb_data
.status
;
1257 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1259 struct sync_cb_data
*cb_data
= private_data
;
1262 assert(mount_context
->magic
== RPC_CONTEXT_MAGIC
);
1264 cb_data
->is_finished
= 1;
1265 cb_data
->status
= status
;
1266 cb_data
->return_data
= NULL
;
1269 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1273 export
= *(exports
*)data
;
1274 while (export
!= NULL
) {
1277 new_export
= malloc(sizeof(*new_export
));
1278 memset(new_export
, 0, sizeof(*new_export
));
1279 new_export
->ex_dir
= strdup(export
->ex_dir
);
1280 new_export
->ex_next
= cb_data
->return_data
;
1282 cb_data
->return_data
= new_export
;
1284 export
= export
->ex_next
;
1288 struct exportnode
*mount_getexports(const char *server
)
1290 struct sync_cb_data cb_data
;
1291 struct rpc_context
*rpc
;
1294 cb_data
.is_finished
= 0;
1295 cb_data
.return_data
= NULL
;
1297 rpc
= rpc_init_context();
1298 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1299 rpc_destroy_context(rpc
);
1303 wait_for_reply(rpc
, &cb_data
);
1304 rpc_destroy_context(rpc
);
1306 return cb_data
.return_data
;
1309 void mount_free_export_list(struct exportnode
*exports
)
1311 struct exportnode
*tmp
;
1313 while ((tmp
= exports
)) {
1314 exports
= exports
->ex_next
;
1322 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1324 while (srv
!= NULL
) {
1325 struct nfs_server_list
*next
= srv
->next
;
1333 struct nfs_list_data
{
1335 struct nfs_server_list
*srvrs
;
1338 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1340 struct nfs_list_data
*srv_data
= private_data
;
1341 struct sockaddr
*sin
;
1343 struct nfs_server_list
*srvr
;
1345 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1347 if (status
== RPC_STATUS_CANCEL
) {
1351 srv_data
->status
= -1;
1355 sin
= rpc_get_recv_sockaddr(rpc
);
1357 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1358 srv_data
->status
= -1;
1362 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1363 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1364 srv_data
->status
= -1;
1368 /* check for dupes */
1369 for (srvr
= srv_data
->srvrs
; srvr
; srvr
= srvr
->next
) {
1370 if (!strcmp(hostdd
, srvr
->addr
)) {
1375 srvr
= malloc(sizeof(struct nfs_server_list
));
1377 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1378 srv_data
->status
= -1;
1382 srvr
->addr
= strdup(hostdd
);
1383 if (srvr
->addr
== NULL
) {
1384 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1386 srv_data
->status
= -1;
1390 srvr
->next
= srv_data
->srvrs
;
1391 srv_data
->srvrs
= srvr
;
1396 static int send_nfsd_probes(struct rpc_context
*rpc
, INTERFACE_INFO
*InterfaceList
, int numIfs
, struct nfs_list_data
*data
)
1400 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1402 for(i
= 0; i
< numIfs
; i
++)
1406 unsigned long nFlags
= 0;
1408 pAddress
= (SOCKADDR
*) & (InterfaceList
[i
].iiBroadcastAddress
);
1410 if(pAddress
->sa_family
!= AF_INET
)
1413 nFlags
= InterfaceList
[i
].iiFlags
;
1415 if (!(nFlags
& IFF_UP
))
1420 if (nFlags
& IFF_LOOPBACK
)
1425 if (!(nFlags
& IFF_BROADCAST
))
1430 if (getnameinfo(pAddress
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0)
1435 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0)
1440 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0)
1448 struct nfs_server_list
*nfs_find_local_servers(void)
1450 struct rpc_context
*rpc
;
1451 struct nfs_list_data data
= {0, NULL
};
1452 struct timeval tv_start
, tv_current
;
1455 INTERFACE_INFO InterfaceList
[20];
1456 unsigned long nBytesReturned
;
1457 int nNumInterfaces
= 0;
1459 rpc
= rpc_init_udp_context();
1465 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0)
1467 rpc_destroy_context(rpc
);
1471 if (WSAIoctl(rpc_get_fd(rpc
), SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
, sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
1476 nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
1478 for (loop
=0; loop
<3; loop
++)
1480 if (send_nfsd_probes(rpc
, InterfaceList
, nNumInterfaces
, &data
) != 0)
1482 rpc_destroy_context(rpc
);
1486 win32_gettimeofday(&tv_start
, NULL
);
1491 pfd
.fd
= rpc_get_fd(rpc
);
1492 pfd
.events
= rpc_which_events(rpc
);
1494 win32_gettimeofday(&tv_current
, NULL
);
1496 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1497 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1499 if (poll(&pfd
, 1, mpt
) < 0)
1501 free_nfs_srvr_list(data
.srvrs
);
1502 rpc_destroy_context(rpc
);
1505 if (pfd
.revents
== 0)
1510 if (rpc_service(rpc
, pfd
.revents
) < 0)
1517 rpc_destroy_context(rpc
);
1519 if (data
.status
!= 0)
1521 free_nfs_srvr_list(data
.srvrs
);
1528 static int send_nfsd_probes(struct rpc_context
*rpc
, struct ifconf
*ifc
, struct nfs_list_data
*data
)
1532 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1534 for (ptr
=(char *)(ifc
->ifc_buf
); ptr
< (char *)(ifc
->ifc_buf
) + ifc
->ifc_len
; ) {
1538 ifr
= (struct ifreq
*)ptr
;
1539 #ifdef HAVE_SOCKADDR_LEN
1540 if (ifr
->ifr_addr
.sa_len
> sizeof(struct sockaddr
)) {
1541 ptr
+= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
1543 ptr
+= sizeof(ifr
->ifr_name
) + sizeof(struct sockaddr
);
1546 ptr
+= sizeof(struct ifreq
);
1549 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) {
1552 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, ifr
) < 0) {
1555 if (!(ifr
->ifr_flags
& IFF_UP
)) {
1558 if (ifr
->ifr_flags
& IFF_LOOPBACK
) {
1561 if (!(ifr
->ifr_flags
& IFF_BROADCAST
)) {
1564 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, ifr
) < 0) {
1567 if (getnameinfo(&ifr
->ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1570 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1574 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0) {
1582 struct nfs_server_list
*nfs_find_local_servers(void)
1584 struct rpc_context
*rpc
;
1585 struct nfs_list_data data
= {0, NULL
};
1586 struct timeval tv_start
, tv_current
;
1591 rpc
= rpc_init_udp_context();
1596 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1597 rpc_destroy_context(rpc
);
1602 /* get list of all interfaces */
1603 size
= sizeof(struct ifreq
);
1607 while(ifc
.ifc_len
> (size
- sizeof(struct ifreq
))) {
1612 ifc
.ifc_buf
= malloc(size
);
1613 memset(ifc
.ifc_buf
, 0, size
);
1614 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1615 rpc_destroy_context(rpc
);
1621 for (loop
=0; loop
<3; loop
++) {
1622 if (send_nfsd_probes(rpc
, &ifc
, &data
) != 0) {
1623 rpc_destroy_context(rpc
);
1628 gettimeofday(&tv_start
, NULL
);
1632 pfd
.fd
= rpc_get_fd(rpc
);
1633 pfd
.events
= rpc_which_events(rpc
);
1635 gettimeofday(&tv_current
, NULL
);
1637 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1638 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1640 if (poll(&pfd
, 1, mpt
) < 0) {
1641 free_nfs_srvr_list(data
.srvrs
);
1642 rpc_destroy_context(rpc
);
1645 if (pfd
.revents
== 0) {
1649 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1656 rpc_destroy_context(rpc
);
1658 if (data
.status
!= 0) {
1659 free_nfs_srvr_list(data
.srvrs
);