diff -r e3839719b079 -r 0542668d0f26 dav/sync.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dav/sync.c Fri Jun 13 13:52:59 2014 +0200 @@ -0,0 +1,211 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "config.h" +#include "scfg.h" +#include "sopt.h" +#include "db.h" + +#include "sync.h" + +static DavContext *ctx; + +static void xmlerrorfnc(void * c, const char * msg, ... ) { + // nothing +} + +int main(int argc, char **argv) { + if(argc < 2) { + fprintf(stderr, "Missing command\n"); + print_usage(argv[0]); + return -1; + } + + char *cmd = argv[1]; + CmdArgs *args = cmd_parse_args(argc - 2, argv + 2); + if(!args) { + print_usage(argv[0]); + return -1; + } + + xmlGenericErrorFunc fnc = xmlerrorfnc; + initGenericErrorDefaultFunc(&fnc); + ctx = dav_context_new(); + load_config(ctx); + if(load_sync_config()) { + return EXIT_FAILURE; + } + + int ret = EXIT_FAILURE; + if(!strcmp(cmd, "pull")) { + ret = cmd_pull(args); + } else if(!strcmp(cmd, "push")) { + ret = cmd_pull(args); + } else if(!strcmp(cmd, "sync")) { + ret = cmd_sync(args); + } + + return ret; +} + +void print_usage(char *cmd) { + +} + +int cmd_pull(CmdArgs *a) { + if(a->argc != 1) { + fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many"); + return -1; + } + + SyncDirectory *dir = scfg_get_dir(a->argv[0]); + if(!dir) { + fprintf(stderr, "Unknown sync dir: %s\n", a->argv[0]); + return -1; + } + + Repository *repo = get_repository(sstr(dir->repository)); + if(!repo) { + fprintf(stderr, "Unkown repository %s\n", dir->name); + return -1; + } + + UcxMap *db = load_db(dir->database); + if(!db) { + fprintf(stderr, "Cannot load database file: %s\n", dir->database); + return -1; + } + + DavSession *sn = dav_session_new_auth( + ctx, + repo->url, + repo->user, + repo->password); + dav_session_set_flags(sn, get_repository_flags(repo)); + sn->key = dav_context_get_key(ctx, repo->default_key); + + DavResource *ls = dav_query(sn, "get D:getetag from / where lastmodified > 0 with depth -1"); + if(!ls) { + fprintf(stderr, "Error\n"); + // TODO: free + return -1; + } + + if(!ls->children) { + // TODO: free + return 0; // empty repository + } + + UcxList *stack = ucx_list_prepend(NULL, ls->children); + while(stack) { + DavResource *res = stack->data; + stack = ucx_list_remove(stack, stack); + + while(res) { + if(sync_get_resource(dir, res, db)) { + fprintf(stderr, "sync_get_resource failed for resource: %s\n", res->path); + } + + if(res->children) { + stack = ucx_list_prepend(stack, res->children); + } + res = res->next; + } + } + + // store db + + + return 0; +} + +int sync_get_resource(SyncDirectory *dir, DavResource *res, UcxMap *db) { + LocalResource *local = ucx_map_cstr_get(db, res->path); + char *etag = dav_get_property(res, "D:getetag"); + if(local) { + if(local->etag && !strcmp(etag, local->etag)) { + // resource is already up-to-date on the client + return 0; + } + } + + char *local_path = util_concat_path(dir->path, res->path); + int ret = 0; + if(res->iscollection) { + mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + printf("mkdir %s\n", local_path); + if(util_mkdir(local_path, mode) && errno != EEXIST) { + ret = -1; + } + } else { + FILE *out = fopen(local_path, "w"); + if(!out) { + fprintf(stderr, "cannot open output file: %s\n", local_path); + free(local_path); + return -1; + } + printf("get %s\n", res->path); + if(dav_get_content(res, out, (dav_write_func)fwrite)) { + ret = -1; + } else { + if(local) { + if(local->etag) { + free(local->etag); + } + local->etag = etag; + } + } + fclose(out); + } + + free(local_path); + return ret; +} + +int cmd_push(CmdArgs *a) { + return 0; +} + +int cmd_sync(CmdArgs *a) { + return 0; +} +