mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-26 06:55:59 +03:00
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
8de3bda0b1
.
Issue #1817
This commit is contained in:
parent
26dde9b543
commit
7fad474863
32 changed files with 362 additions and 810 deletions
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -77,7 +77,6 @@ set(csync_SRCS
|
|||
csync_rename.cpp
|
||||
|
||||
vio/csync_vio.cpp
|
||||
vio/csync_vio_file_stat.cpp
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <config_csync.h>
|
||||
#include <memory>
|
||||
#include <QByteArray>
|
||||
|
||||
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_file_stat_t> (*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 );
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "c_lib.h"
|
||||
#include "c_private.h"
|
||||
#include "c_utf8.h"
|
||||
|
||||
#include "csync_private.h"
|
||||
#include "csync_exclude.h"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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<csync_file_stat_t> 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<csync_file_stat_t> 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;
|
||||
break;
|
||||
default:
|
||||
case CSYNC_FTW_TYPE_FILE:
|
||||
flag = CSYNC_FTW_FLAG_FILE;
|
||||
break;
|
||||
default:
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "c_alloc.h"
|
||||
#include "c_path.h"
|
||||
#include "c_string.h"
|
||||
#include "c_utf8.h"
|
||||
|
||||
/*
|
||||
* dirname - parse directory component.
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
/**
|
||||
* }@
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*/
|
||||
|
||||
#include "config_csync.h"
|
||||
#include "c_utf8.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <ctype.h>
|
||||
|
@ -34,31 +35,26 @@
|
|||
#include <QtCore/QFile>
|
||||
#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)
|
||||
{
|
||||
|
|
122
src/csync/std/c_utf8.h
Normal file
122
src/csync/std/c_utf8.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* cynapses libc functions
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* 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 <QByteArray>
|
||||
|
||||
/**
|
||||
* @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 */
|
|
@ -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_file_stat_t> 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) {
|
||||
|
|
|
@ -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_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);
|
||||
|
||||
char *csync_vio_get_status_string(CSYNC *ctx);
|
||||
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<csync_file_stat_t> 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 */
|
||||
|
|
|
@ -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_file_stat_t> 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<csync_file_stat_t> 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;
|
||||
|
|
|
@ -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_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *dhandle) {
|
||||
|
||||
dhandle_t *handle = NULL;
|
||||
csync_vio_file_stat_t *file_stat = NULL;
|
||||
std::unique_ptr<csync_file_stat_t> 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);
|
||||
|
|
|
@ -321,76 +321,50 @@ static QByteArray findBestChecksum(const QByteArray &checksums)
|
|||
return QByteArray();
|
||||
}
|
||||
|
||||
static csync_vio_file_stat_t *propertyMapToFileStat(const QMap<QString, QString> &map)
|
||||
static std::unique_ptr<csync_file_stat_t> propertyMapToFileStat(const QMap<QString, QString> &map)
|
||||
{
|
||||
csync_vio_file_stat_t *file_stat = csync_vio_file_stat_new();
|
||||
std::unique_ptr<csync_file_stat_t> 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<csync_file_stat_t> 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<FileStatPointer> &)),
|
||||
this, SLOT(singleDirectoryJobResultSlot(const QList<FileStatPointer> &)));
|
||||
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<FileStatPointer> &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<FileStatPointer> &)), 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<csync_file_stat_t> DiscoveryJob::remote_vio_readdir_hook(csync_vio_handle_t *dhandle,
|
||||
void *userdata)
|
||||
{
|
||||
DiscoveryJob *discoveryJob = static_cast<DiscoveryJob *>(userdata);
|
||||
if (discoveryJob) {
|
||||
DiscoveryDirectoryResult *directoryResult = static_cast<DiscoveryDirectoryResult *>(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;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
#include <QLinkedList>
|
||||
#include <deque>
|
||||
|
||||
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<FileStatPointer> list;
|
||||
int listIndex;
|
||||
std::deque<std::unique_ptr<csync_file_stat_t>> list;
|
||||
DiscoveryDirectoryResult()
|
||||
: code(EIO)
|
||||
, listIndex(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -138,12 +105,14 @@ public:
|
|||
void setIsRootPath() { _isRootPath = true; }
|
||||
void start();
|
||||
void abort();
|
||||
std::deque<std::unique_ptr<csync_file_stat_t>> &&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<FileStatPointer> &);
|
||||
void finishedWithResult();
|
||||
void finishedWithError(int csyncErrnoCode, const QString &msg);
|
||||
private slots:
|
||||
void directoryListingIteratedSlot(QString, const QMap<QString, QString> &);
|
||||
|
@ -151,7 +120,7 @@ private slots:
|
|||
void lsJobFinishedWithErrorSlot(QNetworkReply *);
|
||||
|
||||
private:
|
||||
QList<FileStatPointer> _results;
|
||||
std::deque<std::unique_ptr<csync_file_stat_t>> _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<FileStatPointer> &);
|
||||
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<csync_file_stat_t> remote_vio_readdir_hook(csync_vio_handle_t *dhandle,
|
||||
void *userdata);
|
||||
static void remote_vio_closedir_hook(csync_vio_handle_t *dhandle,
|
||||
void *userdata);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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})
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 <stdlib.h>
|
||||
#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");
|
||||
|
|
|
@ -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<csync_file_stat_t> create_fstat(const char *name,
|
||||
ino_t inode,
|
||||
time_t mtime)
|
||||
{
|
||||
csync_vio_file_stat_t *fs = NULL;
|
||||
std::unique_ptr<csync_file_stat_t> 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");
|
||||
fs->path = "file.txt";
|
||||
}
|
||||
|
||||
if (fs->name == NULL) {
|
||||
csync_vio_file_stat_destroy(fs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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<csync_file_stat_t> 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<csync_file_stat_t> 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<csync_file_stat_t> 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<csync_file_stat_t> 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<csync_file_stat_t> 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<csync_file_stat_t> 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)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <stdio.h>
|
||||
#include "c_string.h"
|
||||
#include "c_path.h"
|
||||
#include "c_utf8.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <string.h>
|
||||
|
@ -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 */
|
||||
}
|
||||
|
||||
|
|
|
@ -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<csync_file_stat_t> 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);
|
||||
}
|
||||
|
|
|
@ -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<csync_file_stat_t> 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 ? "<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);
|
||||
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
|
Loading…
Reference in a new issue