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 <sys/types.h>
27 #include <sys/statvfs.h>
28 #include <sys/ioctl.h>
36 #include "libnfs-raw.h"
37 #include "libnfs-raw-mount.h"
38 #include "libnfs-raw-nfs.h"
39 #include "libnfs-private.h"
50 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
55 if (cb_data
->is_finished
) {
58 pfd
.fd
= rpc_get_fd(rpc
);
59 pfd
.events
= rpc_which_events(rpc
);
61 if (poll(&pfd
, 1, -1) < 0) {
62 rpc_set_error(rpc
, "Poll failed");
63 cb_data
->status
= -EIO
;
66 if (rpc_service(rpc
, pfd
.revents
) < 0) {
67 rpc_set_error(rpc
, "rpc_service failed");
68 cb_data
->status
= -EIO
;
80 * connect to the server and mount the export
82 static void mount_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
84 struct sync_cb_data
*cb_data
= private_data
;
86 cb_data
->is_finished
= 1;
87 cb_data
->status
= status
;
90 nfs_set_error(nfs
, "mount/mnt call failed with \"%s\"", (char *)data
);
95 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
97 struct sync_cb_data cb_data
;
99 cb_data
.is_finished
= 0;
101 if (nfs_mount_async(nfs
, server
, export
, mount_cb
, &cb_data
) != 0) {
102 nfs_set_error(nfs
, "nfs_mount_async failed");
106 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
108 return cb_data
.status
;
115 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
117 struct sync_cb_data
*cb_data
= private_data
;
119 cb_data
->is_finished
= 1;
120 cb_data
->status
= status
;
123 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
127 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
130 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
132 struct sync_cb_data cb_data
;
134 cb_data
.is_finished
= 0;
135 cb_data
.return_data
= st
;
137 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
138 nfs_set_error(nfs
, "nfs_stat_async failed");
142 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
144 return cb_data
.status
;
153 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
155 struct sync_cb_data
*cb_data
= private_data
;
156 struct nfsfh
*fh
, **nfsfh
;
158 cb_data
->is_finished
= 1;
159 cb_data
->status
= status
;
162 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
167 nfsfh
= cb_data
->return_data
;
171 int nfs_open(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
173 struct sync_cb_data cb_data
;
175 cb_data
.is_finished
= 0;
176 cb_data
.return_data
= nfsfh
;
178 if (nfs_open_async(nfs
, path
, mode
, open_cb
, &cb_data
) != 0) {
179 nfs_set_error(nfs
, "nfs_open_async failed");
183 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
185 return cb_data
.status
;
194 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
196 struct sync_cb_data
*cb_data
= private_data
;
198 cb_data
->is_finished
= 1;
199 cb_data
->status
= status
;
202 nfs_set_error(nfs
, "pread call failed with \"%s\"", (char *)data
);
206 buffer
= cb_data
->return_data
;
207 memcpy(buffer
, (char *)data
, status
);
210 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, size_t count
, char *buffer
)
212 struct sync_cb_data cb_data
;
214 cb_data
.is_finished
= 0;
215 cb_data
.return_data
= buffer
;
217 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
218 nfs_set_error(nfs
, "nfs_pread_async failed");
222 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
224 return cb_data
.status
;
230 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, size_t count
, char *buffer
)
232 return nfs_pread(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buffer
);
238 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
240 struct sync_cb_data
*cb_data
= private_data
;
241 cb_data
->is_finished
= 1;
242 cb_data
->status
= status
;
245 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
250 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
252 struct sync_cb_data cb_data
;
254 cb_data
.is_finished
= 0;
256 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
257 nfs_set_error(nfs
, "nfs_close_async failed");
261 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
263 return cb_data
.status
;
272 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
274 struct sync_cb_data cb_data
;
276 cb_data
.is_finished
= 0;
277 cb_data
.return_data
= st
;
279 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
280 nfs_set_error(nfs
, "nfs_fstat_async failed");
284 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
286 return cb_data
.status
;
293 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
295 struct sync_cb_data
*cb_data
= private_data
;
296 cb_data
->is_finished
= 1;
297 cb_data
->status
= status
;
300 nfs_set_error(nfs
, "pwrite call failed with \"%s\"", (char *)data
);
305 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, size_t count
, char *buf
)
307 struct sync_cb_data cb_data
;
309 cb_data
.is_finished
= 0;
311 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
312 nfs_set_error(nfs
, "nfs_pwrite_async failed");
316 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
318 return cb_data
.status
;
324 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, size_t count
, char *buf
)
326 return nfs_pwrite(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buf
);
333 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
335 struct sync_cb_data
*cb_data
= private_data
;
336 cb_data
->is_finished
= 1;
337 cb_data
->status
= status
;
340 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
345 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
347 struct sync_cb_data cb_data
;
349 cb_data
.is_finished
= 0;
351 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
352 nfs_set_error(nfs
, "nfs_fsync_async failed");
356 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
358 return cb_data
.status
;
367 static void ftruncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
369 struct sync_cb_data
*cb_data
= private_data
;
370 cb_data
->is_finished
= 1;
371 cb_data
->status
= status
;
374 nfs_set_error(nfs
, "ftruncate call failed with \"%s\"", (char *)data
);
379 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t length
)
381 struct sync_cb_data cb_data
;
383 cb_data
.is_finished
= 0;
385 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_cb
, &cb_data
) != 0) {
386 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
390 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
392 return cb_data
.status
;
400 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
402 struct sync_cb_data
*cb_data
= private_data
;
403 cb_data
->is_finished
= 1;
404 cb_data
->status
= status
;
407 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
412 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, off_t length
)
414 struct sync_cb_data cb_data
;
416 cb_data
.is_finished
= 0;
418 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
419 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
423 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
425 return cb_data
.status
;
435 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
437 struct sync_cb_data
*cb_data
= private_data
;
438 cb_data
->is_finished
= 1;
439 cb_data
->status
= status
;
442 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
447 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
449 struct sync_cb_data cb_data
;
451 cb_data
.is_finished
= 0;
453 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
454 nfs_set_error(nfs
, "nfs_mkdir_async failed");
458 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
460 return cb_data
.status
;
470 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
472 struct sync_cb_data
*cb_data
= private_data
;
473 cb_data
->is_finished
= 1;
474 cb_data
->status
= status
;
477 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
482 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
484 struct sync_cb_data cb_data
;
486 cb_data
.is_finished
= 0;
488 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
489 nfs_set_error(nfs
, "nfs_rmdir_async failed");
493 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
495 return cb_data
.status
;
503 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
505 struct sync_cb_data
*cb_data
= private_data
;
506 struct nfsfh
*fh
, **nfsfh
;
508 cb_data
->is_finished
= 1;
509 cb_data
->status
= status
;
512 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
517 nfsfh
= cb_data
->return_data
;
521 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
523 struct sync_cb_data cb_data
;
525 cb_data
.is_finished
= 0;
526 cb_data
.return_data
= nfsfh
;
528 if (nfs_creat_async(nfs
, path
, mode
, creat_cb
, &cb_data
) != 0) {
529 nfs_set_error(nfs
, "nfs_creat_async failed");
533 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
535 return cb_data
.status
;
544 static void unlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
546 struct sync_cb_data
*cb_data
= private_data
;
548 cb_data
->is_finished
= 1;
549 cb_data
->status
= status
;
552 nfs_set_error(nfs
, "unlink call failed with \"%s\"", (char *)data
);
557 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
559 struct sync_cb_data cb_data
;
561 cb_data
.is_finished
= 0;
563 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
564 nfs_set_error(nfs
, "nfs_unlink_async failed");
568 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
570 return cb_data
.status
;
578 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
580 struct sync_cb_data
*cb_data
= private_data
;
581 struct nfsdir
*dir
, **nfsdir
;
583 cb_data
->is_finished
= 1;
584 cb_data
->status
= status
;
587 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
592 nfsdir
= cb_data
->return_data
;
596 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
598 struct sync_cb_data cb_data
;
600 cb_data
.is_finished
= 0;
601 cb_data
.return_data
= nfsdir
;
603 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
604 nfs_set_error(nfs
, "nfs_opendir_async failed");
608 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
610 return cb_data
.status
;
617 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
619 struct sync_cb_data
*cb_data
= private_data
;
621 cb_data
->is_finished
= 1;
622 cb_data
->status
= status
;
625 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
629 if (cb_data
->return_data
!= NULL
) {
630 memcpy(cb_data
->return_data
, data
, sizeof(off_t
));
634 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, int whence
, off_t
*current_offset
)
636 struct sync_cb_data cb_data
;
638 cb_data
.is_finished
= 0;
639 cb_data
.return_data
= current_offset
;
641 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
642 nfs_set_error(nfs
, "nfs_lseek_async failed");
646 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
648 return cb_data
.status
;
656 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
658 struct sync_cb_data
*cb_data
= private_data
;
660 cb_data
->is_finished
= 1;
661 cb_data
->status
= status
;
664 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
668 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
671 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
673 struct sync_cb_data cb_data
;
675 cb_data
.is_finished
= 0;
676 cb_data
.return_data
= svfs
;
678 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
679 nfs_set_error(nfs
, "nfs_statvfs_async failed");
683 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
685 return cb_data
.status
;
695 static void readlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
697 struct sync_cb_data
*cb_data
= private_data
;
699 cb_data
->is_finished
= 1;
700 cb_data
->status
= status
;
703 nfs_set_error(nfs
, "readlink call failed with \"%s\"", (char *)data
);
707 if (strlen(data
) > (size_t)cb_data
->return_int
) {
708 nfs_set_error(nfs
, "Too small buffer for readlink");
709 cb_data
->status
= -ENAMETOOLONG
;
713 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
716 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
718 struct sync_cb_data cb_data
;
720 cb_data
.is_finished
= 0;
721 cb_data
.return_data
= buf
;
722 cb_data
.return_int
= bufsize
;
724 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
725 nfs_set_error(nfs
, "nfs_readlink_async failed");
729 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
731 return cb_data
.status
;
739 static void chmod_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
, "chmod call failed with \"%s\"", (char *)data
);
752 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
754 struct sync_cb_data cb_data
;
756 cb_data
.is_finished
= 0;
758 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
759 nfs_set_error(nfs
, "nfs_chmod_async failed");
763 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
765 return cb_data
.status
;
774 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
776 struct sync_cb_data
*cb_data
= private_data
;
778 cb_data
->is_finished
= 1;
779 cb_data
->status
= status
;
782 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
787 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
789 struct sync_cb_data cb_data
;
791 cb_data
.is_finished
= 0;
793 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
794 nfs_set_error(nfs
, "nfs_fchmod_async failed");
798 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
800 return cb_data
.status
;
809 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
811 struct sync_cb_data
*cb_data
= private_data
;
813 cb_data
->is_finished
= 1;
814 cb_data
->status
= status
;
817 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
822 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
824 struct sync_cb_data cb_data
;
826 cb_data
.is_finished
= 0;
828 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
829 nfs_set_error(nfs
, "nfs_chown_async failed");
833 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
835 return cb_data
.status
;
841 static void fchown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
843 struct sync_cb_data
*cb_data
= private_data
;
845 cb_data
->is_finished
= 1;
846 cb_data
->status
= status
;
849 nfs_set_error(nfs
, "fchown call failed with \"%s\"", (char *)data
);
854 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
856 struct sync_cb_data cb_data
;
858 cb_data
.is_finished
= 0;
860 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
861 nfs_set_error(nfs
, "nfs_fchown_async failed");
865 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
867 return cb_data
.status
;
875 static void utimes_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
877 struct sync_cb_data
*cb_data
= private_data
;
879 cb_data
->is_finished
= 1;
880 cb_data
->status
= status
;
883 nfs_set_error(nfs
, "utimes call failed with \"%s\"", (char *)data
);
888 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
890 struct sync_cb_data cb_data
;
892 cb_data
.is_finished
= 0;
894 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
895 nfs_set_error(nfs
, "nfs_utimes_async failed");
899 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
901 return cb_data
.status
;
909 static void utime_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
911 struct sync_cb_data
*cb_data
= private_data
;
913 cb_data
->is_finished
= 1;
914 cb_data
->status
= status
;
917 nfs_set_error(nfs
, "utime call failed with \"%s\"", (char *)data
);
922 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
924 struct sync_cb_data cb_data
;
926 cb_data
.is_finished
= 0;
928 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
929 nfs_set_error(nfs
, "nfs_utimes_async failed");
933 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
935 return cb_data
.status
;
944 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
946 struct sync_cb_data
*cb_data
= private_data
;
948 cb_data
->is_finished
= 1;
949 cb_data
->status
= status
;
952 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
957 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
959 struct sync_cb_data cb_data
;
961 cb_data
.is_finished
= 0;
963 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
964 nfs_set_error(nfs
, "nfs_access_async failed");
968 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
970 return cb_data
.status
;
978 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
980 struct sync_cb_data
*cb_data
= private_data
;
982 cb_data
->is_finished
= 1;
983 cb_data
->status
= status
;
986 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
991 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
993 struct sync_cb_data cb_data
;
995 cb_data
.is_finished
= 0;
997 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
998 nfs_set_error(nfs
, "nfs_symlink_async failed");
1002 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
1004 return cb_data
.status
;
1012 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1014 struct sync_cb_data
*cb_data
= private_data
;
1016 cb_data
->is_finished
= 1;
1017 cb_data
->status
= status
;
1020 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1025 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1027 struct sync_cb_data cb_data
;
1029 cb_data
.is_finished
= 0;
1031 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1032 nfs_set_error(nfs
, "nfs_rename_async failed");
1036 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
1038 return cb_data
.status
;
1046 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1048 struct sync_cb_data
*cb_data
= private_data
;
1050 cb_data
->is_finished
= 1;
1051 cb_data
->status
= status
;
1054 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1059 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1061 struct sync_cb_data cb_data
;
1063 cb_data
.is_finished
= 0;
1065 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1066 nfs_set_error(nfs
, "nfs_link_async failed");
1070 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
1072 return cb_data
.status
;
1075 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1077 struct sync_cb_data
*cb_data
= private_data
;
1078 exports export
= *(exports
*)data
;
1080 cb_data
->is_finished
= 1;
1081 cb_data
->status
= status
;
1082 cb_data
->return_data
= NULL
;
1085 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1089 while (export
!= NULL
) {
1092 new_export
= malloc(sizeof(*new_export
));
1093 memset(new_export
, 0, sizeof(*new_export
));
1094 new_export
->ex_dir
= strdup(export
->ex_dir
);
1095 new_export
->ex_next
= cb_data
->return_data
;
1097 cb_data
->return_data
= new_export
;
1099 export
= export
->ex_next
;
1103 struct exportnode
*mount_getexports(const char *server
)
1105 struct sync_cb_data cb_data
;
1106 struct rpc_context
*rpc
;
1109 cb_data
.is_finished
= 0;
1110 cb_data
.return_data
= NULL
;
1112 rpc
= rpc_init_context();
1113 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1114 rpc_destroy_context(rpc
);
1118 wait_for_reply(rpc
, &cb_data
);
1119 rpc_destroy_context(rpc
);
1121 return cb_data
.return_data
;
1124 void mount_free_export_list(struct exportnode
*exports
)
1126 struct exportnode
*tmp
;
1128 while ((tmp
= exports
)) {
1129 exports
= exports
->ex_next
;
1138 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1140 while (srv
!= NULL
) {
1141 struct nfs_server_list
*next
= srv
->next
;
1149 struct nfs_list_data
{
1151 struct nfs_server_list
*srvrs
;
1154 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1156 struct nfs_list_data
*srv_data
= private_data
;
1157 struct sockaddr
*sin
;
1159 struct nfs_server_list
*srvr
;
1161 if (status
== RPC_STATUS_CANCEL
) {
1165 srv_data
->status
= -1;
1169 sin
= rpc_get_recv_sockaddr(rpc
);
1171 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1172 srv_data
->status
= -1;
1176 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1177 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1178 srv_data
->status
= -1;
1183 srvr
= malloc(sizeof(struct nfs_server_list
));
1185 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1186 srv_data
->status
= -1;
1190 srvr
->addr
= strdup(hostdd
);
1191 if (srvr
->addr
== NULL
) {
1192 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1194 srv_data
->status
= -1;
1198 srvr
->next
= srv_data
->srvrs
;
1199 srv_data
->srvrs
= srvr
;
1202 struct nfs_server_list
*nfs_find_local_servers(void)
1204 struct rpc_context
*rpc
;
1205 struct nfs_list_data data
= {0, NULL
};
1206 struct timeval tv_start
, tv_current
;
1211 rpc
= rpc_init_udp_context();
1216 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1217 rpc_destroy_context(rpc
);
1222 /* get list of all interfaces */
1223 size
= sizeof(struct ifreq
);
1227 while (ifc
.ifc_len
== size
) {
1232 ifc
.ifc_buf
= malloc(size
);
1233 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1234 rpc_destroy_context(rpc
);
1240 for (i
= 0; (unsigned)i
< ifc
.ifc_len
/ sizeof(struct ifconf
); i
++) {
1243 if (ifc
.ifc_req
[i
].ifr_addr
.sa_family
!= AF_INET
) {
1246 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, &ifc
.ifc_req
[i
]) < 0) {
1247 rpc_destroy_context(rpc
);
1251 if (!(ifc
.ifc_req
[i
].ifr_flags
& IFF_UP
)) {
1254 if (ifc
.ifc_req
[i
].ifr_flags
& IFF_LOOPBACK
) {
1257 if (!(ifc
.ifc_req
[i
].ifr_flags
& IFF_BROADCAST
)) {
1260 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, &ifc
.ifc_req
[i
]) < 0) {
1261 rpc_destroy_context(rpc
);
1265 if (getnameinfo(&ifc
.ifc_req
[i
].ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1266 rpc_destroy_context(rpc
);
1270 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1271 rpc_destroy_context(rpc
);
1276 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, &data
) < 0) {
1277 rpc_destroy_context(rpc
);
1284 gettimeofday(&tv_start
, NULL
);
1288 pfd
.fd
= rpc_get_fd(rpc
);
1289 pfd
.events
= rpc_which_events(rpc
);
1291 gettimeofday(&tv_current
, NULL
);
1293 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1294 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1296 if (poll(&pfd
, 1, mpt
) < 0) {
1297 free_nfs_srvr_list(data
.srvrs
);
1298 rpc_destroy_context(rpc
);
1301 if (pfd
.revents
== 0) {
1305 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1310 rpc_destroy_context(rpc
);
1312 if (data
.status
!= 0) {
1313 free_nfs_srvr_list(data
.srvrs
);