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 #ifdef HAVE_SYS_TIME_H
93 #include "libnfs-zdr.h"
95 #include "libnfs-raw.h"
96 #include "libnfs-raw-mount.h"
97 #include "libnfs-raw-nfs.h"
98 #include "libnfs-private.h"
100 struct sync_cb_data
{
110 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
114 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
116 while (!cb_data
->is_finished
) {
118 pfd
.fd
= rpc_get_fd(rpc
);
119 pfd
.events
= rpc_which_events(rpc
);
120 if (poll(&pfd
, 1, -1) < 0) {
121 rpc_set_error(rpc
, "Poll failed");
122 cb_data
->status
= -EIO
;
125 if (rpc_service(rpc
, pfd
.revents
) < 0) {
126 rpc_set_error(rpc
, "rpc_service failed");
127 cb_data
->status
= -EIO
;
130 if (rpc_get_fd(rpc
) == -1) {
131 rpc_set_error(rpc
, "Socket closed\n");
137 static void wait_for_nfs_reply(struct nfs_context
*nfs
, struct sync_cb_data
*cb_data
)
141 while (!cb_data
->is_finished
) {
143 pfd
.fd
= nfs_get_fd(nfs
);
144 pfd
.events
= nfs_which_events(nfs
);
145 if (poll(&pfd
, 1, -1) < 0) {
146 nfs_set_error(nfs
, "Poll failed");
147 cb_data
->status
= -EIO
;
150 if (nfs_service(nfs
, pfd
.revents
) < 0) {
151 nfs_set_error(nfs
, "nfs_service failed");
152 cb_data
->status
= -EIO
;
164 * connect to the server and mount the export
166 static void mount_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
168 struct sync_cb_data
*cb_data
= private_data
;
170 cb_data
->is_finished
= 1;
171 cb_data
->status
= status
;
174 nfs_set_error(nfs
, "mount/mnt call failed with \"%s\"", (char *)data
);
179 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
181 struct sync_cb_data cb_data
;
182 struct rpc_context
*rpc
= nfs_get_rpc_context(nfs
);
184 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
186 cb_data
.is_finished
= 0;
188 if (nfs_mount_async(nfs
, server
, export
, mount_cb
, &cb_data
) != 0) {
189 nfs_set_error(nfs
, "nfs_mount_async failed");
193 wait_for_nfs_reply(nfs
, &cb_data
);
195 /* Dont want any more callbacks even if the socket is closed */
196 rpc
->connect_cb
= NULL
;
198 return cb_data
.status
;
205 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
207 struct sync_cb_data
*cb_data
= private_data
;
209 cb_data
->is_finished
= 1;
210 cb_data
->status
= status
;
213 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
217 memcpy(cb_data
->return_data
, data
, sizeof(struct __stat64
));
219 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
224 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct __stat64
*st
)
226 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
229 struct sync_cb_data cb_data
;
231 cb_data
.is_finished
= 0;
232 cb_data
.return_data
= st
;
234 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
235 nfs_set_error(nfs
, "nfs_stat_async failed");
239 wait_for_nfs_reply(nfs
, &cb_data
);
241 return cb_data
.status
;
244 static void stat64_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
, "stat call failed with \"%s\"", (char *)data
);
255 memcpy(cb_data
->return_data
, data
, sizeof(struct nfs_stat_64
));
258 int nfs_stat64(struct nfs_context
*nfs
, const char *path
, struct nfs_stat_64
*st
)
260 struct sync_cb_data cb_data
;
262 cb_data
.is_finished
= 0;
263 cb_data
.return_data
= st
;
265 if (nfs_stat64_async(nfs
, path
, stat64_cb
, &cb_data
) != 0) {
266 nfs_set_error(nfs
, "nfs_stat64_async failed");
270 wait_for_nfs_reply(nfs
, &cb_data
);
272 return cb_data
.status
;
275 int nfs_lstat64(struct nfs_context
*nfs
, const char *path
, struct nfs_stat_64
*st
)
277 struct sync_cb_data cb_data
;
279 cb_data
.is_finished
= 0;
280 cb_data
.return_data
= st
;
282 if (nfs_lstat64_async(nfs
, path
, stat64_cb
, &cb_data
) != 0) {
283 nfs_set_error(nfs
, "nfs_lstat64_async failed");
287 wait_for_nfs_reply(nfs
, &cb_data
);
289 return cb_data
.status
;
295 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
297 struct sync_cb_data
*cb_data
= private_data
;
298 struct nfsfh
*fh
, **nfsfh
;
300 cb_data
->is_finished
= 1;
301 cb_data
->status
= status
;
304 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
309 nfsfh
= cb_data
->return_data
;
313 int nfs_open(struct nfs_context
*nfs
, const char *path
, int flags
, struct nfsfh
**nfsfh
)
315 struct sync_cb_data cb_data
;
317 cb_data
.is_finished
= 0;
318 cb_data
.return_data
= nfsfh
;
320 if (nfs_open_async(nfs
, path
, flags
, open_cb
, &cb_data
) != 0) {
321 nfs_set_error(nfs
, "nfs_open_async failed");
325 wait_for_nfs_reply(nfs
, &cb_data
);
327 return cb_data
.status
;
333 static void chdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
335 struct sync_cb_data
*cb_data
= private_data
;
337 cb_data
->is_finished
= 1;
338 cb_data
->status
= status
;
341 nfs_set_error(nfs
, "chdir call failed with \"%s\"", (char *)data
);
346 int nfs_chdir(struct nfs_context
*nfs
, const char *path
)
348 struct sync_cb_data cb_data
;
350 cb_data
.is_finished
= 0;
352 if (nfs_chdir_async(nfs
, path
, chdir_cb
, &cb_data
) != 0) {
353 nfs_set_error(nfs
, "nfs_chdir_async failed with %s",
358 wait_for_nfs_reply(nfs
, &cb_data
);
360 return cb_data
.status
;
368 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
370 struct sync_cb_data
*cb_data
= private_data
;
372 cb_data
->is_finished
= 1;
373 cb_data
->status
= status
;
376 nfs_set_error(nfs
, "%s call failed with \"%s\"", cb_data
->call
, (char *)data
);
380 buffer
= cb_data
->return_data
;
381 memcpy(buffer
, (char *)data
, status
);
384 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buffer
)
386 struct sync_cb_data cb_data
;
388 cb_data
.is_finished
= 0;
389 cb_data
.return_data
= buffer
;
390 cb_data
.call
= "pread";
392 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
393 nfs_set_error(nfs
, "nfs_pread_async failed");
397 wait_for_nfs_reply(nfs
, &cb_data
);
399 return cb_data
.status
;
405 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buffer
)
407 struct sync_cb_data cb_data
;
409 cb_data
.is_finished
= 0;
410 cb_data
.return_data
= buffer
;
411 cb_data
.call
= "read";
413 if (nfs_read_async(nfs
, nfsfh
, count
, pread_cb
, &cb_data
) != 0) {
414 nfs_set_error(nfs
, "nfs_read_async failed");
418 wait_for_nfs_reply(nfs
, &cb_data
);
420 return cb_data
.status
;
426 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
428 struct sync_cb_data
*cb_data
= private_data
;
429 cb_data
->is_finished
= 1;
430 cb_data
->status
= status
;
433 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
438 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
440 struct sync_cb_data cb_data
;
442 cb_data
.is_finished
= 0;
444 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
445 nfs_set_error(nfs
, "nfs_close_async failed");
449 wait_for_nfs_reply(nfs
, &cb_data
);
451 return cb_data
.status
;
460 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
462 struct sync_cb_data cb_data
;
464 cb_data
.is_finished
= 0;
465 cb_data
.return_data
= st
;
467 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
468 nfs_set_error(nfs
, "nfs_fstat_async failed");
472 wait_for_nfs_reply(nfs
, &cb_data
);
474 return cb_data
.status
;
480 int nfs_fstat64(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct nfs_stat_64
*st
)
482 struct sync_cb_data cb_data
;
484 cb_data
.is_finished
= 0;
485 cb_data
.return_data
= st
;
487 if (nfs_fstat64_async(nfs
, nfsfh
, stat64_cb
, &cb_data
) != 0) {
488 nfs_set_error(nfs
, "nfs_fstat64_async failed");
492 wait_for_nfs_reply(nfs
, &cb_data
);
494 return cb_data
.status
;
501 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
503 struct sync_cb_data
*cb_data
= private_data
;
504 cb_data
->is_finished
= 1;
505 cb_data
->status
= status
;
508 nfs_set_error(nfs
, "%s call failed with \"%s\"", cb_data
->call
, (char *)data
);
511 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t offset
, uint64_t count
, char *buf
)
513 struct sync_cb_data cb_data
;
515 cb_data
.is_finished
= 0;
516 cb_data
.call
= "pwrite";
518 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
519 nfs_set_error(nfs
, "nfs_pwrite_async failed");
523 wait_for_nfs_reply(nfs
, &cb_data
);
525 return cb_data
.status
;
531 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t count
, char *buf
)
533 struct sync_cb_data cb_data
;
535 cb_data
.is_finished
= 0;
536 cb_data
.call
= "write";
538 if (nfs_write_async(nfs
, nfsfh
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
539 nfs_set_error(nfs
, "nfs_write_async failed");
543 wait_for_nfs_reply(nfs
, &cb_data
);
545 return cb_data
.status
;
552 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
554 struct sync_cb_data
*cb_data
= private_data
;
555 cb_data
->is_finished
= 1;
556 cb_data
->status
= status
;
559 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
564 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
566 struct sync_cb_data cb_data
;
568 cb_data
.is_finished
= 0;
570 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
571 nfs_set_error(nfs
, "nfs_fsync_async failed");
575 wait_for_nfs_reply(nfs
, &cb_data
);
577 return cb_data
.status
;
586 static void ftruncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
588 struct sync_cb_data
*cb_data
= private_data
;
589 cb_data
->is_finished
= 1;
590 cb_data
->status
= status
;
593 nfs_set_error(nfs
, "ftruncate call failed with \"%s\"", (char *)data
);
598 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, uint64_t length
)
600 struct sync_cb_data cb_data
;
602 cb_data
.is_finished
= 0;
604 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_cb
, &cb_data
) != 0) {
605 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
609 wait_for_nfs_reply(nfs
, &cb_data
);
611 return cb_data
.status
;
619 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
621 struct sync_cb_data
*cb_data
= private_data
;
622 cb_data
->is_finished
= 1;
623 cb_data
->status
= status
;
626 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
631 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, uint64_t length
)
633 struct sync_cb_data cb_data
;
635 cb_data
.is_finished
= 0;
637 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
638 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
642 wait_for_nfs_reply(nfs
, &cb_data
);
644 return cb_data
.status
;
654 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
656 struct sync_cb_data
*cb_data
= private_data
;
657 cb_data
->is_finished
= 1;
658 cb_data
->status
= status
;
661 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
666 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
668 struct sync_cb_data cb_data
;
670 cb_data
.is_finished
= 0;
672 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
673 nfs_set_error(nfs
, "nfs_mkdir_async failed");
677 wait_for_nfs_reply(nfs
, &cb_data
);
679 return cb_data
.status
;
689 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
691 struct sync_cb_data
*cb_data
= private_data
;
692 cb_data
->is_finished
= 1;
693 cb_data
->status
= status
;
696 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
701 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
703 struct sync_cb_data cb_data
;
705 cb_data
.is_finished
= 0;
707 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
708 nfs_set_error(nfs
, "nfs_rmdir_async failed");
712 wait_for_nfs_reply(nfs
, &cb_data
);
714 return cb_data
.status
;
722 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
724 struct sync_cb_data
*cb_data
= private_data
;
725 struct nfsfh
*fh
, **nfsfh
;
727 cb_data
->is_finished
= 1;
728 cb_data
->status
= status
;
731 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
736 nfsfh
= cb_data
->return_data
;
740 int nfs_create(struct nfs_context
*nfs
, const char *path
, int flags
, int mode
, struct nfsfh
**nfsfh
)
742 struct sync_cb_data cb_data
;
744 cb_data
.is_finished
= 0;
745 cb_data
.return_data
= nfsfh
;
747 if (nfs_create_async(nfs
, path
, flags
, mode
, creat_cb
, &cb_data
) != 0) {
748 nfs_set_error(nfs
, "nfs_create_async failed");
752 wait_for_nfs_reply(nfs
, &cb_data
);
754 return cb_data
.status
;
757 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
759 return nfs_create(nfs
, path
, 0, mode
, nfsfh
);
765 static void mknod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
767 struct sync_cb_data
*cb_data
= private_data
;
769 cb_data
->is_finished
= 1;
770 cb_data
->status
= status
;
773 nfs_set_error(nfs
, "mknod call failed with \"%s\"", (char *)data
);
778 int nfs_mknod(struct nfs_context
*nfs
, const char *path
, int mode
, int dev
)
780 struct sync_cb_data cb_data
;
782 cb_data
.is_finished
= 0;
784 if (nfs_mknod_async(nfs
, path
, mode
, dev
, mknod_cb
, &cb_data
) != 0) {
785 nfs_set_error(nfs
, "nfs_creat_async failed");
789 wait_for_nfs_reply(nfs
, &cb_data
);
791 return cb_data
.status
;
798 static void unlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
800 struct sync_cb_data
*cb_data
= private_data
;
802 cb_data
->is_finished
= 1;
803 cb_data
->status
= status
;
806 nfs_set_error(nfs
, "unlink call failed with \"%s\"", (char *)data
);
811 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
813 struct sync_cb_data cb_data
;
815 cb_data
.is_finished
= 0;
817 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
818 nfs_set_error(nfs
, "nfs_unlink_async failed");
822 wait_for_nfs_reply(nfs
, &cb_data
);
824 return cb_data
.status
;
832 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
834 struct sync_cb_data
*cb_data
= private_data
;
835 struct nfsdir
*dir
, **nfsdir
;
837 cb_data
->is_finished
= 1;
838 cb_data
->status
= status
;
841 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
846 nfsdir
= cb_data
->return_data
;
850 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
852 struct sync_cb_data cb_data
;
854 cb_data
.is_finished
= 0;
855 cb_data
.return_data
= nfsdir
;
857 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
858 nfs_set_error(nfs
, "nfs_opendir_async failed");
862 wait_for_nfs_reply(nfs
, &cb_data
);
864 return cb_data
.status
;
871 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
873 struct sync_cb_data
*cb_data
= private_data
;
875 cb_data
->is_finished
= 1;
876 cb_data
->status
= status
;
879 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
883 if (cb_data
->return_data
!= NULL
) {
884 memcpy(cb_data
->return_data
, data
, sizeof(uint64_t));
888 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int64_t offset
, int whence
, uint64_t *current_offset
)
890 struct sync_cb_data cb_data
;
892 cb_data
.is_finished
= 0;
893 cb_data
.return_data
= current_offset
;
895 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
896 nfs_set_error(nfs
, "nfs_lseek_async failed");
900 wait_for_nfs_reply(nfs
, &cb_data
);
902 return cb_data
.status
;
910 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
912 struct sync_cb_data
*cb_data
= private_data
;
914 cb_data
->is_finished
= 1;
915 cb_data
->status
= status
;
918 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
922 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
925 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
927 struct sync_cb_data cb_data
;
929 cb_data
.is_finished
= 0;
930 cb_data
.return_data
= svfs
;
932 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
933 nfs_set_error(nfs
, "nfs_statvfs_async failed");
937 wait_for_nfs_reply(nfs
, &cb_data
);
939 return cb_data
.status
;
949 static void readlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
951 struct sync_cb_data
*cb_data
= private_data
;
953 cb_data
->is_finished
= 1;
954 cb_data
->status
= status
;
957 nfs_set_error(nfs
, "readlink call failed with \"%s\"", (char *)data
);
961 if (strlen(data
) > (size_t)cb_data
->return_int
) {
962 nfs_set_error(nfs
, "Too small buffer for readlink");
963 cb_data
->status
= -ENAMETOOLONG
;
967 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
970 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
972 struct sync_cb_data cb_data
;
974 cb_data
.is_finished
= 0;
975 cb_data
.return_data
= buf
;
976 cb_data
.return_int
= bufsize
;
978 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
979 nfs_set_error(nfs
, "nfs_readlink_async failed");
983 wait_for_nfs_reply(nfs
, &cb_data
);
985 return cb_data
.status
;
993 static void chmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
995 struct sync_cb_data
*cb_data
= private_data
;
997 cb_data
->is_finished
= 1;
998 cb_data
->status
= status
;
1001 nfs_set_error(nfs
, "chmod call failed with \"%s\"", (char *)data
);
1006 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
1008 struct sync_cb_data cb_data
;
1010 cb_data
.is_finished
= 0;
1012 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
1013 nfs_set_error(nfs
, "nfs_chmod_async failed");
1017 wait_for_nfs_reply(nfs
, &cb_data
);
1019 return cb_data
.status
;
1022 int nfs_lchmod(struct nfs_context
*nfs
, const char *path
, int mode
)
1024 struct sync_cb_data cb_data
;
1026 cb_data
.is_finished
= 0;
1028 if (nfs_lchmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
1029 nfs_set_error(nfs
, "nfs_lchmod_async failed");
1033 wait_for_nfs_reply(nfs
, &cb_data
);
1035 return cb_data
.status
;
1044 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1046 struct sync_cb_data
*cb_data
= private_data
;
1048 cb_data
->is_finished
= 1;
1049 cb_data
->status
= status
;
1052 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
1057 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
1059 struct sync_cb_data cb_data
;
1061 cb_data
.is_finished
= 0;
1063 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
1064 nfs_set_error(nfs
, "nfs_fchmod_async failed");
1068 wait_for_nfs_reply(nfs
, &cb_data
);
1070 return cb_data
.status
;
1079 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1081 struct sync_cb_data
*cb_data
= private_data
;
1083 cb_data
->is_finished
= 1;
1084 cb_data
->status
= status
;
1087 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
1092 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
1094 struct sync_cb_data cb_data
;
1096 cb_data
.is_finished
= 0;
1098 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
1099 nfs_set_error(nfs
, "nfs_chown_async failed");
1103 wait_for_nfs_reply(nfs
, &cb_data
);
1105 return cb_data
.status
;
1111 int nfs_lchown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
1113 struct sync_cb_data cb_data
;
1115 cb_data
.is_finished
= 0;
1117 if (nfs_lchown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
1118 nfs_set_error(nfs
, "nfs_lchown_async failed");
1122 wait_for_nfs_reply(nfs
, &cb_data
);
1124 return cb_data
.status
;
1130 static void fchown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1132 struct sync_cb_data
*cb_data
= private_data
;
1134 cb_data
->is_finished
= 1;
1135 cb_data
->status
= status
;
1138 nfs_set_error(nfs
, "fchown call failed with \"%s\"", (char *)data
);
1143 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
1145 struct sync_cb_data cb_data
;
1147 cb_data
.is_finished
= 0;
1149 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
1150 nfs_set_error(nfs
, "nfs_fchown_async failed");
1154 wait_for_nfs_reply(nfs
, &cb_data
);
1156 return cb_data
.status
;
1164 static void utimes_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1166 struct sync_cb_data
*cb_data
= private_data
;
1168 cb_data
->is_finished
= 1;
1169 cb_data
->status
= status
;
1172 nfs_set_error(nfs
, "utimes call failed with \"%s\"", (char *)data
);
1177 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
1179 struct sync_cb_data cb_data
;
1181 cb_data
.is_finished
= 0;
1183 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
1184 nfs_set_error(nfs
, "nfs_utimes_async failed");
1188 wait_for_nfs_reply(nfs
, &cb_data
);
1190 return cb_data
.status
;
1193 int nfs_lutimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
1195 struct sync_cb_data cb_data
;
1197 cb_data
.is_finished
= 0;
1199 if (nfs_lutimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
1200 nfs_set_error(nfs
, "nfs_lutimes_async failed");
1204 wait_for_nfs_reply(nfs
, &cb_data
);
1206 return cb_data
.status
;
1214 static void utime_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1216 struct sync_cb_data
*cb_data
= private_data
;
1218 cb_data
->is_finished
= 1;
1219 cb_data
->status
= status
;
1222 nfs_set_error(nfs
, "utime call failed with \"%s\"", (char *)data
);
1227 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
1229 struct sync_cb_data cb_data
;
1231 cb_data
.is_finished
= 0;
1233 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
1234 nfs_set_error(nfs
, "nfs_utimes_async failed");
1238 wait_for_nfs_reply(nfs
, &cb_data
);
1240 return cb_data
.status
;
1249 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1251 struct sync_cb_data
*cb_data
= private_data
;
1253 cb_data
->is_finished
= 1;
1254 cb_data
->status
= status
;
1257 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
1262 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
1264 struct sync_cb_data cb_data
;
1266 cb_data
.is_finished
= 0;
1268 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
1269 nfs_set_error(nfs
, "nfs_access_async failed");
1273 wait_for_nfs_reply(nfs
, &cb_data
);
1275 return cb_data
.status
;
1283 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1285 struct sync_cb_data
*cb_data
= private_data
;
1287 cb_data
->is_finished
= 1;
1288 cb_data
->status
= status
;
1291 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
1296 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1298 struct sync_cb_data cb_data
;
1300 cb_data
.is_finished
= 0;
1302 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
1303 nfs_set_error(nfs
, "nfs_symlink_async failed");
1307 wait_for_nfs_reply(nfs
, &cb_data
);
1309 return cb_data
.status
;
1317 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1319 struct sync_cb_data
*cb_data
= private_data
;
1321 cb_data
->is_finished
= 1;
1322 cb_data
->status
= status
;
1325 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1330 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1332 struct sync_cb_data cb_data
;
1334 cb_data
.is_finished
= 0;
1336 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1337 nfs_set_error(nfs
, "nfs_rename_async failed");
1341 wait_for_nfs_reply(nfs
, &cb_data
);
1343 return cb_data
.status
;
1351 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1353 struct sync_cb_data
*cb_data
= private_data
;
1355 cb_data
->is_finished
= 1;
1356 cb_data
->status
= status
;
1359 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1364 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1366 struct sync_cb_data cb_data
;
1368 cb_data
.is_finished
= 0;
1370 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1371 nfs_set_error(nfs
, "nfs_link_async failed");
1375 wait_for_nfs_reply(nfs
, &cb_data
);
1377 return cb_data
.status
;
1380 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1382 struct sync_cb_data
*cb_data
= private_data
;
1385 assert(mount_context
->magic
== RPC_CONTEXT_MAGIC
);
1387 cb_data
->is_finished
= 1;
1388 cb_data
->status
= status
;
1389 cb_data
->return_data
= NULL
;
1392 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1396 export
= *(exports
*)data
;
1397 while (export
!= NULL
) {
1400 new_export
= malloc(sizeof(*new_export
));
1401 memset(new_export
, 0, sizeof(*new_export
));
1402 new_export
->ex_dir
= strdup(export
->ex_dir
);
1403 new_export
->ex_next
= cb_data
->return_data
;
1405 cb_data
->return_data
= new_export
;
1407 export
= export
->ex_next
;
1411 struct exportnode
*mount_getexports(const char *server
)
1413 struct sync_cb_data cb_data
;
1414 struct rpc_context
*rpc
;
1417 cb_data
.is_finished
= 0;
1418 cb_data
.return_data
= NULL
;
1420 rpc
= rpc_init_context();
1421 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1422 rpc_destroy_context(rpc
);
1426 wait_for_reply(rpc
, &cb_data
);
1427 rpc_destroy_context(rpc
);
1429 return cb_data
.return_data
;
1432 void mount_free_export_list(struct exportnode
*exports
)
1434 struct exportnode
*tmp
;
1436 while ((tmp
= exports
)) {
1437 exports
= exports
->ex_next
;
1445 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1447 while (srv
!= NULL
) {
1448 struct nfs_server_list
*next
= srv
->next
;
1456 struct nfs_list_data
{
1458 struct nfs_server_list
*srvrs
;
1461 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1463 struct nfs_list_data
*srv_data
= private_data
;
1464 struct sockaddr
*sin
;
1466 struct nfs_server_list
*srvr
;
1468 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1470 if (status
== RPC_STATUS_CANCEL
) {
1474 srv_data
->status
= -1;
1478 sin
= rpc_get_recv_sockaddr(rpc
);
1480 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1481 srv_data
->status
= -1;
1485 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1486 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1487 srv_data
->status
= -1;
1491 /* check for dupes */
1492 for (srvr
= srv_data
->srvrs
; srvr
; srvr
= srvr
->next
) {
1493 if (!strcmp(hostdd
, srvr
->addr
)) {
1498 srvr
= malloc(sizeof(struct nfs_server_list
));
1500 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1501 srv_data
->status
= -1;
1505 srvr
->addr
= strdup(hostdd
);
1506 if (srvr
->addr
== NULL
) {
1507 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1509 srv_data
->status
= -1;
1513 srvr
->next
= srv_data
->srvrs
;
1514 srv_data
->srvrs
= srvr
;
1519 static int send_nfsd_probes(struct rpc_context
*rpc
, INTERFACE_INFO
*InterfaceList
, int numIfs
, struct nfs_list_data
*data
)
1523 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1525 for(i
= 0; i
< numIfs
; i
++)
1529 unsigned long nFlags
= 0;
1531 pAddress
= (SOCKADDR
*) & (InterfaceList
[i
].iiBroadcastAddress
);
1533 if(pAddress
->sa_family
!= AF_INET
)
1536 nFlags
= InterfaceList
[i
].iiFlags
;
1538 if (!(nFlags
& IFF_UP
))
1543 if (nFlags
& IFF_LOOPBACK
)
1548 if (!(nFlags
& IFF_BROADCAST
))
1553 if (getnameinfo(pAddress
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0)
1558 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0)
1563 if (rpc_pmap2_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0)
1571 struct nfs_server_list
*nfs_find_local_servers(void)
1573 struct rpc_context
*rpc
;
1574 struct nfs_list_data data
= {0, NULL
};
1575 struct timeval tv_start
, tv_current
;
1578 INTERFACE_INFO InterfaceList
[20];
1579 unsigned long nBytesReturned
;
1580 int nNumInterfaces
= 0;
1582 rpc
= rpc_init_udp_context();
1588 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0)
1590 rpc_destroy_context(rpc
);
1594 if (WSAIoctl(rpc_get_fd(rpc
), SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
, sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
1599 nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
1601 for (loop
=0; loop
<3; loop
++)
1603 if (send_nfsd_probes(rpc
, InterfaceList
, nNumInterfaces
, &data
) != 0)
1605 rpc_destroy_context(rpc
);
1609 win32_gettimeofday(&tv_start
, NULL
);
1614 pfd
.fd
= rpc_get_fd(rpc
);
1615 pfd
.events
= rpc_which_events(rpc
);
1617 win32_gettimeofday(&tv_current
, NULL
);
1619 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1620 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1622 if (poll(&pfd
, 1, mpt
) < 0)
1624 free_nfs_srvr_list(data
.srvrs
);
1625 rpc_destroy_context(rpc
);
1628 if (pfd
.revents
== 0)
1633 if (rpc_service(rpc
, pfd
.revents
) < 0)
1640 rpc_destroy_context(rpc
);
1642 if (data
.status
!= 0)
1644 free_nfs_srvr_list(data
.srvrs
);
1651 static int send_nfsd_probes(struct rpc_context
*rpc
, struct ifconf
*ifc
, struct nfs_list_data
*data
)
1655 assert(rpc
->magic
== RPC_CONTEXT_MAGIC
);
1657 for (ptr
=(char *)(ifc
->ifc_buf
); ptr
< (char *)(ifc
->ifc_buf
) + ifc
->ifc_len
; ) {
1661 ifr
= (struct ifreq
*)ptr
;
1662 #ifdef HAVE_SOCKADDR_LEN
1663 if (ifr
->ifr_addr
.sa_len
> sizeof(struct sockaddr
)) {
1664 ptr
+= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
1666 ptr
+= sizeof(ifr
->ifr_name
) + sizeof(struct sockaddr
);
1669 ptr
+= sizeof(struct ifreq
);
1672 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) {
1675 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, ifr
) < 0) {
1678 if (!(ifr
->ifr_flags
& IFF_UP
)) {
1681 if (ifr
->ifr_flags
& IFF_LOOPBACK
) {
1684 if (!(ifr
->ifr_flags
& IFF_BROADCAST
)) {
1687 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, ifr
) < 0) {
1690 if (getnameinfo(&ifr
->ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1693 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1697 if (rpc_pmap2_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, data
) < 0) {
1705 struct nfs_server_list
*nfs_find_local_servers(void)
1707 struct rpc_context
*rpc
;
1708 struct nfs_list_data data
= {0, NULL
};
1709 struct timeval tv_start
, tv_current
;
1714 rpc
= rpc_init_udp_context();
1719 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1720 rpc_destroy_context(rpc
);
1725 /* get list of all interfaces */
1726 size
= sizeof(struct ifreq
);
1730 while(ifc
.ifc_len
> (size
- sizeof(struct ifreq
))) {
1735 ifc
.ifc_buf
= malloc(size
);
1736 memset(ifc
.ifc_buf
, 0, size
);
1737 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1738 rpc_destroy_context(rpc
);
1744 for (loop
=0; loop
<3; loop
++) {
1745 if (send_nfsd_probes(rpc
, &ifc
, &data
) != 0) {
1746 rpc_destroy_context(rpc
);
1751 gettimeofday(&tv_start
, NULL
);
1755 pfd
.fd
= rpc_get_fd(rpc
);
1756 pfd
.events
= rpc_which_events(rpc
);
1758 gettimeofday(&tv_current
, NULL
);
1760 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1761 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1763 if (poll(&pfd
, 1, mpt
) < 0) {
1764 free_nfs_srvr_list(data
.srvrs
);
1765 rpc_destroy_context(rpc
);
1768 if (pfd
.revents
== 0) {
1772 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1779 rpc_destroy_context(rpc
);
1781 if (data
.status
!= 0) {
1782 free_nfs_srvr_list(data
.srvrs
);