c7698351148f502e735e581e08d0c696c990a358
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>
53 #include "libnfs-raw.h"
54 #include "libnfs-raw-mount.h"
55 #include "libnfs-raw-nfs.h"
56 #include "libnfs-private.h"
67 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
71 while (!cb_data
->is_finished
) {
73 pfd
.fd
= rpc_get_fd(rpc
);
74 pfd
.events
= rpc_which_events(rpc
);
75 if (poll(&pfd
, 1, -1) < 0) {
76 rpc_set_error(rpc
, "Poll failed");
77 cb_data
->status
= -EIO
;
80 if (rpc_service(rpc
, pfd
.revents
) < 0) {
81 rpc_set_error(rpc
, "rpc_service failed");
82 cb_data
->status
= -EIO
;
85 if (rpc_get_fd(rpc
) == -1) {
86 rpc_set_error(rpc
, "Socket closed\n");
92 static void wait_for_nfs_reply(struct nfs_context
*nfs
, struct sync_cb_data
*cb_data
)
96 while (!cb_data
->is_finished
) {
98 pfd
.fd
= nfs_get_fd(nfs
);
99 pfd
.events
= nfs_which_events(nfs
);
100 if (poll(&pfd
, 1, -1) < 0) {
101 nfs_set_error(nfs
, "Poll failed");
102 cb_data
->status
= -EIO
;
105 if (nfs_service(nfs
, pfd
.revents
) < 0) {
106 nfs_set_error(nfs
, "nfs_service failed");
107 cb_data
->status
= -EIO
;
110 if (nfs_get_fd(nfs
) == -1) {
111 char *server
= strdup(nfs_get_server(nfs
));
112 char *export
= strdup(nfs_get_export(nfs
));
114 if (nfs_mount(nfs
, server
, export
) != 0) {
115 nfs_set_error(nfs
, "Failed to reconnect to nfs server %s", nfs_get_error(nfs
));
132 * connect to the server and mount the export
134 static void mount_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
136 struct sync_cb_data
*cb_data
= private_data
;
138 cb_data
->is_finished
= 1;
139 cb_data
->status
= status
;
142 nfs_set_error(nfs
, "mount/mnt call failed with \"%s\"", (char *)data
);
147 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
149 struct sync_cb_data cb_data
;
151 cb_data
.is_finished
= 0;
153 if (nfs_mount_async(nfs
, server
, export
, mount_cb
, &cb_data
) != 0) {
154 nfs_set_error(nfs
, "nfs_mount_async failed");
158 wait_for_nfs_reply(nfs
, &cb_data
);
160 return cb_data
.status
;
167 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
169 struct sync_cb_data
*cb_data
= private_data
;
171 cb_data
->is_finished
= 1;
172 cb_data
->status
= status
;
175 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
179 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
182 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
184 struct sync_cb_data cb_data
;
186 cb_data
.is_finished
= 0;
187 cb_data
.return_data
= st
;
189 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
190 nfs_set_error(nfs
, "nfs_stat_async failed");
194 wait_for_nfs_reply(nfs
, &cb_data
);
196 return cb_data
.status
;
205 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
207 struct sync_cb_data
*cb_data
= private_data
;
208 struct nfsfh
*fh
, **nfsfh
;
210 cb_data
->is_finished
= 1;
211 cb_data
->status
= status
;
214 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
219 nfsfh
= cb_data
->return_data
;
223 int nfs_open(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
225 struct sync_cb_data cb_data
;
227 cb_data
.is_finished
= 0;
228 cb_data
.return_data
= nfsfh
;
230 if (nfs_open_async(nfs
, path
, mode
, open_cb
, &cb_data
) != 0) {
231 nfs_set_error(nfs
, "nfs_open_async failed");
235 wait_for_nfs_reply(nfs
, &cb_data
);
237 return cb_data
.status
;
246 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
248 struct sync_cb_data
*cb_data
= private_data
;
250 cb_data
->is_finished
= 1;
251 cb_data
->status
= status
;
254 nfs_set_error(nfs
, "pread call failed with \"%s\"", (char *)data
);
258 buffer
= cb_data
->return_data
;
259 memcpy(buffer
, (char *)data
, status
);
262 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, size_t count
, char *buffer
)
264 struct sync_cb_data cb_data
;
266 cb_data
.is_finished
= 0;
267 cb_data
.return_data
= buffer
;
269 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
270 nfs_set_error(nfs
, "nfs_pread_async failed");
274 wait_for_nfs_reply(nfs
, &cb_data
);
276 return cb_data
.status
;
282 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, size_t count
, char *buffer
)
284 return nfs_pread(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buffer
);
290 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
292 struct sync_cb_data
*cb_data
= private_data
;
293 cb_data
->is_finished
= 1;
294 cb_data
->status
= status
;
297 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
302 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
304 struct sync_cb_data cb_data
;
306 cb_data
.is_finished
= 0;
308 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
309 nfs_set_error(nfs
, "nfs_close_async failed");
313 wait_for_nfs_reply(nfs
, &cb_data
);
315 return cb_data
.status
;
324 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
326 struct sync_cb_data cb_data
;
328 cb_data
.is_finished
= 0;
329 cb_data
.return_data
= st
;
331 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
332 nfs_set_error(nfs
, "nfs_fstat_async failed");
336 wait_for_nfs_reply(nfs
, &cb_data
);
338 return cb_data
.status
;
345 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
347 struct sync_cb_data
*cb_data
= private_data
;
348 cb_data
->is_finished
= 1;
349 cb_data
->status
= status
;
352 nfs_set_error(nfs
, "pwrite call failed with \"%s\"", (char *)data
);
357 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, size_t count
, char *buf
)
359 struct sync_cb_data cb_data
;
361 cb_data
.is_finished
= 0;
363 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
364 nfs_set_error(nfs
, "nfs_pwrite_async failed");
368 wait_for_nfs_reply(nfs
, &cb_data
);
370 return cb_data
.status
;
376 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, size_t count
, char *buf
)
378 return nfs_pwrite(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buf
);
385 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
387 struct sync_cb_data
*cb_data
= private_data
;
388 cb_data
->is_finished
= 1;
389 cb_data
->status
= status
;
392 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
397 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
399 struct sync_cb_data cb_data
;
401 cb_data
.is_finished
= 0;
403 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
404 nfs_set_error(nfs
, "nfs_fsync_async failed");
408 wait_for_nfs_reply(nfs
, &cb_data
);
410 return cb_data
.status
;
419 static void ftruncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
421 struct sync_cb_data
*cb_data
= private_data
;
422 cb_data
->is_finished
= 1;
423 cb_data
->status
= status
;
426 nfs_set_error(nfs
, "ftruncate call failed with \"%s\"", (char *)data
);
431 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t length
)
433 struct sync_cb_data cb_data
;
435 cb_data
.is_finished
= 0;
437 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_cb
, &cb_data
) != 0) {
438 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
442 wait_for_nfs_reply(nfs
, &cb_data
);
444 return cb_data
.status
;
452 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
454 struct sync_cb_data
*cb_data
= private_data
;
455 cb_data
->is_finished
= 1;
456 cb_data
->status
= status
;
459 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
464 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, off_t length
)
466 struct sync_cb_data cb_data
;
468 cb_data
.is_finished
= 0;
470 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
471 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
475 wait_for_nfs_reply(nfs
, &cb_data
);
477 return cb_data
.status
;
487 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
489 struct sync_cb_data
*cb_data
= private_data
;
490 cb_data
->is_finished
= 1;
491 cb_data
->status
= status
;
494 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
499 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
501 struct sync_cb_data cb_data
;
503 cb_data
.is_finished
= 0;
505 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
506 nfs_set_error(nfs
, "nfs_mkdir_async failed");
510 wait_for_nfs_reply(nfs
, &cb_data
);
512 return cb_data
.status
;
522 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
524 struct sync_cb_data
*cb_data
= private_data
;
525 cb_data
->is_finished
= 1;
526 cb_data
->status
= status
;
529 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
534 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
536 struct sync_cb_data cb_data
;
538 cb_data
.is_finished
= 0;
540 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
541 nfs_set_error(nfs
, "nfs_rmdir_async failed");
545 wait_for_nfs_reply(nfs
, &cb_data
);
547 return cb_data
.status
;
555 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
557 struct sync_cb_data
*cb_data
= private_data
;
558 struct nfsfh
*fh
, **nfsfh
;
560 cb_data
->is_finished
= 1;
561 cb_data
->status
= status
;
564 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
569 nfsfh
= cb_data
->return_data
;
573 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
575 struct sync_cb_data cb_data
;
577 cb_data
.is_finished
= 0;
578 cb_data
.return_data
= nfsfh
;
580 if (nfs_creat_async(nfs
, path
, mode
, creat_cb
, &cb_data
) != 0) {
581 nfs_set_error(nfs
, "nfs_creat_async failed");
585 wait_for_nfs_reply(nfs
, &cb_data
);
587 return cb_data
.status
;
596 static void unlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
598 struct sync_cb_data
*cb_data
= private_data
;
600 cb_data
->is_finished
= 1;
601 cb_data
->status
= status
;
604 nfs_set_error(nfs
, "unlink call failed with \"%s\"", (char *)data
);
609 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
611 struct sync_cb_data cb_data
;
613 cb_data
.is_finished
= 0;
615 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
616 nfs_set_error(nfs
, "nfs_unlink_async failed");
620 wait_for_nfs_reply(nfs
, &cb_data
);
622 return cb_data
.status
;
630 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
632 struct sync_cb_data
*cb_data
= private_data
;
633 struct nfsdir
*dir
, **nfsdir
;
635 cb_data
->is_finished
= 1;
636 cb_data
->status
= status
;
639 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
644 nfsdir
= cb_data
->return_data
;
648 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
650 struct sync_cb_data cb_data
;
652 cb_data
.is_finished
= 0;
653 cb_data
.return_data
= nfsdir
;
655 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
656 nfs_set_error(nfs
, "nfs_opendir_async failed");
660 wait_for_nfs_reply(nfs
, &cb_data
);
662 return cb_data
.status
;
669 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
671 struct sync_cb_data
*cb_data
= private_data
;
673 cb_data
->is_finished
= 1;
674 cb_data
->status
= status
;
677 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
681 if (cb_data
->return_data
!= NULL
) {
682 memcpy(cb_data
->return_data
, data
, sizeof(off_t
));
686 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, int whence
, off_t
*current_offset
)
688 struct sync_cb_data cb_data
;
690 cb_data
.is_finished
= 0;
691 cb_data
.return_data
= current_offset
;
693 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
694 nfs_set_error(nfs
, "nfs_lseek_async failed");
698 wait_for_nfs_reply(nfs
, &cb_data
);
700 return cb_data
.status
;
708 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
710 struct sync_cb_data
*cb_data
= private_data
;
712 cb_data
->is_finished
= 1;
713 cb_data
->status
= status
;
716 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
720 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
722 cb_data
->return_data
=NULL
;
726 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
728 struct sync_cb_data cb_data
;
730 cb_data
.is_finished
= 0;
731 cb_data
.return_data
= svfs
;
733 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
734 nfs_set_error(nfs
, "nfs_statvfs_async failed");
738 wait_for_nfs_reply(nfs
, &cb_data
);
740 return cb_data
.status
;
750 static void readlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
752 struct sync_cb_data
*cb_data
= private_data
;
754 cb_data
->is_finished
= 1;
755 cb_data
->status
= status
;
758 nfs_set_error(nfs
, "readlink call failed with \"%s\"", (char *)data
);
762 if (strlen(data
) > (size_t)cb_data
->return_int
) {
763 nfs_set_error(nfs
, "Too small buffer for readlink");
764 cb_data
->status
= -ENAMETOOLONG
;
768 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
771 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
773 struct sync_cb_data cb_data
;
775 cb_data
.is_finished
= 0;
776 cb_data
.return_data
= buf
;
777 cb_data
.return_int
= bufsize
;
779 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
780 nfs_set_error(nfs
, "nfs_readlink_async failed");
784 wait_for_nfs_reply(nfs
, &cb_data
);
786 return cb_data
.status
;
794 static void chmod_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
, "chmod call failed with \"%s\"", (char *)data
);
807 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
809 struct sync_cb_data cb_data
;
811 cb_data
.is_finished
= 0;
813 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
814 nfs_set_error(nfs
, "nfs_chmod_async failed");
818 wait_for_nfs_reply(nfs
, &cb_data
);
820 return cb_data
.status
;
829 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
831 struct sync_cb_data
*cb_data
= private_data
;
833 cb_data
->is_finished
= 1;
834 cb_data
->status
= status
;
837 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
842 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
844 struct sync_cb_data cb_data
;
846 cb_data
.is_finished
= 0;
848 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
849 nfs_set_error(nfs
, "nfs_fchmod_async failed");
853 wait_for_nfs_reply(nfs
, &cb_data
);
855 return cb_data
.status
;
864 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
866 struct sync_cb_data
*cb_data
= private_data
;
868 cb_data
->is_finished
= 1;
869 cb_data
->status
= status
;
872 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
877 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
879 struct sync_cb_data cb_data
;
881 cb_data
.is_finished
= 0;
883 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
884 nfs_set_error(nfs
, "nfs_chown_async failed");
888 wait_for_nfs_reply(nfs
, &cb_data
);
890 return cb_data
.status
;
896 static void fchown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
898 struct sync_cb_data
*cb_data
= private_data
;
900 cb_data
->is_finished
= 1;
901 cb_data
->status
= status
;
904 nfs_set_error(nfs
, "fchown call failed with \"%s\"", (char *)data
);
909 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
911 struct sync_cb_data cb_data
;
913 cb_data
.is_finished
= 0;
915 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
916 nfs_set_error(nfs
, "nfs_fchown_async failed");
920 wait_for_nfs_reply(nfs
, &cb_data
);
922 return cb_data
.status
;
930 static void utimes_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
932 struct sync_cb_data
*cb_data
= private_data
;
934 cb_data
->is_finished
= 1;
935 cb_data
->status
= status
;
938 nfs_set_error(nfs
, "utimes call failed with \"%s\"", (char *)data
);
943 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
945 struct sync_cb_data cb_data
;
947 cb_data
.is_finished
= 0;
949 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
950 nfs_set_error(nfs
, "nfs_utimes_async failed");
954 wait_for_nfs_reply(nfs
, &cb_data
);
956 return cb_data
.status
;
964 static void utime_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
966 struct sync_cb_data
*cb_data
= private_data
;
968 cb_data
->is_finished
= 1;
969 cb_data
->status
= status
;
972 nfs_set_error(nfs
, "utime call failed with \"%s\"", (char *)data
);
977 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
979 struct sync_cb_data cb_data
;
981 cb_data
.is_finished
= 0;
983 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
984 nfs_set_error(nfs
, "nfs_utimes_async failed");
988 wait_for_nfs_reply(nfs
, &cb_data
);
990 return cb_data
.status
;
999 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1001 struct sync_cb_data
*cb_data
= private_data
;
1003 cb_data
->is_finished
= 1;
1004 cb_data
->status
= status
;
1007 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
1012 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
1014 struct sync_cb_data cb_data
;
1016 cb_data
.is_finished
= 0;
1018 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
1019 nfs_set_error(nfs
, "nfs_access_async failed");
1023 wait_for_nfs_reply(nfs
, &cb_data
);
1025 return cb_data
.status
;
1033 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1035 struct sync_cb_data
*cb_data
= private_data
;
1037 cb_data
->is_finished
= 1;
1038 cb_data
->status
= status
;
1041 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
1046 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1048 struct sync_cb_data cb_data
;
1050 cb_data
.is_finished
= 0;
1052 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
1053 nfs_set_error(nfs
, "nfs_symlink_async failed");
1057 wait_for_nfs_reply(nfs
, &cb_data
);
1059 return cb_data
.status
;
1067 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1069 struct sync_cb_data
*cb_data
= private_data
;
1071 cb_data
->is_finished
= 1;
1072 cb_data
->status
= status
;
1075 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1080 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1082 struct sync_cb_data cb_data
;
1084 cb_data
.is_finished
= 0;
1086 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1087 nfs_set_error(nfs
, "nfs_rename_async failed");
1091 wait_for_nfs_reply(nfs
, &cb_data
);
1093 return cb_data
.status
;
1101 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1103 struct sync_cb_data
*cb_data
= private_data
;
1105 cb_data
->is_finished
= 1;
1106 cb_data
->status
= status
;
1109 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1114 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1116 struct sync_cb_data cb_data
;
1118 cb_data
.is_finished
= 0;
1120 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1121 nfs_set_error(nfs
, "nfs_link_async failed");
1125 wait_for_nfs_reply(nfs
, &cb_data
);
1127 return cb_data
.status
;
1130 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1132 struct sync_cb_data
*cb_data
= private_data
;
1133 exports export
= *(exports
*)data
;
1135 cb_data
->is_finished
= 1;
1136 cb_data
->status
= status
;
1137 cb_data
->return_data
= NULL
;
1140 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1144 while (export
!= NULL
) {
1147 new_export
= malloc(sizeof(*new_export
));
1148 memset(new_export
, 0, sizeof(*new_export
));
1149 new_export
->ex_dir
= strdup(export
->ex_dir
);
1150 new_export
->ex_next
= cb_data
->return_data
;
1152 cb_data
->return_data
= new_export
;
1154 export
= export
->ex_next
;
1158 struct exportnode
*mount_getexports(const char *server
)
1160 struct sync_cb_data cb_data
;
1161 struct rpc_context
*rpc
;
1164 cb_data
.is_finished
= 0;
1165 cb_data
.return_data
= NULL
;
1167 rpc
= rpc_init_context();
1168 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1169 rpc_destroy_context(rpc
);
1173 wait_for_reply(rpc
, &cb_data
);
1174 rpc_destroy_context(rpc
);
1176 return cb_data
.return_data
;
1179 void mount_free_export_list(struct exportnode
*exports
)
1181 struct exportnode
*tmp
;
1183 while ((tmp
= exports
)) {
1184 exports
= exports
->ex_next
;
1193 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1195 while (srv
!= NULL
) {
1196 struct nfs_server_list
*next
= srv
->next
;
1204 struct nfs_list_data
{
1206 struct nfs_server_list
*srvrs
;
1209 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1211 struct nfs_list_data
*srv_data
= private_data
;
1212 struct sockaddr
*sin
;
1214 struct nfs_server_list
*srvr
;
1216 if (status
== RPC_STATUS_CANCEL
) {
1220 srv_data
->status
= -1;
1224 sin
= rpc_get_recv_sockaddr(rpc
);
1226 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1227 srv_data
->status
= -1;
1231 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1232 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1233 srv_data
->status
= -1;
1237 /* check for dupes */
1238 for (srvr
= srv_data
->srvrs
; srvr
; srvr
= srvr
->next
) {
1239 if (!strcmp(hostdd
, srvr
->addr
)) {
1244 srvr
= malloc(sizeof(struct nfs_server_list
));
1246 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1247 srv_data
->status
= -1;
1251 srvr
->addr
= strdup(hostdd
);
1252 if (srvr
->addr
== NULL
) {
1253 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1255 srv_data
->status
= -1;
1259 srvr
->next
= srv_data
->srvrs
;
1260 srv_data
->srvrs
= srvr
;
1264 static int send_nfsd_probes(struct rpc_context
*rpc
, struct ifconf
*ifc
, struct nfs_list_data
*data
)
1268 for (ptr
=(char *)(ifc
->ifc_buf
); ptr
< (char *)(ifc
->ifc_buf
) + ifc
->ifc_len
; ) {
1272 ifr
= (struct ifreq
*)ptr
;
1273 #ifdef HAVE_SOCKADDR_LEN
1274 if (ifr
->ifr_addr
.sa_len
> sizeof(struct sockaddr
)) {
1275 ptr
+= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
1277 ptr
+= sizeof(ifr
->ifr_name
) + sizeof(struct sockaddr
);
1280 ptr
+= sizeof(struct ifreq
);
1283 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) {
1286 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, ifr
) < 0) {
1289 if (!(ifr
->ifr_flags
& IFF_UP
)) {
1292 if (ifr
->ifr_flags
& IFF_LOOPBACK
) {
1295 if (!(ifr
->ifr_flags
& IFF_BROADCAST
)) {
1298 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, ifr
) < 0) {
1301 if (getnameinfo(&ifr
->ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1304 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1308 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0) {
1315 #endif/*WIN32 TODO implement this with win32api FIXME*/
1317 struct nfs_server_list
*nfs_find_local_servers(void)
1319 struct rpc_context
*rpc
;
1320 struct nfs_list_data data
= {0, NULL
};
1322 struct timeval tv_start
, tv_current
;
1327 rpc
= rpc_init_udp_context();
1332 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1333 rpc_destroy_context(rpc
);
1338 /* get list of all interfaces */
1339 size
= sizeof(struct ifreq
);
1343 while(ifc
.ifc_len
> (size
- sizeof(struct ifreq
))) {
1348 ifc
.ifc_buf
= malloc(size
);
1349 memset(ifc
.ifc_buf
, 0, size
);
1350 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1351 rpc_destroy_context(rpc
);
1357 for (loop
=0; loop
<3; loop
++) {
1358 if (send_nfsd_probes(rpc
, &ifc
, &data
) != 0) {
1359 rpc_destroy_context(rpc
);
1364 gettimeofday(&tv_start
, NULL
);
1368 pfd
.fd
= rpc_get_fd(rpc
);
1369 pfd
.events
= rpc_which_events(rpc
);
1371 gettimeofday(&tv_current
, NULL
);
1373 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1374 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1376 if (poll(&pfd
, 1, mpt
) < 0) {
1377 free_nfs_srvr_list(data
.srvrs
);
1378 rpc_destroy_context(rpc
);
1381 if (pfd
.revents
== 0) {
1385 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1392 rpc_destroy_context(rpc
);
1394 if (data
.status
!= 0) {
1395 free_nfs_srvr_list(data
.srvrs
);
1398 #endif/*WIN32 - FIXME redef it when send_nfsd_probes is implemented for win32*/