2008-02-27 20:56:47 +03:00
|
|
|
/*
|
|
|
|
* libcsync -- a library to sync a replica with another
|
|
|
|
*
|
|
|
|
* Copyright (c) 2006-2007 by Andreas Schneider <mail@cynapses.org>
|
|
|
|
*
|
|
|
|
* 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 2
|
|
|
|
* 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, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
2008-07-19 14:03:48 +04:00
|
|
|
#ifndef _GNU_SOURCE
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#endif
|
|
|
|
|
2008-02-27 20:56:47 +03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
2011-03-30 15:01:11 +04:00
|
|
|
#include <stdbool.h>
|
2008-06-02 19:02:22 +04:00
|
|
|
#include <unistd.h>
|
2012-03-12 20:04:53 +04:00
|
|
|
#include <getopt.h>
|
|
|
|
#include <errno.h>
|
2008-02-27 20:56:47 +03:00
|
|
|
|
|
|
|
#include <csync.h>
|
|
|
|
|
2012-03-12 20:04:53 +04:00
|
|
|
#include <c_string.h>
|
|
|
|
#include <c_alloc.h>
|
|
|
|
|
2008-05-13 15:40:06 +04:00
|
|
|
#include "csync_auth.h"
|
2012-02-20 21:23:31 +04:00
|
|
|
#include "../src/std/c_private.h"
|
2012-03-11 16:29:27 +04:00
|
|
|
#include "../src/csync_misc.h"
|
2012-02-20 21:23:31 +04:00
|
|
|
|
2012-03-12 20:04:53 +04:00
|
|
|
const char *csync_program_version = "csync commandline client "
|
2009-03-26 12:40:16 +03:00
|
|
|
CSYNC_STRINGIFY(LIBCSYNC_VERSION);
|
2008-02-27 20:56:47 +03:00
|
|
|
|
|
|
|
/* Program documentation. */
|
2012-03-12 20:04:53 +04:00
|
|
|
static char doc[] = "Usage: csync [OPTION...] LOCAL REMOTE\n\
|
|
|
|
csync -- a user level file synchronizer which synchronizes the files\n\
|
|
|
|
at LOCAL with the ones at REMOTE.\n\
|
|
|
|
\n\
|
|
|
|
-c, --conflict-copys Create conflict copys if file changed on both\n\
|
|
|
|
sides.\n\
|
2012-10-27 18:39:33 +04:00
|
|
|
-d, --debug-level=DEBUGLVL Set debug level\n\
|
|
|
|
--disable-statedb Disable the usage and creation of a statedb.\n\
|
2012-03-12 20:04:53 +04:00
|
|
|
--dry-run This runs only update detection and reconcilation.\n\
|
|
|
|
\n\
|
|
|
|
--exclude-file=<file> Add an additional exclude file\n\
|
|
|
|
--test-statedb Test creation of the statedb. Runs update\n\
|
|
|
|
detection.\n\
|
|
|
|
--test-update Test the update detection\n\
|
|
|
|
-?, --help Give this help list\n\
|
|
|
|
--usage Give a short usage message\n\
|
|
|
|
-V, --version Print program version\n\
|
|
|
|
";
|
2008-02-27 20:56:47 +03:00
|
|
|
|
|
|
|
/* The options we understand. */
|
2012-03-12 20:04:53 +04:00
|
|
|
static const struct option long_options[] =
|
|
|
|
{
|
|
|
|
{"exclude-file", required_argument, 0, 0 },
|
2012-10-27 18:39:33 +04:00
|
|
|
{"debug-level", required_argument, 0, 'd' },
|
|
|
|
{"disable-statedb", no_argument, 0, 0 },
|
2012-03-12 20:04:53 +04:00
|
|
|
{"dry-run", no_argument, 0, 0 },
|
|
|
|
{"test-statedb", no_argument, 0, 0 },
|
|
|
|
{"conflict-copies", no_argument, 0, 'c' },
|
|
|
|
{"test-update", no_argument, 0, 0 },
|
|
|
|
{"version", no_argument, 0, 'V' },
|
|
|
|
{"usage", no_argument, 0, 'h' },
|
|
|
|
{0, 0, 0, 0}
|
2008-02-27 20:56:47 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Used by main to communicate with parse_opt. */
|
|
|
|
struct argument_s {
|
|
|
|
char *args[2]; /* SOURCE and DESTINATION */
|
2008-05-20 17:50:02 +04:00
|
|
|
char *exclude_file;
|
2012-10-27 18:39:33 +04:00
|
|
|
int debug_level;
|
2008-07-09 12:10:00 +04:00
|
|
|
int disable_statedb;
|
|
|
|
int create_statedb;
|
2008-02-27 20:56:47 +03:00
|
|
|
int update;
|
|
|
|
int reconcile;
|
|
|
|
int propagate;
|
2011-03-30 15:01:11 +04:00
|
|
|
bool with_conflict_copys;
|
2008-02-27 20:56:47 +03:00
|
|
|
};
|
|
|
|
|
2012-03-12 20:04:53 +04:00
|
|
|
static void print_version()
|
|
|
|
{
|
|
|
|
printf( "%s\n", csync_program_version );
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void print_help()
|
|
|
|
{
|
|
|
|
printf( "%s\n", doc );
|
|
|
|
exit(0);
|
|
|
|
}
|
2008-05-07 12:55:08 +04:00
|
|
|
|
2012-03-12 20:04:53 +04:00
|
|
|
static int parse_args(struct argument_s *csync_args, int argc, char **argv)
|
|
|
|
{
|
|
|
|
while(optind < argc) {
|
|
|
|
int c = -1;
|
|
|
|
struct option *opt = NULL;
|
|
|
|
int result = getopt_long( argc, argv, "dcVh", long_options, &c );
|
|
|
|
|
|
|
|
if( result == -1 ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(result) {
|
|
|
|
case 'd':
|
2012-10-27 18:39:33 +04:00
|
|
|
if (optarg != NULL) {
|
|
|
|
csync_args->debug_level = atoi(optarg);
|
|
|
|
}
|
2012-03-12 20:04:53 +04:00
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
csync_args->with_conflict_copys = true;
|
|
|
|
/* printf("Argument: With conflict copies\n"); */
|
|
|
|
break;
|
|
|
|
case 'V':
|
|
|
|
print_version();
|
|
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
print_help();
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
opt = (struct option*)&(long_options[c]);
|
|
|
|
if(c_streq(opt->name, "exclude-file")) {
|
|
|
|
csync_args->exclude_file = c_strdup(optarg);
|
|
|
|
/* printf("Argument: exclude-file: %s\n", csync_args->exclude_file); */
|
2012-10-27 18:39:33 +04:00
|
|
|
} else if(c_streq(opt->name, "disable-statedb")) {
|
|
|
|
csync_args->disable_statedb = 1;
|
2012-03-12 20:04:53 +04:00
|
|
|
} else if(c_streq(opt->name, "test-update")) {
|
|
|
|
csync_args->create_statedb = 0;
|
|
|
|
csync_args->update = 1;
|
|
|
|
csync_args->reconcile = 0;
|
|
|
|
csync_args->propagate = 0;
|
|
|
|
/* printf("Argument: test-update\n"); */
|
|
|
|
|
|
|
|
} else if(c_streq(opt->name, "dry-run")) {
|
|
|
|
csync_args->create_statedb = 0;
|
|
|
|
csync_args->update = 1;
|
|
|
|
csync_args->reconcile = 1;
|
|
|
|
csync_args->propagate = 0;
|
|
|
|
/* printf("Argument: dry-run\n" ); */
|
|
|
|
|
|
|
|
} else if(c_streq(opt->name, "test-statedb")) {
|
|
|
|
csync_args->create_statedb = 1;
|
|
|
|
csync_args->update = 1;
|
|
|
|
csync_args->reconcile = 0;
|
|
|
|
csync_args->propagate = 0;
|
|
|
|
/* printf("Argument: test-statedb\n"); */
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Argument: No idea what!\n");
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return optind;
|
2008-02-27 20:56:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char **argv) {
|
2008-05-21 16:46:42 +04:00
|
|
|
int rc = 0;
|
2008-02-27 20:56:47 +03:00
|
|
|
CSYNC *csync;
|
2008-07-18 13:35:02 +04:00
|
|
|
char errbuf[256] = {0};
|
2012-03-11 16:29:27 +04:00
|
|
|
int curser = 0;
|
2012-11-01 00:08:08 +04:00
|
|
|
int i;
|
2008-02-27 20:56:47 +03:00
|
|
|
|
|
|
|
struct argument_s arguments;
|
|
|
|
|
|
|
|
/* Default values. */
|
2008-05-20 18:33:34 +04:00
|
|
|
arguments.exclude_file = NULL;
|
2012-10-27 18:39:33 +04:00
|
|
|
arguments.debug_level = 4;
|
2008-07-09 12:10:00 +04:00
|
|
|
arguments.disable_statedb = 0;
|
|
|
|
arguments.create_statedb = 0;
|
2008-02-27 20:56:47 +03:00
|
|
|
arguments.update = 1;
|
|
|
|
arguments.reconcile = 1;
|
|
|
|
arguments.propagate = 1;
|
2012-02-22 20:52:19 +04:00
|
|
|
arguments.with_conflict_copys = false;
|
2008-02-27 20:56:47 +03:00
|
|
|
|
2012-03-12 20:04:53 +04:00
|
|
|
parse_args(&arguments, argc, argv);
|
|
|
|
/* two options must remain as source and target */
|
|
|
|
/* printf("ARGC: %d -> optind: %d\n", argc, optind ); */
|
|
|
|
if( argc - optind < 2 ) {
|
|
|
|
print_help();
|
|
|
|
}
|
2008-02-27 20:56:47 +03:00
|
|
|
|
2012-03-12 20:04:53 +04:00
|
|
|
if (csync_create(&csync, argv[optind], argv[optind+1]) < 0) {
|
2008-02-27 20:56:47 +03:00
|
|
|
fprintf(stderr, "csync_create: failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2012-03-11 16:29:27 +04:00
|
|
|
/*
|
|
|
|
* Protect password from ps listing
|
|
|
|
* Find and replace :password@ by :********@
|
|
|
|
*/
|
2012-11-01 00:08:08 +04:00
|
|
|
for (i = 0; i < argc; i++) {
|
2012-03-11 16:29:27 +04:00
|
|
|
if (csync_fnmatch("*://*:*@*", argv[i], 0) == 0) {
|
|
|
|
curser = strlen(argv[i]);
|
|
|
|
while(curser > 0 && argv[i][curser] != '@') {
|
|
|
|
curser--;
|
|
|
|
}
|
|
|
|
while(curser > 0 && argv[i][curser - 1] != ':') {
|
|
|
|
curser--;
|
|
|
|
argv[i][curser] = '*';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-22 15:08:54 +04:00
|
|
|
csync_set_auth_callback(csync, csync_getpass);
|
2012-10-27 18:39:33 +04:00
|
|
|
|
|
|
|
if (arguments.debug_level) {
|
|
|
|
csync_set_log_verbosity(csync, arguments.debug_level);
|
|
|
|
}
|
|
|
|
|
2008-07-09 12:10:00 +04:00
|
|
|
if (arguments.disable_statedb) {
|
|
|
|
csync_disable_statedb(csync);
|
2008-06-25 15:44:11 +04:00
|
|
|
}
|
2012-10-27 18:39:33 +04:00
|
|
|
|
2011-03-30 15:01:11 +04:00
|
|
|
if(arguments.with_conflict_copys)
|
|
|
|
{
|
|
|
|
csync_enable_conflictcopys(csync);
|
|
|
|
}
|
2008-05-20 18:33:34 +04:00
|
|
|
|
2008-05-21 16:46:42 +04:00
|
|
|
if (csync_init(csync) < 0) {
|
|
|
|
perror("csync_init");
|
|
|
|
rc = 1;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2008-05-20 17:50:02 +04:00
|
|
|
if (arguments.exclude_file != NULL) {
|
|
|
|
if (csync_add_exclude_list(csync, arguments.exclude_file) < 0) {
|
2012-07-19 23:06:18 +04:00
|
|
|
strerror_r(errno, errbuf, sizeof(errbuf));
|
2008-07-18 13:35:02 +04:00
|
|
|
fprintf(stderr, "csync_add_exclude_list - %s: %s\n",
|
2012-07-19 23:06:18 +04:00
|
|
|
arguments.exclude_file, errbuf);
|
2008-05-21 16:46:42 +04:00
|
|
|
rc = 1;
|
|
|
|
goto out;
|
2008-05-20 17:50:02 +04:00
|
|
|
}
|
|
|
|
}
|
2008-02-27 20:56:47 +03:00
|
|
|
|
|
|
|
if (arguments.update) {
|
2008-05-15 15:50:34 +04:00
|
|
|
if (csync_update(csync) < 0) {
|
2008-05-21 16:46:42 +04:00
|
|
|
perror("csync_update");
|
|
|
|
rc = 1;
|
|
|
|
goto out;
|
2008-05-15 15:50:34 +04:00
|
|
|
}
|
2008-02-27 20:56:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (arguments.reconcile) {
|
2008-05-15 15:50:34 +04:00
|
|
|
if (csync_reconcile(csync) < 0) {
|
2008-05-21 16:46:42 +04:00
|
|
|
perror("csync_reconcile");
|
|
|
|
rc = 1;
|
|
|
|
goto out;
|
2008-05-15 15:50:34 +04:00
|
|
|
}
|
2008-02-27 20:56:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (arguments.propagate) {
|
2008-05-16 19:30:57 +04:00
|
|
|
if (csync_propagate(csync) < 0) {
|
2008-05-21 16:46:42 +04:00
|
|
|
perror("csync_propagate");
|
|
|
|
rc = 1;
|
|
|
|
goto out;
|
2008-05-16 19:30:57 +04:00
|
|
|
}
|
2008-02-27 20:56:47 +03:00
|
|
|
}
|
|
|
|
|
2008-07-09 12:10:00 +04:00
|
|
|
if (arguments.create_statedb) {
|
2008-05-05 13:09:16 +04:00
|
|
|
csync_set_status(csync, 0xFFFF);
|
|
|
|
}
|
|
|
|
|
2008-05-21 16:46:42 +04:00
|
|
|
out:
|
2008-05-15 15:50:34 +04:00
|
|
|
csync_destroy(csync);
|
|
|
|
|
2008-05-21 16:46:42 +04:00
|
|
|
return rc;
|
2008-02-27 20:56:47 +03:00
|
|
|
}
|
|
|
|
|
2009-05-13 12:12:07 +04:00
|
|
|
/* vim: set ts=8 sw=2 et cindent: */
|