4dd224c5cdaaf68f301105271a40f12cc1e163dc
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>
33 #include <sys/socket.h>
37 #include "libnfs-raw.h"
38 #include "libnfs-raw-mount.h"
39 #include "libnfs-raw-nfs.h"
40 #include "libnfs-private.h"
51 static void wait_for_reply(struct rpc_context
*rpc
, struct sync_cb_data
*cb_data
)
56 if (cb_data
->is_finished
) {
59 pfd
.fd
= rpc_get_fd(rpc
);
60 pfd
.events
= rpc_which_events(rpc
);
62 if (poll(&pfd
, 1, -1) < 0) {
63 rpc_set_error(rpc
, "Poll failed");
64 cb_data
->status
= -EIO
;
67 if (rpc_service(rpc
, pfd
.revents
) < 0) {
68 rpc_set_error(rpc
, "rpc_service failed");
69 cb_data
->status
= -EIO
;
81 * connect to the server and mount the export
83 static void mount_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
85 struct sync_cb_data
*cb_data
= private_data
;
87 cb_data
->is_finished
= 1;
88 cb_data
->status
= status
;
91 nfs_set_error(nfs
, "mount/mnt call failed with \"%s\"", (char *)data
);
96 int nfs_mount(struct nfs_context
*nfs
, const char *server
, const char *export
)
98 struct sync_cb_data cb_data
;
100 cb_data
.is_finished
= 0;
102 if (nfs_mount_async(nfs
, server
, export
, mount_cb
, &cb_data
) != 0) {
103 nfs_set_error(nfs
, "nfs_mount_async failed");
107 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
109 return cb_data
.status
;
116 static void stat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
118 struct sync_cb_data
*cb_data
= private_data
;
120 cb_data
->is_finished
= 1;
121 cb_data
->status
= status
;
124 nfs_set_error(nfs
, "stat call failed with \"%s\"", (char *)data
);
128 memcpy(cb_data
->return_data
, data
, sizeof(struct stat
));
131 int nfs_stat(struct nfs_context
*nfs
, const char *path
, struct stat
*st
)
133 struct sync_cb_data cb_data
;
135 cb_data
.is_finished
= 0;
136 cb_data
.return_data
= st
;
138 if (nfs_stat_async(nfs
, path
, stat_cb
, &cb_data
) != 0) {
139 nfs_set_error(nfs
, "nfs_stat_async failed");
143 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
145 return cb_data
.status
;
154 static void open_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
156 struct sync_cb_data
*cb_data
= private_data
;
157 struct nfsfh
*fh
, **nfsfh
;
159 cb_data
->is_finished
= 1;
160 cb_data
->status
= status
;
163 nfs_set_error(nfs
, "open call failed with \"%s\"", (char *)data
);
168 nfsfh
= cb_data
->return_data
;
172 int nfs_open(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
174 struct sync_cb_data cb_data
;
176 cb_data
.is_finished
= 0;
177 cb_data
.return_data
= nfsfh
;
179 if (nfs_open_async(nfs
, path
, mode
, open_cb
, &cb_data
) != 0) {
180 nfs_set_error(nfs
, "nfs_open_async failed");
184 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
186 return cb_data
.status
;
195 static void pread_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
197 struct sync_cb_data
*cb_data
= private_data
;
199 cb_data
->is_finished
= 1;
200 cb_data
->status
= status
;
203 nfs_set_error(nfs
, "pread call failed with \"%s\"", (char *)data
);
207 buffer
= cb_data
->return_data
;
208 memcpy(buffer
, (char *)data
, status
);
211 int nfs_pread(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, size_t count
, char *buffer
)
213 struct sync_cb_data cb_data
;
215 cb_data
.is_finished
= 0;
216 cb_data
.return_data
= buffer
;
218 if (nfs_pread_async(nfs
, nfsfh
, offset
, count
, pread_cb
, &cb_data
) != 0) {
219 nfs_set_error(nfs
, "nfs_pread_async failed");
223 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
225 return cb_data
.status
;
231 int nfs_read(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, size_t count
, char *buffer
)
233 return nfs_pread(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buffer
);
239 static void close_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
241 struct sync_cb_data
*cb_data
= private_data
;
242 cb_data
->is_finished
= 1;
243 cb_data
->status
= status
;
246 nfs_set_error(nfs
, "close call failed with \"%s\"", (char *)data
);
251 int nfs_close(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
253 struct sync_cb_data cb_data
;
255 cb_data
.is_finished
= 0;
257 if (nfs_close_async(nfs
, nfsfh
, close_cb
, &cb_data
) != 0) {
258 nfs_set_error(nfs
, "nfs_close_async failed");
262 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
264 return cb_data
.status
;
273 int nfs_fstat(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, struct stat
*st
)
275 struct sync_cb_data cb_data
;
277 cb_data
.is_finished
= 0;
278 cb_data
.return_data
= st
;
280 if (nfs_fstat_async(nfs
, nfsfh
, stat_cb
, &cb_data
) != 0) {
281 nfs_set_error(nfs
, "nfs_fstat_async failed");
285 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
287 return cb_data
.status
;
294 static void pwrite_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
296 struct sync_cb_data
*cb_data
= private_data
;
297 cb_data
->is_finished
= 1;
298 cb_data
->status
= status
;
301 nfs_set_error(nfs
, "pwrite call failed with \"%s\"", (char *)data
);
306 int nfs_pwrite(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, size_t count
, char *buf
)
308 struct sync_cb_data cb_data
;
310 cb_data
.is_finished
= 0;
312 if (nfs_pwrite_async(nfs
, nfsfh
, offset
, count
, buf
, pwrite_cb
, &cb_data
) != 0) {
313 nfs_set_error(nfs
, "nfs_pwrite_async failed");
317 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
319 return cb_data
.status
;
325 int nfs_write(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, size_t count
, char *buf
)
327 return nfs_pwrite(nfs
, nfsfh
, nfs_get_current_offset(nfsfh
), count
, buf
);
334 static void fsync_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
336 struct sync_cb_data
*cb_data
= private_data
;
337 cb_data
->is_finished
= 1;
338 cb_data
->status
= status
;
341 nfs_set_error(nfs
, "fsync call failed with \"%s\"", (char *)data
);
346 int nfs_fsync(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
)
348 struct sync_cb_data cb_data
;
350 cb_data
.is_finished
= 0;
352 if (nfs_fsync_async(nfs
, nfsfh
, fsync_cb
, &cb_data
) != 0) {
353 nfs_set_error(nfs
, "nfs_fsync_async failed");
357 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
359 return cb_data
.status
;
368 static void ftruncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
370 struct sync_cb_data
*cb_data
= private_data
;
371 cb_data
->is_finished
= 1;
372 cb_data
->status
= status
;
375 nfs_set_error(nfs
, "ftruncate call failed with \"%s\"", (char *)data
);
380 int nfs_ftruncate(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t length
)
382 struct sync_cb_data cb_data
;
384 cb_data
.is_finished
= 0;
386 if (nfs_ftruncate_async(nfs
, nfsfh
, length
, ftruncate_cb
, &cb_data
) != 0) {
387 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
391 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
393 return cb_data
.status
;
401 static void truncate_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
403 struct sync_cb_data
*cb_data
= private_data
;
404 cb_data
->is_finished
= 1;
405 cb_data
->status
= status
;
408 nfs_set_error(nfs
, "truncate call failed with \"%s\"", (char *)data
);
413 int nfs_truncate(struct nfs_context
*nfs
, const char *path
, off_t length
)
415 struct sync_cb_data cb_data
;
417 cb_data
.is_finished
= 0;
419 if (nfs_truncate_async(nfs
, path
, length
, truncate_cb
, &cb_data
) != 0) {
420 nfs_set_error(nfs
, "nfs_ftruncate_async failed");
424 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
426 return cb_data
.status
;
436 static void mkdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
438 struct sync_cb_data
*cb_data
= private_data
;
439 cb_data
->is_finished
= 1;
440 cb_data
->status
= status
;
443 nfs_set_error(nfs
, "mkdir call failed with \"%s\"", (char *)data
);
448 int nfs_mkdir(struct nfs_context
*nfs
, const char *path
)
450 struct sync_cb_data cb_data
;
452 cb_data
.is_finished
= 0;
454 if (nfs_mkdir_async(nfs
, path
, mkdir_cb
, &cb_data
) != 0) {
455 nfs_set_error(nfs
, "nfs_mkdir_async failed");
459 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
461 return cb_data
.status
;
471 static void rmdir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
473 struct sync_cb_data
*cb_data
= private_data
;
474 cb_data
->is_finished
= 1;
475 cb_data
->status
= status
;
478 nfs_set_error(nfs
, "rmdir call failed with \"%s\"", (char *)data
);
483 int nfs_rmdir(struct nfs_context
*nfs
, const char *path
)
485 struct sync_cb_data cb_data
;
487 cb_data
.is_finished
= 0;
489 if (nfs_rmdir_async(nfs
, path
, rmdir_cb
, &cb_data
) != 0) {
490 nfs_set_error(nfs
, "nfs_rmdir_async failed");
494 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
496 return cb_data
.status
;
504 static void creat_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
506 struct sync_cb_data
*cb_data
= private_data
;
507 struct nfsfh
*fh
, **nfsfh
;
509 cb_data
->is_finished
= 1;
510 cb_data
->status
= status
;
513 nfs_set_error(nfs
, "creat call failed with \"%s\"", (char *)data
);
518 nfsfh
= cb_data
->return_data
;
522 int nfs_creat(struct nfs_context
*nfs
, const char *path
, int mode
, struct nfsfh
**nfsfh
)
524 struct sync_cb_data cb_data
;
526 cb_data
.is_finished
= 0;
527 cb_data
.return_data
= nfsfh
;
529 if (nfs_creat_async(nfs
, path
, mode
, creat_cb
, &cb_data
) != 0) {
530 nfs_set_error(nfs
, "nfs_creat_async failed");
534 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
536 return cb_data
.status
;
545 static void unlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
547 struct sync_cb_data
*cb_data
= private_data
;
549 cb_data
->is_finished
= 1;
550 cb_data
->status
= status
;
553 nfs_set_error(nfs
, "unlink call failed with \"%s\"", (char *)data
);
558 int nfs_unlink(struct nfs_context
*nfs
, const char *path
)
560 struct sync_cb_data cb_data
;
562 cb_data
.is_finished
= 0;
564 if (nfs_unlink_async(nfs
, path
, unlink_cb
, &cb_data
) != 0) {
565 nfs_set_error(nfs
, "nfs_unlink_async failed");
569 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
571 return cb_data
.status
;
579 static void opendir_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
581 struct sync_cb_data
*cb_data
= private_data
;
582 struct nfsdir
*dir
, **nfsdir
;
584 cb_data
->is_finished
= 1;
585 cb_data
->status
= status
;
588 nfs_set_error(nfs
, "opendir call failed with \"%s\"", (char *)data
);
593 nfsdir
= cb_data
->return_data
;
597 int nfs_opendir(struct nfs_context
*nfs
, const char *path
, struct nfsdir
**nfsdir
)
599 struct sync_cb_data cb_data
;
601 cb_data
.is_finished
= 0;
602 cb_data
.return_data
= nfsdir
;
604 if (nfs_opendir_async(nfs
, path
, opendir_cb
, &cb_data
) != 0) {
605 nfs_set_error(nfs
, "nfs_opendir_async failed");
609 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
611 return cb_data
.status
;
618 static void lseek_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
620 struct sync_cb_data
*cb_data
= private_data
;
622 cb_data
->is_finished
= 1;
623 cb_data
->status
= status
;
626 nfs_set_error(nfs
, "lseek call failed with \"%s\"", (char *)data
);
630 if (cb_data
->return_data
!= NULL
) {
631 memcpy(cb_data
->return_data
, data
, sizeof(off_t
));
635 int nfs_lseek(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, off_t offset
, int whence
, off_t
*current_offset
)
637 struct sync_cb_data cb_data
;
639 cb_data
.is_finished
= 0;
640 cb_data
.return_data
= current_offset
;
642 if (nfs_lseek_async(nfs
, nfsfh
, offset
, whence
, lseek_cb
, &cb_data
) != 0) {
643 nfs_set_error(nfs
, "nfs_lseek_async failed");
647 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
649 return cb_data
.status
;
657 static void statvfs_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
659 struct sync_cb_data
*cb_data
= private_data
;
661 cb_data
->is_finished
= 1;
662 cb_data
->status
= status
;
665 nfs_set_error(nfs
, "statvfs call failed with \"%s\"", (char *)data
);
669 memcpy(cb_data
->return_data
, data
, sizeof(struct statvfs
));
672 int nfs_statvfs(struct nfs_context
*nfs
, const char *path
, struct statvfs
*svfs
)
674 struct sync_cb_data cb_data
;
676 cb_data
.is_finished
= 0;
677 cb_data
.return_data
= svfs
;
679 if (nfs_statvfs_async(nfs
, path
, statvfs_cb
, &cb_data
) != 0) {
680 nfs_set_error(nfs
, "nfs_statvfs_async failed");
684 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
686 return cb_data
.status
;
696 static void readlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
698 struct sync_cb_data
*cb_data
= private_data
;
700 cb_data
->is_finished
= 1;
701 cb_data
->status
= status
;
704 nfs_set_error(nfs
, "readlink call failed with \"%s\"", (char *)data
);
708 if (strlen(data
) > (size_t)cb_data
->return_int
) {
709 nfs_set_error(nfs
, "Too small buffer for readlink");
710 cb_data
->status
= -ENAMETOOLONG
;
714 memcpy(cb_data
->return_data
, data
, strlen(data
)+1);
717 int nfs_readlink(struct nfs_context
*nfs
, const char *path
, char *buf
, int bufsize
)
719 struct sync_cb_data cb_data
;
721 cb_data
.is_finished
= 0;
722 cb_data
.return_data
= buf
;
723 cb_data
.return_int
= bufsize
;
725 if (nfs_readlink_async(nfs
, path
, readlink_cb
, &cb_data
) != 0) {
726 nfs_set_error(nfs
, "nfs_readlink_async failed");
730 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
732 return cb_data
.status
;
740 static void chmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
742 struct sync_cb_data
*cb_data
= private_data
;
744 cb_data
->is_finished
= 1;
745 cb_data
->status
= status
;
748 nfs_set_error(nfs
, "chmod call failed with \"%s\"", (char *)data
);
753 int nfs_chmod(struct nfs_context
*nfs
, const char *path
, int mode
)
755 struct sync_cb_data cb_data
;
757 cb_data
.is_finished
= 0;
759 if (nfs_chmod_async(nfs
, path
, mode
, chmod_cb
, &cb_data
) != 0) {
760 nfs_set_error(nfs
, "nfs_chmod_async failed");
764 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
766 return cb_data
.status
;
775 static void fchmod_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
777 struct sync_cb_data
*cb_data
= private_data
;
779 cb_data
->is_finished
= 1;
780 cb_data
->status
= status
;
783 nfs_set_error(nfs
, "fchmod call failed with \"%s\"", (char *)data
);
788 int nfs_fchmod(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int mode
)
790 struct sync_cb_data cb_data
;
792 cb_data
.is_finished
= 0;
794 if (nfs_fchmod_async(nfs
, nfsfh
, mode
, fchmod_cb
, &cb_data
) != 0) {
795 nfs_set_error(nfs
, "nfs_fchmod_async failed");
799 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
801 return cb_data
.status
;
810 static void chown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
812 struct sync_cb_data
*cb_data
= private_data
;
814 cb_data
->is_finished
= 1;
815 cb_data
->status
= status
;
818 nfs_set_error(nfs
, "chown call failed with \"%s\"", (char *)data
);
823 int nfs_chown(struct nfs_context
*nfs
, const char *path
, int uid
, int gid
)
825 struct sync_cb_data cb_data
;
827 cb_data
.is_finished
= 0;
829 if (nfs_chown_async(nfs
, path
, uid
, gid
, chown_cb
, &cb_data
) != 0) {
830 nfs_set_error(nfs
, "nfs_chown_async failed");
834 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
836 return cb_data
.status
;
842 static void fchown_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
844 struct sync_cb_data
*cb_data
= private_data
;
846 cb_data
->is_finished
= 1;
847 cb_data
->status
= status
;
850 nfs_set_error(nfs
, "fchown call failed with \"%s\"", (char *)data
);
855 int nfs_fchown(struct nfs_context
*nfs
, struct nfsfh
*nfsfh
, int uid
, int gid
)
857 struct sync_cb_data cb_data
;
859 cb_data
.is_finished
= 0;
861 if (nfs_fchown_async(nfs
, nfsfh
, uid
, gid
, fchown_cb
, &cb_data
) != 0) {
862 nfs_set_error(nfs
, "nfs_fchown_async failed");
866 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
868 return cb_data
.status
;
876 static void utimes_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
878 struct sync_cb_data
*cb_data
= private_data
;
880 cb_data
->is_finished
= 1;
881 cb_data
->status
= status
;
884 nfs_set_error(nfs
, "utimes call failed with \"%s\"", (char *)data
);
889 int nfs_utimes(struct nfs_context
*nfs
, const char *path
, struct timeval
*times
)
891 struct sync_cb_data cb_data
;
893 cb_data
.is_finished
= 0;
895 if (nfs_utimes_async(nfs
, path
, times
, utimes_cb
, &cb_data
) != 0) {
896 nfs_set_error(nfs
, "nfs_utimes_async failed");
900 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
902 return cb_data
.status
;
910 static void utime_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
, "utime call failed with \"%s\"", (char *)data
);
923 int nfs_utime(struct nfs_context
*nfs
, const char *path
, struct utimbuf
*times
)
925 struct sync_cb_data cb_data
;
927 cb_data
.is_finished
= 0;
929 if (nfs_utime_async(nfs
, path
, times
, utime_cb
, &cb_data
) != 0) {
930 nfs_set_error(nfs
, "nfs_utimes_async failed");
934 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
936 return cb_data
.status
;
945 static void access_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
947 struct sync_cb_data
*cb_data
= private_data
;
949 cb_data
->is_finished
= 1;
950 cb_data
->status
= status
;
953 nfs_set_error(nfs
, "access call failed with \"%s\"", (char *)data
);
958 int nfs_access(struct nfs_context
*nfs
, const char *path
, int mode
)
960 struct sync_cb_data cb_data
;
962 cb_data
.is_finished
= 0;
964 if (nfs_access_async(nfs
, path
, mode
, access_cb
, &cb_data
) != 0) {
965 nfs_set_error(nfs
, "nfs_access_async failed");
969 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
971 return cb_data
.status
;
979 static void symlink_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
981 struct sync_cb_data
*cb_data
= private_data
;
983 cb_data
->is_finished
= 1;
984 cb_data
->status
= status
;
987 nfs_set_error(nfs
, "symlink call failed with \"%s\"", (char *)data
);
992 int nfs_symlink(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
994 struct sync_cb_data cb_data
;
996 cb_data
.is_finished
= 0;
998 if (nfs_symlink_async(nfs
, oldpath
, newpath
, symlink_cb
, &cb_data
) != 0) {
999 nfs_set_error(nfs
, "nfs_symlink_async failed");
1003 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
1005 return cb_data
.status
;
1013 static void rename_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1015 struct sync_cb_data
*cb_data
= private_data
;
1017 cb_data
->is_finished
= 1;
1018 cb_data
->status
= status
;
1021 nfs_set_error(nfs
, "rename call failed with \"%s\"", (char *)data
);
1026 int nfs_rename(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1028 struct sync_cb_data cb_data
;
1030 cb_data
.is_finished
= 0;
1032 if (nfs_rename_async(nfs
, oldpath
, newpath
, rename_cb
, &cb_data
) != 0) {
1033 nfs_set_error(nfs
, "nfs_rename_async failed");
1037 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
1039 return cb_data
.status
;
1047 static void link_cb(int status
, struct nfs_context
*nfs
, void *data
, void *private_data
)
1049 struct sync_cb_data
*cb_data
= private_data
;
1051 cb_data
->is_finished
= 1;
1052 cb_data
->status
= status
;
1055 nfs_set_error(nfs
, "link call failed with \"%s\"", (char *)data
);
1060 int nfs_link(struct nfs_context
*nfs
, const char *oldpath
, const char *newpath
)
1062 struct sync_cb_data cb_data
;
1064 cb_data
.is_finished
= 0;
1066 if (nfs_link_async(nfs
, oldpath
, newpath
, link_cb
, &cb_data
) != 0) {
1067 nfs_set_error(nfs
, "nfs_link_async failed");
1071 wait_for_reply(nfs_get_rpc_context(nfs
), &cb_data
);
1073 return cb_data
.status
;
1076 void mount_getexports_cb(struct rpc_context
*mount_context
, int status
, void *data
, void *private_data
)
1078 struct sync_cb_data
*cb_data
= private_data
;
1079 exports export
= *(exports
*)data
;
1081 cb_data
->is_finished
= 1;
1082 cb_data
->status
= status
;
1083 cb_data
->return_data
= NULL
;
1086 rpc_set_error(mount_context
, "mount/export call failed with \"%s\"", (char *)data
);
1090 while (export
!= NULL
) {
1093 new_export
= malloc(sizeof(*new_export
));
1094 memset(new_export
, 0, sizeof(*new_export
));
1095 new_export
->ex_dir
= strdup(export
->ex_dir
);
1096 new_export
->ex_next
= cb_data
->return_data
;
1098 cb_data
->return_data
= new_export
;
1100 export
= export
->ex_next
;
1104 struct exportnode
*mount_getexports(const char *server
)
1106 struct sync_cb_data cb_data
;
1107 struct rpc_context
*rpc
;
1110 cb_data
.is_finished
= 0;
1111 cb_data
.return_data
= NULL
;
1113 rpc
= rpc_init_context();
1114 if (mount_getexports_async(rpc
, server
, mount_getexports_cb
, &cb_data
) != 0) {
1115 rpc_destroy_context(rpc
);
1119 wait_for_reply(rpc
, &cb_data
);
1120 rpc_destroy_context(rpc
);
1122 return cb_data
.return_data
;
1125 void mount_free_export_list(struct exportnode
*exports
)
1127 struct exportnode
*tmp
;
1129 while ((tmp
= exports
)) {
1130 exports
= exports
->ex_next
;
1139 void free_nfs_srvr_list(struct nfs_server_list
*srv
)
1141 while (srv
!= NULL
) {
1142 struct nfs_server_list
*next
= srv
->next
;
1150 struct nfs_list_data
{
1152 struct nfs_server_list
*srvrs
;
1155 void callit_cb(struct rpc_context
*rpc
, int status
, void *data _U_
, void *private_data
)
1157 struct nfs_list_data
*srv_data
= private_data
;
1158 struct sockaddr
*sin
;
1160 struct nfs_server_list
*srvr
;
1162 if (status
== RPC_STATUS_CANCEL
) {
1166 srv_data
->status
= -1;
1170 sin
= rpc_get_recv_sockaddr(rpc
);
1172 rpc_set_error(rpc
, "failed to get sockaddr in CALLIT callback");
1173 srv_data
->status
= -1;
1177 if (getnameinfo(sin
, sizeof(struct sockaddr_in
), &hostdd
[0], sizeof(hostdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1178 rpc_set_error(rpc
, "getnameinfo failed in CALLIT callback");
1179 srv_data
->status
= -1;
1184 srvr
= malloc(sizeof(struct nfs_server_list
));
1186 rpc_set_error(rpc
, "Malloc failed when allocating server structure");
1187 srv_data
->status
= -1;
1191 srvr
->addr
= strdup(hostdd
);
1192 if (srvr
->addr
== NULL
) {
1193 rpc_set_error(rpc
, "Strdup failed when allocating server structure");
1195 srv_data
->status
= -1;
1199 srvr
->next
= srv_data
->srvrs
;
1200 srv_data
->srvrs
= srvr
;
1203 struct nfs_server_list
*nfs_find_local_servers(void)
1205 struct rpc_context
*rpc
;
1206 struct nfs_list_data data
= {0, NULL
};
1207 struct timeval tv_start
, tv_current
;
1212 rpc
= rpc_init_udp_context();
1217 if (rpc_bind_udp(rpc
, "0.0.0.0", 0) < 0) {
1218 rpc_destroy_context(rpc
);
1223 /* get list of all interfaces */
1224 size
= sizeof(struct ifreq
);
1228 while (ifc
.ifc_len
== size
) {
1233 ifc
.ifc_buf
= malloc(size
);
1234 if (ioctl(rpc_get_fd(rpc
), SIOCGIFCONF
, (caddr_t
)&ifc
) < 0) {
1235 rpc_destroy_context(rpc
);
1241 for (i
= 0; (unsigned)i
< ifc
.ifc_len
/ sizeof(struct ifconf
); i
++) {
1244 if (ifc
.ifc_req
[i
].ifr_addr
.sa_family
!= AF_INET
) {
1247 if (ioctl(rpc_get_fd(rpc
), SIOCGIFFLAGS
, &ifc
.ifc_req
[i
]) < 0) {
1248 rpc_destroy_context(rpc
);
1252 if (!(ifc
.ifc_req
[i
].ifr_flags
& IFF_UP
)) {
1255 if (ifc
.ifc_req
[i
].ifr_flags
& IFF_LOOPBACK
) {
1258 if (!(ifc
.ifc_req
[i
].ifr_flags
& IFF_BROADCAST
)) {
1261 if (ioctl(rpc_get_fd(rpc
), SIOCGIFBRDADDR
, &ifc
.ifc_req
[i
]) < 0) {
1264 if (getnameinfo(&ifc
.ifc_req
[i
].ifr_broadaddr
, sizeof(struct sockaddr_in
), &bcdd
[0], sizeof(bcdd
), NULL
, 0, NI_NUMERICHOST
) < 0) {
1267 if (rpc_set_udp_destination(rpc
, bcdd
, 111, 1) < 0) {
1268 rpc_destroy_context(rpc
);
1273 if (rpc_pmap_callit_async(rpc
, MOUNT_PROGRAM
, 2, 0, NULL
, 0, callit_cb
, &data
) < 0) {
1274 rpc_destroy_context(rpc
);
1281 gettimeofday(&tv_start
, NULL
);
1285 pfd
.fd
= rpc_get_fd(rpc
);
1286 pfd
.events
= rpc_which_events(rpc
);
1288 gettimeofday(&tv_current
, NULL
);
1290 - (tv_current
.tv_sec
*1000 + tv_current
.tv_usec
/ 1000)
1291 + (tv_start
.tv_sec
*1000 + tv_start
.tv_usec
/ 1000);
1293 if (poll(&pfd
, 1, mpt
) < 0) {
1294 free_nfs_srvr_list(data
.srvrs
);
1295 rpc_destroy_context(rpc
);
1298 if (pfd
.revents
== 0) {
1302 if (rpc_service(rpc
, pfd
.revents
) < 0) {
1307 rpc_destroy_context(rpc
);
1309 if (data
.status
!= 0) {
1310 free_nfs_srvr_list(data
.srvrs
);