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"
26 #include <sys/statvfs.h>
28 #include <sys/ioctl.h>
30 #include <sys/socket.h>
41 #include <sys/types.h>
46 #ifdef HAVE_SYS_SOCKIO_H
47 #include <sys/sockio.h>
51 #include "libnfs-raw.h"
52 #include "libnfs-raw-mount.h"
53 #include "libnfs-raw-nfs.h"
54 #include "libnfs-private.h"
65 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
69 while (!cb_data
->is_finished
) {
71 pfd
.fd
= rpc_get_fd(rpc
);
72 pfd
.events
= rpc_which_events(rpc
);
73 if (poll(&pfd
, 1, -1) < 0) {
74 rpc_set_error(rpc
, "Poll failed");
75 cb_data
->status
= -EIO
;
78 if (rpc_service(rpc
, pfd
.revents
) < 0) {
79 rpc_set_error(rpc
, "rpc_service failed");
80 cb_data
->status
= -EIO
;
83 if (rpc_get_fd(rpc
) == -1) {
84 rpc_set_error(rpc
, "Socket closed\n");
90 static void wait_for_nfs_reply(struct nfs_context
*nfs
, struct sync_cb_data
*cb_data
)
94 while (!cb_data
->is_finished
) {
96 pfd
.fd
= nfs_get_fd(nfs
);
97 pfd
.events
= nfs_which_events(nfs
);
98 if (poll(&pfd
, 1, -1) < 0) {
99 nfs_set_error(nfs
, "Poll failed");
100 cb_data
->status
= -EIO
;
103 if (nfs_service(nfs
, pfd
.revents
) < 0) {
104 nfs_set_error(nfs
, "nfs_service failed");
105 cb_data
->status
= -EIO
;
108 if (nfs_get_fd(nfs
) == -1) {
109 char *server
= strdup(nfs_get_server(nfs
));
110 char *export
= strdup(nfs_get_export(nfs
));
112 if (nfs_mount(nfs
, server
, export
) != 0) {
113 nfs_set_error(nfs
, "Failed to reconnect to nfs server %s", nfs_get_error(nfs
));
130 * connect to the server and mount the export
132 static void mount_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
134 struct sync_cb_data
*cb_data
= private_data
;
136 cb_data
->is_finished
= 1;
137 cb_data
->status
= status
;
140 nfs_set_error(nfs
, "mount/mnt call failed with \"%s\"", (char *)data
);
145 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
147 struct sync_cb_data cb_data
;
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 return cb_data
.status
;
165 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
167 struct sync_cb_data
*cb_data
= private_data
;
169 cb_data
->is_finished
= 1;
170 cb_data
->status
= status
;
173 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
177 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
180 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
182 struct sync_cb_data cb_data
;
184 cb_data
.is_finished
= 0;
185 cb_data
.return_data
= st
;
187 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
188 nfs_set_error(nfs
, "nfs_stat_async failed");
192 wait_for_nfs_reply(nfs
, &cb_data
);
194 return cb_data
.status
;
203 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
205 struct sync_cb_data
*cb_data
= private_data
;
206 struct nfsfh
*fh
, **nfsfh
;
208 cb_data
->is_finished
= 1;
209 cb_data
->status
= status
;
212 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
217 nfsfh
= cb_data
->return_data
;
221 int nfs_open(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
223 struct sync_cb_data cb_data
;
225 cb_data
.is_finished
= 0;
226 cb_data
.return_data
= nfsfh
;
228 if (nfs_open_async(nfs
, path
, mode
, open_cb
, &cb_data
) != 0) {
229 nfs_set_error(nfs
, "nfs_open_async failed");
233 wait_for_nfs_reply(nfs
, &cb_data
);
235 return cb_data
.status
;
244 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
246 struct sync_cb_data
*cb_data
= private_data
;
248 cb_data
->is_finished
= 1;
249 cb_data
->status
= status
;
252 nfs_set_error(nfs
, "pread call failed with \"%s\"", (char *)data
);
256 buffer
= cb_data
->return_data
;
257 memcpy(buffer
, (char *)data
, status
);
260 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, size_t count
, char *buffer
)
262 struct sync_cb_data cb_data
;
264 cb_data
.is_finished
= 0;
265 cb_data
.return_data
= buffer
;
267 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
268 nfs_set_error(nfs
, "nfs_pread_async failed");
272 wait_for_nfs_reply(nfs
, &cb_data
);
274 return cb_data
.status
;
280 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, size_t count
, char *buffer
)
282 return nfs_pread(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buffer
);
288 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
290 struct sync_cb_data
*cb_data
= private_data
;
291 cb_data
->is_finished
= 1;
292 cb_data
->status
= status
;
295 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
300 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
302 struct sync_cb_data cb_data
;
304 cb_data
.is_finished
= 0;
306 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
307 nfs_set_error(nfs
, "nfs_close_async failed");
311 wait_for_nfs_reply(nfs
, &cb_data
);
313 return cb_data
.status
;
322 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
324 struct sync_cb_data cb_data
;
326 cb_data
.is_finished
= 0;
327 cb_data
.return_data
= st
;
329 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
330 nfs_set_error(nfs
, "nfs_fstat_async failed");
334 wait_for_nfs_reply(nfs
, &cb_data
);
336 return cb_data
.status
;
343 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
345 struct sync_cb_data
*cb_data
= private_data
;
346 cb_data
->is_finished
= 1;
347 cb_data
->status
= status
;
350 nfs_set_error(nfs
, "pwrite call failed with \"%s\"", (char *)data
);
355 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, size_t count
, char *buf
)
357 struct sync_cb_data cb_data
;
359 cb_data
.is_finished
= 0;
361 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
362 nfs_set_error(nfs
, "nfs_pwrite_async failed");
366 wait_for_nfs_reply(nfs
, &cb_data
);
368 return cb_data
.status
;
374 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, size_t count
, char *buf
)
376 return nfs_pwrite(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buf
);
383 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
385 struct sync_cb_data
*cb_data
= private_data
;
386 cb_data
->is_finished
= 1;
387 cb_data
->status
= status
;
390 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
395 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
397 struct sync_cb_data cb_data
;
399 cb_data
.is_finished
= 0;
401 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
402 nfs_set_error(nfs
, "nfs_fsync_async failed");
406 wait_for_nfs_reply(nfs
, &cb_data
);
408 return cb_data
.status
;
417 static void ftruncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
419 struct sync_cb_data
*cb_data
= private_data
;
420 cb_data
->is_finished
= 1;
421 cb_data
->status
= status
;
424 nfs_set_error(nfs
, "ftruncate call failed with \"%s\"", (char *)data
);
429 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t length
)
431 struct sync_cb_data cb_data
;
433 cb_data
.is_finished
= 0;
435 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_cb
, &cb_data
) != 0) {
436 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
440 wait_for_nfs_reply(nfs
, &cb_data
);
442 return cb_data
.status
;
450 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
452 struct sync_cb_data
*cb_data
= private_data
;
453 cb_data
->is_finished
= 1;
454 cb_data
->status
= status
;
457 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
462 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, off_t length
)
464 struct sync_cb_data cb_data
;
466 cb_data
.is_finished
= 0;
468 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
469 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
473 wait_for_nfs_reply(nfs
, &cb_data
);
475 return cb_data
.status
;
485 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
487 struct sync_cb_data
*cb_data
= private_data
;
488 cb_data
->is_finished
= 1;
489 cb_data
->status
= status
;
492 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
497 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
499 struct sync_cb_data cb_data
;
501 cb_data
.is_finished
= 0;
503 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
504 nfs_set_error(nfs
, "nfs_mkdir_async failed");
508 wait_for_nfs_reply(nfs
, &cb_data
);
510 return cb_data
.status
;
520 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
522 struct sync_cb_data
*cb_data
= private_data
;
523 cb_data
->is_finished
= 1;
524 cb_data
->status
= status
;
527 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
532 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
534 struct sync_cb_data cb_data
;
536 cb_data
.is_finished
= 0;
538 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
539 nfs_set_error(nfs
, "nfs_rmdir_async failed");
543 wait_for_nfs_reply(nfs
, &cb_data
);
545 return cb_data
.status
;
553 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
555 struct sync_cb_data
*cb_data
= private_data
;
556 struct nfsfh
*fh
, **nfsfh
;
558 cb_data
->is_finished
= 1;
559 cb_data
->status
= status
;
562 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
567 nfsfh
= cb_data
->return_data
;
571 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
573 struct sync_cb_data cb_data
;
575 cb_data
.is_finished
= 0;
576 cb_data
.return_data
= nfsfh
;
578 if (nfs_creat_async(nfs
, path
, mode
, creat_cb
, &cb_data
) != 0) {
579 nfs_set_error(nfs
, "nfs_creat_async failed");
583 wait_for_nfs_reply(nfs
, &cb_data
);
585 return cb_data
.status
;
594 static void unlink_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
, "unlink call failed with \"%s\"", (char *)data
);
607 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
609 struct sync_cb_data cb_data
;
611 cb_data
.is_finished
= 0;
613 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
614 nfs_set_error(nfs
, "nfs_unlink_async failed");
618 wait_for_nfs_reply(nfs
, &cb_data
);
620 return cb_data
.status
;
628 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
630 struct sync_cb_data
*cb_data
= private_data
;
631 struct nfsdir
*dir
, **nfsdir
;
633 cb_data
->is_finished
= 1;
634 cb_data
->status
= status
;
637 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
642 nfsdir
= cb_data
->return_data
;
646 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
648 struct sync_cb_data cb_data
;
650 cb_data
.is_finished
= 0;
651 cb_data
.return_data
= nfsdir
;
653 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
654 nfs_set_error(nfs
, "nfs_opendir_async failed");
658 wait_for_nfs_reply(nfs
, &cb_data
);
660 return cb_data
.status
;
667 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
669 struct sync_cb_data
*cb_data
= private_data
;
671 cb_data
->is_finished
= 1;
672 cb_data
->status
= status
;
675 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
679 if (cb_data
->return_data
!= NULL
) {
680 memcpy(cb_data
->return_data
, data
, sizeof(off_t
));
684 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, int whence
, off_t
*current_offset
)
686 struct sync_cb_data cb_data
;
688 cb_data
.is_finished
= 0;
689 cb_data
.return_data
= current_offset
;
691 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
692 nfs_set_error(nfs
, "nfs_lseek_async failed");
696 wait_for_nfs_reply(nfs
, &cb_data
);
698 return cb_data
.status
;
706 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
708 struct sync_cb_data
*cb_data
= private_data
;
710 cb_data
->is_finished
= 1;
711 cb_data
->status
= status
;
714 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
718 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
721 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
723 struct sync_cb_data cb_data
;
725 cb_data
.is_finished
= 0;
726 cb_data
.return_data
= svfs
;
728 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
729 nfs_set_error(nfs
, "nfs_statvfs_async failed");
733 wait_for_nfs_reply(nfs
, &cb_data
);
735 return cb_data
.status
;
745 static void readlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
747 struct sync_cb_data
*cb_data
= private_data
;
749 cb_data
->is_finished
= 1;
750 cb_data
->status
= status
;
753 nfs_set_error(nfs
, "readlink call failed with \"%s\"", (char *)data
);
757 if (strlen(data
) > (size_t)cb_data
->return_int
) {
758 nfs_set_error(nfs
, "Too small buffer for readlink");
759 cb_data
->status
= -ENAMETOOLONG
;
763 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
766 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
768 struct sync_cb_data cb_data
;
770 cb_data
.is_finished
= 0;
771 cb_data
.return_data
= buf
;
772 cb_data
.return_int
= bufsize
;
774 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
775 nfs_set_error(nfs
, "nfs_readlink_async failed");
779 wait_for_nfs_reply(nfs
, &cb_data
);
781 return cb_data
.status
;
789 static void chmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
791 struct sync_cb_data
*cb_data
= private_data
;
793 cb_data
->is_finished
= 1;
794 cb_data
->status
= status
;
797 nfs_set_error(nfs
, "chmod call failed with \"%s\"", (char *)data
);
802 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
804 struct sync_cb_data cb_data
;
806 cb_data
.is_finished
= 0;
808 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
809 nfs_set_error(nfs
, "nfs_chmod_async failed");
813 wait_for_nfs_reply(nfs
, &cb_data
);
815 return cb_data
.status
;
824 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
826 struct sync_cb_data
*cb_data
= private_data
;
828 cb_data
->is_finished
= 1;
829 cb_data
->status
= status
;
832 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
837 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
839 struct sync_cb_data cb_data
;
841 cb_data
.is_finished
= 0;
843 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
844 nfs_set_error(nfs
, "nfs_fchmod_async failed");
848 wait_for_nfs_reply(nfs
, &cb_data
);
850 return cb_data
.status
;
859 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
861 struct sync_cb_data
*cb_data
= private_data
;
863 cb_data
->is_finished
= 1;
864 cb_data
->status
= status
;
867 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
872 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
874 struct sync_cb_data cb_data
;
876 cb_data
.is_finished
= 0;
878 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
879 nfs_set_error(nfs
, "nfs_chown_async failed");
883 wait_for_nfs_reply(nfs
, &cb_data
);
885 return cb_data
.status
;
891 static void fchown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
893 struct sync_cb_data
*cb_data
= private_data
;
895 cb_data
->is_finished
= 1;
896 cb_data
->status
= status
;
899 nfs_set_error(nfs
, "fchown call failed with \"%s\"", (char *)data
);
904 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
906 struct sync_cb_data cb_data
;
908 cb_data
.is_finished
= 0;
910 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
911 nfs_set_error(nfs
, "nfs_fchown_async failed");
915 wait_for_nfs_reply(nfs
, &cb_data
);
917 return cb_data
.status
;
925 static void utimes_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
927 struct sync_cb_data
*cb_data
= private_data
;
929 cb_data
->is_finished
= 1;
930 cb_data
->status
= status
;
933 nfs_set_error(nfs
, "utimes call failed with \"%s\"", (char *)data
);
938 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
940 struct sync_cb_data cb_data
;
942 cb_data
.is_finished
= 0;
944 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
945 nfs_set_error(nfs
, "nfs_utimes_async failed");
949 wait_for_nfs_reply(nfs
, &cb_data
);
951 return cb_data
.status
;
959 static void utime_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
961 struct sync_cb_data
*cb_data
= private_data
;
963 cb_data
->is_finished
= 1;
964 cb_data
->status
= status
;
967 nfs_set_error(nfs
, "utime call failed with \"%s\"", (char *)data
);
972 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
974 struct sync_cb_data cb_data
;
976 cb_data
.is_finished
= 0;
978 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
979 nfs_set_error(nfs
, "nfs_utimes_async failed");
983 wait_for_nfs_reply(nfs
, &cb_data
);
985 return cb_data
.status
;
994 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
996 struct sync_cb_data
*cb_data
= private_data
;
998 cb_data
->is_finished
= 1;
999 cb_data
->status
= status
;
1002 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
1007 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
1009 struct sync_cb_data cb_data
;
1011 cb_data
.is_finished
= 0;
1013 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
1014 nfs_set_error(nfs
, "nfs_access_async failed");
1018 wait_for_nfs_reply(nfs
, &cb_data
);
1020 return cb_data
.status
;
1028 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1030 struct sync_cb_data
*cb_data
= private_data
;
1032 cb_data
->is_finished
= 1;
1033 cb_data
->status
= status
;
1036 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
1041 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1043 struct sync_cb_data cb_data
;
1045 cb_data
.is_finished
= 0;
1047 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
1048 nfs_set_error(nfs
, "nfs_symlink_async failed");
1052 wait_for_nfs_reply(nfs
, &cb_data
);
1054 return cb_data
.status
;
1062 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1064 struct sync_cb_data
*cb_data
= private_data
;
1066 cb_data
->is_finished
= 1;
1067 cb_data
->status
= status
;
1070 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1075 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1077 struct sync_cb_data cb_data
;
1079 cb_data
.is_finished
= 0;
1081 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1082 nfs_set_error(nfs
, "nfs_rename_async failed");
1086 wait_for_nfs_reply(nfs
, &cb_data
);
1088 return cb_data
.status
;
1096 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1098 struct sync_cb_data
*cb_data
= private_data
;
1100 cb_data
->is_finished
= 1;
1101 cb_data
->status
= status
;
1104 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1109 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1111 struct sync_cb_data cb_data
;
1113 cb_data
.is_finished
= 0;
1115 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1116 nfs_set_error(nfs
, "nfs_link_async failed");
1120 wait_for_nfs_reply(nfs
, &cb_data
);
1122 return cb_data
.status
;
1125 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1127 struct sync_cb_data
*cb_data
= private_data
;
1128 exports export
= *(exports
*)data
;
1130 cb_data
->is_finished
= 1;
1131 cb_data
->status
= status
;
1132 cb_data
->return_data
= NULL
;
1135 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1139 while (export
!= NULL
) {
1142 new_export
= malloc(sizeof(*new_export
));
1143 memset(new_export
, 0, sizeof(*new_export
));
1144 new_export
->ex_dir
= strdup(export
->ex_dir
);
1145 new_export
->ex_next
= cb_data
->return_data
;
1147 cb_data
->return_data
= new_export
;
1149 export
= export
->ex_next
;
1153 struct exportnode
*mount_getexports(const char *server
)
1155 struct sync_cb_data cb_data
;
1156 struct rpc_context
*rpc
;
1159 cb_data
.is_finished
= 0;
1160 cb_data
.return_data
= NULL
;
1162 rpc
= rpc_init_context();
1163 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1164 rpc_destroy_context(rpc
);
1168 wait_for_reply(rpc
, &cb_data
);
1169 rpc_destroy_context(rpc
);
1171 return cb_data
.return_data
;
1174 void mount_free_export_list(struct exportnode
*exports
)
1176 struct exportnode
*tmp
;
1178 while ((tmp
= exports
)) {
1179 exports
= exports
->ex_next
;
1187 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1189 while (srv
!= NULL
) {
1190 struct nfs_server_list
*next
= srv
->next
;
1198 struct nfs_list_data
{
1200 struct nfs_server_list
*srvrs
;
1203 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1205 struct nfs_list_data
*srv_data
= private_data
;
1206 struct sockaddr
*sin
;
1208 struct nfs_server_list
*srvr
;
1210 if (status
== RPC_STATUS_CANCEL
) {
1214 srv_data
->status
= -1;
1218 sin
= rpc_get_recv_sockaddr(rpc
);
1220 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1221 srv_data
->status
= -1;
1225 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1226 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1227 srv_data
->status
= -1;
1231 /* check for dupes */
1232 for (srvr
= srv_data
->srvrs
; srvr
; srvr
= srvr
->next
) {
1233 if (!strcmp(hostdd
, srvr
->addr
)) {
1238 srvr
= malloc(sizeof(struct nfs_server_list
));
1240 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1241 srv_data
->status
= -1;
1245 srvr
->addr
= strdup(hostdd
);
1246 if (srvr
->addr
== NULL
) {
1247 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1249 srv_data
->status
= -1;
1253 srvr
->next
= srv_data
->srvrs
;
1254 srv_data
->srvrs
= srvr
;
1259 static int send_nfsd_probes(struct rpc_context
*rpc
, INTERFACE_INFO
*InterfaceList
, int numIfs
, struct nfs_list_data
*data
)
1263 for(i
= 0; i
< numIfs
; i
++)
1267 unsigned long nFlags
= 0;
1269 pAddress
= (SOCKADDR
*) & (InterfaceList
[i
].iiBroadcastAddress
);
1271 if(pAddress
->sa_family
!= AF_INET
)
1274 nFlags
= InterfaceList
[i
].iiFlags
;
1276 if (!(nFlags
& IFF_UP
))
1281 if (nFlags
& IFF_LOOPBACK
)
1286 if (!(nFlags
& IFF_BROADCAST
))
1291 if (getnameinfo(pAddress
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0)
1296 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0)
1301 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0)
1309 struct nfs_server_list
*nfs_find_local_servers(void)
1311 struct rpc_context
*rpc
;
1312 struct nfs_list_data data
= {0, NULL
};
1313 struct timeval tv_start
, tv_current
;
1316 INTERFACE_INFO InterfaceList
[20];
1317 unsigned long nBytesReturned
;
1318 int nNumInterfaces
= 0;
1320 rpc
= rpc_init_udp_context();
1326 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0)
1328 rpc_destroy_context(rpc
);
1332 if (WSAIoctl(rpc_get_fd(rpc
), SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
, sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
1337 nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
1339 for (loop
=0; loop
<3; loop
++)
1341 if (send_nfsd_probes(rpc
, InterfaceList
, nNumInterfaces
, &data
) != 0)
1343 rpc_destroy_context(rpc
);
1347 win32_gettimeofday(&tv_start
, NULL
);
1352 pfd
.fd
= rpc_get_fd(rpc
);
1353 pfd
.events
= rpc_which_events(rpc
);
1355 win32_gettimeofday(&tv_current
, NULL
);
1357 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1358 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1360 if (poll(&pfd
, 1, mpt
) < 0)
1362 free_nfs_srvr_list(data
.srvrs
);
1363 rpc_destroy_context(rpc
);
1366 if (pfd
.revents
== 0)
1371 if (rpc_service(rpc
, pfd
.revents
) < 0)
1378 rpc_destroy_context(rpc
);
1380 if (data
.status
!= 0)
1382 free_nfs_srvr_list(data
.srvrs
);
1389 static int send_nfsd_probes(struct rpc_context
*rpc
, struct ifconf
*ifc
, struct nfs_list_data
*data
)
1393 for (ptr
=(char *)(ifc
->ifc_buf
); ptr
< (char *)(ifc
->ifc_buf
) + ifc
->ifc_len
; ) {
1397 ifr
= (struct ifreq
*)ptr
;
1398 #ifdef HAVE_SOCKADDR_LEN
1399 if (ifr
->ifr_addr
.sa_len
> sizeof(struct sockaddr
)) {
1400 ptr
+= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
1402 ptr
+= sizeof(ifr
->ifr_name
) + sizeof(struct sockaddr
);
1405 ptr
+= sizeof(struct ifreq
);
1408 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) {
1411 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, ifr
) < 0) {
1414 if (!(ifr
->ifr_flags
& IFF_UP
)) {
1417 if (ifr
->ifr_flags
& IFF_LOOPBACK
) {
1420 if (!(ifr
->ifr_flags
& IFF_BROADCAST
)) {
1423 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, ifr
) < 0) {
1426 if (getnameinfo(&ifr
->ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1429 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1433 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0) {
1441 struct nfs_server_list
*nfs_find_local_servers(void)
1443 struct rpc_context
*rpc
;
1444 struct nfs_list_data data
= {0, NULL
};
1445 struct timeval tv_start
, tv_current
;
1450 rpc
= rpc_init_udp_context();
1455 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1456 rpc_destroy_context(rpc
);
1461 /* get list of all interfaces */
1462 size
= sizeof(struct ifreq
);
1466 while(ifc
.ifc_len
> (size
- sizeof(struct ifreq
))) {
1471 ifc
.ifc_buf
= malloc(size
);
1472 memset(ifc
.ifc_buf
, 0, size
);
1473 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1474 rpc_destroy_context(rpc
);
1480 for (loop
=0; loop
<3; loop
++) {
1481 if (send_nfsd_probes(rpc
, &ifc
, &data
) != 0) {
1482 rpc_destroy_context(rpc
);
1487 gettimeofday(&tv_start
, NULL
);
1491 pfd
.fd
= rpc_get_fd(rpc
);
1492 pfd
.events
= rpc_which_events(rpc
);
1494 gettimeofday(&tv_current
, NULL
);
1496 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1497 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1499 if (poll(&pfd
, 1, mpt
) < 0) {
1500 free_nfs_srvr_list(data
.srvrs
);
1501 rpc_destroy_context(rpc
);
1504 if (pfd
.revents
== 0) {
1508 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1515 rpc_destroy_context(rpc
);
1517 if (data
.status
!= 0) {
1518 free_nfs_srvr_list(data
.srvrs
);