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>
33 #include "libnfs-raw.h"
34 #include "rpc/mount.h"
46 static void wait_for_reply(struct nfs_context *nfs, struct sync_cb_data *cb_data)
51 if (cb_data->is_finished) {
54 pfd.fd = nfs_get_fd(nfs);
55 pfd.events = nfs_which_events(nfs);
57 if (poll(&pfd, 1, -1) < 0) {
58 printf("Poll failed");
59 cb_data->status = -EIO;
62 if (nfs_service(nfs, pfd.revents) < 0) {
63 printf("nfs_service failed\n");
64 cb_data->status = -EIO;
76 * connect to the server and mount the export
78 static void mount_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
80 struct sync_cb_data *cb_data = private_data;
82 cb_data->is_finished = 1;
83 cb_data->status = status;
86 printf("mount/mnt call failed with \"%s\"\n", (char *)data);
91 int nfs_mount_sync(struct nfs_context *nfs, const char *server, const char *export)
93 struct sync_cb_data cb_data;
95 cb_data.is_finished = 0;
97 if (nfs_mount_async(nfs, server, export, mount_cb, &cb_data) != 0) {
98 printf("nfs_mount_async failed\n");
102 wait_for_reply(nfs, &cb_data);
104 return cb_data.status;
111 static void stat_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
113 struct sync_cb_data *cb_data = private_data;
115 cb_data->is_finished = 1;
116 cb_data->status = status;
119 printf("stat call failed with \"%s\"\n", (char *)data);
123 memcpy(cb_data->return_data, data, sizeof(struct stat));
126 int nfs_stat_sync(struct nfs_context *nfs, const char *path, struct stat *st)
128 struct sync_cb_data cb_data;
130 cb_data.is_finished = 0;
131 cb_data.return_data = st;
133 if (nfs_stat_async(nfs, path, stat_cb, &cb_data) != 0) {
134 printf("nfs_stat_async failed\n");
138 wait_for_reply(nfs, &cb_data);
140 return cb_data.status;
149 static void open_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
151 struct sync_cb_data *cb_data = private_data;
152 struct nfsfh *fh, **nfsfh;
154 cb_data->is_finished = 1;
155 cb_data->status = status;
158 printf("open call failed with \"%s\"\n", (char *)data);
163 nfsfh = cb_data->return_data;
167 int nfs_open_sync(struct nfs_context *nfs, const char *path, int mode, struct nfsfh **nfsfh)
169 struct sync_cb_data cb_data;
171 cb_data.is_finished = 0;
172 cb_data.return_data = nfsfh;
174 if (nfs_open_async(nfs, path, mode, open_cb, &cb_data) != 0) {
175 printf("nfs_open_async failed\n");
179 wait_for_reply(nfs, &cb_data);
181 return cb_data.status;
190 static void pread_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
192 struct sync_cb_data *cb_data = private_data;
194 cb_data->is_finished = 1;
195 cb_data->status = status;
198 printf("pread call failed with \"%s\"\n", (char *)data);
202 buffer = cb_data->return_data;
203 memcpy(buffer, (char *)data, status);
206 int nfs_pread_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, size_t count, char *buffer)
208 struct sync_cb_data cb_data;
210 cb_data.is_finished = 0;
211 cb_data.return_data = buffer;
213 if (nfs_pread_async(nfs, nfsfh, offset, count, pread_cb, &cb_data) != 0) {
214 printf("nfs_pread_async failed\n");
218 wait_for_reply(nfs, &cb_data);
220 return cb_data.status;
226 int nfs_read_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, size_t count, char *buffer)
228 return nfs_pread_sync(nfs, nfsfh, nfs_get_current_offset(nfsfh), count, buffer);
234 static void close_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
236 struct sync_cb_data *cb_data = private_data;
237 cb_data->is_finished = 1;
238 cb_data->status = status;
241 printf("close call failed with \"%s\"\n", (char *)data);
246 int nfs_close_sync(struct nfs_context *nfs, struct nfsfh *nfsfh)
248 struct sync_cb_data cb_data;
250 cb_data.is_finished = 0;
252 if (nfs_close_async(nfs, nfsfh, close_cb, &cb_data) != 0) {
253 printf("nfs_close_async failed\n");
257 wait_for_reply(nfs, &cb_data);
259 return cb_data.status;
268 int nfs_fstat_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, struct stat *st)
270 struct sync_cb_data cb_data;
272 cb_data.is_finished = 0;
273 cb_data.return_data = st;
275 if (nfs_fstat_async(nfs, nfsfh, stat_cb, &cb_data) != 0) {
276 printf("nfs_fstat_async failed\n");
280 wait_for_reply(nfs, &cb_data);
282 return cb_data.status;
289 static void pwrite_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
291 struct sync_cb_data *cb_data = private_data;
292 cb_data->is_finished = 1;
293 cb_data->status = status;
296 printf("pwrite call failed with \"%s\"\n", (char *)data);
301 int nfs_pwrite_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, size_t count, char *buf)
303 struct sync_cb_data cb_data;
305 cb_data.is_finished = 0;
307 if (nfs_pwrite_async(nfs, nfsfh, offset, count, buf, pwrite_cb, &cb_data) != 0) {
308 printf("nfs_pwrite_async failed\n");
312 wait_for_reply(nfs, &cb_data);
314 return cb_data.status;
320 int nfs_write_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, size_t count, char *buf)
322 return nfs_pwrite_sync(nfs, nfsfh, nfs_get_current_offset(nfsfh), count, buf);
329 static void fsync_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
331 struct sync_cb_data *cb_data = private_data;
332 cb_data->is_finished = 1;
333 cb_data->status = status;
336 printf("fsync call failed with \"%s\"\n", (char *)data);
341 int nfs_fsync_sync(struct nfs_context *nfs, struct nfsfh *nfsfh)
343 struct sync_cb_data cb_data;
345 cb_data.is_finished = 0;
347 if (nfs_fsync_async(nfs, nfsfh, fsync_cb, &cb_data) != 0) {
348 printf("nfs_fsync_async failed\n");
352 wait_for_reply(nfs, &cb_data);
354 return cb_data.status;
363 static void ftruncate_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
365 struct sync_cb_data *cb_data = private_data;
366 cb_data->is_finished = 1;
367 cb_data->status = status;
370 printf("ftruncate call failed with \"%s\"\n", (char *)data);
375 int nfs_ftruncate_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t length)
377 struct sync_cb_data cb_data;
379 cb_data.is_finished = 0;
381 if (nfs_ftruncate_async(nfs, nfsfh, length, ftruncate_cb, &cb_data) != 0) {
382 printf("nfs_ftruncate_async failed\n");
386 wait_for_reply(nfs, &cb_data);
388 return cb_data.status;
396 static void truncate_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
398 struct sync_cb_data *cb_data = private_data;
399 cb_data->is_finished = 1;
400 cb_data->status = status;
403 printf("truncate call failed with \"%s\"\n", (char *)data);
408 int nfs_truncate_sync(struct nfs_context *nfs, const char *path, off_t length)
410 struct sync_cb_data cb_data;
412 cb_data.is_finished = 0;
414 if (nfs_truncate_async(nfs, path, length, truncate_cb, &cb_data) != 0) {
415 printf("nfs_ftruncate_async failed\n");
419 wait_for_reply(nfs, &cb_data);
421 return cb_data.status;
431 static void mkdir_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
433 struct sync_cb_data *cb_data = private_data;
434 cb_data->is_finished = 1;
435 cb_data->status = status;
438 printf("mkdir call failed with \"%s\"\n", (char *)data);
443 int nfs_mkdir_sync(struct nfs_context *nfs, const char *path)
445 struct sync_cb_data cb_data;
447 cb_data.is_finished = 0;
449 if (nfs_mkdir_async(nfs, path, mkdir_cb, &cb_data) != 0) {
450 printf("nfs_mkdir_async failed\n");
454 wait_for_reply(nfs, &cb_data);
456 return cb_data.status;
466 static void rmdir_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
468 struct sync_cb_data *cb_data = private_data;
469 cb_data->is_finished = 1;
470 cb_data->status = status;
473 printf("rmdir call failed with \"%s\"\n", (char *)data);
478 int nfs_rmdir_sync(struct nfs_context *nfs, const char *path)
480 struct sync_cb_data cb_data;
482 cb_data.is_finished = 0;
484 if (nfs_rmdir_async(nfs, path, rmdir_cb, &cb_data) != 0) {
485 printf("nfs_rmdir_async failed\n");
489 wait_for_reply(nfs, &cb_data);
491 return cb_data.status;
499 static void creat_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
501 struct sync_cb_data *cb_data = private_data;
502 struct nfsfh *fh, **nfsfh;
504 cb_data->is_finished = 1;
505 cb_data->status = status;
508 printf("creat call failed with \"%s\"\n", (char *)data);
513 nfsfh = cb_data->return_data;
517 int nfs_creat_sync(struct nfs_context *nfs, const char *path, int mode, struct nfsfh **nfsfh)
519 struct sync_cb_data cb_data;
521 cb_data.is_finished = 0;
522 cb_data.return_data = nfsfh;
524 if (nfs_creat_async(nfs, path, mode, creat_cb, &cb_data) != 0) {
525 printf("nfs_creat_async failed\n");
529 wait_for_reply(nfs, &cb_data);
531 return cb_data.status;
540 static void unlink_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
542 struct sync_cb_data *cb_data = private_data;
544 cb_data->is_finished = 1;
545 cb_data->status = status;
548 printf("unlink call failed with \"%s\"\n", (char *)data);
553 int nfs_unlink_sync(struct nfs_context *nfs, const char *path)
555 struct sync_cb_data cb_data;
557 cb_data.is_finished = 0;
559 if (nfs_unlink_async(nfs, path, unlink_cb, &cb_data) != 0) {
560 printf("nfs_unlink_async failed\n");
564 wait_for_reply(nfs, &cb_data);
566 return cb_data.status;
574 static void opendir_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
576 struct sync_cb_data *cb_data = private_data;
577 struct nfsdir *dir, **nfsdir;
579 cb_data->is_finished = 1;
580 cb_data->status = status;
583 printf("opendir call failed with \"%s\"\n", (char *)data);
588 nfsdir = cb_data->return_data;
592 int nfs_opendir_sync(struct nfs_context *nfs, const char *path, struct nfsdir **nfsdir)
594 struct sync_cb_data cb_data;
596 cb_data.is_finished = 0;
597 cb_data.return_data = nfsdir;
599 if (nfs_opendir_async(nfs, path, opendir_cb, &cb_data) != 0) {
600 printf("nfs_opendir_async failed\n");
604 wait_for_reply(nfs, &cb_data);
606 return cb_data.status;
613 static void lseek_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
615 struct sync_cb_data *cb_data = private_data;
617 cb_data->is_finished = 1;
618 cb_data->status = status;
621 printf("lseek call failed with \"%s\"\n", (char *)data);
625 if (cb_data->return_data != NULL) {
626 memcpy(cb_data->return_data, data, sizeof(off_t));
630 int nfs_lseek_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, int whence, off_t *current_offset)
632 struct sync_cb_data cb_data;
634 cb_data.is_finished = 0;
635 cb_data.return_data = current_offset;
637 if (nfs_lseek_async(nfs, nfsfh, offset, whence, lseek_cb, &cb_data) != 0) {
638 printf("nfs_lseek_async failed\n");
642 wait_for_reply(nfs, &cb_data);
644 return cb_data.status;
652 static void statvfs_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
654 struct sync_cb_data *cb_data = private_data;
656 cb_data->is_finished = 1;
657 cb_data->status = status;
660 printf("statvfs call failed with \"%s\"\n", (char *)data);
664 memcpy(cb_data->return_data, data, sizeof(struct statvfs));
667 int nfs_statvfs_sync(struct nfs_context *nfs, const char *path, struct statvfs *svfs)
669 struct sync_cb_data cb_data;
671 cb_data.is_finished = 0;
672 cb_data.return_data = svfs;
674 if (nfs_statvfs_async(nfs, path, statvfs_cb, &cb_data) != 0) {
675 printf("nfs_statvfs_async failed\n");
679 wait_for_reply(nfs, &cb_data);
681 return cb_data.status;
691 static void readlink_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
693 struct sync_cb_data *cb_data = private_data;
695 cb_data->is_finished = 1;
696 cb_data->status = status;
699 printf("readlink call failed with \"%s\"\n", (char *)data);
703 if (strlen(data) > (size_t)cb_data->return_int) {
704 printf("Too small buffer for readlink\n");
705 cb_data->status = -ENAMETOOLONG;
709 memcpy(cb_data->return_data, data, strlen(data)+1);
712 int nfs_readlink_sync(struct nfs_context *nfs, const char *path, char *buf, int bufsize)
714 struct sync_cb_data cb_data;
716 cb_data.is_finished = 0;
717 cb_data.return_data = buf;
718 cb_data.return_int = bufsize;
720 if (nfs_readlink_async(nfs, path, readlink_cb, &cb_data) != 0) {
721 printf("nfs_readlink_async failed\n");
725 wait_for_reply(nfs, &cb_data);
727 return cb_data.status;
735 static void chmod_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
737 struct sync_cb_data *cb_data = private_data;
739 cb_data->is_finished = 1;
740 cb_data->status = status;
743 printf("chmod call failed with \"%s\"\n", (char *)data);
748 int nfs_chmod_sync(struct nfs_context *nfs, const char *path, int mode)
750 struct sync_cb_data cb_data;
752 cb_data.is_finished = 0;
754 if (nfs_chmod_async(nfs, path, mode, chmod_cb, &cb_data) != 0) {
755 printf("nfs_chmod_async failed\n");
759 wait_for_reply(nfs, &cb_data);
761 return cb_data.status;
770 static void fchmod_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
772 struct sync_cb_data *cb_data = private_data;
774 cb_data->is_finished = 1;
775 cb_data->status = status;
778 printf("fchmod call failed with \"%s\"\n", (char *)data);
783 int nfs_fchmod_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode)
785 struct sync_cb_data cb_data;
787 cb_data.is_finished = 0;
789 if (nfs_fchmod_async(nfs, nfsfh, mode, fchmod_cb, &cb_data) != 0) {
790 printf("nfs_fchmod_async failed\n");
794 wait_for_reply(nfs, &cb_data);
796 return cb_data.status;
805 static void chown_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
807 struct sync_cb_data *cb_data = private_data;
809 cb_data->is_finished = 1;
810 cb_data->status = status;
813 printf("chown call failed with \"%s\"\n", (char *)data);
818 int nfs_chown_sync(struct nfs_context *nfs, const char *path, int uid, int gid)
820 struct sync_cb_data cb_data;
822 cb_data.is_finished = 0;
824 if (nfs_chown_async(nfs, path, uid, gid, chown_cb, &cb_data) != 0) {
825 printf("nfs_chown_async failed\n");
829 wait_for_reply(nfs, &cb_data);
831 return cb_data.status;
837 static void fchown_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
839 struct sync_cb_data *cb_data = private_data;
841 cb_data->is_finished = 1;
842 cb_data->status = status;
845 printf("fchown call failed with \"%s\"\n", (char *)data);
850 int nfs_fchown_sync(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid)
852 struct sync_cb_data cb_data;
854 cb_data.is_finished = 0;
856 if (nfs_fchown_async(nfs, nfsfh, uid, gid, fchown_cb, &cb_data) != 0) {
857 printf("nfs_fchown_async failed\n");
861 wait_for_reply(nfs, &cb_data);
863 return cb_data.status;
871 static void utimes_cb(int status, struct nfs_context *nfs _U_, 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 printf("utimes call failed with \"%s\"\n", (char *)data);
884 int nfs_utimes_sync(struct nfs_context *nfs, const char *path, struct timeval *times)
886 struct sync_cb_data cb_data;
888 cb_data.is_finished = 0;
890 if (nfs_utimes_async(nfs, path, times, utimes_cb, &cb_data) != 0) {
891 printf("nfs_utimes_async failed\n");
895 wait_for_reply(nfs, &cb_data);
897 return cb_data.status;
905 static void utime_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
907 struct sync_cb_data *cb_data = private_data;
909 cb_data->is_finished = 1;
910 cb_data->status = status;
913 printf("utime call failed with \"%s\"\n", (char *)data);
918 int nfs_utime_sync(struct nfs_context *nfs, const char *path, struct utimbuf *times)
920 struct sync_cb_data cb_data;
922 cb_data.is_finished = 0;
924 if (nfs_utime_async(nfs, path, times, utime_cb, &cb_data) != 0) {
925 printf("nfs_utimes_async failed\n");
929 wait_for_reply(nfs, &cb_data);
931 return cb_data.status;
940 static void access_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
942 struct sync_cb_data *cb_data = private_data;
944 cb_data->is_finished = 1;
945 cb_data->status = status;
948 printf("access call failed with \"%s\"\n", (char *)data);
953 int nfs_access_sync(struct nfs_context *nfs, const char *path, int mode)
955 struct sync_cb_data cb_data;
957 cb_data.is_finished = 0;
959 if (nfs_access_async(nfs, path, mode, access_cb, &cb_data) != 0) {
960 printf("nfs_access_async failed\n");
964 wait_for_reply(nfs, &cb_data);
966 return cb_data.status;
974 static void symlink_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
976 struct sync_cb_data *cb_data = private_data;
978 cb_data->is_finished = 1;
979 cb_data->status = status;
982 printf("symlink call failed with \"%s\"\n", (char *)data);
987 int nfs_symlink_sync(struct nfs_context *nfs, const char *oldpath, const char *newpath)
989 struct sync_cb_data cb_data;
991 cb_data.is_finished = 0;
993 if (nfs_symlink_async(nfs, oldpath, newpath, symlink_cb, &cb_data) != 0) {
994 printf("nfs_symlink_async failed\n");
998 wait_for_reply(nfs, &cb_data);
1000 return cb_data.status;
1008 static void rename_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
1010 struct sync_cb_data *cb_data = private_data;
1012 cb_data->is_finished = 1;
1013 cb_data->status = status;
1016 printf("rename call failed with \"%s\"\n", (char *)data);
1021 int nfs_rename_sync(struct nfs_context *nfs, const char *oldpath, const char *newpath)
1023 struct sync_cb_data cb_data;
1025 cb_data.is_finished = 0;
1027 if (nfs_rename_async(nfs, oldpath, newpath, rename_cb, &cb_data) != 0) {
1028 printf("nfs_rename_async failed\n");
1032 wait_for_reply(nfs, &cb_data);
1034 return cb_data.status;
1042 static void link_cb(int status, struct nfs_context *nfs _U_, void *data, void *private_data)
1044 struct sync_cb_data *cb_data = private_data;
1046 cb_data->is_finished = 1;
1047 cb_data->status = status;
1050 printf("link call failed with \"%s\"\n", (char *)data);
1055 int nfs_link_sync(struct nfs_context *nfs, const char *oldpath, const char *newpath)
1057 struct sync_cb_data cb_data;
1059 cb_data.is_finished = 0;
1061 if (nfs_link_async(nfs, oldpath, newpath, link_cb, &cb_data) != 0) {
1062 printf("nfs_link_async failed\n");
1066 wait_for_reply(nfs, &cb_data);
1068 return cb_data.status;