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:
Jocelyn Turcotte 2017-09-05 16:12:32 +02:00 committed by Roeland Jago Douma
parent 26dde9b543
commit 7fad474863
No known key found for this signature in database
GPG key ID: F941078878347C0C
32 changed files with 362 additions and 810 deletions

View file

@ -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();

View file

@ -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
*

View file

@ -77,7 +77,6 @@ set(csync_SRCS
csync_rename.cpp
vio/csync_vio.cpp
vio/csync_vio_file_stat.cpp
)
if (WIN32)

View file

@ -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 );
/**

View file

@ -31,6 +31,7 @@
#include "c_lib.h"
#include "c_private.h"
#include "c_utf8.h"
#include "csync_private.h"
#include "csync_exclude.h"

View file

@ -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;
}

View file

@ -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"

View file

@ -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;
}

View file

@ -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.

View file

@ -33,6 +33,7 @@
#include "c_alloc.h"
#include "c_path.h"
#include "c_string.h"
#include "c_utf8.h"
/*
* dirname - parse directory component.

View file

@ -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)
/**
* }@
*/

View file

@ -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;

View file

@ -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
View 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 */

View file

@ -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) {

View file

@ -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);

View file

@ -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);
}
}
}

View file

@ -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 */

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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})

View file

@ -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;

View file

@ -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");

View file

@ -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)

View file

@ -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 */
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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);
}