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"
33 #include <sys/socket.h>
38 #define statvfs statfs
45 #ifdef HAVE_SYS_STATVFS_H
46 #include <sys/statvfs.h>
49 #ifdef HAVE_SYS_IOCTL_H
50 #include <sys/ioctl.h>
65 #include <sys/types.h>
68 #include <netinet/in.h>
71 #ifdef HAVE_SYS_SOCKIO_H
72 #include <sys/sockio.h>
75 #include "libnfs-zdr.h"
77 #include "libnfs-raw.h"
78 #include "libnfs-raw-mount.h"
79 #include "libnfs-raw-nfs.h"
80 #include "libnfs-private.h"
91 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
95 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
97 while (!cb_data
->is_finished
) {
99 pfd
.fd
= rpc_get_fd(rpc
);
100 pfd
.events
= rpc_which_events(rpc
);
101 if (poll(&pfd
, 1, -1) < 0) {
102 rpc_set_error(rpc
, "Poll failed");
103 cb_data
->status
= -EIO
;
106 if (rpc_service(rpc
, pfd
.revents
) < 0) {
107 rpc_set_error(rpc
, "rpc_service failed");
108 cb_data
->status
= -EIO
;
111 if (rpc_get_fd(rpc
) == -1) {
112 rpc_set_error(rpc
, "Socket closed\n");
118 static void wait_for_nfs_reply(struct nfs_context
*nfs
, struct sync_cb_data
*cb_data
)
122 while (!cb_data
->is_finished
) {
124 pfd
.fd
= nfs_get_fd(nfs
);
125 pfd
.events
= nfs_which_events(nfs
);
126 if (poll(&pfd
, 1, -1) < 0) {
127 nfs_set_error(nfs
, "Poll failed");
128 cb_data
->status
= -EIO
;
131 if (nfs_service(nfs
, pfd
.revents
) < 0) {
132 nfs_set_error(nfs
, "nfs_service failed");
133 cb_data
->status
= -EIO
;
145 * connect to the server and mount the export
147 static void mount_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
149 struct sync_cb_data
*cb_data
= private_data
;
151 cb_data
->is_finished
= 1;
152 cb_data
->status
= status
;
155 nfs_set_error(nfs
, "mount/mnt call failed with \"%s\"", (char *)data
);
160 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
162 struct sync_cb_data cb_data
;
163 struct rpc_context
*rpc
= nfs_get_rpc_context(nfs
);
165 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
167 cb_data
.is_finished
= 0;
169 if (nfs_mount_async(nfs
, server
, export
, mount_cb
, &cb_data
) != 0) {
170 nfs_set_error(nfs
, "nfs_mount_async failed");
174 wait_for_nfs_reply(nfs
, &cb_data
);
176 /* Dont want any more callbacks even if the socket is closed */
177 rpc
->connect_cb
= NULL
;
179 return cb_data
.status
;
186 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
188 struct sync_cb_data
*cb_data
= private_data
;
190 cb_data
->is_finished
= 1;
191 cb_data
->status
= status
;
194 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
198 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
201 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
203 struct sync_cb_data cb_data
;
205 cb_data
.is_finished
= 0;
206 cb_data
.return_data
= st
;
208 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
209 nfs_set_error(nfs
, "nfs_stat_async failed");
213 wait_for_nfs_reply(nfs
, &cb_data
);
215 return cb_data
.status
;
224 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
226 struct sync_cb_data
*cb_data
= private_data
;
227 struct nfsfh
*fh
, **nfsfh
;
229 cb_data
->is_finished
= 1;
230 cb_data
->status
= status
;
233 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
238 nfsfh
= cb_data
->return_data
;
242 int nfs_open(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
244 struct sync_cb_data cb_data
;
246 cb_data
.is_finished
= 0;
247 cb_data
.return_data
= nfsfh
;
249 if (nfs_open_async(nfs
, path
, mode
, open_cb
, &cb_data
) != 0) {
250 nfs_set_error(nfs
, "nfs_open_async failed");
254 wait_for_nfs_reply(nfs
, &cb_data
);
256 return cb_data
.status
;
265 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
267 struct sync_cb_data
*cb_data
= private_data
;
269 cb_data
->is_finished
= 1;
270 cb_data
->status
= status
;
273 nfs_set_error(nfs
, "pread call failed with \"%s\"", (char *)data
);
277 buffer
= cb_data
->return_data
;
278 memcpy(buffer
, (char *)data
, status
);
281 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buffer
)
283 struct sync_cb_data cb_data
;
285 cb_data
.is_finished
= 0;
286 cb_data
.return_data
= buffer
;
288 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
289 nfs_set_error(nfs
, "nfs_pread_async failed");
293 wait_for_nfs_reply(nfs
, &cb_data
);
295 return cb_data
.status
;
301 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buffer
)
303 return nfs_pread(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buffer
);
309 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
311 struct sync_cb_data
*cb_data
= private_data
;
312 cb_data
->is_finished
= 1;
313 cb_data
->status
= status
;
316 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
321 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
323 struct sync_cb_data cb_data
;
325 cb_data
.is_finished
= 0;
327 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
328 nfs_set_error(nfs
, "nfs_close_async failed");
332 wait_for_nfs_reply(nfs
, &cb_data
);
334 return cb_data
.status
;
343 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
345 struct sync_cb_data cb_data
;
347 cb_data
.is_finished
= 0;
348 cb_data
.return_data
= st
;
350 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
351 nfs_set_error(nfs
, "nfs_fstat_async failed");
355 wait_for_nfs_reply(nfs
, &cb_data
);
357 return cb_data
.status
;
364 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
366 struct sync_cb_data
*cb_data
= private_data
;
367 cb_data
->is_finished
= 1;
368 cb_data
->status
= status
;
371 nfs_set_error(nfs
, "pwrite call failed with \"%s\"", (char *)data
);
376 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buf
)
378 struct sync_cb_data cb_data
;
380 cb_data
.is_finished
= 0;
382 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
383 nfs_set_error(nfs
, "nfs_pwrite_async failed");
387 wait_for_nfs_reply(nfs
, &cb_data
);
389 return cb_data
.status
;
395 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buf
)
397 return nfs_pwrite(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buf
);
404 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
406 struct sync_cb_data
*cb_data
= private_data
;
407 cb_data
->is_finished
= 1;
408 cb_data
->status
= status
;
411 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
416 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
418 struct sync_cb_data cb_data
;
420 cb_data
.is_finished
= 0;
422 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
423 nfs_set_error(nfs
, "nfs_fsync_async failed");
427 wait_for_nfs_reply(nfs
, &cb_data
);
429 return cb_data
.status
;
438 static void ftruncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
440 struct sync_cb_data
*cb_data
= private_data
;
441 cb_data
->is_finished
= 1;
442 cb_data
->status
= status
;
445 nfs_set_error(nfs
, "ftruncate call failed with \"%s\"", (char *)data
);
450 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t length
)
452 struct sync_cb_data cb_data
;
454 cb_data
.is_finished
= 0;
456 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_cb
, &cb_data
) != 0) {
457 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
461 wait_for_nfs_reply(nfs
, &cb_data
);
463 return cb_data
.status
;
471 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
473 struct sync_cb_data
*cb_data
= private_data
;
474 cb_data
->is_finished
= 1;
475 cb_data
->status
= status
;
478 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
483 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, uint64_t length
)
485 struct sync_cb_data cb_data
;
487 cb_data
.is_finished
= 0;
489 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
490 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
494 wait_for_nfs_reply(nfs
, &cb_data
);
496 return cb_data
.status
;
506 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
508 struct sync_cb_data
*cb_data
= private_data
;
509 cb_data
->is_finished
= 1;
510 cb_data
->status
= status
;
513 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
518 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
520 struct sync_cb_data cb_data
;
522 cb_data
.is_finished
= 0;
524 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
525 nfs_set_error(nfs
, "nfs_mkdir_async failed");
529 wait_for_nfs_reply(nfs
, &cb_data
);
531 return cb_data
.status
;
541 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
543 struct sync_cb_data
*cb_data
= private_data
;
544 cb_data
->is_finished
= 1;
545 cb_data
->status
= status
;
548 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
553 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
555 struct sync_cb_data cb_data
;
557 cb_data
.is_finished
= 0;
559 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
560 nfs_set_error(nfs
, "nfs_rmdir_async failed");
564 wait_for_nfs_reply(nfs
, &cb_data
);
566 return cb_data
.status
;
574 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
576 struct sync_cb_data
*cb_data
= private_data
;
577 struct nfsfh
*fh
, **nfsfh
;
579 cb_data
->is_finished
= 1;
580 cb_data
->status
= status
;
583 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
588 nfsfh
= cb_data
->return_data
;
592 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
594 struct sync_cb_data cb_data
;
596 cb_data
.is_finished
= 0;
597 cb_data
.return_data
= nfsfh
;
599 if (nfs_creat_async(nfs
, path
, mode
, creat_cb
, &cb_data
) != 0) {
600 nfs_set_error(nfs
, "nfs_creat_async failed");
604 wait_for_nfs_reply(nfs
, &cb_data
);
606 return cb_data
.status
;
612 static void mknod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
614 struct sync_cb_data
*cb_data
= private_data
;
616 cb_data
->is_finished
= 1;
617 cb_data
->status
= status
;
620 nfs_set_error(nfs
, "mknod call failed with \"%s\"", (char *)data
);
625 int nfs_mknod(struct nfs_context
*nfs
, const char *path
, int mode
, int dev
)
627 struct sync_cb_data cb_data
;
629 cb_data
.is_finished
= 0;
631 if (nfs_mknod_async(nfs
, path
, mode
, dev
, mknod_cb
, &cb_data
) != 0) {
632 nfs_set_error(nfs
, "nfs_creat_async failed");
636 wait_for_nfs_reply(nfs
, &cb_data
);
638 return cb_data
.status
;
645 static void unlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
647 struct sync_cb_data
*cb_data
= private_data
;
649 cb_data
->is_finished
= 1;
650 cb_data
->status
= status
;
653 nfs_set_error(nfs
, "unlink call failed with \"%s\"", (char *)data
);
658 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
660 struct sync_cb_data cb_data
;
662 cb_data
.is_finished
= 0;
664 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
665 nfs_set_error(nfs
, "nfs_unlink_async failed");
669 wait_for_nfs_reply(nfs
, &cb_data
);
671 return cb_data
.status
;
679 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
681 struct sync_cb_data
*cb_data
= private_data
;
682 struct nfsdir
*dir
, **nfsdir
;
684 cb_data
->is_finished
= 1;
685 cb_data
->status
= status
;
688 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
693 nfsdir
= cb_data
->return_data
;
697 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
699 struct sync_cb_data cb_data
;
701 cb_data
.is_finished
= 0;
702 cb_data
.return_data
= nfsdir
;
704 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
705 nfs_set_error(nfs
, "nfs_opendir_async failed");
709 wait_for_nfs_reply(nfs
, &cb_data
);
711 return cb_data
.status
;
718 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
720 struct sync_cb_data
*cb_data
= private_data
;
722 cb_data
->is_finished
= 1;
723 cb_data
->status
= status
;
726 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
730 if (cb_data
->return_data
!= NULL
) {
731 memcpy(cb_data
->return_data
, data
, sizeof(uint64_t));
735 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, int whence
, uint64_t *current_offset
)
737 struct sync_cb_data cb_data
;
739 cb_data
.is_finished
= 0;
740 cb_data
.return_data
= current_offset
;
742 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
743 nfs_set_error(nfs
, "nfs_lseek_async failed");
747 wait_for_nfs_reply(nfs
, &cb_data
);
749 return cb_data
.status
;
757 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
759 struct sync_cb_data
*cb_data
= private_data
;
761 cb_data
->is_finished
= 1;
762 cb_data
->status
= status
;
765 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
769 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
772 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
774 struct sync_cb_data cb_data
;
776 cb_data
.is_finished
= 0;
777 cb_data
.return_data
= svfs
;
779 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
780 nfs_set_error(nfs
, "nfs_statvfs_async failed");
784 wait_for_nfs_reply(nfs
, &cb_data
);
786 return cb_data
.status
;
796 static void readlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
798 struct sync_cb_data
*cb_data
= private_data
;
800 cb_data
->is_finished
= 1;
801 cb_data
->status
= status
;
804 nfs_set_error(nfs
, "readlink call failed with \"%s\"", (char *)data
);
808 if (strlen(data
) > (size_t)cb_data
->return_int
) {
809 nfs_set_error(nfs
, "Too small buffer for readlink");
810 cb_data
->status
= -ENAMETOOLONG
;
814 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
817 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
819 struct sync_cb_data cb_data
;
821 cb_data
.is_finished
= 0;
822 cb_data
.return_data
= buf
;
823 cb_data
.return_int
= bufsize
;
825 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
826 nfs_set_error(nfs
, "nfs_readlink_async failed");
830 wait_for_nfs_reply(nfs
, &cb_data
);
832 return cb_data
.status
;
840 static void chmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
842 struct sync_cb_data
*cb_data
= private_data
;
844 cb_data
->is_finished
= 1;
845 cb_data
->status
= status
;
848 nfs_set_error(nfs
, "chmod call failed with \"%s\"", (char *)data
);
853 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
855 struct sync_cb_data cb_data
;
857 cb_data
.is_finished
= 0;
859 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
860 nfs_set_error(nfs
, "nfs_chmod_async failed");
864 wait_for_nfs_reply(nfs
, &cb_data
);
866 return cb_data
.status
;
875 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
877 struct sync_cb_data
*cb_data
= private_data
;
879 cb_data
->is_finished
= 1;
880 cb_data
->status
= status
;
883 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
888 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
890 struct sync_cb_data cb_data
;
892 cb_data
.is_finished
= 0;
894 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
895 nfs_set_error(nfs
, "nfs_fchmod_async failed");
899 wait_for_nfs_reply(nfs
, &cb_data
);
901 return cb_data
.status
;
910 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
912 struct sync_cb_data
*cb_data
= private_data
;
914 cb_data
->is_finished
= 1;
915 cb_data
->status
= status
;
918 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
923 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
925 struct sync_cb_data cb_data
;
927 cb_data
.is_finished
= 0;
929 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
930 nfs_set_error(nfs
, "nfs_chown_async failed");
934 wait_for_nfs_reply(nfs
, &cb_data
);
936 return cb_data
.status
;
942 static void fchown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
944 struct sync_cb_data
*cb_data
= private_data
;
946 cb_data
->is_finished
= 1;
947 cb_data
->status
= status
;
950 nfs_set_error(nfs
, "fchown call failed with \"%s\"", (char *)data
);
955 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
957 struct sync_cb_data cb_data
;
959 cb_data
.is_finished
= 0;
961 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
962 nfs_set_error(nfs
, "nfs_fchown_async failed");
966 wait_for_nfs_reply(nfs
, &cb_data
);
968 return cb_data
.status
;
976 static void utimes_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
978 struct sync_cb_data
*cb_data
= private_data
;
980 cb_data
->is_finished
= 1;
981 cb_data
->status
= status
;
984 nfs_set_error(nfs
, "utimes call failed with \"%s\"", (char *)data
);
989 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
991 struct sync_cb_data cb_data
;
993 cb_data
.is_finished
= 0;
995 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
996 nfs_set_error(nfs
, "nfs_utimes_async failed");
1000 wait_for_nfs_reply(nfs
, &cb_data
);
1002 return cb_data
.status
;
1010 static void utime_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1012 struct sync_cb_data
*cb_data
= private_data
;
1014 cb_data
->is_finished
= 1;
1015 cb_data
->status
= status
;
1018 nfs_set_error(nfs
, "utime call failed with \"%s\"", (char *)data
);
1023 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
1025 struct sync_cb_data cb_data
;
1027 cb_data
.is_finished
= 0;
1029 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
1030 nfs_set_error(nfs
, "nfs_utimes_async failed");
1034 wait_for_nfs_reply(nfs
, &cb_data
);
1036 return cb_data
.status
;
1045 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1047 struct sync_cb_data
*cb_data
= private_data
;
1049 cb_data
->is_finished
= 1;
1050 cb_data
->status
= status
;
1053 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
1058 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
1060 struct sync_cb_data cb_data
;
1062 cb_data
.is_finished
= 0;
1064 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
1065 nfs_set_error(nfs
, "nfs_access_async failed");
1069 wait_for_nfs_reply(nfs
, &cb_data
);
1071 return cb_data
.status
;
1079 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1081 struct sync_cb_data
*cb_data
= private_data
;
1083 cb_data
->is_finished
= 1;
1084 cb_data
->status
= status
;
1087 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
1092 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1094 struct sync_cb_data cb_data
;
1096 cb_data
.is_finished
= 0;
1098 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
1099 nfs_set_error(nfs
, "nfs_symlink_async failed");
1103 wait_for_nfs_reply(nfs
, &cb_data
);
1105 return cb_data
.status
;
1113 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1115 struct sync_cb_data
*cb_data
= private_data
;
1117 cb_data
->is_finished
= 1;
1118 cb_data
->status
= status
;
1121 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1126 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1128 struct sync_cb_data cb_data
;
1130 cb_data
.is_finished
= 0;
1132 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1133 nfs_set_error(nfs
, "nfs_rename_async failed");
1137 wait_for_nfs_reply(nfs
, &cb_data
);
1139 return cb_data
.status
;
1147 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1149 struct sync_cb_data
*cb_data
= private_data
;
1151 cb_data
->is_finished
= 1;
1152 cb_data
->status
= status
;
1155 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1160 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1162 struct sync_cb_data cb_data
;
1164 cb_data
.is_finished
= 0;
1166 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1167 nfs_set_error(nfs
, "nfs_link_async failed");
1171 wait_for_nfs_reply(nfs
, &cb_data
);
1173 return cb_data
.status
;
1176 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1178 struct sync_cb_data
*cb_data
= private_data
;
1181 assert(mount_context
->magic
== RPC_CONTEXT_MAGIC
);
1183 cb_data
->is_finished
= 1;
1184 cb_data
->status
= status
;
1185 cb_data
->return_data
= NULL
;
1188 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1192 export
= *(exports
*)data
;
1193 while (export
!= NULL
) {
1196 new_export
= malloc(sizeof(*new_export
));
1197 memset(new_export
, 0, sizeof(*new_export
));
1198 new_export
->ex_dir
= strdup(export
->ex_dir
);
1199 new_export
->ex_next
= cb_data
->return_data
;
1201 cb_data
->return_data
= new_export
;
1203 export
= export
->ex_next
;
1207 struct exportnode
*mount_getexports(const char *server
)
1209 struct sync_cb_data cb_data
;
1210 struct rpc_context
*rpc
;
1213 cb_data
.is_finished
= 0;
1214 cb_data
.return_data
= NULL
;
1216 rpc
= rpc_init_context();
1217 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1218 rpc_destroy_context(rpc
);
1222 wait_for_reply(rpc
, &cb_data
);
1223 rpc_destroy_context(rpc
);
1225 return cb_data
.return_data
;
1228 void mount_free_export_list(struct exportnode
*exports
)
1230 struct exportnode
*tmp
;
1232 while ((tmp
= exports
)) {
1233 exports
= exports
->ex_next
;
1241 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1243 while (srv
!= NULL
) {
1244 struct nfs_server_list
*next
= srv
->next
;
1252 struct nfs_list_data
{
1254 struct nfs_server_list
*srvrs
;
1257 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1259 struct nfs_list_data
*srv_data
= private_data
;
1260 struct sockaddr
*sin
;
1262 struct nfs_server_list
*srvr
;
1264 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1266 if (status
== RPC_STATUS_CANCEL
) {
1270 srv_data
->status
= -1;
1274 sin
= rpc_get_recv_sockaddr(rpc
);
1276 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1277 srv_data
->status
= -1;
1281 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1282 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1283 srv_data
->status
= -1;
1287 /* check for dupes */
1288 for (srvr
= srv_data
->srvrs
; srvr
; srvr
= srvr
->next
) {
1289 if (!strcmp(hostdd
, srvr
->addr
)) {
1294 srvr
= malloc(sizeof(struct nfs_server_list
));
1296 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1297 srv_data
->status
= -1;
1301 srvr
->addr
= strdup(hostdd
);
1302 if (srvr
->addr
== NULL
) {
1303 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1305 srv_data
->status
= -1;
1309 srvr
->next
= srv_data
->srvrs
;
1310 srv_data
->srvrs
= srvr
;
1315 static int send_nfsd_probes(struct rpc_context
*rpc
, INTERFACE_INFO
*InterfaceList
, int numIfs
, struct nfs_list_data
*data
)
1319 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1321 for(i
= 0; i
< numIfs
; i
++)
1325 unsigned long nFlags
= 0;
1327 pAddress
= (SOCKADDR
*) & (InterfaceList
[i
].iiBroadcastAddress
);
1329 if(pAddress
->sa_family
!= AF_INET
)
1332 nFlags
= InterfaceList
[i
].iiFlags
;
1334 if (!(nFlags
& IFF_UP
))
1339 if (nFlags
& IFF_LOOPBACK
)
1344 if (!(nFlags
& IFF_BROADCAST
))
1349 if (getnameinfo(pAddress
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0)
1354 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0)
1359 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0)
1367 struct nfs_server_list
*nfs_find_local_servers(void)
1369 struct rpc_context
*rpc
;
1370 struct nfs_list_data data
= {0, NULL
};
1371 struct timeval tv_start
, tv_current
;
1374 INTERFACE_INFO InterfaceList
[20];
1375 unsigned long nBytesReturned
;
1376 int nNumInterfaces
= 0;
1378 rpc
= rpc_init_udp_context();
1384 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0)
1386 rpc_destroy_context(rpc
);
1390 if (WSAIoctl(rpc_get_fd(rpc
), SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
, sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
1395 nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
1397 for (loop
=0; loop
<3; loop
++)
1399 if (send_nfsd_probes(rpc
, InterfaceList
, nNumInterfaces
, &data
) != 0)
1401 rpc_destroy_context(rpc
);
1405 win32_gettimeofday(&tv_start
, NULL
);
1410 pfd
.fd
= rpc_get_fd(rpc
);
1411 pfd
.events
= rpc_which_events(rpc
);
1413 win32_gettimeofday(&tv_current
, NULL
);
1415 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1416 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1418 if (poll(&pfd
, 1, mpt
) < 0)
1420 free_nfs_srvr_list(data
.srvrs
);
1421 rpc_destroy_context(rpc
);
1424 if (pfd
.revents
== 0)
1429 if (rpc_service(rpc
, pfd
.revents
) < 0)
1436 rpc_destroy_context(rpc
);
1438 if (data
.status
!= 0)
1440 free_nfs_srvr_list(data
.srvrs
);
1447 static int send_nfsd_probes(struct rpc_context
*rpc
, struct ifconf
*ifc
, struct nfs_list_data
*data
)
1451 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1453 for (ptr
=(char *)(ifc
->ifc_buf
); ptr
< (char *)(ifc
->ifc_buf
) + ifc
->ifc_len
; ) {
1457 ifr
= (struct ifreq
*)ptr
;
1458 #ifdef HAVE_SOCKADDR_LEN
1459 if (ifr
->ifr_addr
.sa_len
> sizeof(struct sockaddr
)) {
1460 ptr
+= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
1462 ptr
+= sizeof(ifr
->ifr_name
) + sizeof(struct sockaddr
);
1465 ptr
+= sizeof(struct ifreq
);
1468 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) {
1471 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, ifr
) < 0) {
1474 if (!(ifr
->ifr_flags
& IFF_UP
)) {
1477 if (ifr
->ifr_flags
& IFF_LOOPBACK
) {
1480 if (!(ifr
->ifr_flags
& IFF_BROADCAST
)) {
1483 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, ifr
) < 0) {
1486 if (getnameinfo(&ifr
->ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1489 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1493 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0) {
1501 struct nfs_server_list
*nfs_find_local_servers(void)
1503 struct rpc_context
*rpc
;
1504 struct nfs_list_data data
= {0, NULL
};
1505 struct timeval tv_start
, tv_current
;
1510 rpc
= rpc_init_udp_context();
1515 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1516 rpc_destroy_context(rpc
);
1521 /* get list of all interfaces */
1522 size
= sizeof(struct ifreq
);
1526 while(ifc
.ifc_len
> (size
- sizeof(struct ifreq
))) {
1531 ifc
.ifc_buf
= malloc(size
);
1532 memset(ifc
.ifc_buf
, 0, size
);
1533 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1534 rpc_destroy_context(rpc
);
1540 for (loop
=0; loop
<3; loop
++) {
1541 if (send_nfsd_probes(rpc
, &ifc
, &data
) != 0) {
1542 rpc_destroy_context(rpc
);
1547 gettimeofday(&tv_start
, NULL
);
1551 pfd
.fd
= rpc_get_fd(rpc
);
1552 pfd
.events
= rpc_which_events(rpc
);
1554 gettimeofday(&tv_current
, NULL
);
1556 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1557 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1559 if (poll(&pfd
, 1, mpt
) < 0) {
1560 free_nfs_srvr_list(data
.srvrs
);
1561 rpc_destroy_context(rpc
);
1564 if (pfd
.revents
== 0) {
1568 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1575 rpc_destroy_context(rpc
);
1577 if (data
.status
!= 0) {
1578 free_nfs_srvr_list(data
.srvrs
);