2 Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>.
18 * High level api to nfs filesystems
21 #include "win32_compat.h"
27 #include <sys/statvfs.h>
29 #include <netinet/in.h>
31 #define statvfs statfs
34 #include <sys/ioctl.h>
36 #include <sys/socket.h>
48 #include <sys/types.h>
53 #ifdef HAVE_SYS_SOCKIO_H
54 #include <sys/sockio.h>
57 #include "libnfs-zdr.h"
59 #include "libnfs-raw.h"
60 #include "libnfs-raw-mount.h"
61 #include "libnfs-raw-nfs.h"
62 #include "libnfs-private.h"
73 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
77 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
79 while (!cb_data
->is_finished
) {
81 pfd
.fd
= rpc_get_fd(rpc
);
82 pfd
.events
= rpc_which_events(rpc
);
83 if (poll(&pfd
, 1, -1) < 0) {
84 rpc_set_error(rpc
, "Poll failed");
85 cb_data
->status
= -EIO
;
88 if (rpc_service(rpc
, pfd
.revents
) < 0) {
89 rpc_set_error(rpc
, "rpc_service failed");
90 cb_data
->status
= -EIO
;
93 if (rpc_get_fd(rpc
) == -1) {
94 rpc_set_error(rpc
, "Socket closed\n");
100 static void wait_for_nfs_reply(struct nfs_context
*nfs
, struct sync_cb_data
*cb_data
)
104 while (!cb_data
->is_finished
) {
106 pfd
.fd
= nfs_get_fd(nfs
);
107 pfd
.events
= nfs_which_events(nfs
);
108 if (poll(&pfd
, 1, -1) < 0) {
109 nfs_set_error(nfs
, "Poll failed");
110 cb_data
->status
= -EIO
;
113 if (nfs_service(nfs
, pfd
.revents
) < 0) {
114 nfs_set_error(nfs
, "nfs_service failed");
115 cb_data
->status
= -EIO
;
127 * connect to the server and mount the export
129 static void mount_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
131 struct sync_cb_data
*cb_data
= private_data
;
133 cb_data
->is_finished
= 1;
134 cb_data
->status
= status
;
137 nfs_set_error(nfs
, "mount/mnt call failed with \"%s\"", (char *)data
);
142 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
144 struct sync_cb_data cb_data
;
145 struct rpc_context
*rpc
= nfs_get_rpc_context(nfs
);
147 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
149 cb_data
.is_finished
= 0;
151 if (nfs_mount_async(nfs
, server
, export
, mount_cb
, &cb_data
) != 0) {
152 nfs_set_error(nfs
, "nfs_mount_async failed");
156 wait_for_nfs_reply(nfs
, &cb_data
);
158 /* Dont want any more callbacks even if the socket is closed */
159 rpc
->connect_cb
= NULL
;
161 return cb_data
.status
;
168 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
170 struct sync_cb_data
*cb_data
= private_data
;
172 cb_data
->is_finished
= 1;
173 cb_data
->status
= status
;
176 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
180 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
183 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
185 struct sync_cb_data cb_data
;
187 cb_data
.is_finished
= 0;
188 cb_data
.return_data
= st
;
190 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
191 nfs_set_error(nfs
, "nfs_stat_async failed");
195 wait_for_nfs_reply(nfs
, &cb_data
);
197 return cb_data
.status
;
206 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
208 struct sync_cb_data
*cb_data
= private_data
;
209 struct nfsfh
*fh
, **nfsfh
;
211 cb_data
->is_finished
= 1;
212 cb_data
->status
= status
;
215 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
220 nfsfh
= cb_data
->return_data
;
224 int nfs_open(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
226 struct sync_cb_data cb_data
;
228 cb_data
.is_finished
= 0;
229 cb_data
.return_data
= nfsfh
;
231 if (nfs_open_async(nfs
, path
, mode
, open_cb
, &cb_data
) != 0) {
232 nfs_set_error(nfs
, "nfs_open_async failed");
236 wait_for_nfs_reply(nfs
, &cb_data
);
238 return cb_data
.status
;
247 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
249 struct sync_cb_data
*cb_data
= private_data
;
251 cb_data
->is_finished
= 1;
252 cb_data
->status
= status
;
255 nfs_set_error(nfs
, "pread call failed with \"%s\"", (char *)data
);
259 buffer
= cb_data
->return_data
;
260 memcpy(buffer
, (char *)data
, status
);
263 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buffer
)
265 struct sync_cb_data cb_data
;
267 cb_data
.is_finished
= 0;
268 cb_data
.return_data
= buffer
;
270 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
271 nfs_set_error(nfs
, "nfs_pread_async failed");
275 wait_for_nfs_reply(nfs
, &cb_data
);
277 return cb_data
.status
;
283 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buffer
)
285 return nfs_pread(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buffer
);
291 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
293 struct sync_cb_data
*cb_data
= private_data
;
294 cb_data
->is_finished
= 1;
295 cb_data
->status
= status
;
298 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
303 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
305 struct sync_cb_data cb_data
;
307 cb_data
.is_finished
= 0;
309 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
310 nfs_set_error(nfs
, "nfs_close_async failed");
314 wait_for_nfs_reply(nfs
, &cb_data
);
316 return cb_data
.status
;
325 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
327 struct sync_cb_data cb_data
;
329 cb_data
.is_finished
= 0;
330 cb_data
.return_data
= st
;
332 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
333 nfs_set_error(nfs
, "nfs_fstat_async failed");
337 wait_for_nfs_reply(nfs
, &cb_data
);
339 return cb_data
.status
;
346 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
348 struct sync_cb_data
*cb_data
= private_data
;
349 cb_data
->is_finished
= 1;
350 cb_data
->status
= status
;
353 nfs_set_error(nfs
, "pwrite call failed with \"%s\"", (char *)data
);
358 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buf
)
360 struct sync_cb_data cb_data
;
362 cb_data
.is_finished
= 0;
364 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
365 nfs_set_error(nfs
, "nfs_pwrite_async failed");
369 wait_for_nfs_reply(nfs
, &cb_data
);
371 return cb_data
.status
;
377 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buf
)
379 return nfs_pwrite(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buf
);
386 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
388 struct sync_cb_data
*cb_data
= private_data
;
389 cb_data
->is_finished
= 1;
390 cb_data
->status
= status
;
393 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
398 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
400 struct sync_cb_data cb_data
;
402 cb_data
.is_finished
= 0;
404 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
405 nfs_set_error(nfs
, "nfs_fsync_async failed");
409 wait_for_nfs_reply(nfs
, &cb_data
);
411 return cb_data
.status
;
420 static void ftruncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
422 struct sync_cb_data
*cb_data
= private_data
;
423 cb_data
->is_finished
= 1;
424 cb_data
->status
= status
;
427 nfs_set_error(nfs
, "ftruncate call failed with \"%s\"", (char *)data
);
432 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t length
)
434 struct sync_cb_data cb_data
;
436 cb_data
.is_finished
= 0;
438 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_cb
, &cb_data
) != 0) {
439 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
443 wait_for_nfs_reply(nfs
, &cb_data
);
445 return cb_data
.status
;
453 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
455 struct sync_cb_data
*cb_data
= private_data
;
456 cb_data
->is_finished
= 1;
457 cb_data
->status
= status
;
460 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
465 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, uint64_t length
)
467 struct sync_cb_data cb_data
;
469 cb_data
.is_finished
= 0;
471 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
472 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
476 wait_for_nfs_reply(nfs
, &cb_data
);
478 return cb_data
.status
;
488 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
490 struct sync_cb_data
*cb_data
= private_data
;
491 cb_data
->is_finished
= 1;
492 cb_data
->status
= status
;
495 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
500 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
502 struct sync_cb_data cb_data
;
504 cb_data
.is_finished
= 0;
506 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
507 nfs_set_error(nfs
, "nfs_mkdir_async failed");
511 wait_for_nfs_reply(nfs
, &cb_data
);
513 return cb_data
.status
;
523 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
525 struct sync_cb_data
*cb_data
= private_data
;
526 cb_data
->is_finished
= 1;
527 cb_data
->status
= status
;
530 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
535 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
537 struct sync_cb_data cb_data
;
539 cb_data
.is_finished
= 0;
541 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
542 nfs_set_error(nfs
, "nfs_rmdir_async failed");
546 wait_for_nfs_reply(nfs
, &cb_data
);
548 return cb_data
.status
;
556 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
558 struct sync_cb_data
*cb_data
= private_data
;
559 struct nfsfh
*fh
, **nfsfh
;
561 cb_data
->is_finished
= 1;
562 cb_data
->status
= status
;
565 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
570 nfsfh
= cb_data
->return_data
;
574 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
576 struct sync_cb_data cb_data
;
578 cb_data
.is_finished
= 0;
579 cb_data
.return_data
= nfsfh
;
581 if (nfs_creat_async(nfs
, path
, mode
, creat_cb
, &cb_data
) != 0) {
582 nfs_set_error(nfs
, "nfs_creat_async failed");
586 wait_for_nfs_reply(nfs
, &cb_data
);
588 return cb_data
.status
;
594 static void mknod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
596 struct sync_cb_data
*cb_data
= private_data
;
598 cb_data
->is_finished
= 1;
599 cb_data
->status
= status
;
602 nfs_set_error(nfs
, "mknod call failed with \"%s\"", (char *)data
);
607 int nfs_mknod(struct nfs_context
*nfs
, const char *path
, int mode
, int dev
)
609 struct sync_cb_data cb_data
;
611 cb_data
.is_finished
= 0;
613 if (nfs_mknod_async(nfs
, path
, mode
, dev
, mknod_cb
, &cb_data
) != 0) {
614 nfs_set_error(nfs
, "nfs_creat_async failed");
618 wait_for_nfs_reply(nfs
, &cb_data
);
620 return cb_data
.status
;
627 static void unlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
629 struct sync_cb_data
*cb_data
= private_data
;
631 cb_data
->is_finished
= 1;
632 cb_data
->status
= status
;
635 nfs_set_error(nfs
, "unlink call failed with \"%s\"", (char *)data
);
640 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
642 struct sync_cb_data cb_data
;
644 cb_data
.is_finished
= 0;
646 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
647 nfs_set_error(nfs
, "nfs_unlink_async failed");
651 wait_for_nfs_reply(nfs
, &cb_data
);
653 return cb_data
.status
;
661 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
663 struct sync_cb_data
*cb_data
= private_data
;
664 struct nfsdir
*dir
, **nfsdir
;
666 cb_data
->is_finished
= 1;
667 cb_data
->status
= status
;
670 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
675 nfsdir
= cb_data
->return_data
;
679 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
681 struct sync_cb_data cb_data
;
683 cb_data
.is_finished
= 0;
684 cb_data
.return_data
= nfsdir
;
686 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
687 nfs_set_error(nfs
, "nfs_opendir_async failed");
691 wait_for_nfs_reply(nfs
, &cb_data
);
693 return cb_data
.status
;
700 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
702 struct sync_cb_data
*cb_data
= private_data
;
704 cb_data
->is_finished
= 1;
705 cb_data
->status
= status
;
708 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
712 if (cb_data
->return_data
!= NULL
) {
713 memcpy(cb_data
->return_data
, data
, sizeof(uint64_t));
717 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, int whence
, uint64_t *current_offset
)
719 struct sync_cb_data cb_data
;
721 cb_data
.is_finished
= 0;
722 cb_data
.return_data
= current_offset
;
724 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
725 nfs_set_error(nfs
, "nfs_lseek_async failed");
729 wait_for_nfs_reply(nfs
, &cb_data
);
731 return cb_data
.status
;
739 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
741 struct sync_cb_data
*cb_data
= private_data
;
743 cb_data
->is_finished
= 1;
744 cb_data
->status
= status
;
747 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
751 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
754 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
756 struct sync_cb_data cb_data
;
758 cb_data
.is_finished
= 0;
759 cb_data
.return_data
= svfs
;
761 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
762 nfs_set_error(nfs
, "nfs_statvfs_async failed");
766 wait_for_nfs_reply(nfs
, &cb_data
);
768 return cb_data
.status
;
778 static void readlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
780 struct sync_cb_data
*cb_data
= private_data
;
782 cb_data
->is_finished
= 1;
783 cb_data
->status
= status
;
786 nfs_set_error(nfs
, "readlink call failed with \"%s\"", (char *)data
);
790 if (strlen(data
) > (size_t)cb_data
->return_int
) {
791 nfs_set_error(nfs
, "Too small buffer for readlink");
792 cb_data
->status
= -ENAMETOOLONG
;
796 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
799 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
801 struct sync_cb_data cb_data
;
803 cb_data
.is_finished
= 0;
804 cb_data
.return_data
= buf
;
805 cb_data
.return_int
= bufsize
;
807 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
808 nfs_set_error(nfs
, "nfs_readlink_async failed");
812 wait_for_nfs_reply(nfs
, &cb_data
);
814 return cb_data
.status
;
822 static void chmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
824 struct sync_cb_data
*cb_data
= private_data
;
826 cb_data
->is_finished
= 1;
827 cb_data
->status
= status
;
830 nfs_set_error(nfs
, "chmod call failed with \"%s\"", (char *)data
);
835 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
837 struct sync_cb_data cb_data
;
839 cb_data
.is_finished
= 0;
841 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
842 nfs_set_error(nfs
, "nfs_chmod_async failed");
846 wait_for_nfs_reply(nfs
, &cb_data
);
848 return cb_data
.status
;
857 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
859 struct sync_cb_data
*cb_data
= private_data
;
861 cb_data
->is_finished
= 1;
862 cb_data
->status
= status
;
865 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
870 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
872 struct sync_cb_data cb_data
;
874 cb_data
.is_finished
= 0;
876 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
877 nfs_set_error(nfs
, "nfs_fchmod_async failed");
881 wait_for_nfs_reply(nfs
, &cb_data
);
883 return cb_data
.status
;
892 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
894 struct sync_cb_data
*cb_data
= private_data
;
896 cb_data
->is_finished
= 1;
897 cb_data
->status
= status
;
900 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
905 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
907 struct sync_cb_data cb_data
;
909 cb_data
.is_finished
= 0;
911 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
912 nfs_set_error(nfs
, "nfs_chown_async failed");
916 wait_for_nfs_reply(nfs
, &cb_data
);
918 return cb_data
.status
;
924 static void fchown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
926 struct sync_cb_data
*cb_data
= private_data
;
928 cb_data
->is_finished
= 1;
929 cb_data
->status
= status
;
932 nfs_set_error(nfs
, "fchown call failed with \"%s\"", (char *)data
);
937 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
939 struct sync_cb_data cb_data
;
941 cb_data
.is_finished
= 0;
943 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
944 nfs_set_error(nfs
, "nfs_fchown_async failed");
948 wait_for_nfs_reply(nfs
, &cb_data
);
950 return cb_data
.status
;
958 static void utimes_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
960 struct sync_cb_data
*cb_data
= private_data
;
962 cb_data
->is_finished
= 1;
963 cb_data
->status
= status
;
966 nfs_set_error(nfs
, "utimes call failed with \"%s\"", (char *)data
);
971 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
973 struct sync_cb_data cb_data
;
975 cb_data
.is_finished
= 0;
977 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
978 nfs_set_error(nfs
, "nfs_utimes_async failed");
982 wait_for_nfs_reply(nfs
, &cb_data
);
984 return cb_data
.status
;
992 static void utime_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
994 struct sync_cb_data
*cb_data
= private_data
;
996 cb_data
->is_finished
= 1;
997 cb_data
->status
= status
;
1000 nfs_set_error(nfs
, "utime call failed with \"%s\"", (char *)data
);
1005 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
1007 struct sync_cb_data cb_data
;
1009 cb_data
.is_finished
= 0;
1011 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
1012 nfs_set_error(nfs
, "nfs_utimes_async failed");
1016 wait_for_nfs_reply(nfs
, &cb_data
);
1018 return cb_data
.status
;
1027 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1029 struct sync_cb_data
*cb_data
= private_data
;
1031 cb_data
->is_finished
= 1;
1032 cb_data
->status
= status
;
1035 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
1040 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
1042 struct sync_cb_data cb_data
;
1044 cb_data
.is_finished
= 0;
1046 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
1047 nfs_set_error(nfs
, "nfs_access_async failed");
1051 wait_for_nfs_reply(nfs
, &cb_data
);
1053 return cb_data
.status
;
1061 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1063 struct sync_cb_data
*cb_data
= private_data
;
1065 cb_data
->is_finished
= 1;
1066 cb_data
->status
= status
;
1069 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
1074 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1076 struct sync_cb_data cb_data
;
1078 cb_data
.is_finished
= 0;
1080 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
1081 nfs_set_error(nfs
, "nfs_symlink_async failed");
1085 wait_for_nfs_reply(nfs
, &cb_data
);
1087 return cb_data
.status
;
1095 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1097 struct sync_cb_data
*cb_data
= private_data
;
1099 cb_data
->is_finished
= 1;
1100 cb_data
->status
= status
;
1103 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1108 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1110 struct sync_cb_data cb_data
;
1112 cb_data
.is_finished
= 0;
1114 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1115 nfs_set_error(nfs
, "nfs_rename_async failed");
1119 wait_for_nfs_reply(nfs
, &cb_data
);
1121 return cb_data
.status
;
1129 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1131 struct sync_cb_data
*cb_data
= private_data
;
1133 cb_data
->is_finished
= 1;
1134 cb_data
->status
= status
;
1137 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1142 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1144 struct sync_cb_data cb_data
;
1146 cb_data
.is_finished
= 0;
1148 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1149 nfs_set_error(nfs
, "nfs_link_async failed");
1153 wait_for_nfs_reply(nfs
, &cb_data
);
1155 return cb_data
.status
;
1158 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1160 struct sync_cb_data
*cb_data
= private_data
;
1163 assert(mount_context
->magic
== RPC_CONTEXT_MAGIC
);
1165 cb_data
->is_finished
= 1;
1166 cb_data
->status
= status
;
1167 cb_data
->return_data
= NULL
;
1170 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1174 export
= *(exports
*)data
;
1175 while (export
!= NULL
) {
1178 new_export
= malloc(sizeof(*new_export
));
1179 memset(new_export
, 0, sizeof(*new_export
));
1180 new_export
->ex_dir
= strdup(export
->ex_dir
);
1181 new_export
->ex_next
= cb_data
->return_data
;
1183 cb_data
->return_data
= new_export
;
1185 export
= export
->ex_next
;
1189 struct exportnode
*mount_getexports(const char *server
)
1191 struct sync_cb_data cb_data
;
1192 struct rpc_context
*rpc
;
1195 cb_data
.is_finished
= 0;
1196 cb_data
.return_data
= NULL
;
1198 rpc
= rpc_init_context();
1199 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1200 rpc_destroy_context(rpc
);
1204 wait_for_reply(rpc
, &cb_data
);
1205 rpc_destroy_context(rpc
);
1207 return cb_data
.return_data
;
1210 void mount_free_export_list(struct exportnode
*exports
)
1212 struct exportnode
*tmp
;
1214 while ((tmp
= exports
)) {
1215 exports
= exports
->ex_next
;
1223 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1225 while (srv
!= NULL
) {
1226 struct nfs_server_list
*next
= srv
->next
;
1234 struct nfs_list_data
{
1236 struct nfs_server_list
*srvrs
;
1239 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1241 struct nfs_list_data
*srv_data
= private_data
;
1242 struct sockaddr
*sin
;
1244 struct nfs_server_list
*srvr
;
1246 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1248 if (status
== RPC_STATUS_CANCEL
) {
1252 srv_data
->status
= -1;
1256 sin
= rpc_get_recv_sockaddr(rpc
);
1258 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1259 srv_data
->status
= -1;
1263 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1264 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1265 srv_data
->status
= -1;
1269 /* check for dupes */
1270 for (srvr
= srv_data
->srvrs
; srvr
; srvr
= srvr
->next
) {
1271 if (!strcmp(hostdd
, srvr
->addr
)) {
1276 srvr
= malloc(sizeof(struct nfs_server_list
));
1278 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1279 srv_data
->status
= -1;
1283 srvr
->addr
= strdup(hostdd
);
1284 if (srvr
->addr
== NULL
) {
1285 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1287 srv_data
->status
= -1;
1291 srvr
->next
= srv_data
->srvrs
;
1292 srv_data
->srvrs
= srvr
;
1297 static int send_nfsd_probes(struct rpc_context
*rpc
, INTERFACE_INFO
*InterfaceList
, int numIfs
, struct nfs_list_data
*data
)
1301 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1303 for(i
= 0; i
< numIfs
; i
++)
1307 unsigned long nFlags
= 0;
1309 pAddress
= (SOCKADDR
*) & (InterfaceList
[i
].iiBroadcastAddress
);
1311 if(pAddress
->sa_family
!= AF_INET
)
1314 nFlags
= InterfaceList
[i
].iiFlags
;
1316 if (!(nFlags
& IFF_UP
))
1321 if (nFlags
& IFF_LOOPBACK
)
1326 if (!(nFlags
& IFF_BROADCAST
))
1331 if (getnameinfo(pAddress
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0)
1336 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0)
1341 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0)
1349 struct nfs_server_list
*nfs_find_local_servers(void)
1351 struct rpc_context
*rpc
;
1352 struct nfs_list_data data
= {0, NULL
};
1353 struct timeval tv_start
, tv_current
;
1356 INTERFACE_INFO InterfaceList
[20];
1357 unsigned long nBytesReturned
;
1358 int nNumInterfaces
= 0;
1360 rpc
= rpc_init_udp_context();
1366 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0)
1368 rpc_destroy_context(rpc
);
1372 if (WSAIoctl(rpc_get_fd(rpc
), SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
, sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
1377 nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
1379 for (loop
=0; loop
<3; loop
++)
1381 if (send_nfsd_probes(rpc
, InterfaceList
, nNumInterfaces
, &data
) != 0)
1383 rpc_destroy_context(rpc
);
1387 win32_gettimeofday(&tv_start
, NULL
);
1392 pfd
.fd
= rpc_get_fd(rpc
);
1393 pfd
.events
= rpc_which_events(rpc
);
1395 win32_gettimeofday(&tv_current
, NULL
);
1397 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1398 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1400 if (poll(&pfd
, 1, mpt
) < 0)
1402 free_nfs_srvr_list(data
.srvrs
);
1403 rpc_destroy_context(rpc
);
1406 if (pfd
.revents
== 0)
1411 if (rpc_service(rpc
, pfd
.revents
) < 0)
1418 rpc_destroy_context(rpc
);
1420 if (data
.status
!= 0)
1422 free_nfs_srvr_list(data
.srvrs
);
1429 static int send_nfsd_probes(struct rpc_context
*rpc
, struct ifconf
*ifc
, struct nfs_list_data
*data
)
1433 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1435 for (ptr
=(char *)(ifc
->ifc_buf
); ptr
< (char *)(ifc
->ifc_buf
) + ifc
->ifc_len
; ) {
1439 ifr
= (struct ifreq
*)ptr
;
1440 #ifdef HAVE_SOCKADDR_LEN
1441 if (ifr
->ifr_addr
.sa_len
> sizeof(struct sockaddr
)) {
1442 ptr
+= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
1444 ptr
+= sizeof(ifr
->ifr_name
) + sizeof(struct sockaddr
);
1447 ptr
+= sizeof(struct ifreq
);
1450 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) {
1453 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, ifr
) < 0) {
1456 if (!(ifr
->ifr_flags
& IFF_UP
)) {
1459 if (ifr
->ifr_flags
& IFF_LOOPBACK
) {
1462 if (!(ifr
->ifr_flags
& IFF_BROADCAST
)) {
1465 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, ifr
) < 0) {
1468 if (getnameinfo(&ifr
->ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1471 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1475 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0) {
1483 struct nfs_server_list
*nfs_find_local_servers(void)
1485 struct rpc_context
*rpc
;
1486 struct nfs_list_data data
= {0, NULL
};
1487 struct timeval tv_start
, tv_current
;
1492 rpc
= rpc_init_udp_context();
1497 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1498 rpc_destroy_context(rpc
);
1503 /* get list of all interfaces */
1504 size
= sizeof(struct ifreq
);
1508 while(ifc
.ifc_len
> (size
- sizeof(struct ifreq
))) {
1513 ifc
.ifc_buf
= malloc(size
);
1514 memset(ifc
.ifc_buf
, 0, size
);
1515 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1516 rpc_destroy_context(rpc
);
1522 for (loop
=0; loop
<3; loop
++) {
1523 if (send_nfsd_probes(rpc
, &ifc
, &data
) != 0) {
1524 rpc_destroy_context(rpc
);
1529 gettimeofday(&tv_start
, NULL
);
1533 pfd
.fd
= rpc_get_fd(rpc
);
1534 pfd
.events
= rpc_which_events(rpc
);
1536 gettimeofday(&tv_current
, NULL
);
1538 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1539 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1541 if (poll(&pfd
, 1, mpt
) < 0) {
1542 free_nfs_srvr_list(data
.srvrs
);
1543 rpc_destroy_context(rpc
);
1546 if (pfd
.revents
== 0) {
1550 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1557 rpc_destroy_context(rpc
);
1559 if (data
.status
!= 0) {
1560 free_nfs_srvr_list(data
.srvrs
);