From 62d26814b2e333deb9a5b61b9fc9ea7d33594add Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Mon, 12 Oct 2015 17:06:49 +0200 Subject: [PATCH 1/3] SyncEngine: Handle 403 Forbidden properly. A 403 is a reply code sent from the file firewall to indicate that this directory is forbidden to use for the user. The patch handles it by setting the state to IGNORED. This addresses #3490 --- csync/src/csync.h | 3 ++- csync/src/csync_macros.h | 1 + csync/src/csync_update.c | 14 ++++++++++++++ src/libsync/discoveryphase.cpp | 4 +++- src/libsync/syncengine.cpp | 8 ++++++++ 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/csync/src/csync.h b/csync/src/csync.h index 49abffd60..e2ab1aea7 100644 --- a/csync/src/csync.h +++ b/csync/src/csync.h @@ -102,7 +102,8 @@ enum csync_status_codes_e { CYSNC_STATUS_FILE_LOCKED_OR_OPEN, CSYNC_STATUS_INDIVIDUAL_EXCLUDE_HIDDEN, CSYNC_STATUS_INVALID_CHARACTERS, - CSYNC_STATUS_INDIVIDUAL_STAT_FAILED + CSYNC_STATUS_INDIVIDUAL_STAT_FAILED, + CSYNC_STATUS_FORBIDDEN }; typedef enum csync_status_codes_e CSYNC_STATUS; diff --git a/csync/src/csync_macros.h b/csync/src/csync_macros.h index 925a523a6..f128b434d 100644 --- a/csync/src/csync_macros.h +++ b/csync/src/csync_macros.h @@ -46,6 +46,7 @@ #define ERRNO_SERVICE_UNAVAILABLE CSYNC_CUSTOM_ERRNO_BASE+14 #define ERRNO_USER_ABORT CSYNC_CUSTOM_ERRNO_BASE+16 #define ERRNO_STORAGE_UNAVAILABLE CSYNC_CUSTOM_ERRNO_BASE+17 +#define ERRNO_FORBIDDEN CSYNC_CUSTOM_ERRNO_BASE+18 #endif /* _CSYNC_MACROS_H */ /* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */ diff --git a/csync/src/csync_update.c b/csync/src/csync_update.c index 0bda6646a..0642b4483 100644 --- a/csync/src/csync_update.c +++ b/csync/src/csync_update.c @@ -640,6 +640,20 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "asprintf failed!"); } } + // + else if(errno == ERRNO_FORBIDDEN) { + CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Directory access Forbidden (File Firewall?)"); + if (ctx->current_fs) { + ctx->current_fs->instruction = CSYNC_INSTRUCTION_IGNORE; + ctx->current_fs->error_status = CSYNC_STATUS_FORBIDDEN; + /* If a directory has ignored files, put the flag on the parent directory as well */ + if( previous_fs ) { + previous_fs->has_ignored_files = true; + } + goto done; + } + /* if current_fs is not defined here, better throw an error */ + } // The server usually replies with the custom "503 Storage not available" // if some path is temporarily unavailable. But in some cases a standard 503 // is returned too. Thus we can't distinguish the two and will treat any diff --git a/src/libsync/discoveryphase.cpp b/src/libsync/discoveryphase.cpp index 034239f6f..9c73e07f2 100644 --- a/src/libsync/discoveryphase.cpp +++ b/src/libsync/discoveryphase.cpp @@ -160,8 +160,10 @@ int get_errno_from_http_errcode( int err, const QString & reason ) { case 423: /* Locked */ new_errno = EACCES; break; - case 400: /* Bad Request */ case 403: /* Forbidden */ + new_errno = ERRNO_FORBIDDEN; + break; + case 400: /* Bad Request */ case 409: /* Conflict */ case 411: /* Length Required */ case 412: /* Precondition Failed */ diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp index 94fe02716..520b82e2c 100644 --- a/src/libsync/syncengine.cpp +++ b/src/libsync/syncengine.cpp @@ -161,6 +161,9 @@ QString SyncEngine::csyncErrorToString(CSYNC_STATUS err) case CSYNC_STATUS_STORAGE_UNAVAILABLE: errStr = tr("The mounted folder is temporarily not available on the server"); break; + case CSYNC_STATUS_FORBIDDEN: + errStr = tr("Access is forbidden"); + break; case CSYNC_STATUS_OPENDIR_ERROR: errStr = tr("An error occurred while opening a folder"); break; @@ -412,6 +415,11 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote ) item->_status = SyncFileItem::SoftError; _temporarilyUnavailablePaths.insert(item->_file); break; + case CSYNC_STATUS_FORBIDDEN: + item->_errorString = QLatin1String("Access forbidden."); + item->_status = SyncFileItem::SoftError; + _temporarilyUnavailablePaths.insert(item->_file); + break; case CSYNC_STATUS_PERMISSION_DENIED: item->_errorString = QLatin1String("Directory not accessible on client, permission denied."); item->_status = SyncFileItem::SoftError; From e7ad7d405cccbeaeb2575437dd36b204a0759568 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Mon, 12 Oct 2015 17:10:01 +0200 Subject: [PATCH 2/3] csync_update: Add missing comment about 403 forbidden handling. --- csync/src/csync_update.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/csync/src/csync_update.c b/csync/src/csync_update.c index 0642b4483..94ef28ff5 100644 --- a/csync/src/csync_update.c +++ b/csync/src/csync_update.c @@ -640,7 +640,8 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "asprintf failed!"); } } - // + // 403 Forbidden can be sent by the server if the file firewall is active. + // A file or directory should be ignored and sync must continue. See #3490 else if(errno == ERRNO_FORBIDDEN) { CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Directory access Forbidden (File Firewall?)"); if (ctx->current_fs) { From be88e5a2c30663cad80d5d27072e88a9dd9a1e25 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Wed, 18 Nov 2015 15:28:03 +0100 Subject: [PATCH 3/3] csync_update: refactor a bit and remove redundant code. --- csync/src/csync_update.c | 45 +++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/csync/src/csync_update.c b/csync/src/csync_update.c index 94ef28ff5..e7b215bbd 100644 --- a/csync/src/csync_update.c +++ b/csync/src/csync_update.c @@ -573,6 +573,26 @@ static bool fill_tree_from_db(CSYNC *ctx, const char *uri) return true; } +/* set the current item to an ignored state. + * If the item is set to ignored, the update phase continues, ie. its not a hard error */ +static bool mark_current_item_ignored( CSYNC *ctx, csync_file_stat_t *previous_fs, CSYNC_STATUS status ) +{ + if(!ctx) { + return false; + } + + if (ctx->current_fs) { + ctx->current_fs->instruction = CSYNC_INSTRUCTION_IGNORE; + ctx->current_fs->error_status = status; + /* If a directory has ignored files, put the flag on the parent directory as well */ + if( previous_fs ) { + previous_fs->has_ignored_files = true; + } + return true; + } + return false; +} + /* File tree walker */ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, unsigned int depth) { @@ -625,13 +645,8 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, /* permission denied */ ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_OPENDIR_ERROR); if (errno == EACCES) { - if (ctx->current_fs) { - ctx->current_fs->instruction = CSYNC_INSTRUCTION_IGNORE; - ctx->current_fs->error_status = CSYNC_STATUS_PERMISSION_DENIED; - /* If a directory has ignored files, put the flag on the parent directory as well */ - if( previous_fs ) { - previous_fs->has_ignored_files = true; - } + CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Permission denied."); + if (mark_current_item_ignored(ctx, previous_fs, CSYNC_STATUS_PERMISSION_DENIED)) { goto done; } } else if(errno == ENOENT) { @@ -644,13 +659,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, // A file or directory should be ignored and sync must continue. See #3490 else if(errno == ERRNO_FORBIDDEN) { CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Directory access Forbidden (File Firewall?)"); - if (ctx->current_fs) { - ctx->current_fs->instruction = CSYNC_INSTRUCTION_IGNORE; - ctx->current_fs->error_status = CSYNC_STATUS_FORBIDDEN; - /* If a directory has ignored files, put the flag on the parent directory as well */ - if( previous_fs ) { - previous_fs->has_ignored_files = true; - } + if( mark_current_item_ignored(ctx, previous_fs, CSYNC_STATUS_FORBIDDEN) ) { goto done; } /* if current_fs is not defined here, better throw an error */ @@ -661,13 +670,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, // 503 as request to ignore the folder. See #3113 #2884. else if(errno == ERRNO_STORAGE_UNAVAILABLE || errno == ERRNO_SERVICE_UNAVAILABLE) { CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Storage was not available!"); - if (ctx->current_fs) { - ctx->current_fs->instruction = CSYNC_INSTRUCTION_IGNORE; - ctx->current_fs->error_status = CSYNC_STATUS_STORAGE_UNAVAILABLE; - /* If a directory has ignored files, put the flag on the parent directory as well */ - if( previous_fs ) { - previous_fs->has_ignored_files = true; - } + if( mark_current_item_ignored(ctx, previous_fs, CSYNC_STATUS_STORAGE_UNAVAILABLE ) ) { goto done; } /* if current_fs is not defined here, better throw an error */