From 71caa3356ce4884f011eaed319ab7646f68e91de Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 8 Jan 2013 00:15:23 +0100 Subject: [PATCH] Automatically creates the destination folder if it does not exist --- modules/csync_owncloud.c | 8 ++++++-- src/csync_propagate.c | 32 +++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/modules/csync_owncloud.c b/modules/csync_owncloud.c index ce8f71c2a..3940440cb 100644 --- a/modules/csync_owncloud.c +++ b/modules/csync_owncloud.c @@ -1907,8 +1907,12 @@ static int owncloud_rename(const char *olduri, const char *newuri) { if( rc >= 0 ) { DEBUG_WEBDAV("MOVE: %s => %s: %d", src, target, rc ); rc = ne_move(dav_session.ctx, 1, src, target ); - - set_errno_from_neon_errcode(rc); + if (rc == NE_ERROR && http_result_code_from_session() == 409) { + /* destination folder might not exist */ + errno = ENOENT; + } else { + set_errno_from_neon_errcode(rc); + } } SAFE_FREE( src ); SAFE_FREE( target ); diff --git a/src/csync_propagate.c b/src/csync_propagate.c index 159debfe2..1233d5e44 100644 --- a/src/csync_propagate.c +++ b/src/csync_propagate.c @@ -694,6 +694,7 @@ static int _csync_rename_file(CSYNC *ctx, csync_file_stat_t *st) { char *duri = NULL; const char *tmd5 = NULL; c_rbnode_t *node = NULL; + char *tdir = NULL; switch (ctx->current) { case REMOTE_REPLICA: @@ -719,21 +720,41 @@ static int _csync_rename_file(CSYNC *ctx, csync_file_stat_t *st) { } CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Renaming %s => %s", suri, duri); - if (! c_streq(suri, duri)) { - if (rc > -1 && (rc = csync_vio_rename(ctx, suri, duri)) != 0) { + if (! c_streq(suri, duri) && rc > -1) { + while ((rc = csync_vio_rename(ctx, suri, duri)) != 0) { switch (errno) { + case ENOENT: + /* get the directory name */ + if(tdir) { + /* we're looping */ + CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, + "dir: %s, loop in mkdir detected!", tdir); + rc = 1; + goto out; + } + tdir = c_dirname(duri); + if (tdir == NULL) { + rc = -1; + goto out; + } + + if (csync_vio_mkdirs(ctx, tdir, C_DIR_MODE) < 0) { + strerror_r(errno, errbuf, sizeof(errbuf)); + CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, + "dir: %s, command: mkdirs, error: %s", + tdir, errbuf); + } + break; default: strerror_r(errno, errbuf, sizeof(errbuf)); CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "dir: %s, command: rename, error: %s", suri, errbuf); - break; + goto out; } - goto out; } - /* set owner and group if possible */ if (ctx->pwd.euid == 0) { csync_vio_chown(ctx, duri, st->uid, st->gid); @@ -782,6 +803,7 @@ static int _csync_rename_file(CSYNC *ctx, csync_file_stat_t *st) { out: SAFE_FREE(suri); SAFE_FREE(duri); + SAFE_FREE(tdir); /* set instruction for the statedb merger */ if (rc != 0) {