4 Copyright (C) 2008 by Ronnie Sahlberg (ronniesahlberg@gmail.com)
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include <sys/types.h>
27 #define discard_const(ptr) ((void *)((intptr_t)(ptr)))
29 typedef struct _data_t {
34 typedef struct _tree_t {
37 struct _tree_t *parent;
39 struct _tree_t *right;
49 static void free_node(tree_t *t)
51 free(discard_const(t->key.dptr));
52 free(discard_const(t->fh.dptr));
56 static tree_t *find_fhandle(tree_t *tree, const char *key)
64 i = strcmp(key, tree->key.dptr);
69 return find_fhandle(tree->left, key);
72 return find_fhandle(tree->right, key);
75 static data_t *lookup_fhandle(struct nfsio *nfsio, const char *name)
79 while (name[0] == '.') name++;
85 t = find_fhandle(nfsio->fhandles, name);
93 static void delete_fhandle(struct nfsio *nfsio, const char *name)
97 while (name[0] == '.') name++;
99 t = find_fhandle(nfsio->fhandles, name);
104 /* we have a left child */
108 for(tmp_tree=t->left;tmp_tree->right;tmp_tree=tmp_tree->right)
110 tmp_tree->right = t->right;
112 if (t->parent == NULL) {
113 nfsio->fhandles = tmp_tree;
118 if (t->parent->left == t) {
119 t->parent->left = t->left;
124 t->parent->right = t->left;
129 /* we only have a right child */
133 for(tmp_tree=t->right;tmp_tree->left;tmp_tree=tmp_tree->left)
135 tmp_tree->left = t->left;
137 if (t->parent == NULL) {
138 nfsio->fhandles = tmp_tree;
143 if (t->parent->left == t) {
144 t->parent->left = t->right;
149 t->parent->right = t->right;
154 /* we are a leaf node */
155 if (t->parent == NULL) {
156 nfsio->fhandles = NULL;
158 if (t->parent->left == t) {
159 t->parent->left = NULL;
161 t->parent->right = NULL;
168 static void insert_fhandle(struct nfsio *nfsio, const char *name, const char *fhandle, int length)
174 while (name[0] == '.') name++;
176 t = malloc(sizeof(tree_t));
178 fprintf(stderr, "MALLOC failed to allocate tree_t in insert_fhandle\n");
182 t->key.dptr = strdup(name);
183 if (t->key.dptr == NULL) {
184 fprintf(stderr, "STRDUP failed to allocate key in insert_fhandle\n");
187 t->key.dsize = strlen(name);
190 t->fh.dptr = malloc(length);
191 if (t->key.dptr == NULL) {
192 fprintf(stderr, "MALLOC failed to allocate fhandle in insert_fhandle\n");
195 memcpy(discard_const(t->fh.dptr), fhandle, length);
196 t->fh.dsize = length;
202 if (nfsio->fhandles == NULL) {
207 tmp_t = nfsio->fhandles;
209 i = strcmp(t->key.dptr, tmp_t->key.dptr);
211 free(discard_const(tmp_t->fh.dptr));
212 tmp_t->fh.dsize = t->fh.dsize;
213 tmp_t->fh.dptr = t->fh.dptr;
214 free(discard_const(t->key.dptr));
219 if (tmp_t->left == NULL) {
227 if (tmp_t->right == NULL) {
232 tmp_t = tmp_t->right;
242 static const struct nfs_errors nfs_errors[] = {
245 {"NFS3ERR_NOENT", 2},
248 {"NFS3ERR_ACCES", 13},
249 {"NFS3ERR_EXIST", 17},
250 {"NFS3ERR_XDEV", 18},
251 {"NFS3ERR_NODEV", 19},
252 {"NFS3ERR_NOTDIR", 20},
253 {"NFS3ERR_ISDIR", 21},
254 {"NFS3ERR_INVAL", 22},
255 {"NFS3ERR_FBIG", 27},
256 {"NFS3ERR_NOSPC", 28},
257 {"NFS3ERR_ROFS", 30},
258 {"NFS3ERR_MLINK", 31},
259 {"NFS3ERR_NAMETOOLONG", 63},
260 {"NFS3ERR_NOTEMPTY", 66},
261 {"NFS3ERR_DQUOT", 69},
262 {"NFS3ERR_STALE", 70},
263 {"NFS3ERR_REMOTE", 71},
264 {"NFS3ERR_BADHANDLE", 10001},
265 {"NFS3ERR_NOT_SYNC", 10002},
266 {"NFS3ERR_BAD_COOKIE", 10003},
267 {"NFS3ERR_NOTSUPP", 10004},
268 {"NFS3ERR_TOOSMALL", 10005},
269 {"NFS3ERR_SERVERFAULT", 10006},
270 {"NFS3ERR_BADTYPE", 10007},
271 {"NFS3ERR_JUKEBOX", 10008},
276 const char *nfs_error(int error)
280 for(i=0;i<sizeof(nfs_errors)/sizeof(struct nfs_errors);i++) {
281 if (error == nfs_errors[i].idx) {
282 return nfs_errors[i].err;
285 return "Unknown NFS error";
291 void nfsio_disconnect(struct nfsio *nfsio)
293 if (nfsio->clnt != NULL) {
294 clnt_destroy(nfsio->clnt);
297 if (nfsio->s != -1) {
300 // qqq free the tree*/
308 struct nfsio *nfsio_connect(const char *server, const char *export, const char *protocol)
310 dirpath mountdir=discard_const(export);
314 struct sockaddr_in sin;
317 nfsio = malloc(sizeof(struct nfsio));
319 fprintf(stderr, "Failed to malloc nfsio\n");
322 bzero(nfsio, sizeof(struct nfsio));
328 * set up the MOUNT client. If we are running as root, we get
329 * a port <1024 by default. If we are not root, we can not
330 * bind to these ports, so the server must be in "insecure"
333 memset(&sin, 0, sizeof(sin));
335 sin.sin_family = PF_INET;
336 if (inet_aton(server, &sin.sin_addr) == 0) {
337 fprintf(stderr, "Invalid address '%s'\n", server);
338 nfsio_disconnect(nfsio);
342 if (!strcmp(protocol, "tcp")) {
343 nfsio->s = RPC_ANYSOCK;
344 nfsio->clnt = clnttcp_create(&sin, MOUNT_PROGRAM, MOUNT_V3, &nfsio->s, 32768, 32768);
350 nfsio->s = RPC_ANYSOCK;
351 nfsio->clnt = clntudp_create(&sin, MOUNT_PROGRAM, MOUNT_V3, wait, &nfsio->s);
354 if (nfsio->clnt == NULL) {
355 printf("ERROR: failed to connect to MOUNT daemon on %s\n", server);
356 nfsio_disconnect(nfsio);
359 nfsio->clnt->cl_auth = authunix_create_default();
361 mountres=mountproc3_mnt_3(&mountdir, nfsio->clnt);
362 if (mountres == NULL) {
363 printf("ERROR: failed to call the MNT procedure\n");
364 nfsio_disconnect(nfsio);
367 if (mountres->fhs_status != MNT3_OK) {
368 printf("ERROR: Server returned error %d when trying to MNT\n",mountres->fhs_status);
369 nfsio_disconnect(nfsio);
373 fh = &mountres->mountres3_u.mountinfo.fhandle;
374 insert_fhandle(nfsio, "/", fh->fhandle3_val, fh->fhandle3_len);
377 /* we dont need the mount client any more */
378 clnt_destroy(nfsio->clnt);
385 * set up the NFS client. If we are running as root, we get
386 * a port <1024 by default. If we are not root, we can not
387 * bind to these ports, so the server must be in "insecure"
390 memset(&sin, 0, sizeof(sin));
392 sin.sin_family = PF_INET;
393 if (inet_aton(server, &sin.sin_addr) == 0) {
394 fprintf(stderr, "Invalid address '%s'\n", server);
395 nfsio_disconnect(nfsio);
399 if (!strcmp(protocol, "tcp")) {
400 nfsio->s = RPC_ANYSOCK;
401 nfsio->clnt = clnttcp_create(&sin, NFS_PROGRAM, NFS_V3, &nfsio->s, 327680, 327680);
407 nfsio->s = RPC_ANYSOCK;
408 nfsio->clnt = clntudp_create(&sin, NFS_PROGRAM, NFS_V3, wait, &nfsio->s);
411 if (nfsio->clnt == NULL) {
412 fprintf(stderr, "Failed to initialize nfs client structure\n");
413 nfsio_disconnect(nfsio);
416 nfsio->clnt->cl_auth = authunix_create_default();
422 nfsstat3 nfsio_getattr(struct nfsio *nfsio, const char *name, fattr3 *attributes)
424 struct GETATTR3args GETATTR3args;
425 struct GETATTR3res *GETATTR3res;
428 fh = lookup_fhandle(nfsio, name);
430 fprintf(stderr, "failed to fetch handle in nfsio_getattr\n");
431 return NFS3ERR_SERVERFAULT;
434 GETATTR3args.object.data.data_len = fh->dsize;
435 GETATTR3args.object.data.data_val = discard_const(fh->dptr);
437 GETATTR3res = nfsproc3_getattr_3(&GETATTR3args, nfsio->clnt);
439 if (GETATTR3res == NULL) {
440 fprintf(stderr, "nfsproc3_getattr_3 failed in getattr\n");
441 return NFS3ERR_SERVERFAULT;
444 if (GETATTR3res->status != NFS3_OK) {
445 fprintf(stderr, "nfsproc3_getattr_3 failed in getattr. status:%d\n", GETATTR3res->status);
446 return GETATTR3res->status;
450 memcpy(attributes, &GETATTR3res->GETATTR3res_u.resok.obj_attributes, sizeof(fattr3));
456 nfsstat3 nfsio_lookup(struct nfsio *nfsio, const char *name, fattr3 *attributes)
459 struct LOOKUP3args LOOKUP3args;
460 struct LOOKUP3res *LOOKUP3res;
461 char *tmp_name = NULL;
466 tmp_name = strdup(name);
467 if (tmp_name == NULL) {
468 fprintf(stderr, "failed to strdup name in nfsio_lookup\n");
469 ret = NFS3ERR_SERVERFAULT;
473 ptr = rindex(tmp_name, '/');
475 fprintf(stderr, "name did not contain '/' in nfsio_lookup\n");
476 ret = NFS3ERR_SERVERFAULT;
483 fh = lookup_fhandle(nfsio, tmp_name);
485 fprintf(stderr, "failed to fetch parent handle for '%s' in nfsio_lookup\n", tmp_name);
486 ret = NFS3ERR_SERVERFAULT;
490 LOOKUP3args.what.dir.data.data_len = fh->dsize;
491 LOOKUP3args.what.dir.data.data_val = discard_const(fh->dptr);
492 LOOKUP3args.what.name = ptr;
494 LOOKUP3res = nfsproc3_lookup_3(&LOOKUP3args, nfsio->clnt);
496 if (LOOKUP3res == NULL) {
497 fprintf(stderr, "nfsproc3_lookup_3 failed in lookup\n");
498 ret = NFS3ERR_SERVERFAULT;
502 if (LOOKUP3res->status != NFS3_OK) {
503 ret = LOOKUP3res->status;
508 insert_fhandle(nfsio, name,
509 LOOKUP3res->LOOKUP3res_u.resok.object.data.data_val,
510 LOOKUP3res->LOOKUP3res_u.resok.object.data.data_len);
513 memcpy(attributes, &LOOKUP3res->LOOKUP3res_u.resok.obj_attributes.post_op_attr_u.attributes, sizeof(fattr3));
524 nfsstat3 nfsio_access(struct nfsio *nfsio, const char *name, uint32 desired, uint32 *access)
527 struct ACCESS3args ACCESS3args;
528 struct ACCESS3res *ACCESS3res;
531 fh = lookup_fhandle(nfsio, name);
533 fprintf(stderr, "failed to fetch handle in nfsio_access\n");
534 return NFS3ERR_SERVERFAULT;
537 ACCESS3args.object.data.data_val = discard_const(fh->dptr);
538 ACCESS3args.object.data.data_len = fh->dsize;
539 ACCESS3args.access = desired;
541 ACCESS3res = nfsproc3_access_3(&ACCESS3args, nfsio->clnt);
543 if (ACCESS3res == NULL) {
544 fprintf(stderr, "nfsproc3_access_3 failed in access\n");
545 return NFS3ERR_SERVERFAULT;
548 if (ACCESS3res->status != NFS3_OK) {
549 fprintf(stderr, "nfsproc3_access_3 failed. status:%d\n",
551 return ACCESS3res->status;
555 *access = ACCESS3res->ACCESS3res_u.resok.access;
563 nfsstat3 nfsio_create(struct nfsio *nfsio, const char *name)
566 struct CREATE3args CREATE3args;
567 struct CREATE3res *CREATE3res;
568 char *tmp_name = NULL;
573 tmp_name = strdup(name);
574 if (tmp_name == NULL) {
575 fprintf(stderr, "failed to strdup name in nfsio_create\n");
576 ret = NFS3ERR_SERVERFAULT;
580 ptr = rindex(tmp_name, '/');
582 fprintf(stderr, "name did not contain '/' in nfsio_create\n");
583 ret = NFS3ERR_SERVERFAULT;
590 fh = lookup_fhandle(nfsio, tmp_name);
592 fprintf(stderr, "failed to fetch parent handle in nfsio_create\n");
593 ret = NFS3ERR_SERVERFAULT;
597 CREATE3args.where.dir.data.data_len = fh->dsize;
598 CREATE3args.where.dir.data.data_val = discard_const(fh->dptr);
599 CREATE3args.where.name = ptr;
601 CREATE3args.how.mode = UNCHECKED;
602 CREATE3args.how.createhow3_u.obj_attributes.mode.set_it = TRUE;
603 CREATE3args.how.createhow3_u.obj_attributes.mode.set_mode3_u.mode = 0777;
604 CREATE3args.how.createhow3_u.obj_attributes.uid.set_it = TRUE;
605 CREATE3args.how.createhow3_u.obj_attributes.uid.set_uid3_u.uid = 0;
606 CREATE3args.how.createhow3_u.obj_attributes.gid.set_it = TRUE;
607 CREATE3args.how.createhow3_u.obj_attributes.gid.set_gid3_u.gid = 0;
608 CREATE3args.how.createhow3_u.obj_attributes.size.set_it = FALSE;
609 CREATE3args.how.createhow3_u.obj_attributes.atime.set_it = FALSE;
610 CREATE3args.how.createhow3_u.obj_attributes.mtime.set_it = FALSE;
612 CREATE3res = nfsproc3_create_3(&CREATE3args, nfsio->clnt);
614 if (CREATE3res == NULL) {
615 fprintf(stderr, "nfsproc3_create_3 failed in nfsio_create\n");
616 ret = NFS3ERR_SERVERFAULT;
620 if (CREATE3res->status != NFS3_OK) {
621 fprintf(stderr, "nfsproc3_create_3 failed in nfsio_create. status:%d\n", CREATE3res->status);
622 ret = CREATE3res->status;
627 insert_fhandle(nfsio, name,
628 CREATE3res->CREATE3res_u.resok.obj.post_op_fh3_u.handle.data.data_val,
629 CREATE3res->CREATE3res_u.resok.obj.post_op_fh3_u.handle.data.data_len);
639 nfsstat3 nfsio_remove(struct nfsio *nfsio, const char *name)
642 struct REMOVE3args REMOVE3args;
643 struct REMOVE3res *REMOVE3res;
645 char *tmp_name = NULL;
649 tmp_name = strdup(name);
650 if (tmp_name == NULL) {
651 fprintf(stderr, "failed to strdup name in nfsio_remove\n");
652 ret = NFS3ERR_SERVERFAULT;
656 ptr = rindex(tmp_name, '/');
658 fprintf(stderr, "name did not contain '/' in nfsio_remove\n");
659 ret = NFS3ERR_SERVERFAULT;
666 fh = lookup_fhandle(nfsio, tmp_name);
668 fprintf(stderr, "failed to fetch parent handle in nfsio_remove\n");
669 ret = NFS3ERR_SERVERFAULT;
674 REMOVE3args.object.dir.data.data_len = fh->dsize;
675 REMOVE3args.object.dir.data.data_val = discard_const(fh->dptr);
676 REMOVE3args.object.name = ptr;
678 REMOVE3res = nfsproc3_remove_3(&REMOVE3args, nfsio->clnt);
680 if (REMOVE3res == NULL) {
681 fprintf(stderr, "nfsproc3_remove_3 failed in nfsio_remove\n");
682 ret = NFS3ERR_SERVERFAULT;
686 if (REMOVE3res->status != NFS3_OK) {
687 fprintf(stderr, "nfsproc3_remove_3 failed in nfsio_remove. status:%d\n", REMOVE3res->status);
688 ret = REMOVE3res->status;
693 delete_fhandle(nfsio, name);
704 nfsstat3 nfsio_write(struct nfsio *nfsio, const char *name, char *buf, uint32 offset, int len, int stable)
706 struct WRITE3args WRITE3args;
707 struct WRITE3res *WRITE3res;
711 fh = lookup_fhandle(nfsio, name);
713 fprintf(stderr, "failed to fetch handle in nfsio_write\n");
714 ret = NFS3ERR_SERVERFAULT;
718 WRITE3args.file.data.data_len = fh->dsize;
719 WRITE3args.file.data.data_val = discard_const(fh->dptr);
720 WRITE3args.offset = offset;
721 WRITE3args.count = len;
722 WRITE3args.stable = stable;
723 WRITE3args.data.data_len = len;
724 WRITE3args.data.data_val = buf;
727 WRITE3res = nfsproc3_write_3(&WRITE3args, nfsio->clnt);
729 if (WRITE3res == NULL) {
730 fprintf(stderr, "nfsproc3_write_3 failed in nfsio_write\n");
731 ret = NFS3ERR_SERVERFAULT;
735 if (WRITE3res->status != NFS3_OK) {
736 fprintf(stderr, "nfsproc3_write_3 failed in getattr. status:%d\n", WRITE3res->status);
737 ret = WRITE3res->status;
744 nfsstat3 nfsio_read(struct nfsio *nfsio, const char *name, char *buf, uint32 offset, int len, int *count, int *eof)
746 struct READ3args READ3args;
747 struct READ3res *READ3res;
751 fh = lookup_fhandle(nfsio, name);
753 fprintf(stderr, "failed to fetch handle in nfsio_read\n");
754 ret = NFS3ERR_SERVERFAULT;
758 READ3args.file.data.data_len = fh->dsize;
759 READ3args.file.data.data_val = discard_const(fh->dptr);
760 READ3args.offset = offset;
761 READ3args.count = len;
763 READ3res = nfsproc3_read_3(&READ3args, nfsio->clnt);
765 if (READ3res == NULL) {
766 fprintf(stderr, "nfsproc3_read_3 failed in nfsio_read\n");
767 ret = NFS3ERR_SERVERFAULT;
771 if (READ3res->status != NFS3_OK) {
772 fprintf(stderr, "nfsproc3_read_3 failed in nfsio_read. status:%d\n", READ3res->status);
773 ret = READ3res->status;
778 *count = READ3res->READ3res_u.resok.count;
781 *eof = READ3res->READ3res_u.resok.eof;
783 memcpy(buf, &READ3res->READ3res_u.resok.data.data_val,
784 READ3res->READ3res_u.resok.count);
792 nfsstat3 nfsio_commit(struct nfsio *nfsio, const char *name)
794 struct COMMIT3args COMMIT3args;
795 struct COMMIT3res *COMMIT3res;
799 fh = lookup_fhandle(nfsio, name);
801 fprintf(stderr, "failed to fetch handle in nfsio_commit\n");
802 ret = NFS3ERR_SERVERFAULT;
806 COMMIT3args.file.data.data_len = fh->dsize;
807 COMMIT3args.file.data.data_val = discard_const(fh->dptr);
808 COMMIT3args.offset = 0;
809 COMMIT3args.count = 0;
812 COMMIT3res = nfsproc3_commit_3(&COMMIT3args, nfsio->clnt);
814 if (COMMIT3res == NULL) {
815 fprintf(stderr, "nfsproc3_commit_3 failed in nfsio_commit\n");
816 ret = NFS3ERR_SERVERFAULT;
820 if (COMMIT3res->status != NFS3_OK) {
821 fprintf(stderr, "nfsproc3_commit_3 failed in nfsio_commit. status:%d\n", COMMIT3res->status);
822 ret = COMMIT3res->status;
830 nfsstat3 nfsio_fsinfo(struct nfsio *nfsio)
832 struct FSINFO3args FSINFO3args;
833 struct FSINFO3res *FSINFO3res;
836 fh = lookup_fhandle(nfsio, "/");
838 fprintf(stderr, "failed to fetch handle in nfsio_fsinfo\n");
839 return NFS3ERR_SERVERFAULT;
842 FSINFO3args.fsroot.data.data_len = fh->dsize;
843 FSINFO3args.fsroot.data.data_val = discard_const(fh->dptr);
845 FSINFO3res = nfsproc3_fsinfo_3(&FSINFO3args, nfsio->clnt);
847 if (FSINFO3res == NULL) {
848 fprintf(stderr, "nfsproc3_fsinfo_3 failed in nfsio_fsinfo\n");
849 return NFS3ERR_SERVERFAULT;
852 if (FSINFO3res->status != NFS3_OK) {
853 fprintf(stderr, "nfsproc3_fsinfo_3 failed in nfsio_fsinfo. status:%d\n", FSINFO3res->status);
854 return FSINFO3res->status;
861 nfsstat3 nfsio_fsstat(struct nfsio *nfsio)
863 struct FSSTAT3args FSSTAT3args;
864 struct FSSTAT3res *FSSTAT3res;
867 fh = lookup_fhandle(nfsio, "/");
869 fprintf(stderr, "failed to fetch handle in nfsio_fsstat\n");
870 return NFS3ERR_SERVERFAULT;
873 FSSTAT3args.fsroot.data.data_len = fh->dsize;
874 FSSTAT3args.fsroot.data.data_val = discard_const(fh->dptr);
876 FSSTAT3res = nfsproc3_fsstat_3(&FSSTAT3args, nfsio->clnt);
878 if (FSSTAT3res == NULL) {
879 fprintf(stderr, "nfsproc3_fsstat_3 failed in nfsio_fsstat\n");
880 return NFS3ERR_SERVERFAULT;
883 if (FSSTAT3res->status != NFS3_OK) {
884 fprintf(stderr, "nfsproc3_fsstat_3 failed in nfsio_fsstat. status:%d\n", FSSTAT3res->status);
885 return FSSTAT3res->status;
891 nfsstat3 nfsio_pathconf(struct nfsio *nfsio, char *name)
893 struct PATHCONF3args PATHCONF3args;
894 struct PATHCONF3res *PATHCONF3res;
897 fh = lookup_fhandle(nfsio, name);
899 fprintf(stderr, "failed to fetch handle in nfsio_pathconf\n");
900 return NFS3ERR_SERVERFAULT;
903 PATHCONF3args.object.data.data_len = fh->dsize;
904 PATHCONF3args.object.data.data_val = discard_const(fh->dptr);
906 PATHCONF3res = nfsproc3_pathconf_3(&PATHCONF3args, nfsio->clnt);
908 if (PATHCONF3res == NULL) {
909 fprintf(stderr, "nfsproc3_pathconf_3 failed in nfsio_pathconf\n");
910 return NFS3ERR_SERVERFAULT;
913 if (PATHCONF3res->status != NFS3_OK) {
914 fprintf(stderr, "nfsproc3_pathconf_3 failed in nfsio_pathconf. status:%d\n", PATHCONF3res->status);
915 return PATHCONF3res->status;
922 nfsstat3 nfsio_symlink(struct nfsio *nfsio, const char *old, const char *new)
925 struct SYMLINK3args SYMLINK3args;
926 struct SYMLINK3res *SYMLINK3res;
928 char *tmp_name = NULL;
932 tmp_name = strdup(old);
933 if (tmp_name == NULL) {
934 fprintf(stderr, "failed to strdup name in nfsio_symlink\n");
935 ret = NFS3ERR_SERVERFAULT;
939 ptr = rindex(tmp_name, '/');
941 fprintf(stderr, "name did not contain '/' in nfsio_symlink\n");
942 ret = NFS3ERR_SERVERFAULT;
949 fh = lookup_fhandle(nfsio, tmp_name);
951 fprintf(stderr, "failed to fetch parent handle in nfsio_symlink\n");
952 ret = NFS3ERR_SERVERFAULT;
957 SYMLINK3args.where.dir.data.data_len = fh->dsize;
958 SYMLINK3args.where.dir.data.data_val = discard_const(fh->dptr);
959 SYMLINK3args.where.name = ptr;
961 SYMLINK3args.symlink.symlink_attributes.mode.set_it = TRUE;
962 SYMLINK3args.symlink.symlink_attributes.mode.set_mode3_u.mode = 0777;
963 SYMLINK3args.symlink.symlink_attributes.uid.set_it = TRUE;
964 SYMLINK3args.symlink.symlink_attributes.uid.set_uid3_u.uid= 0;
965 SYMLINK3args.symlink.symlink_attributes.gid.set_it = TRUE;
966 SYMLINK3args.symlink.symlink_attributes.gid.set_gid3_u.gid = 0;
967 SYMLINK3args.symlink.symlink_attributes.size.set_it = FALSE;
968 SYMLINK3args.symlink.symlink_attributes.atime.set_it = FALSE;
969 SYMLINK3args.symlink.symlink_attributes.mtime.set_it = FALSE;
970 SYMLINK3args.symlink.symlink_data = discard_const(new);
973 SYMLINK3res = nfsproc3_symlink_3(&SYMLINK3args, nfsio->clnt);
975 if (SYMLINK3res == NULL) {
976 fprintf(stderr, "nfsproc3_symlink_3 failed in nfsio_symlink\n");
977 ret = NFS3ERR_SERVERFAULT;
981 if (SYMLINK3res->status != NFS3_OK) {
982 fprintf(stderr, "nfsproc3_symlink_3 failed in nfsio_symlink. status:%d\n", SYMLINK3res->status);
983 ret = SYMLINK3res->status;
988 insert_fhandle(nfsio, old,
989 SYMLINK3res->SYMLINK3res_u.resok.obj.post_op_fh3_u.handle.data.data_val,
990 SYMLINK3res->SYMLINK3res_u.resok.obj.post_op_fh3_u.handle.data.data_len);
1001 nfsstat3 nfsio_link(struct nfsio *nfsio, const char *old, const char *new)
1004 struct LINK3args LINK3args;
1005 struct LINK3res *LINK3res;
1007 char *tmp_name = NULL;
1008 data_t *fh, *new_fh;
1011 tmp_name = strdup(old);
1012 if (tmp_name == NULL) {
1013 fprintf(stderr, "failed to strdup name in nfsio_link\n");
1014 ret = NFS3ERR_SERVERFAULT;
1018 ptr = rindex(tmp_name, '/');
1020 fprintf(stderr, "name did not contain '/' in nfsio_link\n");
1021 ret = NFS3ERR_SERVERFAULT;
1028 fh = lookup_fhandle(nfsio, tmp_name);
1030 fprintf(stderr, "failed to fetch parent handle in nfsio_link\n");
1031 ret = NFS3ERR_SERVERFAULT;
1036 new_fh = lookup_fhandle(nfsio, new);
1037 if (new_fh == NULL) {
1038 fprintf(stderr, "failed to fetch handle in nfsio_link\n");
1039 ret = NFS3ERR_SERVERFAULT;
1044 LINK3args.file.data.data_len = new_fh->dsize;
1045 LINK3args.file.data.data_val = discard_const(new_fh->dptr);
1048 LINK3args.link.dir.data.data_len = fh->dsize;
1049 LINK3args.link.dir.data.data_val = discard_const(fh->dptr);
1050 LINK3args.link.name = ptr;
1052 LINK3res = nfsproc3_link_3(&LINK3args, nfsio->clnt);
1054 if (LINK3res == NULL) {
1055 fprintf(stderr, "nfsproc3_link_3 failed in nfsio_link\n");
1056 ret = NFS3ERR_SERVERFAULT;
1060 if (LINK3res->status != NFS3_OK) {
1061 fprintf(stderr, "nfsproc3_link_3 failed in nfsio_link. status:%d\n", LINK3res->status);
1062 ret = LINK3res->status;
1067 // insert_fhandle(nfsio, old,
1068 // LINK3res->LINK3res_u.resok.obj.post_op_fh3_u.handle.data.data_val,
1069 // LINK3res->LINK3res_u.resok.obj.post_op_fh3_u.handle.data.data_len);
1081 nfsstat3 nfsio_readlink(struct nfsio *nfsio, char *name, char **link_name)
1083 struct READLINK3args READLINK3args;
1084 struct READLINK3res *READLINK3res;
1087 fh = lookup_fhandle(nfsio, name);
1089 fprintf(stderr, "failed to fetch handle in nfsio_readlink\n");
1090 return NFS3ERR_SERVERFAULT;
1094 READLINK3args.symlink.data.data_len = fh->dsize;
1095 READLINK3args.symlink.data.data_val = discard_const(fh->dptr);
1097 READLINK3res = nfsproc3_readlink_3(&READLINK3args, nfsio->clnt);
1099 if (READLINK3res == NULL) {
1100 fprintf(stderr, "nfsproc3_readlink_3 failed in nfsio_readlink\n");
1101 return NFS3ERR_SERVERFAULT;
1104 if (READLINK3res->status != NFS3_OK) {
1105 fprintf(stderr, "nfsproc3_readlink_3 failed in nfsio_readlink. status:%d\n", READLINK3res->status);
1106 return READLINK3res->status;
1110 *link_name = strdup(READLINK3res->READLINK3res_u.resok.data);
1117 nfsstat3 nfsio_rmdir(struct nfsio *nfsio, const char *name)
1120 struct RMDIR3args RMDIR3args;
1121 struct RMDIR3res *RMDIR3res;
1123 char *tmp_name = NULL;
1127 tmp_name = strdup(name);
1128 if (tmp_name == NULL) {
1129 fprintf(stderr, "failed to strdup name in nfsio_rmdir\n");
1130 return NFS3ERR_SERVERFAULT;
1133 ptr = rindex(tmp_name, '/');
1135 fprintf(stderr, "name did not contain '/' in nfsio_rmdir\n");
1136 ret = NFS3ERR_SERVERFAULT;
1143 fh = lookup_fhandle(nfsio, tmp_name);
1145 fprintf(stderr, "failed to fetch parent handle in nfsio_rmdir\n");
1146 ret = NFS3ERR_SERVERFAULT;
1151 RMDIR3args.object.dir.data.data_len = fh->dsize;
1152 RMDIR3args.object.dir.data.data_val = discard_const(fh->dptr);
1153 RMDIR3args.object.name = ptr;
1155 RMDIR3res = nfsproc3_rmdir_3(&RMDIR3args, nfsio->clnt);
1157 if (RMDIR3res == NULL) {
1158 fprintf(stderr, "nfsproc3_rmdir_3 failed in nfsio_rmdir\n");
1159 ret = NFS3ERR_SERVERFAULT;
1163 if (RMDIR3res->status != NFS3_OK) {
1164 fprintf(stderr, "nfsproc3_rmdir_3(%s) failed in nfsio_rmdir. status:%s(%d)\n", name, nfs_error(RMDIR3res->status), RMDIR3res->status);
1165 ret = RMDIR3res->status;
1170 delete_fhandle(nfsio, name);
1182 nfsstat3 nfsio_mkdir(struct nfsio *nfsio, const char *name)
1185 struct MKDIR3args MKDIR3args;
1186 struct MKDIR3res *MKDIR3res;
1188 char *tmp_name = NULL;
1192 tmp_name = strdup(name);
1193 if (tmp_name == NULL) {
1194 fprintf(stderr, "failed to strdup name in nfsio_mkdir\n");
1195 return NFS3ERR_SERVERFAULT;
1198 ptr = rindex(tmp_name, '/');
1200 fprintf(stderr, "name did not contain '/' in nfsio_mkdir\n");
1201 ret = NFS3ERR_SERVERFAULT;
1208 fh = lookup_fhandle(nfsio, tmp_name);
1210 fprintf(stderr, "failed to fetch parent handle in nfsio_mkdir\n");
1211 ret = NFS3ERR_SERVERFAULT;
1215 MKDIR3args.where.dir.data.data_len = fh->dsize;
1216 MKDIR3args.where.dir.data.data_val = discard_const(fh->dptr);
1217 MKDIR3args.where.name = ptr;
1219 MKDIR3args.attributes.mode.set_it = TRUE;
1220 MKDIR3args.attributes.mode.set_mode3_u.mode = 0777;
1221 MKDIR3args.attributes.uid.set_it = TRUE;
1222 MKDIR3args.attributes.uid.set_uid3_u.uid = 0;
1223 MKDIR3args.attributes.gid.set_it = TRUE;
1224 MKDIR3args.attributes.gid.set_gid3_u.gid = 0;
1225 MKDIR3args.attributes.size.set_it = FALSE;
1226 MKDIR3args.attributes.atime.set_it = FALSE;
1227 MKDIR3args.attributes.mtime.set_it = FALSE;
1229 MKDIR3res = nfsproc3_mkdir_3(&MKDIR3args, nfsio->clnt);
1231 if (MKDIR3res == NULL) {
1232 fprintf(stderr, "nfsproc3_mkdir_3 failed in nfsio_mkdir\n");
1233 ret = NFS3ERR_SERVERFAULT;
1237 if (MKDIR3res->status != NFS3_OK) {
1238 fprintf(stderr, "nfsproc3_mkdir_3(%s) failed in nfsio_mkdir. status:%s(%d)\n", name, nfs_error(MKDIR3res->status), MKDIR3res->status);
1239 ret = MKDIR3res->status;
1243 insert_fhandle(nfsio, name,
1244 MKDIR3res->MKDIR3res_u.resok.obj.post_op_fh3_u.handle.data.data_val,
1245 MKDIR3res->MKDIR3res_u.resok.obj.post_op_fh3_u.handle.data.data_len);
1255 nfsstat3 nfsio_readdirplus(struct nfsio *nfsio, const char *name, nfs3_dirent_cb cb, void *private_data)
1257 struct READDIRPLUS3args READDIRPLUS3args;
1258 struct READDIRPLUS3res *READDIRPLUS3res;
1261 entryplus3 *e, *last_e = NULL;
1266 if(dir[strlen(dir)-1] != '/'){
1269 dir[strlen(dir)-1] = 0;
1272 fh = lookup_fhandle(nfsio, name);
1274 fprintf(stderr, "failed to fetch handle for '%s' in nfsio_readdirplus\n", name);
1275 ret = NFS3ERR_SERVERFAULT;
1279 READDIRPLUS3args.dir.data.data_len = fh->dsize;
1280 READDIRPLUS3args.dir.data.data_val = discard_const(fh->dptr);
1281 READDIRPLUS3args.cookie = 0;
1282 bzero(&READDIRPLUS3args.cookieverf, NFS3_COOKIEVERFSIZE);
1283 READDIRPLUS3args.dircount = 6000;
1284 READDIRPLUS3args.maxcount = 8192;
1287 READDIRPLUS3res = nfsproc3_readdirplus_3(&READDIRPLUS3args, nfsio->clnt);
1289 if (READDIRPLUS3res == NULL) {
1290 fprintf(stderr, "nfsproc3_readdirplus_3 failed in readdirplus\n");
1291 ret = NFS3ERR_SERVERFAULT;
1295 if (READDIRPLUS3res->status != NFS3_OK) {
1296 fprintf(stderr, "nfsproc3_readdirplus_3 failed in readdirplus. status:%d\n", READDIRPLUS3res->status);
1297 ret = READDIRPLUS3res->status;
1301 for(e = READDIRPLUS3res->READDIRPLUS3res_u.resok.reply.entries;e;e=e->nextentry){
1304 if(!strcmp(e->name, ".")){
1307 if(!strcmp(e->name, "..")){
1310 if(e->name_handle.handle_follows == 0){
1316 asprintf(&new_name, "%s/%s", dir, e->name);
1317 insert_fhandle(nfsio, new_name,
1318 e->name_handle.post_op_fh3_u.handle.data.data_val,
1319 e->name_handle.post_op_fh3_u.handle.data.data_len);
1323 cb(e, private_data);
1327 if (READDIRPLUS3res->READDIRPLUS3res_u.resok.reply.eof == 0) {
1328 if (READDIRPLUS3args.cookie == 0) {
1329 memcpy(&READDIRPLUS3args.cookieverf,
1330 &READDIRPLUS3res->READDIRPLUS3res_u.resok.cookieverf,
1331 NFS3_COOKIEVERFSIZE);
1334 READDIRPLUS3args.cookie = last_e->cookie;
1348 nfsstat3 nfsio_rename(struct nfsio *nfsio, const char *old, const char *new)
1351 struct RENAME3args RENAME3args;
1352 struct RENAME3res *RENAME3res;
1354 char *tmp_old_name = NULL;
1355 char *tmp_new_name = NULL;
1356 data_t *old_fh, *new_fh;
1357 char *old_ptr, *new_ptr;
1359 tmp_old_name = strdup(old);
1360 if (tmp_old_name == NULL) {
1361 fprintf(stderr, "failed to strdup name in nfsio_rename\n");
1362 ret = NFS3ERR_SERVERFAULT;
1366 old_ptr = rindex(tmp_old_name, '/');
1367 if (old_ptr == NULL) {
1368 fprintf(stderr, "name did not contain '/' in nfsio_rename\n");
1369 ret = NFS3ERR_SERVERFAULT;
1376 old_fh = lookup_fhandle(nfsio, tmp_old_name);
1377 if (old_fh == NULL) {
1378 fprintf(stderr, "failed to fetch parent handle in nfsio_rename\n");
1379 ret = NFS3ERR_SERVERFAULT;
1383 tmp_new_name = strdup(new);
1384 if (tmp_new_name == NULL) {
1385 fprintf(stderr, "failed to strdup name in nfsio_rename\n");
1386 ret = NFS3ERR_SERVERFAULT;
1390 new_ptr = rindex(tmp_new_name, '/');
1391 if (new_ptr == NULL) {
1392 fprintf(stderr, "name did not contain '/' in nfsio_rename\n");
1393 ret = NFS3ERR_SERVERFAULT;
1400 new_fh = lookup_fhandle(nfsio, tmp_new_name);
1401 if (new_fh == NULL) {
1402 fprintf(stderr, "failed to fetch parent handle in nfsio_rename\n");
1403 ret = NFS3ERR_SERVERFAULT;
1407 RENAME3args.from.dir.data.data_len = old_fh->dsize;
1408 RENAME3args.from.dir.data.data_val = discard_const(old_fh->dptr);
1409 RENAME3args.from.name = old_ptr;
1411 RENAME3args.to.dir.data.data_len = new_fh->dsize;
1412 RENAME3args.to.dir.data.data_val = discard_const(new_fh->dptr);
1413 RENAME3args.to.name = new_ptr;
1416 RENAME3res = nfsproc3_rename_3(&RENAME3args, nfsio->clnt);
1418 if (RENAME3res == NULL) {
1419 fprintf(stderr, "nfsproc3_rename_3 failed in nfsio_rename\n");
1420 ret = NFS3ERR_SERVERFAULT;
1424 if (RENAME3res->status != NFS3_OK) {
1425 fprintf(stderr, "nfsproc3_rename_3 failed in nfsio_rename. status:%d\n", RENAME3res->status);
1426 ret = RENAME3res->status;
1431 old_fh = lookup_fhandle(nfsio, old);
1432 if (old_fh == NULL) {
1433 fprintf(stderr, "failed to fetch parent handle in nfsio_rename\n");
1434 ret = NFS3ERR_SERVERFAULT;
1439 insert_fhandle(nfsio, new, old_fh->dptr, old_fh->dsize);
1440 delete_fhandle(nfsio, old);