2008-02-27 20:56:47 +03:00
|
|
|
/*
|
|
|
|
* libcsync -- a library to sync a directory with another
|
|
|
|
*
|
2013-07-23 19:31:55 +04:00
|
|
|
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
|
|
|
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>wie
|
2008-02-27 20:56:47 +03:00
|
|
|
*
|
2013-07-23 19:31:55 +04:00
|
|
|
* 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.
|
2008-02-27 20:56:47 +03:00
|
|
|
*
|
2013-07-23 19:31:55 +04:00
|
|
|
* This library is distributed in the hope that it will be useful,
|
2008-02-27 20:56:47 +03:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2013-07-23 19:31:55 +04:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
2008-02-27 20:56:47 +03:00
|
|
|
*
|
2013-07-23 19:31:55 +04:00
|
|
|
* 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
|
2008-02-27 20:56:47 +03:00
|
|
|
*/
|
|
|
|
|
2012-03-02 19:47:34 +04:00
|
|
|
#include "config.h"
|
|
|
|
|
2008-06-18 15:16:45 +04:00
|
|
|
#ifndef _GNU_SOURCE
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#endif
|
|
|
|
|
2008-07-21 16:31:34 +04:00
|
|
|
#include <errno.h>
|
2009-01-22 16:44:06 +03:00
|
|
|
#include <limits.h>
|
2008-06-18 15:16:45 +04:00
|
|
|
#include <stdio.h>
|
|
|
|
|
2009-01-22 16:44:06 +03:00
|
|
|
#include "c_jhash.h"
|
2008-02-27 20:56:47 +03:00
|
|
|
#include "csync_util.h"
|
2008-06-18 15:16:45 +04:00
|
|
|
#include "vio/csync_vio.h"
|
2008-02-27 20:56:47 +03:00
|
|
|
|
2008-04-28 18:47:35 +04:00
|
|
|
#define CSYNC_LOG_CATEGORY_NAME "csync.util"
|
|
|
|
#include "csync_log.h"
|
2013-07-03 00:58:50 +04:00
|
|
|
#include "csync_statedb.h"
|
2008-04-28 18:47:35 +04:00
|
|
|
|
2008-04-30 18:22:48 +04:00
|
|
|
typedef struct {
|
|
|
|
const char *instr_str;
|
|
|
|
enum csync_instructions_e instr_code;
|
|
|
|
} _instr_code_struct;
|
|
|
|
|
|
|
|
static const _instr_code_struct _instr[] =
|
|
|
|
{
|
2011-04-12 21:42:08 +04:00
|
|
|
{ "INSTRUCTION_NONE", CSYNC_INSTRUCTION_NONE },
|
|
|
|
{ "INSTRUCTION_EVAL", CSYNC_INSTRUCTION_EVAL },
|
|
|
|
{ "INSTRUCTION_REMOVE", CSYNC_INSTRUCTION_REMOVE },
|
|
|
|
{ "INSTRUCTION_RENAME", CSYNC_INSTRUCTION_RENAME },
|
|
|
|
{ "INSTRUCTION_NEW", CSYNC_INSTRUCTION_NEW },
|
2011-04-12 19:09:39 +04:00
|
|
|
{ "INSTRUCTION_CONFLICT", CSYNC_INSTRUCTION_CONFLICT },
|
2011-04-12 21:42:08 +04:00
|
|
|
{ "INSTRUCTION_IGNORE", CSYNC_INSTRUCTION_IGNORE },
|
|
|
|
{ "INSTRUCTION_SYNC", CSYNC_INSTRUCTION_SYNC },
|
2011-04-12 19:09:39 +04:00
|
|
|
{ "INSTRUCTION_STAT_ERR", CSYNC_INSTRUCTION_STAT_ERROR },
|
2011-04-12 21:42:08 +04:00
|
|
|
{ "INSTRUCTION_ERROR", CSYNC_INSTRUCTION_ERROR },
|
|
|
|
{ "INSTRUCTION_DELETED", CSYNC_INSTRUCTION_DELETED },
|
|
|
|
{ "INSTRUCTION_UPDATED", CSYNC_INSTRUCTION_UPDATED },
|
2008-04-30 18:22:48 +04:00
|
|
|
{ NULL, CSYNC_INSTRUCTION_ERROR }
|
|
|
|
};
|
|
|
|
|
2008-04-28 18:47:35 +04:00
|
|
|
struct csync_memstat_s {
|
|
|
|
int size;
|
|
|
|
int resident;
|
|
|
|
int shared;
|
|
|
|
int trs;
|
|
|
|
int drs;
|
|
|
|
int lrs;
|
|
|
|
int dt;
|
|
|
|
};
|
|
|
|
|
2008-04-30 18:22:48 +04:00
|
|
|
const char *csync_instruction_str(enum csync_instructions_e instr)
|
|
|
|
{
|
|
|
|
int idx = 0;
|
|
|
|
|
|
|
|
while (_instr[idx].instr_str != NULL) {
|
|
|
|
if (_instr[idx].instr_code == instr) {
|
|
|
|
return _instr[idx].instr_str;
|
|
|
|
}
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return "ERROR!";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-01 12:59:55 +04:00
|
|
|
void csync_memstat_check(void) {
|
2008-05-08 18:16:55 +04:00
|
|
|
int s = 0;
|
2008-04-28 18:47:35 +04:00
|
|
|
struct csync_memstat_s m;
|
|
|
|
FILE* fp;
|
|
|
|
|
|
|
|
/* get process memory stats */
|
|
|
|
fp = fopen("/proc/self/statm","r");
|
|
|
|
if (fp == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
2008-05-08 18:16:55 +04:00
|
|
|
s = fscanf(fp, "%d%d%d%d%d%d%d", &m.size, &m.resident, &m.shared, &m.trs,
|
2008-04-28 18:47:35 +04:00
|
|
|
&m.drs, &m.lrs, &m.dt);
|
|
|
|
fclose(fp);
|
2008-05-08 18:16:55 +04:00
|
|
|
if (s == EOF) {
|
|
|
|
return;
|
|
|
|
}
|
2008-04-28 18:47:35 +04:00
|
|
|
|
|
|
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "Memory: %dK total size, %dK resident, %dK shared",
|
|
|
|
m.size * 4, m.resident * 4, m.shared * 4);
|
|
|
|
}
|
|
|
|
|
2008-06-18 15:16:45 +04:00
|
|
|
static int _merge_file_trees_visitor(void *obj, void *data) {
|
|
|
|
csync_file_stat_t *fs = NULL;
|
2012-08-17 17:48:15 +04:00
|
|
|
csync_file_stat_t *tfs = NULL;
|
2008-06-18 15:16:45 +04:00
|
|
|
csync_vio_file_stat_t *vst = NULL;
|
|
|
|
|
|
|
|
CSYNC *ctx = NULL;
|
2008-06-28 19:18:10 +04:00
|
|
|
c_rbtree_t *tree = NULL;
|
2008-06-18 15:16:45 +04:00
|
|
|
c_rbnode_t *node = NULL;
|
|
|
|
|
2008-07-21 16:31:34 +04:00
|
|
|
char errbuf[256] = {0};
|
2008-06-18 15:16:45 +04:00
|
|
|
char *uri = NULL;
|
|
|
|
int rc = -1;
|
|
|
|
|
|
|
|
fs = (csync_file_stat_t *) obj;
|
|
|
|
ctx = (CSYNC *) data;
|
|
|
|
|
|
|
|
/* search for UPDATED file */
|
2013-04-17 18:25:52 +04:00
|
|
|
if (fs->instruction != CSYNC_INSTRUCTION_UPDATED && !fs->should_update_md5) {
|
2008-06-18 15:16:45 +04:00
|
|
|
rc = 0;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2008-06-28 19:18:10 +04:00
|
|
|
switch (ctx->current) {
|
|
|
|
case LOCAL_REPLICA:
|
|
|
|
tree = ctx->local.tree;
|
|
|
|
break;
|
2012-10-19 16:23:20 +04:00
|
|
|
case REMOTE_REPLICA:
|
2008-06-28 19:18:10 +04:00
|
|
|
tree = ctx->remote.tree;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-06-18 15:16:45 +04:00
|
|
|
/* check if the file is new or has been synced */
|
2008-06-28 19:18:10 +04:00
|
|
|
node = c_rbtree_find(tree, &fs->phash);
|
2008-06-18 15:16:45 +04:00
|
|
|
if (node == NULL) {
|
2013-03-21 00:55:34 +04:00
|
|
|
csync_file_stat_t *new_stat = NULL;
|
2008-06-18 15:16:45 +04:00
|
|
|
|
2013-03-21 00:55:34 +04:00
|
|
|
new_stat = c_malloc(sizeof(csync_file_stat_t) + fs->pathlen + 1);
|
|
|
|
if (new_stat == NULL) {
|
2013-08-02 17:19:41 +04:00
|
|
|
C_STRERROR(errno, errbuf, sizeof(errbuf));
|
2008-07-21 16:31:34 +04:00
|
|
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
|
|
|
|
"file: %s, merge malloc, error: %s",
|
|
|
|
fs->path,
|
2012-03-07 19:42:42 +04:00
|
|
|
errbuf);
|
2008-06-18 15:16:45 +04:00
|
|
|
rc = -1;
|
|
|
|
goto out;
|
|
|
|
}
|
2013-03-21 00:55:34 +04:00
|
|
|
new_stat = memcpy(new_stat, fs, sizeof(csync_file_stat_t) + fs->pathlen + 1);
|
2012-10-30 15:00:51 +04:00
|
|
|
if (fs->md5)
|
2013-03-21 00:55:34 +04:00
|
|
|
new_stat->md5 = c_strdup(fs->md5);
|
2012-10-30 15:00:51 +04:00
|
|
|
if (fs->destpath)
|
2013-03-21 00:55:34 +04:00
|
|
|
new_stat->destpath = c_strdup(fs->destpath);
|
2013-04-24 16:53:09 +04:00
|
|
|
if (fs->error_string)
|
2013-05-07 17:20:22 +04:00
|
|
|
new_stat->error_string = c_strdup(fs->error_string);
|
2008-06-18 15:16:45 +04:00
|
|
|
|
2013-03-21 00:55:34 +04:00
|
|
|
if (c_rbtree_insert(tree, new_stat) < 0) {
|
2013-08-02 17:19:41 +04:00
|
|
|
C_STRERROR(errno, errbuf, sizeof(errbuf));
|
2013-03-21 00:55:34 +04:00
|
|
|
SAFE_FREE(new_stat);
|
2008-07-21 16:31:34 +04:00
|
|
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
|
|
|
|
"file: %s, rb tree insert, error: %s",
|
|
|
|
fs->path,
|
2012-03-07 19:42:42 +04:00
|
|
|
errbuf);
|
2008-06-18 15:16:45 +04:00
|
|
|
rc = -1;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2008-06-28 19:18:10 +04:00
|
|
|
node = c_rbtree_find(tree, &fs->phash);
|
2008-06-18 15:16:45 +04:00
|
|
|
if (node == NULL) {
|
|
|
|
rc = -1;
|
2008-07-21 16:31:34 +04:00
|
|
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Unable to find node");
|
2008-06-18 15:16:45 +04:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fs = c_rbtree_node_data(node);
|
|
|
|
|
|
|
|
switch (ctx->current) {
|
2012-09-24 16:57:32 +04:00
|
|
|
case LOCAL_REPLICA:
|
|
|
|
/* If there is a destpath, this is a rename and the target must be used. */
|
|
|
|
if( fs->destpath ) {
|
2013-08-02 17:19:41 +04:00
|
|
|
if (asprintf(&uri, "%s/%s", ctx->local.uri, fs->destpath) < 0) {
|
|
|
|
rc = -1;
|
|
|
|
C_STRERROR(errno, errbuf, sizeof(errbuf));
|
|
|
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file uri alloc failed: %s",
|
|
|
|
errbuf);
|
|
|
|
SAFE_FREE(fs->destpath);
|
|
|
|
goto out;
|
|
|
|
}
|
2012-09-24 16:57:32 +04:00
|
|
|
SAFE_FREE(fs->destpath);
|
|
|
|
} else {
|
|
|
|
if (asprintf(&uri, "%s/%s", ctx->local.uri, fs->path) < 0) {
|
|
|
|
rc = -1;
|
2013-08-02 17:19:41 +04:00
|
|
|
C_STRERROR(errno, errbuf, sizeof(errbuf));
|
2012-09-24 16:57:32 +04:00
|
|
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file uri alloc failed: %s",
|
|
|
|
errbuf);
|
|
|
|
goto out;
|
|
|
|
}
|
2008-06-18 15:16:45 +04:00
|
|
|
}
|
|
|
|
break;
|
2012-10-19 16:23:20 +04:00
|
|
|
case REMOTE_REPLICA:
|
2008-06-18 15:16:45 +04:00
|
|
|
if (asprintf(&uri, "%s/%s", ctx->remote.uri, fs->path) < 0) {
|
2012-09-24 16:57:32 +04:00
|
|
|
rc = -1;
|
2013-08-02 17:19:41 +04:00
|
|
|
C_STRERROR(errno, errbuf, sizeof(errbuf));
|
2012-09-24 16:57:32 +04:00
|
|
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file uri alloc failed: %s",
|
|
|
|
errbuf);
|
|
|
|
goto out;
|
2008-06-18 15:16:45 +04:00
|
|
|
}
|
|
|
|
break;
|
2012-09-24 16:57:32 +04:00
|
|
|
default:
|
2008-06-18 15:16:45 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-06-28 19:18:10 +04:00
|
|
|
/* get file stat of the file on the replica */
|
2008-06-18 15:16:45 +04:00
|
|
|
vst = csync_vio_file_stat_new();
|
|
|
|
if (csync_vio_stat(ctx, uri, vst) < 0) {
|
2013-08-02 17:19:41 +04:00
|
|
|
C_STRERROR(errno, errbuf, sizeof(errbuf));
|
2008-07-21 16:31:34 +04:00
|
|
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
|
|
|
|
"file: %s, updating stat failed, error: %s",
|
|
|
|
uri,
|
2012-03-07 19:42:42 +04:00
|
|
|
errbuf);
|
2008-06-18 15:16:45 +04:00
|
|
|
|
2012-12-15 20:45:11 +04:00
|
|
|
/* Not a fatal error, since it is better to have outdated information than no information */
|
|
|
|
} else {
|
|
|
|
/* update file stat */
|
|
|
|
fs->inode = vst->inode;
|
|
|
|
fs->modtime = vst->mtime;
|
|
|
|
}
|
2008-06-18 15:16:45 +04:00
|
|
|
|
2012-09-24 16:57:32 +04:00
|
|
|
/* update with the id from the remote repo. This method always works on the local repo */
|
2012-08-17 17:48:15 +04:00
|
|
|
node = c_rbtree_find(ctx->remote.tree, &fs->phash);
|
|
|
|
if (node == NULL) {
|
2012-09-24 16:57:32 +04:00
|
|
|
rc = -1;
|
|
|
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Unable to find node");
|
|
|
|
goto out;
|
2012-08-17 17:48:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
tfs = c_rbtree_node_data(node);
|
2012-09-24 16:57:32 +04:00
|
|
|
if( tfs && tfs->md5 ) {
|
2012-08-30 14:04:48 +04:00
|
|
|
if( fs->md5 ) SAFE_FREE(fs->md5);
|
2012-09-24 16:57:32 +04:00
|
|
|
fs->md5 = c_strdup( tfs->md5 );
|
2012-09-26 17:32:38 +04:00
|
|
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "PRE UPDATED %s: %s", fs->path, fs->md5);
|
2012-08-20 20:11:46 +04:00
|
|
|
} else {
|
2012-09-24 16:57:32 +04:00
|
|
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "md5 is empty in merger!");
|
2012-08-20 20:11:46 +04:00
|
|
|
}
|
2012-09-24 16:57:32 +04:00
|
|
|
|
2012-08-17 17:48:15 +04:00
|
|
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "file: %s, instruction: UPDATED (%s)", uri, fs->md5);
|
2008-06-18 15:16:45 +04:00
|
|
|
|
2013-07-15 17:30:40 +04:00
|
|
|
if (fs->instruction != CSYNC_INSTRUCTION_ERROR) {
|
|
|
|
fs->instruction = CSYNC_INSTRUCTION_NONE;
|
|
|
|
}
|
2008-06-28 19:18:10 +04:00
|
|
|
|
2008-06-18 15:16:45 +04:00
|
|
|
rc = 0;
|
|
|
|
out:
|
|
|
|
csync_vio_file_stat_destroy(vst);
|
|
|
|
SAFE_FREE(uri);
|
|
|
|
|
2008-06-28 19:18:10 +04:00
|
|
|
if (rc != 0) {
|
|
|
|
fs->instruction = CSYNC_INSTRUCTION_ERROR;
|
|
|
|
}
|
|
|
|
|
2008-06-18 15:16:45 +04:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2013-07-03 00:58:50 +04:00
|
|
|
static int _fix_errors_visitor(void *obj, void *data) {
|
|
|
|
csync_file_stat_t *fs = NULL;
|
|
|
|
csync_file_stat_t *tfs = NULL;
|
|
|
|
|
|
|
|
CSYNC *ctx = NULL;
|
|
|
|
|
|
|
|
int rc = -1;
|
|
|
|
|
|
|
|
fs = (csync_file_stat_t *) obj;
|
|
|
|
ctx = (CSYNC *) data;
|
|
|
|
|
|
|
|
/* search for ERROR */
|
2013-07-15 12:46:33 +04:00
|
|
|
if (fs->instruction != CSYNC_INSTRUCTION_ERROR
|
|
|
|
|| fs->type == CSYNC_FTW_TYPE_DIR) {
|
2013-07-03 00:58:50 +04:00
|
|
|
rc = 0;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check if the file is new or has been synced */
|
|
|
|
tfs = csync_statedb_get_stat_by_hash(ctx, fs->phash);
|
|
|
|
if (tfs == NULL) {
|
|
|
|
rc = 0;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* update file stat */
|
|
|
|
fs->inode = tfs->inode;
|
|
|
|
fs->modtime = tfs->modtime;
|
|
|
|
|
|
|
|
fs->instruction = CSYNC_INSTRUCTION_UPDATED;
|
|
|
|
|
|
|
|
rc = 0;
|
|
|
|
out:
|
|
|
|
csync_file_stat_free(tfs);
|
|
|
|
|
|
|
|
if (rc != 0) {
|
|
|
|
fs->instruction = CSYNC_INSTRUCTION_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-18 15:16:45 +04:00
|
|
|
/*
|
|
|
|
* merge the local tree with the new files from remote and update the
|
|
|
|
* inode numbers
|
|
|
|
*/
|
|
|
|
int csync_merge_file_trees(CSYNC *ctx) {
|
|
|
|
int rc = -1;
|
|
|
|
|
2013-07-03 00:58:50 +04:00
|
|
|
/* walk over the local tree, in case of error take the value from the database */
|
|
|
|
ctx->current = REMOTE_REPLICA;
|
|
|
|
ctx->replica = ctx->remote.type;
|
2008-06-18 15:16:45 +04:00
|
|
|
|
2013-07-03 00:58:50 +04:00
|
|
|
rc = c_rbtree_walk(ctx->local.tree, ctx, _fix_errors_visitor);
|
2008-06-18 15:16:45 +04:00
|
|
|
if (rc < 0) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2013-07-03 00:58:50 +04:00
|
|
|
/* walk over remote tree, stat on local system */
|
|
|
|
ctx->current = LOCAL_REPLICA;
|
|
|
|
ctx->replica = ctx->local.type;
|
2008-06-18 15:16:45 +04:00
|
|
|
|
2013-07-03 00:58:50 +04:00
|
|
|
rc = c_rbtree_walk(ctx->remote.tree, ctx, _merge_file_trees_visitor);
|
2008-06-18 15:16:45 +04:00
|
|
|
if (rc < 0) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
out:
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2009-01-19 13:32:58 +03:00
|
|
|
int csync_unix_extensions(CSYNC *ctx) {
|
2009-01-13 17:50:44 +03:00
|
|
|
int rc = -1;
|
|
|
|
char *uri = NULL;
|
|
|
|
csync_vio_handle_t *fp = NULL;
|
|
|
|
|
2009-01-19 13:32:58 +03:00
|
|
|
ctx->options.unix_extensions = 0;
|
2009-01-13 17:50:44 +03:00
|
|
|
|
2012-02-22 19:18:07 +04:00
|
|
|
rc = asprintf(&uri, "%s/csync_unix_extension*test.ctmp", ctx->remote.uri);
|
|
|
|
if (rc < 0) {
|
2009-01-13 17:50:44 +03:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx->replica = ctx->remote.type;
|
|
|
|
fp = csync_vio_creat(ctx, uri, 0644);
|
|
|
|
if (fp == NULL) {
|
|
|
|
rc = 0;
|
|
|
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO,
|
|
|
|
"Disabled unix filesystem synchronization");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
csync_vio_close(ctx, fp);
|
|
|
|
|
2009-01-19 13:32:58 +03:00
|
|
|
ctx->options.unix_extensions = 1;
|
2009-01-13 17:50:44 +03:00
|
|
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "Enabled unix filesystem synchronization");
|
|
|
|
|
|
|
|
rc = 1;
|
|
|
|
|
|
|
|
out:
|
|
|
|
csync_vio_unlink(ctx, uri);
|
|
|
|
SAFE_FREE(uri);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
2012-12-10 21:58:46 +04:00
|
|
|
|
|
|
|
void csync_win32_set_file_hidden( const char *file, bool h ) {
|
|
|
|
#ifdef _WIN32
|
|
|
|
const _TCHAR *fileName;
|
2013-07-31 15:12:10 +04:00
|
|
|
DWORD dwAttrs;
|
2012-12-10 21:58:46 +04:00
|
|
|
if( !file ) return;
|
|
|
|
|
|
|
|
fileName = c_multibyte( file );
|
2013-07-31 15:12:10 +04:00
|
|
|
dwAttrs = GetFileAttributesW(fileName);
|
2012-12-10 21:58:46 +04:00
|
|
|
|
|
|
|
if (dwAttrs==INVALID_FILE_ATTRIBUTES) return;
|
|
|
|
|
|
|
|
if (h && !(dwAttrs & FILE_ATTRIBUTE_HIDDEN)) {
|
|
|
|
SetFileAttributesW(fileName, dwAttrs | FILE_ATTRIBUTE_HIDDEN );
|
|
|
|
} else if (!h && (dwAttrs & FILE_ATTRIBUTE_HIDDEN)) {
|
|
|
|
SetFileAttributesW(fileName, dwAttrs & ~FILE_ATTRIBUTE_HIDDEN );
|
|
|
|
}
|
|
|
|
|
|
|
|
c_free_multibyte(fileName);
|
|
|
|
#else
|
2012-12-14 19:48:05 +04:00
|
|
|
(void) h;
|
2012-12-10 21:58:46 +04:00
|
|
|
(void) file;
|
|
|
|
#endif
|
2012-12-12 16:51:54 +04:00
|
|
|
}
|
2013-08-18 18:21:18 +04:00
|
|
|
|
2013-07-04 12:39:59 +04:00
|
|
|
csync_vio_file_stat_t *csync_vio_convert_file_stat(csync_file_stat_t *st) {
|
|
|
|
csync_vio_file_stat_t *vfs = NULL;
|
|
|
|
|
|
|
|
if (st == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
vfs = csync_vio_file_stat_new();
|
|
|
|
if (vfs == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
vfs->acl = NULL;
|
|
|
|
if (st->pathlen > 0) {
|
|
|
|
vfs->name = c_strdup(st->path);
|
|
|
|
}
|
|
|
|
vfs->uid = st->uid;
|
|
|
|
vfs->gid = st->gid;
|
|
|
|
|
|
|
|
vfs->atime = 0;
|
|
|
|
vfs->mtime = st->modtime;
|
|
|
|
vfs->ctime = 0;
|
|
|
|
|
|
|
|
vfs->size = st->size;
|
|
|
|
vfs->blksize = 0; /* Depricated. */
|
|
|
|
vfs->blkcount = 0;
|
|
|
|
|
|
|
|
vfs->mode = st->mode;
|
|
|
|
vfs->device = 0;
|
|
|
|
vfs->inode = st->inode;
|
|
|
|
vfs->nlink = st->nlink;
|
|
|
|
|
|
|
|
/* fields. */
|
|
|
|
vfs->fields = CSYNC_VIO_FILE_STAT_FIELDS_TYPE
|
|
|
|
+ CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS
|
|
|
|
+ CSYNC_VIO_FILE_STAT_FIELDS_INODE
|
|
|
|
+ CSYNC_VIO_FILE_STAT_FIELDS_LINK_COUNT
|
|
|
|
+ CSYNC_VIO_FILE_STAT_FIELDS_SIZE
|
|
|
|
+ CSYNC_VIO_FILE_STAT_FIELDS_MTIME
|
|
|
|
+ CSYNC_VIO_FILE_STAT_FIELDS_UID
|
|
|
|
+ CSYNC_VIO_FILE_STAT_FIELDS_GID;
|
|
|
|
|
|
|
|
if (st->type == CSYNC_FTW_TYPE_DIR)
|
|
|
|
vfs->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
|
|
|
|
else if (st->type == CSYNC_FTW_TYPE_FILE)
|
|
|
|
vfs->type = CSYNC_VIO_FILE_TYPE_REGULAR;
|
|
|
|
else if (st->type == CSYNC_FTW_TYPE_SLINK)
|
|
|
|
vfs->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
|
|
|
|
else
|
|
|
|
vfs->type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
|
|
|
|
|
|
|
|
return vfs;
|
|
|
|
}
|