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"
32 #ifdef HAVE_SYS_SOCKET_H
33 #include <sys/socket.h>
41 #define statvfs statfs
48 #ifdef HAVE_SYS_STATVFS_H
49 #include <sys/statvfs.h>
52 #ifdef HAVE_SYS_IOCTL_H
53 #include <sys/ioctl.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"
106 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
110 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
112 while (!cb_data
->is_finished
) {
114 pfd
.fd
= rpc_get_fd(rpc
);
115 pfd
.events
= rpc_which_events(rpc
);
116 if (poll(&pfd
, 1, -1) < 0) {
117 rpc_set_error(rpc
, "Poll failed");
118 cb_data
->status
= -EIO
;
121 if (rpc_service(rpc
, pfd
.revents
) < 0) {
122 rpc_set_error(rpc
, "rpc_service failed");
123 cb_data
->status
= -EIO
;
126 if (rpc_get_fd(rpc
) == -1) {
127 rpc_set_error(rpc
, "Socket closed\n");
133 static void wait_for_nfs_reply(struct nfs_context
*nfs
, struct sync_cb_data
*cb_data
)
137 while (!cb_data
->is_finished
) {
139 pfd
.fd
= nfs_get_fd(nfs
);
140 pfd
.events
= nfs_which_events(nfs
);
141 if (poll(&pfd
, 1, -1) < 0) {
142 nfs_set_error(nfs
, "Poll failed");
143 cb_data
->status
= -EIO
;
146 if (nfs_service(nfs
, pfd
.revents
) < 0) {
147 nfs_set_error(nfs
, "nfs_service failed");
148 cb_data
->status
= -EIO
;
160 * connect to the server and mount the export
162 static void mount_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
, "mount/mnt call failed with \"%s\"", (char *)data
);
175 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
177 struct sync_cb_data cb_data
;
178 struct rpc_context
*rpc
= nfs_get_rpc_context(nfs
);
180 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
182 cb_data
.is_finished
= 0;
184 if (nfs_mount_async(nfs
, server
, export
, mount_cb
, &cb_data
) != 0) {
185 nfs_set_error(nfs
, "nfs_mount_async failed");
189 wait_for_nfs_reply(nfs
, &cb_data
);
191 /* Dont want any more callbacks even if the socket is closed */
192 rpc
->connect_cb
= NULL
;
194 return cb_data
.status
;
201 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
203 struct sync_cb_data
*cb_data
= private_data
;
205 cb_data
->is_finished
= 1;
206 cb_data
->status
= status
;
209 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
213 memcpy(cb_data
->return_data
, data
, sizeof(struct __stat64
));
215 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
220 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct __stat64
*st
)
222 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
225 struct sync_cb_data cb_data
;
227 cb_data
.is_finished
= 0;
228 cb_data
.return_data
= st
;
230 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
231 nfs_set_error(nfs
, "nfs_stat_async failed");
235 wait_for_nfs_reply(nfs
, &cb_data
);
237 return cb_data
.status
;
240 static void stat64_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
242 struct sync_cb_data
*cb_data
= private_data
;
244 cb_data
->is_finished
= 1;
245 cb_data
->status
= status
;
248 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
251 memcpy(cb_data
->return_data
, data
, sizeof(struct nfs_stat_64
));
254 int nfs_stat64(struct nfs_context
*nfs
, const char *path
, struct nfs_stat_64
*st
)
256 struct sync_cb_data cb_data
;
258 cb_data
.is_finished
= 0;
259 cb_data
.return_data
= st
;
261 if (nfs_stat64_async(nfs
, path
, stat64_cb
, &cb_data
) != 0) {
262 nfs_set_error(nfs
, "nfs_stat64_async failed");
266 wait_for_nfs_reply(nfs
, &cb_data
);
268 return cb_data
.status
;
271 int nfs_lstat64(struct nfs_context
*nfs
, const char *path
, struct nfs_stat_64
*st
)
273 struct sync_cb_data cb_data
;
275 cb_data
.is_finished
= 0;
276 cb_data
.return_data
= st
;
278 if (nfs_lstat64_async(nfs
, path
, stat64_cb
, &cb_data
) != 0) {
279 nfs_set_error(nfs
, "nfs_lstat64_async failed");
283 wait_for_nfs_reply(nfs
, &cb_data
);
285 return cb_data
.status
;
291 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
293 struct sync_cb_data
*cb_data
= private_data
;
294 struct nfsfh
*fh
, **nfsfh
;
296 cb_data
->is_finished
= 1;
297 cb_data
->status
= status
;
300 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
305 nfsfh
= cb_data
->return_data
;
309 int nfs_open(struct nfs_context
*nfs
, const char *path
, int flags
, struct nfsfh
**nfsfh
)
311 struct sync_cb_data cb_data
;
313 cb_data
.is_finished
= 0;
314 cb_data
.return_data
= nfsfh
;
316 if (nfs_open_async(nfs
, path
, flags
, open_cb
, &cb_data
) != 0) {
317 nfs_set_error(nfs
, "nfs_open_async failed");
321 wait_for_nfs_reply(nfs
, &cb_data
);
323 return cb_data
.status
;
329 static void chdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
331 struct sync_cb_data
*cb_data
= private_data
;
333 cb_data
->is_finished
= 1;
334 cb_data
->status
= status
;
337 nfs_set_error(nfs
, "chdir call failed with \"%s\"", (char *)data
);
342 int nfs_chdir(struct nfs_context
*nfs
, const char *path
)
344 struct sync_cb_data cb_data
;
346 cb_data
.is_finished
= 0;
348 if (nfs_chdir_async(nfs
, path
, chdir_cb
, &cb_data
) != 0) {
349 nfs_set_error(nfs
, "nfs_chdir_async failed with %s",
354 wait_for_nfs_reply(nfs
, &cb_data
);
356 return cb_data
.status
;
364 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
366 struct sync_cb_data
*cb_data
= private_data
;
368 cb_data
->is_finished
= 1;
369 cb_data
->status
= status
;
372 nfs_set_error(nfs
, "%s call failed with \"%s\"", cb_data
->call
, (char *)data
);
376 buffer
= cb_data
->return_data
;
377 memcpy(buffer
, (char *)data
, status
);
380 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buffer
)
382 struct sync_cb_data cb_data
;
384 cb_data
.is_finished
= 0;
385 cb_data
.return_data
= buffer
;
386 cb_data
.call
= "pread";
388 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
389 nfs_set_error(nfs
, "nfs_pread_async failed");
393 wait_for_nfs_reply(nfs
, &cb_data
);
395 return cb_data
.status
;
401 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buffer
)
403 struct sync_cb_data cb_data
;
405 cb_data
.is_finished
= 0;
406 cb_data
.return_data
= buffer
;
407 cb_data
.call
= "read";
409 if (nfs_read_async(nfs
, nfsfh
, count
, pread_cb
, &cb_data
) != 0) {
410 nfs_set_error(nfs
, "nfs_read_async failed");
414 wait_for_nfs_reply(nfs
, &cb_data
);
416 return cb_data
.status
;
422 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
424 struct sync_cb_data
*cb_data
= private_data
;
425 cb_data
->is_finished
= 1;
426 cb_data
->status
= status
;
429 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
434 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
436 struct sync_cb_data cb_data
;
438 cb_data
.is_finished
= 0;
440 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
441 nfs_set_error(nfs
, "nfs_close_async failed");
445 wait_for_nfs_reply(nfs
, &cb_data
);
447 return cb_data
.status
;
456 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
458 struct sync_cb_data cb_data
;
460 cb_data
.is_finished
= 0;
461 cb_data
.return_data
= st
;
463 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
464 nfs_set_error(nfs
, "nfs_fstat_async failed");
468 wait_for_nfs_reply(nfs
, &cb_data
);
470 return cb_data
.status
;
476 int nfs_fstat64(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct nfs_stat_64
*st
)
478 struct sync_cb_data cb_data
;
480 cb_data
.is_finished
= 0;
481 cb_data
.return_data
= st
;
483 if (nfs_fstat64_async(nfs
, nfsfh
, stat64_cb
, &cb_data
) != 0) {
484 nfs_set_error(nfs
, "nfs_fstat64_async failed");
488 wait_for_nfs_reply(nfs
, &cb_data
);
490 return cb_data
.status
;
497 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
499 struct sync_cb_data
*cb_data
= private_data
;
500 cb_data
->is_finished
= 1;
501 cb_data
->status
= status
;
504 nfs_set_error(nfs
, "%s call failed with \"%s\"", cb_data
->call
, (char *)data
);
507 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buf
)
509 struct sync_cb_data cb_data
;
511 cb_data
.is_finished
= 0;
512 cb_data
.call
= "pwrite";
514 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
515 nfs_set_error(nfs
, "nfs_pwrite_async failed");
519 wait_for_nfs_reply(nfs
, &cb_data
);
521 return cb_data
.status
;
527 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buf
)
529 struct sync_cb_data cb_data
;
531 cb_data
.is_finished
= 0;
532 cb_data
.call
= "write";
534 if (nfs_write_async(nfs
, nfsfh
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
535 nfs_set_error(nfs
, "nfs_write_async failed");
539 wait_for_nfs_reply(nfs
, &cb_data
);
541 return cb_data
.status
;
548 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
550 struct sync_cb_data
*cb_data
= private_data
;
551 cb_data
->is_finished
= 1;
552 cb_data
->status
= status
;
555 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
560 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
562 struct sync_cb_data cb_data
;
564 cb_data
.is_finished
= 0;
566 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
567 nfs_set_error(nfs
, "nfs_fsync_async failed");
571 wait_for_nfs_reply(nfs
, &cb_data
);
573 return cb_data
.status
;
582 static void ftruncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
584 struct sync_cb_data
*cb_data
= private_data
;
585 cb_data
->is_finished
= 1;
586 cb_data
->status
= status
;
589 nfs_set_error(nfs
, "ftruncate call failed with \"%s\"", (char *)data
);
594 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t length
)
596 struct sync_cb_data cb_data
;
598 cb_data
.is_finished
= 0;
600 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_cb
, &cb_data
) != 0) {
601 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
605 wait_for_nfs_reply(nfs
, &cb_data
);
607 return cb_data
.status
;
615 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
617 struct sync_cb_data
*cb_data
= private_data
;
618 cb_data
->is_finished
= 1;
619 cb_data
->status
= status
;
622 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
627 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, uint64_t length
)
629 struct sync_cb_data cb_data
;
631 cb_data
.is_finished
= 0;
633 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
634 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
638 wait_for_nfs_reply(nfs
, &cb_data
);
640 return cb_data
.status
;
650 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
652 struct sync_cb_data
*cb_data
= private_data
;
653 cb_data
->is_finished
= 1;
654 cb_data
->status
= status
;
657 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
662 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
664 struct sync_cb_data cb_data
;
666 cb_data
.is_finished
= 0;
668 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
669 nfs_set_error(nfs
, "nfs_mkdir_async failed");
673 wait_for_nfs_reply(nfs
, &cb_data
);
675 return cb_data
.status
;
685 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
687 struct sync_cb_data
*cb_data
= private_data
;
688 cb_data
->is_finished
= 1;
689 cb_data
->status
= status
;
692 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
697 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
699 struct sync_cb_data cb_data
;
701 cb_data
.is_finished
= 0;
703 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
704 nfs_set_error(nfs
, "nfs_rmdir_async failed");
708 wait_for_nfs_reply(nfs
, &cb_data
);
710 return cb_data
.status
;
718 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
720 struct sync_cb_data
*cb_data
= private_data
;
721 struct nfsfh
*fh
, **nfsfh
;
723 cb_data
->is_finished
= 1;
724 cb_data
->status
= status
;
727 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
732 nfsfh
= cb_data
->return_data
;
736 int nfs_create(struct nfs_context
*nfs
, const char *path
, int flags
, int mode
, struct nfsfh
**nfsfh
)
738 struct sync_cb_data cb_data
;
740 cb_data
.is_finished
= 0;
741 cb_data
.return_data
= nfsfh
;
743 if (nfs_create_async(nfs
, path
, flags
, mode
, creat_cb
, &cb_data
) != 0) {
744 nfs_set_error(nfs
, "nfs_create_async failed");
748 wait_for_nfs_reply(nfs
, &cb_data
);
750 return cb_data
.status
;
753 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
755 return nfs_create(nfs
, path
, 0, mode
, nfsfh
);
761 static void mknod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
763 struct sync_cb_data
*cb_data
= private_data
;
765 cb_data
->is_finished
= 1;
766 cb_data
->status
= status
;
769 nfs_set_error(nfs
, "mknod call failed with \"%s\"", (char *)data
);
774 int nfs_mknod(struct nfs_context
*nfs
, const char *path
, int mode
, int dev
)
776 struct sync_cb_data cb_data
;
778 cb_data
.is_finished
= 0;
780 if (nfs_mknod_async(nfs
, path
, mode
, dev
, mknod_cb
, &cb_data
) != 0) {
781 nfs_set_error(nfs
, "nfs_creat_async failed");
785 wait_for_nfs_reply(nfs
, &cb_data
);
787 return cb_data
.status
;
794 static void unlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
796 struct sync_cb_data
*cb_data
= private_data
;
798 cb_data
->is_finished
= 1;
799 cb_data
->status
= status
;
802 nfs_set_error(nfs
, "unlink call failed with \"%s\"", (char *)data
);
807 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
809 struct sync_cb_data cb_data
;
811 cb_data
.is_finished
= 0;
813 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
814 nfs_set_error(nfs
, "nfs_unlink_async failed");
818 wait_for_nfs_reply(nfs
, &cb_data
);
820 return cb_data
.status
;
828 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
830 struct sync_cb_data
*cb_data
= private_data
;
831 struct nfsdir
*dir
, **nfsdir
;
833 cb_data
->is_finished
= 1;
834 cb_data
->status
= status
;
837 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
842 nfsdir
= cb_data
->return_data
;
846 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
848 struct sync_cb_data cb_data
;
850 cb_data
.is_finished
= 0;
851 cb_data
.return_data
= nfsdir
;
853 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
854 nfs_set_error(nfs
, "nfs_opendir_async failed");
858 wait_for_nfs_reply(nfs
, &cb_data
);
860 return cb_data
.status
;
867 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
869 struct sync_cb_data
*cb_data
= private_data
;
871 cb_data
->is_finished
= 1;
872 cb_data
->status
= status
;
875 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
879 if (cb_data
->return_data
!= NULL
) {
880 memcpy(cb_data
->return_data
, data
, sizeof(uint64_t));
884 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int64_t offset
, int whence
, uint64_t *current_offset
)
886 struct sync_cb_data cb_data
;
888 cb_data
.is_finished
= 0;
889 cb_data
.return_data
= current_offset
;
891 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
892 nfs_set_error(nfs
, "nfs_lseek_async failed");
896 wait_for_nfs_reply(nfs
, &cb_data
);
898 return cb_data
.status
;
906 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
908 struct sync_cb_data
*cb_data
= private_data
;
910 cb_data
->is_finished
= 1;
911 cb_data
->status
= status
;
914 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
918 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
921 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
923 struct sync_cb_data cb_data
;
925 cb_data
.is_finished
= 0;
926 cb_data
.return_data
= svfs
;
928 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
929 nfs_set_error(nfs
, "nfs_statvfs_async failed");
933 wait_for_nfs_reply(nfs
, &cb_data
);
935 return cb_data
.status
;
945 static void readlink_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
, "readlink call failed with \"%s\"", (char *)data
);
957 if (strlen(data
) > (size_t)cb_data
->return_int
) {
958 nfs_set_error(nfs
, "Too small buffer for readlink");
959 cb_data
->status
= -ENAMETOOLONG
;
963 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
966 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
968 struct sync_cb_data cb_data
;
970 cb_data
.is_finished
= 0;
971 cb_data
.return_data
= buf
;
972 cb_data
.return_int
= bufsize
;
974 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
975 nfs_set_error(nfs
, "nfs_readlink_async failed");
979 wait_for_nfs_reply(nfs
, &cb_data
);
981 return cb_data
.status
;
989 static void chmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
991 struct sync_cb_data
*cb_data
= private_data
;
993 cb_data
->is_finished
= 1;
994 cb_data
->status
= status
;
997 nfs_set_error(nfs
, "chmod call failed with \"%s\"", (char *)data
);
1002 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
1004 struct sync_cb_data cb_data
;
1006 cb_data
.is_finished
= 0;
1008 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
1009 nfs_set_error(nfs
, "nfs_chmod_async failed");
1013 wait_for_nfs_reply(nfs
, &cb_data
);
1015 return cb_data
.status
;
1018 int nfs_lchmod(struct nfs_context
*nfs
, const char *path
, int mode
)
1020 struct sync_cb_data cb_data
;
1022 cb_data
.is_finished
= 0;
1024 if (nfs_lchmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
1025 nfs_set_error(nfs
, "nfs_lchmod_async failed");
1029 wait_for_nfs_reply(nfs
, &cb_data
);
1031 return cb_data
.status
;
1040 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1042 struct sync_cb_data
*cb_data
= private_data
;
1044 cb_data
->is_finished
= 1;
1045 cb_data
->status
= status
;
1048 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
1053 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
1055 struct sync_cb_data cb_data
;
1057 cb_data
.is_finished
= 0;
1059 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
1060 nfs_set_error(nfs
, "nfs_fchmod_async failed");
1064 wait_for_nfs_reply(nfs
, &cb_data
);
1066 return cb_data
.status
;
1075 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1077 struct sync_cb_data
*cb_data
= private_data
;
1079 cb_data
->is_finished
= 1;
1080 cb_data
->status
= status
;
1083 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
1088 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
1090 struct sync_cb_data cb_data
;
1092 cb_data
.is_finished
= 0;
1094 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
1095 nfs_set_error(nfs
, "nfs_chown_async failed");
1099 wait_for_nfs_reply(nfs
, &cb_data
);
1101 return cb_data
.status
;
1107 int nfs_lchown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
1109 struct sync_cb_data cb_data
;
1111 cb_data
.is_finished
= 0;
1113 if (nfs_lchown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
1114 nfs_set_error(nfs
, "nfs_lchown_async failed");
1118 wait_for_nfs_reply(nfs
, &cb_data
);
1120 return cb_data
.status
;
1126 static void fchown_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
, "fchown call failed with \"%s\"", (char *)data
);
1139 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
1141 struct sync_cb_data cb_data
;
1143 cb_data
.is_finished
= 0;
1145 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
1146 nfs_set_error(nfs
, "nfs_fchown_async failed");
1150 wait_for_nfs_reply(nfs
, &cb_data
);
1152 return cb_data
.status
;
1160 static void utimes_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
, "utimes call failed with \"%s\"", (char *)data
);
1173 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
1175 struct sync_cb_data cb_data
;
1177 cb_data
.is_finished
= 0;
1179 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
1180 nfs_set_error(nfs
, "nfs_utimes_async failed");
1184 wait_for_nfs_reply(nfs
, &cb_data
);
1186 return cb_data
.status
;
1189 int nfs_lutimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
1191 struct sync_cb_data cb_data
;
1193 cb_data
.is_finished
= 0;
1195 if (nfs_lutimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
1196 nfs_set_error(nfs
, "nfs_lutimes_async failed");
1200 wait_for_nfs_reply(nfs
, &cb_data
);
1202 return cb_data
.status
;
1210 static void utime_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1212 struct sync_cb_data
*cb_data
= private_data
;
1214 cb_data
->is_finished
= 1;
1215 cb_data
->status
= status
;
1218 nfs_set_error(nfs
, "utime call failed with \"%s\"", (char *)data
);
1223 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
1225 struct sync_cb_data cb_data
;
1227 cb_data
.is_finished
= 0;
1229 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
1230 nfs_set_error(nfs
, "nfs_utimes_async failed");
1234 wait_for_nfs_reply(nfs
, &cb_data
);
1236 return cb_data
.status
;
1245 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1247 struct sync_cb_data
*cb_data
= private_data
;
1249 cb_data
->is_finished
= 1;
1250 cb_data
->status
= status
;
1253 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
1258 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
1260 struct sync_cb_data cb_data
;
1262 cb_data
.is_finished
= 0;
1264 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
1265 nfs_set_error(nfs
, "nfs_access_async failed");
1269 wait_for_nfs_reply(nfs
, &cb_data
);
1271 return cb_data
.status
;
1279 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1281 struct sync_cb_data
*cb_data
= private_data
;
1283 cb_data
->is_finished
= 1;
1284 cb_data
->status
= status
;
1287 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
1292 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1294 struct sync_cb_data cb_data
;
1296 cb_data
.is_finished
= 0;
1298 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
1299 nfs_set_error(nfs
, "nfs_symlink_async failed");
1303 wait_for_nfs_reply(nfs
, &cb_data
);
1305 return cb_data
.status
;
1313 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1315 struct sync_cb_data
*cb_data
= private_data
;
1317 cb_data
->is_finished
= 1;
1318 cb_data
->status
= status
;
1321 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1326 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1328 struct sync_cb_data cb_data
;
1330 cb_data
.is_finished
= 0;
1332 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1333 nfs_set_error(nfs
, "nfs_rename_async failed");
1337 wait_for_nfs_reply(nfs
, &cb_data
);
1339 return cb_data
.status
;
1347 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1349 struct sync_cb_data
*cb_data
= private_data
;
1351 cb_data
->is_finished
= 1;
1352 cb_data
->status
= status
;
1355 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1360 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1362 struct sync_cb_data cb_data
;
1364 cb_data
.is_finished
= 0;
1366 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1367 nfs_set_error(nfs
, "nfs_link_async failed");
1371 wait_for_nfs_reply(nfs
, &cb_data
);
1373 return cb_data
.status
;
1376 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1378 struct sync_cb_data
*cb_data
= private_data
;
1381 assert(mount_context
->magic
== RPC_CONTEXT_MAGIC
);
1383 cb_data
->is_finished
= 1;
1384 cb_data
->status
= status
;
1385 cb_data
->return_data
= NULL
;
1388 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1392 export
= *(exports
*)data
;
1393 while (export
!= NULL
) {
1396 new_export
= malloc(sizeof(*new_export
));
1397 memset(new_export
, 0, sizeof(*new_export
));
1398 new_export
->ex_dir
= strdup(export
->ex_dir
);
1399 new_export
->ex_next
= cb_data
->return_data
;
1401 cb_data
->return_data
= new_export
;
1403 export
= export
->ex_next
;
1407 struct exportnode
*mount_getexports(const char *server
)
1409 struct sync_cb_data cb_data
;
1410 struct rpc_context
*rpc
;
1413 cb_data
.is_finished
= 0;
1414 cb_data
.return_data
= NULL
;
1416 rpc
= rpc_init_context();
1417 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1418 rpc_destroy_context(rpc
);
1422 wait_for_reply(rpc
, &cb_data
);
1423 rpc_destroy_context(rpc
);
1425 return cb_data
.return_data
;
1428 void mount_free_export_list(struct exportnode
*exports
)
1430 struct exportnode
*tmp
;
1432 while ((tmp
= exports
)) {
1433 exports
= exports
->ex_next
;
1441 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1443 while (srv
!= NULL
) {
1444 struct nfs_server_list
*next
= srv
->next
;
1452 struct nfs_list_data
{
1454 struct nfs_server_list
*srvrs
;
1457 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1459 struct nfs_list_data
*srv_data
= private_data
;
1460 struct sockaddr
*sin
;
1462 struct nfs_server_list
*srvr
;
1464 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1466 if (status
== RPC_STATUS_CANCEL
) {
1470 srv_data
->status
= -1;
1474 sin
= rpc_get_recv_sockaddr(rpc
);
1476 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1477 srv_data
->status
= -1;
1481 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1482 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1483 srv_data
->status
= -1;
1487 /* check for dupes */
1488 for (srvr
= srv_data
->srvrs
; srvr
; srvr
= srvr
->next
) {
1489 if (!strcmp(hostdd
, srvr
->addr
)) {
1494 srvr
= malloc(sizeof(struct nfs_server_list
));
1496 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1497 srv_data
->status
= -1;
1501 srvr
->addr
= strdup(hostdd
);
1502 if (srvr
->addr
== NULL
) {
1503 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1505 srv_data
->status
= -1;
1509 srvr
->next
= srv_data
->srvrs
;
1510 srv_data
->srvrs
= srvr
;
1515 static int send_nfsd_probes(struct rpc_context
*rpc
, INTERFACE_INFO
*InterfaceList
, int numIfs
, struct nfs_list_data
*data
)
1519 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1521 for(i
= 0; i
< numIfs
; i
++)
1525 unsigned long nFlags
= 0;
1527 pAddress
= (SOCKADDR
*) & (InterfaceList
[i
].iiBroadcastAddress
);
1529 if(pAddress
->sa_family
!= AF_INET
)
1532 nFlags
= InterfaceList
[i
].iiFlags
;
1534 if (!(nFlags
& IFF_UP
))
1539 if (nFlags
& IFF_LOOPBACK
)
1544 if (!(nFlags
& IFF_BROADCAST
))
1549 if (getnameinfo(pAddress
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0)
1554 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0)
1559 if (rpc_pmap2_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0)
1567 struct nfs_server_list
*nfs_find_local_servers(void)
1569 struct rpc_context
*rpc
;
1570 struct nfs_list_data data
= {0, NULL
};
1571 struct timeval tv_start
, tv_current
;
1574 INTERFACE_INFO InterfaceList
[20];
1575 unsigned long nBytesReturned
;
1576 int nNumInterfaces
= 0;
1578 rpc
= rpc_init_udp_context();
1584 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0)
1586 rpc_destroy_context(rpc
);
1590 if (WSAIoctl(rpc_get_fd(rpc
), SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
, sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
1595 nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
1597 for (loop
=0; loop
<3; loop
++)
1599 if (send_nfsd_probes(rpc
, InterfaceList
, nNumInterfaces
, &data
) != 0)
1601 rpc_destroy_context(rpc
);
1605 win32_gettimeofday(&tv_start
, NULL
);
1610 pfd
.fd
= rpc_get_fd(rpc
);
1611 pfd
.events
= rpc_which_events(rpc
);
1613 win32_gettimeofday(&tv_current
, NULL
);
1615 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1616 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1618 if (poll(&pfd
, 1, mpt
) < 0)
1620 free_nfs_srvr_list(data
.srvrs
);
1621 rpc_destroy_context(rpc
);
1624 if (pfd
.revents
== 0)
1629 if (rpc_service(rpc
, pfd
.revents
) < 0)
1636 rpc_destroy_context(rpc
);
1638 if (data
.status
!= 0)
1640 free_nfs_srvr_list(data
.srvrs
);
1647 static int send_nfsd_probes(struct rpc_context
*rpc
, struct ifconf
*ifc
, struct nfs_list_data
*data
)
1651 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1653 for (ptr
=(char *)(ifc
->ifc_buf
); ptr
< (char *)(ifc
->ifc_buf
) + ifc
->ifc_len
; ) {
1657 ifr
= (struct ifreq
*)ptr
;
1658 #ifdef HAVE_SOCKADDR_LEN
1659 if (ifr
->ifr_addr
.sa_len
> sizeof(struct sockaddr
)) {
1660 ptr
+= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
1662 ptr
+= sizeof(ifr
->ifr_name
) + sizeof(struct sockaddr
);
1665 ptr
+= sizeof(struct ifreq
);
1668 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) {
1671 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, ifr
) < 0) {
1674 if (!(ifr
->ifr_flags
& IFF_UP
)) {
1677 if (ifr
->ifr_flags
& IFF_LOOPBACK
) {
1680 if (!(ifr
->ifr_flags
& IFF_BROADCAST
)) {
1683 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, ifr
) < 0) {
1686 if (getnameinfo(&ifr
->ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1689 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1693 if (rpc_pmap2_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0) {
1701 struct nfs_server_list
*nfs_find_local_servers(void)
1703 struct rpc_context
*rpc
;
1704 struct nfs_list_data data
= {0, NULL
};
1705 struct timeval tv_start
, tv_current
;
1710 rpc
= rpc_init_udp_context();
1715 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1716 rpc_destroy_context(rpc
);
1721 /* get list of all interfaces */
1722 size
= sizeof(struct ifreq
);
1726 while(ifc
.ifc_len
> (size
- sizeof(struct ifreq
))) {
1731 ifc
.ifc_buf
= malloc(size
);
1732 memset(ifc
.ifc_buf
, 0, size
);
1733 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1734 rpc_destroy_context(rpc
);
1740 for (loop
=0; loop
<3; loop
++) {
1741 if (send_nfsd_probes(rpc
, &ifc
, &data
) != 0) {
1742 rpc_destroy_context(rpc
);
1747 gettimeofday(&tv_start
, NULL
);
1751 pfd
.fd
= rpc_get_fd(rpc
);
1752 pfd
.events
= rpc_which_events(rpc
);
1754 gettimeofday(&tv_current
, NULL
);
1756 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1757 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1759 if (poll(&pfd
, 1, mpt
) < 0) {
1760 free_nfs_srvr_list(data
.srvrs
);
1761 rpc_destroy_context(rpc
);
1764 if (pfd
.revents
== 0) {
1768 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1775 rpc_destroy_context(rpc
);
1777 if (data
.status
!= 0) {
1778 free_nfs_srvr_list(data
.srvrs
);