switch ...  
Commits (287)
Showing 78 changed files with 2533 additions and 340 deletions
... ... @@ -54,7 +54,7 @@ PROJECT_LOGO =
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = doc
OUTPUT_DIRECTORY = doc/doxygen
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
... ...
... ... @@ -54,6 +54,7 @@ tmp
/config.log
/config.status
/config.sub
/config.cache
/configure
/depcomp
/examples/Makefile
... ...
... ... @@ -22,7 +22,7 @@ build_test() {
$MAKE clean
echo ">>> Testing with \"$@\""
# make sure we test paralled build as they tend to fail when single works
./configure $@ && $MAKE -j5 || {
./configure -C $@ >/dev/null || rm -f config.cache && ./configure -C $@ >/dev/null && $MAKE -j5 >/dev/null || {
echo "!!! test with \"$@\" configure options failed"
exit 1
}
... ... @@ -41,7 +41,7 @@ run_example_cleanup_failure() {
# Run example script
run_example() {
MODE="$1"
MODE="$1"; shift;
export CLSYNC_PIDFILE="/tmp/clsync-example-$MODE.pid"
... ... @@ -50,7 +50,7 @@ run_example() {
trap run_example_cleanup_failure INT TERM
cd examples
bash -x clsync-start-"$MODE".sh --background --pid-file "$CLSYNC_PIDFILE" --config-file '/NULL/' -w1 -t1 -d1
bash -x clsync-start-"$MODE".sh --background --pid-file "$CLSYNC_PIDFILE" --config-file '/NULL/' -w1 -t1 -d9 $@
cd -
sleep 1
... ... @@ -108,9 +108,15 @@ if true; then
for a3 in "--enable-paranoid=0" "--enable-paranoid=1" "--enable-paranoid=2" ; do
for a4 in "--with-capabilities" "--without-capabilities"; do
for a5 in "--enable-socket" "--disable-socket"; do
for a6 in "--enable-libclsync" "--disable-libclsync"; do
arg="$a0 $a1 $a2 $a3 $a4 $a5 $a6"
for a6 in "--enable-socket-library" "--disable-socket-library"; do
for a7 in "--enable-highload-locks" ""; do
for a8 in "--with-libcgroup" "--without-libcgroup"; do
# for a9 in "--with-libseccomp" "--without-libseccomp"; do
arg="$a0 $a1 $a2 $a3 $a4 $a5 $a6 $a7 $a8 $a9"
build_test "$arg"
# done
done
done
done
done
done
... ... @@ -119,7 +125,7 @@ if true; then
done
# clsync disabled, libclsync enabled
a0="--disable-clsync --enable-libclsync"
a0="--disable-clsync --enable-socket-library"
for a2 in "--enable-debug" "--disable-debug"; do
for a3 in "--enable-paranoid=0" "--enable-paranoid=1" "--enable-paranoid=2" ; do
arg="$a0 $a1 $a2"
... ... @@ -128,7 +134,7 @@ if true; then
done
# clsync disabled, libclsync disabled
build_test "--disable-clsync --disable-libclsync"
build_test "--disable-clsync --disable-socket-library"
fi
... ... @@ -139,6 +145,7 @@ if true; then
export CFLAGS="$CFLAGS --coverage -O0"
export PATH="$(pwd):$PATH"
build_test --enable-cluster --enable-debug --enable-paranoid=2 --with-capabilities --without-mhash
run_example rsyncdirect --thread-splitting
run_example rsyncdirect
run_example rsyncshell
# run_example rsyncso
... ...
language: c
before_install:
- sudo apt-get install libcap-dev libglib2.0-dev libmhash-dev libkqueue.*
- sudo apt-get update
- sudo apt-get install libcap-dev libglib2.0-dev libmhash-dev libkqueue.* libcgroup-dev libseccomp-dev linux-libc-dev libkqueue-dev
- sudo pip install cpp-coveralls --use-mirrors
script:
- ./.travis.sh
... ...
... ... @@ -5,36 +5,71 @@ if CLSYNC
bin_PROGRAMS = clsync
clsync_SOURCES = calc.c cluster.c error.c fileutils.c glibex.c \
indexes.c main.c malloc.c sync.c calc.h cluster.h fileutils.h \
glibex.h main.h port-hacks.h sync.h common.h control.h
indexes.c main.c malloc.c rules.c stringex.c sync.c \
posix-hacks.c privileged.c pthreadex.c calc.h cluster.h \
fileutils.h glibex.h main.h port-hacks.h posix-hacks.h \
pthreadex.h stringex.h sync.h common.h control.h privileged.h \
rules.h syscalls.h
clsync_CFLAGS = $(AM_CFLAGS)
clsync_CFLAGS = $(AM_CFLAGS)
clsync_LDFLAGS = $(AM_LDFLAGS)
if HAVE_KQUEUE
clsync_CFLAGS += -DKQUEUE_SUPPORT
clsync_CFLAGS += -DKQUEUE_SUPPORT
clsync_SOURCES += mon_kqueue.c mon_kqueue.h
endif
if HAVE_INOTIFY
clsync_CFLAGS += -DINOTIFY_SUPPORT
clsync_CFLAGS += -DINOTIFY_SUPPORT
clsync_SOURCES += mon_inotify.c mon_inotify.h
if INOTIFY_OLD
clsync_CFLAGS += -DINOTIFY_OLD
clsync_CFLAGS += -DINOTIFY_OLD
endif
endif
if HAVE_FANOTIFY
clsync_CFLAGS += -DFANOTIFY_SUPPORT
clsync_CFLAGS += -DFANOTIFY_SUPPORT
clsync_SOURCES += mon_fanotify.c mon_fanotify.h
endif
if HAVE_BSM
clsync_CFLAGS += -DBSM_SUPPORT
clsync_CFLAGS += -DBSM_SUPPORT
clsync_SOURCES += mon_bsm.c mon_bsm.h
endif
if HAVE_GIO
clsync_CFLAGS += -DGIO_SUPPORT $(GIO_CFLAGS)
clsync_LDFLAGS += $(GIO_LIBS)
clsync_SOURCES += mon_gio.c mon_gio.h
endif
if HAVE_DTRACEPIPE
clsync_CFLAGS += -DDTRACEPIPE_SUPPORT
clsync_CFLAGS += -DDTRACEPIPE_SUPPORT
clsync_SOURCES += mon_dtracepipe.c mon_dtracepipe.h
endif
if HAVE_BACKTRACE
clsync_CFLAGS += -DBACKTRACE_SUPPORT
clsync_CFLAGS += -DBACKTRACE_SUPPORT
endif
if HAVE_CAPABILITIES
clsync_CFLAGS += -DCAPABILITIES_SUPPORT
if HAVE_SECCOMP
clsync_CFLAGS += -DSECCOMP_SUPPORT
endif
endif
if HAVE_GETMNTENT
clsync_CFLAGS += -DGETMNTENT_SUPPORT
endif
if HAVE_UNSHARE
clsync_CFLAGS += -DUNSHARE_SUPPORT
if HAVE_PIVOTROOT
clsync_CFLAGS += -DPIVOTROOT_OPT_SUPPORT
endif
endif
if HAVE_TRE
clsync_CFLAGS += -DTRE_SUPPORT
endif
if HAVE_LIBCGROUP
clsync_CFLAGS += -DCGROUP_SUPPORT
clsync_SOURCES += cgroup.c cgroup.h
endif
if HLLOCKS
clsync_CFLAGS += -DHL_LOCKS
endif
if SOCKET
... ... @@ -52,7 +87,7 @@ EXTRA_DIST = .doxygen .travis.sh .travis.yml NOTES SHORTHANDS freebsd debian gen
if LIBCLSYNC
lib_LTLIBRARIES = libclsync.la
libclsync_la_SOURCES = malloc.c libclsync.c socket.c
libclsync_la_SOURCES = malloc.c libclsync.c socket.c error.c
libclsync_la_LDFLAGS = -version-info 0:0:0
endif
... ... @@ -103,5 +138,5 @@ CLEANFILES = revision.h
if CLSYNC
CLEANFILES += examples/rules
clean-local:
-rm -rf examples/testdir examples/*.o examples/*.so examples/*.xz doc
-rm -rf examples/testdir examples/*.o examples/*.so examples/*.xz doc/doxygen
endif
... ...
... ... @@ -5,19 +5,19 @@ broadcast: dst_node_id == NOID
session example of two nodes (A and B):
A appears (getting node_id):
"A" appears (getting node_id):
A -> getmyid (serial: 0; src: NOID ; dst: NOID; name: A) | cluster_init()
A -> hello (serial: 0; src: NOID ; dst: NOID; name: A) | cluster_init()
A -> register (serial: 1; src: 0 ; dst: NOID; name: A) |
Trying to sync with somebody:
A -> updtree (serial: 2; src: 0 ; dst: NOID; [A modtree])
B appears (getting node_id):
"B" appears (getting node_id):
B -> getmyid (serial: 0; src: NOID ; dst: NOID; name: B) | cluster_init()
A -> setid (serial: 3; src: 0 ; dst: NOID; name: A; updatets: 100)
B -> hello (serial: 0; src: NOID ; dst: NOID; name: B) | cluster_init()
A -> welcome (serial: 3; src: 0 ; dst: NOID; my_name: A; to_name: B)
B -> register (serial: 1; src: 1 : dst: NOID; name: B) |
A -> ack (serial: 4; src: 0 ; dst: 1; ack_serial: 1)
... ... @@ -41,11 +41,11 @@ B -> ack (serial: 6; src: 1 ; dst: 0; ack_serial: 10)
A -> unlockall (serial: 11: src: 0 ; dst: NOID)
B -> ack (serial: 7; src: 1 ; dst: 0; ack_serial: 11)
A disappers (shutdown)
A appears (registering with old node_id)
"A" disappers (shutdown)
"A" appears (registering with old node_id)
A -> getmyid (serial: 0; src: NOID ; dst: NOID; name: A)
B -> setid (serial: 4; src: 1 ; dst: 0; name: A; updatets: 200)
A -> hello (serial: 0; src: NOID ; dst: NOID; name: A)
B -> welcome (serial: 4; src: 1 ; dst: 0; my_name: B; to_name: A)
A -> register (serial: 1; src: 0 ; dst: NOID; name: A)
B -> ack (serial: 5; src: 1 ; dst: 0; ack_serial: 1)
... ...
This diff is collapsed. Click to expand it.
... ... @@ -17,7 +17,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common.h"
#include "calc.h"
#include "error.h"
#ifdef HAVE_MHASH
#include <mhash.h>
... ... @@ -36,7 +39,13 @@
// Copied from http://en.wikipedia.org/wiki/Adler-32
uint32_t adler32_calc(const unsigned char *const data, uint32_t len) { // where data is the location of the data in physical
// memory and len is the length of the data in bytes
// memory and len is the length of the data in bytes
if (len&3)
warning("len [%i] & 3 == %i != 0. Wrong length (not a multiple of 4).", len, len&3);
debug(70, "%p, %i", data, len);
const int MOD_ADLER = 65521;
uint32_t a = 1, b = 0;
int32_t index;
... ... @@ -44,6 +53,7 @@ uint32_t adler32_calc(const unsigned char *const data, uint32_t len) { // where
// Process each byte of the data in order
for (index = 0; index < len; ++index)
{
debug(80, "%5i: %02x %02x %02x", index, data[index], a, b);
a = (a + data[index]) % MOD_ADLER;
b = (b + a) % MOD_ADLER;
}
... ...
... ... @@ -24,6 +24,7 @@
static inline uint32_t adler32_calc(const unsigned char *const data, uint32_t len) {
uint32_t adler32;
debug(70, "%p, %i -> mhash", data, len);
MHASH td = mhash_init(MHASH_ADLER32);
mhash(td, data, len);
... ...
/*
clsync - file tree sync utility based on inotify/kqueue/bsm
Copyright (C) 2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common.h"
#include "error.h"
#include <libcgroup.h>
static struct cgroup *cgroup = NULL;
int clsync_cgroup_init(ctx_t *ctx_p) {
debug(2, "cgroup_name == \"%s\"", ctx_p->cg_groupname);
SAFE( cgroup_init(), return -1; );
SAFE( (cgroup = cgroup_new_cgroup(ctx_p->cg_groupname)) == NULL, return -1; );
return 0;
}
int clsync_cgroup_forbid_extra_devices() {
int rc;
char *allowed_devices[] = CG_ALLOWED_DEVICES, **allowed_device_i;
/*
* Unfortunately, libcgroup doesn't allow multiple values for one key, and cgroups doesn't allow multiple devices for one set. So I was been have to write this hack. It adds character '/' to start of "devices.allow" for every new entry. So libclsync thinks that it's different keys, "/sys/fs/cgroup/devices/clsync/123/devices.allow" == "/sys/fs/cgroup/devices/clsync/123//devices.allow".
*/
char control_name_buf[BUFSIZ+BUFSIZ]={[0 ... BUFSIZ-1] = '/', 'd', 'e', 'v', 'i', 'c', 'e', 's', '.', 'a', 'l', 'l', 'o', 'w'}, *control_name = &control_name_buf[BUFSIZ];
debug(2, "");
struct cgroup_controller *cgc;
SAFE( (cgc = cgroup_add_controller(cgroup, "devices")) == NULL, return -1; );
debug(8, "Deny device: \"a\"");
SAFE( cgroup_add_value_string(cgc, "devices.deny", "a"), return -1; );
allowed_device_i = allowed_devices;
while (*allowed_device_i != NULL) {
critical_on (control_name < control_name_buf);
debug(8, "Allow device: \"%s\" (\"%s\" = \"%s\")", *allowed_device_i, control_name, *allowed_device_i);
SAFE( cgroup_add_value_string(cgc, control_name, *allowed_device_i),return -1; );
control_name--;
allowed_device_i++;
}
if ((rc=cgroup_create_cgroup(cgroup, 1))) {
error("Got error while cgroup_create_cgroup(): %s", cgroup_strerror(rc));
return -1;
}
return 0;
}
int clsync_cgroup_attach(ctx_t *ctx_p) {
int rc;
debug(2, "");
if ((rc=cgroup_attach_task_pid(cgroup, ctx_p->pid))) {
error("Got error while cgroup_attach_task_pid(): %s", cgroup_strerror(rc));
return -1;
}
return 0;
}
int clsync_cgroup_deinit(ctx_t *ctx_p) {
debug(2, "");
error_on(cgroup_delete_cgroup_ext(cgroup, CGFLAG_DELETE_IGNORE_MIGRATION | CGFLAG_DELETE_RECURSIVE));
cgroup_free(&cgroup);
debug(15, "end");
return 0;
}
... ...
/*
clsync - file tree sync utility based on inotify/kqueue/bsm
Copyright (C) 2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
extern int clsync_cgroup_init(struct ctx *ctx_p);
extern int clsync_cgroup_forbid_extra_devices();
extern int clsync_cgroup_attach(struct ctx *ctx_p);
extern int clsync_cgroup_deinit(struct ctx *ctx_p);
... ...
This diff is collapsed. Click to expand it.
... ... @@ -68,16 +68,15 @@
// Types
enum adler32_calc {
ADLER32_CALC_NONE = 0x00,
ADLER32_CALC_NONE = 0x00,
ADLER32_CALC_HEADER = 0x01,
ADLER32_CALC_DATA = 0x02,
ADLER32_CALC_ALL = 0x03,
ADLER32_CALC_DATA = 0x02,
ADLER32_CALC_ALL = 0x03,
};
typedef enum adler32_calc adler32_calc_t;
enum cluster_read_flags {
CLREAD_NONE = 0x00,
CLREAD_CONTINUE = 0x01,
CLREAD_ALL = 0xff
};
typedef enum cluster_read_flags cluster_read_flags_t;
... ... @@ -112,33 +111,38 @@ struct nodeinfo {
packets_stats_t packets_in;
packets_stats_t packets_out;
uint32_t last_serial;
char *node_name;
};
typedef struct nodeinfo nodeinfo_t;
enum clustercmd_id {
CLUSTERCMDID_PING = 0,
CLUSTERCMDID_ACK = 1,
CLUSTERCMDID_REG = 2,
CLUSTERCMDID_GETMYID = 3,
CLUSTERCMDID_SETID = 4,
CLUSTERCMDID_HT_EXCH = 5,
CLUSTERCMDID_PING = 0,
CLUSTERCMDID_ACK = 1,
CLUSTERCMDID_REG = 2,
CLUSTERCMDID_HELLO = 3,
CLUSTERCMDID_WELCOME = 4,
CLUSTERCMDID_DIE = 5,
CLUSTERCMDID_HT_EXCH = 6,
COUNT_CLUSTERCMDID
};
typedef enum clustercmd_id clustercmd_id_t;
struct clustercmd_getmyid {
char node_name[1];
struct clustercmd_hello {
char node_name[0];
};
typedef struct clustercmd_getmyid clustercmd_getmyid_t;
struct clustercmd_setiddata {
uint32_t updatets;
char node_name[1];
typedef struct clustercmd_hello clustercmd_hello_t;
#define welcome_to_node_name_len(cmd_p) ((cmd_p)->h.data_len-(((clustercmd_welcome_t *)&(cmd_p)->data)->from_node_name_len)-sizeof(clustercmd_welcome_t))
#define welcome_to_node_name(cmddata_p) (&cmddata_p->from_node_name[cmddata_p->from_node_name_len])
struct clustercmd_welcome {
size_t from_node_name_len;
char from_node_name[0];
// to_node_name == my_node_name+my_node_name_len
};
typedef struct clustercmd_setiddata clustercmd_setiddata_t;
typedef struct clustercmd_welcome clustercmd_welcome_t;
struct clustercmd_reg {
char node_name[1];
char node_name[0];
};
typedef struct clustercmd_reg clustercmd_reg_t;
... ... @@ -149,7 +153,7 @@ typedef struct clustercmd_ack clustercmd_ack_t;
enum reject_reason {
REJ_UNKNOWN = 0,
REJ_adler32MISMATCH,
REJ_ADLER32MISMATCH,
};
typedef enum reject_reason reject_reason_t;
... ... @@ -162,13 +166,13 @@ typedef struct clustercmd_rej clustercmd_rej_t;
struct clustercmd_ht_exch {
time_t ctime;
size_t path_length;
char path[1];
char path[0];
};
typedef struct clustercmd_ht_exch clustercmd_ht_exch_t;
struct clustercmdadler32 {
uint32_t hdr;
uint32_t dat;
uint32_t hdr; // 32
uint32_t dat; // 64
};
typedef struct clustercmdadler32 clustercmdadler32_t;
... ... @@ -177,23 +181,26 @@ struct clustercmdhdr { // bits
uint8_t src_node_id; // 16
uint8_t flags; // 24 (for future compatibility)
uint8_t cmd_id; // 32
clustercmdadler32_t adler32; // 64
uint32_t data_len; // 96
uint32_t ts; // 128
uint32_t serial; // 160
clustercmdadler32_t adler32; // 96
uint32_t data_len; // 128
uint32_t ts; // 160
uint32_t serial; // 192
};
typedef struct clustercmdhdr clustercmdhdr_t;
typedef char clustercmd_die_t;
struct clustercmd {
clustercmdhdr_t h;
union data {
char p[1];
clustercmd_setiddata_t setid;
char p[0];
clustercmd_welcome_t welcome;
clustercmd_reg_t reg;
clustercmd_ack_t ack;
clustercmd_rej_t rej;
clustercmd_getmyid_t getmyid;
clustercmd_hello_t hello;
clustercmd_ht_exch_t ht_exch;
clustercmd_die_t die;
} data;
};
typedef struct clustercmd clustercmd_t;
... ...
... ... @@ -69,17 +69,14 @@
#include <pthread.h>
#include <glib.h>
#ifdef HAVE_CAPABILITIES
# include <sys/capability.h> // for capset()/capget() for --preserve-file-access
# include <sys/prctl.h> // for prctl() for --preserve-fil-access
#endif
#include "configuration.h"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "clsync.h"
#include "port-hacks.h"
#include "posix-hacks.h"
#include "ctx.h"
#include "program.h"
... ... @@ -117,20 +114,44 @@
# endif
#endif
#ifndef offsetof
# define offsetof(a, b) __builtin_offsetof(a, b)
#endif
// clang defines "__GNUC__", but not compatible with gnuc. Fixing.
#ifdef __clang__
# ifdef __GNUC__
# undef __GNUC__
# endif
#endif
#define TOSTR(a) # a
#define XTOSTR(a) TOSTR(a)
#define COLLECTDELAY_INSTANT ((unsigned int)~0)
#define MSG_SECURITY_PROBLEM(a) "Security problem: "a". Don't use this application until the bug will be fixed. Report about the problem to: "AUTHOR
#define require_strlen_le(str, limit) \
if (strlen(str) >= limit)\
critical("length of "TOSTR(str)" (\"%s\") >= "TOSTR(limit));\
#define SAFE(code, onfail) ({\
long _SAFE_rc;\
if ((_SAFE_rc = code)) {\
error("Got error while "TOSTR(code));\
onfail;\
} \
_SAFE_rc;\
})
enum paramsource_enum {
PS_UNKNOWN = 0,
PS_ARGUMENT,
PS_CONFIG
PS_CONFIG,
PS_CONTROL,
PS_DEFAULTS,
};
typedef enum paramsource_enum paramsource_t;
... ... @@ -141,23 +162,12 @@ enum notifyengine_enum {
NE_INOTIFY,
NE_KQUEUE,
NE_BSM,
NE_BSM_PREFETCH,
NE_DTRACEPIPE,
NE_GIO,
};
typedef enum notifyengine_enum notifyengine_t;
#define STATE_STARTING(state_p) (state_p == NULL)
enum state_enum {
STATE_EXIT = 0,
STATE_STARTING,
STATE_RUNNING,
STATE_REHASH,
STATE_TERM,
STATE_THREAD_GC,
STATE_INITSYNC,
STATE_UNKNOWN
};
typedef enum state_enum state_t;
enum threadingmode {
PM_OFF = 0,
PM_SAFE,
... ... @@ -165,6 +175,13 @@ enum threadingmode {
};
typedef enum threadingmode threadingmode_t;
enum splittingmode_enum {
SM_OFF = 0,
SM_THREAD,
SM_PROCESS,
};
typedef enum splittingmode_enum splittingmode_t;
/*
struct excludeinfo {
unsigned int seqid_min;
... ... @@ -187,29 +204,35 @@ struct eventinfo {
};
typedef struct eventinfo eventinfo_t;
struct thread_callbackfunct_arg {
char *excfpath;
char *incfpath;
};
typedef struct thread_callbackfunct_arg thread_callbackfunct_arg_t;
typedef int (*thread_callbackfunct_t)(ctx_t *ctx_p, char **argv);
typedef int (*thread_callbackfunct_t)(ctx_t *ctx_p, thread_callbackfunct_arg_t *arg_p);
struct threadinfo {
int thread_num;
uint32_t iteration;
thread_callbackfunct_t callback;
char **argv;
pthread_t pthread;
int exitcode;
int errcode;
state_t state;
ctx_t *ctx_p;
time_t starttime;
time_t expiretime;
int child_pid;
GHashTable *fpath2ei_ht; // file path -> event information
int try_n;
int thread_num;
uint32_t iteration;
thread_callbackfunct_t callback;
thread_callbackfunct_arg_t *callback_arg;
char **argv;
pthread_t pthread;
int exitcode;
int errcode;
state_t state;
ctx_t *ctx_p;
time_t starttime;
time_t expiretime;
int child_pid;
GHashTable *fpath2ei_ht; // file path -> event information
int try_n;
// for so-synchandler
int n;
api_eventinfo_t *ei;
int n;
api_eventinfo_t *ei;
};
typedef struct threadinfo threadinfo_t;
... ... @@ -245,6 +268,12 @@ struct dosync_arg {
api_eventinfo_t *api_ei;
int api_ei_count;
char buf[BUFSIZ+1];
// for be read by sync_parameter_get():
const char *include_list[MAXARGUMENTS+2];
size_t include_list_count;
const char *list_type_str;
const char *evmask_str;
};
struct doubleentry {
... ...
#ifndef __CONFIGURATION_H
#define __CONFIGURATION_H
#ifndef BUFSIZ
... ... @@ -13,6 +15,8 @@
// clsync should be used, if there's more than 5-10 nodes. So the limit in 255 is quite enough. :)
#define MAXNODES ((1<<8)-1)
#define MAXSIGNALNUM (1<<9)
// max user/group lengths
#define USER_LEN (1<<8)
#define GROUP_LEN USER_LEN
... ... @@ -29,13 +33,18 @@
// children count limit
#define MAXCHILDREN (1<<8)
#define MAXMOUNTPOINTS (1<<8)
#define MAXPERMITTEDHOOKFILES (1<<8)
#ifdef __CLSYNC_COMMON_H
# if INOTIFY_SUPPORT
# define DEFAULT_NOTIFYENGINE NE_UNDEFINED
# ifdef __linux__
# undef DEFAULT_NOTIFYENGINE
# define DEFAULT_NOTIFYENGINE NE_INOTIFY
# elif KQUEUE_SUPPORT
# endif
# ifdef __FreeBSD__
# undef DEFAULT_NOTIFYENGINE
# define DEFAULT_NOTIFYENGINE NE_KQUEUE
# else
# error No inotify/kqueue support, cannot compile working clsync
# endif
#endif
#define DEFAULT_RULES_PERM RA_ALL
... ... @@ -56,14 +65,14 @@
#define DEFAULT_RETRIES 1
#define DEFAULT_VERBOSE 3
#define DEFAULT_DUMPDIR "/tmp/clsync-dump-%label%"
#define DEFAULT_DETACH_IPC 1
#define FANOTIFY_FLAGS (FAN_CLOEXEC|FAN_UNLIMITED_QUEUE|FAN_UNLIMITED_MARKS)
#define FANOTIFY_EVFLAGS (O_LARGEFILE|O_RDONLY|O_CLOEXEC)
#define FANOTIFY_MARKMASK (FAN_OPEN|FAN_MODIFY|FAN_CLOSE|FAN_ONDIR|FAN_EVENT_ON_CHILD)
#define INOTIFY_FLAGS 0
//(FD_CLOEXEC)
#define INOTIFY_FLAGS (IN_CLOEXEC)
#define INOTIFY_MARKMASK (IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF|IN_MOVED_FROM|IN_MOVED_TO|IN_MODIFY|IN_DONT_FOLLOW)
... ... @@ -75,15 +84,19 @@
#define ALLOC_PORTION (1<<10) /* 1 KiX */
#define CLUSTER_WINDOW_BUFSIZE_PORTION (1<<20) /* 1 MiB */
#define CLUSTER_PACKET_MAXSIZE (1<<24) /* 16 MiB */
#define CLUSTER_PACKET_MAXSIZE (1<<20) /* 1 MiB */
#define CLUSTER_WINDOW_PCKTLIMIT (1<<20) /* 1 Ki packets */
#define CONFIG_PATHS { ".clsync.conf", "/etc/clsync/clsync.conf", NULL } /* "~/.clsync.conf" and "/etc/clsync/clsync.conf" */
#define CONFIG_PATHS { ".clsync.conf", "/etc/clsync/clsync.conf", "/etc/clsync.conf", "/usr/local/etc/clsync/clsync.conf", "/usr/local/etc/clsync.conf", NULL } /* "~/.clsync.conf", "/etc/clsync/clsync.conf" ... */
#define API_PREFIX "clsyncapi_"
#define DUMP_DIRMODE 0750
#define DUMP_FILEMODE 0644
#define DEFAULT_CP_PATH "cp"
#define DEFAULT_RSYNC_PATH "rsync"
// size of event chain size to be processes at a time
#define KQUEUE_EVENTLISTSIZE 256
... ... @@ -98,8 +111,102 @@ minfree:0\n\
naflags:fc,fd,fw,fm,cl\n\
policy:cnt\n\
filesz:1M\n\
expire-after:20M\n\
"
#define DTRACE_PATH "dtrace"
#define PIVOT_AUTO_DIR "/dev/shm/clsync-rootfs"
#define TMPDIR_TEMPLATE "/tmp/clsync-XXXXXX"
#define SYSLOG_BUFSIZ (1<<16)
#define SYSLOG_FLAGS (LOG_PID|LOG_CONS)
#define SYSLOG_FACILITY LOG_DAEMON
#define CLSYNCSOCK_WINDOW (1<<8)
#define DEFAULT_SYNCHANDLER_ARGS_SIMPLE "sync \%label\% \%EVENT-MASK\% \%INCLUDE-LIST\%"
#define DEFAULT_SYNCHANDLER_ARGS_DIRECT "\%INCLUDE-LIST\% \%destination-dir\%/"
#define DEFAULT_SYNCHANDLER_ARGS_SHELL_NR "synclist \%label\% \%INCLUDE-LIST-PATH\%"
#define DEFAULT_SYNCHANDLER_ARGS_SHELL_R "initialsync \%label\% \%INCLUDE-LIST\%"
#define DEFAULT_SYNCHANDLER_ARGS_RDIRECT_E "-aH --delete --exclude-from \%EXCLUDE-LIST-PATH\% --include-from \%INCLUDE-LIST-PATH\% --exclude=* \%watch-dir\%/ \%destination-dir\%/"
#define DEFAULT_SYNCHANDLER_ARGS_RDIRECT_I "-aH --delete --include-from \%INCLUDE-LIST-PATH\% --exclude=* \%watch-dir\%/ \%destination-dir\%/"
#define DEFAULT_SYNCHANDLER_ARGS_RSHELL_E "rsynclist \%label% \%INCLUDE-LIST-PATH\% %EXCLUDE-LIST-PATH%"
#define DEFAULT_SYNCHANDLER_ARGS_RSHELL_I "rsynclist \%label% \%INCLUDE-LIST-PATH\%"
#define RSYNC_ARGS_E { \
"-aH", \
"--delete", \
"--exclude-from", \
"\%EXCLUDE-LIST-PATH\%",\
"--include-from", \
"\%INCLUDE-LIST-PATH\%",\
"--exclude=*", \
NULL }
#define RSYNC_ARGS_I { \
"-aH", \
"--delete", \
"--include-from", \
"\%INCLUDE-LIST-PATH\%",\
"--exclude=*", \
NULL }
#define DEFAULT_PRESERVE_CAPABILITIES ( CAP_TO_MASK(CAP_DAC_READ_SEARCH) | CAP_TO_MASK(CAP_SETUID) | CAP_TO_MASK(CAP_SETGID) | CAP_TO_MASK(CAP_KILL) )
#define DEFAULT_USER "nobody"
#define DEFAULT_GROUP "nogroup"
#define DEFAULT_UID 65534
#define DEFAULT_GID 65534
#define DEFAULT_CAPS_INHERIT CI_EMPTY
#define DEFAULT_PIVOT_MODE (PW_OFF)
#define DEVZERO "/dev/zero"
// How long to wait on highloaded locks before fallback to mutexes
// See: doc/devel/thread-splitting/highload-locks/clsync-graph-comma.odc
// But optimal value can be very different on different systems
#define HL_LOCK_TRIES_INITIAL (1<<13)
// Enable run-time auto-adjustment
#define HL_LOCK_TRIES_AUTO
// Iterations delay between adjustments (power of 2; 2^x)
#define HL_LOCK_AUTO_INTERVAL 7 /* 128 */
// Initial adjustment factor
#define HL_LOCK_AUTO_K 1.1
// Delay detection error threshold
#define HL_LOCK_AUTO_THREADHOLD 0.2
// Adjustment factor denominator
#define HL_LOCK_AUTO_DECELERATION 1.1
// Don't adjust if the factor is less than
#define HL_LOCK_AUTO_K_FINISH 0.001
// Upper limit
#define HL_LOCK_AUTO_LIMIT_HIGH (1<<20)
//#define READWRITE_SIGNALLING
#define CG_DEV_CONSOLE "c 5:1"
#define CG_DEV_ZERO "c 1:5"
#define CG_DEV_RANDOM "c 1:8"
#define CG_DEV_URANDOM "c 1:9"
#define CG_DEV_NULL "c 1:3"
#define CG_ALLOWED_DEVICES { \
CG_DEV_CONSOLE " rw", \
CG_DEV_ZERO " r", \
CG_DEV_URANDOM " r", \
CG_DEV_RANDOM " r", \
CG_DEV_NULL " w", \
NULL \
}
#define DEFAULT_CG_GROUPNAME "clsync/%PID%"
// In nanoseconds
#define OUTPUT_LOCK_TIMEOUT (100*1000*1000)
#define WAITPID_TIMED_GRANULARITY (30*1000*1000)
#define BSM_QUEUE_LENGTH_MAX (1024*1024)
#define GIO_QUEUE_LENGTH_MAX BSM_QUEUE_LENGTH_MAX
#endif
... ...
... ... @@ -7,9 +7,12 @@ AC_CONFIG_SRCDIR([sync.c])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([1.11 foreign -Wall -Wno-portability])
AC_CONFIG_HEADERS([config.h])
AC_PROG_CC([gcc cc])
AM_PROG_CC_C_O
AC_PROG_CC_STDC
AC_CONFIG_MACRO_DIR([m4])
AC_PROG_LIBTOOL
AM_PROG_LIBTOOL
LT_INIT
... ... @@ -55,7 +58,6 @@ AS_HELP_STRING(--enable-cluster,
[enable clustering support (not yet implemented), default: no]))
AS_IF([test "x$enable_cluster" = "xyes"], [CPPFLAGS="${CPPFLAGS} -DCLUSTER_SUPPORT"
dnl mhash check
AC_ARG_WITH(mhash,
AS_HELP_STRING(--with-mhash,
... ... @@ -68,6 +70,7 @@ AS_IF([test "x$enable_cluster" = "xyes"], [CPPFLAGS="${CPPFLAGS} -DCLUSTER_SUPPO
])
])
dnl --enable-socket
AC_ARG_ENABLE(socket,
AS_HELP_STRING(--enable-socket,
... ... @@ -84,13 +87,29 @@ AS_HELP_STRING(--enable-socket-library,
[build libclsync socket library, default: no]))
AM_CONDITIONAL([LIBCLSYNC], [test "x$enable_socket_library" = "xyes"])
dnl --enable-highload-locks
AC_ARG_ENABLE(highload-locks,
AS_HELP_STRING(--enable-highload-locks,
[enable locks for high loaded instances (it requires more CPU, but it's faster) for --thread-splitting [not well tested, can cause deadlocks with 100% CPU utilization], default: no]))
AM_CONDITIONAL([HLLOCKS], [test "x$enable_highload_locks" = "xyes"])
dnl --enable-debug
AC_ARG_ENABLE(debug,
AS_HELP_STRING(--enable-debug,
[enable debugging, default: no]))
[enable debugging support, default: yes; value: no, yes, force]),
[case "${enableval}" in
(0|"no") debug=0 ;;
(1|"yes") debug=1 ;;
(2|"force") debug=2 ;;
(*) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
esac],
[debug=1])
AS_IF([ test "$debug" -ge 1 ],
[CFLAGS="${CFLAGS} -pipe -Wall -O0 -ggdb3" CPPFLAGS="${CPPFLAGS} -D_DEBUG_SUPPORT"])
AS_IF([test "x$enable_debug" = "xyes"],
[CFLAGS="${CFLAGS} -pipe -Wall -O0 -ggdb3" CPPFLAGS="${CPPFLAGS} -D_DEBUG"])
AS_IF([ test "$debug" -ge 2 ],
[CPPFLAGS="${CPPFLAGS} -D_DEBUG_FORCE"])
dnl --paranoid
AC_ARG_ENABLE(paranoid,
... ... @@ -100,15 +119,19 @@ AS_HELP_STRING([--enable-paranoid],
(0|"no") paranoid=0 ;;
(1|"yes") paranoid=1 ;;
(2) paranoid=2 ;;
(*) AC_MSG_ERROR([bad value ${enableval} for --paranoid]) ;;
(*) AC_MSG_ERROR([bad value ${enableval} for --enable-paranoid]) ;;
esac],
[paranoid=1])
AS_IF([test $paranoid -ge 1],[
CPPFLAGS="${CPPFLAGS} -D_FORTIFY_SOURCE=2 -DPARANOID"
CFLAGS="${CFLAGS} -fstack-protector-all -Wall --param ssp-buffer-size=4 -fstack-check"
LDFLAGS="${LDFLAGS} -Xlinker -zrelro"
])
AS_IF(
[test $paranoid -ge 1],
[
CPPFLAGS="${CPPFLAGS} -D_FORTIFY_SOURCE=2 -DPARANOID"
CFLAGS="${CFLAGS} -fstack-protector-all -Wall --param ssp-buffer-size=4"
LDFLAGS="${LDFLAGS} -Xlinker -zrelro"
AX_CHECK_COMPILE_FLAG([-fstack-check], [CFLAGS="${CFLAGS} -fstack-check"])
]
)
AS_IF([test $paranoid -eq 2], [CPPFLAGS="${CPPFLAGS} -DVERYPARANOID"])
# Checks for programs.
... ... @@ -126,20 +149,115 @@ dnl -lrt is needed on < glibc-2.17
AC_SEARCH_LIBS([clock_getres], [rt], [],
[AC_MSG_ERROR("Unable to find librt; clock_getres() is needed")])
dnl searching for getmntent
AC_CHECK_FUNC([getmntent], [HAVE_GETMNTENT=1])
dnl searching for pivot_root
AC_CHECK_FUNC([pivot_root], [HAVE_PIVOTROOT=1])
dnl searching for unshare
AC_CHECK_FUNC([unshare], [HAVE_UNSHARE=1])
dnl libcgroup check
AC_ARG_WITH(libcgroup,
AS_HELP_STRING(--with-libcgroup,
[Enable cgroup support via libcgroup; values: no, check, yes; default: check]),
[],
[with_libcgroup=check]
)
case "$with_libcgroup" in
yes)
AC_CHECK_LIB([cgroup], [cgroup_init],
[
AC_CHECK_HEADER(libcgroup.h, [], [AC_MSG_FAILURE([Cannot find libcgroup.h])])
LDFLAGS="${LDFLAGS} -lcgroup"
HAVE_LIBCGROUP=1
],
[
AC_MSG_FAILURE(
[Cannot find libcgroup])
]
)
;;
check)
AC_CHECK_LIB([cgroup], [cgroup_init],
[
AC_CHECK_HEADER(libcgroup.h, [], [AC_MSG_FAILURE([Cannot find libcgroup.h])])
LDFLAGS="${LDFLAGS} -lcgroup"
HAVE_LIBCGROUP=1
],
[]
)
;;
esac
dnl capabilities check
AC_ARG_WITH(capabilities,
AS_HELP_STRING(--with-capabilities,
[enable linux capabilities support, default: disabled]))
AS_HELP_STRING(--with-capabilities,
[Enable linux capabilities support; values: no, check, yes; default: check]),
[],
[with_capabilities=check]
)
AS_IF(
[test "x$with_capabilities" = "xyes"],
[AC_CHECK_HEADER(
[sys/capability.h],
[CPPFLAGS="${CPPFLAGS} -DHAVE_CAPABILITIES"],
[AC_MSG_ERROR("Unable to find sys/capability.h")]
)]
case "$with_capabilities" in
yes)
AC_CHECK_FUNC([capset],
[
AC_CHECK_HEADER(sys/capability.h, [HAVE_CAPABILITIES=2], [AC_MSG_FAILURE([Cannot find sys/capability.h])])
],
[
AC_MSG_FAILURE([There is no capabilities support on this system])
]
)
;;
check)
AC_CHECK_FUNC([capset],
[
AC_CHECK_HEADER(sys/capability.h, [HAVE_CAPABILITIES=2])
]
)
;;
esac
dnl tre check
AC_ARG_WITH(tre,
AS_HELP_STRING(--with-tre,
[Enable tre support be able to predict which directories should be scanned for excludes; values: no, check, yes; default: check]),
[],
[with_tre=check]
)
case "$with_tre" in
yes)
AC_CHECK_LIB([tre], [tre_regaexec],
[
AC_CHECK_HEADER(tre/tre.h, [], [AC_MSG_FAILURE([Cannot find tre/tre.h])])
LDFLAGS="${LDFLAGS} -ltre"
HAVE_TRE=1
],
[
AC_MSG_FAILURE(
[Cannot find libtre])
]
)
;;
check)
AC_CHECK_LIB([tre], [tre_regaexec],
[
AC_CHECK_HEADER(tre/tre.h, [], [AC_MSG_FAILURE([Cannot find tre/tre.h])])
LDFLAGS="${LDFLAGS} -ltre"
HAVE_TRE=1
],
[]
)
;;
esac
dnl kqueue/inotify/bsm
AC_ARG_WITH(kqueue,
AS_HELP_STRING(--with-kqueue,
[Enable kqueue support; values: no, native, lib, check; default: check]),
... ... @@ -154,9 +272,16 @@ AC_ARG_WITH(inotify,
[with_inotify=check]
)
AC_ARG_WITH(gio,
AS_HELP_STRING(--with-gio,
[Enable GIO support as FS monitor subsystem; values: no, lib, check; default: check]),
[],
[with_gio=check]
)
AC_ARG_WITH(bsm,
AS_HELP_STRING(--with-bsm,
[Enable BSM (Sun/*BSD audit) support as FS monitor subsystem; values: no, native, check; default: check]),
[Enable BSM (Sun/*BSD audit) support as FS monitor subsystem; values: no, lib, check; default: check]),
[],
[with_bsm=check]
)
... ... @@ -247,6 +372,25 @@ case "$with_inotify" in
;;
esac
case "$with_gio" in
check)
PKG_CHECK_MODULES(GIO, [gio-2.0], [
HAVE_GIO=1
AC_SUBST([GIO_CFLAGS])
AC_SUBST([GIO_LIBS])
])
;;
lib)
PKG_CHECK_MODULES(GIO, [gio-2.0], [
HAVE_GIO=1
AC_SUBST([GIO_CFLAGS])
AC_SUBST([GIO_LIBS])
], [
AC_MSG_FAILURE([Cannot find libgio-2.0])
])
;;
esac
case "$with_bsm" in
check)
AC_CHECK_FUNC([au_fetch_tok],
... ... @@ -281,13 +425,46 @@ esac
AS_IF([test "$HAVE_INOTIFY" != ""], [AC_CHECK_FUNC([inotify_init1], [], [INOTIFY_OLD=1])])
AM_CONDITIONAL([HAVE_KQUEUE], [test "x$HAVE_KQUEUE" != "x"])
AM_CONDITIONAL([HAVE_INOTIFY], [test "x$HAVE_INOTIFY" != "x"])
AM_CONDITIONAL([INOTIFY_OLD], [test "x$INOTIFY_OLD" != "x"])
AM_CONDITIONAL([HAVE_FANOTIFY], [test "x$HAVE_FANOTIFY" != "x"])
AM_CONDITIONAL([HAVE_BSM], [test "x$HAVE_BSM" != "x"])
AM_CONDITIONAL([HAVE_DTRACEPIPE],[test "x$HAVE_DTRACEPIPE" != "x"])
AM_CONDITIONAL([HAVE_BACKTRACE], [test "x$HAVE_BACKTRACE" != "x"])
dnl searching for seccomp
AC_ARG_WITH(libseccomp,
AS_HELP_STRING(--with-libseccomp,
[Enable seccomp support be able to forbid extra syscalls; values: no, check, yes; default: check]),
[],
[with_libseccomp=check]
)
case "$with_libseccomp" in
yes)
AC_CHECK_TYPES([scmp_filter_ctx], [], [AC_MSG_FAILURE([Cannot find valid seccomp.h])], [[#include <seccomp.h>]])
AC_CHECK_DECLS([seccomp_syscall_resolve_name_arch], [], [AC_MSG_FAILURE([Cannot find valid seccomp.h])], [[#include <seccomp.h>]])
AC_CHECK_TYPES([struct seccomp_data], [HAVE_SECCOMP=1], [AC_MSG_FAILURE([Cannot find valid linux/seccomp.h])], [[#include <linux/seccomp.h>]])
;;
check)
AC_CHECK_TYPES([scmp_filter_ctx], [
AC_CHECK_DECLS([seccomp_syscall_resolve_name_arch], [
AC_CHECK_TYPES([struct seccomp_data], [HAVE_SECCOMP=1], [], [[#include <linux/seccomp.h>]])
], [], [[#include <seccomp.h>]])
], [], [[#include <seccomp.h>]])
;;
esac
AS_IF([test "$HAVE_CAPABILITIES" != ""], [
])
AM_CONDITIONAL([HAVE_KQUEUE], [test "x$HAVE_KQUEUE" != "x"])
AM_CONDITIONAL([HAVE_INOTIFY], [test "x$HAVE_INOTIFY" != "x"])
AM_CONDITIONAL([INOTIFY_OLD], [test "x$INOTIFY_OLD" != "x"])
AM_CONDITIONAL([HAVE_FANOTIFY], [test "x$HAVE_FANOTIFY" != "x"])
AM_CONDITIONAL([HAVE_BSM], [test "x$HAVE_BSM" != "x"])
AM_CONDITIONAL([HAVE_GIO], [test "x$HAVE_GIO" != "x"])
AM_CONDITIONAL([HAVE_DTRACEPIPE], [test "x$HAVE_DTRACEPIPE" != "x"])
AM_CONDITIONAL([HAVE_BACKTRACE], [test "x$HAVE_BACKTRACE" != "x"])
AM_CONDITIONAL([HAVE_CAPABILITIES], [test "x$HAVE_CAPABILITIES" != "x"])
AM_CONDITIONAL([HAVE_GETMNTENT], [test "x$HAVE_GETMNTENT" != "x"])
AM_CONDITIONAL([HAVE_PIVOTROOT], [test "x$HAVE_PIVOTROOT" != "x"])
AM_CONDITIONAL([HAVE_UNSHARE], [test "x$HAVE_UNSHARE" != "x"])
AM_CONDITIONAL([HAVE_SECCOMP], [test "x$HAVE_SECCOMP" != "x"])
AM_CONDITIONAL([HAVE_TRE], [test "x$HAVE_TRE" != "x"])
AM_CONDITIONAL([HAVE_LIBCGROUP], [test "x$HAVE_LIBCGROUP" != "x"])
AS_IF([test "$HAVE_KQUEUE" = '' -a "$HAVE_INOTIFY" = '' -a "$HAVE_FANOTIFY" = '' -a "$HAVE_BSM" = '' ], [AC_MSG_FAILURE([kqueue, inotify and bsm are not supported on this system])])
... ...
... ... @@ -27,6 +27,7 @@
#include "indexes.h"
#include "main.h"
#include "ctx.h"
#include "error.h"
#include "sync.h"
... ... @@ -36,9 +37,9 @@
static pthread_t pthread_control;
static inline int control_error(clsyncsock_t *clsyncsock_p, const char *const funct, const char *const args) {
static inline int control_error(clsyncsock_t *clsyncsock_p, sockcmd_t *sockcmd_p, const char *const funct, const char *const args) {
debug(3, "%s(%s): %u: %s", funct, args, errno, strerror(errno));
return socket_send(clsyncsock_p, SOCKCMD_REPLY_ECUSTOM, funct, args, errno, strerror(errno));
return socket_reply(clsyncsock_p, sockcmd_p, SOCKCMD_REPLY_ECUSTOM, funct, args, errno, strerror(errno));
}
... ... @@ -48,8 +49,8 @@ int control_dump(ctx_t *ctx_p, clsyncsock_t *clsyncsock_p, sockcmd_t *sockcmd_p)
debug(3, "%s", dat->dir_path);
return (sync_dump(ctx_p, dat->dir_path)) ?
control_error(clsyncsock_p, "sync_dump", dat->dir_path) :
socket_send(clsyncsock_p, SOCKCMD_REPLY_DUMP);
control_error(clsyncsock_p, sockcmd_p, "sync_dump", dat->dir_path) :
socket_reply(clsyncsock_p, sockcmd_p, SOCKCMD_REPLY_DUMP);
}
int control_procclsyncsock(socket_sockthreaddata_t *arg, sockcmd_t *sockcmd_p) {
... ... @@ -62,8 +63,18 @@ int control_procclsyncsock(socket_sockthreaddata_t *arg, sockcmd_t *sockcmd_p) {
rc = control_dump(ctx_p, clsyncsock_p, sockcmd_p);
break;
case SOCKCMD_REQUEST_INFO:
rc = socket_send(clsyncsock_p, SOCKCMD_REPLY_INFO, ctx_p->config_block, ctx_p->label, ctx_p->flags, ctx_p->flags_set);
rc = socket_reply(clsyncsock_p, sockcmd_p, SOCKCMD_REPLY_INFO, ctx_p->config_block, ctx_p->label, ctx_p->flags, ctx_p->flags_set);
break;
case SOCKCMD_REQUEST_SET: {
sockcmd_dat_set_t *dat = sockcmd_p->data;
rc = ctx_set(ctx_p, dat->key, dat->value);
if (rc) {
control_error(clsyncsock_p, sockcmd_p, "ctx_set", dat->key);
break;
}
rc = socket_reply(clsyncsock_p, sockcmd_p, SOCKCMD_REPLY_SET);
break;
}
case SOCKCMD_REQUEST_DIE:
rc = sync_term(SIGTERM);
break;
... ...
... ... @@ -22,6 +22,17 @@
#define __CLSYNC_CTX_H
#include <regex.h>
#ifdef CAPABILITIES_SUPPORT
# include <sys/capability.h> // __u32
#endif
#define MAX_BLOCKTHREADS (1<<4)
#define register_blockthread(thread) {\
critical_on (ctx_p->blockthread_count >= MAX_BLOCKTHREADS);\
ctx_p->blockthread[ctx_p->blockthread_count++] = pthread_self();\
debug(3, "register_blockthread(): ctx_p->blockthread_count -> %i", ctx_p->blockthread_count);\
}
#define OPTION_FLAGS (1<<10)
#define OPTION_LONGOPTONLY (1<<9)
... ... @@ -40,13 +51,12 @@ enum flags_enum {
BACKGROUND = 'b',
UID = 'u',
GID = 'g',
CAP_PRESERVE_FILEACCESS = 'C',
CAP_PRESERVE = 'C',
THREADING = 'p',
RETRIES = 'r',
OUTPUT_METHOD = 'Y',
EXCLUDEMOUNTPOINTS= 'X',
PIDFILE = 'z',
#ifdef CLUSTER_SUPPORT
CLUSTERIFACE = 'c',
CLUSTERMCASTIPADDR='m',
CLUSTERMCASTIPPORT='P',
... ... @@ -54,8 +64,6 @@ enum flags_enum {
CLUSTERNODENAME = 'n',
CLUSTERHDLMIN = 'o',
CLUSTERHDLMAX = 'O',
CLUSTERSDLMAX = 11|OPTION_LONGOPTONLY,
#endif
DELAY = 't',
BFILEDELAY = 'T',
SYNCDELAY = 'w',
... ... @@ -84,26 +92,72 @@ enum flags_enum {
EXITONNOEVENTS = 8|OPTION_LONGOPTONLY,
STANDBYFILE = 9|OPTION_LONGOPTONLY,
EXITHOOK = 10|OPTION_LONGOPTONLY,
CLUSTERSDLMAX = 11|OPTION_LONGOPTONLY,
PREEXITHOOK = 12|OPTION_LONGOPTONLY,
SOCKETAUTH = 13|OPTION_LONGOPTONLY,
SOCKETMOD = 14|OPTION_LONGOPTONLY,
SOCKETOWN = 15|OPTION_LONGOPTONLY,
MAXITERATIONS = 16|OPTION_LONGOPTONLY,
IGNOREFAILURES = 17|OPTION_LONGOPTONLY,
DUMPDIR = 18|OPTION_LONGOPTONLY,
CONFIGBLOCKINHERITS = 19|OPTION_LONGOPTONLY,
MONITOR = 20|OPTION_LONGOPTONLY,
SYNCHANDLERARGS0 = 21|OPTION_LONGOPTONLY,
SYNCHANDLERARGS1 = 22|OPTION_LONGOPTONLY,
CUSTOMSIGNALS = 23|OPTION_LONGOPTONLY,
CHROOT = 24|OPTION_LONGOPTONLY,
MOUNTPOINTS = 25|OPTION_LONGOPTONLY,
SPLITTING = 26|OPTION_LONGOPTONLY,
SYNCHANDLERUID = 27|OPTION_LONGOPTONLY,
SYNCHANDLERGID = 28|OPTION_LONGOPTONLY,
CAPS_INHERIT = 29|OPTION_LONGOPTONLY,
CHECK_EXECVP_ARGS = 30|OPTION_LONGOPTONLY,
PIVOT_ROOT = 31|OPTION_LONGOPTONLY,
DETACH_NETWORK = 32|OPTION_LONGOPTONLY,
DETACH_MISCELLANEA = 33|OPTION_LONGOPTONLY,
ADDPERMITTEDHOOKFILES = 34|OPTION_LONGOPTONLY,
SECCOMP_FILTER = 35|OPTION_LONGOPTONLY,
FORGET_PRIVTHREAD_INFO = 36|OPTION_LONGOPTONLY,
SECURESPLITTING = 37|OPTION_LONGOPTONLY,
FTS_EXPERIMENTAL_OPTIMIZATION = 38|OPTION_LONGOPTONLY,
FORBIDDEVICES = 39|OPTION_LONGOPTONLY,
CG_GROUPNAME = 40|OPTION_LONGOPTONLY,
PERMIT_MPROTECT = 41|OPTION_LONGOPTONLY,
SHM_MPROTECT = 42|OPTION_LONGOPTONLY,
MODSIGN = 43|OPTION_LONGOPTONLY,
CANCEL_SYSCALLS = 44|OPTION_LONGOPTONLY,
EXITONSYNCSKIP = 45|OPTION_LONGOPTONLY,
DETACH_IPC = 46|OPTION_LONGOPTONLY,
};
typedef enum flags_enum flags_t;
SOCKETAUTH = 12|OPTION_LONGOPTONLY,
SOCKETMOD = 13|OPTION_LONGOPTONLY,
SOCKETOWN = 14|OPTION_LONGOPTONLY,
MAXITERATIONS = 15|OPTION_LONGOPTONLY,
IGNOREFAILURES = 16|OPTION_LONGOPTONLY,
DUMPDIR = 17|OPTION_LONGOPTONLY,
enum detachnetwork_way {
DN_OFF = 0,
DN_NONPRIVILEGED,
DN_EVERYWHERE,
};
typedef enum detachnetwork_way detachnetwork_way_t;
CONFIGBLOCKINHERITS = 18|OPTION_LONGOPTONLY,
enum pivotroot_way {
PW_OFF = 0,
PW_DIRECT,
PW_AUTO,
PW_AUTORO,
};
typedef enum pivotroot_way pivotroot_way_t;
MONITOR = 19|OPTION_LONGOPTONLY,
enum capsinherit {
CI_DONTTOUCH = 0,
CI_PERMITTED,
CI_CLSYNC,
CI_EMPTY,
};
typedef enum flags_enum flags_t;
typedef enum capsinherit capsinherit_t;
enum mode_id {
MODE_UNSET = 0,
MODE_SIMPLE,
MODE_DIRECT,
MODE_SHELL,
MODE_RSYNCSHELL,
MODE_RSYNCDIRECT,
... ... @@ -130,10 +184,10 @@ enum ruleactionsign_enum {
typedef enum ruleactionsign_enum ruleactionsign_t;
enum ruleaction_enum {
RA_NONE = 0x00,
RA_MONITOR = 0x01,
RA_WALK = 0x02,
RA_ALL = 0xff
RA_NONE = 0x00,
RA_MONITOR = 0x01,
RA_WALK = 0x02,
RA_ALL = 0x0f,
};
typedef enum ruleaction_enum ruleaction_t;
... ... @@ -174,14 +228,87 @@ struct notifyenginefuncts {
int (*add_watch_dir)(struct ctx *ctx_p, struct indexes *indexes_p, const char *const accpath);
};
enum shflags {
SHFL_NONE = 0x00,
SHFL_RSYNC_ARGS = 0x01,
SHFL_INCLUDE_LIST = 0x02,
SHFL_INCLUDE_LIST_PATH = 0x04,
SHFL_EXCLUDE_LIST_PATH = 0x08,
};
typedef enum shflags shflags_t;
enum shargsid {
SHARGS_PRIMARY = 0,
SHARGS_INITIAL,
SHARGS_MAX,
};
struct synchandler_args {
char *v[MAXARGUMENTS];
int c;
char isexpanded[MAXARGUMENTS];
};
typedef struct synchandler_args synchandler_args_t;
#define STATE_STARTING(state_p) (state_p == NULL)
enum state_enum {
STATE_EXIT = 0,
STATE_STARTING,
STATE_RUNNING,
STATE_SYNCHANDLER_ERR,
STATE_REHASH,
STATE_PREEXIT,
STATE_TERM,
STATE_THREAD_GC,
STATE_INITSYNC,
STATE_UNKNOWN
};
typedef enum state_enum state_t;
enum stat_fields {
STAT_FIELD_RESET = 0x0000,
STAT_FIELD_DEV = 0x0001,
STAT_FIELD_INO = 0x0002,
STAT_FIELD_MODE = 0x0004,
STAT_FIELD_NLINK = 0x0008,
STAT_FIELD_UID = 0x0010,
STAT_FIELD_GID = 0x0020,
STAT_FIELD_RDEV = 0x0040,
STAT_FIELD_SIZE = 0x0080,
STAT_FIELD_BLKSIZE = 0x0100,
STAT_FIELD_BLOCKS = 0x0200,
STAT_FIELD_ATIME = 0x0400,
STAT_FIELD_MTIME = 0x0800,
STAT_FIELD_CTIME = 0x1000,
STAT_FIELD_ALL = 0x1ff7,
};
enum syscall_bitmask {
CSC_RESET = 0x00,
CSC_MON_STAT = 0x01,
};
#define CAP_PRESERVE_TRY (1<<16)
struct ctx {
#ifndef LIBCLSYNC
volatile state_t state;
pid_t pid;
char pid_str[65];
size_t pid_str_len;
uid_t uid;
gid_t gid;
uid_t synchandler_uid;
gid_t synchandler_gid;
#ifdef CAPABILITIES_SUPPORT
__u32 caps;
#endif
pid_t child_pid[MAXCHILDREN]; // Used only for non-pthread mode
int children; // Used only for non-pthread mode
uint32_t iteration_num;
rule_t rules[MAXRULES];
size_t rules_count;
dev_t st_dev;
#endif
char *flags_values_raw[OPTION_FLAGS];
... ... @@ -189,12 +316,14 @@ struct ctx {
int flags_set[OPTION_FLAGS];
#ifndef LIBCLSYNC
char *config_path;
char *config_block;
const char *config_block;
char *customsignal[MAXSIGNALNUM+1];
char *label;
char *watchdir;
char *pidfile;
char *standbyfile;
char *exithookfile;
char *preexithookfile;
char *destdir;
char *destproto;
char *watchdirwslash;
... ... @@ -202,6 +331,9 @@ struct ctx {
char *statusfile;
char *socketpath;
char *dump_path;
#ifdef CGROUP_SUPPORT
char *cg_groupname;
#endif
int socket;
mode_t socketmod;
uid_t socketuid;
... ... @@ -239,11 +371,34 @@ struct ctx {
unsigned int synctimeout;
sigset_t *sigset;
char isignoredexitcode[(1<<8)];
pthread_t blockthread[MAX_BLOCKTHREADS];
size_t blockthread_count;
char *chroot_dir;
#ifdef CAPABILITIES_SUPPORT
char *permitted_hookfile[MAXPERMITTEDHOOKFILES+1];
int permitted_hookfiles;
#endif
#ifdef GETMNTENT_SUPPORT
char *mountpoint[MAXMOUNTPOINTS+1];
int mountpoints;
#endif
synchandler_args_t synchandler_args[SHARGS_MAX];
shflags_t synchandler_argf;
#endif // ifndef LIBCLSYNC
void *indexes_p;
void *fsmondata;
};
typedef struct ctx ctx_t;
struct fileinfo {
stat64_t lstat;
};
typedef struct fileinfo fileinfo_t;
#endif
... ...
clsync (0.4-1) unstable; urgency=low
* A lot of fixes
-- Dmitry Yu Okunev <dyokunev@ut.mephi.ru> Thu, 6 Nov 2014 10:17:49 +0300
clsync (0.3-1) unstable; urgency=low
* Added support of control socket
... ...
... ... @@ -2,5 +2,5 @@ usr/include/clsync/configuration.h
usr/include/clsync/clsync.h
usr/include/clsync/malloc.h
usr/include/clsync/indexes.h
usr/include/clsync/options.h
usr/include/clsync/output.h
usr/include/clsync/ctx.h
usr/include/clsync/error.h
... ...
usr/bin/clsync
usr/share/man/man1/clsync.1
... ...
... ... @@ -13,7 +13,7 @@ Vcs-Browser: http://anonscm.debian.org/gitweb/?p=collab-maint/clsync.git
Package: clsync
Recommends: rsync
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Depends: ${misc:Depends}
Description: live sync tool based on inotify, written in GNU C
Clsync recursively watches for source directory and executes external
program to sync the changes. Clsync is adapted to use together with rsync.
... ... @@ -23,7 +23,7 @@ Description: live sync tool based on inotify, written in GNU C
Package: clsync-doc
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Depends: ${misc:Depends}
Description: examples and other documentation for clsync
Clsync recursively watches for source directory and executes external
program to sync the changes. Clsync is adapted to use together with rsync.
... ... @@ -33,7 +33,7 @@ Description: examples and other documentation for clsync
Package: clsync-dev
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Depends: ${misc:Depends}
Description: development files for clsync
Clsync recursively watches for source directory and executes external
program to sync the changes. Clsync is adapted to use together with rsync.
... ... @@ -43,6 +43,7 @@ Description: development files for clsync
Package: libclsync
Architecture: any
Pre-Depends: multiarch-support
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: clsync control socket library
Clsync recursively watches for source directory and executes external
... ... @@ -53,7 +54,7 @@ Description: clsync control socket library
Package: libclsync-dev
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Depends: ${misc:Depends}
Description: development files for libclsync
Clsync recursively watches for source directory and executes external
program to sync the changes. Clsync is adapted to use together with rsync.
... ...
usr/include/clsync/socket.h
usr/include/clsync/libclsync.h
usr/include/libclsync/socket.h
usr/include/libclsync/libclsync.h
... ...
... ... @@ -12,9 +12,12 @@
%:
dh $@ --parallel --with autoreconf
#override_dh_auto_configure:
# dh_auto_configure -- --enable-socket=yes
override_dh_auto_configure:
dh_auto_configure -- --enable-socket --enable-socket-library --enable-highload-locks
#override_dh_auto_install:
# dh_auto_install
override_dh_auto_install:
# $(MAKE) DESTDIR=$$(pwd)/debian/clsync prefix=/usr install
dh_auto_install
sed -i "/dependency_libs/ s/'.*'/''/" `find . -name '*.la'`
# -rm --verbose debian/clsync/usr/share/doc/clsync/LICENSE
... ...
#include <stdlib.h>
#include <errno.h>
// Required header:
#include <clsync/clsync.h>
// Optional headers:
#include <clsync/configuration.h>
#include <clsync/error.h>
#include <clsync/ctx.h>
struct ctx *ctx_p = NULL;
int clsyncapi_init(struct ctx *_ctx_p, struct indexes *_indexes_p) {
ctx_p = _ctx_p;
return 0;
}
int clsyncapi_rsync(const char *inclistfile, const char *exclistfile) {
return 0;
}
int clsyncapi_sync(int n, api_eventinfo_t *ei) {
return 0;
}
int clsyncapi_deinit() {
return 0;
}
... ...
#!/bin/bash
RUN_TIMES=27
configuration() {
git checkout -- configuration.h
for regex in "$@"; do
sed -i configuration.h -e "$regex"
done
}
configure() {
./configure -C $@ >/dev/null 2>/dev/null || ./configure $@ || exit -1
}
run() {
time ./clsync -Mso -S'doc/devel/thread-splitting/benchmark-synchandler.so' --have-recursive-sync --max-iterations 1 -W ~/clsync-test $@ || exit -1
}
benchmark() {
make clean all
HL_INITIAL=$(awk '{if ($2 == "HL_LOCK_TRIES_INITIAL") print $3}' < configuration.h)
HL_AUTO=$(gcc -x c - -o /tmp/hl_auto.bin.$$ << 'EOF'
#include <stdio.h>
#include "configuration.h"
int main() {
#ifdef HL_LOCK_TRIES_AUTO
printf("auto\n");
#else
printf("noauto\n");
#endif
return 0;
}
EOF
/tmp/hl_auto.bin.$$
rm -f /tmp/hl_auto.bin.$$
)
CONFIGURE=$(awk '{if ($2 == "./configure") {$1=""; $2="";print $0; exit}}' < config.log)
hash="$@|$CONFIGURE"
if [[ "$HL_AUTO" == "auto" ]]; then
hash="$hash|$HL_AUTO"
else
hash="$hash|$HL_INITIAL"