# HG changeset patch # User Olaf Wintermann # Date 1458310110 -3600 # Node ID e22c29b7ee2f40d37a9158ee2d9e091ad5e6a8e3 # Parent f1b3873a65258b123cdbd5c7ca8afdaf1e2e6c70 using locks in dav-sync Locking can be configured in sync.xml with true|false and true|false. By default lock-pull is false and lock-push is true. diff -r f1b3873a6525 -r e22c29b7ee2f dav/scfg.c --- a/dav/scfg.c Fri Mar 18 13:00:00 2016 +0100 +++ b/dav/scfg.c Fri Mar 18 15:08:30 2016 +0100 @@ -129,6 +129,8 @@ UcxList *exclude = NULL; int max_retry = DAV_MAX_RETRY; bool backuppull = false; + bool lockpull = false; + bool lockpush = true; node = node->children; while(node) { @@ -162,6 +164,10 @@ } } else if(xstreq(node->name, "backup-on-pull")) { backuppull = util_getboolean(value); + } else if(xstreq(node->name, "lock-pull")) { + lockpull = util_getboolean(value); + } else if(xstreq(node->name, "lock-push")) { + lockpush = util_getboolean(value); } } node = node->next; @@ -192,6 +198,8 @@ dir->database = strdup(database); dir->max_retry = max_retry; dir->backuppull = backuppull; + dir->lockpull = lockpull; + dir->lockpush = lockpush; if (include) { dir->include = include; } else { diff -r f1b3873a6525 -r e22c29b7ee2f dav/scfg.h --- a/dav/scfg.h Fri Mar 18 13:00:00 2016 +0100 +++ b/dav/scfg.h Fri Mar 18 15:08:30 2016 +0100 @@ -51,6 +51,8 @@ UcxList *exclude; int max_retry; bool backuppull; + bool lockpull; + bool lockpush; } SyncDirectory; int load_sync_config(); diff -r f1b3873a6525 -r e22c29b7ee2f dav/sopt.c --- a/dav/sopt.c Fri Mar 18 13:00:00 2016 +0100 +++ b/dav/sopt.c Fri Mar 18 15:08:30 2016 +0100 @@ -81,6 +81,14 @@ ucx_map_cstr_put(a->options, "conflict", NOARG); break; } + case 'l': { + ucx_map_cstr_put(a->options, "lock", NOARG); + break; + } + case 'd': { + ucx_map_cstr_put(a->options, "nolock", NOARG); + break; + } case 'r': { ucx_map_cstr_put(a->options, "read", NOARG); break; diff -r f1b3873a6525 -r e22c29b7ee2f dav/sync.c --- a/dav/sync.c Fri Mar 18 13:00:00 2016 +0100 +++ b/dav/sync.c Fri Mar 18 15:08:30 2016 +0100 @@ -121,8 +121,8 @@ fprintf(stderr, "Usage: %s command [options] arguments...\n\n", cmd); fprintf(stderr, "Commands:\n"); - fprintf(stderr, " pull [-c] \n"); - fprintf(stderr, " push [-c] \n"); + fprintf(stderr, " pull [-cld] \n"); + fprintf(stderr, " push [-cld] \n"); fprintf(stderr, " resolve-conflicts \n"); fprintf(stderr, " delete-conflicts \n"); fprintf(stderr, " trash-info \n"); @@ -130,6 +130,8 @@ fprintf(stderr, "Options:\n"); fprintf(stderr, " -c Disable conflict detection\n"); + fprintf(stderr, " -l Lock the repository before access\n"); + fprintf(stderr, " -d Don't lock the repository\n"); //fprintf(stderr, " -r Read changes from stdin\n\n"); fprintf(stderr, " -v verbose output (all commands)\n\n"); @@ -223,9 +225,30 @@ curl_easy_setopt(sn->handle, CURLOPT_STDERR, stderr); } + // lock repository + DavBool locked = FALSE; + DavResource *root = dav_resource_new(sn, "/"); + root->iscollection = TRUE; + if((dir->lockpush || cmd_getoption(a, "lock")) && !cmd_getoption(a, "nolock")) { + if(dav_lock(root)) { + print_resource_error(sn, "/"); + dav_session_destroy(sn); + fprintf(stderr, "Abort\n"); + return -1; + } + locked = TRUE; + } + + int ret = 0; DavResource *ls = dav_query(sn, "select D:getetag,idav:status from / with depth = infinity"); if(!ls) { print_resource_error(sn, "/"); + if(locked) { + if(dav_unlock(root)) { + print_resource_error(sn, "/"); + } + } + fprintf(stderr, "Abort\n"); dav_session_destroy(sn); @@ -240,6 +263,11 @@ if(!ls->children) { // TODO: free fprintf(stderr, "Repository is empty\n"); + if(locked) { + if(dav_unlock(root)) { + print_resource_error(sn, "/"); + } + } return 0; // empty repository } @@ -305,26 +333,35 @@ ucx_map_free(db->resources); db->resources = svrres; + // unlock repository + if(locked) { + if(dav_unlock(root)) { + print_resource_error(sn, "/"); + ret = -1; + } + } + // store db if(store_db(db, dir->database)) { fprintf(stderr, "Cannot store sync db\n"); - fprintf(stderr, "Abort\n"); - return -1; // TODO: don't return here + ret = -1; } // TODO: cleanup - BUT DONT CLEANUP SYNC CONFIG (do this in main!) dav_session_destroy(sn); // Report - char *str_success = sync_success == 1 ? "file" : "files"; - char *str_delete = sync_delete == 1 ? "file" : "files"; - char *str_error = sync_error == 1 ? "error" : "errors"; - printf("Result: %d %s pulled, %d %s deleted, %d %s\n", - sync_success, str_success, - sync_delete,str_delete, - sync_error, str_error); + if(ret == 0) { + char *str_success = sync_success == 1 ? "file" : "files"; + char *str_delete = sync_delete == 1 ? "file" : "files"; + char *str_error = sync_error == 1 ? "error" : "errors"; + printf("Result: %d %s pulled, %d %s deleted, %d %s\n", + sync_success, str_success, + sync_delete,str_delete, + sync_error, str_error); + } - return 0; + return ret; } int sync_get_resource( @@ -666,8 +703,8 @@ curl_easy_setopt(sn->handle, CURLOPT_STDERR, stderr); } - DavResource *testsvr = dav_query(sn, "select - from / with depth = 0"); - if(!testsvr) { + DavResource *root = dav_query(sn, "select - from / with depth = 0"); + if(!root) { print_resource_error(sn, "/"); dav_session_destroy(sn); fprintf(stderr, "Abort\n"); @@ -676,6 +713,18 @@ int cdt = cmd_getoption(a, "conflict") ? 0 : 1; // conflict detection + // lock repository + DavBool locked = FALSE; + if((dir->lockpush || cmd_getoption(a, "lock")) && !cmd_getoption(a, "nolock")) { + if(dav_lock(root)) { + print_resource_error(sn, "/"); + dav_session_destroy(sn); + fprintf(stderr, "Abort\n"); + return -1; + } + locked = TRUE; + } + int sync_success = 0; int sync_delete = 0; int sync_skipped = 0; @@ -759,26 +808,37 @@ ucx_map_free(db->resources); db->resources = lclres; + // unlock repository + if(locked) { + if(dav_unlock(root)) { + print_resource_error(sn, "/"); + ret = -1; + } + } + // store db if(store_db(db, dir->database)) { fprintf(stderr, "Cannot store sync db\n"); - return -1; + ret = -1; } - // TODO: free res + // cleanup + dav_session_destroy(sn); // Report - char *str_success = sync_success == 1 ? "file" : "files"; - char *str_delete = sync_delete == 1 ? "file" : "files"; - char *str_skipped = sync_delete == 1 ? "file" : "files"; - char *str_error = sync_error == 1 ? "error" : "errors"; - printf("Result: %d %s pushed, %d %s deleted, %d %s skipped, %d %s\n", - sync_success, str_success, - sync_delete,str_delete, - sync_skipped,str_skipped, - sync_error, str_error); + if(ret == 0) { + char *str_success = sync_success == 1 ? "file" : "files"; + char *str_delete = sync_delete == 1 ? "file" : "files"; + char *str_skipped = sync_delete == 1 ? "file" : "files"; + char *str_error = sync_error == 1 ? "error" : "errors"; + printf("Result: %d %s pushed, %d %s deleted, %d %s skipped, %d %s\n", + sync_success, str_success, + sync_delete,str_delete, + sync_skipped,str_skipped, + sync_error, str_error); + } - return 0; + return ret; } UcxList* local_scan(SyncDirectory *dir, SyncDatabase *db) { @@ -905,7 +965,6 @@ res->isdirectory = 1; return res; } - return NULL; } int local_resource_is_changed(SyncDirectory *dir, SyncDatabase *db, LocalResource *res) { diff -r f1b3873a6525 -r e22c29b7ee2f dav/version.h --- a/dav/version.h Fri Mar 18 13:00:00 2016 +0100 +++ b/dav/version.h Fri Mar 18 15:08:30 2016 +0100 @@ -29,7 +29,7 @@ #ifndef VERSION_H #define VERSION_H -#define DAV_VERSION "0.9.7 dev" +#define DAV_VERSION "0.9.8 dev" #endif /* VERSION_H */ diff -r f1b3873a6525 -r e22c29b7ee2f libidav/webdav.h --- a/libidav/webdav.h Fri Mar 18 13:00:00 2016 +0100 +++ b/libidav/webdav.h Fri Mar 18 15:08:30 2016 +0100 @@ -43,12 +43,12 @@ typedef int DavBool; #ifndef TRUE -#define TRUE 0 +#define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif - + typedef struct DavContext DavContext; typedef struct DavProxy DavProxy; typedef struct DavSession DavSession;