From: Jocelyn Turcotte Date: Tue, 5 Sep 2017 14:12:32 +0000 (+0200) Subject: Replace csync_vio_file_stat_t with csync_file_stat_t X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~701^2~132 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=7fad4748630a0fdadfb583636453ea3c89782356;p=nextcloud-desktop.git Replace csync_vio_file_stat_t with csync_file_stat_t Also move csync_normalize_etag to common/utility since we don't need the char* function anymore. Remove the single space file_stat->remotePerm codepath since this won't be used in csync anymore since 8de3bda0b1f900ab183698454740fd979f7ab9d7. Issue #1817 --- diff --git a/src/common/utility.cpp b/src/common/utility.cpp index 8bc2f2d35..f55fbea4e 100644 --- a/src/common/utility.cpp +++ b/src/common/utility.cpp @@ -380,6 +380,26 @@ QString Utility::fileNameForGuiUse(const QString &fName) return fName; } +QByteArray Utility::normalizeEtag(QByteArray etag) +{ + /* strip "XXXX-gzip" */ + if(etag.startsWith('"') && etag.endsWith("-gzip\"")) { + etag.chop(6); + etag.remove(0, 1); + } + /* strip trailing -gzip */ + if(etag.endsWith("-gzip")) { + etag.chop(5); + } + /* strip normal quotes */ + if (etag.startsWith('"') && etag.endsWith('"')) { + etag.chop(1); + etag.remove(0, 1); + } + etag.squeeze(); + return etag; +} + bool Utility::hasDarkSystray() { return hasDarkSystray_private(); diff --git a/src/common/utility.h b/src/common/utility.h index c1063a45c..d32a7bb3f 100644 --- a/src/common/utility.h +++ b/src/common/utility.h @@ -131,6 +131,8 @@ namespace Utility { OCSYNC_EXPORT QString fileNameForGuiUse(const QString &fName); + OCSYNC_EXPORT QByteArray normalizeEtag(QByteArray etag); + /** * @brief timeAgoInWords - human readable time span * diff --git a/src/csync/CMakeLists.txt b/src/csync/CMakeLists.txt index b9c772507..7ab4f7326 100644 --- a/src/csync/CMakeLists.txt +++ b/src/csync/CMakeLists.txt @@ -77,7 +77,6 @@ set(csync_SRCS csync_rename.cpp vio/csync_vio.cpp - vio/csync_vio_file_stat.cpp ) if (WIN32) diff --git a/src/csync/csync.h b/src/csync/csync.h index 4eea748ef..1cf16f937 100644 --- a/src/csync/csync.h +++ b/src/csync/csync.h @@ -39,6 +39,7 @@ #include #include #include +#include #include enum csync_status_codes_e { @@ -54,7 +55,6 @@ enum csync_status_codes_e { CSYNC_STATUS_TIMESKEW, /* OBSOLETE */ CSYNC_STATUS_FILESYSTEM_UNKNOWN, /* UNUSED */ CSYNC_STATUS_TREE_ERROR, /* csync trees could not be created */ - CSYNC_STATUS_MEMORY_ERROR, /* not enough memory problem */ CSYNC_STATUS_PARAM_ERROR, /* parameter is zero where not expected */ CSYNC_STATUS_UPDATE_ERROR, /* general update or discovery error */ CSYNC_STATUS_RECONCILE_ERROR, /* general reconcile error */ @@ -150,82 +150,6 @@ enum csync_ftw_type_e { // currently specified at https://github.com/owncloud/core/issues/8322 are 9 to 10 #define REMOTE_PERM_BUF_SIZE 15 -typedef struct csync_vio_file_stat_s csync_vio_file_stat_t; - -enum csync_vio_file_flags_e { - CSYNC_VIO_FILE_FLAGS_NONE = 0, - CSYNC_VIO_FILE_FLAGS_SYMLINK = 1 << 0, - CSYNC_VIO_FILE_FLAGS_HIDDEN = 1 << 1 -}; - -enum csync_vio_file_type_e { - CSYNC_VIO_FILE_TYPE_UNKNOWN, - CSYNC_VIO_FILE_TYPE_REGULAR, - CSYNC_VIO_FILE_TYPE_DIRECTORY, - CSYNC_VIO_FILE_TYPE_FIFO, - CSYNC_VIO_FILE_TYPE_SOCKET, - CSYNC_VIO_FILE_TYPE_CHARACTER_DEVICE, - CSYNC_VIO_FILE_TYPE_BLOCK_DEVICE, - CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK -}; - -enum csync_vio_file_stat_fields_e { - CSYNC_VIO_FILE_STAT_FIELDS_NONE = 0, - CSYNC_VIO_FILE_STAT_FIELDS_TYPE = 1 << 0, - CSYNC_VIO_FILE_STAT_FIELDS_MODE = 1 << 1, // local POSIX mode - CSYNC_VIO_FILE_STAT_FIELDS_FLAGS = 1 << 2, -// CSYNC_VIO_FILE_STAT_FIELDS_DEVICE = 1 << 3, - CSYNC_VIO_FILE_STAT_FIELDS_INODE = 1 << 4, -// CSYNC_VIO_FILE_STAT_FIELDS_LINK_COUNT = 1 << 5, - CSYNC_VIO_FILE_STAT_FIELDS_SIZE = 1 << 6, -// CSYNC_VIO_FILE_STAT_FIELDS_BLOCK_COUNT = 1 << 7, /* will be removed */ -// CSYNC_VIO_FILE_STAT_FIELDS_BLOCK_SIZE = 1 << 8, /* will be removed */ - CSYNC_VIO_FILE_STAT_FIELDS_ATIME = 1 << 9, - CSYNC_VIO_FILE_STAT_FIELDS_MTIME = 1 << 10, - CSYNC_VIO_FILE_STAT_FIELDS_CTIME = 1 << 11, -// CSYNC_VIO_FILE_STAT_FIELDS_SYMLINK_NAME = 1 << 12, -// CSYNC_VIO_FILE_STAT_FIELDS_CHECKSUM = 1 << 13, -// CSYNC_VIO_FILE_STAT_FIELDS_ACL = 1 << 14, -// CSYNC_VIO_FILE_STAT_FIELDS_UID = 1 << 15, -// CSYNC_VIO_FILE_STAT_FIELDS_GID = 1 << 16, - CSYNC_VIO_FILE_STAT_FIELDS_ETAG = 1 << 17, - CSYNC_VIO_FILE_STAT_FIELDS_FILE_ID = 1 << 18, - CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADURL = 1 << 19, - CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADCOOKIES = 1 << 20, - CSYNC_VIO_FILE_STAT_FIELDS_PERM = 1 << 21 // remote oC perm - -}; - - -struct csync_vio_file_stat_s { - char *name; - char *etag; // FIXME: Should this be inlined like file_id and perm? - char file_id[FILE_ID_BUF_SIZE+1]; - char *directDownloadUrl; - char *directDownloadCookies; - char remotePerm[REMOTE_PERM_BUF_SIZE+1]; - - time_t atime; - time_t mtime; - time_t ctime; - int64_t size; - - mode_t mode; - - uint64_t inode; - - int fields; // actually enum csync_vio_file_stat_fields_e fields; - enum csync_vio_file_type_e type; - - int flags; - - char *original_name; // only set if locale conversion fails - - // For remote file stats: the highest quality checksum the server provided - // in the "SHA1:324315da2143" form. - char *checksumHeader; -}; - typedef struct csync_file_stat_s csync_file_stat_t; struct csync_file_stat_s { @@ -236,6 +160,7 @@ struct csync_file_stat_s { enum csync_ftw_type_e type : 4; bool child_modified : 1; bool has_ignored_files : 1; /* specify that a directory, or child directory contains ignored files */ + bool is_hidden : 1; // Not saved in the DB, only used during discovery for local files. QByteArray path; QByteArray rename_path; @@ -244,6 +169,7 @@ struct csync_file_stat_s { QByteArray directDownloadUrl; QByteArray directDownloadCookies; QByteArray remotePerm; + QByteArray original_path; // only set if locale conversion fails // In the local tree, this can hold a checksum and its type if it is // computed during discovery for some reason. @@ -263,21 +189,12 @@ struct csync_file_stat_s { , type(CSYNC_FTW_TYPE_SKIP) , child_modified(false) , has_ignored_files(false) + , is_hidden(false) , error_status(CSYNC_STATUS_OK) , instruction(CSYNC_INSTRUCTION_NONE) { } }; -csync_vio_file_stat_t OCSYNC_EXPORT *csync_vio_file_stat_new(void); -csync_vio_file_stat_t OCSYNC_EXPORT *csync_vio_file_stat_copy(csync_vio_file_stat_t *file_stat); - -void OCSYNC_EXPORT csync_vio_file_stat_destroy(csync_vio_file_stat_t *fstat); - -void OCSYNC_EXPORT csync_vio_file_stat_set_file_id( csync_vio_file_stat_t* dst, const char* src ); - -void OCSYNC_EXPORT csync_vio_set_file_id(char* dst, const char *src ); - - /** * CSync File Traversal structure. * @@ -338,7 +255,7 @@ typedef void (*csync_update_callback) (bool local, typedef void csync_vio_handle_t; typedef csync_vio_handle_t* (*csync_vio_opendir_hook) (const char *url, void *userdata); -typedef csync_vio_file_stat_t* (*csync_vio_readdir_hook) (csync_vio_handle_t *dhhandle, +typedef std::unique_ptr (*csync_vio_readdir_hook) (csync_vio_handle_t *dhhandle, void *userdata); typedef void (*csync_vio_closedir_hook) (csync_vio_handle_t *dhhandle, void *userdata); @@ -539,7 +456,6 @@ void OCSYNC_EXPORT csync_resume(CSYNC *ctx); */ int OCSYNC_EXPORT csync_abort_requested(CSYNC *ctx); -char OCSYNC_EXPORT *csync_normalize_etag(const char *); time_t OCSYNC_EXPORT oc_httpdate_parse( const char *date ); /** diff --git a/src/csync/csync_exclude.cpp b/src/csync/csync_exclude.cpp index 9ab187e71..7517ee218 100644 --- a/src/csync/csync_exclude.cpp +++ b/src/csync/csync_exclude.cpp @@ -31,6 +31,7 @@ #include "c_lib.h" #include "c_private.h" +#include "c_utf8.h" #include "csync_private.h" #include "csync_exclude.h" diff --git a/src/csync/csync_misc.cpp b/src/csync/csync_misc.cpp index cf719439f..bb8e98c8a 100644 --- a/src/csync/csync_misc.cpp +++ b/src/csync/csync_misc.cpp @@ -170,37 +170,3 @@ CSYNC_STATUS csync_errno_to_status(int error, CSYNC_STATUS default_status) return status; } - -/* Remove possible quotes, and also the -gzip at the end - * Remove "-gzip" at the end (cf. https://github.comowncloud/client/issues/1195) - * The caller must take ownership of the resulting string. - */ -char *csync_normalize_etag(const char *etag) -{ - int len = 0; - char *buf = NULL; - if (!etag) - return NULL; - - len = strlen(etag); - /* strip "XXXX-gzip" */ - if(len >= 7 && etag[0] == '"' && c_streq(etag + len - 6, "-gzip\"")) { - etag++; - len -= 7; - } - /* strip leading -gzip */ - if(len >= 5 && c_streq(etag + len - 5, "-gzip")) { - len -= 5; - } - /* strip normal quotes */ - if (etag[0] == '"' && etag[len-1] == '"') { - etag++; - len -= 2; - } - - buf = (char*)c_malloc( len+1 ); - strncpy( buf, etag, len ); - buf[len] = '\0'; - return buf; -} - diff --git a/src/csync/csync_statedb.cpp b/src/csync/csync_statedb.cpp index 4c4eb9828..523767dc4 100644 --- a/src/csync/csync_statedb.cpp +++ b/src/csync/csync_statedb.cpp @@ -42,6 +42,7 @@ #include "c_string.h" #include "c_jhash.h" +#include "c_utf8.h" #include "csync_time.h" #define CSYNC_LOG_CATEGORY_NAME "csync.statedb" diff --git a/src/csync/csync_update.cpp b/src/csync/csync_update.cpp index e62e3be29..fab7acd4a 100644 --- a/src/csync/csync_update.cpp +++ b/src/csync/csync_update.cpp @@ -96,43 +96,6 @@ static bool _last_db_return_error(CSYNC* ctx) { return ctx->statedb.lastReturnValue != SQLITE_OK && ctx->statedb.lastReturnValue != SQLITE_DONE && ctx->statedb.lastReturnValue != SQLITE_ROW; } -/* - * This static method is needed because the type members of the two structs use - * different enum values. A direct comparion is not neccessarily correct. - * - * tmp is csync_file_stat_t - * fs is csync_vio_file_stat_t with this vio type: - * enum csync_vio_file_type_e { - * CSYNC_VIO_FILE_TYPE_UNKNOWN, - * CSYNC_VIO_FILE_TYPE_REGULAR, - * CSYNC_VIO_FILE_TYPE_DIRECTORY, - * CSYNC_VIO_FILE_TYPE_FIFO, - * CSYNC_VIO_FILE_TYPE_SOCKET, - * CSYNC_VIO_FILE_TYPE_CHARACTER_DEVICE, - * CSYNC_VIO_FILE_TYPE_BLOCK_DEVICE, - * CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK - * }; - * - * csync_file_stat_t can be: - * CSYNC_FTW_TYPE_SKIP, CSYNC_FTW_TYPE_FILE - * CSYNC_FTW_TYPE_DIR, CSYNC_FTW_TYPE_SLINK - */ -static bool _csync_filetype_different( const csync_file_stat_t *tmp, const csync_vio_file_stat_t *fs) -{ - if( !(tmp && fs)) return false; - - if( tmp->type == CSYNC_FTW_TYPE_SKIP ) return true; - - if( tmp->type == CSYNC_FTW_TYPE_DIR && fs->type != CSYNC_VIO_FILE_TYPE_DIRECTORY ) - return true; - if( tmp->type == CSYNC_FTW_TYPE_FILE && fs->type != CSYNC_VIO_FILE_TYPE_REGULAR ) - return true; - if( tmp->type == CSYNC_FTW_TYPE_SLINK && fs->type != CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK ) - return true; - - return false; // both are NOT different. -} - /* Return true if two mtime are considered equal * We consider mtime that are one hour difference to be equal if they are one hour appart * because on some system (FAT) the date is changing when the daylight saving is changing */ @@ -162,7 +125,7 @@ static bool _csync_mtime_equal(time_t a, time_t b) * See doc/dev/sync-algorithm.md for an overview. */ static int _csync_detect_update(CSYNC *ctx, const char *file, - const csync_vio_file_stat_t *fs, enum csync_ftw_type_e type) { + const csync_file_stat_t *fs, enum csync_ftw_type_e type) { uint64_t h = 0; const char *path = NULL; std::unique_ptr st; @@ -196,7 +159,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file, * because it's a hidden file that should not be synced. * This code should probably be in csync_exclude, but it does not have the fs parameter. * Keep it here for now */ - if (ctx->ignore_hidden_files && (fs->flags & CSYNC_VIO_FILE_FLAGS_HIDDEN)) { + if (ctx->ignore_hidden_files && (fs->is_hidden)) { CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file excluded because it is a hidden file: %s", path); excluded = CSYNC_FILE_EXCLUDE_HIDDEN; } @@ -225,7 +188,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file, st.reset(new csync_file_stat_t); if (type == CSYNC_FTW_TYPE_FILE ) { - if (fs->mtime == 0) { + if (fs->modtime == 0) { CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s - mtime is zero!", path); } } @@ -257,21 +220,21 @@ static int _csync_detect_update(CSYNC *ctx, const char *file, CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "Database entry found, compare: %" PRId64 " <-> %" PRId64 ", etag: %s <-> %s, inode: %" PRId64 " <-> %" PRId64 ", size: %" PRId64 " <-> %" PRId64 ", perms: %s <-> %s, ignore: %d", - ((int64_t) fs->mtime), ((int64_t) tmp->modtime), - fs->etag, tmp->etag.constData(), (uint64_t) fs->inode, (uint64_t) tmp->inode, - (uint64_t) fs->size, (uint64_t) tmp->size, fs->remotePerm, tmp->remotePerm.constData(), tmp->has_ignored_files ); - if (ctx->current == REMOTE_REPLICA && !c_streq(fs->etag, tmp->etag)) { + ((int64_t) fs->modtime), ((int64_t) tmp->modtime), + fs->etag.constData(), tmp->etag.constData(), (uint64_t) fs->inode, (uint64_t) tmp->inode, + (uint64_t) fs->size, (uint64_t) tmp->size, fs->remotePerm.constData(), tmp->remotePerm.constData(), tmp->has_ignored_files ); + if (ctx->current == REMOTE_REPLICA && fs->etag != tmp->etag) { st->instruction = CSYNC_INSTRUCTION_EVAL; // Preserve the EVAL flag later on if the type has changed. - if (_csync_filetype_different(tmp.get(), fs)) { + if (tmp->type != fs->type) { st->child_modified = true; } goto out; } if (ctx->current == LOCAL_REPLICA && - (!_csync_mtime_equal(fs->mtime, tmp->modtime) + (!_csync_mtime_equal(fs->modtime, tmp->modtime) // zero size in statedb can happen during migration || (tmp->size != 0 && fs->size != tmp->size))) { @@ -296,15 +259,15 @@ static int _csync_detect_update(CSYNC *ctx, const char *file, } // Preserve the EVAL flag later on if the type has changed. - if (_csync_filetype_different(tmp.get(), fs)) { + if (tmp->type != fs->type) { st->child_modified = true; } st->instruction = CSYNC_INSTRUCTION_EVAL; goto out; } - bool metadata_differ = (ctx->current == REMOTE_REPLICA && (!c_streq(fs->file_id, tmp->file_id) - || !c_streq(fs->remotePerm, tmp->remotePerm))) + bool metadata_differ = (ctx->current == REMOTE_REPLICA && (fs->file_id != tmp->file_id + || fs->remotePerm != tmp->remotePerm)) || (ctx->current == LOCAL_REPLICA && fs->inode != tmp->inode); if (type == CSYNC_FTW_TYPE_DIR && ctx->current == REMOTE_REPLICA && !metadata_differ && ctx->read_remote_from_db) { @@ -330,8 +293,6 @@ static int _csync_detect_update(CSYNC *ctx, const char *file, st->instruction = CSYNC_INSTRUCTION_NONE; } } else { - enum csync_vio_file_type_e tmp_vio_type = CSYNC_VIO_FILE_TYPE_UNKNOWN; - /* check if it's a file and has been renamed */ if (ctx->current == LOCAL_REPLICA) { CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Checking for rename based on inode # %" PRId64 "", (uint64_t) fs->inode); @@ -343,23 +304,12 @@ static int _csync_detect_update(CSYNC *ctx, const char *file, return -1; } - /* translate the file type between the two stat types csync has. */ - if( tmp && tmp->type == CSYNC_FTW_TYPE_FILE ) { - tmp_vio_type = CSYNC_VIO_FILE_TYPE_REGULAR; - } else if( tmp && tmp->type == CSYNC_FTW_TYPE_DIR) { - tmp_vio_type = CSYNC_VIO_FILE_TYPE_DIRECTORY; - } else if( tmp && tmp->type == CSYNC_FTW_TYPE_SLINK ) { - tmp_vio_type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK; - } else { - tmp_vio_type = CSYNC_VIO_FILE_TYPE_UNKNOWN; - } - // Default to NEW unless we're sure it's a rename. st->instruction = CSYNC_INSTRUCTION_NEW; bool isRename = - tmp && tmp->inode == fs->inode && tmp_vio_type == fs->type - && (tmp->modtime == fs->mtime || fs->type == CSYNC_VIO_FILE_TYPE_DIRECTORY) + tmp && tmp->inode == fs->inode && tmp->type == fs->type + && (tmp->modtime == fs->modtime || fs->type == CSYNC_FTW_TYPE_DIR) #ifdef NO_RENAME_EXTENSION && _csync_sameextension(tmp->path, path) #endif @@ -368,7 +318,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file, // Verify the checksum where possible if (isRename && !tmp->checksumHeader.isEmpty() && ctx->callbacks.checksum_hook - && fs->type == CSYNC_VIO_FILE_TYPE_REGULAR) { + && fs->type == CSYNC_FTW_TYPE_FILE) { st->checksumHeader = ctx->callbacks.checksum_hook( file, tmp->checksumHeader, ctx->callbacks.checksum_userdata); @@ -382,7 +332,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file, CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "pot rename detected based on inode # %" PRId64 "", (uint64_t) fs->inode); /* inode found so the file has been renamed */ st->instruction = CSYNC_INSTRUCTION_EVAL_RENAME; - if (fs->type == CSYNC_VIO_FILE_TYPE_DIRECTORY) { + if (fs->type == CSYNC_FTW_TYPE_DIR) { csync_rename_record(ctx, tmp->path, path); } } @@ -397,17 +347,17 @@ static int _csync_detect_update(CSYNC *ctx, const char *file, return -1; } if(tmp ) { /* tmp existing at all */ - if ( _csync_filetype_different(tmp.get(), fs)) { + if (tmp->type != fs->type) { CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "file types different is not!"); st->instruction = CSYNC_INSTRUCTION_NEW; goto out; } CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "remote rename detected based on fileid %s %s", tmp->path.constData(), file); st->instruction = CSYNC_INSTRUCTION_EVAL_RENAME; - if (fs->type == CSYNC_VIO_FILE_TYPE_DIRECTORY) { + if (fs->type == CSYNC_FTW_TYPE_DIR) { csync_rename_record(ctx, tmp->path, path); } else { - if( !c_streq(tmp->etag, fs->etag) ) { + if( tmp->etag != fs->etag ) { /* CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "ETags are different!"); */ /* File with different etag, don't do a rename, but download the file again */ st->instruction = CSYNC_INSTRUCTION_NEW; @@ -419,7 +369,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file, /* file not found in statedb */ st->instruction = CSYNC_INSTRUCTION_NEW; - if (fs->type == CSYNC_VIO_FILE_TYPE_DIRECTORY && ctx->current == REMOTE_REPLICA && ctx->callbacks.checkSelectiveSyncNewFolderHook) { + if (fs->type == CSYNC_FTW_TYPE_DIR && ctx->current == REMOTE_REPLICA && ctx->callbacks.checkSelectiveSyncNewFolderHook) { if (ctx->callbacks.checkSelectiveSyncNewFolderHook(ctx->callbacks.update_callback_userdata, path, fs->remotePerm)) { return 1; } @@ -468,25 +418,17 @@ out: st->inode = fs->inode; st->size = fs->size; - st->modtime = fs->mtime; + st->modtime = fs->modtime; st->type = type; - st->etag = NULL; - if( fs->etag ) { - st->etag = fs->etag; - } + st->is_hidden = fs->is_hidden; + st->etag = fs->etag; st->file_id = fs->file_id; - if (fs->fields & CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADURL) { - st->directDownloadUrl = fs->directDownloadUrl; - } - if (fs->fields & CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADCOOKIES) { - st->directDownloadCookies = fs->directDownloadCookies; - } - if (fs->fields & CSYNC_VIO_FILE_STAT_FIELDS_PERM) { - st->remotePerm = fs->remotePerm; - } + st->directDownloadUrl = fs->directDownloadUrl; + st->directDownloadCookies = fs->directDownloadCookies; + st->remotePerm = fs->remotePerm; // For the remote: propagate the discovered checksum - if (fs->checksumHeader && ctx->current == REMOTE_REPLICA) { + if (ctx->current == REMOTE_REPLICA) { st->checksumHeader = fs->checksumHeader; } @@ -516,7 +458,7 @@ out: return 0; } -int csync_walker(CSYNC *ctx, const char *file, const csync_vio_file_stat_t *fs, +int csync_walker(CSYNC *ctx, const char *file, const csync_file_stat_t *fs, int flag) { int rc = -1; enum csync_ftw_type_e type = CSYNC_FTW_TYPE_SKIP; @@ -532,11 +474,7 @@ int csync_walker(CSYNC *ctx, const char *file, const csync_vio_file_stat_t *fs, switch (flag) { case CSYNC_FTW_FLAG_FILE: if (ctx->current == REMOTE_REPLICA) { - if (fs->fields & CSYNC_VIO_FILE_STAT_FIELDS_SIZE) { - CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [file_id=%s size=%" PRIu64 "]", file, fs->file_id, fs->size); - } else { - CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [file_id=%s size=UNKNOWN]", file, fs->file_id); - } + CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [file_id=%s size=%" PRIu64 "]", file, fs->file_id.constData(), fs->size); } else { CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [inode=%" PRIu64 " size=%" PRIu64 "]", file, fs->inode, fs->size); } @@ -544,7 +482,7 @@ int csync_walker(CSYNC *ctx, const char *file, const csync_vio_file_stat_t *fs, break; case CSYNC_FTW_FLAG_DIR: /* enter directory */ if (ctx->current == REMOTE_REPLICA) { - CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "directory: %s [file_id=%s]", file, fs->file_id); + CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "directory: %s [file_id=%s]", file, fs->file_id.constData()); } else { CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "directory: %s [inode=%" PRIu64 "]", file, fs->inode); } @@ -615,10 +553,10 @@ static bool mark_current_item_ignored( CSYNC *ctx, csync_file_stat_t *previous_f /* File tree walker */ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, unsigned int depth) { - char *filename = NULL; - char *d_name = NULL; + QByteArray filename; + QByteArray d_name; csync_vio_handle_t *dh = NULL; - csync_vio_file_stat_t *dirent = NULL; + std::unique_ptr dirent; csync_file_stat_t *previous_fs = NULL; int read_from_db = 0; int rc = 0; @@ -628,7 +566,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, if (!depth) { mark_current_item_ignored(ctx, previous_fs, CSYNC_STATUS_INDIVIDUAL_TOO_DEEP); - goto done; + return 0; } read_from_db = ctx->remote.read_from_db; @@ -641,7 +579,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, ctx->status_code = CSYNC_STATUS_OPENDIR_ERROR; goto error; } - goto done; + return 0; } if ((dh = csync_vio_opendir(ctx, uri)) == NULL) { @@ -656,7 +594,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, if (errno == EACCES) { CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Permission denied."); if (mark_current_item_ignored(ctx, previous_fs, CSYNC_STATUS_PERMISSION_DENIED)) { - goto done; + return 0; } } else if(errno == ENOENT) { asp = asprintf( &ctx->error_string, "%s", uri); @@ -669,7 +607,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, else if(errno == ERRNO_FORBIDDEN) { CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Directory access Forbidden (File Firewall?)"); if( mark_current_item_ignored(ctx, previous_fs, CSYNC_STATUS_FORBIDDEN) ) { - goto done; + return 0; } /* if current_fs is not defined here, better throw an error */ } @@ -680,7 +618,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, else if(errno == ERRNO_STORAGE_UNAVAILABLE || errno == ERRNO_SERVICE_UNAVAILABLE) { CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Storage was not available!"); if( mark_current_item_ignored(ctx, previous_fs, CSYNC_STATUS_STORAGE_UNAVAILABLE ) ) { - goto done; + return 0; } /* if current_fs is not defined here, better throw an error */ } else { @@ -690,47 +628,40 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, } while ((dirent = csync_vio_readdir(ctx, dh))) { - int flen; int flag; /* Conversion error */ - if (dirent->name == NULL && dirent->original_name) { + if (dirent->path.isEmpty() && !dirent->original_path.isEmpty()) { ctx->status_code = CSYNC_STATUS_INVALID_CHARACTERS; - ctx->error_string = dirent->original_name; // take ownership - dirent->original_name = NULL; + ctx->error_string = c_strdup(dirent->original_path); + dirent->original_path.clear(); goto error; } - d_name = dirent->name; - if (d_name == NULL) { + d_name = dirent->path; + if (d_name.isEmpty()) { ctx->status_code = CSYNC_STATUS_READDIR_ERROR; goto error; } /* skip "." and ".." */ - if ( (d_name[0] == '.' && d_name[1] == '\0') - || (d_name[0] == '.' && d_name[1] == '.' && d_name[2] == '\0')) { - csync_vio_file_stat_destroy(dirent); - dirent = NULL; + if ( d_name == "." || d_name == "..") { + dirent.reset(); continue; } if (uri[0] == '\0') { - filename = c_strdup(d_name); - flen = strlen(d_name); + filename = d_name; } else { - flen = asprintf(&filename, "%s/%s", uri, d_name); - } - if (flen < 0 || !filename) { - csync_vio_file_stat_destroy(dirent); - dirent = NULL; - ctx->status_code = CSYNC_STATUS_MEMORY_ERROR; - goto error; + /* For the local replica, dirent->path only contains the file name */ + filename = uri; + filename += '/'; + filename += d_name; } /* Only for the local replica we have to stat(), for the remote one we have all data already */ if (ctx->replica == LOCAL_REPLICA) { - res = csync_vio_stat(ctx, filename, dirent); + res = csync_vio_stat(ctx, filename, dirent.get()); } else { res = 0; } @@ -740,39 +671,32 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, * local stat function. */ if( d_name[0] == '.' ) { - if (strcmp(".sys.admin#recall#", d_name) != 0) { /* recall file shall not be ignored (#4420) */ - dirent->flags |= CSYNC_VIO_FILE_FLAGS_HIDDEN; + if (d_name == ".sys.admin#recall#") { /* recall file shall not be ignored (#4420) */ + dirent->is_hidden = true; } } + flag = CSYNC_FTW_FLAG_NSTAT; if( res == 0) { switch (dirent->type) { - case CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK: + case CSYNC_FTW_TYPE_SLINK: flag = CSYNC_FTW_FLAG_SLINK; break; - case CSYNC_VIO_FILE_TYPE_DIRECTORY: + case CSYNC_FTW_TYPE_DIR: flag = CSYNC_FTW_FLAG_DIR; break; - case CSYNC_VIO_FILE_TYPE_BLOCK_DEVICE: - case CSYNC_VIO_FILE_TYPE_CHARACTER_DEVICE: - case CSYNC_VIO_FILE_TYPE_SOCKET: - flag = CSYNC_FTW_FLAG_SPEC; - break; - case CSYNC_VIO_FILE_TYPE_FIFO: - flag = CSYNC_FTW_FLAG_SPEC; + case CSYNC_FTW_TYPE_FILE: + flag = CSYNC_FTW_FLAG_FILE; break; default: - flag = CSYNC_FTW_FLAG_FILE; break; }; - } else { - flag = CSYNC_FTW_FLAG_NSTAT; } previous_fs = ctx->current_fs; /* Call walker function for each file */ - rc = fn(ctx, filename, dirent, flag); + rc = fn(ctx, filename, dirent.get(), flag); /* this function may update ctx->current and ctx->read_from_db */ if (rc < 0) { @@ -814,24 +738,19 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, ctx->current_fs = previous_fs; ctx->remote.read_from_db = read_from_db; - SAFE_FREE(filename); - csync_vio_file_stat_destroy(dirent); - dirent = NULL; + dirent.reset(); } csync_vio_closedir(ctx, dh); CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, " <= Closing walk for %s with read_from_db %d", uri, read_from_db); -done: - csync_vio_file_stat_destroy(dirent); - SAFE_FREE(filename); return rc; + error: ctx->remote.read_from_db = read_from_db; if (dh != NULL) { csync_vio_closedir(ctx, dh); } - SAFE_FREE(filename); return -1; } diff --git a/src/csync/csync_update.h b/src/csync/csync_update.h index d83ee91e8..b1de56dee 100644 --- a/src/csync/csync_update.h +++ b/src/csync/csync_update.h @@ -46,14 +46,13 @@ enum csync_ftw_flags_e { CSYNC_FTW_FLAG_DNR, /* Unreadable directory. */ CSYNC_FTW_FLAG_NSTAT, /* Unstatable file. */ CSYNC_FTW_FLAG_SLINK, /* Symbolic link. */ - CSYNC_FTW_FLAG_SPEC, /* Special file (fifo, ...). */ /* These flags are only passed from the `nftw' function. */ CSYNC_FTW_FLAG_DP, /* Directory, all subdirs have been visited. */ CSYNC_FTW_FLAG_SLN /* Symbolic link naming non-existing file. */ }; typedef int (*csync_walker_fn) (CSYNC *ctx, const char *file, - const csync_vio_file_stat_t *fs, int flag); + const csync_file_stat_t *fs, int flag); /** * @brief The walker function to use in the file tree walker. @@ -68,7 +67,7 @@ typedef int (*csync_walker_fn) (CSYNC *ctx, const char *file, * * @return 0 on success, < 0 on error. */ -int csync_walker(CSYNC *ctx, const char *file, const csync_vio_file_stat_t *fs, int flag); +int csync_walker(CSYNC *ctx, const char *file, const csync_file_stat_t *fs, int flag); /** * @brief The file tree walker. diff --git a/src/csync/std/c_path.c b/src/csync/std/c_path.c index 1094a1c67..497ce411e 100644 --- a/src/csync/std/c_path.c +++ b/src/csync/std/c_path.c @@ -33,6 +33,7 @@ #include "c_alloc.h" #include "c_path.h" #include "c_string.h" +#include "c_utf8.h" /* * dirname - parse directory component. diff --git a/src/csync/std/c_string.h b/src/csync/std/c_string.h index 4d7d9b599..ef1784892 100644 --- a/src/csync/std/c_string.h +++ b/src/csync/std/c_string.h @@ -147,77 +147,6 @@ void c_strlist_clear(c_strlist_t *strlist); */ void c_strlist_destroy(c_strlist_t *strlist); -/** - * @brief Convert a platform locale string to utf8. - * - * This function is part of the multi platform abstraction of basic file - * operations to handle various platform encoding correctly. - * - * Instead of using the standard file operations the multi platform aliases - * defined in c_private.h have to be used instead. - * - * To convert path names returned by these functions to the internally used - * utf8 format this function has to be used. The returned string has to - * be freed by c_free_locale_string(). On some platforms this method allocates - * memory and on others not but it has never to be cared about. - * - * @param str The multibyte encoded string to convert - * - * @return The malloced converted string or NULL on error. - * - * @see c_free_locale_string() - * @see c_utf8_to_locale() - * - */ - char* c_utf8_from_locale(const mbchar_t *str); - -/** - * @brief Convert a utf8 encoded string to platform specific locale. - * - * This function is part of the multi platform abstraction of basic file - * operations to handle various platform encoding correctly. - * - * Instead of using the standard file operations the multi platform aliases - * defined in c_private.h have to be used instead. - * - * To convert strings as input for the cross platform functions from the - * internally used utf8 format, this function has to be used. - * The returned string has to be freed by c_free_locale_string(). On some - * platforms this method allocates memory and on others not but it has never - * sto be cared about. - * - * If the string to convert is a path, consider using c_utf8_path_to_locale(). - * - * @param str The utf8 string to convert. - * - * @return The malloced converted multibyte string or NULL on error. - * - * @see c_free_locale_string() - * @see c_utf8_from_locale() - * - */ -mbchar_t* c_utf8_string_to_locale(const char *wstr); - -/** - * @brief Free buffer malloced by c_utf8_from_locale or c_utf8_to_locale(). - * - * This function is part of the multi platform abstraction of basic file - * operations to handle various platform encoding correctly. - * - * Instead of using the standard file operations the multi platform aliases - * defined in c_private.h have to be used instead. - * - * This function frees the memory that was allocated by a previous call to - * c_utf8_to_locale() or c_utf8_from_locale(). - * - * @param buf The buffer to free. - * - * @see c_utf8_from_locale(), c_utf8_to_locale() - * - */ -#define c_free_locale_string(x) SAFE_FREE(x) - - /** * }@ */ diff --git a/src/csync/std/c_time.c b/src/csync/std/c_time.c index 561cd4763..4bcdcbf56 100644 --- a/src/csync/std/c_time.c +++ b/src/csync/std/c_time.c @@ -24,6 +24,7 @@ #include "c_path.h" #include "c_time.h" +#include "c_utf8.h" struct timespec c_tspecdiff(struct timespec time1, struct timespec time0) { struct timespec ret; diff --git a/src/csync/std/c_utf8.cpp b/src/csync/std/c_utf8.cpp index 4bd5d75ac..ae61170a9 100644 --- a/src/csync/std/c_utf8.cpp +++ b/src/csync/std/c_utf8.cpp @@ -20,6 +20,7 @@ */ #include "config_csync.h" +#include "c_utf8.h" #ifdef _WIN32 #include @@ -34,31 +35,26 @@ #include #endif -extern "C" { #include "c_alloc.h" #include "c_string.h" /* Convert a locale String to UTF8 */ -char* c_utf8_from_locale(const mbchar_t *wstr) +QByteArray c_utf8_from_locale(const mbchar_t *wstr) { if (wstr == NULL) { - return NULL; + return QByteArray(); } #ifdef _WIN32 - char *dst = NULL; - char *mdst = NULL; + QByteArray dst; int size_needed; size_t len; len = wcslen(wstr); /* Call once to get the required size. */ size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr, len, NULL, 0, NULL, NULL); if (size_needed > 0) { - mdst = (char*)c_malloc(size_needed + 1); - - memset(mdst, 0, size_needed + 1); - WideCharToMultiByte(CP_UTF8, 0, wstr, len, mdst, size_needed, NULL, NULL); - dst = mdst; + dst.resize(size_needed); + WideCharToMultiByte(CP_UTF8, 0, wstr, len, dst.data(), size_needed, NULL, NULL); } return dst; #else @@ -67,15 +63,17 @@ char* c_utf8_from_locale(const mbchar_t *wstr) if (s.isEmpty() || dec.hasFailure()) { /* Conversion error: since we can't report error from this function, just return the original string. We take care of invalid utf-8 in SyncEngine::treewalkFile */ - return c_strdup(wstr); + return QByteArray(wstr); } #ifdef __APPLE__ s = s.normalized(QString::NormalizationForm_C); #endif - return c_strdup(std::move(s).toUtf8().constData()); + return std::move(s).toUtf8(); #endif } +extern "C" { + /* Convert a an UTF8 string to locale */ mbchar_t* c_utf8_string_to_locale(const char *str) { diff --git a/src/csync/std/c_utf8.h b/src/csync/std/c_utf8.h new file mode 100644 index 000000000..522cab34d --- /dev/null +++ b/src/csync/std/c_utf8.h @@ -0,0 +1,122 @@ +/* + * cynapses libc functions + * + * Copyright (c) 2008-2013 by Andreas Schneider + * Copyright (c) 2012-2013 by Klaas Freitag + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file c_string.h + * + * @brief Interface of the cynapses string implementations + * + * @defgroup cynStringInternals cynapses libc string functions + * @ingroup cynLibraryAPI + * + * @{ + */ +#ifndef _C_UTF8_H +#define _C_UTF8_H + +#include "c_private.h" +#include "c_macro.h" + +#ifdef __cplusplus +#include + +/** + * @brief Convert a platform locale string to utf8. + * + * This function is part of the multi platform abstraction of basic file + * operations to handle various platform encoding correctly. + * + * Instead of using the standard file operations the multi platform aliases + * defined in c_private.h have to be used instead. + * + * To convert path names returned by these functions to the internally used + * utf8 format this function has to be used. + * + * @param str The multibyte encoded string to convert + * + * @return The converted string or a null QByteArray on error. + * + * @see c_free_locale_string() + * @see c_utf8_to_locale() + * + */ + QByteArray c_utf8_from_locale(const mbchar_t *str); + +extern "C" { + +#endif // __cplusplus + +/** + * @brief Convert a utf8 encoded string to platform specific locale. + * + * This function is part of the multi platform abstraction of basic file + * operations to handle various platform encoding correctly. + * + * Instead of using the standard file operations the multi platform aliases + * defined in c_private.h have to be used instead. + * + * To convert strings as input for the cross platform functions from the + * internally used utf8 format, this function has to be used. + * The returned string has to be freed by c_free_locale_string(). On some + * platforms this method allocates memory and on others not but it has never + * sto be cared about. + * + * If the string to convert is a path, consider using c_utf8_path_to_locale(). + * + * @param str The utf8 string to convert. + * + * @return The malloced converted multibyte string or NULL on error. + * + * @see c_free_locale_string() + * @see c_utf8_from_locale() + * + */ +mbchar_t* c_utf8_string_to_locale(const char *wstr); + +/** + * @brief Free buffer malloced by c_utf8_to_locale(). + * + * This function is part of the multi platform abstraction of basic file + * operations to handle various platform encoding correctly. + * + * Instead of using the standard file operations the multi platform aliases + * defined in c_private.h have to be used instead. + * + * This function frees the memory that was allocated by a previous call to + * c_utf8_to_locale(). + * + * @param buf The buffer to free. + * + * @see c_utf8_from_locale(), c_utf8_to_locale() + * + */ +#define c_free_locale_string(x) SAFE_FREE(x) + + +/** + * }@ + */ + +#ifdef __cplusplus +} +#endif + +#endif /* _C_UTF8_H */ diff --git a/src/csync/vio/csync_vio.cpp b/src/csync/vio/csync_vio.cpp index 909117836..cea6b04e1 100644 --- a/src/csync/vio/csync_vio.cpp +++ b/src/csync/vio/csync_vio.cpp @@ -84,7 +84,7 @@ int csync_vio_closedir(CSYNC *ctx, csync_vio_handle_t *dhandle) { return rc; } -csync_vio_file_stat_t *csync_vio_readdir(CSYNC *ctx, csync_vio_handle_t *dhandle) { +std::unique_ptr csync_vio_readdir(CSYNC *ctx, csync_vio_handle_t *dhandle) { switch(ctx->replica) { case REMOTE_REPLICA: if( ctx->remote.read_from_db ) { @@ -104,7 +104,7 @@ csync_vio_file_stat_t *csync_vio_readdir(CSYNC *ctx, csync_vio_handle_t *dhandle } -int csync_vio_stat(CSYNC *ctx, const char *uri, csync_vio_file_stat_t *buf) { +int csync_vio_stat(CSYNC *ctx, const char *uri, csync_file_stat_t *buf) { int rc = -1; switch(ctx->replica) { diff --git a/src/csync/vio/csync_vio.h b/src/csync/vio/csync_vio.h index 715b18542..62522950b 100644 --- a/src/csync/vio/csync_vio.h +++ b/src/csync/vio/csync_vio.h @@ -34,9 +34,9 @@ typedef struct fhandle_s { csync_vio_handle_t *csync_vio_opendir(CSYNC *ctx, const char *name); int csync_vio_closedir(CSYNC *ctx, csync_vio_handle_t *dhandle); -csync_vio_file_stat_t *csync_vio_readdir(CSYNC *ctx, csync_vio_handle_t *dhandle); +std::unique_ptr csync_vio_readdir(CSYNC *ctx, csync_vio_handle_t *dhandle); -int csync_vio_stat(CSYNC *ctx, const char *uri, csync_vio_file_stat_t *buf); +int csync_vio_stat(CSYNC *ctx, const char *uri, csync_file_stat_t *buf); char *csync_vio_get_status_string(CSYNC *ctx); diff --git a/src/csync/vio/csync_vio_file_stat.cpp b/src/csync/vio/csync_vio_file_stat.cpp deleted file mode 100644 index 8ebb64f33..000000000 --- a/src/csync/vio/csync_vio_file_stat.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * libcsync -- a library to sync a directory with another - * - * Copyright (c) 2008-2013 by Andreas Schneider - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "c_lib.h" -#include "csync.h" -#include "csync_log.h" - -csync_vio_file_stat_t *csync_vio_file_stat_new(void) { - csync_vio_file_stat_t *file_stat = (csync_vio_file_stat_t *) c_malloc(sizeof(csync_vio_file_stat_t)); - ZERO_STRUCTP(file_stat); - return file_stat; -} - -csync_vio_file_stat_t* csync_vio_file_stat_copy(csync_vio_file_stat_t *file_stat) { - csync_vio_file_stat_t *file_stat_cpy = csync_vio_file_stat_new(); - memcpy(file_stat_cpy, file_stat, sizeof(csync_vio_file_stat_t)); - if (file_stat_cpy->fields & CSYNC_VIO_FILE_STAT_FIELDS_ETAG) { - file_stat_cpy->etag = c_strdup(file_stat_cpy->etag); - } - if (file_stat_cpy->directDownloadCookies) { - file_stat_cpy->directDownloadCookies = c_strdup(file_stat_cpy->directDownloadCookies); - } - if (file_stat_cpy->directDownloadUrl) { - file_stat_cpy->directDownloadUrl = c_strdup(file_stat_cpy->directDownloadUrl); - } - if (file_stat_cpy->checksumHeader) { - file_stat_cpy->checksumHeader = c_strdup(file_stat_cpy->checksumHeader); - } - file_stat_cpy->name = c_strdup(file_stat_cpy->name); - return file_stat_cpy; -} - -void csync_vio_file_stat_destroy(csync_vio_file_stat_t *file_stat) { - /* FIXME: free rest */ - if (file_stat == NULL) { - return; - } - - if (file_stat->fields & CSYNC_VIO_FILE_STAT_FIELDS_ETAG) { - SAFE_FREE(file_stat->etag); - } - SAFE_FREE(file_stat->directDownloadUrl); - SAFE_FREE(file_stat->directDownloadCookies); - SAFE_FREE(file_stat->name); - SAFE_FREE(file_stat->original_name); - SAFE_FREE(file_stat->checksumHeader); - SAFE_FREE(file_stat); -} - -void csync_vio_file_stat_set_file_id( csync_vio_file_stat_t *dst, const char* src ) { - - csync_vio_set_file_id( dst->file_id, src ); - if( c_streq( dst->file_id, "" )) { - return; - } - dst->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FILE_ID; -} - -void csync_vio_set_file_id( char* dst, const char *src ) { - if( src && dst ) { - if( strlen(src) > FILE_ID_BUF_SIZE ) { - CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Ignoring file_id because it is too long: %s", src); - strcpy(dst, ""); - } else { - strcpy(dst, src); - } - } -} diff --git a/src/csync/vio/csync_vio_local.h b/src/csync/vio/csync_vio_local.h index 294383121..eae64f02d 100644 --- a/src/csync/vio/csync_vio_local.h +++ b/src/csync/vio/csync_vio_local.h @@ -23,8 +23,8 @@ csync_vio_handle_t OCSYNC_EXPORT *csync_vio_local_opendir(const char *name); int OCSYNC_EXPORT csync_vio_local_closedir(csync_vio_handle_t *dhandle); -csync_vio_file_stat_t OCSYNC_EXPORT *csync_vio_local_readdir(csync_vio_handle_t *dhandle); +std::unique_ptr OCSYNC_EXPORT csync_vio_local_readdir(csync_vio_handle_t *dhandle); -int OCSYNC_EXPORT csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf); +int OCSYNC_EXPORT csync_vio_local_stat(const char *uri, csync_file_stat_t *buf); #endif /* _CSYNC_VIO_LOCAL_H */ diff --git a/src/csync/vio/csync_vio_local_unix.cpp b/src/csync/vio/csync_vio_local_unix.cpp index 40e4794c3..5223878a1 100644 --- a/src/csync/vio/csync_vio_local_unix.cpp +++ b/src/csync/vio/csync_vio_local_unix.cpp @@ -29,6 +29,7 @@ #include "c_private.h" #include "c_lib.h" #include "c_string.h" +#include "c_utf8.h" #include "csync_util.h" #include "csync_log.h" #include "csync_vio.h" @@ -83,31 +84,26 @@ int csync_vio_local_closedir(csync_vio_handle_t *dhandle) { return rc; } -csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle) { + +std::unique_ptr csync_vio_local_readdir(csync_vio_handle_t *dhandle) { dhandle_t *handle = NULL; - csync_vio_file_stat_t *file_stat = NULL; handle = (dhandle_t *) dhandle; struct _tdirent *dirent = NULL; - - errno = 0; - file_stat = csync_vio_file_stat_new(); - if (file_stat == NULL) { - goto err; - } - file_stat->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE; + std::unique_ptr file_stat; dirent = _treaddir(handle->dh); if (dirent == NULL) { - goto err; + return {}; } - file_stat->name = c_utf8_from_locale(dirent->d_name); - if (file_stat->name == NULL) { - //file_stat->original_name = c_strdup(dirent->d_name); - if (asprintf(&file_stat->original_name, "%s/%s", handle->path, dirent->d_name) < 0) { - goto err; - } + + file_stat.reset(new csync_file_stat_t); + file_stat->path = c_utf8_from_locale(dirent->d_name); + if (file_stat->path.isNull()) { + file_stat->original_path = handle->path; + file_stat->original_path += '/'; + file_stat->original_path += dirent->d_name; CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Invalid characters in file/directory name, please rename: \"%s\" (%s)", dirent->d_name, handle->path); } @@ -122,31 +118,22 @@ csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle) { break; case DT_DIR: case DT_REG: - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; if (dirent->d_type == DT_DIR) { - file_stat->type = CSYNC_VIO_FILE_TYPE_DIRECTORY; + file_stat->type = CSYNC_FTW_TYPE_DIR; } else { - file_stat->type = CSYNC_VIO_FILE_TYPE_REGULAR; + file_stat->type = CSYNC_FTW_TYPE_FILE; } break; - case DT_UNKNOWN: - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; - file_stat->type = CSYNC_VIO_FILE_TYPE_UNKNOWN; default: break; } #endif return file_stat; - -err: - csync_vio_file_stat_destroy(file_stat); - - return NULL; } -int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) { +int csync_vio_local_stat(const char *uri, csync_file_stat_t *buf) { csync_stat_t sb; mbchar_t *wuri = c_utf8_path_to_locale( uri ); @@ -156,66 +143,33 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) { return -1; } - buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE; + *buf = csync_file_stat_t(); switch(sb.st_mode & S_IFMT) { - case S_IFBLK: - buf->type = CSYNC_VIO_FILE_TYPE_BLOCK_DEVICE; - break; - case S_IFCHR: - buf->type = CSYNC_VIO_FILE_TYPE_CHARACTER_DEVICE; - break; case S_IFDIR: - buf->type = CSYNC_VIO_FILE_TYPE_DIRECTORY; - break; - case S_IFIFO: - buf->type = CSYNC_VIO_FILE_TYPE_FIFO; + buf->type = CSYNC_FTW_TYPE_DIR; break; case S_IFREG: - buf->type = CSYNC_VIO_FILE_TYPE_REGULAR; + buf->type = CSYNC_FTW_TYPE_FILE; break; case S_IFLNK: - buf->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK; - break; case S_IFSOCK: - buf->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK; + buf->type = CSYNC_FTW_TYPE_SLINK; break; default: - buf->type = CSYNC_VIO_FILE_TYPE_UNKNOWN; + buf->type = CSYNC_FTW_TYPE_SKIP; break; } - buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; - buf->mode = sb.st_mode; - buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MODE; - - if (buf->type == CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK) { - /* FIXME: handle symlink */ - buf->flags = CSYNC_VIO_FILE_FLAGS_SYMLINK; - } else { - buf->flags = CSYNC_VIO_FILE_FLAGS_NONE; - } #ifdef __APPLE__ if (sb.st_flags & UF_HIDDEN) { - buf->flags |= CSYNC_VIO_FILE_FLAGS_HIDDEN; + buf->is_hidden = true; } #endif - buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FLAGS; buf->inode = sb.st_ino; - buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_INODE; - - buf->atime = sb.st_atime; - buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME; - - buf->mtime = sb.st_mtime; - buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME; - - buf->ctime = sb.st_ctime; - buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_CTIME; - + buf->modtime = sb.st_mtime; buf->size = sb.st_size; - buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE; c_free_locale_string(wuri); return 0; diff --git a/src/csync/vio/csync_vio_local_win.cpp b/src/csync/vio/csync_vio_local_win.cpp index e9d2ba566..435ad87d6 100644 --- a/src/csync/vio/csync_vio_local_win.cpp +++ b/src/csync/vio/csync_vio_local_win.cpp @@ -29,7 +29,7 @@ #include "c_private.h" #include "c_lib.h" -#include "c_string.h" +#include "c_utf8.h" #include "csync_util.h" #include "csync_log.h" #include "csync_vio.h" @@ -134,21 +134,15 @@ static time_t FileTimeToUnixTime(FILETIME *filetime, DWORD *remainder) } } -csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle) { +std::unique_ptr csync_vio_local_readdir(csync_vio_handle_t *dhandle) { dhandle_t *handle = NULL; - csync_vio_file_stat_t *file_stat = NULL; + std::unique_ptr file_stat; DWORD rem; handle = (dhandle_t *) dhandle; errno = 0; - file_stat = csync_vio_file_stat_new(); - if (file_stat == NULL) { - errno = ENOMEM; - goto err; - } - file_stat->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE; // the win32 functions get the first valid entry with the opendir // thus we must not jump to next entry if it was the first find. @@ -161,67 +155,46 @@ csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle) { if (dwError != ERROR_NO_MORE_FILES) { errno = EACCES; // no more files is fine. Otherwise EACCESS } - goto err; + return nullptr; } } - file_stat->name = c_utf8_from_locale(handle->ffd.cFileName); + file_stat.reset(new csync_file_stat_t); + file_stat->path = c_utf8_from_locale(handle->ffd.cFileName); - file_stat->flags = CSYNC_VIO_FILE_FLAGS_NONE; - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { // Detect symlinks, and treat junctions as symlinks too. if (handle->ffd.dwReserved0 == IO_REPARSE_TAG_SYMLINK || handle->ffd.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT) { - file_stat->flags |= CSYNC_VIO_FILE_FLAGS_SYMLINK; - file_stat->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK; + file_stat->type = CSYNC_FTW_TYPE_SLINK; } else { // The SIS and DEDUP reparse points should be treated as // regular files. We don't know about the other ones yet, // but will also treat them normally for now. - file_stat->type = CSYNC_VIO_FILE_TYPE_REGULAR; + file_stat->type = CSYNC_FTW_TYPE_FILE; } } else if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE || handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE || handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) { - file_stat->type = CSYNC_VIO_FILE_TYPE_UNKNOWN; + file_stat->type = CSYNC_FTW_TYPE_SKIP; } else if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - file_stat->type = CSYNC_VIO_FILE_TYPE_DIRECTORY; + file_stat->type = CSYNC_FTW_TYPE_DIR; } else { - file_stat->type = CSYNC_VIO_FILE_TYPE_REGULAR; + file_stat->type = CSYNC_FTW_TYPE_FILE; } /* Check for the hidden flag */ if( handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ) { - file_stat->flags |= CSYNC_VIO_FILE_FLAGS_HIDDEN; + file_stat->is_hidden = true; } - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FLAGS; - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; - file_stat->size = (handle->ffd.nFileSizeHigh * ((int64_t)(MAXDWORD)+1)) + handle->ffd.nFileSizeLow; - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE; - - file_stat->atime = FileTimeToUnixTime(&handle->ffd.ftLastAccessTime, &rem); - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME; - - file_stat->mtime = FileTimeToUnixTime(&handle->ffd.ftLastWriteTime, &rem); - /* CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Local File MTime: %llu", (unsigned long long) buf->mtime ); */ - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME; - - file_stat->ctime = FileTimeToUnixTime(&handle->ffd.ftCreationTime, &rem); - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_CTIME; - + file_stat->modtime = FileTimeToUnixTime(&handle->ffd.ftLastWriteTime, &rem); return file_stat; - -err: - SAFE_FREE(file_stat); - - return NULL; } -int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) { +int csync_vio_local_stat(const char *uri, csync_file_stat_t *buf) { /* Almost nothing to do since csync_vio_local_readdir already filled up most of the information But we still need to fetch the file ID. Possible optimisation: only fetch the file id when we need it (for new files) @@ -257,17 +230,10 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) { FileIndex.QuadPart &= 0x0000FFFFFFFFFFFF; /* printf("Index: %I64i\n", FileIndex.QuadPart); */ buf->inode = FileIndex.QuadPart; + buf->size = (fileInfo.nFileSizeHigh * ((int64_t)(MAXDWORD)+1)) + fileInfo.nFileSizeLow; - if (!(buf->fields & CSYNC_VIO_FILE_STAT_FIELDS_SIZE)) { - buf->size = (fileInfo.nFileSizeHigh * ((int64_t)(MAXDWORD)+1)) + fileInfo.nFileSizeLow; - buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE; - } - if (!(buf->fields & CSYNC_VIO_FILE_STAT_FIELDS_MTIME)) { - DWORD rem; - buf->mtime = FileTimeToUnixTime(&fileInfo.ftLastWriteTime, &rem); - /* CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Local File MTime: %llu", (unsigned long long) buf->mtime ); */ - buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME; - } + DWORD rem; + buf->modtime = FileTimeToUnixTime(&fileInfo.ftLastWriteTime, &rem); c_free_locale_string(wuri); CloseHandle(h); diff --git a/src/libsync/discoveryphase.cpp b/src/libsync/discoveryphase.cpp index dcad77390..3ba03cac9 100644 --- a/src/libsync/discoveryphase.cpp +++ b/src/libsync/discoveryphase.cpp @@ -321,76 +321,50 @@ static QByteArray findBestChecksum(const QByteArray &checksums) return QByteArray(); } -static csync_vio_file_stat_t *propertyMapToFileStat(const QMap &map) +static std::unique_ptr propertyMapToFileStat(const QMap &map) { - csync_vio_file_stat_t *file_stat = csync_vio_file_stat_new(); + std::unique_ptr file_stat(new csync_file_stat_t); for (auto it = map.constBegin(); it != map.constEnd(); ++it) { QString property = it.key(); QString value = it.value(); if (property == "resourcetype") { if (value.contains("collection")) { - file_stat->type = CSYNC_VIO_FILE_TYPE_DIRECTORY; + file_stat->type = CSYNC_FTW_TYPE_DIR; } else { - file_stat->type = CSYNC_VIO_FILE_TYPE_REGULAR; + file_stat->type = CSYNC_FTW_TYPE_FILE; } - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; } else if (property == "getlastmodified") { - file_stat->mtime = oc_httpdate_parse(value.toUtf8()); - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME; + file_stat->modtime = oc_httpdate_parse(value.toUtf8()); } else if (property == "getcontentlength") { bool ok = false; qlonglong ll = value.toLongLong(&ok); if (ok && ll >= 0) { file_stat->size = ll; - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE; } } else if (property == "getetag") { - file_stat->etag = csync_normalize_etag(value.toUtf8()); - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG; + file_stat->etag = Utility::normalizeEtag(value.toUtf8()); } else if (property == "id") { - csync_vio_file_stat_set_file_id(file_stat, value.toUtf8()); + file_stat->file_id = value.toUtf8(); } else if (property == "downloadURL") { - file_stat->directDownloadUrl = strdup(value.toUtf8()); - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADURL; + file_stat->directDownloadUrl = value.toUtf8(); } else if (property == "dDC") { - file_stat->directDownloadCookies = strdup(value.toUtf8()); - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADCOOKIES; + file_stat->directDownloadCookies = value.toUtf8(); } else if (property == "permissions") { - auto v = value.toUtf8(); - if (value.isEmpty()) { - // special meaning for our code: server returned permissions but are empty - // meaning only reading is allowed for this resource - file_stat->remotePerm[0] = ' '; - // see _csync_detect_update() - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERM; - } else if (v.length() < int(sizeof(file_stat->remotePerm))) { - strcpy(file_stat->remotePerm, v.constData()); - file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERM; - } else { - qCWarning(lcDiscovery) << "permissions too large" << v; - } + file_stat->remotePerm = value.toUtf8(); } else if (property == "checksums") { - QByteArray checksum = findBestChecksum(value.toUtf8()); - if (!checksum.isEmpty()) { - file_stat->checksumHeader = strdup(checksum.constData()); - } + file_stat->checksumHeader = findBestChecksum(value.toUtf8()); } else if (property == "share-types" && !value.isEmpty()) { // Since QMap is sorted, "share-types" is always "permissions". - if (file_stat->remotePerm[0] == '\0' || !(file_stat->fields & CSYNC_VIO_FILE_STAT_FIELDS_PERM)) { + if (file_stat->remotePerm.isEmpty()) { qWarning() << "Server returned a share type, but no permissions?"; } else { // S means shared with me. // But for our purpose, we want to know if the file is shared. It does not matter // if we are the owner or not. // Piggy back on the persmission field 'S' - if (!std::strchr(file_stat->remotePerm, 'S')) { - if (std::strlen(file_stat->remotePerm) < sizeof(file_stat->remotePerm) - 1) { - std::strcat(file_stat->remotePerm, "S"); - } else { - qWarning() << "permissions too large" << file_stat->remotePerm; - } - } + if (!file_stat->remotePerm.contains('S')) + file_stat->remotePerm.append('S'); } } } @@ -423,17 +397,16 @@ void DiscoverySingleDirectoryJob::directoryListingIteratedSlot(QString file, con } - FileStatPointer file_stat(propertyMapToFileStat(map)); - file_stat->name = strdup(file.toUtf8()); - if (!file_stat->etag || strlen(file_stat->etag) == 0) { - qCCritical(lcDiscovery) << "etag of" << file_stat->name << "is" << file_stat->etag << " This must not happen."; + std::unique_ptr file_stat(propertyMapToFileStat(map)); + file_stat->path = file.toUtf8(); + if (file_stat->etag.isEmpty()) { + qCCritical(lcDiscovery) << "etag of" << file_stat->path << "is" << file_stat->etag << "This must not happen."; } if (_isExternalStorage) { /* All the entries in a external storage have 'M' in their permission. However, for all purposes in the desktop client, we only need to know about the mount points. So replace the 'M' by a 'm' for every sub entries in an external storage */ - std::replace(file_stat->remotePerm, file_stat->remotePerm + strlen(file_stat->remotePerm), - 'M', 'm'); + file_stat->remotePerm.replace('M', 'm'); } QStringRef fileRef(&file); @@ -441,7 +414,7 @@ void DiscoverySingleDirectoryJob::directoryListingIteratedSlot(QString file, con if (slashPos > -1) { fileRef = file.midRef(slashPos + 1); } - _results.append(file_stat); + _results.push_back(std::move(file_stat)); } //This works in concerto with the RequestEtagJob and the Folder object to check if the remote folder changed. @@ -465,7 +438,7 @@ void DiscoverySingleDirectoryJob::lsJobFinishedWithoutErrorSlot() } emit etag(_firstEtag); emit etagConcatenation(_etagConcatenation); - emit finishedWithResult(_results); + emit finishedWithResult(); deleteLater(); } @@ -527,8 +500,8 @@ void DiscoveryMainThread::doOpendirSlot(const QString &subPath, DiscoveryDirecto // Schedule the DiscoverySingleDirectoryJob _singleDirJob = new DiscoverySingleDirectoryJob(_account, fullPath, this); - QObject::connect(_singleDirJob, SIGNAL(finishedWithResult(const QList &)), - this, SLOT(singleDirectoryJobResultSlot(const QList &))); + QObject::connect(_singleDirJob, SIGNAL(finishedWithResult()), + this, SLOT(singleDirectoryJobResultSlot())); QObject::connect(_singleDirJob, SIGNAL(finishedWithError(int, QString)), this, SLOT(singleDirectoryJobFinishedWithErrorSlot(int, QString))); QObject::connect(_singleDirJob, SIGNAL(firstDirectoryPermissions(QString)), @@ -546,17 +519,17 @@ void DiscoveryMainThread::doOpendirSlot(const QString &subPath, DiscoveryDirecto } -void DiscoveryMainThread::singleDirectoryJobResultSlot(const QList &result) +void DiscoveryMainThread::singleDirectoryJobResultSlot() { if (!_currentDiscoveryDirectoryResult) { return; // possibly aborted } - qCDebug(lcDiscovery) << "Have" << result.count() << "results for " << _currentDiscoveryDirectoryResult->path; - - _currentDiscoveryDirectoryResult->list = result; + _currentDiscoveryDirectoryResult->list = _singleDirJob->takeResults(); _currentDiscoveryDirectoryResult->code = 0; - _currentDiscoveryDirectoryResult->listIndex = 0; + + qCDebug(lcDiscovery) << "Have" << _currentDiscoveryDirectoryResult->list.size() << "results for " << _currentDiscoveryDirectoryResult->path; + _currentDiscoveryDirectoryResult = 0; // the sync thread owns it now if (!_firstFolderProcessed) { @@ -652,7 +625,7 @@ void DiscoveryMainThread::abort() if (_singleDirJob) { _singleDirJob->disconnect(SIGNAL(finishedWithError(int, QString)), this); _singleDirJob->disconnect(SIGNAL(firstDirectoryPermissions(QString)), this); - _singleDirJob->disconnect(SIGNAL(finishedWithResult(const QList &)), this); + _singleDirJob->disconnect(SIGNAL(finishedWithResult()), this); _singleDirJob->abort(); } if (_currentDiscoveryDirectoryResult) { @@ -704,16 +677,16 @@ csync_vio_handle_t *DiscoveryJob::remote_vio_opendir_hook(const char *url, } -csync_vio_file_stat_t *DiscoveryJob::remote_vio_readdir_hook(csync_vio_handle_t *dhandle, +std::unique_ptr DiscoveryJob::remote_vio_readdir_hook(csync_vio_handle_t *dhandle, void *userdata) { DiscoveryJob *discoveryJob = static_cast(userdata); if (discoveryJob) { DiscoveryDirectoryResult *directoryResult = static_cast(dhandle); - if (directoryResult->listIndex < directoryResult->list.size()) { - csync_vio_file_stat_t *file_stat = directoryResult->list.at(directoryResult->listIndex++).data(); - // Make a copy, csync_update will delete the copy - return csync_vio_file_stat_copy(file_stat); + if (!directoryResult->list.empty()) { + auto file_stat = std::move(directoryResult->list.front()); + directoryResult->list.pop_front(); + return file_stat; } } return NULL; diff --git a/src/libsync/discoveryphase.h b/src/libsync/discoveryphase.h index b7d252c67..4404e76ea 100644 --- a/src/libsync/discoveryphase.h +++ b/src/libsync/discoveryphase.h @@ -23,6 +23,7 @@ #include #include #include +#include namespace OCC { @@ -76,48 +77,14 @@ struct SyncOptions }; -/** - * @brief The FileStatPointer class - * @ingroup libsync - */ -class FileStatPointer -{ -public: - FileStatPointer(csync_vio_file_stat_t *stat) - : _stat(stat) - { - } - FileStatPointer(const FileStatPointer &other) - : _stat(csync_vio_file_stat_copy(other._stat)) - { - } - ~FileStatPointer() - { - csync_vio_file_stat_destroy(_stat); - } - FileStatPointer &operator=(const FileStatPointer &other) - { - csync_vio_file_stat_destroy(_stat); - _stat = csync_vio_file_stat_copy(other._stat); - return *this; - } - inline csync_vio_file_stat_t *data() const { return _stat; } - inline csync_vio_file_stat_t *operator->() const { return _stat; } - -private: - csync_vio_file_stat_t *_stat; -}; - struct DiscoveryDirectoryResult { QString path; QString msg; int code; - QList list; - int listIndex; + std::deque> list; DiscoveryDirectoryResult() : code(EIO) - , listIndex(0) { } }; @@ -138,12 +105,14 @@ public: void setIsRootPath() { _isRootPath = true; } void start(); void abort(); + std::deque> &&takeResults() { return std::move(_results); } + // This is not actually a network job, it is just a job signals: void firstDirectoryPermissions(const QString &); void etagConcatenation(const QString &); void etag(const QString &); - void finishedWithResult(const QList &); + void finishedWithResult(); void finishedWithError(int csyncErrnoCode, const QString &msg); private slots: void directoryListingIteratedSlot(QString, const QMap &); @@ -151,7 +120,7 @@ private slots: void lsJobFinishedWithErrorSlot(QNetworkReply *); private: - QList _results; + std::deque> _results; QString _subPath; QString _etagConcatenation; QString _firstEtag; @@ -203,7 +172,7 @@ public slots: void doGetSizeSlot(const QString &path, qint64 *result); // From Job: - void singleDirectoryJobResultSlot(const QList &); + void singleDirectoryJobResultSlot(); void singleDirectoryJobFinishedWithErrorSlot(int csyncErrnoCode, const QString &msg); void singleDirectoryJobFirstDirectoryPermissionsSlot(const QString &); @@ -250,7 +219,7 @@ class DiscoveryJob : public QObject // For using QNAM to get the directory listings static csync_vio_handle_t *remote_vio_opendir_hook(const char *url, void *userdata); - static csync_vio_file_stat_t *remote_vio_readdir_hook(csync_vio_handle_t *dhandle, + static std::unique_ptr remote_vio_readdir_hook(csync_vio_handle_t *dhandle, void *userdata); static void remote_vio_closedir_hook(csync_vio_handle_t *dhandle, void *userdata); diff --git a/src/libsync/filesystem.cpp b/src/libsync/filesystem.cpp index 4625eed04..2e365c608 100644 --- a/src/libsync/filesystem.cpp +++ b/src/libsync/filesystem.cpp @@ -44,6 +44,7 @@ extern "C" int c_utimes(const char *, const struct timeval *); #include "vio/csync_vio_local.h" #include "std/c_path.h" #include "std/c_string.h" +#include "std/c_utf8.h" namespace OCC { @@ -173,17 +174,16 @@ void FileSystem::setFileReadOnlyWeak(const QString &filename, bool readonly) time_t FileSystem::getModTime(const QString &filename) { - csync_vio_file_stat_t *stat = csync_vio_file_stat_new(); + csync_file_stat_t stat; qint64 result = -1; - if (csync_vio_local_stat(filename.toUtf8().data(), stat) != -1 - && (stat->fields & CSYNC_VIO_FILE_STAT_FIELDS_MTIME)) { - result = stat->mtime; + if (csync_vio_local_stat(filename.toUtf8().data(), &stat) != -1 + && (stat.modtime != 0)) { + result = stat.modtime; } else { qCWarning(lcFileSystem) << "Could not get modification time for" << filename << "with csync, using QFileInfo"; result = Utility::qDateTimeToTime_t(QFileInfo(filename).lastModified()); } - csync_vio_file_stat_destroy(stat); return result; } @@ -428,14 +428,12 @@ bool FileSystem::openAndSeekFileSharedRead(QFile *file, QString *errorOrNull, qi static qint64 getSizeWithCsync(const QString &filename) { qint64 result = 0; - csync_vio_file_stat_t *stat = csync_vio_file_stat_new(); - if (csync_vio_local_stat(filename.toUtf8().data(), stat) != -1 - && (stat->fields & CSYNC_VIO_FILE_STAT_FIELDS_SIZE)) { - result = stat->size; + csync_file_stat_t stat; + if (csync_vio_local_stat(filename.toUtf8().data(), &stat) != -1) { + result = stat.size; } else { qCWarning(lcFileSystem) << "Could not get size for" << filename << "with csync"; } - csync_vio_file_stat_destroy(stat); return result; } #endif diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp index 6fff8e538..df0f2e0e8 100644 --- a/src/libsync/syncengine.cpp +++ b/src/libsync/syncengine.cpp @@ -134,9 +134,6 @@ QString SyncEngine::csyncErrorToString(CSYNC_STATUS err) case CSYNC_STATUS_TREE_ERROR: errStr = tr("CSync got an error while processing internal trees."); break; - case CSYNC_STATUS_MEMORY_ERROR: - errStr = tr("CSync failed to reserve memory."); - break; case CSYNC_STATUS_PARAM_ERROR: errStr = tr("CSync fatal parameter error."); break; diff --git a/test/csync/CMakeLists.txt b/test/csync/CMakeLists.txt index a27505d12..6b26eb96c 100644 --- a/test/csync/CMakeLists.txt +++ b/test/csync/CMakeLists.txt @@ -44,7 +44,6 @@ add_cmocka_test(check_csync_statedb_query csync_tests/check_csync_statedb_query. add_cmocka_test(check_csync_commit csync_tests/check_csync_commit.cpp ${TEST_TARGET_LIBRARIES}) # vio -add_cmocka_test(check_vio_file_stat vio_tests/check_vio_file_stat.cpp ${TEST_TARGET_LIBRARIES}) add_cmocka_test(check_vio vio_tests/check_vio.cpp ${TEST_TARGET_LIBRARIES}) add_cmocka_test(check_vio_ext vio_tests/check_vio_ext.cpp ${TEST_TARGET_LIBRARIES}) diff --git a/test/csync/csync_tests/check_csync_log.cpp b/test/csync/csync_tests/check_csync_log.cpp index c5f312ff5..b7c30c5a0 100644 --- a/test/csync/csync_tests/check_csync_log.cpp +++ b/test/csync/csync_tests/check_csync_log.cpp @@ -25,6 +25,7 @@ #include "csync.h" #include "csync_log.cpp" #include "c_private.h" +#include "std/c_utf8.h" static int setup(void **state) { CSYNC *csync; diff --git a/test/csync/csync_tests/check_csync_misc.cpp b/test/csync/csync_tests/check_csync_misc.cpp index 64f95694b..4d07d4335 100644 --- a/test/csync/csync_tests/check_csync_misc.cpp +++ b/test/csync/csync_tests/check_csync_misc.cpp @@ -17,20 +17,19 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "csync_misc.h" +#include "common/utility.h" #include #include "torture.h" static void check_csync_normalize_etag(void **state) { - char *str; + QByteArray str; (void) state; /* unused */ #define CHECK_NORMALIZE_ETAG(TEST, EXPECT) \ - str = csync_normalize_etag(TEST); \ - assert_string_equal(str, EXPECT); \ - free(str); + str = OCC::Utility::normalizeEtag(TEST); \ + assert_string_equal(str.constData(), EXPECT); \ CHECK_NORMALIZE_ETAG("foo", "foo"); diff --git a/test/csync/csync_tests/check_csync_update.cpp b/test/csync/csync_tests/check_csync_update.cpp index 237687e4c..1b260ed8b 100644 --- a/test/csync/csync_tests/check_csync_update.cpp +++ b/test/csync/csync_tests/check_csync_update.cpp @@ -176,63 +176,41 @@ static int teardown_rm(void **state) { } /* create a file stat, caller must free memory */ -static csync_vio_file_stat_t* create_fstat(const char *name, +static std::unique_ptr create_fstat(const char *name, ino_t inode, time_t mtime) { - csync_vio_file_stat_t *fs = NULL; + std::unique_ptr fs(new csync_file_stat_t); time_t t; - fs = csync_vio_file_stat_new(); - if (fs == NULL) { - return NULL; - } - if (name && *name) { - fs->name = c_strdup(name); + fs->path = name; } else { - fs->name = c_strdup("file.txt"); - } - - if (fs->name == NULL) { - csync_vio_file_stat_destroy(fs); - return NULL; + fs->path = "file.txt"; } - fs->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE; - - fs->type = CSYNC_VIO_FILE_TYPE_REGULAR; - fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; - + fs->type = CSYNC_FTW_TYPE_FILE; if (inode == 0) { fs->inode = 619070; } else { fs->inode = inode; } - fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_INODE; - fs->size = 157459; - fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE; - - if (mtime == 0) { - fs->atime = fs->ctime = fs->mtime = time(&t); + fs->modtime = time(&t); } else { - fs->atime = fs->ctime = fs->mtime = mtime; + fs->modtime = mtime; } - fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME; - fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_CTIME; - fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME; return fs; } static int failing_fn(CSYNC *ctx, const char *file, - const csync_vio_file_stat_t *fs, + const csync_file_stat_t *fs, int flag) { (void) ctx; @@ -248,15 +226,14 @@ static void check_csync_detect_update(void **state) { CSYNC *csync = (CSYNC*)*state; csync_file_stat_t *st; - csync_vio_file_stat_t *fs; + std::unique_ptr fs; int rc; fs = create_fstat("file.txt", 0, 1217597845); - assert_non_null(fs); rc = _csync_detect_update(csync, "/tmp/check_csync1/file.txt", - fs, + fs.get(), CSYNC_FTW_TYPE_FILE); assert_int_equal(rc, 0); @@ -266,8 +243,6 @@ static void check_csync_detect_update(void **state) /* create a statedb */ csync_set_status(csync, 0xFFFF); - - csync_vio_file_stat_destroy(fs); } /* Test behaviour in case no db is there. For that its important that the @@ -277,15 +252,14 @@ static void check_csync_detect_update_db_none(void **state) { CSYNC *csync = (CSYNC*)*state; csync_file_stat_t *st; - csync_vio_file_stat_t *fs; + std::unique_ptr fs; int rc; fs = create_fstat("file.txt", 0, 1217597845); - assert_non_null(fs); rc = _csync_detect_update(csync, "/tmp/check_csync1/file.txt", - fs, + fs.get(), CSYNC_FTW_TYPE_FILE); assert_int_equal(rc, 0); @@ -296,23 +270,20 @@ static void check_csync_detect_update_db_none(void **state) /* create a statedb */ csync_set_status(csync, 0xFFFF); - - csync_vio_file_stat_destroy(fs); } static void check_csync_detect_update_db_eval(void **state) { CSYNC *csync = (CSYNC*)*state; csync_file_stat_t *st; - csync_vio_file_stat_t *fs; + std::unique_ptr fs; int rc; fs = create_fstat("file.txt", 0, 42); - assert_non_null(fs); rc = _csync_detect_update(csync, "/tmp/check_csync1/file.txt", - fs, + fs.get(), CSYNC_FTW_TYPE_FILE); assert_int_equal(rc, 0); @@ -322,8 +293,6 @@ static void check_csync_detect_update_db_eval(void **state) /* create a statedb */ csync_set_status(csync, 0xFFFF); - - csync_vio_file_stat_destroy(fs); } @@ -332,16 +301,15 @@ static void check_csync_detect_update_db_rename(void **state) CSYNC *csync = (CSYNC*)*state; // csync_file_stat_t *st; - csync_vio_file_stat_t *fs; + std::unique_ptr fs; int rc = 0; fs = create_fstat("wurst.txt", 0, 42); - assert_non_null(fs); csync_set_statedb_exists(csync, 1); rc = _csync_detect_update(csync, "/tmp/check_csync1/wurst.txt", - fs, + fs.get(), CSYNC_FTW_TYPE_FILE); assert_int_equal(rc, 0); @@ -355,23 +323,20 @@ static void check_csync_detect_update_db_rename(void **state) */ /* create a statedb */ csync_set_status(csync, 0xFFFF); - - csync_vio_file_stat_destroy(fs); } static void check_csync_detect_update_db_new(void **state) { CSYNC *csync = (CSYNC*)*state; csync_file_stat_t *st; - csync_vio_file_stat_t *fs; + std::unique_ptr fs; int rc; fs = create_fstat("file.txt", 42000, 0); - assert_non_null(fs); rc = _csync_detect_update(csync, "/tmp/check_csync1/file.txt", - fs, + fs.get(), CSYNC_FTW_TYPE_FILE); assert_int_equal(rc, 0); @@ -382,22 +347,19 @@ static void check_csync_detect_update_db_new(void **state) /* create a statedb */ csync_set_status(csync, 0xFFFF); - - csync_vio_file_stat_destroy(fs); } static void check_csync_detect_update_null(void **state) { CSYNC *csync = (CSYNC*)*state; - csync_vio_file_stat_t *fs; + std::unique_ptr fs; int rc; fs = create_fstat("file.txt", 0, 0); - assert_non_null(fs); rc = _csync_detect_update(csync, NULL, - fs, + fs.get(), CSYNC_FTW_TYPE_FILE); assert_int_equal(rc, -1); @@ -406,8 +368,6 @@ static void check_csync_detect_update_null(void **state) NULL, CSYNC_FTW_TYPE_FILE); assert_int_equal(rc, -1); - - csync_vio_file_stat_destroy(fs); } static void check_csync_ftw(void **state) diff --git a/test/csync/encoding_tests/check_encoding.cpp b/test/csync/encoding_tests/check_encoding.cpp index 443d2c625..6252dde4d 100644 --- a/test/csync/encoding_tests/check_encoding.cpp +++ b/test/csync/encoding_tests/check_encoding.cpp @@ -21,6 +21,7 @@ #include #include "c_string.h" #include "c_path.h" +#include "c_utf8.h" #ifdef _WIN32 #include @@ -48,7 +49,6 @@ static void check_iconv_to_native_normalization(void **state) static void check_iconv_from_native_normalization(void **state) { - char *out = NULL; #ifdef _WIN32 const mbchar_t *in = L"\x48\xc3\xa4"; // UTF-8 #else @@ -60,12 +60,9 @@ static void check_iconv_from_native_normalization(void **state) #endif const char *exp_out = "\x48\xc3\xa4"; // UTF-8 - out = c_utf8_from_locale(in); + QByteArray out = c_utf8_from_locale(in); assert_string_equal(out, exp_out); - c_free_locale_string(out); - assert_null(out); - (void) state; /* unused */ } @@ -80,15 +77,11 @@ static void check_iconv_ascii(void **state) const mbchar_t *in = "abc/ABC\\123"; // UTF-8 #endif #endif - char *out = NULL; const char *exp_out = "abc/ABC\\123"; - out = c_utf8_from_locale(in); + QByteArray out = c_utf8_from_locale(in); assert_string_equal(out, exp_out); - c_free_locale_string(out); - assert_null(out); - (void) state; /* unused */ } diff --git a/test/csync/vio_tests/check_vio.cpp b/test/csync/vio_tests/check_vio.cpp index fc87485bf..cdb36a6a0 100644 --- a/test/csync/vio_tests/check_vio.cpp +++ b/test/csync/vio_tests/check_vio.cpp @@ -26,6 +26,7 @@ #include "torture.h" #include "csync_private.h" +#include "std/c_utf8.h" #include "vio/csync_vio.h" #define CSYNC_TEST_DIR "/tmp/csync_test/" @@ -141,16 +142,15 @@ static void check_csync_vio_readdir(void **state) { CSYNC *csync = (CSYNC*)*state; csync_vio_handle_t *dh; - csync_vio_file_stat_t *dirent; + std::unique_ptr dirent; int rc; dh = csync_vio_opendir(csync, CSYNC_TEST_DIR); assert_non_null(dh); dirent = csync_vio_readdir(csync, dh); - assert_non_null(dirent); + assert_non_null(dirent.get()); - csync_vio_file_stat_destroy(dirent); rc = csync_vio_closedir(csync, dh); assert_int_equal(rc, 0); } diff --git a/test/csync/vio_tests/check_vio_ext.cpp b/test/csync/vio_tests/check_vio_ext.cpp index fa2c771c3..d93bdef01 100644 --- a/test/csync/vio_tests/check_vio_ext.cpp +++ b/test/csync/vio_tests/check_vio_ext.cpp @@ -27,6 +27,7 @@ #include "torture.h" #include "csync_private.h" +#include "std/c_utf8.h" #include "vio/csync_vio.h" #ifdef _WIN32 @@ -184,7 +185,7 @@ static void create_dirs( const char *path ) static void traverse_dir(void **state, const char *dir, int *cnt) { csync_vio_handle_t *dh; - csync_vio_file_stat_t *dirent; + std::unique_ptr dirent; statevar *sv = (statevar*) *state; CSYNC *csync = sv->csync; char *subdir; @@ -204,22 +205,21 @@ static void traverse_dir(void **state, const char *dir, int *cnt) assert_non_null(dh); while( (dirent = csync_vio_readdir(csync, dh)) ) { - assert_non_null(dirent); - if (dirent->original_name) { - sv->ignored_dir = c_strdup(dirent->original_name); + assert_non_null(dirent.get()); + if (!dirent->original_path.isEmpty()) { + sv->ignored_dir = c_strdup(dirent->original_path); continue; } - assert_non_null(dirent->name); - assert_int_equal( dirent->fields & CSYNC_VIO_FILE_STAT_FIELDS_TYPE, CSYNC_VIO_FILE_STAT_FIELDS_TYPE ); + assert_false(dirent->path.isEmpty()); - if( c_streq( dirent->name, "..") || c_streq( dirent->name, "." )) { + if( c_streq( dirent->path, "..") || c_streq( dirent->path, "." )) { continue; } - is_dir = (dirent->type == CSYNC_VIO_FILE_TYPE_DIRECTORY) ? 1:0; + is_dir = (dirent->type == CSYNC_FTW_TYPE_DIR) ? 1:0; - assert_int_not_equal( asprintf( &subdir, "%s/%s", dir, dirent->name ), -1 ); + assert_int_not_equal( asprintf( &subdir, "%s/%s", dir, dirent->path.constData() ), -1 ); assert_int_not_equal( asprintf( &subdir_out, format_str, is_dir ? "":" ", @@ -249,7 +249,6 @@ static void traverse_dir(void **state, const char *dir, int *cnt) SAFE_FREE(subdir_out); } - csync_vio_file_stat_destroy(dirent); rc = csync_vio_closedir(csync, dh); assert_int_equal(rc, 0); diff --git a/test/csync/vio_tests/check_vio_file_stat.cpp b/test/csync/vio_tests/check_vio_file_stat.cpp deleted file mode 100644 index 3bca997a1..000000000 --- a/test/csync/vio_tests/check_vio_file_stat.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * libcsync -- a library to sync a directory with another - * - * Copyright (c) 2008-2013 by Andreas Schneider - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include "torture.h" - -#include "csync.h" - -static void check_csync_vio_file_stat_new(void **state) -{ - csync_vio_file_stat_t *tstat; - - (void) state; /* unused */ - - tstat = csync_vio_file_stat_new(); - assert_non_null(tstat); - - csync_vio_file_stat_destroy(tstat); -} - - -int torture_run_tests(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test(check_csync_vio_file_stat_new), - }; - - return cmocka_run_group_tests(tests, NULL, NULL); -} -