60 {
"watch-dir", required_argument, NULL,
WATCHDIR},
61 {
"sync-handler", required_argument, NULL,
SYNCHANDLER},
64 {
"rules-file", required_argument, NULL,
RULESFILE},
65 {
"destination-dir", required_argument, NULL,
DESTDIR},
66 {
"mode", required_argument, NULL,
MODE},
67 {
"socket", required_argument, NULL,
SOCKETPATH},
68 {
"socket-auth", required_argument, NULL,
SOCKETAUTH},
69 {
"socket-mod", required_argument, NULL,
SOCKETMOD},
70 {
"socket-own", required_argument, NULL,
SOCKETOWN},
71 {
"status-file", required_argument, NULL,
STATUSFILE},
73 {
"background", optional_argument, NULL,
BACKGROUND},
74 {
"config-file", required_argument, NULL,
CONFIGFILE},
75 {
"config-block", required_argument, NULL,
CONFIGBLOCK},
78 {
"pid-file", required_argument, NULL,
PIDFILE},
79 {
"uid", required_argument, NULL,
UID},
80 {
"gid", required_argument, NULL,
GID},
85 {
"chroot", required_argument, NULL,
CHROOT},
86#ifdef PIVOTROOT_OPT_SUPPORT
87 {
"pivot-root", required_argument, NULL,
PIVOT_ROOT},
91 {
"detach-ipc", required_argument, NULL,
DETACH_IPC},
94#ifdef CAPABILITIES_SUPPORT
95# ifdef SECCOMP_SUPPORT
98 {
"splitting", required_argument, NULL,
SPLITTING},
101# ifdef SECCOMP_SUPPORT
106 {
"shm-mprotect", optional_argument, NULL,
SHM_MPROTECT},
108#ifdef UNSHARE_SUPPORT
109# ifdef GETMNTENT_SUPPORT
110 {
"mountpoints", required_argument, NULL,
MOUNTPOINTS},
113#ifdef CAPABILITIES_SUPPORT
114 {
"preserve-capabilities", required_argument, NULL,
CAP_PRESERVE},
115 {
"inherit-capabilities", optional_argument, NULL,
CAPS_INHERIT},
119 {
"cgroup-group-name", required_argument, NULL,
CG_GROUPNAME},
121#ifdef THREADING_SUPPORT
122 {
"threading", required_argument, NULL,
THREADING},
124 {
"retries", required_argument, NULL,
RETRIES},
126 {
"exit-on-sync-skipping", optional_argument, NULL,
EXITONSYNCSKIP},
130#ifdef CLUSTER_SUPPORT
131 {
"cluster-iface", required_argument, NULL,
CLUSTERIFACE},
136 {
"cluster-hash-dl-min", required_argument, NULL,
CLUSTERHDLMIN},
137 {
"cluster-hash-dl-max", required_argument, NULL,
CLUSTERHDLMAX},
138 {
"cluster-scan-dl-max", required_argument, NULL,
CLUSTERSDLMAX},
141 {
"standby-file", required_argument, NULL,
STANDBYFILE},
142 {
"modification-signature", required_argument, NULL,
MODSIGN},
143 {
"timeout-sync", required_argument, NULL,
SYNCTIMEOUT},
144 {
"delay-sync", required_argument, NULL,
SYNCDELAY},
145 {
"delay-collect", required_argument, NULL,
DELAY},
146 {
"delay-collect-bigfile", required_argument, NULL,
BFILEDELAY},
149 {
"lists-dir", required_argument, NULL,
OUTLISTSDIR},
153 {
"auto-add-rules-w", optional_argument, NULL,
AUTORULESW},
158 {
"dont-unlink-lists", optional_argument, NULL,
DONTUNLINK},
160 {
"full-initialsync", optional_argument, NULL,
INITFULL},
161 {
"only-initialsync", optional_argument, NULL,
ONLYINITSYNC},
162 {
"skip-initialsync", optional_argument, NULL,
SKIPINITSYNC},
164 {
"exit-hook", required_argument, NULL,
EXITHOOK},
165 {
"pre-exit-hook", required_argument, NULL,
PREEXITHOOK},
166 {
"sync-on-quit", optional_argument, NULL,
SOFTEXITSYNC},
167 {
"verbose", optional_argument, NULL,
VERBOSE},
168 {
"debug", optional_argument, NULL,
DEBUG},
169 {
"dump-dir", required_argument, NULL,
DUMPDIR},
170 {
"quiet", optional_argument, NULL,
QUIET},
171 {
"monitor", required_argument, NULL,
MONITOR},
172 {
"label", required_argument, NULL,
LABEL},
173 {
"help", optional_argument, NULL,
HELP},
1064 fprintf ( stderr,
"Force-Debug: parse_parameter(): %i: %i = \"%s\"\n", paramsource, param_id, arg );
1067 switch ( paramsource ) {
1088 error (
"Parameter #%i is already set. No need in setting the default value.", param_id );
1105 debug ( 9,
"Correcting setting %i -> \"%s\"", param_id, arg );
1109 error (
"Unknown parameter #%i source (value \"%s\").", param_id, arg != NULL ? arg :
"" );
1113 if ( ( arg != NULL ) ) {
1123 switch ( param_id ) {
1142 warning (
"Cannot change \"custom-signal\" in run-time. Ignoring." );
1152 struct passwd *pwd = getpwnam ( arg );
1155 if ( pwd == NULL ) {
1165 struct group *grp = getgrnam ( arg );
1168 if ( grp == NULL ) {
1177#ifdef CAPABILITIES_SUPPORT
1178# ifdef SECCOMP_SUPPORT
1197 char *value, *arg_orig = arg;
1204 splittingmode_t splittingmode = getsubopt ( &arg, splitting_modes, &value );
1206 if ( (
int ) splittingmode == -1 ) {
1208 error (
"Invalid splitting mode entered: \"%s\"", arg_orig );
1217 switch ( splittingmode ) {
1227 error (
"Cannot understand \"--secure-splitting=off\". This configuration line have no sence." );
1240 char *subopts = arg;
1243 while ( *subopts != 0 ) {
1245 __u32 cap = getsubopt ( &subopts, capabilities, &value );
1246 debug ( 4,
"cap == 0x%x", cap );
1248 if ( cap != X_CAP_RESET )
1249 ctx_p->caps |= CAP_TO_MASK ( XCAP_TO_CAP ( cap ) );
1256 char *value, *arg_orig = arg;
1267 error (
"Invalid capabilities inheriting mode entered: \"%s\"", arg_orig );
1278 struct passwd *pwd = getpwnam ( arg );
1281 if ( pwd == NULL ) {
1293 struct group *grp = getgrnam ( arg );
1296 if ( grp == NULL ) {
1308 struct passwd *pwd = getpwnam ( arg );
1311 if ( pwd == NULL ) {
1323 struct group *grp = getgrnam ( arg );
1326 if ( grp == NULL ) {
1339 warning (
"Cannot change \"chroot\" in run-time. Ignoring." );
1351#ifdef PIVOTROOT_OPT_SUPPORT
1354 char *value, *arg_orig = arg;
1363 if ( (
int ) pivotway == -1 ) {
1365 error (
"Invalid pivot_root use way entered: \"%s\"", arg_orig );
1374#ifdef UNSHARE_SUPPORT
1377 char *value, *arg_orig = arg;
1388 error (
"Invalid network detach way entered: \"%s\"", arg_orig );
1397#ifdef CAPABILITIES_SUPPORT
1403 warning (
"Cannot change \"add-permitted-hook-files\" in run-time. Ignoring." );
1407 while (
ctx_p->permitted_hookfiles )
1408 free (
ctx_p->permitted_hookfile[--
ctx_p->permitted_hookfiles] );
1413 char *end = strchr ( ptr,
',' );
1419 while (
ctx_p->permitted_hookfiles )
1420 free (
ctx_p->permitted_hookfile[--
ctx_p->permitted_hookfiles] );
1430 error (
"Too many permitted hook files" );
1434 ctx_p->permitted_hookfile[
ctx_p->permitted_hookfiles++] = strdup ( ptr );
1447#ifdef UNSHARE_SUPPORT
1448# ifdef GETMNTENT_SUPPORT
1454 warning (
"Cannot change \"mountpoints\" in run-time. Ignoring." );
1458 while (
ctx_p->mountpoints )
1459 free (
ctx_p->mountpoint[--
ctx_p->mountpoints] );
1467 char *end = strchr ( ptr,
',' );
1473 while (
ctx_p->mountpoints )
1474 free (
ctx_p->mountpoint[--
ctx_p->mountpoints] );
1484 error (
"Too many mountpoints" );
1488 ctx_p->mountpoint[
ctx_p->mountpoints++] = strdup ( ptr );
1505 warning (
"Cannot change \"pid-file\" in run-time. Ignoring." );
1515#ifdef THREADING_SUPPORT
1518 char *value, *arg_orig = arg;
1529 error (
"Invalid threading mode entered: \"%s\"", arg_orig );
1540 char *value, *arg_orig = arg;
1551 error (
"Invalid log writing destination entered: \"%s\"", arg_orig );
1559#ifdef CLUSTER_SUPPORT
1562 ctx_p->cluster_iface = arg;
1566 ctx_p->cluster_mcastipaddr = arg;
1578 ctx_p->cluster_nodename = arg;
1601#ifdef CGROUP_SUPPORT
1604 ctx_p->cg_groupname = arg;
1609 if ( strlen ( arg ) ) {
1620 char *subopts = arg;
1623 while ( *subopts != 0 ) {
1653 char *subopts = arg;
1655 while ( *subopts != 0 ) {
1672 char *value, *arg_orig = arg;
1675 warning (
"Cannot change \"monitor\" in run-time. Ignoring." );
1686 if ( (
int ) notifyengine == -1 ) {
1688 error (
"Invalid FS monitor subsystem entered: \"%s\"", arg_orig );
1692 switch ( notifyengine ) {
1693#ifdef FANOTIFY_SUPPORT
1697#ifdef INOTIFY_SUPPORT
1700#ifdef KQUEUE_SUPPORT
1710#ifdef DTRACEPIPE_SUPPORT
1716 error (
PROGRAM" is compiled without %s subsystem support. Recompile with option \"--with-%s\" if you're planning to use it.", arg_orig, arg_orig );
1733 if ( strlen ( arg ) ) {
1744 if ( strlen ( arg ) ) {
1755 char *ptr = arg, *start = arg;
1763 exitcode = (
unsigned char ) atoi ( start );
1773 fprintf ( stderr,
"Force-Debug: parse_parameter(): Reset ignored exitcodes.\n" );
1778 fprintf ( stderr,
"Force-Debug: parse_parameter(): Adding ignored exitcode %u.\n",
exitcode );
1790 error (
"Expected a digit or comma but got \"%c\"", *ptr );
1793 }
while ( * ( ptr++ ) );
1804 warning (
"Cannot change \"watch-dir\" in run-time. Ignoring." );
1820 char *sep = strstr ( arg,
"://" );
1829 if ( sep == NULL ) {
1830 char *at_ptr = strchr ( arg,
'@' );
1831 char *cl_ptr = strchr ( arg,
':' );
1833 if ( at_ptr != NULL && cl_ptr != NULL && at_ptr < cl_ptr ) {
1844 while ( ptr < sep ) {
1845 if ( *ptr <
'a' || *ptr >
'z' )
1852 size_t len = ( ptr - arg ) + 1;
1873 error (
"Wrong socket auth mech entered: \"%s\"", arg );
1879 if ( !sscanf ( arg,
"%o", (
unsigned int * ) &
ctx_p->
socketmod ) ) {
1880 error (
"Non octal value passed to --socket-mod: \"%s\"", arg );
1888 char *colon = strchr ( arg,
':' );
1892 if ( colon == NULL ) {
1893 struct passwd *pwent = getpwnam ( arg );
1895 if ( pwent == NULL ) {
1896 error (
"Cannot find username \"%s\" (case #0)",
1901 uid = pwent->pw_uid;
1902 gid = pwent->pw_gid;
1905 memcpy ( user, arg, MIN (
USER_LEN, colon - arg ) );
1906 user[colon - arg] = 0;
1909 struct passwd *pwent = getpwnam ( user );
1911 if ( pwent == NULL ) {
1912 error (
"Cannot find username \"%s\" (case #1)",
1918 struct group *grent = getgrnam ( group );
1920 if ( grent == NULL ) {
1921 error (
"Cannot find group \"%s\"",
1926 uid = pwent->pw_uid;
1927 gid = grent->gr_gid;
1933 debug ( 2,
"socket: uid == %u; gid == %u", uid, gid );
1950 error (
"Wrong mode name entered: \"%s\"", arg );
1972 fprintf ( stderr,
"Force-Debug: flag %i is set to %i\n", param_id & 0xff,
ctx_p->
flags[param_id] );
1978 if ( arg == NULL ) {
2727int main (
int _argc,
char *_argv[] )
2732 int ret = 0, nret, rm_listoutdir = 0;
2743#ifdef CLUSTER_SUPPORT
2751#ifdef PIVOTROOT_OPT_SUPPORT
2754#ifdef CAPABILITIES_SUPPORT
2760 ncpus = sysconf ( _SC_NPROCESSORS_ONLN );
2777 if ( nret ) ret = nret;
2782 if ( nret ) ret = nret;
2785 debug ( 5,
"after arguments_parse(): uid == %d, gid == %d, privileged_uid == %d, privileged_gid == %d, synchandler_uid == %d, synchandler_gid == %d",
2800 debug ( 4,
"uid == %d, gid == %d, privileged_uid == %d, privileged_gid == %d, synchandler_uid == %d, synchandler_gid == %d",
2803#ifdef CGROUP_SUPPORT
2805 if (
ctx_p->cg_groupname == NULL ) {
2818 char *args_line0 = NULL, *args_line1 = NULL;
2846 if ( args_line0 != NULL ) {
2847 char *args_line = strdup ( args_line0 );
2851 if ( args_line1 != NULL ) {
2852 char *args_line = strdup ( args_line1 );
2863 if ( rwatchdir == NULL ) {
2868 debug ( 5,
"rwatchdir == \"%s\"", rwatchdir );
2942 ret = errno = EINVAL;
2943 error (
"Very-Paranoid: --watch-dir is supposed to be not \"/\"." );
2956 char *newwatchdir = xmalloc ( size );
2969 if ( rdestdir == NULL ) {
2974 debug ( 5,
"rdestdir == \"%s\"", rdestdir );
2982 ret = errno = EINVAL;
2983 error (
"destdir is supposed to be not \"/\"." );
2989 char *newdestdir = xmalloc ( size );
3003 error (
"Cannot find rules-file. Got error while realpath(\"%s\")",
ctx_p->
rulfpath );
3019 if ( rhandlerfpath != NULL )
3042 debug ( 9,
"Custom arguments %u count: %u", n - 1, args_p->
c );
3045 while ( i < args_p->c ) {
3046 int macros_count = -1, expanded = -1;
3048 debug ( 12,
"args_p->v[%u] == \"%s\" (t: %u; e: %u)", i, args_p->
v[i], macros_count, expanded );
3050 if ( macros_count == expanded )
3059#ifdef UNSHARE_SUPPORT
3060# ifdef GETMNTENT_SUPPORT
3065 if (
ctx_p->mountpoints ) {
3067 ent_f = setmntent (
"/proc/mounts",
"r" );
3069 if ( ent_f == NULL ) {
3070 error (
"Got error while setmntent(\"/proc/mounts\", \"r\")" );
3076# define unshare_wrapper(a) \
3078 error("Got error from unshare("TOSTR(a)")");\
3083 unshare ( CLONE_NEWUTS );
3088 unshare ( CLONE_NEWIPC );
3089 unshare ( CLONE_NEWUTS );
3090 unshare ( CLONE_SYSVSEM );
3094 unshare_wrapper ( CLONE_FILES );
3095 unshare_wrapper ( CLONE_FS );
3096 unshare_wrapper ( CLONE_NEWNS );
3100 unshare_wrapper ( CLONE_NEWNET );
3102# undef unshare_wrapper
3106#ifdef PIVOTROOT_OPT_SUPPORT
3120 if ( mkdir (
"old_root", 0700 ) ) {
3121 if ( errno != EEXIST ) {
3122 error (
"Got error from mkdir(\"old_root\", 0700)" );
3129 if ( errno != EEXIST ) {
3136 unsigned long mount_flags = MS_BIND | MS_REC |
3140 error (
"Got error while mount(\"%s\", \"%s\", NULL, %o, NULL)",
3160#ifdef UNSHARE_SUPPORT
3161# ifdef GETMNTENT_SUPPORT
3163 if (
ctx_p->mountpoints && ( ent_f != NULL ) ) {
3165 while ( NULL != ( ent = getmntent ( ent_f ) ) ) {
3167 debug ( 8,
"Checking should \"%s\" be umount or not", ent->mnt_dir );
3170 while ( i < ctx_p->mountpoints ) {
3171 debug ( 9,
"\"%s\" <?> \"%s\"", ent->mnt_dir,
ctx_p->mountpoint[i] );
3173 if ( !strcmp ( ent->mnt_dir,
ctx_p->mountpoint[i] ) ) {
3174 debug ( 9,
"found" );
3181 if ( i >=
ctx_p->mountpoints ) {
3182 debug ( 1,
"umount2(\"%s\", MNT_DETACH)", ent->mnt_dir );
3184 if ( umount2 ( ent->mnt_dir, MNT_DETACH ) && errno != ENOENT && errno != EINVAL ) {
3185 error (
"Got error while umount2(\"%s\", MNT_DETACH)", ent->mnt_dir );
3191 endmntent ( ent_f );
3198#ifdef PIVOTROOT_OPT_SUPPORT
3209 error (
"Got error while pivot_root(\".\", \"old_root\")" );
3218 debug ( 7,
"chroot(\".\")" );
3220 if ( chroot (
"." ) ) {
3221 error (
"Got error while chroot(\".\")" );
3225#ifdef PIVOTROOT_OPT_SUPPORT
3235 if ( umount2 (
"old_root", MNT_DETACH ) ) {
3236 error (
"Got error while umount2(\"old_root\", MNT_DETACH)" );
3249 debug ( 1,
"Trying to open the status file for writing." );
3255 debug ( 1,
"Changing owner of the status file to %u:%u", uid, gid );
3258 warning (
"Cannot fchown(%u -> \"%s\", %u, %u)",
3265#ifdef CAPABILITIES_SUPPORT
3266 debug ( 1,
"Preserving Linux capabilities" );
3269 if ( prctl ( PR_SET_KEEPCAPS, 1 ) < 0 ) {
3270 error (
"Cannot prctl(PR_SET_KEEPCAPS, 1) to preserve capabilities" );
3275#ifdef CGROUP_SUPPORT
3291 debug ( 3,
"Trying to drop effective gid to %i",
ctx_p->
gid );
3302 debug ( 3,
"Trying to drop effective uid to %i",
ctx_p->
uid );
3312 debug ( 1,
"Trying to open the status file for writing (after setuid()/setgid())." );
3316 error (
"Cannot open file \"%s\" for writing.",
3326 if ( !ret ) ret = rc;
3340 char *tempdir = getenv (
"TMPDIR" );
3344 size_t tempdir_len = strlen(tempdir);
3345 size_t tempsuff_len = strlen(tempsuff);
3348 char *
template = xmalloc(tempdir_len + tempsuff_len + 1);
3349 memcpy (
template, tempdir, tempdir_len);
3350 memcpy (
template + tempdir_len, tempsuff, tempsuff_len);
3351 template[tempdir_len + tempsuff_len] = 0;
3357 error (
"Cannot create temporary dir for list files by template '%s'",
template );
3363 struct stat st = {0};
3367 if ( errno == ENOENT ) {
3383 if ( st.st_mode & ( S_IRWXG | S_IRWXO ) ) {
3385 ret = errno = EACCES;
3402 pid_t pid = getpid();
3405 if ( pidfile == NULL ) {
3407 if ( errno == EACCES ) {
3409 uid_t euid = geteuid();
3410 gid_t egid = getegid();
3411 debug ( 1,
"Don't have permissions to open file \"%s\". Trying seteuid(0)+open()+fchown()+close()+seteuid(%i)",
ctx_p->
pidfile, euid );
3414 if ( !errno )
SAFE ( seteuid ( 0 ), ret = errno );
3416 if ( !errno )
SAFE ( ( fd = open (
ctx_p->
pidfile, O_CREAT | O_WRONLY, 0644 ) ) == -1, ret = errno );
3418 if ( !errno )
SAFE ( fchown ( fd, euid, egid ), ret = errno );
3420 if ( !errno )
SAFE ( close ( fd ), ret = errno );
3422 if ( !errno )
SAFE ( seteuid ( euid ), ret = errno );
3427 if ( pidfile == NULL ) {
3428 error (
"Cannot open file \"%s\" to write a pid there",
3434 if ( pidfile != NULL ) {
3435 if ( fprintf ( pidfile,
"%u", pid ) < 0 ) {
3436 error (
"Cannot write pid into file \"%s\"",
3445 debug ( 3,
"Current errno is %i.", ret );
3456 debug ( 1,
"Cannot unlink pidfile \"%s\": %s. Just truncating the file.",
3460 if ( pidfile != NULL )
3468 error (
"Cannot close file \"%s\".",
3474 error (
"Cannot unlink status file \"%s\"",
3486 if ( rm_listoutdir == 2 )
3509 debug ( 1,
"finished, exitcode: %i: %s.", ret, strerror ( ret ) );
char * parameter_expand(ctx_t *ctx_p, char *arg, int exceptionflags, int *macro_count_p, int *expand_count_p, const char *(*parameter_get)(const char *variable_name, void *arg), void *parameter_get_arg)
Expands option values, e. g. "/var/log/clsync-%label%.pid" -> "/var/log/clsync-clone....