diff -r 000cdd124115 -r 5f80c5d0e87f dav/main.c --- a/dav/main.c Wed Oct 25 17:52:35 2017 +0200 +++ b/dav/main.c Sat Oct 28 15:25:17 2017 +0200 @@ -157,8 +157,8 @@ static char *cmdusageinfo[] = { "list [-altdepcR] [-u ] ", - "get [-pcRK] [-o ] [-u ] ", - "put [-pcR] [-k ] [-L ] ", + "get [-pcRKA] [-o ] [-u ] ", + "put [-pcRA] [-k ] [-L ] ", "mkdir [-pc] [-k ] [-L ] ", "remove [-pc] [-L ] ", "copy [-pcO] [-L ] ", @@ -218,6 +218,7 @@ fprintf(stderr, " -d order by last modified date\n"); fprintf(stderr, " -e show extended flags\n"); fprintf(stderr, " -O override resources\n"); + fprintf(stderr, " -A tar import/export\n"); fprintf(stderr, " -L specificy lock token\n"); fprintf(stderr, " -T timeout in seconds\n"); fprintf(stderr, " -n specify namespace uri\n"); @@ -717,12 +718,19 @@ * use stdout if the output file is - */ char *outfile = cmd_getoption(a, "output"); + char *basepath = outfile; + char *tar = cmd_getoption(a, "tar"); if(!outfile) { if(res->iscollection) { - outfile = ""; + basepath = ""; } else { - outfile = res->name; + basepath = res->name; } + if(tar) { + outfile = "-"; + } + } else if(tar) { + basepath = ""; } else if(res->iscollection && !strcmp(outfile, "-")) { fprintf( stderr, @@ -738,7 +746,7 @@ GetResource *getres = malloc(sizeof(GetResource)); getres->res = res; - getres->path = strdup(outfile); + getres->path = strdup(basepath); char *structure = cmd_getoption(a, "structure"); @@ -756,7 +764,7 @@ GetResource *newres = malloc(sizeof(GetResource)); newres->res = child; newres->path = pathlen > 0 ? - util_concat_path(g->path, child->name) : child->name; + util_concat_path(g->path, child->name) : strdup(child->name); stack = ucx_list_prepend(stack, newres); @@ -779,15 +787,36 @@ } } + // download resources int ret; + getfunc get; + TarOutputStream *tout = NULL; + if(tar) { + get = (getfunc)resource2tar; + FILE *tarfile = strcmp(outfile, "-") ? fopen(outfile, "wb") : stdout; + if(!tarfile) { + perror("Cannot open tar output file"); + return -1; + } + tout = tar_open(tarfile); + } else { + get = get_resource; + } UCX_FOREACH(elm, reslist) { GetResource *getres = elm->data; - ret = get_resource(repo, getres->res, a, getres->path); + ret = get(repo, getres, a, tout); if(ret) { break; } } + if(tar) { + // close tar stream + if(tar_close(tout)) { + fprintf(stderr, "tar stream broken\n"); + ret = -1; + } + } ucx_list_free_content(reslist, free_getres); ucx_list_free(reslist); @@ -796,8 +825,9 @@ return ret; } -int get_resource(Repository *repo, DavResource *res, CmdArgs *a, char *out) { - size_t outlen = strlen(out); +int get_resource(Repository *repo, GetResource *getres, CmdArgs *a, void *unused) { + DavResource *res = getres->res; + char *out = res->path; if(res->iscollection) { printf("get: %s\n", res->path); @@ -851,6 +881,35 @@ return 0; } +#define DEFAULT_DIR_MODE T_IRUSR | T_IWUSR | T_IXUSR | T_IRGRP | T_IXGRP | T_IROTH | T_IXOTH +#define DEFAULT_FILE_MODE T_IRUSR | T_IWUSR | T_IRGRP | T_IROTH + +int resource2tar(Repository *repo, GetResource *res, CmdArgs *a, TarOutputStream *tar) { + DavResource *d = res->res; + + if(d->iscollection) { + fprintf(stderr, "add d: %s\n", res->path); + return tar_add_dir(tar, res->path, DEFAULT_DIR_MODE, d->lastmodified); + } + + fprintf(stderr, "add f: %s\n", res->path); + + // add tar file header + if(tar_begin_file(tar, res->path, DEFAULT_FILE_MODE, d->contentlength, d->lastmodified)) { + fprintf(stderr, "TAR Error: %s\n", tar_error2str(tar->error)); + return -1; + } + + if(dav_get_content(d, tar, (dav_write_func)tar_fwrite)) { + print_resource_error(d->session, d->path); + return -1; + } + + // download content + + return tar_end_file(tar); +} + int cmd_put(CmdArgs *a) { if(a->argc != 2) { // TODO: change, when put supports multiple files (however it should do) @@ -883,12 +942,17 @@ } } + char *tar = cmd_getoption(a, "tar"); int ret; - if(!strcmp(file, "-")) { - FILE *in = stdin; - ret = put_file(repo, a, sn, path, "stdin", in, 0); + if(!tar) { + if(!strcmp(file, "-")) { + FILE *in = stdin; + ret = put_file(repo, a, sn, path, "stdin", in, 0); + } else { + ret = put_entry(repo, a, sn, path, file, TRUE); + } } else { - ret = put_entry(repo, a, sn, path, file, TRUE); + ret = put_tar(repo, a, sn, file, path); } free(path); @@ -977,6 +1041,91 @@ return ret; } +int put_tar(Repository *repo, CmdArgs *a, DavSession *sn, char *tarfile, char *path) { + int isstdin = !strcmp(tarfile, "-"); + FILE *in = isstdin ? stdin : fopen(tarfile, "rb"); + if(!in) { + perror("Cannot open tar file"); + return -1; + } + + DavResource *col = NULL; + for(int i=0;i<2;i++) { + col = dav_query(sn, "select - from %s", path); + if(!col && sn->error == DAV_UNAUTHORIZED) { + if(request_auth(repo, sn, a)) { + continue; + } + } + break; + } + if(!col) { + if(sn->error == DAV_NOT_FOUND) { + col = dav_resource_new(sn, path); + col->iscollection = TRUE; + if(dav_create(col)) { + print_resource_error(sn, path); + return -1; + } + } else { + print_resource_error(sn, path); + return -1; + } + } else if(!col->iscollection) { + fprintf(stderr, "%s is not a collection\n", col->href); + return -1; + } + + + int ret = 0; + TarInputStream *tar = tar_inputstream_open(in); + TarEntry *e = NULL; + while((e = tar_read_entry(tar)) != NULL) { + char *newpath = util_concat_path(path, e->path); + if(e->type == TAR_TYPE_FILE) { + fprintf(stderr, "put: %s\n", e->path); + DavResource *res = dav_resource_new(sn, newpath); + dav_set_content(res, tar, (dav_read_func)tar_fread); + dav_set_content_length(res, (size_t)e->size); + + if(dav_store(res)) { + print_resource_error(sn, res->path); + fprintf(stderr, "Cannot upload file.\n"); + if(sn->errorstr) { + fprintf(stderr, "%s\n", sn->errorstr); + } + return -1; + } + + } else if(e->type == TAR_TYPE_DIRECTORY) { + printf("mkcol: %s\n", e->path); + DavResource *res = dav_resource_new(sn, newpath); + res->iscollection = TRUE; + if(!dav_exists(res)) { + if(dav_create(res)) { + fprintf(stderr, "Cannot create collection %s\n", newpath); + print_resource_error(sn, res->path); + ret = 1; + free(newpath); + break; + } + } + } else { + fprintf(stderr, "skip: %s\n", e->path); + } + free(newpath); + } + if(tar->error != TAR_OK) { + ret = -1; + } + + if(!isstdin) { + fclose(in); + } + + return ret; +} + int put_file(Repository *repo, CmdArgs *a, DavSession *sn, char *path, char *name, FILE *in, off_t len) { DavResource *res = NULL; for(int i=0;i<2;i++) {