2 Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2010
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 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 General Public License for more details.
14 You should have received a copy of the GNU 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>
32 #include <ccan/compiler/compiler.h>
34 #include "libnfs-raw.h"
35 #include "rpc/mount.h"
47 static void wait_for_reply(struct nfs_context *nfs, struct sync_cb_data *cb_data)
52 if (cb_data->is_finished) {
55 pfd.fd = nfs_get_fd(nfs);
56 pfd.events = nfs_which_events(nfs);
58 if (poll(&pfd, 1, -1) < 0) {
59 printf("Poll failed");
60 cb_data->status = -EIO;
63 if (nfs_service(nfs, pfd.revents) < 0) {
64 printf("nfs_service failed\n");
65 cb_data->status = -EIO;
77 * connect to the server and mount the export
79 static void mount_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
81 struct sync_cb_data *cb_data = private_data;
83 cb_data->is_finished = 1;
84 cb_data->status = status;
87 printf("mount/mnt call failed with \"%s\"\n", (char *)data);
92 int nfs_mount_sync(struct nfs_context *nfs, const char *server, const char *export)
94 struct sync_cb_data cb_data;
96 cb_data.is_finished = 0;
98 if (nfs_mount_async(nfs, server, export, mount_cb, &cb_data) != 0) {
99 printf("nfs_mount_async failed\n");
103 wait_for_reply(nfs, &cb_data);
105 return cb_data.status;
112 static void stat_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
114 struct sync_cb_data *cb_data = private_data;
116 cb_data->is_finished = 1;
117 cb_data->status = status;
120 printf("stat call failed with \"%s\"\n", (char *)data);
124 memcpy(cb_data->return_data, data, sizeof(struct stat));
127 int nfs_stat_sync(struct nfs_context *nfs, const char *path, struct stat *st)
129 struct sync_cb_data cb_data;
131 cb_data.is_finished = 0;
132 cb_data.return_data = st;
134 if (nfs_stat_async(nfs, path, stat_cb, &cb_data) != 0) {
135 printf("nfs_stat_async failed\n");
139 wait_for_reply(nfs, &cb_data);
141 return cb_data.status;
150 static void open_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
152 struct sync_cb_data *cb_data = private_data;
153 struct nfsfh *fh, **nfsfh;
155 cb_data->is_finished = 1;
156 cb_data->status = status;
159 printf("open call failed with \"%s\"\n", (char *)data);
164 nfsfh = cb_data->return_data;
168 int nfs_open_sync(struct nfs_context *nfs, const char *path, int mode, struct nfsfh **nfsfh)
170 struct sync_cb_data cb_data;
172 cb_data.is_finished = 0;
173 cb_data.return_data = nfsfh;
175 if (nfs_open_async(nfs, path, mode, open_cb, &cb_data) != 0) {
176 printf("nfs_open_async failed\n");
180 wait_for_reply(nfs, &cb_data);
182 return cb_data.status;
191 static void pread_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
193 struct sync_cb_data *cb_data = private_data;
195 cb_data->is_finished = 1;
196 cb_data->status = status;
199 printf("pread call failed with \"%s\"\n", (char *)data);
203 buffer = cb_data->return_data;
204 memcpy(buffer, (char *)data, status);
207 int nfs_pread_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_off_t offset, size_t count, char *buffer)
209 struct sync_cb_data cb_data;
211 cb_data.is_finished = 0;
212 cb_data.return_data = buffer;
214 if (nfs_pread_async(nfs, nfsfh, offset, count, pread_cb, &cb_data) != 0) {
215 printf("nfs_pread_async failed\n");
219 wait_for_reply(nfs, &cb_data);
221 return cb_data.status;
227 int nfs_read_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, size_t count, char *buffer)
229 return nfs_pread_sync(nfs, nfsfh, nfs_get_current_offset(nfsfh), count, buffer);
235 static void close_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
237 struct sync_cb_data *cb_data = private_data;
238 cb_data->is_finished = 1;
239 cb_data->status = status;
242 printf("close call failed with \"%s\"\n", (char *)data);
247 int nfs_close_sync(struct nfs_context *nfs, struct nfsfh *nfsfh)
249 struct sync_cb_data cb_data;
251 cb_data.is_finished = 0;
253 if (nfs_close_async(nfs, nfsfh, close_cb, &cb_data) != 0) {
254 printf("nfs_close_async failed\n");
258 wait_for_reply(nfs, &cb_data);
260 return cb_data.status;
269 int nfs_fstat_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, struct stat *st)
271 struct sync_cb_data cb_data;
273 cb_data.is_finished = 0;
274 cb_data.return_data = st;
276 if (nfs_fstat_async(nfs, nfsfh, stat_cb, &cb_data) != 0) {
277 printf("nfs_fstat_async failed\n");
281 wait_for_reply(nfs, &cb_data);
283 return cb_data.status;
290 static void pwrite_cb(int status, struct nfs_context *nfs UNUSED, 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 printf("pwrite call failed with \"%s\"\n", (char *)data);
302 int nfs_pwrite_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_off_t offset, size_t count, char *buf)
304 struct sync_cb_data cb_data;
306 cb_data.is_finished = 0;
308 if (nfs_pwrite_async(nfs, nfsfh, offset, count, buf, pwrite_cb, &cb_data) != 0) {
309 printf("nfs_pwrite_async failed\n");
313 wait_for_reply(nfs, &cb_data);
315 return cb_data.status;
321 int nfs_write_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, size_t count, char *buf)
323 return nfs_pwrite_sync(nfs, nfsfh, nfs_get_current_offset(nfsfh), count, buf);
330 static void fsync_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
332 struct sync_cb_data *cb_data = private_data;
333 cb_data->is_finished = 1;
334 cb_data->status = status;
337 printf("fsync call failed with \"%s\"\n", (char *)data);
342 int nfs_fsync_sync(struct nfs_context *nfs, struct nfsfh *nfsfh)
344 struct sync_cb_data cb_data;
346 cb_data.is_finished = 0;
348 if (nfs_fsync_async(nfs, nfsfh, fsync_cb, &cb_data) != 0) {
349 printf("nfs_fsync_async failed\n");
353 wait_for_reply(nfs, &cb_data);
355 return cb_data.status;
364 static void ftruncate_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
366 struct sync_cb_data *cb_data = private_data;
367 cb_data->is_finished = 1;
368 cb_data->status = status;
371 printf("ftruncate call failed with \"%s\"\n", (char *)data);
376 int nfs_ftruncate_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_off_t length)
378 struct sync_cb_data cb_data;
380 cb_data.is_finished = 0;
382 if (nfs_ftruncate_async(nfs, nfsfh, length, ftruncate_cb, &cb_data) != 0) {
383 printf("nfs_ftruncate_async failed\n");
387 wait_for_reply(nfs, &cb_data);
389 return cb_data.status;
397 static void truncate_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
399 struct sync_cb_data *cb_data = private_data;
400 cb_data->is_finished = 1;
401 cb_data->status = status;
404 printf("truncate call failed with \"%s\"\n", (char *)data);
409 int nfs_truncate_sync(struct nfs_context *nfs, const char *path, nfs_off_t length)
411 struct sync_cb_data cb_data;
413 cb_data.is_finished = 0;
415 if (nfs_truncate_async(nfs, path, length, truncate_cb, &cb_data) != 0) {
416 printf("nfs_ftruncate_async failed\n");
420 wait_for_reply(nfs, &cb_data);
422 return cb_data.status;
432 static void mkdir_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
434 struct sync_cb_data *cb_data = private_data;
435 cb_data->is_finished = 1;
436 cb_data->status = status;
439 printf("mkdir call failed with \"%s\"\n", (char *)data);
444 int nfs_mkdir_sync(struct nfs_context *nfs, const char *path)
446 struct sync_cb_data cb_data;
448 cb_data.is_finished = 0;
450 if (nfs_mkdir_async(nfs, path, mkdir_cb, &cb_data) != 0) {
451 printf("nfs_mkdir_async failed\n");
455 wait_for_reply(nfs, &cb_data);
457 return cb_data.status;
467 static void rmdir_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
469 struct sync_cb_data *cb_data = private_data;
470 cb_data->is_finished = 1;
471 cb_data->status = status;
474 printf("rmdir call failed with \"%s\"\n", (char *)data);
479 int nfs_rmdir_sync(struct nfs_context *nfs, const char *path)
481 struct sync_cb_data cb_data;
483 cb_data.is_finished = 0;
485 if (nfs_rmdir_async(nfs, path, rmdir_cb, &cb_data) != 0) {
486 printf("nfs_rmdir_async failed\n");
490 wait_for_reply(nfs, &cb_data);
492 return cb_data.status;
500 static void creat_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
502 struct sync_cb_data *cb_data = private_data;
503 struct nfsfh *fh, **nfsfh;
505 cb_data->is_finished = 1;
506 cb_data->status = status;
509 printf("creat call failed with \"%s\"\n", (char *)data);
514 nfsfh = cb_data->return_data;
518 int nfs_creat_sync(struct nfs_context *nfs, const char *path, int mode, struct nfsfh **nfsfh)
520 struct sync_cb_data cb_data;
522 cb_data.is_finished = 0;
523 cb_data.return_data = nfsfh;
525 if (nfs_creat_async(nfs, path, mode, creat_cb, &cb_data) != 0) {
526 printf("nfs_creat_async failed\n");
530 wait_for_reply(nfs, &cb_data);
532 return cb_data.status;
541 static void unlink_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
543 struct sync_cb_data *cb_data = private_data;
545 cb_data->is_finished = 1;
546 cb_data->status = status;
549 printf("unlink call failed with \"%s\"\n", (char *)data);
554 int nfs_unlink_sync(struct nfs_context *nfs, const char *path)
556 struct sync_cb_data cb_data;
558 cb_data.is_finished = 0;
560 if (nfs_unlink_async(nfs, path, unlink_cb, &cb_data) != 0) {
561 printf("nfs_unlink_async failed\n");
565 wait_for_reply(nfs, &cb_data);
567 return cb_data.status;
575 static void opendir_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
577 struct sync_cb_data *cb_data = private_data;
578 struct nfsdir *dir, **nfsdir;
580 cb_data->is_finished = 1;
581 cb_data->status = status;
584 printf("opendir call failed with \"%s\"\n", (char *)data);
589 nfsdir = cb_data->return_data;
593 int nfs_opendir_sync(struct nfs_context *nfs, const char *path, struct nfsdir **nfsdir)
595 struct sync_cb_data cb_data;
597 cb_data.is_finished = 0;
598 cb_data.return_data = nfsdir;
600 if (nfs_opendir_async(nfs, path, opendir_cb, &cb_data) != 0) {
601 printf("nfs_opendir_async failed\n");
605 wait_for_reply(nfs, &cb_data);
607 return cb_data.status;
614 static void lseek_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
616 struct sync_cb_data *cb_data = private_data;
618 cb_data->is_finished = 1;
619 cb_data->status = status;
622 printf("lseek call failed with \"%s\"\n", (char *)data);
626 if (cb_data->return_data != NULL) {
627 memcpy(cb_data->return_data, data, sizeof(nfs_off_t));
631 int nfs_lseek_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_off_t offset, int whence, nfs_off_t *current_offset)
633 struct sync_cb_data cb_data;
635 cb_data.is_finished = 0;
636 cb_data.return_data = current_offset;
638 if (nfs_lseek_async(nfs, nfsfh, offset, whence, lseek_cb, &cb_data) != 0) {
639 printf("nfs_lseek_async failed\n");
643 wait_for_reply(nfs, &cb_data);
645 return cb_data.status;
653 static void statvfs_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
655 struct sync_cb_data *cb_data = private_data;
657 cb_data->is_finished = 1;
658 cb_data->status = status;
661 printf("statvfs call failed with \"%s\"\n", (char *)data);
665 memcpy(cb_data->return_data, data, sizeof(struct statvfs));
668 int nfs_statvfs_sync(struct nfs_context *nfs, const char *path, struct statvfs *svfs)
670 struct sync_cb_data cb_data;
672 cb_data.is_finished = 0;
673 cb_data.return_data = svfs;
675 if (nfs_statvfs_async(nfs, path, statvfs_cb, &cb_data) != 0) {
676 printf("nfs_statvfs_async failed\n");
680 wait_for_reply(nfs, &cb_data);
682 return cb_data.status;
692 static void readlink_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
694 struct sync_cb_data *cb_data = private_data;
696 cb_data->is_finished = 1;
697 cb_data->status = status;
700 printf("readlink call failed with \"%s\"\n", (char *)data);
704 if (strlen(data) > (size_t)cb_data->return_int) {
705 printf("Too small buffer for readlink\n");
706 cb_data->status = -ENAMETOOLONG;
710 memcpy(cb_data->return_data, data, strlen(data)+1);
713 int nfs_readlink_sync(struct nfs_context *nfs, const char *path, char *buf, int bufsize)
715 struct sync_cb_data cb_data;
717 cb_data.is_finished = 0;
718 cb_data.return_data = buf;
719 cb_data.return_int = bufsize;
721 if (nfs_readlink_async(nfs, path, readlink_cb, &cb_data) != 0) {
722 printf("nfs_readlink_async failed\n");
726 wait_for_reply(nfs, &cb_data);
728 return cb_data.status;
736 static void chmod_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
738 struct sync_cb_data *cb_data = private_data;
740 cb_data->is_finished = 1;
741 cb_data->status = status;
744 printf("chmod call failed with \"%s\"\n", (char *)data);
749 int nfs_chmod_sync(struct nfs_context *nfs, const char *path, int mode)
751 struct sync_cb_data cb_data;
753 cb_data.is_finished = 0;
755 if (nfs_chmod_async(nfs, path, mode, chmod_cb, &cb_data) != 0) {
756 printf("nfs_chmod_async failed\n");
760 wait_for_reply(nfs, &cb_data);
762 return cb_data.status;
771 static void fchmod_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
773 struct sync_cb_data *cb_data = private_data;
775 cb_data->is_finished = 1;
776 cb_data->status = status;
779 printf("fchmod call failed with \"%s\"\n", (char *)data);
784 int nfs_fchmod_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode)
786 struct sync_cb_data cb_data;
788 cb_data.is_finished = 0;
790 if (nfs_fchmod_async(nfs, nfsfh, mode, fchmod_cb, &cb_data) != 0) {
791 printf("nfs_fchmod_async failed\n");
795 wait_for_reply(nfs, &cb_data);
797 return cb_data.status;
806 static void chown_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
808 struct sync_cb_data *cb_data = private_data;
810 cb_data->is_finished = 1;
811 cb_data->status = status;
814 printf("chown call failed with \"%s\"\n", (char *)data);
819 int nfs_chown_sync(struct nfs_context *nfs, const char *path, int uid, int gid)
821 struct sync_cb_data cb_data;
823 cb_data.is_finished = 0;
825 if (nfs_chown_async(nfs, path, uid, gid, chown_cb, &cb_data) != 0) {
826 printf("nfs_chown_async failed\n");
830 wait_for_reply(nfs, &cb_data);
832 return cb_data.status;
838 static void fchown_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
840 struct sync_cb_data *cb_data = private_data;
842 cb_data->is_finished = 1;
843 cb_data->status = status;
846 printf("fchown call failed with \"%s\"\n", (char *)data);
851 int nfs_fchown_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid)
853 struct sync_cb_data cb_data;
855 cb_data.is_finished = 0;
857 if (nfs_fchown_async(nfs, nfsfh, uid, gid, fchown_cb, &cb_data) != 0) {
858 printf("nfs_fchown_async failed\n");
862 wait_for_reply(nfs, &cb_data);
864 return cb_data.status;
872 static void utimes_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
874 struct sync_cb_data *cb_data = private_data;
876 cb_data->is_finished = 1;
877 cb_data->status = status;
880 printf("utimes call failed with \"%s\"\n", (char *)data);
885 int nfs_utimes_sync(struct nfs_context *nfs, const char *path, struct timeval *times)
887 struct sync_cb_data cb_data;
889 cb_data.is_finished = 0;
891 if (nfs_utimes_async(nfs, path, times, utimes_cb, &cb_data) != 0) {
892 printf("nfs_utimes_async failed\n");
896 wait_for_reply(nfs, &cb_data);
898 return cb_data.status;
906 static void utime_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
908 struct sync_cb_data *cb_data = private_data;
910 cb_data->is_finished = 1;
911 cb_data->status = status;
914 printf("utime call failed with \"%s\"\n", (char *)data);
919 int nfs_utime_sync(struct nfs_context *nfs, const char *path, struct utimbuf *times)
921 struct sync_cb_data cb_data;
923 cb_data.is_finished = 0;
925 if (nfs_utime_async(nfs, path, times, utime_cb, &cb_data) != 0) {
926 printf("nfs_utimes_async failed\n");
930 wait_for_reply(nfs, &cb_data);
932 return cb_data.status;
941 static void access_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
943 struct sync_cb_data *cb_data = private_data;
945 cb_data->is_finished = 1;
946 cb_data->status = status;
949 printf("access call failed with \"%s\"\n", (char *)data);
954 int nfs_access_sync(struct nfs_context *nfs, const char *path, int mode)
956 struct sync_cb_data cb_data;
958 cb_data.is_finished = 0;
960 if (nfs_access_async(nfs, path, mode, access_cb, &cb_data) != 0) {
961 printf("nfs_access_async failed\n");
965 wait_for_reply(nfs, &cb_data);
967 return cb_data.status;
975 static void symlink_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
977 struct sync_cb_data *cb_data = private_data;
979 cb_data->is_finished = 1;
980 cb_data->status = status;
983 printf("symlink call failed with \"%s\"\n", (char *)data);
988 int nfs_symlink_sync(struct nfs_context *nfs, const char *oldpath, const char *newpath)
990 struct sync_cb_data cb_data;
992 cb_data.is_finished = 0;
994 if (nfs_symlink_async(nfs, oldpath, newpath, symlink_cb, &cb_data) != 0) {
995 printf("nfs_symlink_async failed\n");
999 wait_for_reply(nfs, &cb_data);
1001 return cb_data.status;
1009 static void rename_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
1011 struct sync_cb_data *cb_data = private_data;
1013 cb_data->is_finished = 1;
1014 cb_data->status = status;
1017 printf("rename call failed with \"%s\"\n", (char *)data);
1022 int nfs_rename_sync(struct nfs_context *nfs, const char *oldpath, const char *newpath)
1024 struct sync_cb_data cb_data;
1026 cb_data.is_finished = 0;
1028 if (nfs_rename_async(nfs, oldpath, newpath, rename_cb, &cb_data) != 0) {
1029 printf("nfs_rename_async failed\n");
1033 wait_for_reply(nfs, &cb_data);
1035 return cb_data.status;
1043 static void link_cb(int status, struct nfs_context *nfs UNUSED, void *data, void *private_data)
1045 struct sync_cb_data *cb_data = private_data;
1047 cb_data->is_finished = 1;
1048 cb_data->status = status;
1051 printf("link call failed with \"%s\"\n", (char *)data);
1056 int nfs_link_sync(struct nfs_context *nfs, const char *oldpath, const char *newpath)
1058 struct sync_cb_data cb_data;
1060 cb_data.is_finished = 0;
1062 if (nfs_link_async(nfs, oldpath, newpath, link_cb, &cb_data) != 0) {
1063 printf("nfs_link_async failed\n");
1067 wait_for_reply(nfs, &cb_data);
1069 return cb_data.status;