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 t->right->parent = tmp_tree;
115 if (t->parent == NULL) {
116 nfsio->fhandles = tmp_tree;
117 tmp_tree->parent = NULL;
122 if (t->parent->left == t) {
123 t->parent->left = t->left;
125 t->left->parent = t->parent;
131 t->parent->right = t->left;
133 t->left->parent = t->parent;
139 /* we only have a right child */
143 for(tmp_tree=t->right;tmp_tree->left;tmp_tree=tmp_tree->left)
145 tmp_tree->left = t->left;
147 t->left->parent = tmp_tree;
150 if (t->parent == NULL) {
151 nfsio->fhandles = tmp_tree;
152 tmp_tree->parent = NULL;
157 if (t->parent->left == t) {
158 t->parent->left = t->right;
160 t->right->parent = t->parent;
166 t->parent->right = t->right;
168 t->right->parent = t->parent;
174 /* we are a leaf node */
175 if (t->parent == NULL) {
176 nfsio->fhandles = NULL;
178 if (t->parent->left == t) {
179 t->parent->left = NULL;
181 t->parent->right = NULL;
188 static void insert_fhandle(struct nfsio *nfsio, const char *name, const char *fhandle, int length)
194 while (name[0] == '.') name++;
196 t = malloc(sizeof(tree_t));
198 fprintf(stderr, "MALLOC failed to allocate tree_t in insert_fhandle\n");
202 t->key.dptr = strdup(name);
203 if (t->key.dptr == NULL) {
204 fprintf(stderr, "STRDUP failed to allocate key in insert_fhandle\n");
207 t->key.dsize = strlen(name);
210 t->fh.dptr = malloc(length);
211 if (t->key.dptr == NULL) {
212 fprintf(stderr, "MALLOC failed to allocate fhandle in insert_fhandle\n");
215 memcpy(discard_const(t->fh.dptr), fhandle, length);
216 t->fh.dsize = length;
222 if (nfsio->fhandles == NULL) {
227 tmp_t = nfsio->fhandles;
229 i = strcmp(t->key.dptr, tmp_t->key.dptr);
231 free(discard_const(tmp_t->fh.dptr));
232 tmp_t->fh.dsize = t->fh.dsize;
233 tmp_t->fh.dptr = t->fh.dptr;
234 free(discard_const(t->key.dptr));
239 if (tmp_t->left == NULL) {
247 if (tmp_t->right == NULL) {
252 tmp_t = tmp_t->right;
262 static const struct nfs_errors nfs_errors[] = {
265 {"NFS3ERR_NOENT", 2},
268 {"NFS3ERR_ACCES", 13},
269 {"NFS3ERR_EXIST", 17},
270 {"NFS3ERR_XDEV", 18},
271 {"NFS3ERR_NODEV", 19},
272 {"NFS3ERR_NOTDIR", 20},
273 {"NFS3ERR_ISDIR", 21},
274 {"NFS3ERR_INVAL", 22},
275 {"NFS3ERR_FBIG", 27},
276 {"NFS3ERR_NOSPC", 28},
277 {"NFS3ERR_ROFS", 30},
278 {"NFS3ERR_MLINK", 31},
279 {"NFS3ERR_NAMETOOLONG", 63},
280 {"NFS3ERR_NOTEMPTY", 66},
281 {"NFS3ERR_DQUOT", 69},
282 {"NFS3ERR_STALE", 70},
283 {"NFS3ERR_REMOTE", 71},
284 {"NFS3ERR_BADHANDLE", 10001},
285 {"NFS3ERR_NOT_SYNC", 10002},
286 {"NFS3ERR_BAD_COOKIE", 10003},
287 {"NFS3ERR_NOTSUPP", 10004},
288 {"NFS3ERR_TOOSMALL", 10005},
289 {"NFS3ERR_SERVERFAULT", 10006},
290 {"NFS3ERR_BADTYPE", 10007},
291 {"NFS3ERR_JUKEBOX", 10008},
296 const char *nfs_error(int error)
300 for(i=0;i<sizeof(nfs_errors)/sizeof(struct nfs_errors);i++) {
301 if (error == nfs_errors[i].idx) {
302 return nfs_errors[i].err;
305 return "Unknown NFS error";
311 void nfsio_disconnect(struct nfsio *nfsio)
313 if (nfsio->clnt != NULL) {
314 clnt_destroy(nfsio->clnt);
317 if (nfsio->s != -1) {
320 // qqq free the tree*/
328 struct nfsio *nfsio_connect(const char *server, const char *export, const char *protocol)
330 dirpath mountdir=discard_const(export);
334 struct sockaddr_in sin;
337 nfsio = malloc(sizeof(struct nfsio));
339 fprintf(stderr, "Failed to malloc nfsio\n");
342 bzero(nfsio, sizeof(struct nfsio));
348 * set up the MOUNT client. If we are running as root, we get
349 * a port <1024 by default. If we are not root, we can not
350 * bind to these ports, so the server must be in "insecure"
353 memset(&sin, 0, sizeof(sin));
355 sin.sin_family = PF_INET;
356 if (inet_aton(server, &sin.sin_addr) == 0) {
357 fprintf(stderr, "Invalid address '%s'\n", server);
358 nfsio_disconnect(nfsio);
362 if (!strcmp(protocol, "tcp")) {
363 nfsio->s = RPC_ANYSOCK;
364 nfsio->clnt = clnttcp_create(&sin, MOUNT_PROGRAM, MOUNT_V3, &nfsio->s, 32768, 32768);
370 nfsio->s = RPC_ANYSOCK;
371 nfsio->clnt = clntudp_create(&sin, MOUNT_PROGRAM, MOUNT_V3, wait, &nfsio->s);
374 if (nfsio->clnt == NULL) {
375 printf("ERROR: failed to connect to MOUNT daemon on %s\n", server);
376 nfsio_disconnect(nfsio);
379 nfsio->clnt->cl_auth = authunix_create_default();
381 mountres=mountproc3_mnt_3(&mountdir, nfsio->clnt);
382 if (mountres == NULL) {
383 printf("ERROR: failed to call the MNT procedure\n");
384 nfsio_disconnect(nfsio);
387 if (mountres->fhs_status != MNT3_OK) {
388 printf("ERROR: Server returned error %d when trying to MNT\n",mountres->fhs_status);
389 nfsio_disconnect(nfsio);
393 fh = &mountres->mountres3_u.mountinfo.fhandle;
394 insert_fhandle(nfsio, "/", fh->fhandle3_val, fh->fhandle3_len);
397 /* we dont need the mount client any more */
398 clnt_destroy(nfsio->clnt);
405 * set up the NFS client. If we are running as root, we get
406 * a port <1024 by default. If we are not root, we can not
407 * bind to these ports, so the server must be in "insecure"
410 memset(&sin, 0, sizeof(sin));
412 sin.sin_family = PF_INET;
413 if (inet_aton(server, &sin.sin_addr) == 0) {
414 fprintf(stderr, "Invalid address '%s'\n", server);
415 nfsio_disconnect(nfsio);
419 if (!strcmp(protocol, "tcp")) {
420 nfsio->s = RPC_ANYSOCK;
421 nfsio->clnt = clnttcp_create(&sin, NFS_PROGRAM, NFS_V3, &nfsio->s, 327680, 327680);
427 nfsio->s = RPC_ANYSOCK;
428 nfsio->clnt = clntudp_create(&sin, NFS_PROGRAM, NFS_V3, wait, &nfsio->s);
431 if (nfsio->clnt == NULL) {
432 fprintf(stderr, "Failed to initialize nfs client structure\n");
433 nfsio_disconnect(nfsio);
436 nfsio->clnt->cl_auth = authunix_create_default();
442 nfsstat3 nfsio_getattr(struct nfsio *nfsio, const char *name, fattr3 *attributes)
444 struct GETATTR3args GETATTR3args;
445 struct GETATTR3res *GETATTR3res;
448 fh = lookup_fhandle(nfsio, name);
450 fprintf(stderr, "failed to fetch handle in nfsio_getattr\n");
451 return NFS3ERR_SERVERFAULT;
454 GETATTR3args.object.data.data_len = fh->dsize;
455 GETATTR3args.object.data.data_val = discard_const(fh->dptr);
457 GETATTR3res = nfsproc3_getattr_3(&GETATTR3args, nfsio->clnt);
459 if (GETATTR3res == NULL) {
460 fprintf(stderr, "nfsproc3_getattr_3 failed in getattr\n");
461 return NFS3ERR_SERVERFAULT;
464 if (GETATTR3res->status != NFS3_OK) {
465 fprintf(stderr, "nfsproc3_getattr_3 failed in getattr. status:%d\n", GETATTR3res->status);
466 return GETATTR3res->status;
470 memcpy(attributes, &GETATTR3res->GETATTR3res_u.resok.obj_attributes, sizeof(fattr3));
476 nfsstat3 nfsio_lookup(struct nfsio *nfsio, const char *name, fattr3 *attributes)
479 struct LOOKUP3args LOOKUP3args;
480 struct LOOKUP3res *LOOKUP3res;
481 char *tmp_name = NULL;
486 tmp_name = strdup(name);
487 if (tmp_name == NULL) {
488 fprintf(stderr, "failed to strdup name in nfsio_lookup\n");
489 ret = NFS3ERR_SERVERFAULT;
493 ptr = rindex(tmp_name, '/');
495 fprintf(stderr, "name did not contain '/' in nfsio_lookup\n");
496 ret = NFS3ERR_SERVERFAULT;
503 fh = lookup_fhandle(nfsio, tmp_name);
505 fprintf(stderr, "failed to fetch parent handle for '%s' in nfsio_lookup\n", tmp_name);
506 ret = NFS3ERR_SERVERFAULT;
510 LOOKUP3args.what.dir.data.data_len = fh->dsize;
511 LOOKUP3args.what.dir.data.data_val = discard_const(fh->dptr);
512 LOOKUP3args.what.name = ptr;
514 LOOKUP3res = nfsproc3_lookup_3(&LOOKUP3args, nfsio->clnt);
516 if (LOOKUP3res == NULL) {
517 fprintf(stderr, "nfsproc3_lookup_3 failed in lookup\n");
518 ret = NFS3ERR_SERVERFAULT;
522 if (LOOKUP3res->status != NFS3_OK) {
523 ret = LOOKUP3res->status;
528 insert_fhandle(nfsio, name,
529 LOOKUP3res->LOOKUP3res_u.resok.object.data.data_val,
530 LOOKUP3res->LOOKUP3res_u.resok.object.data.data_len);
533 memcpy(attributes, &LOOKUP3res->LOOKUP3res_u.resok.obj_attributes.post_op_attr_u.attributes, sizeof(fattr3));
544 nfsstat3 nfsio_access(struct nfsio *nfsio, const char *name, uint32 desired, uint32 *access)
547 struct ACCESS3args ACCESS3args;
548 struct ACCESS3res *ACCESS3res;
551 fh = lookup_fhandle(nfsio, name);
553 fprintf(stderr, "failed to fetch handle in nfsio_access\n");
554 return NFS3ERR_SERVERFAULT;
557 ACCESS3args.object.data.data_val = discard_const(fh->dptr);
558 ACCESS3args.object.data.data_len = fh->dsize;
559 ACCESS3args.access = desired;
561 ACCESS3res = nfsproc3_access_3(&ACCESS3args, nfsio->clnt);
563 if (ACCESS3res == NULL) {
564 fprintf(stderr, "nfsproc3_access_3 failed in access\n");
565 return NFS3ERR_SERVERFAULT;
568 if (ACCESS3res->status != NFS3_OK) {
569 fprintf(stderr, "nfsproc3_access_3 failed. status:%d\n",
571 return ACCESS3res->status;
575 *access = ACCESS3res->ACCESS3res_u.resok.access;
583 nfsstat3 nfsio_create(struct nfsio *nfsio, const char *name)
586 struct CREATE3args CREATE3args;
587 struct CREATE3res *CREATE3res;
588 char *tmp_name = NULL;
593 tmp_name = strdup(name);
594 if (tmp_name == NULL) {
595 fprintf(stderr, "failed to strdup name in nfsio_create\n");
596 ret = NFS3ERR_SERVERFAULT;
600 ptr = rindex(tmp_name, '/');
602 fprintf(stderr, "name did not contain '/' in nfsio_create\n");
603 ret = NFS3ERR_SERVERFAULT;
610 fh = lookup_fhandle(nfsio, tmp_name);
612 fprintf(stderr, "failed to fetch parent handle in nfsio_create\n");
613 ret = NFS3ERR_SERVERFAULT;
617 CREATE3args.where.dir.data.data_len = fh->dsize;
618 CREATE3args.where.dir.data.data_val = discard_const(fh->dptr);
619 CREATE3args.where.name = ptr;
621 CREATE3args.how.mode = UNCHECKED;
622 CREATE3args.how.createhow3_u.obj_attributes.mode.set_it = TRUE;
623 CREATE3args.how.createhow3_u.obj_attributes.mode.set_mode3_u.mode = 0777;
624 CREATE3args.how.createhow3_u.obj_attributes.uid.set_it = TRUE;
625 CREATE3args.how.createhow3_u.obj_attributes.uid.set_uid3_u.uid = 0;
626 CREATE3args.how.createhow3_u.obj_attributes.gid.set_it = TRUE;
627 CREATE3args.how.createhow3_u.obj_attributes.gid.set_gid3_u.gid = 0;
628 CREATE3args.how.createhow3_u.obj_attributes.size.set_it = FALSE;
629 CREATE3args.how.createhow3_u.obj_attributes.atime.set_it = FALSE;
630 CREATE3args.how.createhow3_u.obj_attributes.mtime.set_it = FALSE;
632 CREATE3res = nfsproc3_create_3(&CREATE3args, nfsio->clnt);
634 if (CREATE3res == NULL) {
635 fprintf(stderr, "nfsproc3_create_3 failed in nfsio_create\n");
636 ret = NFS3ERR_SERVERFAULT;
640 if (CREATE3res->status != NFS3_OK) {
641 fprintf(stderr, "nfsproc3_create_3 failed in nfsio_create. status:%d\n", CREATE3res->status);
642 ret = CREATE3res->status;
647 insert_fhandle(nfsio, name,
648 CREATE3res->CREATE3res_u.resok.obj.post_op_fh3_u.handle.data.data_val,
649 CREATE3res->CREATE3res_u.resok.obj.post_op_fh3_u.handle.data.data_len);
659 nfsstat3 nfsio_remove(struct nfsio *nfsio, const char *name)
662 struct REMOVE3args REMOVE3args;
663 struct REMOVE3res *REMOVE3res;
665 char *tmp_name = NULL;
669 tmp_name = strdup(name);
670 if (tmp_name == NULL) {
671 fprintf(stderr, "failed to strdup name in nfsio_remove\n");
672 ret = NFS3ERR_SERVERFAULT;
676 ptr = rindex(tmp_name, '/');
678 fprintf(stderr, "name did not contain '/' in nfsio_remove\n");
679 ret = NFS3ERR_SERVERFAULT;
686 fh = lookup_fhandle(nfsio, tmp_name);
688 fprintf(stderr, "failed to fetch parent handle in nfsio_remove\n");
689 ret = NFS3ERR_SERVERFAULT;
694 REMOVE3args.object.dir.data.data_len = fh->dsize;
695 REMOVE3args.object.dir.data.data_val = discard_const(fh->dptr);
696 REMOVE3args.object.name = ptr;
698 REMOVE3res = nfsproc3_remove_3(&REMOVE3args, nfsio->clnt);
700 if (REMOVE3res == NULL) {
701 fprintf(stderr, "nfsproc3_remove_3 failed in nfsio_remove\n");
702 ret = NFS3ERR_SERVERFAULT;
706 if (REMOVE3res->status != NFS3_OK) {
707 fprintf(stderr, "nfsproc3_remove_3 failed in nfsio_remove. status:%d\n", REMOVE3res->status);
708 ret = REMOVE3res->status;
713 delete_fhandle(nfsio, name);
724 nfsstat3 nfsio_write(struct nfsio *nfsio, const char *name, char *buf, uint32 offset, int len, int stable)
726 struct WRITE3args WRITE3args;
727 struct WRITE3res *WRITE3res;
731 fh = lookup_fhandle(nfsio, name);
733 fprintf(stderr, "failed to fetch handle in nfsio_write\n");
734 ret = NFS3ERR_SERVERFAULT;
738 WRITE3args.file.data.data_len = fh->dsize;
739 WRITE3args.file.data.data_val = discard_const(fh->dptr);
740 WRITE3args.offset = offset;
741 WRITE3args.count = len;
742 WRITE3args.stable = stable;
743 WRITE3args.data.data_len = len;
744 WRITE3args.data.data_val = buf;
747 WRITE3res = nfsproc3_write_3(&WRITE3args, nfsio->clnt);
749 if (WRITE3res == NULL) {
750 fprintf(stderr, "nfsproc3_write_3 failed in nfsio_write\n");
751 ret = NFS3ERR_SERVERFAULT;
755 if (WRITE3res->status != NFS3_OK) {
756 fprintf(stderr, "nfsproc3_write_3 failed in getattr. status:%d\n", WRITE3res->status);
757 ret = WRITE3res->status;
764 nfsstat3 nfsio_read(struct nfsio *nfsio, const char *name, char *buf, uint32 offset, int len, int *count, int *eof)
766 struct READ3args READ3args;
767 struct READ3res *READ3res;
771 fh = lookup_fhandle(nfsio, name);
773 fprintf(stderr, "failed to fetch handle in nfsio_read\n");
774 ret = NFS3ERR_SERVERFAULT;
778 READ3args.file.data.data_len = fh->dsize;
779 READ3args.file.data.data_val = discard_const(fh->dptr);
780 READ3args.offset = offset;
781 READ3args.count = len;
783 READ3res = nfsproc3_read_3(&READ3args, nfsio->clnt);
785 if (READ3res == NULL) {
786 fprintf(stderr, "nfsproc3_read_3 failed in nfsio_read\n");
787 ret = NFS3ERR_SERVERFAULT;
791 if (READ3res->status != NFS3_OK) {
792 fprintf(stderr, "nfsproc3_read_3 failed in nfsio_read. status:%d\n", READ3res->status);
793 ret = READ3res->status;
798 *count = READ3res->READ3res_u.resok.count;
801 *eof = READ3res->READ3res_u.resok.eof;
803 memcpy(buf, &READ3res->READ3res_u.resok.data.data_val,
804 READ3res->READ3res_u.resok.count);
812 nfsstat3 nfsio_commit(struct nfsio *nfsio, const char *name)
814 struct COMMIT3args COMMIT3args;
815 struct COMMIT3res *COMMIT3res;
819 fh = lookup_fhandle(nfsio, name);
821 fprintf(stderr, "failed to fetch handle in nfsio_commit\n");
822 ret = NFS3ERR_SERVERFAULT;
826 COMMIT3args.file.data.data_len = fh->dsize;
827 COMMIT3args.file.data.data_val = discard_const(fh->dptr);
828 COMMIT3args.offset = 0;
829 COMMIT3args.count = 0;
832 COMMIT3res = nfsproc3_commit_3(&COMMIT3args, nfsio->clnt);
834 if (COMMIT3res == NULL) {
835 fprintf(stderr, "nfsproc3_commit_3 failed in nfsio_commit\n");
836 ret = NFS3ERR_SERVERFAULT;
840 if (COMMIT3res->status != NFS3_OK) {
841 fprintf(stderr, "nfsproc3_commit_3 failed in nfsio_commit. status:%d\n", COMMIT3res->status);
842 ret = COMMIT3res->status;
850 nfsstat3 nfsio_fsinfo(struct nfsio *nfsio)
852 struct FSINFO3args FSINFO3args;
853 struct FSINFO3res *FSINFO3res;
856 fh = lookup_fhandle(nfsio, "/");
858 fprintf(stderr, "failed to fetch handle in nfsio_fsinfo\n");
859 return NFS3ERR_SERVERFAULT;
862 FSINFO3args.fsroot.data.data_len = fh->dsize;
863 FSINFO3args.fsroot.data.data_val = discard_const(fh->dptr);
865 FSINFO3res = nfsproc3_fsinfo_3(&FSINFO3args, nfsio->clnt);
867 if (FSINFO3res == NULL) {
868 fprintf(stderr, "nfsproc3_fsinfo_3 failed in nfsio_fsinfo\n");
869 return NFS3ERR_SERVERFAULT;
872 if (FSINFO3res->status != NFS3_OK) {
873 fprintf(stderr, "nfsproc3_fsinfo_3 failed in nfsio_fsinfo. status:%d\n", FSINFO3res->status);
874 return FSINFO3res->status;
881 nfsstat3 nfsio_fsstat(struct nfsio *nfsio)
883 struct FSSTAT3args FSSTAT3args;
884 struct FSSTAT3res *FSSTAT3res;
887 fh = lookup_fhandle(nfsio, "/");
889 fprintf(stderr, "failed to fetch handle in nfsio_fsstat\n");
890 return NFS3ERR_SERVERFAULT;
893 FSSTAT3args.fsroot.data.data_len = fh->dsize;
894 FSSTAT3args.fsroot.data.data_val = discard_const(fh->dptr);
896 FSSTAT3res = nfsproc3_fsstat_3(&FSSTAT3args, nfsio->clnt);
898 if (FSSTAT3res == NULL) {
899 fprintf(stderr, "nfsproc3_fsstat_3 failed in nfsio_fsstat\n");
900 return NFS3ERR_SERVERFAULT;
903 if (FSSTAT3res->status != NFS3_OK) {
904 fprintf(stderr, "nfsproc3_fsstat_3 failed in nfsio_fsstat. status:%d\n", FSSTAT3res->status);
905 return FSSTAT3res->status;
911 nfsstat3 nfsio_pathconf(struct nfsio *nfsio, char *name)
913 struct PATHCONF3args PATHCONF3args;
914 struct PATHCONF3res *PATHCONF3res;
917 fh = lookup_fhandle(nfsio, name);
919 fprintf(stderr, "failed to fetch handle in nfsio_pathconf\n");
920 return NFS3ERR_SERVERFAULT;
923 PATHCONF3args.object.data.data_len = fh->dsize;
924 PATHCONF3args.object.data.data_val = discard_const(fh->dptr);
926 PATHCONF3res = nfsproc3_pathconf_3(&PATHCONF3args, nfsio->clnt);
928 if (PATHCONF3res == NULL) {
929 fprintf(stderr, "nfsproc3_pathconf_3 failed in nfsio_pathconf\n");
930 return NFS3ERR_SERVERFAULT;
933 if (PATHCONF3res->status != NFS3_OK) {
934 fprintf(stderr, "nfsproc3_pathconf_3 failed in nfsio_pathconf. status:%d\n", PATHCONF3res->status);
935 return PATHCONF3res->status;
942 nfsstat3 nfsio_symlink(struct nfsio *nfsio, const char *old, const char *new)
945 struct SYMLINK3args SYMLINK3args;
946 struct SYMLINK3res *SYMLINK3res;
948 char *tmp_name = NULL;
952 tmp_name = strdup(old);
953 if (tmp_name == NULL) {
954 fprintf(stderr, "failed to strdup name in nfsio_symlink\n");
955 ret = NFS3ERR_SERVERFAULT;
959 ptr = rindex(tmp_name, '/');
961 fprintf(stderr, "name did not contain '/' in nfsio_symlink\n");
962 ret = NFS3ERR_SERVERFAULT;
969 fh = lookup_fhandle(nfsio, tmp_name);
971 fprintf(stderr, "failed to fetch parent handle in nfsio_symlink\n");
972 ret = NFS3ERR_SERVERFAULT;
977 SYMLINK3args.where.dir.data.data_len = fh->dsize;
978 SYMLINK3args.where.dir.data.data_val = discard_const(fh->dptr);
979 SYMLINK3args.where.name = ptr;
981 SYMLINK3args.symlink.symlink_attributes.mode.set_it = TRUE;
982 SYMLINK3args.symlink.symlink_attributes.mode.set_mode3_u.mode = 0777;
983 SYMLINK3args.symlink.symlink_attributes.uid.set_it = TRUE;
984 SYMLINK3args.symlink.symlink_attributes.uid.set_uid3_u.uid= 0;
985 SYMLINK3args.symlink.symlink_attributes.gid.set_it = TRUE;
986 SYMLINK3args.symlink.symlink_attributes.gid.set_gid3_u.gid = 0;
987 SYMLINK3args.symlink.symlink_attributes.size.set_it = FALSE;
988 SYMLINK3args.symlink.symlink_attributes.atime.set_it = FALSE;
989 SYMLINK3args.symlink.symlink_attributes.mtime.set_it = FALSE;
990 SYMLINK3args.symlink.symlink_data = discard_const(new);
993 SYMLINK3res = nfsproc3_symlink_3(&SYMLINK3args, nfsio->clnt);
995 if (SYMLINK3res == NULL) {
996 fprintf(stderr, "nfsproc3_symlink_3 failed in nfsio_symlink\n");
997 ret = NFS3ERR_SERVERFAULT;
1001 if (SYMLINK3res->status != NFS3_OK) {
1002 fprintf(stderr, "nfsproc3_symlink_3 failed in nfsio_symlink. status:%d\n", SYMLINK3res->status);
1003 ret = SYMLINK3res->status;
1008 insert_fhandle(nfsio, old,
1009 SYMLINK3res->SYMLINK3res_u.resok.obj.post_op_fh3_u.handle.data.data_val,
1010 SYMLINK3res->SYMLINK3res_u.resok.obj.post_op_fh3_u.handle.data.data_len);
1021 nfsstat3 nfsio_link(struct nfsio *nfsio, const char *old, const char *new)
1024 struct LINK3args LINK3args;
1025 struct LINK3res *LINK3res;
1027 char *tmp_name = NULL;
1028 data_t *fh, *new_fh;
1031 tmp_name = strdup(old);
1032 if (tmp_name == NULL) {
1033 fprintf(stderr, "failed to strdup name in nfsio_link\n");
1034 ret = NFS3ERR_SERVERFAULT;
1038 ptr = rindex(tmp_name, '/');
1040 fprintf(stderr, "name did not contain '/' in nfsio_link\n");
1041 ret = NFS3ERR_SERVERFAULT;
1048 fh = lookup_fhandle(nfsio, tmp_name);
1050 fprintf(stderr, "failed to fetch parent handle in nfsio_link\n");
1051 ret = NFS3ERR_SERVERFAULT;
1056 new_fh = lookup_fhandle(nfsio, new);
1057 if (new_fh == NULL) {
1058 fprintf(stderr, "failed to fetch handle in nfsio_link\n");
1059 ret = NFS3ERR_SERVERFAULT;
1064 LINK3args.file.data.data_len = new_fh->dsize;
1065 LINK3args.file.data.data_val = discard_const(new_fh->dptr);
1068 LINK3args.link.dir.data.data_len = fh->dsize;
1069 LINK3args.link.dir.data.data_val = discard_const(fh->dptr);
1070 LINK3args.link.name = ptr;
1072 LINK3res = nfsproc3_link_3(&LINK3args, nfsio->clnt);
1074 if (LINK3res == NULL) {
1075 fprintf(stderr, "nfsproc3_link_3 failed in nfsio_link\n");
1076 ret = NFS3ERR_SERVERFAULT;
1080 if (LINK3res->status != NFS3_OK) {
1081 fprintf(stderr, "nfsproc3_link_3 failed in nfsio_link. status:%d\n", LINK3res->status);
1082 ret = LINK3res->status;
1087 // insert_fhandle(nfsio, old,
1088 // LINK3res->LINK3res_u.resok.obj.post_op_fh3_u.handle.data.data_val,
1089 // LINK3res->LINK3res_u.resok.obj.post_op_fh3_u.handle.data.data_len);
1101 nfsstat3 nfsio_readlink(struct nfsio *nfsio, char *name, char **link_name)
1103 struct READLINK3args READLINK3args;
1104 struct READLINK3res *READLINK3res;
1107 fh = lookup_fhandle(nfsio, name);
1109 fprintf(stderr, "failed to fetch handle in nfsio_readlink\n");
1110 return NFS3ERR_SERVERFAULT;
1114 READLINK3args.symlink.data.data_len = fh->dsize;
1115 READLINK3args.symlink.data.data_val = discard_const(fh->dptr);
1117 READLINK3res = nfsproc3_readlink_3(&READLINK3args, nfsio->clnt);
1119 if (READLINK3res == NULL) {
1120 fprintf(stderr, "nfsproc3_readlink_3 failed in nfsio_readlink\n");
1121 return NFS3ERR_SERVERFAULT;
1124 if (READLINK3res->status != NFS3_OK) {
1125 fprintf(stderr, "nfsproc3_readlink_3 failed in nfsio_readlink. status:%d\n", READLINK3res->status);
1126 return READLINK3res->status;
1130 *link_name = strdup(READLINK3res->READLINK3res_u.resok.data);
1137 nfsstat3 nfsio_rmdir(struct nfsio *nfsio, const char *name)
1140 struct RMDIR3args RMDIR3args;
1141 struct RMDIR3res *RMDIR3res;
1143 char *tmp_name = NULL;
1147 tmp_name = strdup(name);
1148 if (tmp_name == NULL) {
1149 fprintf(stderr, "failed to strdup name in nfsio_rmdir\n");
1150 return NFS3ERR_SERVERFAULT;
1153 ptr = rindex(tmp_name, '/');
1155 fprintf(stderr, "name did not contain '/' in nfsio_rmdir\n");
1156 ret = NFS3ERR_SERVERFAULT;
1163 fh = lookup_fhandle(nfsio, tmp_name);
1165 fprintf(stderr, "failed to fetch parent handle in nfsio_rmdir\n");
1166 ret = NFS3ERR_SERVERFAULT;
1171 RMDIR3args.object.dir.data.data_len = fh->dsize;
1172 RMDIR3args.object.dir.data.data_val = discard_const(fh->dptr);
1173 RMDIR3args.object.name = ptr;
1175 RMDIR3res = nfsproc3_rmdir_3(&RMDIR3args, nfsio->clnt);
1177 if (RMDIR3res == NULL) {
1178 fprintf(stderr, "nfsproc3_rmdir_3 failed in nfsio_rmdir\n");
1179 ret = NFS3ERR_SERVERFAULT;
1183 if (RMDIR3res->status != NFS3_OK) {
1184 fprintf(stderr, "nfsproc3_rmdir_3(%s) failed in nfsio_rmdir. status:%s(%d)\n", name, nfs_error(RMDIR3res->status), RMDIR3res->status);
1185 ret = RMDIR3res->status;
1190 delete_fhandle(nfsio, name);
1202 nfsstat3 nfsio_mkdir(struct nfsio *nfsio, const char *name)
1205 struct MKDIR3args MKDIR3args;
1206 struct MKDIR3res *MKDIR3res;
1208 char *tmp_name = NULL;
1212 tmp_name = strdup(name);
1213 if (tmp_name == NULL) {
1214 fprintf(stderr, "failed to strdup name in nfsio_mkdir\n");
1215 return NFS3ERR_SERVERFAULT;
1218 ptr = rindex(tmp_name, '/');
1220 fprintf(stderr, "name did not contain '/' in nfsio_mkdir\n");
1221 ret = NFS3ERR_SERVERFAULT;
1228 fh = lookup_fhandle(nfsio, tmp_name);
1230 fprintf(stderr, "failed to fetch parent handle in nfsio_mkdir\n");
1231 ret = NFS3ERR_SERVERFAULT;
1235 MKDIR3args.where.dir.data.data_len = fh->dsize;
1236 MKDIR3args.where.dir.data.data_val = discard_const(fh->dptr);
1237 MKDIR3args.where.name = ptr;
1239 MKDIR3args.attributes.mode.set_it = TRUE;
1240 MKDIR3args.attributes.mode.set_mode3_u.mode = 0777;
1241 MKDIR3args.attributes.uid.set_it = TRUE;
1242 MKDIR3args.attributes.uid.set_uid3_u.uid = 0;
1243 MKDIR3args.attributes.gid.set_it = TRUE;
1244 MKDIR3args.attributes.gid.set_gid3_u.gid = 0;
1245 MKDIR3args.attributes.size.set_it = FALSE;
1246 MKDIR3args.attributes.atime.set_it = FALSE;
1247 MKDIR3args.attributes.mtime.set_it = FALSE;
1249 MKDIR3res = nfsproc3_mkdir_3(&MKDIR3args, nfsio->clnt);
1251 if (MKDIR3res == NULL) {
1252 fprintf(stderr, "nfsproc3_mkdir_3 failed in nfsio_mkdir\n");
1253 ret = NFS3ERR_SERVERFAULT;
1257 if (MKDIR3res->status != NFS3_OK) {
1258 fprintf(stderr, "nfsproc3_mkdir_3(%s) failed in nfsio_mkdir. status:%s(%d)\n", name, nfs_error(MKDIR3res->status), MKDIR3res->status);
1259 ret = MKDIR3res->status;
1263 insert_fhandle(nfsio, name,
1264 MKDIR3res->MKDIR3res_u.resok.obj.post_op_fh3_u.handle.data.data_val,
1265 MKDIR3res->MKDIR3res_u.resok.obj.post_op_fh3_u.handle.data.data_len);
1275 nfsstat3 nfsio_readdirplus(struct nfsio *nfsio, const char *name, nfs3_dirent_cb cb, void *private_data)
1277 struct READDIRPLUS3args READDIRPLUS3args;
1278 struct READDIRPLUS3res *READDIRPLUS3res;
1281 entryplus3 *e, *last_e = NULL;
1286 if(dir[strlen(dir)-1] != '/'){
1289 dir[strlen(dir)-1] = 0;
1292 fh = lookup_fhandle(nfsio, name);
1294 fprintf(stderr, "failed to fetch handle for '%s' in nfsio_readdirplus\n", name);
1295 ret = NFS3ERR_SERVERFAULT;
1299 READDIRPLUS3args.dir.data.data_len = fh->dsize;
1300 READDIRPLUS3args.dir.data.data_val = discard_const(fh->dptr);
1301 READDIRPLUS3args.cookie = 0;
1302 bzero(&READDIRPLUS3args.cookieverf, NFS3_COOKIEVERFSIZE);
1303 READDIRPLUS3args.dircount = 6000;
1304 READDIRPLUS3args.maxcount = 8192;
1307 READDIRPLUS3res = nfsproc3_readdirplus_3(&READDIRPLUS3args, nfsio->clnt);
1309 if (READDIRPLUS3res == NULL) {
1310 fprintf(stderr, "nfsproc3_readdirplus_3 failed in readdirplus\n");
1311 ret = NFS3ERR_SERVERFAULT;
1315 if (READDIRPLUS3res->status != NFS3_OK) {
1316 fprintf(stderr, "nfsproc3_readdirplus_3 failed in readdirplus. status:%d\n", READDIRPLUS3res->status);
1317 ret = READDIRPLUS3res->status;
1321 for(e = READDIRPLUS3res->READDIRPLUS3res_u.resok.reply.entries;e;e=e->nextentry){
1324 if(!strcmp(e->name, ".")){
1327 if(!strcmp(e->name, "..")){
1330 if(e->name_handle.handle_follows == 0){
1336 asprintf(&new_name, "%s/%s", dir, e->name);
1337 insert_fhandle(nfsio, new_name,
1338 e->name_handle.post_op_fh3_u.handle.data.data_val,
1339 e->name_handle.post_op_fh3_u.handle.data.data_len);
1343 cb(e, private_data);
1347 if (READDIRPLUS3res->READDIRPLUS3res_u.resok.reply.eof == 0) {
1348 if (READDIRPLUS3args.cookie == 0) {
1349 memcpy(&READDIRPLUS3args.cookieverf,
1350 &READDIRPLUS3res->READDIRPLUS3res_u.resok.cookieverf,
1351 NFS3_COOKIEVERFSIZE);
1354 READDIRPLUS3args.cookie = last_e->cookie;
1368 nfsstat3 nfsio_rename(struct nfsio *nfsio, const char *old, const char *new)
1371 struct RENAME3args RENAME3args;
1372 struct RENAME3res *RENAME3res;
1374 char *tmp_old_name = NULL;
1375 char *tmp_new_name = NULL;
1376 data_t *old_fh, *new_fh;
1377 char *old_ptr, *new_ptr;
1379 tmp_old_name = strdup(old);
1380 if (tmp_old_name == NULL) {
1381 fprintf(stderr, "failed to strdup name in nfsio_rename\n");
1382 ret = NFS3ERR_SERVERFAULT;
1386 old_ptr = rindex(tmp_old_name, '/');
1387 if (old_ptr == NULL) {
1388 fprintf(stderr, "name did not contain '/' in nfsio_rename\n");
1389 ret = NFS3ERR_SERVERFAULT;
1396 old_fh = lookup_fhandle(nfsio, tmp_old_name);
1397 if (old_fh == NULL) {
1398 fprintf(stderr, "failed to fetch parent handle in nfsio_rename\n");
1399 ret = NFS3ERR_SERVERFAULT;
1403 tmp_new_name = strdup(new);
1404 if (tmp_new_name == NULL) {
1405 fprintf(stderr, "failed to strdup name in nfsio_rename\n");
1406 ret = NFS3ERR_SERVERFAULT;
1410 new_ptr = rindex(tmp_new_name, '/');
1411 if (new_ptr == NULL) {
1412 fprintf(stderr, "name did not contain '/' in nfsio_rename\n");
1413 ret = NFS3ERR_SERVERFAULT;
1420 new_fh = lookup_fhandle(nfsio, tmp_new_name);
1421 if (new_fh == NULL) {
1422 fprintf(stderr, "failed to fetch parent handle in nfsio_rename\n");
1423 ret = NFS3ERR_SERVERFAULT;
1427 RENAME3args.from.dir.data.data_len = old_fh->dsize;
1428 RENAME3args.from.dir.data.data_val = discard_const(old_fh->dptr);
1429 RENAME3args.from.name = old_ptr;
1431 RENAME3args.to.dir.data.data_len = new_fh->dsize;
1432 RENAME3args.to.dir.data.data_val = discard_const(new_fh->dptr);
1433 RENAME3args.to.name = new_ptr;
1436 RENAME3res = nfsproc3_rename_3(&RENAME3args, nfsio->clnt);
1438 if (RENAME3res == NULL) {
1439 fprintf(stderr, "nfsproc3_rename_3 failed in nfsio_rename\n");
1440 ret = NFS3ERR_SERVERFAULT;
1444 if (RENAME3res->status != NFS3_OK) {
1445 fprintf(stderr, "nfsproc3_rename_3 failed in nfsio_rename. status:%d\n", RENAME3res->status);
1446 ret = RENAME3res->status;
1451 old_fh = lookup_fhandle(nfsio, old);
1452 if (old_fh == NULL) {
1453 fprintf(stderr, "failed to fetch parent handle in nfsio_rename\n");
1454 ret = NFS3ERR_SERVERFAULT;
1459 insert_fhandle(nfsio, new, old_fh->dptr, old_fh->dsize);
1460 delete_fhandle(nfsio, old);