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>
|
2013-12-11 17:54:34 +04:00
|
|
|
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
|
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
|
|
|
*/
|
|
|
|
|
2014-01-15 15:20:03 +04:00
|
|
|
#include "config_csync.h"
|
2012-03-02 19:47:34 +04:00
|
|
|
|
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 },
|
2013-11-14 20:05:58 +04:00
|
|
|
{ "INSTRUCTION_EVAL_RENAME", CSYNC_INSTRUCTION_EVAL_RENAME },
|
2011-04-12 21:42:08 +04:00
|
|
|
{ "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 },
|
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);
|
|
|
|
}
|
|
|
|
|
2012-12-10 21:58:46 +04:00
|
|
|
void csync_win32_set_file_hidden( const char *file, bool h ) {
|
|
|
|
#ifdef _WIN32
|
2013-08-18 18:43:46 +04:00
|
|
|
const mbchar_t *fileName;
|
2013-07-31 15:12:10 +04:00
|
|
|
DWORD dwAttrs;
|
2012-12-10 21:58:46 +04:00
|
|
|
if( !file ) return;
|
|
|
|
|
2013-08-18 18:43:46 +04:00
|
|
|
fileName = c_utf8_to_locale( file );
|
2013-07-31 15:12:10 +04:00
|
|
|
dwAttrs = GetFileAttributesW(fileName);
|
2012-12-10 21:58:46 +04:00
|
|
|
|
2014-06-20 12:25:00 +04:00
|
|
|
if (dwAttrs != INVALID_FILE_ATTRIBUTES) {
|
|
|
|
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 );
|
|
|
|
}
|
2012-12-10 21:58:46 +04:00
|
|
|
}
|
|
|
|
|
2013-08-18 18:43:46 +04:00
|
|
|
c_free_locale_string(fileName);
|
2012-12-10 21:58:46 +04:00
|
|
|
#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
|
|
|
|
2014-04-28 16:18:58 +04:00
|
|
|
bool (*csync_file_locked_or_open_ext) (const char*) = 0; // filled in by library user
|
2014-05-07 14:38:57 +04:00
|
|
|
void set_csync_file_locked_or_open_ext(bool (*f) (const char*));
|
2014-04-29 20:37:34 +04:00
|
|
|
void set_csync_file_locked_or_open_ext(bool (*f) (const char*)) {
|
|
|
|
csync_file_locked_or_open_ext = f;
|
|
|
|
}
|
|
|
|
|
2014-04-28 18:57:56 +04:00
|
|
|
bool csync_file_locked_or_open( const char *dir, const char *fname) {
|
2014-04-29 14:30:13 +04:00
|
|
|
char *tmp_uri = NULL;
|
|
|
|
bool ret;
|
2014-04-28 18:57:56 +04:00
|
|
|
if (!csync_file_locked_or_open_ext) {
|
2014-04-28 16:18:58 +04:00
|
|
|
return false;
|
2014-04-28 18:57:56 +04:00
|
|
|
}
|
2014-08-12 16:03:04 +04:00
|
|
|
if (asprintf(&tmp_uri, "%s/%s", dir, fname) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
2014-04-29 14:30:13 +04:00
|
|
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "csync_file_locked_or_open %s", tmp_uri);
|
|
|
|
ret = csync_file_locked_or_open_ext(tmp_uri);
|
2014-04-28 18:57:56 +04:00
|
|
|
SAFE_FREE(tmp_uri);
|
|
|
|
return ret;
|
2014-04-28 16:18:58 +04:00
|
|
|
}
|
2015-01-23 19:09:48 +03:00
|
|
|
|
|
|
|
#ifndef HAVE_TIMEGM
|
|
|
|
#ifdef _WIN32
|
|
|
|
static int is_leap(unsigned y) {
|
|
|
|
y += 1900;
|
|
|
|
return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static time_t timegm(struct tm *tm) {
|
|
|
|
static const unsigned ndays[2][12] = {
|
|
|
|
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
|
|
|
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} };
|
|
|
|
|
|
|
|
time_t res = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 70; i < tm->tm_year; ++i)
|
|
|
|
res += is_leap(i) ? 366 : 365;
|
|
|
|
|
|
|
|
for (i = 0; i < tm->tm_mon; ++i)
|
|
|
|
res += ndays[is_leap(tm->tm_year)][i];
|
|
|
|
res += tm->tm_mday - 1;
|
|
|
|
res *= 24;
|
|
|
|
res += tm->tm_hour;
|
|
|
|
res *= 60;
|
|
|
|
res += tm->tm_min;
|
|
|
|
res *= 60;
|
|
|
|
res += tm->tm_sec;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
/* A hopefully portable version of timegm */
|
|
|
|
static time_t timegm(struct tm *tm ) {
|
|
|
|
time_t ret;
|
|
|
|
char *tz;
|
|
|
|
|
|
|
|
tz = getenv("TZ");
|
|
|
|
setenv("TZ", "", 1);
|
|
|
|
tzset();
|
|
|
|
ret = mktime(tm);
|
|
|
|
if (tz)
|
|
|
|
setenv("TZ", tz, 1);
|
|
|
|
else
|
|
|
|
unsetenv("TZ");
|
|
|
|
tzset();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif /* Platform switch */
|
|
|
|
#endif /* HAVE_TIMEGM */
|
|
|
|
|
|
|
|
#define RFC1123_FORMAT "%3s, %02d %3s %4d %02d:%02d:%02d GMT"
|
|
|
|
static const char short_months[12][4] = {
|
|
|
|
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
|
|
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
|
|
|
};
|
|
|
|
/*
|
|
|
|
* This function is borrowed from libneon's ne_httpdate_parse.
|
|
|
|
* Unfortunately that one converts to local time but here UTC is
|
|
|
|
* needed.
|
|
|
|
* This one uses timegm instead, which returns UTC.
|
|
|
|
*/
|
|
|
|
time_t oc_httpdate_parse( const char *date ) {
|
|
|
|
struct tm gmt;
|
|
|
|
char wkday[4], mon[4];
|
|
|
|
int n;
|
|
|
|
time_t result = 0;
|
|
|
|
|
|
|
|
memset(&gmt, 0, sizeof(struct tm));
|
|
|
|
|
|
|
|
/* it goes: Sun, 06 Nov 1994 08:49:37 GMT */
|
|
|
|
n = sscanf(date, RFC1123_FORMAT,
|
|
|
|
wkday, &gmt.tm_mday, mon, &gmt.tm_year, &gmt.tm_hour,
|
|
|
|
&gmt.tm_min, &gmt.tm_sec);
|
|
|
|
/* Is it portable to check n==7 here? */
|
|
|
|
gmt.tm_year -= 1900;
|
|
|
|
for (n=0; n<12; n++)
|
|
|
|
if (strcmp(mon, short_months[n]) == 0)
|
|
|
|
break;
|
|
|
|
/* tm_mon comes out as 12 if the month is corrupt, which is desired,
|
|
|
|
* since the mktime will then fail */
|
|
|
|
gmt.tm_mon = n;
|
|
|
|
gmt.tm_isdst = -1;
|
|
|
|
result = timegm(&gmt);
|
|
|
|
return result;
|
|
|
|
}
|