155 return ret; |
155 return ret; |
156 } |
156 } |
157 |
157 |
158 static char *cmdusageinfo[] = { |
158 static char *cmdusageinfo[] = { |
159 "list [-altdepcR] [-u <date>] <url>", |
159 "list [-altdepcR] [-u <date>] <url>", |
160 "get [-pcRK] [-o <file>] [-u <date>] <url>", |
160 "get [-pcRKA] [-o <file>] [-u <date>] <url>", |
161 "put [-pcR] [-k <key>] [-L <lock>] <url> <file>", |
161 "put [-pcRA] [-k <key>] [-L <lock>] <url> <file>", |
162 "mkdir [-pc] [-k <key>] [-L <lock>] <url>", |
162 "mkdir [-pc] [-k <key>] [-L <lock>] <url>", |
163 "remove [-pc] [-L <lock>] <url>", |
163 "remove [-pc] [-L <lock>] <url>", |
164 "copy [-pcO] [-L <lock>] <url> <url>", |
164 "copy [-pcO] [-L <lock>] <url> <url>", |
165 "move [-pcO] [-L <lock>] <url> <url>", |
165 "move [-pcO] [-L <lock>] <url> <url>", |
166 "get-property [-pc] [-n <uri>] <url> <property>", |
166 "get-property [-pc] [-n <uri>] <url> <property>", |
216 fprintf(stderr, " -l print resources in long list format\n"); |
216 fprintf(stderr, " -l print resources in long list format\n"); |
217 fprintf(stderr, " -t print content type\n"); |
217 fprintf(stderr, " -t print content type\n"); |
218 fprintf(stderr, " -d order by last modified date\n"); |
218 fprintf(stderr, " -d order by last modified date\n"); |
219 fprintf(stderr, " -e show extended flags\n"); |
219 fprintf(stderr, " -e show extended flags\n"); |
220 fprintf(stderr, " -O override resources\n"); |
220 fprintf(stderr, " -O override resources\n"); |
|
221 fprintf(stderr, " -A tar import/export\n"); |
221 fprintf(stderr, " -L <lock> specificy lock token\n"); |
222 fprintf(stderr, " -L <lock> specificy lock token\n"); |
222 fprintf(stderr, " -T <sec> timeout in seconds\n"); |
223 fprintf(stderr, " -T <sec> timeout in seconds\n"); |
223 fprintf(stderr, " -n <uri> specify namespace uri\n"); |
224 fprintf(stderr, " -n <uri> specify namespace uri\n"); |
224 fprintf(stderr, " -N disable authentication prompt (all commands)\n"); |
225 fprintf(stderr, " -N disable authentication prompt (all commands)\n"); |
225 fprintf(stderr, " -i disable cert verification (all commands)\n"); |
226 fprintf(stderr, " -i disable cert verification (all commands)\n"); |
715 /* |
716 /* |
716 * determine the output file |
717 * determine the output file |
717 * use stdout if the output file is - |
718 * use stdout if the output file is - |
718 */ |
719 */ |
719 char *outfile = cmd_getoption(a, "output"); |
720 char *outfile = cmd_getoption(a, "output"); |
|
721 char *basepath = outfile; |
|
722 char *tar = cmd_getoption(a, "tar"); |
720 if(!outfile) { |
723 if(!outfile) { |
721 if(res->iscollection) { |
724 if(res->iscollection) { |
722 outfile = ""; |
725 basepath = ""; |
723 } else { |
726 } else { |
724 outfile = res->name; |
727 basepath = res->name; |
725 } |
728 } |
|
729 if(tar) { |
|
730 outfile = "-"; |
|
731 } |
|
732 } else if(tar) { |
|
733 basepath = ""; |
726 } else if(res->iscollection && !strcmp(outfile, "-")) { |
734 } else if(res->iscollection && !strcmp(outfile, "-")) { |
727 fprintf( |
735 fprintf( |
728 stderr, |
736 stderr, |
729 "Cannot write output to stdout " |
737 "Cannot write output to stdout " |
730 "if the requested resource is a collection.\n"); |
738 "if the requested resource is a collection.\n"); |
736 uint64_t totalsize = 0; |
744 uint64_t totalsize = 0; |
737 uint64_t rescount = 0; |
745 uint64_t rescount = 0; |
738 |
746 |
739 GetResource *getres = malloc(sizeof(GetResource)); |
747 GetResource *getres = malloc(sizeof(GetResource)); |
740 getres->res = res; |
748 getres->res = res; |
741 getres->path = strdup(outfile); |
749 getres->path = strdup(basepath); |
742 |
750 |
743 char *structure = cmd_getoption(a, "structure"); |
751 char *structure = cmd_getoption(a, "structure"); |
744 |
752 |
745 // iterate over resource tree |
753 // iterate over resource tree |
746 UcxList *stack = ucx_list_prepend(NULL, getres); |
754 UcxList *stack = ucx_list_prepend(NULL, getres); |
754 // add resource to stack |
762 // add resource to stack |
755 size_t pathlen = strlen(g->path); |
763 size_t pathlen = strlen(g->path); |
756 GetResource *newres = malloc(sizeof(GetResource)); |
764 GetResource *newres = malloc(sizeof(GetResource)); |
757 newres->res = child; |
765 newres->res = child; |
758 newres->path = pathlen > 0 ? |
766 newres->path = pathlen > 0 ? |
759 util_concat_path(g->path, child->name) : child->name; |
767 util_concat_path(g->path, child->name) : strdup(child->name); |
760 |
768 |
761 stack = ucx_list_prepend(stack, newres); |
769 stack = ucx_list_prepend(stack, newres); |
762 |
770 |
763 child = child->next; |
771 child = child->next; |
764 } |
772 } |
777 } else { |
785 } else { |
778 reslist = ucx_list_append(reslist, g); |
786 reslist = ucx_list_append(reslist, g); |
779 } |
787 } |
780 } |
788 } |
781 |
789 |
|
790 // download resources |
782 int ret; |
791 int ret; |
|
792 getfunc get; |
|
793 TarOutputStream *tout = NULL; |
|
794 if(tar) { |
|
795 get = (getfunc)resource2tar; |
|
796 FILE *tarfile = strcmp(outfile, "-") ? fopen(outfile, "wb") : stdout; |
|
797 if(!tarfile) { |
|
798 perror("Cannot open tar output file"); |
|
799 return -1; |
|
800 } |
|
801 tout = tar_open(tarfile); |
|
802 } else { |
|
803 get = get_resource; |
|
804 } |
783 UCX_FOREACH(elm, reslist) { |
805 UCX_FOREACH(elm, reslist) { |
784 GetResource *getres = elm->data; |
806 GetResource *getres = elm->data; |
785 |
807 |
786 ret = get_resource(repo, getres->res, a, getres->path); |
808 ret = get(repo, getres, a, tout); |
787 if(ret) { |
809 if(ret) { |
788 break; |
810 break; |
|
811 } |
|
812 } |
|
813 if(tar) { |
|
814 // close tar stream |
|
815 if(tar_close(tout)) { |
|
816 fprintf(stderr, "tar stream broken\n"); |
|
817 ret = -1; |
789 } |
818 } |
790 } |
819 } |
791 |
820 |
792 ucx_list_free_content(reslist, free_getres); |
821 ucx_list_free_content(reslist, free_getres); |
793 ucx_list_free(reslist); |
822 ucx_list_free(reslist); |
794 free(path); |
823 free(path); |
795 |
824 |
796 return ret; |
825 return ret; |
797 } |
826 } |
798 |
827 |
799 int get_resource(Repository *repo, DavResource *res, CmdArgs *a, char *out) { |
828 int get_resource(Repository *repo, GetResource *getres, CmdArgs *a, void *unused) { |
800 size_t outlen = strlen(out); |
829 DavResource *res = getres->res; |
|
830 char *out = res->path; |
801 |
831 |
802 if(res->iscollection) { |
832 if(res->iscollection) { |
803 printf("get: %s\n", res->path); |
833 printf("get: %s\n", res->path); |
804 |
834 |
805 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; |
835 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; |
849 } |
879 } |
850 |
880 |
851 return 0; |
881 return 0; |
852 } |
882 } |
853 |
883 |
|
884 #define DEFAULT_DIR_MODE T_IRUSR | T_IWUSR | T_IXUSR | T_IRGRP | T_IXGRP | T_IROTH | T_IXOTH |
|
885 #define DEFAULT_FILE_MODE T_IRUSR | T_IWUSR | T_IRGRP | T_IROTH |
|
886 |
|
887 int resource2tar(Repository *repo, GetResource *res, CmdArgs *a, TarOutputStream *tar) { |
|
888 DavResource *d = res->res; |
|
889 |
|
890 if(d->iscollection) { |
|
891 fprintf(stderr, "add d: %s\n", res->path); |
|
892 return tar_add_dir(tar, res->path, DEFAULT_DIR_MODE, d->lastmodified); |
|
893 } |
|
894 |
|
895 fprintf(stderr, "add f: %s\n", res->path); |
|
896 |
|
897 // add tar file header |
|
898 if(tar_begin_file(tar, res->path, DEFAULT_FILE_MODE, d->contentlength, d->lastmodified)) { |
|
899 fprintf(stderr, "TAR Error: %s\n", tar_error2str(tar->error)); |
|
900 return -1; |
|
901 } |
|
902 |
|
903 if(dav_get_content(d, tar, (dav_write_func)tar_fwrite)) { |
|
904 print_resource_error(d->session, d->path); |
|
905 return -1; |
|
906 } |
|
907 |
|
908 // download content |
|
909 |
|
910 return tar_end_file(tar); |
|
911 } |
|
912 |
854 int cmd_put(CmdArgs *a) { |
913 int cmd_put(CmdArgs *a) { |
855 if(a->argc != 2) { |
914 if(a->argc != 2) { |
856 // TODO: change, when put supports multiple files (however it should do) |
915 // TODO: change, when put supports multiple files (however it should do) |
857 fprintf(stderr, "Too %s arguments\n", a->argc < 2 ? "few":"many"); |
916 fprintf(stderr, "Too %s arguments\n", a->argc < 2 ? "few":"many"); |
858 fprintf(stderr, "Usage: dav %s\n", find_usage_str("put")); |
917 fprintf(stderr, "Usage: dav %s\n", find_usage_str("put")); |
881 // TODO: free |
940 // TODO: free |
882 return -1; |
941 return -1; |
883 } |
942 } |
884 } |
943 } |
885 |
944 |
|
945 char *tar = cmd_getoption(a, "tar"); |
886 int ret; |
946 int ret; |
887 if(!strcmp(file, "-")) { |
947 if(!tar) { |
888 FILE *in = stdin; |
948 if(!strcmp(file, "-")) { |
889 ret = put_file(repo, a, sn, path, "stdin", in, 0); |
949 FILE *in = stdin; |
|
950 ret = put_file(repo, a, sn, path, "stdin", in, 0); |
|
951 } else { |
|
952 ret = put_entry(repo, a, sn, path, file, TRUE); |
|
953 } |
890 } else { |
954 } else { |
891 ret = put_entry(repo, a, sn, path, file, TRUE); |
955 ret = put_tar(repo, a, sn, file, path); |
892 } |
956 } |
893 |
957 |
894 free(path); |
958 free(path); |
895 return ret; |
959 return ret; |
896 } |
960 } |
969 } |
1033 } |
970 char *filename = util_resource_name(file); |
1034 char *filename = util_resource_name(file); |
971 //path = util_concat_path(path, filename); |
1035 //path = util_concat_path(path, filename); |
972 ret = put_file(repo, a, sn, path, filename, in, s.st_size); |
1036 ret = put_file(repo, a, sn, path, filename, in, s.st_size); |
973 //free(path); |
1037 //free(path); |
|
1038 fclose(in); |
|
1039 } |
|
1040 |
|
1041 return ret; |
|
1042 } |
|
1043 |
|
1044 int put_tar(Repository *repo, CmdArgs *a, DavSession *sn, char *tarfile, char *path) { |
|
1045 int isstdin = !strcmp(tarfile, "-"); |
|
1046 FILE *in = isstdin ? stdin : fopen(tarfile, "rb"); |
|
1047 if(!in) { |
|
1048 perror("Cannot open tar file"); |
|
1049 return -1; |
|
1050 } |
|
1051 |
|
1052 DavResource *col = NULL; |
|
1053 for(int i=0;i<2;i++) { |
|
1054 col = dav_query(sn, "select - from %s", path); |
|
1055 if(!col && sn->error == DAV_UNAUTHORIZED) { |
|
1056 if(request_auth(repo, sn, a)) { |
|
1057 continue; |
|
1058 } |
|
1059 } |
|
1060 break; |
|
1061 } |
|
1062 if(!col) { |
|
1063 if(sn->error == DAV_NOT_FOUND) { |
|
1064 col = dav_resource_new(sn, path); |
|
1065 col->iscollection = TRUE; |
|
1066 if(dav_create(col)) { |
|
1067 print_resource_error(sn, path); |
|
1068 return -1; |
|
1069 } |
|
1070 } else { |
|
1071 print_resource_error(sn, path); |
|
1072 return -1; |
|
1073 } |
|
1074 } else if(!col->iscollection) { |
|
1075 fprintf(stderr, "%s is not a collection\n", col->href); |
|
1076 return -1; |
|
1077 } |
|
1078 |
|
1079 |
|
1080 int ret = 0; |
|
1081 TarInputStream *tar = tar_inputstream_open(in); |
|
1082 TarEntry *e = NULL; |
|
1083 while((e = tar_read_entry(tar)) != NULL) { |
|
1084 char *newpath = util_concat_path(path, e->path); |
|
1085 if(e->type == TAR_TYPE_FILE) { |
|
1086 fprintf(stderr, "put: %s\n", e->path); |
|
1087 DavResource *res = dav_resource_new(sn, newpath); |
|
1088 dav_set_content(res, tar, (dav_read_func)tar_fread); |
|
1089 dav_set_content_length(res, (size_t)e->size); |
|
1090 |
|
1091 if(dav_store(res)) { |
|
1092 print_resource_error(sn, res->path); |
|
1093 fprintf(stderr, "Cannot upload file.\n"); |
|
1094 if(sn->errorstr) { |
|
1095 fprintf(stderr, "%s\n", sn->errorstr); |
|
1096 } |
|
1097 return -1; |
|
1098 } |
|
1099 |
|
1100 } else if(e->type == TAR_TYPE_DIRECTORY) { |
|
1101 printf("mkcol: %s\n", e->path); |
|
1102 DavResource *res = dav_resource_new(sn, newpath); |
|
1103 res->iscollection = TRUE; |
|
1104 if(!dav_exists(res)) { |
|
1105 if(dav_create(res)) { |
|
1106 fprintf(stderr, "Cannot create collection %s\n", newpath); |
|
1107 print_resource_error(sn, res->path); |
|
1108 ret = 1; |
|
1109 free(newpath); |
|
1110 break; |
|
1111 } |
|
1112 } |
|
1113 } else { |
|
1114 fprintf(stderr, "skip: %s\n", e->path); |
|
1115 } |
|
1116 free(newpath); |
|
1117 } |
|
1118 if(tar->error != TAR_OK) { |
|
1119 ret = -1; |
|
1120 } |
|
1121 |
|
1122 if(!isstdin) { |
974 fclose(in); |
1123 fclose(in); |
975 } |
1124 } |
976 |
1125 |
977 return ret; |
1126 return ret; |
978 } |
1127 } |