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>
61 #ifdef HAVE_NETINET_IN_H
62 #include <netinet/in.h>
69 #include <sys/types.h>
74 #ifdef HAVE_SYS_SOCKIO_H
75 #include <sys/sockio.h>
78 #include "libnfs-zdr.h"
80 #include "libnfs-raw.h"
81 #include "libnfs-raw-mount.h"
82 #include "libnfs-raw-nfs.h"
83 #include "libnfs-private.h"
94 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
98 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
100 while (!cb_data
->is_finished
) {
102 pfd
.fd
= rpc_get_fd(rpc
);
103 pfd
.events
= rpc_which_events(rpc
);
104 if (poll(&pfd
, 1, -1) < 0) {
105 rpc_set_error(rpc
, "Poll failed");
106 cb_data
->status
= -EIO
;
109 if (rpc_service(rpc
, pfd
.revents
) < 0) {
110 rpc_set_error(rpc
, "rpc_service failed");
111 cb_data
->status
= -EIO
;
114 if (rpc_get_fd(rpc
) == -1) {
115 rpc_set_error(rpc
, "Socket closed\n");
121 static void wait_for_nfs_reply(struct nfs_context
*nfs
, struct sync_cb_data
*cb_data
)
125 while (!cb_data
->is_finished
) {
127 pfd
.fd
= nfs_get_fd(nfs
);
128 pfd
.events
= nfs_which_events(nfs
);
129 if (poll(&pfd
, 1, -1) < 0) {
130 nfs_set_error(nfs
, "Poll failed");
131 cb_data
->status
= -EIO
;
134 if (nfs_service(nfs
, pfd
.revents
) < 0) {
135 nfs_set_error(nfs
, "nfs_service failed");
136 cb_data
->status
= -EIO
;
148 * connect to the server and mount the export
150 static void mount_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
152 struct sync_cb_data
*cb_data
= private_data
;
154 cb_data
->is_finished
= 1;
155 cb_data
->status
= status
;
158 nfs_set_error(nfs
, "mount/mnt call failed with \"%s\"", (char *)data
);
163 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
165 struct sync_cb_data cb_data
;
166 struct rpc_context
*rpc
= nfs_get_rpc_context(nfs
);
168 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
170 cb_data
.is_finished
= 0;
172 if (nfs_mount_async(nfs
, server
, export
, mount_cb
, &cb_data
) != 0) {
173 nfs_set_error(nfs
, "nfs_mount_async failed");
177 wait_for_nfs_reply(nfs
, &cb_data
);
179 /* Dont want any more callbacks even if the socket is closed */
180 rpc
->connect_cb
= NULL
;
182 return cb_data
.status
;
189 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
191 struct sync_cb_data
*cb_data
= private_data
;
193 cb_data
->is_finished
= 1;
194 cb_data
->status
= status
;
197 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
201 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
204 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
206 struct sync_cb_data cb_data
;
208 cb_data
.is_finished
= 0;
209 cb_data
.return_data
= st
;
211 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
212 nfs_set_error(nfs
, "nfs_stat_async failed");
216 wait_for_nfs_reply(nfs
, &cb_data
);
218 return cb_data
.status
;
227 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
229 struct sync_cb_data
*cb_data
= private_data
;
230 struct nfsfh
*fh
, **nfsfh
;
232 cb_data
->is_finished
= 1;
233 cb_data
->status
= status
;
236 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
241 nfsfh
= cb_data
->return_data
;
245 int nfs_open(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
247 struct sync_cb_data cb_data
;
249 cb_data
.is_finished
= 0;
250 cb_data
.return_data
= nfsfh
;
252 if (nfs_open_async(nfs
, path
, mode
, open_cb
, &cb_data
) != 0) {
253 nfs_set_error(nfs
, "nfs_open_async failed");
257 wait_for_nfs_reply(nfs
, &cb_data
);
259 return cb_data
.status
;
268 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
270 struct sync_cb_data
*cb_data
= private_data
;
272 cb_data
->is_finished
= 1;
273 cb_data
->status
= status
;
276 nfs_set_error(nfs
, "pread call failed with \"%s\"", (char *)data
);
280 buffer
= cb_data
->return_data
;
281 memcpy(buffer
, (char *)data
, status
);
284 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buffer
)
286 struct sync_cb_data cb_data
;
288 cb_data
.is_finished
= 0;
289 cb_data
.return_data
= buffer
;
291 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
292 nfs_set_error(nfs
, "nfs_pread_async failed");
296 wait_for_nfs_reply(nfs
, &cb_data
);
298 return cb_data
.status
;
304 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buffer
)
306 return nfs_pread(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buffer
);
312 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
314 struct sync_cb_data
*cb_data
= private_data
;
315 cb_data
->is_finished
= 1;
316 cb_data
->status
= status
;
319 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
324 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
326 struct sync_cb_data cb_data
;
328 cb_data
.is_finished
= 0;
330 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
331 nfs_set_error(nfs
, "nfs_close_async failed");
335 wait_for_nfs_reply(nfs
, &cb_data
);
337 return cb_data
.status
;
346 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
348 struct sync_cb_data cb_data
;
350 cb_data
.is_finished
= 0;
351 cb_data
.return_data
= st
;
353 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
354 nfs_set_error(nfs
, "nfs_fstat_async failed");
358 wait_for_nfs_reply(nfs
, &cb_data
);
360 return cb_data
.status
;
367 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
369 struct sync_cb_data
*cb_data
= private_data
;
370 cb_data
->is_finished
= 1;
371 cb_data
->status
= status
;
374 nfs_set_error(nfs
, "pwrite call failed with \"%s\"", (char *)data
);
379 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buf
)
381 struct sync_cb_data cb_data
;
383 cb_data
.is_finished
= 0;
385 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
386 nfs_set_error(nfs
, "nfs_pwrite_async failed");
390 wait_for_nfs_reply(nfs
, &cb_data
);
392 return cb_data
.status
;
398 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buf
)
400 return nfs_pwrite(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buf
);
407 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
409 struct sync_cb_data
*cb_data
= private_data
;
410 cb_data
->is_finished
= 1;
411 cb_data
->status
= status
;
414 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
419 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
421 struct sync_cb_data cb_data
;
423 cb_data
.is_finished
= 0;
425 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
426 nfs_set_error(nfs
, "nfs_fsync_async failed");
430 wait_for_nfs_reply(nfs
, &cb_data
);
432 return cb_data
.status
;
441 static void ftruncate_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
, "ftruncate call failed with \"%s\"", (char *)data
);
453 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t length
)
455 struct sync_cb_data cb_data
;
457 cb_data
.is_finished
= 0;
459 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_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
;
474 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
476 struct sync_cb_data
*cb_data
= private_data
;
477 cb_data
->is_finished
= 1;
478 cb_data
->status
= status
;
481 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
486 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, uint64_t length
)
488 struct sync_cb_data cb_data
;
490 cb_data
.is_finished
= 0;
492 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
493 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
497 wait_for_nfs_reply(nfs
, &cb_data
);
499 return cb_data
.status
;
509 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
511 struct sync_cb_data
*cb_data
= private_data
;
512 cb_data
->is_finished
= 1;
513 cb_data
->status
= status
;
516 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
521 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
523 struct sync_cb_data cb_data
;
525 cb_data
.is_finished
= 0;
527 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
528 nfs_set_error(nfs
, "nfs_mkdir_async failed");
532 wait_for_nfs_reply(nfs
, &cb_data
);
534 return cb_data
.status
;
544 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
546 struct sync_cb_data
*cb_data
= private_data
;
547 cb_data
->is_finished
= 1;
548 cb_data
->status
= status
;
551 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
556 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
558 struct sync_cb_data cb_data
;
560 cb_data
.is_finished
= 0;
562 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
563 nfs_set_error(nfs
, "nfs_rmdir_async failed");
567 wait_for_nfs_reply(nfs
, &cb_data
);
569 return cb_data
.status
;
577 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
579 struct sync_cb_data
*cb_data
= private_data
;
580 struct nfsfh
*fh
, **nfsfh
;
582 cb_data
->is_finished
= 1;
583 cb_data
->status
= status
;
586 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
591 nfsfh
= cb_data
->return_data
;
595 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
597 struct sync_cb_data cb_data
;
599 cb_data
.is_finished
= 0;
600 cb_data
.return_data
= nfsfh
;
602 if (nfs_creat_async(nfs
, path
, mode
, creat_cb
, &cb_data
) != 0) {
603 nfs_set_error(nfs
, "nfs_creat_async failed");
607 wait_for_nfs_reply(nfs
, &cb_data
);
609 return cb_data
.status
;
615 static void mknod_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
, "mknod call failed with \"%s\"", (char *)data
);
628 int nfs_mknod(struct nfs_context
*nfs
, const char *path
, int mode
, int dev
)
630 struct sync_cb_data cb_data
;
632 cb_data
.is_finished
= 0;
634 if (nfs_mknod_async(nfs
, path
, mode
, dev
, mknod_cb
, &cb_data
) != 0) {
635 nfs_set_error(nfs
, "nfs_creat_async failed");
639 wait_for_nfs_reply(nfs
, &cb_data
);
641 return cb_data
.status
;
648 static void unlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
650 struct sync_cb_data
*cb_data
= private_data
;
652 cb_data
->is_finished
= 1;
653 cb_data
->status
= status
;
656 nfs_set_error(nfs
, "unlink call failed with \"%s\"", (char *)data
);
661 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
663 struct sync_cb_data cb_data
;
665 cb_data
.is_finished
= 0;
667 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
668 nfs_set_error(nfs
, "nfs_unlink_async failed");
672 wait_for_nfs_reply(nfs
, &cb_data
);
674 return cb_data
.status
;
682 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
684 struct sync_cb_data
*cb_data
= private_data
;
685 struct nfsdir
*dir
, **nfsdir
;
687 cb_data
->is_finished
= 1;
688 cb_data
->status
= status
;
691 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
696 nfsdir
= cb_data
->return_data
;
700 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
702 struct sync_cb_data cb_data
;
704 cb_data
.is_finished
= 0;
705 cb_data
.return_data
= nfsdir
;
707 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
708 nfs_set_error(nfs
, "nfs_opendir_async failed");
712 wait_for_nfs_reply(nfs
, &cb_data
);
714 return cb_data
.status
;
721 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
723 struct sync_cb_data
*cb_data
= private_data
;
725 cb_data
->is_finished
= 1;
726 cb_data
->status
= status
;
729 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
733 if (cb_data
->return_data
!= NULL
) {
734 memcpy(cb_data
->return_data
, data
, sizeof(uint64_t));
738 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, int whence
, uint64_t *current_offset
)
740 struct sync_cb_data cb_data
;
742 cb_data
.is_finished
= 0;
743 cb_data
.return_data
= current_offset
;
745 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
746 nfs_set_error(nfs
, "nfs_lseek_async failed");
750 wait_for_nfs_reply(nfs
, &cb_data
);
752 return cb_data
.status
;
760 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
762 struct sync_cb_data
*cb_data
= private_data
;
764 cb_data
->is_finished
= 1;
765 cb_data
->status
= status
;
768 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
772 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
775 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
777 struct sync_cb_data cb_data
;
779 cb_data
.is_finished
= 0;
780 cb_data
.return_data
= svfs
;
782 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
783 nfs_set_error(nfs
, "nfs_statvfs_async failed");
787 wait_for_nfs_reply(nfs
, &cb_data
);
789 return cb_data
.status
;
799 static void readlink_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
, "readlink call failed with \"%s\"", (char *)data
);
811 if (strlen(data
) > (size_t)cb_data
->return_int
) {
812 nfs_set_error(nfs
, "Too small buffer for readlink");
813 cb_data
->status
= -ENAMETOOLONG
;
817 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
820 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
822 struct sync_cb_data cb_data
;
824 cb_data
.is_finished
= 0;
825 cb_data
.return_data
= buf
;
826 cb_data
.return_int
= bufsize
;
828 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
829 nfs_set_error(nfs
, "nfs_readlink_async failed");
833 wait_for_nfs_reply(nfs
, &cb_data
);
835 return cb_data
.status
;
843 static void chmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
845 struct sync_cb_data
*cb_data
= private_data
;
847 cb_data
->is_finished
= 1;
848 cb_data
->status
= status
;
851 nfs_set_error(nfs
, "chmod call failed with \"%s\"", (char *)data
);
856 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
858 struct sync_cb_data cb_data
;
860 cb_data
.is_finished
= 0;
862 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
863 nfs_set_error(nfs
, "nfs_chmod_async failed");
867 wait_for_nfs_reply(nfs
, &cb_data
);
869 return cb_data
.status
;
878 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
880 struct sync_cb_data
*cb_data
= private_data
;
882 cb_data
->is_finished
= 1;
883 cb_data
->status
= status
;
886 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
891 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
893 struct sync_cb_data cb_data
;
895 cb_data
.is_finished
= 0;
897 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
898 nfs_set_error(nfs
, "nfs_fchmod_async failed");
902 wait_for_nfs_reply(nfs
, &cb_data
);
904 return cb_data
.status
;
913 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
915 struct sync_cb_data
*cb_data
= private_data
;
917 cb_data
->is_finished
= 1;
918 cb_data
->status
= status
;
921 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
926 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
928 struct sync_cb_data cb_data
;
930 cb_data
.is_finished
= 0;
932 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
933 nfs_set_error(nfs
, "nfs_chown_async failed");
937 wait_for_nfs_reply(nfs
, &cb_data
);
939 return cb_data
.status
;
945 static void fchown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
947 struct sync_cb_data
*cb_data
= private_data
;
949 cb_data
->is_finished
= 1;
950 cb_data
->status
= status
;
953 nfs_set_error(nfs
, "fchown call failed with \"%s\"", (char *)data
);
958 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
960 struct sync_cb_data cb_data
;
962 cb_data
.is_finished
= 0;
964 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
965 nfs_set_error(nfs
, "nfs_fchown_async failed");
969 wait_for_nfs_reply(nfs
, &cb_data
);
971 return cb_data
.status
;
979 static void utimes_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
981 struct sync_cb_data
*cb_data
= private_data
;
983 cb_data
->is_finished
= 1;
984 cb_data
->status
= status
;
987 nfs_set_error(nfs
, "utimes call failed with \"%s\"", (char *)data
);
992 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
994 struct sync_cb_data cb_data
;
996 cb_data
.is_finished
= 0;
998 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
999 nfs_set_error(nfs
, "nfs_utimes_async failed");
1003 wait_for_nfs_reply(nfs
, &cb_data
);
1005 return cb_data
.status
;
1013 static void utime_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1015 struct sync_cb_data
*cb_data
= private_data
;
1017 cb_data
->is_finished
= 1;
1018 cb_data
->status
= status
;
1021 nfs_set_error(nfs
, "utime call failed with \"%s\"", (char *)data
);
1026 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
1028 struct sync_cb_data cb_data
;
1030 cb_data
.is_finished
= 0;
1032 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
1033 nfs_set_error(nfs
, "nfs_utimes_async failed");
1037 wait_for_nfs_reply(nfs
, &cb_data
);
1039 return cb_data
.status
;
1048 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1050 struct sync_cb_data
*cb_data
= private_data
;
1052 cb_data
->is_finished
= 1;
1053 cb_data
->status
= status
;
1056 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
1061 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
1063 struct sync_cb_data cb_data
;
1065 cb_data
.is_finished
= 0;
1067 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
1068 nfs_set_error(nfs
, "nfs_access_async failed");
1072 wait_for_nfs_reply(nfs
, &cb_data
);
1074 return cb_data
.status
;
1082 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1084 struct sync_cb_data
*cb_data
= private_data
;
1086 cb_data
->is_finished
= 1;
1087 cb_data
->status
= status
;
1090 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
1095 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1097 struct sync_cb_data cb_data
;
1099 cb_data
.is_finished
= 0;
1101 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
1102 nfs_set_error(nfs
, "nfs_symlink_async failed");
1106 wait_for_nfs_reply(nfs
, &cb_data
);
1108 return cb_data
.status
;
1116 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1118 struct sync_cb_data
*cb_data
= private_data
;
1120 cb_data
->is_finished
= 1;
1121 cb_data
->status
= status
;
1124 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1129 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1131 struct sync_cb_data cb_data
;
1133 cb_data
.is_finished
= 0;
1135 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1136 nfs_set_error(nfs
, "nfs_rename_async failed");
1140 wait_for_nfs_reply(nfs
, &cb_data
);
1142 return cb_data
.status
;
1150 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1152 struct sync_cb_data
*cb_data
= private_data
;
1154 cb_data
->is_finished
= 1;
1155 cb_data
->status
= status
;
1158 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1163 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1165 struct sync_cb_data cb_data
;
1167 cb_data
.is_finished
= 0;
1169 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1170 nfs_set_error(nfs
, "nfs_link_async failed");
1174 wait_for_nfs_reply(nfs
, &cb_data
);
1176 return cb_data
.status
;
1179 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1181 struct sync_cb_data
*cb_data
= private_data
;
1184 assert(mount_context
->magic
== RPC_CONTEXT_MAGIC
);
1186 cb_data
->is_finished
= 1;
1187 cb_data
->status
= status
;
1188 cb_data
->return_data
= NULL
;
1191 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1195 export
= *(exports
*)data
;
1196 while (export
!= NULL
) {
1199 new_export
= malloc(sizeof(*new_export
));
1200 memset(new_export
, 0, sizeof(*new_export
));
1201 new_export
->ex_dir
= strdup(export
->ex_dir
);
1202 new_export
->ex_next
= cb_data
->return_data
;
1204 cb_data
->return_data
= new_export
;
1206 export
= export
->ex_next
;
1210 struct exportnode
*mount_getexports(const char *server
)
1212 struct sync_cb_data cb_data
;
1213 struct rpc_context
*rpc
;
1216 cb_data
.is_finished
= 0;
1217 cb_data
.return_data
= NULL
;
1219 rpc
= rpc_init_context();
1220 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1221 rpc_destroy_context(rpc
);
1225 wait_for_reply(rpc
, &cb_data
);
1226 rpc_destroy_context(rpc
);
1228 return cb_data
.return_data
;
1231 void mount_free_export_list(struct exportnode
*exports
)
1233 struct exportnode
*tmp
;
1235 while ((tmp
= exports
)) {
1236 exports
= exports
->ex_next
;
1244 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1246 while (srv
!= NULL
) {
1247 struct nfs_server_list
*next
= srv
->next
;
1255 struct nfs_list_data
{
1257 struct nfs_server_list
*srvrs
;
1260 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1262 struct nfs_list_data
*srv_data
= private_data
;
1263 struct sockaddr
*sin
;
1265 struct nfs_server_list
*srvr
;
1267 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1269 if (status
== RPC_STATUS_CANCEL
) {
1273 srv_data
->status
= -1;
1277 sin
= rpc_get_recv_sockaddr(rpc
);
1279 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1280 srv_data
->status
= -1;
1284 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1285 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1286 srv_data
->status
= -1;
1290 /* check for dupes */
1291 for (srvr
= srv_data
->srvrs
; srvr
; srvr
= srvr
->next
) {
1292 if (!strcmp(hostdd
, srvr
->addr
)) {
1297 srvr
= malloc(sizeof(struct nfs_server_list
));
1299 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1300 srv_data
->status
= -1;
1304 srvr
->addr
= strdup(hostdd
);
1305 if (srvr
->addr
== NULL
) {
1306 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1308 srv_data
->status
= -1;
1312 srvr
->next
= srv_data
->srvrs
;
1313 srv_data
->srvrs
= srvr
;
1318 static int send_nfsd_probes(struct rpc_context
*rpc
, INTERFACE_INFO
*InterfaceList
, int numIfs
, struct nfs_list_data
*data
)
1322 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1324 for(i
= 0; i
< numIfs
; i
++)
1328 unsigned long nFlags
= 0;
1330 pAddress
= (SOCKADDR
*) & (InterfaceList
[i
].iiBroadcastAddress
);
1332 if(pAddress
->sa_family
!= AF_INET
)
1335 nFlags
= InterfaceList
[i
].iiFlags
;
1337 if (!(nFlags
& IFF_UP
))
1342 if (nFlags
& IFF_LOOPBACK
)
1347 if (!(nFlags
& IFF_BROADCAST
))
1352 if (getnameinfo(pAddress
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0)
1357 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0)
1362 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0)
1370 struct nfs_server_list
*nfs_find_local_servers(void)
1372 struct rpc_context
*rpc
;
1373 struct nfs_list_data data
= {0, NULL
};
1374 struct timeval tv_start
, tv_current
;
1377 INTERFACE_INFO InterfaceList
[20];
1378 unsigned long nBytesReturned
;
1379 int nNumInterfaces
= 0;
1381 rpc
= rpc_init_udp_context();
1387 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0)
1389 rpc_destroy_context(rpc
);
1393 if (WSAIoctl(rpc_get_fd(rpc
), SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
, sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
1398 nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
1400 for (loop
=0; loop
<3; loop
++)
1402 if (send_nfsd_probes(rpc
, InterfaceList
, nNumInterfaces
, &data
) != 0)
1404 rpc_destroy_context(rpc
);
1408 win32_gettimeofday(&tv_start
, NULL
);
1413 pfd
.fd
= rpc_get_fd(rpc
);
1414 pfd
.events
= rpc_which_events(rpc
);
1416 win32_gettimeofday(&tv_current
, NULL
);
1418 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1419 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1421 if (poll(&pfd
, 1, mpt
) < 0)
1423 free_nfs_srvr_list(data
.srvrs
);
1424 rpc_destroy_context(rpc
);
1427 if (pfd
.revents
== 0)
1432 if (rpc_service(rpc
, pfd
.revents
) < 0)
1439 rpc_destroy_context(rpc
);
1441 if (data
.status
!= 0)
1443 free_nfs_srvr_list(data
.srvrs
);
1450 static int send_nfsd_probes(struct rpc_context
*rpc
, struct ifconf
*ifc
, struct nfs_list_data
*data
)
1454 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1456 for (ptr
=(char *)(ifc
->ifc_buf
); ptr
< (char *)(ifc
->ifc_buf
) + ifc
->ifc_len
; ) {
1460 ifr
= (struct ifreq
*)ptr
;
1461 #ifdef HAVE_SOCKADDR_LEN
1462 if (ifr
->ifr_addr
.sa_len
> sizeof(struct sockaddr
)) {
1463 ptr
+= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
1465 ptr
+= sizeof(ifr
->ifr_name
) + sizeof(struct sockaddr
);
1468 ptr
+= sizeof(struct ifreq
);
1471 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) {
1474 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, ifr
) < 0) {
1477 if (!(ifr
->ifr_flags
& IFF_UP
)) {
1480 if (ifr
->ifr_flags
& IFF_LOOPBACK
) {
1483 if (!(ifr
->ifr_flags
& IFF_BROADCAST
)) {
1486 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, ifr
) < 0) {
1489 if (getnameinfo(&ifr
->ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1492 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1496 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0) {
1504 struct nfs_server_list
*nfs_find_local_servers(void)
1506 struct rpc_context
*rpc
;
1507 struct nfs_list_data data
= {0, NULL
};
1508 struct timeval tv_start
, tv_current
;
1513 rpc
= rpc_init_udp_context();
1518 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1519 rpc_destroy_context(rpc
);
1524 /* get list of all interfaces */
1525 size
= sizeof(struct ifreq
);
1529 while(ifc
.ifc_len
> (size
- sizeof(struct ifreq
))) {
1534 ifc
.ifc_buf
= malloc(size
);
1535 memset(ifc
.ifc_buf
, 0, size
);
1536 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1537 rpc_destroy_context(rpc
);
1543 for (loop
=0; loop
<3; loop
++) {
1544 if (send_nfsd_probes(rpc
, &ifc
, &data
) != 0) {
1545 rpc_destroy_context(rpc
);
1550 gettimeofday(&tv_start
, NULL
);
1554 pfd
.fd
= rpc_get_fd(rpc
);
1555 pfd
.events
= rpc_which_events(rpc
);
1557 gettimeofday(&tv_current
, NULL
);
1559 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1560 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1562 if (poll(&pfd
, 1, mpt
) < 0) {
1563 free_nfs_srvr_list(data
.srvrs
);
1564 rpc_destroy_context(rpc
);
1567 if (pfd
.revents
== 0) {
1571 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1578 rpc_destroy_context(rpc
);
1580 if (data
.status
!= 0) {
1581 free_nfs_srvr_list(data
.srvrs
);