Fri, 13 Jun 2014 13:52:59 +0200
added new sync tool
/* * 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 <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <time.h> #include <libxml/xmlerror.h> #include <sys/types.h> #include <ucx/string.h> #include <dirent.h> #include <libidav/webdav.h> #include <libidav/utils.h> #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; }