# HG changeset patch # User Olaf Wintermann # Date 1455298018 -3600 # Node ID a76e43d89f556176552f4e8d5bf354dbc3b7a51c # Parent 0d04ccf6747bbea1e133452489e319dea960e1d7 dav-sync can create and delete empty directories now diff -r 0d04ccf6747b -r a76e43d89f55 dav/db.h --- a/dav/db.h Wed Feb 10 12:32:07 2016 +0100 +++ b/dav/db.h Fri Feb 12 18:26:58 2016 +0100 @@ -46,8 +46,9 @@ char *name; char *path; char *etag; - time_t last_modified; - off_t size; + time_t last_modified; + off_t size; + DavBool isdirectory; }; struct SyncDatabase { diff -r 0d04ccf6747b -r a76e43d89f55 dav/main.h --- a/dav/main.h Wed Feb 10 12:32:07 2016 +0100 +++ b/dav/main.h Fri Feb 12 18:26:58 2016 +0100 @@ -33,7 +33,7 @@ #include "optparser.h" #include -#define DAV_VERSION "0.9.1" +#include "version.h" #ifdef __cplusplus extern "C" { diff -r 0d04ccf6747b -r a76e43d89f55 dav/sync.c --- a/dav/sync.c Wed Feb 10 12:32:07 2016 +0100 +++ b/dav/sync.c Fri Feb 12 18:26:58 2016 +0100 @@ -88,6 +88,12 @@ ret = cmd_pull(args); } else if(!strcmp(cmd, "push")) { ret = cmd_push(args); + } else if(!strcasecmp(cmd, "version") || !strcasecmp(cmd, "-version") || !strcasecmp(cmd, "--version")) { +#ifdef DEBUG + fprintf(stderr, "dav-synv %s unstable\n", DAV_VERSION); +#else + fprintf(stderr, "dav-sync %s\n", DAV_VERSION); +#endif } // TODO: cleanup sync config (don't forget to call regfree for regex) @@ -236,12 +242,19 @@ // delete every remotely removed resource UcxMapIterator i = ucx_map_iterator(db->resources); LocalResource *local; + UcxList *rmdirs = NULL; UCX_MAP_FOREACH(key, local, i) { if (res_matches_filter(dir, local->path)) { continue; } // sync_remove_resource does all necessary tests - sync_remove_local_resource(dir, local); + if(sync_remove_local_resource(dir, local)) { + rmdirs = ucx_list_append(rmdirs, local); + } + } + UCX_FOREACH(elm, rmdirs) { + LocalResource *local_dir = elm->data; + sync_remove_local_directory(dir, local_dir); } ucx_map_free(db->resources); db->resources = svrres; @@ -265,7 +278,7 @@ char *etag = dav_get_property(res, "D:getetag"); struct stat s; - if(local) { + if(local && !res->iscollection) { int exists = 1; if(stat(local_path, &s)) { // Ignore the fact, that the file is locally removed. If the @@ -315,6 +328,16 @@ if(util_mkdir(local_path, mode) && errno != EEXIST) { ret = -1; } + + if(ret == 0) { + if(!local) { + // new local resource + local = calloc(1, sizeof(LocalResource)); + local->path = util_concat_path(res->path, "/"); + local->last_modified = s.st_mtime; + ucx_map_cstr_put(db->resources, local->path, local); + } + } } else { if(!tmp_path) { fprintf(stderr, "Cannot create tmp path for %s\n", local_path); @@ -381,17 +404,22 @@ return ret; } -void sync_remove_local_resource(SyncDirectory *dir, LocalResource *res) { +int sync_remove_local_resource(SyncDirectory *dir, LocalResource *res) { char *local_path = util_concat_path(dir->path, res->path); struct stat s; if(stat(local_path, &s)) { free(local_path); - return; + return 0; + } + + if(S_ISDIR(s.st_mode)) { + free(local_path); + return 1; } if(s.st_mtime != res->last_modified) { free(local_path); - return; + return 0; } printf("delete: %s\n", res->path); @@ -402,6 +430,19 @@ fprintf(stderr, "Cannot remove file %s\n", local_path); } free(local_path); + + return 0; +} + +void sync_remove_local_directory(SyncDirectory *dir, LocalResource *res) { + char *local_path = util_concat_path(dir->path, res->path); + + printf("delete: %s\n", res->path); + if(rmdir(local_path)) { + // TODO + } + + free(local_path); } void rename_local_file(SyncDirectory *dir, SyncDatabase *db, char *path) { @@ -549,10 +590,18 @@ if (!res_matches_filter(dir, local_res->path+1)) { // upload every changed file if (local_resource_is_changed(dir, db, local_res)) { - printf("put: %s\n", local_res->path); DavResource *res = dav_resource_new(sn, local_res->path); - if(sync_put_resource(dir, res, local_res)) { - // TODO: I don't know what to do now + + if(local_res->isdirectory) { + printf("mkcol: %s\n", local_res->path); + if(sync_mkdir(dir, res, local_res)) { + // TODO: I don't know what to do now + } + } else { + printf("put: %s\n", local_res->path); + if(sync_put_resource(dir, res, local_res)) { + // TODO: I don't know what to do now + } } dav_resource_free(res); } @@ -616,6 +665,7 @@ int isdir; LocalResource *res = local_resource_new(dir, db, new_path, &isdir); if(isdir) { + resources = ucx_list_append(resources, res); stack = ucx_list_prepend(stack, new_path); } else if(res) { resources = ucx_list_append(resources, res); @@ -706,6 +756,11 @@ return res; } else { *isdir = 1; + LocalResource *res = calloc(1, sizeof(LocalResource)); + res->path = util_concat_path(path, "/"); + res->last_modified = s.st_mtime; + res->isdirectory = 1; + return res; } return NULL; } @@ -822,31 +877,52 @@ return ret; } +int sync_mkdir(SyncDirectory *dir, DavResource *res, LocalResource *local) { + res->iscollection = 1; + int ret = -1; + for(int i=0;imax_retry;i++) { + if(dav_create(res)) { + continue; + } + ret = 0; + break; + } + return ret; +} + int sync_delete_remote_resource(DavSession *sn, LocalResource *local_res) { DavResource *res = dav_get(sn, local_res->path, "D:getetag"); if(!res) { return sn->error == DAV_NOT_FOUND ? 0 : 1; } - char *etag = dav_get_property(res, "D:getetag"); - if(etag) { - if(strlen(etag) > 2 && etag[0] == 'W' && etag[1] == '/') { - etag = etag + 2; - } - } - int ret = 0; - if(etag && !strcmp(etag, local_res->etag)) { - // local resource metadata == remote resource metadata - // resource can be deleted + if(res->iscollection) { printf("delete: %s\n", res->path); if(dav_delete(res)) { - if(sn->error != DAV_NOT_FOUND) { - fprintf(stderr, "Cannot delete resource %s\n", res->path); - } + ret = 1; + fprintf(stderr, "Cannot delete resource %s\n", res->path); } } else { - ret = 1; + char *etag = dav_get_property(res, "D:getetag"); + if(etag) { + if(strlen(etag) > 2 && etag[0] == 'W' && etag[1] == '/') { + etag = etag + 2; + } + } + + if(etag && !strcmp(etag, local_res->etag)) { + // local resource metadata == remote resource metadata + // resource can be deleted + printf("delete: %s\n", res->path); + if(dav_delete(res)) { + if(sn->error != DAV_NOT_FOUND) { + fprintf(stderr, "Cannot delete resource %s\n", res->path); + } + } + } else { + ret = 1; + } } // cleanup diff -r 0d04ccf6747b -r a76e43d89f55 dav/sync.h --- a/dav/sync.h Wed Feb 10 12:32:07 2016 +0100 +++ b/dav/sync.h Fri Feb 12 18:26:58 2016 +0100 @@ -35,6 +35,8 @@ #include "sopt.h" +#include "version.h" + #ifdef __cplusplus extern "C" { #endif @@ -48,7 +50,8 @@ int cmd_sync(CmdArgs *args); int sync_get_resource(CmdArgs *a, SyncDirectory *dir, DavResource *res, SyncDatabase *db); -void sync_remove_local_resource(SyncDirectory *dir, LocalResource *res); +int sync_remove_local_resource(SyncDirectory *dir, LocalResource *res); +void sync_remove_local_directory(SyncDirectory *dir, LocalResource *res); void rename_local_file(SyncDirectory *dir, SyncDatabase *db, char *path); char* create_tmp_download_path(char *path); void move_to_trash(SyncDirectory *dir, char *path); @@ -60,6 +63,7 @@ int sync_set_status(DavResource *res, char *status); int sync_remove_status(DavResource *res); int sync_put_resource(SyncDirectory *dir, DavResource *res, LocalResource *local); +int sync_mkdir(SyncDirectory *dir, DavResource *res, LocalResource *local); int sync_delete_remote_resource(DavSession *sn, LocalResource *res); diff -r 0d04ccf6747b -r a76e43d89f55 dav/version.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dav/version.h Fri Feb 12 18:26:58 2016 +0100 @@ -0,0 +1,35 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2016 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. + */ + +#ifndef VERSION_H +#define VERSION_H + +#define DAV_VERSION "0.9.2" + +#endif /* VERSION_H */ +