#define __STDC_FORMAT_MACROS
#include <inttypes.h>
-/* calculate the hash of a given uri */
-static uint64_t _hash_of_file(CSYNC *ctx, const char *file) {
- const char *path;
- int len;
- uint64_t h = 0;
-
- if( ctx && file ) {
- path = file;
- if (ctx->current == LOCAL_REPLICA) {
- if (strlen(path) <= strlen(ctx->local.uri)) {
- return 0;
- }
- path += strlen(ctx->local.uri) + 1;
- }
- len = strlen(path);
- h = c_jhash64((uint8_t *) path, len, 0);
- }
- return h;
-}
-
#ifdef NO_RENAME_EXTENSION
/* Return true if the two path have the same extension. false otherwise. */
static bool _csync_sameextension(const char *p1, const char *p2) {
return ctx->statedb.lastReturnValue != SQLITE_OK && ctx->statedb.lastReturnValue != SQLITE_DONE && ctx->statedb.lastReturnValue != SQLITE_ROW;
}
+static QByteArray _rel_to_abs(CSYNC* ctx, const QByteArray &relativePath) {
+ return QByteArray() % const_cast<const char *>(ctx->local.uri) % '/' % relativePath;
+}
+
/* 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 */
*
* See doc/dev/sync-algorithm.md for an overview.
*/
-static int _csync_detect_update(CSYNC *ctx, const char *file,
- const csync_file_stat_t *fs, enum csync_ftw_type_e type) {
- uint64_t h = 0;
- const char *path = NULL;
- std::unique_ptr<csync_file_stat_t> st;
+static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> fs) {
std::unique_ptr<csync_file_stat_t> tmp;
CSYNC_EXCLUDE_TYPE excluded;
- if ((file == NULL) || (fs == NULL)) {
+ if (fs == NULL) {
errno = EINVAL;
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
return -1;
}
- path = file;
- if (ctx->current == LOCAL_REPLICA) {
- if (strlen(path) <= strlen(ctx->local.uri)) {
- ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
- return -1;
- }
- path += strlen(ctx->local.uri) + 1;
- }
-
- if (type == CSYNC_FTW_TYPE_SKIP) {
+ if (fs->type == CSYNC_FTW_TYPE_SKIP) {
excluded =CSYNC_FILE_EXCLUDE_STAT_FAILED;
} else {
/* Check if file is excluded */
- excluded = csync_excluded_traversal(ctx->excludes, path, type);
+ excluded = csync_excluded_traversal(ctx->excludes, fs->path, fs->type);
}
if( excluded == CSYNC_NOT_EXCLUDED ) {
* 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->is_hidden)) {
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file excluded because it is a hidden file: %s", path);
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file excluded because it is a hidden file: %s", fs->path.constData());
excluded = CSYNC_FILE_EXCLUDE_HIDDEN;
}
} else {
/* File is ignored because it's matched by a user- or system exclude pattern. */
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "%s excluded (%d)", path, excluded);
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "%s excluded (%d)", fs->path.constData(), excluded);
if (excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE) {
return 1;
}
}
if (ctx->current == REMOTE_REPLICA && ctx->callbacks.checkSelectiveSyncBlackListHook) {
- if (ctx->callbacks.checkSelectiveSyncBlackListHook(ctx->callbacks.update_callback_userdata, path)) {
+ if (ctx->callbacks.checkSelectiveSyncBlackListHook(ctx->callbacks.update_callback_userdata, fs->path)) {
return 1;
}
}
- h = _hash_of_file(ctx, file );
- if( h == 0 ) {
- return -1;
- }
-
- st.reset(new csync_file_stat_t);
-
- if (type == CSYNC_FTW_TYPE_FILE ) {
+ if (fs->type == CSYNC_FTW_TYPE_FILE ) {
if (fs->modtime == 0) {
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s - mtime is zero!", path);
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s - mtime is zero!", fs->path.constData());
}
}
- if (excluded > CSYNC_NOT_EXCLUDED || type == CSYNC_FTW_TYPE_SLINK) {
- st->instruction = CSYNC_INSTRUCTION_IGNORE;
+ if (excluded > CSYNC_NOT_EXCLUDED || fs->type == CSYNC_FTW_TYPE_SLINK) {
+ fs->instruction = CSYNC_INSTRUCTION_IGNORE;
if (ctx->current_fs) {
ctx->current_fs->has_ignored_files = true;
}
* does not change on rename.
*/
if (csync_get_statedb_exists(ctx)) {
- tmp = csync_statedb_get_stat_by_hash(ctx, h);
+ tmp = csync_statedb_get_stat_by_hash(ctx, fs->phash);
if(_last_db_return_error(ctx)) {
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
return -1;
}
- if(tmp && tmp->phash == h ) { /* there is an entry in the database */
+ if(tmp && tmp->phash == fs->phash ) { /* there is an entry in the database */
/* we have an update! */
CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "Database entry found, compare: %" PRId64 " <-> %" PRId64
", etag: %s <-> %s, inode: %" PRId64 " <-> %" PRId64
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;
+ fs->instruction = CSYNC_INSTRUCTION_EVAL;
// Preserve the EVAL flag later on if the type has changed.
if (tmp->type != fs->type) {
- st->child_modified = true;
+ fs->child_modified = true;
}
goto out;
// Checksum comparison at this stage is only enabled for .eml files,
// check #4754 #4755
- bool isEmlFile = csync_fnmatch("*.eml", file, FNM_CASEFOLD) == 0;
+ bool isEmlFile = csync_fnmatch("*.eml", fs->path, FNM_CASEFOLD) == 0;
if (isEmlFile && fs->size == tmp->size && !tmp->checksumHeader.isEmpty()) {
if (ctx->callbacks.checksum_hook) {
- st->checksumHeader = ctx->callbacks.checksum_hook(
- file, tmp->checksumHeader,
+ fs->checksumHeader = ctx->callbacks.checksum_hook(
+ _rel_to_abs(ctx, fs->path), tmp->checksumHeader,
ctx->callbacks.checksum_userdata);
}
bool checksumIdentical = false;
- if (!st->checksumHeader.isEmpty()) {
- checksumIdentical = st->checksumHeader == tmp->checksumHeader;
+ if (!fs->checksumHeader.isEmpty()) {
+ checksumIdentical = fs->checksumHeader == tmp->checksumHeader;
}
if (checksumIdentical) {
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "NOTE: Checksums are identical, file did not actually change: %s", path);
- st->instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "NOTE: Checksums are identical, file did not actually change: %s", fs->path.constData());
+ fs->instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
goto out;
}
}
// Preserve the EVAL flag later on if the type has changed.
if (tmp->type != fs->type) {
- st->child_modified = true;
+ fs->child_modified = true;
}
- st->instruction = CSYNC_INSTRUCTION_EVAL;
+ fs->instruction = CSYNC_INSTRUCTION_EVAL;
goto out;
}
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
+ if (fs->type == CSYNC_FTW_TYPE_DIR && ctx->current == REMOTE_REPLICA
&& !metadata_differ && ctx->read_remote_from_db) {
/* If both etag and file id are equal for a directory, read all contents from
* the database.
* The metadata comparison ensure that we fetch all the file id or permission when
* upgrading owncloud
*/
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Reading from database: %s", path);
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Reading from database: %s", fs->path.constData());
ctx->remote.read_from_db = true;
}
/* If it was remembered in the db that the remote dir has ignored files, store
* that so that the reconciler can make advantage of.
*/
if( ctx->current == REMOTE_REPLICA ) {
- st->has_ignored_files = tmp->has_ignored_files;
+ fs->has_ignored_files = tmp->has_ignored_files;
}
if (metadata_differ) {
/* file id or permissions has changed. Which means we need to update them in the DB. */
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Need to update metadata for: %s", path);
- st->instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Need to update metadata for: %s", fs->path.constData());
+ fs->instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
} else {
- st->instruction = CSYNC_INSTRUCTION_NONE;
+ fs->instruction = CSYNC_INSTRUCTION_NONE;
}
} else {
/* check if it's a file and has been renamed */
}
// Default to NEW unless we're sure it's a rename.
- st->instruction = CSYNC_INSTRUCTION_NEW;
+ fs->instruction = CSYNC_INSTRUCTION_NEW;
bool isRename =
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)
+ && _csync_sameextension(tmp->path, fs->path)
#endif
;
// Verify the checksum where possible
if (isRename && !tmp->checksumHeader.isEmpty() && ctx->callbacks.checksum_hook
&& fs->type == CSYNC_FTW_TYPE_FILE) {
- st->checksumHeader = ctx->callbacks.checksum_hook(
- file, tmp->checksumHeader,
- ctx->callbacks.checksum_userdata);
- if (!st->checksumHeader.isEmpty()) {
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "checking checksum of potential rename %s %s <-> %s", path, st->checksumHeader.constData(), tmp->checksumHeader.constData());
- isRename = st->checksumHeader == tmp->checksumHeader;
+ fs->checksumHeader = ctx->callbacks.checksum_hook(
+ _rel_to_abs(ctx, fs->path), tmp->checksumHeader,
+ ctx->callbacks.checksum_userdata);
+ if (!fs->checksumHeader.isEmpty()) {
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "checking checksum of potential rename %s %s <-> %s", fs->path.constData(), fs->checksumHeader.constData(), tmp->checksumHeader.constData());
+ isRename = fs->checksumHeader == tmp->checksumHeader;
}
}
if (isRename) {
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;
+ fs->instruction = CSYNC_INSTRUCTION_EVAL_RENAME;
if (fs->type == CSYNC_FTW_TYPE_DIR) {
- csync_rename_record(ctx, tmp->path, path);
+ csync_rename_record(ctx, tmp->path, fs->path);
}
}
goto out;
if(tmp ) { /* tmp existing at all */
if (tmp->type != fs->type) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "file types different is not!");
- st->instruction = CSYNC_INSTRUCTION_NEW;
+ fs->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;
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "remote rename detected based on fileid %s --> %s", tmp->path.constData(), fs->path.constData());
+ fs->instruction = CSYNC_INSTRUCTION_EVAL_RENAME;
if (fs->type == CSYNC_FTW_TYPE_DIR) {
- csync_rename_record(ctx, tmp->path, path);
+ csync_rename_record(ctx, tmp->path, fs->path);
} else {
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;
+ fs->instruction = CSYNC_INSTRUCTION_NEW;
}
}
goto out;
} else {
/* file not found in statedb */
- st->instruction = CSYNC_INSTRUCTION_NEW;
+ fs->instruction = CSYNC_INSTRUCTION_NEW;
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)) {
+ if (ctx->callbacks.checkSelectiveSyncNewFolderHook(ctx->callbacks.update_callback_userdata, fs->path, fs->remotePerm)) {
return 1;
}
}
out:
/* Set the ignored error string. */
- if (st->instruction == CSYNC_INSTRUCTION_IGNORE) {
- if( type == CSYNC_FTW_TYPE_SLINK ) {
- st->error_status = CSYNC_STATUS_INDIVIDUAL_IS_SYMLINK; /* Symbolic links are ignored. */
+ if (fs->instruction == CSYNC_INSTRUCTION_IGNORE) {
+ if( fs->type == CSYNC_FTW_TYPE_SLINK ) {
+ fs->error_status = CSYNC_STATUS_INDIVIDUAL_IS_SYMLINK; /* Symbolic links are ignored. */
} else {
if (excluded == CSYNC_FILE_EXCLUDE_LIST) {
- st->error_status = CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST; /* File listed on ignore list. */
+ fs->error_status = CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST; /* File listed on ignore list. */
} else if (excluded == CSYNC_FILE_EXCLUDE_INVALID_CHAR) {
- st->error_status = CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS; /* File contains invalid characters. */
+ fs->error_status = CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS; /* File contains invalid characters. */
} else if (excluded == CSYNC_FILE_EXCLUDE_TRAILING_SPACE) {
- st->error_status = CSYNC_STATUS_INDIVIDUAL_TRAILING_SPACE; /* File ends with a trailing space. */
+ fs->error_status = CSYNC_STATUS_INDIVIDUAL_TRAILING_SPACE; /* File ends with a trailing space. */
} else if (excluded == CSYNC_FILE_EXCLUDE_LONG_FILENAME) {
- st->error_status = CSYNC_STATUS_INDIVIDUAL_EXCLUDE_LONG_FILENAME; /* File name is too long. */
+ fs->error_status = CSYNC_STATUS_INDIVIDUAL_EXCLUDE_LONG_FILENAME; /* File name is too long. */
} else if (excluded == CSYNC_FILE_EXCLUDE_HIDDEN ) {
- st->error_status = CSYNC_STATUS_INDIVIDUAL_EXCLUDE_HIDDEN;
+ fs->error_status = CSYNC_STATUS_INDIVIDUAL_EXCLUDE_HIDDEN;
} else if (excluded == CSYNC_FILE_EXCLUDE_STAT_FAILED) {
- st->error_status = CSYNC_STATUS_INDIVIDUAL_STAT_FAILED;
+ fs->error_status = CSYNC_STATUS_INDIVIDUAL_STAT_FAILED;
} else if (excluded == CSYNC_FILE_EXCLUDE_CONFLICT) {
- st->error_status = CSYNC_STATUS_INDIVIDUAL_IS_CONFLICT_FILE;
+ fs->error_status = CSYNC_STATUS_INDIVIDUAL_IS_CONFLICT_FILE;
}
}
}
- if (st->instruction != CSYNC_INSTRUCTION_NONE
- && st->instruction != CSYNC_INSTRUCTION_IGNORE
- && st->instruction != CSYNC_INSTRUCTION_UPDATE_METADATA
- && type != CSYNC_FTW_TYPE_DIR) {
- st->child_modified = true;
+ if (fs->instruction != CSYNC_INSTRUCTION_NONE
+ && fs->instruction != CSYNC_INSTRUCTION_IGNORE
+ && fs->instruction != CSYNC_INSTRUCTION_UPDATE_METADATA
+ && fs->type != CSYNC_FTW_TYPE_DIR) {
+ fs->child_modified = true;
}
- ctx->current_fs = st.get();
-
- st->inode = fs->inode;
- st->size = fs->size;
- st->modtime = fs->modtime;
- st->type = type;
- st->is_hidden = fs->is_hidden;
- st->etag = fs->etag;
- st->file_id = fs->file_id;
- st->directDownloadUrl = fs->directDownloadUrl;
- st->directDownloadCookies = fs->directDownloadCookies;
- st->remotePerm = fs->remotePerm;
-
- // For the remote: propagate the discovered checksum
- if (ctx->current == REMOTE_REPLICA) {
- st->checksumHeader = fs->checksumHeader;
- }
-
- st->phash = h;
- st->path = path;
+ ctx->current_fs = fs.get();
- CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "file: %s, instruction: %s <<=", st->path.constData(),
- csync_instruction_str(st->instruction));
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "file: %s, instruction: %s <<=", fs->path.constData(),
+ csync_instruction_str(fs->instruction));
switch (ctx->current) {
case LOCAL_REPLICA:
- if (c_rbtree_insert(ctx->local.tree, (void *) st.release()) < 0) {
+ if (c_rbtree_insert(ctx->local.tree, (void *) fs.release()) < 0) {
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
return -1;
}
break;
case REMOTE_REPLICA:
- if (c_rbtree_insert(ctx->remote.tree, (void *) st.release()) < 0) {
+ if (c_rbtree_insert(ctx->remote.tree, (void *) fs.release()) < 0) {
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
return -1;
}
return 0;
}
-int csync_walker(CSYNC *ctx, const char *file, const csync_file_stat_t *fs,
- int flag) {
+int csync_walker(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> fs) {
int rc = -1;
- enum csync_ftw_type_e type = CSYNC_FTW_TYPE_SKIP;
- std::unique_ptr<csync_file_stat_t> st;
- uint64_t h;
if (ctx->abort) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Aborted!");
return -1;
}
- switch (flag) {
- case CSYNC_FTW_FLAG_FILE:
+ switch (fs->type) {
+ case CSYNC_FTW_TYPE_FILE:
if (ctx->current == REMOTE_REPLICA) {
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [file_id=%s size=%" PRIu64 "]", file, fs->file_id.constData(), fs->size);
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [file_id=%s size=%" PRIu64 "]", fs->path.constData(), fs->file_id.constData(), fs->size);
} else {
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [inode=%" PRIu64 " size=%" PRIu64 "]", file, fs->inode, fs->size);
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [inode=%" PRIu64 " size=%" PRIu64 "]", fs->path.constData(), fs->inode, fs->size);
}
- type = CSYNC_FTW_TYPE_FILE;
break;
- case CSYNC_FTW_FLAG_DIR: /* enter directory */
+ case CSYNC_FTW_TYPE_DIR: /* enter directory */
if (ctx->current == REMOTE_REPLICA) {
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "directory: %s [file_id=%s]", file, fs->file_id.constData());
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "directory: %s [file_id=%s]", fs->path.constData(), fs->file_id.constData());
} else {
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "directory: %s [inode=%" PRIu64 "]", file, fs->inode);
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "directory: %s [inode=%" PRIu64 "]", fs->path.constData(), fs->inode);
}
- type = CSYNC_FTW_TYPE_DIR;
break;
- case CSYNC_FTW_FLAG_NSTAT: /* not statable file */
- /* if file was here before and now is not longer stat-able, still
- * add it to the db, otherwise not. */
- h = _hash_of_file( ctx, file );
- if( h == 0 ) {
- return 0;
- }
- st = csync_statedb_get_stat_by_hash(ctx, h);
- if( !st ) {
- return 0;
- }
- st.reset();
-
- type = CSYNC_FTW_TYPE_SKIP;
- break;
- case CSYNC_FTW_FLAG_SLINK:
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "symlink: %s - not supported", file);
- type = CSYNC_FTW_TYPE_SLINK;
+ case CSYNC_FTW_TYPE_SLINK:
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "symlink: %s - not supported", fs->path.constData());
break;
- case CSYNC_FTW_FLAG_DNR:
- case CSYNC_FTW_FLAG_DP:
- case CSYNC_FTW_FLAG_SLN:
default:
return 0;
break;
}
- rc = _csync_detect_update(ctx, file, fs, type );
+ rc = _csync_detect_update(ctx, std::move(fs));
return rc;
}
int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
unsigned int depth) {
QByteArray filename;
- QByteArray d_name;
+ QByteArray fullpath;
csync_vio_handle_t *dh = NULL;
std::unique_ptr<csync_file_stat_t> dirent;
csync_file_stat_t *previous_fs = NULL;
int read_from_db = 0;
int rc = 0;
- int res = 0;
bool do_read_from_db = (ctx->current == REMOTE_REPLICA && ctx->remote.read_from_db);
}
while ((dirent = csync_vio_readdir(ctx, dh))) {
- int flag;
-
/* Conversion error */
if (dirent->path.isEmpty() && !dirent->original_path.isEmpty()) {
ctx->status_code = CSYNC_STATUS_INVALID_CHARACTERS;
goto error;
}
- d_name = dirent->path;
- if (d_name.isEmpty()) {
+ // At this point dirent->path only contains the file name.
+ filename = dirent->path;
+ if (filename.isEmpty()) {
ctx->status_code = CSYNC_STATUS_READDIR_ERROR;
goto error;
}
/* skip "." and ".." */
- if ( d_name == "." || d_name == "..") {
- dirent.reset();
+ if ( filename == "." || filename == "..") {
continue;
}
- if (uri[0] == '\0') {
- filename = d_name;
- } else {
- /* For the local replica, dirent->path only contains the file name */
- filename = uri;
- filename += '/';
- filename += d_name;
- }
-
+ fullpath = uri;
+ if (!fullpath.isEmpty())
+ fullpath += '/';
+ fullpath += filename;
/* Only for the local replica we have to stat(), for the remote one we have all data already */
if (ctx->current == LOCAL_REPLICA) {
- res = csync_vio_stat(ctx, filename, dirent.get());
- } else {
- res = 0;
+ if (csync_vio_stat(ctx, fullpath, dirent.get()) != 0) {
+ // Will get excluded by _csync_detect_update.
+ dirent->type = CSYNC_FTW_TYPE_SKIP;
+ }
}
/* if the filename starts with a . we consider it a hidden file
* For windows, the hidden state is also discovered within the vio
* local stat function.
*/
- if( d_name[0] == '.' ) {
- if (d_name == ".sys.admin#recall#") { /* recall file shall not be ignored (#4420) */
+ if( filename[0] == '.' ) {
+ if (filename == ".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_FTW_TYPE_SLINK:
- flag = CSYNC_FTW_FLAG_SLINK;
- break;
- case CSYNC_FTW_TYPE_DIR:
- flag = CSYNC_FTW_FLAG_DIR;
- break;
- case CSYNC_FTW_TYPE_FILE:
- flag = CSYNC_FTW_FLAG_FILE;
- break;
- default:
- break;
- };
+ // Now process to have a relative path to the sync root for the local replica, or to the data root on the remote.
+ dirent->path = fullpath;
+ if (ctx->current == LOCAL_REPLICA) {
+ if (dirent->path.size() <= (int)strlen(ctx->local.uri)) {
+ ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
+ goto error;
+ }
+ // "len + 1" to include the slash in-between.
+ dirent->path = dirent->path.mid(strlen(ctx->local.uri) + 1);
}
+ // We calculate the phash using the relative path.
+ dirent->phash = c_jhash64((const uint8_t*)dirent->path.constData(), dirent->path.size(), 0);
previous_fs = ctx->current_fs;
+ bool recurse = dirent->type == CSYNC_FTW_TYPE_DIR;
/* Call walker function for each file */
- rc = fn(ctx, filename, dirent.get(), flag);
+ rc = fn(ctx, std::move(dirent));
/* this function may update ctx->current and ctx->read_from_db */
if (rc < 0) {
goto error;
}
- if (flag == CSYNC_FTW_FLAG_DIR && rc == 0
+ if (recurse && rc == 0
&& (!ctx->current_fs || ctx->current_fs->instruction != CSYNC_INSTRUCTION_IGNORE)) {
- rc = csync_ftw(ctx, filename, fn, depth - 1);
+ rc = csync_ftw(ctx, fullpath, fn, depth - 1);
if (rc < 0) {
ctx->current_fs = previous_fs;
goto error;
ctx->current_fs = previous_fs;
ctx->remote.read_from_db = read_from_db;
- dirent.reset();
}
csync_vio_closedir(ctx, dh);