Merge csync inside the mirall repository

This commit is contained in:
Olivier Goffart 2014-01-13 14:43:14 +01:00
commit 924e0e3242
209 changed files with 31147 additions and 3 deletions

8
.gitignore vendored
View File

@ -6,9 +6,13 @@ CMakeLists.txt.user*
*~
*.autosave
doc/_build/*
*~
*.kate-swp
*.kdev4
win/
admin/win/nsi/l10n/pofiles/*.po
*.swp
*~$
build*
cscope.*
tags
t1.cfg

View File

@ -0,0 +1,23 @@
# - ADD_CHECK_TEST(test_name test_source linklib1 ... linklibN)
# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
# Copyright (c) 2007-2010 Andreas Schneider <asn@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
enable_testing()
include(CTest)
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
set(CMAKE_C_FLAGS_PROFILING "-g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags")
set(CMAKE_SHARED_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
set(CMAKE_MODULE_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
set(CMAKE_EXEC_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
function (ADD_CMOCKA_TEST _testName _testSource)
add_executable(${_testName} ${_testSource})
target_link_libraries(${_testName} ${ARGN})
add_test(${_testName} ${CMAKE_CURRENT_BINARY_DIR}/${_testName})
endfunction (ADD_CMOCKA_TEST)

View File

@ -0,0 +1,22 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,26 @@
# - Check whether the C compiler supports a given flag in the
# context of a stack checking compiler option.
# CHECK_C_COMPILER_FLAG_SSP(FLAG VARIABLE)
#
# FLAG - the compiler flag
# VARIABLE - variable to store the result
#
# This actually calls check_c_source_compiles.
# See help for CheckCSourceCompiles for a listing of variables
# that can modify the build.
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
include(CheckCSourceCompiles)
function(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT)
set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT})
set(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
endfunction(CHECK_C_COMPILER_FLAG_SSP)

View File

@ -0,0 +1,29 @@
@CHECK_PROTOTYPE_DEFINITION_HEADER@
static void cmakeRequireSymbol(int dummy, ...) {
(void) dummy;
}
static void checkSymbol(void) {
#ifndef @CHECK_PROTOTYPE_DEFINITION_SYMBOL@
cmakeRequireSymbol(0, &@CHECK_PROTOTYPE_DEFINITION_SYMBOL@);
#endif
}
@CHECK_PROTOTYPE_DEFINITION_PROTO@ {
return @CHECK_PROTOTYPE_DEFINITION_RETURN@;
}
#ifdef __CLASSIC_C__
int main() {
int ac;
char*av[];
#else
int main(int ac, char *av[]) {
#endif
checkSymbol();
if (ac > 1000) {
return *av[0];
}
return 0;
}

View File

@ -0,0 +1,98 @@
# - Check if the protoype we expect is correct.
# check_prototype_definition(FUNCTION PROTOTYPE RETURN HEADER VARIABLE)
# FUNCTION - The name of the function (used to check if prototype exists)
# PROTOTYPE- The prototype to check.
# RETURN - The return value of the function.
# HEADER - The header files required.
# VARIABLE - The variable to store the result.
# Example:
# check_prototype_definition(getpwent_r
# "struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)"
# "NULL"
# "unistd.h;pwd.h"
# SOLARIS_GETPWENT_R)
# The following variables may be set before calling this macro to
# modify the way the check is run:
#
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
# CMAKE_REQUIRED_INCLUDES = list of include directories
# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
#=============================================================================
# Copyright 2005-2009 Kitware, Inc.
# Copyright 2010-2011 Andreas Schneider <asn@cryptomilk.org>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
#
get_filename_component(__check_proto_def_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
function(CHECK_PROTOTYPE_DEFINITION _FUNCTION _PROTOTYPE _RETURN _HEADER _VARIABLE)
if ("${_VARIABLE}" MATCHES "^${_VARIABLE}$")
set(CHECK_PROTOTYPE_DEFINITION_CONTENT "/* */\n")
set(CHECK_PROTOTYPE_DEFINITION_FLAGS ${CMAKE_REQUIRED_FLAGS})
if (CMAKE_REQUIRED_LIBRARIES)
set(CHECK_PROTOTYPE_DEFINITION_LIBS
LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
else()
set(CHECK_PROTOTYPE_DEFINITION_LIBS)
endif()
if (CMAKE_REQUIRED_INCLUDES)
set(CMAKE_SYMBOL_EXISTS_INCLUDES
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
else()
set(CMAKE_SYMBOL_EXISTS_INCLUDES)
endif()
foreach(_FILE ${_HEADER})
set(CHECK_PROTOTYPE_DEFINITION_HEADER
"${CHECK_PROTOTYPE_DEFINITION_HEADER}#include <${_FILE}>\n")
endforeach()
set(CHECK_PROTOTYPE_DEFINITION_SYMBOL ${_FUNCTION})
set(CHECK_PROTOTYPE_DEFINITION_PROTO ${_PROTOTYPE})
set(CHECK_PROTOTYPE_DEFINITION_RETURN ${_RETURN})
configure_file("${__check_proto_def_dir}/CheckPrototypeDefinition.c.in"
"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c" @ONLY)
file(READ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c _SOURCE)
try_compile(${_VARIABLE}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
${CHECK_PROTOTYPE_DEFINITION_LIBS}
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${CHECK_PROTOTYPE_DEFINITION_FLAGS}
"${CMAKE_SYMBOL_EXISTS_INCLUDES}"
OUTPUT_VARIABLE OUTPUT)
if (${_VARIABLE})
set(${_VARIABLE} 1 CACHE INTERNAL "Have correct prototype for ${_FUNCTION}")
message(STATUS "Checking prototype ${_FUNCTION} for ${_VARIABLE} - True")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Determining if the prototype ${_FUNCTION} exists for ${_VARIABLE} passed with the following output:\n"
"${OUTPUT}\n\n")
else ()
message(STATUS "Checking prototype ${_FUNCTION} for ${_VARIABLE} - False")
set(${_VARIABLE} 0 CACHE INTERNAL "Have correct prototype for ${_FUNCTION}")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if the prototype ${_FUNCTION} exists for ${_VARIABLE} failed with the following output:\n"
"${OUTPUT}\n\n${_SOURCE}\n\n")
endif ()
endif()
endfunction()

View File

@ -0,0 +1,30 @@
# Always include srcdir and builddir in include path
# This saves typing ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY} in
# about every subdir
# since cmake 2.4.0
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Put the include dirs which are in the source or build tree
# before all other include dirs, so the headers in the sources
# are prefered over the already installed ones
# since cmake 2.4.1
set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
# Use colored output
# since cmake 2.4.0
set(CMAKE_COLOR_MAKEFILE ON)
# Define the generic version of the libraries here
set(GENERIC_LIB_VERSION "0.1.0")
set(GENERIC_LIB_SOVERSION "0")
# set -Werror
set(CMAKE_ENABLE_WERROR ON)
# Set the default build type to release with debug info
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RelWithDebInfo
CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
)
endif (NOT CMAKE_BUILD_TYPE)

View File

@ -0,0 +1,88 @@
# define system dependent compiler flags
include(CheckCCompilerFlag)
include(CheckCCompilerFlagSSP)
#
# Define GNUCC compiler flags
#
if (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
# add -Wconversion ?
# cannot be pedantic with sqlite3 directly linked
if (NOT CSYNC_STATIC_COMPILE_DIR)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -pedantic-errors")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute -D_GNU_SOURCE")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__STDC_FORMAT_MACROS=1")
set(CSYNC_STRICT OFF CACHE BOOL "Strict error checking, enabled -Werror and friends")
if (CSYNC_STRICT)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
endif(CSYNC_STRICT)
# with -fPIC
check_c_compiler_flag("-fPIC" WITH_FPIC)
if (WITH_FPIC AND NOT WIN32)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
endif (WITH_FPIC AND NOT WIN32)
check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
if (WITH_STACK_PROTECTOR AND NOT WIN32)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
endif (WITH_STACK_PROTECTOR AND NOT WIN32)
if (CMAKE_BUILD_TYPE)
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
if (CMAKE_BUILD_TYPE_LOWER MATCHES "(release|relwithdebinfo|minsizerel)")
check_c_compiler_flag("-Wp,-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
if (WITH_FORTIFY_SOURCE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wp,-D_FORTIFY_SOURCE=2")
endif (WITH_FORTIFY_SOURCE)
endif()
endif()
endif (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
if (UNIX AND NOT WIN32)
#
# Check for large filesystem support
#
if (CMAKE_SIZEOF_VOID_P MATCHES "8")
# with large file support
execute_process(
COMMAND
getconf LFS64_CFLAGS
OUTPUT_VARIABLE
_lfs_CFLAGS
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
else (CMAKE_SIZEOF_VOID_P MATCHES "8")
# with large file support
execute_process(
COMMAND
getconf LFS_CFLAGS
OUTPUT_VARIABLE
_lfs_CFLAGS
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
if (_lfs_CFLAGS)
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_lfs_CFLAGS}")
endif (_lfs_CFLAGS)
else(UNIX AND NOT WIN32)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FILE_OFFSET_BITS=64")
endif (UNIX AND NOT WIN32)
if (MSVC)
# Use secure functions by defaualt and suppress warnings about
#"deprecated" functions
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
endif (MSVC)

View File

@ -0,0 +1,28 @@
# Set system vars
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
set(LINUX TRUE)
endif(CMAKE_SYSTEM_NAME MATCHES "Linux")
if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
set(FREEBSD TRUE)
set(BSD TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
set(OPENBSD TRUE)
set(BSD TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
if (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
set(NETBSD TRUE)
set(BSD TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
set(SOLARIS TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
if (CMAKE_SYSTEM_NAME MATCHES "OS2")
set(OS2 TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "OS2")

View File

@ -0,0 +1,49 @@
# - Try to find CMocka
# Once done this will define
#
# CMOCKA_ROOT_DIR - Set this variable to the root installation of CMocka
#
# Read-Only variables:
# CMOCKA_FOUND - system has CMocka
# CMOCKA_INCLUDE_DIR - the CMocka include directory
# CMOCKA_LIBRARIES - Link these to use CMocka
# CMOCKA_DEFINITIONS - Compiler switches required for using CMocka
#
#=============================================================================
# Copyright (c) 2011-2012 Andreas Schneider <asn@cryptomilk.org>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
#
find_path(CMOCKA_INCLUDE_DIR
NAMES
cmocka.h
PATHS
${CMOCKA_ROOT_DIR}/include
)
find_library(CMOCKA_LIBRARY
NAMES
cmocka
PATHS
${CMOCKA_ROOT_DIR}/include
)
if (CMOCKA_LIBRARY)
set(CMOCKA_LIBRARIES
${CMOCKA_LIBRARIES}
${CMOCKA_LIBRARY}
)
endif (CMOCKA_LIBRARY)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CMocka DEFAULT_MSG CMOCKA_LIBRARIES CMOCKA_INCLUDE_DIR)
# show the CMOCKA_INCLUDE_DIR and CMOCKA_LIBRARIES variables only in the advanced view
mark_as_advanced(CMOCKA_INCLUDE_DIR CMOCKA_LIBRARIES)

View File

@ -0,0 +1,82 @@
# - Try to find Iconv
# Once done this will define
#
# ICONV_FOUND - system has Iconv
# ICONV_INCLUDE_DIRS - the Iconv include directory
# ICONV_LIBRARIES - Link these to use Iconv
# ICONV_DEFINITIONS - Compiler switches required for using Iconv
#
# Copyright (c) 2013 Andreas Schneider <asn@cryptomilk.org>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
include(CheckIncludeFile)
include(CheckFunctionExists)
include(CheckLibraryExists)
include(CheckPrototypeDefinition)
find_path(ICONV_INCLUDE_DIR
NAMES
iconv.h sys/iconv.h
)
set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
check_include_file(iconv.h HAVE_ICONV_H)
check_include_file(sys/iconv.h HAVE_SYS_ICONV_H)
set(CMAKE_REQUIRED_INCLUDES)
find_library(ICONV_LIBRARY
NAMES
iconv
libiconv
PATHS
)
if (ICONV_LIBRARY)
get_filename_component(_ICONV_NAME ${ICONV_LIBRARY} NAME)
get_filename_component(_ICONV_PATH ${ICONV_LIBRARY} PATH)
check_library_exists(${_ICONV_NAME} iconv ${_ICONV_PATH} HAVE_ICONV)
else()
check_function_exists(iconv HAVE_ICONV)
endif()
if (HAVE_ICONV_H OR HAVE_SYS_ICONV_H)
if (HAVE_ICONV_H)
set(_ICONV_PROTO_INCLUDE "iconv.h")
endif (HAVE_ICONV_H)
if (HAVE_SYS_ICONV_H)
set(_ICONV_PROTO_INCLUDE "sys/iconv.h")
endif (HAVE_SYS_ICONV_H)
set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
check_prototype_definition(iconv
"size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)"
"-1"
${_ICONV_PROTO_INCLUDE}
HAVE_ICONV_CONST)
set(CMAKE_REQUIRED_INCLUDES)
endif (HAVE_ICONV_H OR HAVE_SYS_ICONV_H)
set(ICONV_INCLUDE_DIRS
${ICONV_INCLUDE_DIR}
)
if (ICONV_LIBRARY)
set(ICONV_LIBRARIES
${ICONV_LIBRARIES}
${ICONV_LIBRARY}
)
endif (ICONV_LIBRARY)
include(FindPackageHandleStandardArgs)
if (ICONV_LIBRARIES)
find_package_handle_standard_args(Iconv DEFAULT_MSG ICONV_LIBRARIES ICONV_INCLUDE_DIRS)
else()
find_package_handle_standard_args(Iconv DEFAULT_MSG ICONV_INCLUDE_DIRS)
endif()
# show the ICONV_INCLUDE_DIRS and ICONV_LIBRARIES variables only in the advanced view
mark_as_advanced(ICONV_INCLUDE_DIRS ICONV_LIBRARIES)

View File

@ -0,0 +1,96 @@
# - Try to find LibSSH
# Once done this will define
#
# LIBSSH_FOUND - system has LibSSH
# LIBSSH_INCLUDE_DIRS - the LibSSH include directory
# LIBSSH_LIBRARIES - Link these to use LibSSH
# LIBSSH_DEFINITIONS - Compiler switches required for using LibSSH
#
# Copyright (c) 2009 Andreas Schneider <asn@cryptomilk.org>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
if (LIBSSH_LIBRARIES AND LIBSSH_INCLUDE_DIRS)
# in cache already
set(LIBSSH_FOUND TRUE)
else (LIBSSH_LIBRARIES AND LIBSSH_INCLUDE_DIRS)
find_path(LIBSSH_INCLUDE_DIR
NAMES
libssh/libssh.h
PATHS
/usr/include
/usr/local/include
/opt/local/include
/sw/include
${CMAKE_INCLUDE_PATH}
${CMAKE_INSTALL_PREFIX}/include
)
find_library(SSH_LIBRARY
NAMES
ssh
libssh
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
${CMAKE_LIBRARY_PATH}
${CMAKE_INSTALL_PREFIX}/lib
)
if (LIBSSH_INCLUDE_DIR AND SSH_LIBRARY)
set(SSH_FOUND TRUE)
endif (LIBSSH_INCLUDE_DIR AND SSH_LIBRARY)
set(LIBSSH_INCLUDE_DIRS
${LIBSSH_INCLUDE_DIR}
)
if (SSH_FOUND)
set(LIBSSH_LIBRARIES
${LIBSSH_LIBRARIES}
${SSH_LIBRARY}
)
if (LibSSH_FIND_VERSION)
file(STRINGS ${LIBSSH_INCLUDE_DIR}/libssh/libssh.h LIBSSH_VERSION_MAJOR
REGEX "#define[ ]+LIBSSH_VERSION_MAJOR[ ]+[0-9]+")
# Older versions of libssh like libssh-0.2 have LIBSSH_VERSION but not LIBSSH_VERSION_MAJOR
if (LIBSSH_VERSION_MAJOR)
string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_MAJOR ${LIBSSH_VERSION_MAJOR})
file(STRINGS ${LIBSSH_INCLUDE_DIR}/libssh/libssh.h LIBSSH_VERSION_MINOR
REGEX "#define[ ]+LIBSSH_VERSION_MINOR[ ]+[0-9]+")
string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_MINOR ${LIBSSH_VERSION_MINOR})
file(STRINGS ${LIBSSH_INCLUDE_DIR}/libssh/libssh.h LIBSSH_VERSION_PATCH
REGEX "#define[ ]+LIBSSH_VERSION_MICRO[ ]+[0-9]+")
string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_PATCH ${LIBSSH_VERSION_PATCH})
set(LibSSH_VERSION ${LIBSSH_VERSION_MAJOR}.${LIBSSH_VERSION_MINOR}.${LIBSSH_VERSION_PATCH})
include(FindPackageVersionCheck)
find_package_version_check(LibSSH DEFAULT_MSG)
else (LIBSSH_VERSION_MAJOR)
message(STATUS "LIBSSH_VERSION_MAJOR not found in ${LIBSSH_INCLUDE_DIR}/libssh/libssh.h, assuming libssh is too old")
set(LIBSSH_FOUND FALSE)
endif (LIBSSH_VERSION_MAJOR)
endif (LibSSH_FIND_VERSION)
endif (SSH_FOUND)
# If the version is too old, but libs and includes are set,
# find_package_handle_standard_args will set LIBSSH_FOUND to TRUE again,
# so we need this if() here.
if (LIBSSH_FOUND)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LibSSH DEFAULT_MSG LIBSSH_LIBRARIES LIBSSH_INCLUDE_DIRS)
endif (LIBSSH_FOUND)
# show the LIBSSH_INCLUDE_DIRS and LIBSSH_LIBRARIES variables only in the advanced view
mark_as_advanced(LIBSSH_INCLUDE_DIRS LIBSSH_LIBRARIES)
endif (LIBSSH_LIBRARIES AND LIBSSH_INCLUDE_DIRS)

View File

@ -6,7 +6,7 @@
# NEON_LIBRARIES - Link these to use Neon
# NEON_DEFINITIONS - Compiler switches required for using Neon
#
# Copyright (c) 2011 Andreas Schneider <asn@cryptomilk.org>
# Copyright (c) 2011-2013 Andreas Schneider <asn@cryptomilk.org>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.

View File

@ -0,0 +1,306 @@
# - Try to find the OpenSSL encryption library
# Once done this will define
#
# OPENSSL_ROOT_DIR - Set this variable to the root installation of OpenSSL
#
# Read-Only variables:
# OPENSSL_FOUND - system has the OpenSSL library
# OPENSSL_INCLUDE_DIR - the OpenSSL include directory
# OPENSSL_LIBRARIES - The libraries needed to use OpenSSL
# OPENSSL_VERSION - This is set to $major.$minor.$revision$path (eg. 0.9.8s)
#=============================================================================
# Copyright 2006-2009 Kitware, Inc.
# Copyright 2006 Alexander Neundorf <neundorf@kde.org>
# Copyright 2009-2011 Mathieu Malaterre <mathieu.malaterre@gmail.com>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
if (UNIX)
find_package(PkgConfig QUIET)
pkg_check_modules(_OPENSSL QUIET openssl)
endif (UNIX)
# http://www.slproweb.com/products/Win32OpenSSL.html
SET(_OPENSSL_ROOT_HINTS
$ENV{OPENSSL_ROOT_DIR}
${OPENSSL_ROOT_DIR}
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
)
SET(_OPENSSL_ROOT_PATHS
"$ENV{PROGRAMFILES}/OpenSSL"
"$ENV{PROGRAMFILES}/OpenSSL-Win32"
"$ENV{PROGRAMFILES}/OpenSSL-Win64"
"C:/OpenSSL/"
"C:/OpenSSL-Win32/"
"C:/OpenSSL-Win64/"
)
SET(_OPENSSL_ROOT_HINTS_AND_PATHS
HINTS ${_OPENSSL_ROOT_HINTS}
PATHS ${_OPENSSL_ROOT_PATHS}
)
FIND_PATH(OPENSSL_INCLUDE_DIR
NAMES
openssl/ssl.h
HINTS
${_OPENSSL_INCLUDEDIR}
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
include
)
IF(WIN32 AND NOT CYGWIN)
# MINGW should go here too
IF(MSVC)
# /MD and /MDd are the standard values - if someone wants to use
# others, the libnames have to change here too
# use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b
# TODO: handle /MT and static lib
# In Visual C++ naming convention each of these four kinds of Windows libraries has it's standard suffix:
# * MD for dynamic-release
# * MDd for dynamic-debug
# * MT for static-release
# * MTd for static-debug
# Implementation details:
# We are using the libraries located in the VC subdir instead of the parent directory eventhough :
# libeay32MD.lib is identical to ../libeay32.lib, and
# ssleay32MD.lib is identical to ../ssleay32.lib
FIND_LIBRARY(LIB_EAY_DEBUG
NAMES
libeay32MDd
libeay32
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
"lib"
"VC"
"lib/VC"
)
FIND_LIBRARY(LIB_EAY_RELEASE
NAMES
libeay32MD
libeay32
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
"lib"
"VC"
"lib/VC"
)
FIND_LIBRARY(SSL_EAY_DEBUG
NAMES
ssleay32MDd
ssleay32
ssl
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
"lib"
"VC"
"lib/VC"
)
FIND_LIBRARY(SSL_EAY_RELEASE
NAMES
ssleay32MD
ssleay32
ssl
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
"lib"
"VC"
"lib/VC"
)
if( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
set( OPENSSL_LIBRARIES
optimized ${SSL_EAY_RELEASE} debug ${SSL_EAY_DEBUG}
optimized ${LIB_EAY_RELEASE} debug ${LIB_EAY_DEBUG}
)
else()
set( OPENSSL_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} )
endif()
MARK_AS_ADVANCED(SSL_EAY_DEBUG SSL_EAY_RELEASE)
MARK_AS_ADVANCED(LIB_EAY_DEBUG LIB_EAY_RELEASE)
ELSEIF(MINGW)
# same player, for MingW
FIND_LIBRARY(LIB_EAY
NAMES
libeay32
crypto
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
"lib"
"lib/MinGW"
)
FIND_LIBRARY(SSL_EAY
NAMES
ssleay32
ssl
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
"lib"
"lib/MinGW"
)
MARK_AS_ADVANCED(SSL_EAY LIB_EAY)
set( OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY} )
ELSE(MSVC)
# Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues:
FIND_LIBRARY(LIB_EAY
NAMES
libeay32
HINTS
${_OPENSSL_LIBDIR}
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
lib
)
FIND_LIBRARY(SSL_EAY
NAMES
ssleay32
HINTS
${_OPENSSL_LIBDIR}
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
lib
)
MARK_AS_ADVANCED(SSL_EAY LIB_EAY)
set( OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY} )
ENDIF(MSVC)
ELSE(WIN32 AND NOT CYGWIN)
FIND_LIBRARY(OPENSSL_SSL_LIBRARY
NAMES
ssl
ssleay32
ssleay32MD
HINTS
${_OPENSSL_LIBDIR}
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
lib
)
FIND_LIBRARY(OPENSSL_CRYPTO_LIBRARY
NAMES
crypto
HINTS
${_OPENSSL_LIBDIR}
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
lib
)
MARK_AS_ADVANCED(OPENSSL_CRYPTO_LIBRARY OPENSSL_SSL_LIBRARY)
# compat defines
SET(OPENSSL_SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY})
SET(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
SET(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY})
ENDIF(WIN32 AND NOT CYGWIN)
function(from_hex HEX DEC)
string(TOUPPER "${HEX}" HEX)
set(_res 0)
string(LENGTH "${HEX}" _strlen)
while (_strlen GREATER 0)
math(EXPR _res "${_res} * 16")
string(SUBSTRING "${HEX}" 0 1 NIBBLE)
string(SUBSTRING "${HEX}" 1 -1 HEX)
if (NIBBLE STREQUAL "A")
math(EXPR _res "${_res} + 10")
elseif (NIBBLE STREQUAL "B")
math(EXPR _res "${_res} + 11")
elseif (NIBBLE STREQUAL "C")
math(EXPR _res "${_res} + 12")
elseif (NIBBLE STREQUAL "D")
math(EXPR _res "${_res} + 13")
elseif (NIBBLE STREQUAL "E")
math(EXPR _res "${_res} + 14")
elseif (NIBBLE STREQUAL "F")
math(EXPR _res "${_res} + 15")
else()
math(EXPR _res "${_res} + ${NIBBLE}")
endif()
string(LENGTH "${HEX}" _strlen)
endwhile()
set(${DEC} ${_res} PARENT_SCOPE)
endfunction(from_hex)
if (OPENSSL_INCLUDE_DIR)
if (_OPENSSL_VERSION)
set(OPENSSL_VERSION "${_OPENSSL_VERSION}")
elseif(OPENSSL_INCLUDE_DIR AND EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h")
file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_str
REGEX "^#define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])+.*")
# The version number is encoded as 0xMNNFFPPS: major minor fix patch status
# The status gives if this is a developer or prerelease and is ignored here.
# Major, minor, and fix directly translate into the version numbers shown in
# the string. The patch field translates to the single character suffix that
# indicates the bug fix state, which 00 -> nothing, 01 -> a, 02 -> b and so
# on.
string(REGEX REPLACE "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F]).*$"
"\\1;\\2;\\3;\\4;\\5" OPENSSL_VERSION_LIST "${openssl_version_str}")
list(GET OPENSSL_VERSION_LIST 0 OPENSSL_VERSION_MAJOR)
list(GET OPENSSL_VERSION_LIST 1 OPENSSL_VERSION_MINOR)
from_hex("${OPENSSL_VERSION_MINOR}" OPENSSL_VERSION_MINOR)
list(GET OPENSSL_VERSION_LIST 2 OPENSSL_VERSION_FIX)
from_hex("${OPENSSL_VERSION_FIX}" OPENSSL_VERSION_FIX)
list(GET OPENSSL_VERSION_LIST 3 OPENSSL_VERSION_PATCH)
if (NOT OPENSSL_VERSION_PATCH STREQUAL "00")
from_hex("${OPENSSL_VERSION_PATCH}" _tmp)
# 96 is the ASCII code of 'a' minus 1
math(EXPR OPENSSL_VERSION_PATCH_ASCII "${_tmp} + 96")
unset(_tmp)
# Once anyone knows how OpenSSL would call the patch versions beyond 'z'
# this should be updated to handle that, too. This has not happened yet
# so it is simply ignored here for now.
string(ASCII "${OPENSSL_VERSION_PATCH_ASCII}" OPENSSL_VERSION_PATCH_STRING)
endif (NOT OPENSSL_VERSION_PATCH STREQUAL "00")
set(OPENSSL_VERSION "${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_FIX}${OPENSSL_VERSION_PATCH_STRING}")
endif (_OPENSSL_VERSION)
endif (OPENSSL_INCLUDE_DIR)
include(FindPackageHandleStandardArgs)
if (OPENSSL_VERSION)
find_package_handle_standard_args(OpenSSL
REQUIRED_VARS
OPENSSL_LIBRARIES
OPENSSL_INCLUDE_DIR
VERSION_VAR
OPENSSL_VERSION
FAIL_MESSAGE
"Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
)
else (OPENSSL_VERSION)
find_package_handle_standard_args(OpenSSL "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
OPENSSL_LIBRARIES
OPENSSL_INCLUDE_DIR
)
endif (OPENSSL_VERSION)
MARK_AS_ADVANCED(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES)

View File

@ -0,0 +1,68 @@
# FIND_PACKAGE_VERSION_CHECK(NAME (DEFAULT_MSG|"Custom failure message"))
# This function is intended to be used in FindXXX.cmake modules files.
# It handles NAME_FIND_VERSION and NAME_VERSION variables in a Module.
#
# Example:
# find_package(LibSSH 0.3.2)
#
# # check for the version and set it
# set(LibSSH_VERSION 0.3.0)
# find_package_version_check(LibSSH DEFAULT_MSG)
#
#
# Copyright (c) 2009 Andreas Schneider <asn@cryptomilk.org>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
function(FIND_PACKAGE_VERSION_CHECK _NAME _FAIL_MSG)
string(TOUPPER ${_NAME} _NAME_UPPER)
set(_AGE "old")
if(${_NAME}_FIND_VERSION_EXACT)
if (${_NAME}_FIND_VERSION VERSION_EQUAL ${_NAME}_VERSION)
# exact version found
set(${_NAME_UPPER}_FOUND TRUE)
else (${_NAME}_FIND_VERSION VERSION_EQUAL ${_NAME}_VERSION)
# exect version not found
set(${_NAME_UPPER}_FOUND FALSE)
# check if newer or older
if (${_NAME}_FIND_VERSION VERSION_LESS ${_NAME}_VERSION)
set(_AGE "new")
else (${_NAME}_FIND_VERSION VERSION_LESS ${_NAME}_VERSION)
set(_AGE "old")
endif (${_NAME}_FIND_VERSION VERSION_LESS ${_NAME}_VERSION)
endif (${_NAME}_FIND_VERSION VERSION_EQUAL ${_NAME}_VERSION)
else (${_NAME}_FIND_VERSION_EXACT)
if (${_NAME}_FIND_VERSION)
if (${_NAME}_VERSION VERSION_LESS ${_NAME}_FIND_VERSION)
set(${_NAME_UPPER}_FOUND FALSE)
set(_AGE "old")
else (${_NAME}_VERSION VERSION_LESS ${_NAME}_FIND_VERSION)
set(${_NAME_UPPER}_FOUND TRUE)
endif (${_NAME}_VERSION VERSION_LESS ${_NAME}_FIND_VERSION)
endif (${_NAME}_FIND_VERSION)
endif(${_NAME}_FIND_VERSION_EXACT)
if ("${_FAIL_MSG}" STREQUAL "DEFAULT_MSG")
if (${_NAME}_FIND_VERSION_EXACT)
set(_FAIL_MESSAGE "The installed ${_NAME} version ${${_NAME}_VERSION} is too ${_AGE}, version ${${_NAME}_FIND_VERSION} is required.")
else (${_NAME}_FIND_VERSION_EXACT)
set(_FAIL_MESSAGE "The installed ${_NAME} version ${${_NAME}_VERSION} is too ${_AGE}, at least version ${${_NAME}_FIND_VERSION} is required.")
endif (${_NAME}_FIND_VERSION_EXACT)
else ("${_FAIL_MSG}" STREQUAL "DEFAULT_MSG")
set(_FAIL_MESSAGE "${_FAIL_MSG}")
endif ("${_FAIL_MSG}" STREQUAL "DEFAULT_MSG")
if (NOT ${_NAME_UPPER}_FOUND)
if (${_NAME}_FIND_REQUIRED)
message(FATAL_ERROR "${_FAIL_MESSAGE}")
else (${_NAME}_FIND_REQUIRED)
if (NOT ${_NAME}_FIND_QUIETLY)
message(STATUS "${_FAIL_MESSAGE}")
endif (NOT ${_NAME}_FIND_QUIETLY)
endif (${_NAME}_FIND_REQUIRED)
endif (NOT ${_NAME_UPPER}_FOUND)
set(${_NAME_UPPER}_FOUND ${${_NAME_UPPER}_FOUND} PARENT_SCOPE)
endfunction(FIND_PACKAGE_VERSION_CHECK)

View File

@ -0,0 +1,66 @@
# - Try to find SMBClient
# Once done this will define
#
# SMBCLIENT_FOUND - system has SMBClient
# SMBCLIENT_INCLUDE_DIRS - the SMBClient include directory
# SMBCLIENT_LIBRARIES - Link these to use SMBClient
# SMBCLIENT_DEFINITIONS - Compiler switches required for using SMBClient
#
# Copyright (c) 2013 Andreas Schneider <asn@cryptomilk.org>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
if (SMBCLIENT_LIBRARIES AND SMBCLIENT_INCLUDE_DIRS)
# in cache already
set(SMBCLIENT_FOUND TRUE)
else (SMBCLIENT_LIBRARIES AND SMBCLIENT_INCLUDE_DIRS)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(_SMBCLIENT smbclient)
endif (PKG_CONFIG_FOUND)
find_path(SMBCLIENT_INCLUDE_DIR
NAMES
libsmbclient.h
PATHS
${_SMBCLIENT_INCLUDEDIR}
/usr/include
/usr/local/include
/opt/local/include
/sw/include
)
find_library(SMBCLIENT_LIBRARY
NAMES
smbclient
PATHS
${_SMBCLIENT_LIBDIR}
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
set(SMBCLIENT_INCLUDE_DIRS
${SMBCLIENT_INCLUDE_DIR}
)
if (SMBCLIENT_LIBRARY)
set(SMBCLIENT_LIBRARIES
${SMBCLIENT_LIBRARIES}
${SMBCLIENT_LIBRARY}
)
endif (SMBCLIENT_LIBRARY)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SMBClient DEFAULT_MSG SMBCLIENT_LIBRARIES SMBCLIENT_INCLUDE_DIRS)
# show the SMBCLIENT_INCLUDE_DIRS and SMBCLIENT_LIBRARIES variables only in the advanced view
mark_as_advanced(SMBCLIENT_INCLUDE_DIRS SMBCLIENT_LIBRARIES)
endif (SMBCLIENT_LIBRARIES AND SMBCLIENT_INCLUDE_DIRS)

View File

@ -0,0 +1,58 @@
# - Try to find SQLite3
# Once done this will define
#
# SQLITE3_FOUND - system has SQLite3
# SQLITE3_INCLUDE_DIRS - the SQLite3 include directory
# SQLITE3_LIBRARIES - Link these to use SQLite3
# SQLITE3_DEFINITIONS - Compiler switches required for using SQLite3
#
# Copyright (c) 2009-2013 Andreas Schneider <asn@cryptomilk.org>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
if (UNIX)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(_SQLITE3 sqlite3)
endif (PKG_CONFIG_FOUND)
endif (UNIX)
find_path(SQLITE3_INCLUDE_DIR
NAMES
sqlite3.h
PATHS
${_SQLITE3_INCLUDEDIR}
)
find_library(SQLITE3_LIBRARY
NAMES
sqlite3
PATHS
${_SQLITE3_LIBDIR}
)
set(SQLITE3_INCLUDE_DIRS
${SQLITE3_INCLUDE_DIR}
)
if (SQLITE3_LIBRARY)
set(SQLITE3_LIBRARIES
${SQLITE3_LIBRARIES}
${SQLITE3_LIBRARY}
)
endif (SQLITE3_LIBRARY)
if (SQLite3_FIND_VERSION AND _SQLITE3_VERSION)
set(SQLite3_VERSION _SQLITE3_VERSION)
endif (SQLite3_FIND_VERSION AND _SQLITE3_VERSION)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SQLite3 DEFAULT_MSG SQLITE3_LIBRARIES SQLITE3_INCLUDE_DIRS)
# show the SQLITE3_INCLUDE_DIRS and SQLITE3_LIBRARIES variables only in the advanced view
mark_as_advanced(SQLITE3_INCLUDE_DIRS SQLITE3_LIBRARIES)

View File

@ -0,0 +1,21 @@
# - MACRO_ADD_COMPILE_FLAGS(target_name flag1 ... flagN)
# Copyright (c) 2006, Oswald Buddenhagen, <ossi@kde.org>
# Copyright (c) 2006, Andreas Schneider, <asn@cryptomilk.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
macro (MACRO_ADD_COMPILE_FLAGS _target)
get_target_property(_flags ${_target} COMPILE_FLAGS)
if (_flags)
set(_flags ${_flags} ${ARGN})
else (_flags)
set(_flags ${ARGN})
endif (_flags)
set_target_properties(${_target} PROPERTIES COMPILE_FLAGS ${_flags})
endmacro (MACRO_ADD_COMPILE_FLAGS)

View File

@ -0,0 +1,20 @@
# - MACRO_ADD_LINK_FLAGS(target_name flag1 ... flagN)
# Copyright (c) 2006, Oswald Buddenhagen, <ossi@kde.org>
# Copyright (c) 2006, Andreas Schneider, <asn@cryptomilk.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
macro (MACRO_ADD_LINK_FLAGS _target)
get_target_property(_flags ${_target} LINK_FLAGS)
if (_flags)
set(_flags "${_flags} ${ARGN}")
else (_flags)
set(_flags "${ARGN}")
endif (_flags)
set_target_properties(${_target} PROPERTIES LINK_FLAGS "${_flags}")
endmacro (MACRO_ADD_LINK_FLAGS)

View File

@ -0,0 +1,30 @@
# - MACRO_ADD_PLUGIN(name [WITH_PREFIX] file1 .. fileN)
#
# Create a plugin from the given source files.
# If WITH_PREFIX is given, the resulting plugin will have the
# prefix "lib", otherwise it won't.
#
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
# Copyright (c) 2006, Laurent Montel, <montel@kde.org>
# Copyright (c) 2006, Andreas Schneider, <asn@cryptomilk.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
macro (MACRO_ADD_PLUGIN _target_NAME _with_PREFIX)
if (${_with_PREFIX} STREQUAL "WITH_PREFIX")
set(_first_SRC)
else (${_with_PREFIX} STREQUAL "WITH_PREFIX")
set(_first_SRC ${_with_PREFIX})
endif (${_with_PREFIX} STREQUAL "WITH_PREFIX")
add_library(${_target_NAME} MODULE ${_first_SRC} ${ARGN})
if (_first_SRC)
set_target_properties(${_target_NAME} PROPERTIES PREFIX "")
endif (_first_SRC)
endmacro (MACRO_ADD_PLUGIN _name _sources)

View File

@ -0,0 +1,33 @@
# - macro_copy_file(_src _dst)
# Copies a file to ${_dst} only if ${_src} is different (newer) than ${_dst}
#
# Example:
# macro_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/icon.png ${CMAKE_CURRENT_BINARY_DIR}/.)
# Copies file icon.png to ${CMAKE_CURRENT_BINARY_DIR} directory
#
# Copyright (c) 2006-2007 Wengo
# Copyright (c) 2006-2008 Andreas Schneider <asn@cryptomilk.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING file.
macro (macro_copy_file _src _dst)
# Removes all path containing .svn or CVS or CMakeLists.txt during the copy
if (NOT ${_src} MATCHES ".*\\.svn|CVS|CMakeLists\\.txt.*")
if (CMAKE_VERBOSE_MAKEFILE)
message(STATUS "Copy file from ${_src} to ${_dst}")
endif (CMAKE_VERBOSE_MAKEFILE)
# Creates directory if necessary
get_filename_component(_path ${_dst} PATH)
file(MAKE_DIRECTORY ${_path})
execute_process(
COMMAND
${CMAKE_COMMAND} -E copy_if_different ${_src} ${_dst}
OUTPUT_QUIET
)
endif (NOT ${_src} MATCHES ".*\\.svn|CVS|CMakeLists\\.txt.*")
endmacro (macro_copy_file)

View File

@ -0,0 +1,17 @@
# - MACRO_ENSURE_OUT_OF_SOURCE_BUILD(<errorMessage>)
# MACRO_ENSURE_OUT_OF_SOURCE_BUILD(<errorMessage>)
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
macro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD _errorMessage)
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" _insource)
if (_insource)
message(SEND_ERROR "${_errorMessage}")
message(FATAL_ERROR "Remove the file CMakeCache.txt in ${CMAKE_SOURCE_DIR} first.")
endif (_insource)
endmacro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD)

View File

@ -0,0 +1,58 @@
# - macro_asciidoc2man(inputfile outputfile)
#
# Create a manpage with asciidoc.
# Example: macro_asciidoc2man(foo.txt foo.1)
#
# Copyright (c) 2006, Andreas Schneider, <asn@cryptomilk.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
include(MacroCopyFile)
macro(MACRO_ASCIIDOC2MAN _a2m_input _a2m_output)
find_program(A2X
NAMES
a2x
)
#message("+++ A2X: ${A2X}")
if (A2X)
#message("+++ ${A2X} --doctype=manpage --format=manpage --destination-dir=${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${_a2m_input}")
macro_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/${_a2m_input} ${CMAKE_CURRENT_BINARY_DIR}/${_a2m_input})
execute_process(
COMMAND
${A2X} --doctype=manpage --format=manpage ${_a2m_input}
WORKING_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}
RESULT_VARIABLE
A2M_MAN_GENERATED
ERROR_QUIET
)
#message("+++ A2M_MAN_GENERATED: ${A2M_MAN_GENERATED}")
if (A2M_MAN_GENERATED EQUAL 0)
find_file(A2M_MAN_FILE
NAME
${_a2m_output}
PATHS
${CMAKE_CURRENT_BINARY_DIR}
NO_DEFAULT_PATH
)
if (A2M_MAN_FILE)
get_filename_component(A2M_MAN_CATEGORY ${A2M_MAN_FILE} EXT)
string(SUBSTRING ${A2M_MAN_CATEGORY} 1 1 A2M_MAN_CATEGORY)
install(
FILES
${A2M_MAN_FILE}
DESTINATION
${MAN_INSTALL_DIR}/man${A2M_MAN_CATEGORY}
)
endif (A2M_MAN_FILE)
endif (A2M_MAN_GENERATED EQUAL 0)
endif (A2X)
endmacro(MACRO_ASCIIDOC2MAN _a2m_input _a2m_file)

View File

@ -0,0 +1,127 @@
# -helper macro to add a "doc" target with CMake build system.
# and configure doxy.config.in to doxy.config
#
# target "doc" allows building the documentation with doxygen/dot on WIN32 and Linux
# Creates .chm windows help file if MS HTML help workshop
# (available from http://msdn.microsoft.com/workshop/author/htmlhelp)
# is installed with its DLLs in PATH.
#
#
# Please note, that the tools, e.g.:
# doxygen, dot, latex, dvips, makeindex, gswin32, etc.
# must be in path.
#
# Note about Visual Studio Projects:
# MSVS has its own path environment which may differ from the shell.
# See "Menu Tools/Options/Projects/VC++ Directories" in VS 7.1
#
# author Jan Woetzel 2004-2006
# www.mip.informatik.uni-kiel.de/~jw
FIND_PACKAGE(Doxygen)
IF (DOXYGEN_FOUND)
# click+jump in Emacs and Visual Studio (for doxy.config) (jw)
IF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
SET(DOXY_WARN_FORMAT "\"$file($line) : $text \"")
ELSE (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
SET(DOXY_WARN_FORMAT "\"$file:$line: $text \"")
ENDIF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
# we need latex for doxygen because of the formulas
FIND_PACKAGE(LATEX)
IF (NOT LATEX_COMPILER)
MESSAGE(STATUS "latex command LATEX_COMPILER not found but usually required. You will probably get warnings and user inetraction on doxy run.")
ENDIF (NOT LATEX_COMPILER)
IF (NOT MAKEINDEX_COMPILER)
MESSAGE(STATUS "makeindex command MAKEINDEX_COMPILER not found but usually required.")
ENDIF (NOT MAKEINDEX_COMPILER)
IF (NOT DVIPS_CONVERTER)
MESSAGE(STATUS "dvips command DVIPS_CONVERTER not found but usually required.")
ENDIF (NOT DVIPS_CONVERTER)
FIND_PROGRAM(DOXYGEN_DOT_EXECUTABLE_PATH NAMES dot)
IF (DOXYGEN_DOT_EXECUTABLE_PATH)
SET(DOXYGEN_DOT_FOUND "YES")
ENDIF (DOXYGEN_DOT_EXECUTABLE_PATH)
IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
MESSAGE(STATUS "Generate ${CMAKE_CURRENT_BINARY_DIR}/doxy.config from doxy.config.in")
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in
${CMAKE_CURRENT_BINARY_DIR}/doxy.config
@ONLY )
# use (configured) doxy.config from (out of place) BUILD tree:
SET(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
# use static hand-edited doxy.config from SOURCE tree:
SET(DOXY_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
MESSAGE(STATUS "WARNING: using existing ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config instead of configuring from doxy.config.in file.")
ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
IF (EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
# using template doxy.config.in
MESSAGE(STATUS "Generate ${CMAKE_CURRENT_BINARY_DIR}/doxy.config from doxy.config.in")
CONFIGURE_FILE(${CMAKE_MODULE_PATH}/doxy.config.in
${CMAKE_CURRENT_BINARY_DIR}/doxy.config
@ONLY )
SET(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
ELSE (EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
# failed completely...
MESSAGE(SEND_ERROR "Please create ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in (or doxy.config as fallback)")
ENDIF(EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
ADD_CUSTOM_TARGET(doc ${DOXYGEN_EXECUTABLE} ${DOXY_CONFIG} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
# create a windows help .chm file using hhc.exe
# HTMLHelp DLL must be in path!
# fallback: use hhw.exe interactively
IF (WIN32)
FIND_PACKAGE(HTMLHelp)
IF (HTML_HELP_COMPILER)
SET (TMP "${CMAKE_CURRENT_BINARY_DIR}\\doc\\html\\index.hhp")
STRING(REGEX REPLACE "[/]" "\\\\" HHP_FILE ${TMP} )
# MESSAGE(SEND_ERROR "DBG HHP_FILE=${HHP_FILE}")
ADD_CUSTOM_TARGET(winhelp ${HTML_HELP_COMPILER} ${HHP_FILE})
ADD_DEPENDENCIES (winhelp doc)
IF (NOT TARGET_DOC_SKIP_INSTALL)
# install windows help?
# determine useful name for output file
# should be project and version unique to allow installing
# multiple projects into one global directory
IF (EXISTS "${PROJECT_BINARY_DIR}/doc/html/index.chm")
IF (PROJECT_NAME)
SET(OUT "${PROJECT_NAME}")
ELSE (PROJECT_NAME)
SET(OUT "Documentation") # default
ENDIF(PROJECT_NAME)
IF (${PROJECT_NAME}_VERSION_MAJOR)
SET(OUT "${OUT}-${${PROJECT_NAME}_VERSION_MAJOR}")
IF (${PROJECT_NAME}_VERSION_MINOR)
SET(OUT "${OUT}.${${PROJECT_NAME}_VERSION_MINOR}")
IF (${PROJECT_NAME}_VERSION_PATCH)
SET(OUT "${OUT}.${${PROJECT_NAME}_VERSION_PATCH}")
ENDIF(${PROJECT_NAME}_VERSION_PATCH)
ENDIF(${PROJECT_NAME}_VERSION_MINOR)
ENDIF(${PROJECT_NAME}_VERSION_MAJOR)
# keep suffix
SET(OUT "${OUT}.chm")
#MESSAGE("DBG ${PROJECT_BINARY_DIR}/doc/html/index.chm \n${OUT}")
# create target used by install and package commands
INSTALL(FILES "${PROJECT_BINARY_DIR}/doc/html/index.chm"
DESTINATION "doc"
RENAME "${OUT}"
)
ENDIF(EXISTS "${PROJECT_BINARY_DIR}/doc/html/index.chm")
ENDIF(NOT TARGET_DOC_SKIP_INSTALL)
ENDIF(HTML_HELP_COMPILER)
# MESSAGE(SEND_ERROR "HTML_HELP_COMPILER=${HTML_HELP_COMPILER}")
ENDIF (WIN32)
ENDIF(DOXYGEN_FOUND)

View File

@ -0,0 +1,154 @@
#!/usr/bin/env ruby
# Simple script to generate simple cmake modules for finding
# libraries (packages)
#
# usage: generate_findpackage_file
# then you will be prompted to enter the required parameters
#
#####################################################################
#
# Copyright (c) 2006 Alexander Neundorf <neundorf@kde.org>
# Copyright (c) 2006 Andreas Schneider <asn@cryptomilk.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.
#
require 'readline'
package=Readline.readline("Name of package: ")
name=Readline.readline("\nYour Name (for copyright): ")
email=Readline.readline("\nYour mail (for copyright): ")
pkgconfig=Readline.readline("\npkgconfig package name (e.g. \"libxml-2.0\", leave empty to skip pkgconfig): ")
header=Readline.readline("\nLook for header (e.g. \"jpeglib.h\" or \"libxml/xpath.h\"): ")
incSubDir=Readline.readline("\nLook for header subdir (e.g. \"libxml2\", empty to skip ): ")
libs=Readline.readline("\nLook for library (e.g. \"xml2\" or \"avcodec avutil\"): ")
t = Time.now
cmakeIncDirName=package.upcase+"_INCLUDE_DIR"
cmakeIncDirNames=package.upcase+"_INCLUDE_DIRS"
cmakeLibNames=package.upcase+"_LIBRARIES"
cmakeDefsName=package.upcase+"_DEFINITIONS"
cmakeFoundName=package.upcase+"_FOUND"
cmakeQuietName=package+"_FIND_QUIETLY"
cmakeRequiredName=package+"_FIND_REQUIRED"
file=File.new("Find#{package}.cmake", "w+")
file.printf("# - Try to find #{package}\n")
file.printf("# Once done this will define\n")
file.printf("#\n")
file.printf("# #{cmakeFoundName} - system has #{package}\n")
file.printf("# #{cmakeIncDirNames} - the #{package} include directory\n")
file.printf("# #{cmakeLibNames} - Link these to use #{package}\n")
file.printf("# #{cmakeDefsName} - Compiler switches required for using #{package}\n")
file.printf("#\n")
file.printf("# Copyright (c) #{t.year} #{name} <#{email}>\n")
file.printf("#\n")
file.printf("# Redistribution and use is allowed according to the terms of the New\n")
file.printf("# BSD license.\n")
file.printf("# For details see the accompanying COPYING-CMAKE-SCRIPTS file.\n")
file.printf("#\n")
file.printf("\n")
file.printf("\n")
file.printf("if (#{cmakeLibNames} AND #{cmakeIncDirNames})\n")
file.printf(" # in cache already\n")
file.printf(" set(#{cmakeFoundName} TRUE)\n")
file.printf("else (#{cmakeLibNames} AND #{cmakeIncDirNames})\n")
if not pkgconfig.empty?
file.printf(" find_package(PkgConfig)\n")
file.printf(" if (PKG_CONFIG_FOUND)\n")
file.printf(" pkg_check_modules(_#{package.upcase} #{pkgconfig})\n")
file.printf(" endif (PKG_CONFIG_FOUND)\n")
end
file.printf("\n")
file.printf(" find_path(#{cmakeIncDirName}\n")
file.printf(" NAMES\n")
file.printf(" #{header}\n")
file.printf(" PATHS\n")
if not pkgconfig.empty?
file.printf(" ${_#{package.upcase}_INCLUDEDIR}\n")
end
file.printf(" /usr/include\n")
file.printf(" /usr/local/include\n")
file.printf(" /opt/local/include\n")
file.printf(" /sw/include\n")
if not incSubDir.empty?
file.printf(" PATH_SUFFIXES\n")
file.printf(" #{incSubDir}\n")
end
file.printf(" )\n")
file.printf("\n")
libs.split(" ").each do |lib|
file.printf(" find_library(#{lib.upcase}_LIBRARY\n")
file.printf(" NAMES\n")
file.printf(" #{lib}\n")
file.printf(" PATHS\n")
if not pkgconfig.empty?
file.printf(" ${_#{package.upcase}_LIBDIR}\n")
end
file.printf(" /usr/lib\n")
file.printf(" /usr/local/lib\n")
file.printf(" /opt/local/lib\n")
file.printf(" /sw/lib\n")
file.printf(" )\n")
file.printf("\n")
end
file.printf(" set(#{cmakeIncDirNames}\n")
file.printf(" ${#{cmakeIncDirName}}\n")
file.printf(" )\n")
file.printf("\n")
libs.split(" ").each do |lib|
file.printf(" if (#{lib.upcase}_LIBRARY)\n")
file.printf(" set(#{cmakeLibNames}\n")
file.printf(" ${#{cmakeLibNames}}\n")
file.printf(" ${#{lib.upcase}_LIBRARY}\n")
file.printf(" )\n")
file.printf(" endif (#{lib.upcase}_LIBRARY)\n")
file.printf("\n")
end
file.printf(" include(FindPackageHandleStandardArgs)\n")
file.printf(" find_package_handle_standard_args(#{package} DEFAULT_MSG #{cmakeLibNames} #{cmakeIncDirNames})\n")
file.printf("\n")
file.printf(" # show the #{cmakeIncDirNames} and #{cmakeLibNames} variables only in the advanced view\n")
file.printf(" mark_as_advanced(#{cmakeIncDirNames} #{cmakeLibNames})\n\n")
file.printf("endif (#{cmakeLibNames} AND #{cmakeIncDirNames})\n\n")
printf("Done, generated Find#{package}.cmake\n")

View File

@ -0,0 +1,135 @@
#!/usr/bin/env ruby
# simple script to generate CMakeLists.txt for wengophone libs
#
# usage: generate_lib_file
# then you will be prompted to enter the required parameters
#
#####################################################################
#
# Copyright (c) 2006 Andreas Schneider <asn@cryptomilk.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.
#
print("Name of project: ")
project=gets.chomp
printf("\n")
print("Other projects to includes (e.g. \"owutil tinyxml\", leave emtpy to skip): ")
otherprojects=gets.chomp
printf("\n")
print("Defininitions (leave empty to skip): ")
definitions=gets.chomp
cmakePublicIncDirName = project.upcase+"_PUBLIC_INCLUDE_DIRS"
cmakePrivateIncDirName = project.upcase+"_PRIVATE_INCLUDE_DIRS"
cmakeLibName = project.upcase+"_LIBRARY"
cmakeLibNames = project.upcase+"_LINK_LIBRARIES"
cmakePublicDefsName = project.upcase+"_PUBLIC_DEFINITIONS"
cmakePrivateDefsName = project.upcase+"_PRIVATE_DEFINITIONS"
file=File.new("CMakeLists.txt", "w+")
file.printf("project(#{project})\n")
file.printf("\n")
file.printf("# needed include directories to build #{project}\n")
file.printf("# saves the variable in internal cache for later use\n")
file.printf("set(#{cmakePublicIncDirName}\n")
file.printf(" ${CMAKE_CURRENT_SOURCE_DIR}\n")
file.printf(" ${CMAKE_CURRENT_SOURCE_DIR}/include\n")
file.printf(" CACHE INTERNAL \"#{project} public include directories\"\n")
file.printf(")\n")
file.printf("\n")
file.printf("set(#{cmakePrivateIncDirName}\n")
otherprojects.split(" ").each do |otherproject|
file.printf(" ${#{otherproject.upcase}_PUBLIC_INCLUDE_DIRS}\n")
end
file.printf(" ${CMAKE_CURRENT_BINARY_DIR}\n")
file.printf(")\n")
file.printf("\n")
file.printf("set(#{cmakeLibName}\n")
file.printf(" #{project}\n")
file.printf(" CACHE INTERNAL \"#{project} library\"\n")
file.printf(")\n")
file.printf("\n")
file.printf("# #{project} lib and dependencies\n")
file.printf("set(#{cmakeLibNames}\n")
file.printf(" #{cmakeLibName}\n")
otherprojects.split(" ").each do |otherproject|
file.printf(" ${#{otherproject.upcase}_LIBRARIES}\n")
end
file.printf(")\n")
file.printf("\n")
if not definitions.empty?
file.printf("set(#{cmakePublicDefsName}\n")
file.printf(" #{definitions}\n")
file.printf(" CACHE INTERNAL \"#{project} public definitions\"\n")
file.printf(")\n")
file.printf("\n")
file.printf("set(#{cmakePrivateDefsName}\n")
file.printf(" #{definitions}\n")
file.printf(")\n")
file.printf("\n")
end
file.printf("set(#{project}_SRCS\n")
file.printf(" files.c\n")
file.printf(")\n")
file.printf("\n")
file.printf("include_directories(\n")
file.printf(" ${#{cmakePublicIncDirName}}\n")
file.printf(" ${#{cmakePrivateIncDirName}}\n")
file.printf(")\n")
file.printf("\n")
if not definitions.empty?
file.printf("add_definitions(\n")
file.printf(" ${#{cmakePublicDefsName}}\n")
file.printf(" ${#{cmakePrivateDefsName}}\n")
file.printf(")\n")
file.printf("\n")
end
file.printf("\n")
file.printf("add_library(${#{cmakeLibName}} STATIC ${#{project}_SRCS})\n")
file.printf("\n")
file.printf("target_link_libraries(${#{cmakeLibNames}})\n")
file.printf("\n")
printf("Generated CMakeLists.txt for #{project}\n")

32
config.h.cmake Normal file
View File

@ -0,0 +1,32 @@
#cmakedefine PACKAGE "${APPLICATION_NAME}"
#cmakedefine VERSION "${APPLICATION_VERSION}"
#cmakedefine LOCALEDIR "${LOCALE_INSTALL_DIR}"
#cmakedefine DATADIR "${DATADIR}"
#cmakedefine LIBDIR "${LIBDIR}"
#cmakedefine PLUGINDIR "${PLUGINDIR}"
#cmakedefine SYSCONFDIR "${SYSCONFDIR}"
#cmakedefine BINARYDIR "${BINARYDIR}"
#cmakedefine SOURCEDIR "${SOURCEDIR}"
#cmakedefine HAVE_CLOCK_GETTIME
#cmakedefine WITH_LOG4C 1
#cmakedefine WITH_ICONV 1
#cmakedefine HAVE_ARGP_H 1
#cmakedefine HAVE_ICONV_H 1
#cmakedefine HAVE_SYS_ICONV_H 1
#cmakedefine HAVE_TIMEGM 1
#cmakedefine HAVE_STRERROR_R 1
#cmakedefine HAVE_UTIMES 1
#cmakedefine HAVE_LSTAT 1
#cmakedefine HAVE_FNMATCH 1
#cmakedefine HAVE___MINGW_ASPRINTF 1
#cmakedefine HAVE_ICONV 1
#cmakedefine HAVE_ICONV_CONST 1
#cmakedefine NEON_WITH_LFS 1
#cmakedefine HAVE___MINGW_ASPRINTF 1
#cmakedefine WITH_UNIT_TESTING 1

10
config/CMakeLists.txt Normal file
View File

@ -0,0 +1,10 @@
macro_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/ocsync.conf ${CMAKE_CURRENT_BINARY_DIR}/ocsync.conf)
macro_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/ocsync_exclude.conf ${CMAKE_CURRENT_BINARY_DIR}/ocsync_exclude.conf)
install(
FILES
ocsync.conf
ocsync_exclude.conf
DESTINATION
${SYSCONF_INSTALL_DIR}/ocsync
)

16
config/ocsync.conf Normal file
View File

@ -0,0 +1,16 @@
# max diff time between two recplicas in seconds
max_time_difference = 10
# max directory depth recursion
max_depth = 50
# NOT IN USE:
# sync symbolic links if the remote filesystem supports it.
#sync_symbolic_links = false
# connection timeout in seconds
timeout = 30
# create a copy for backup for the file which has a conflict
#with_confilct_copies = no

View File

@ -0,0 +1,47 @@
# Exclude patterns (one per line). Blank lines in the file and
# lines starting with '#' are ignored.
#
# You can use shell wildcard patterns. See the manpage of sh(1)
#
# If a pattern starts with ']', the ']' is removed from the pattern,
# And the files that matches that pattern will be ignored, but if
# their parent directory is removed on the other side, the file will
# be removed. Otherwise, ignored file prevent the directory from
# being removed.
.beagle
.ccache
.csync*
.fontconfig
.java/
.jpi_cache
.kde*/cache-*
.kde*/socket-*
.kde*/tmp-*
.mozilla/plugins
.mozilla/firefox/*/Cache
.netscape/cache/
.snapshot
.thumbnails
*.~*
]*.directory
# exclude all object file
# *.o
# exclude all bak files
# *.bak
#
# ignore conflict files.
*_conflict-*
.Temporary Items
.Trashes
.Document Revisions-V100
.fseventd
.apdisk
.htaccess

7
config_test.h.cmake Normal file
View File

@ -0,0 +1,7 @@
/* mind to have trailing slashes! */
#define TESTFILES_DIR "@SOURCE_DIR@/tests/ownCloud/testfiles/"
#define TEST_CONFIG_DIR "@SOURCE_DIR@/tests/ownCloud/"

3
csync/AUTHORS Normal file
View File

@ -0,0 +1,3 @@
Andreas Schneider <asn@cryptomilk.org>
Klaas Freitag <freitag@owncloud.com>
Olivier Goffart <olivier>

71
csync/CMakeLists.txt Normal file
View File

@ -0,0 +1,71 @@
project(ocsync C)
# Required cmake version
cmake_minimum_required(VERSION 2.6.0)
# global needed variables
set(APPLICATION_NAME ${PROJECT_NAME})
set(APPLICATION_VERSION_MAJOR "0")
set(APPLICATION_VERSION_MINOR "91")
set(APPLICATION_VERSION_PATCH "4")
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
set(LIBRARY_VERSION "0.2.1")
set(LIBRARY_SOVERSION "0")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
set(CMAKE_MODULE_PATH
${CMAKE_SOURCE_DIR}/cmake/Modules
)
# add definitions
include(DefineCMakeDefaults)
include(DefinePlatformDefaults)
include(DefineCompilerFlags)
include(DefineOptions.cmake)
include(DefineInstallationPaths)
# disallow in-source build
include(MacroEnsureOutOfSourceBuild)
macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.")
# add macros
include(MacroAddPlugin)
include(MacroCopyFile)
if (NOT WIN32)
find_package(Iconv)
endif (NOT WIN32)
find_package(CMocka)
if (CMOCKA_FOUND AND UNIT_TESTING)
include(AddCMockaTest)
endif (CMOCKA_FOUND AND UNIT_TESTING)
include(ConfigureChecks.cmake)
set(SOURCE_DIR ${CMAKE_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
macro_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/CTestCustom.cmake ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake)
if (MEM_NULL_TESTS)
add_definitions(-DCSYNC_MEM_NULL_TESTS)
endif (MEM_NULL_TESTS)
add_subdirectory(src)
add_subdirectory(config)
add_subdirectory(doc)
if (CMOCKA_FOUND AND UNIT_TESTING)
add_subdirectory(tests)
endif (CMOCKA_FOUND AND UNIT_TESTING)
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
configure_file(config_test.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config_test.h)

502
csync/COPYING Normal file
View File

@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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.
This library 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
Lesser General Public License for more details.
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
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

12
csync/CTestConfig.cmake Normal file
View File

@ -0,0 +1,12 @@
set(UPDATE_TYPE "true")
set(MEMORYCHECK_SUPPRESSIONS_FILE ${CMAKE_SOURCE_DIR}/tests/valgrind-csync.supp)
set(CTEST_PROJECT_NAME "csync")
set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "mock.cryptomilk.org")
set(CTEST_DROP_LOCATION "/submit.php?project=${CTEST_PROJECT_NAME}")
set(CTEST_DROP_SITE_CDASH TRUE)

4
csync/CTestCustom.cmake Normal file
View File

@ -0,0 +1,4 @@
set(CTEST_CUSTOM_MEMCHECK_IGNORE
${CTEST_CUSTOM_MEMCHECK_IGNORE}
check_std_c_jhash
)

355
csync/ChangeLog Normal file
View File

@ -0,0 +1,355 @@
ChangeLog
==========
version 0.91.4 (released 2013-12-12, ownCloud Cleint 1.5.0)
* changelog added, version bumped.
version 0.91.3 (released 2013-12-11, ownCloud Client 1.5.0rc1)
* Fix progress bar on win32
* Fix network rate limiting on win32
* Do not check for etag during failing requests
* Start quota timer only after the predecessor returned
* Remove tmp files in case of certain download problems
* Some valgrind fixes
* Theming fix: button behaviour
* Fix a case where a sync loop could happen.
* Multi-linguar installer
* Fix handling of quotes in etags written by older ownClouds
* Fix errno handling in update phase
* Make csync compile on FreeBSD
* Minor cleanups.
version 0.91.2 (released 2013-12-10, ownCloud Client 1.5.0beta3)
* have translatable error message for indiv. file errors.
* Use uint64_t for inode on win32 to fix a type glitch.
* Add test that directrories are properly moved.
* Handle symlinks correctly.
* Do not longer recurse into ignored directories in update
phase.
* Added proper symlink detection for win32 platform.
version 0.91.1 (released 2013-12-03, ownCloud Client 1.5.0beta2)
* Close database correctly to fix a potential crash (mirall#1229)
* Handle invalid inodes correctly.
* Use lstat rather than stat to detect symlinks correctly.
(core#6146)
version 0.91.0 (released 2013-11-28, ownCloud Client 1.5.0beta1)
* fix ascii to int conversion for large numbers.
* add support for file ids, needed to detect server side moves.
* removed unused code, ie. database writing code that went to
mirall.
* add functions to query the database by fileid.
* add functions to read fileids from PUT replies.
* add server side move detection.
* enhanced test scripts
* Remove ne_sock_init and ne_sock_exit from owncloud module
(mirall#1115)
* Renamed 'md5' to 'etag' in code identifiers to avoid confusion.
* add new state EVAL_RENAME
* link the owncloud module directly rather than dl-loading it.
* add a content type header 'application/octet-stream' to PUTs.
* remove -gzip from etag header if its there. (mirall#1195)
* Many minor fixes, refactorings and improvements.
version 0.90.4 (released 2013-10-18, ownCloud Client 1.4.2)
* Count renamed and deleted files for progress information.
* Do not reset csync internal error state in helper funcs
and do not overwrite error messages.
That fixes error reporting to the client.
* Disable check on inodes on all platforms as inodes are not
reliable.
* Fix resuming after user aborting the sync process.
* enabled HBF debugging permanently.
version 0.90.1 (released 2013-09-24, ownCloud Client 1.4.1)
* no more check on the local inode in updater for win32 (bug #779)
* detect if server does not send an etag after an upload
completed.
* fix crash in case of network timeout, reported as
https://github.com/owncloud/mirall/issues/1010
* compile and cmake fixes for win32
* fixed behaviour of csync_exclude
* documentation and spelling fixes.
version 0.90.0 (released 2013-09-04, ownCloud Client 1.4.0)
* Added API to get progress information from csync.
* Added c_rename function to csync std.
* Fix: Do renames of files before any puts.
* Improved database integrity checks.
* Improvements of database writing efficiendy.
* Fix: stat file on win32 even if its opened by application.
* httpbf: configurable block size and threshold.
* Many fixes found by a Coverity check.
* Fix: use correct stat struct on all platforms
* Fix: download resuming.
* ownCloud module: Bandwith limitation added.
* Added ability to remove ignored files automatically.
* Fix: Use int64_t and friends
* Fix: Removed all compile warnings.
* Left excluded files and links in csync's tree to be able to show.
them to the user.
* Add OC-Total-Length header for better quota handling.
* Report inbetween progress
version 0.80.0 (released 2013-06-25)
* Big file chunking (e.g. up/download of big files should now be no
problem anymore)
* Resuming (download of big files will resume)
* Fix false conflicts when database is corrupt/missing
* Fix false conflicts when file is locked
* Put legitimate conflict files only on client side
* Fix unreliable sync after push_file failed
* Fix rename due to inode cast error
* Make chunking work on nginx setups or through nginx proxies
* Improve error reporting in csync_update
* Clean progress database on csync_commit
* Fix issues detected by Coverity
* Fix conflict file appearing when a file cannot be stated
* Do not shadow server errors by not downloading files that have
failed to download in the past
version 0.70.6 (released 2013-04-11)
* [Fixes] Try to avoid to upload incomplete files
* [Fixes] Increase read timeout to 300 seconds
* [Fixes] Handle IGNORE status correctly
* [Fixes] Set path and phash for ignored files
* [Fixes] Fix some issues discovered by Coverity
* [Fixes] Make sure to never allow empty pathes in rmdir
* [Fixes] Fix a crash caused by superfluous free() calls
version 0.70.5 (released 2013-04-02)
* detect 'wrong' conflict files on client side.
* [Fixes] Give context to module to enable logging (cmd client).
* [Fixes] Fix version table contents.
* [Fixes] Fix handling of non statable files on Win32.
* [Fixes] Fix renames on clientside on read only shares.
* [Fixes] Various small fixes and improvements.
version 0.70.4 (released 2013-02-26)
* [Win32] Ship with upto-date openssl version to fix SSL problems we saw.
* [Fixes] Fix crash during mkdir.
* [Fixes] Added workaround for problem that server sometimes does
not respond properly to PROPFIND (mirall#285)
* [Fixes] Fix handling of deletion of non empty or locked
directories.
* [Fixes] Fixed some potential memory leaks.
* [Fixes] Files with filenames with unix extensions
are ignored now.
version 0.70.3 (released 2013-01-24)
* [Platform] Fix session cookie extraction (mirall bug #260).
version 0.70.2 (released 2013-01-23)
* [Platform] Improved module parameter system.
* [Platform] New logging framework. Dropped log4c dependency.
* [Platform] New API to provide sync progress information.
* [Fixes] More efficiency for the ownCloud plugin through less HTTP requests to
the server.
* [Fixes] ownCloud plugin: Improved upload performance.
* [Fixes] Improved error reporting to mirall.
* [Fixes] ownCloud plugin: Improved interpretation of HTTP error codes.
* [Fixes] ownCloud plugin: Do not abort on errors with individual files any
more.
* [Fixes] Lots of other minor fixes.
* [MacOSX] Use libneon with proper big file support.
* [Win32] Use libneon with openSSL support now.
version 0.70.0 and 0.70.1 were beta versions.
version 0.60.2 (released 2012-11-26)
* Migration to cross platform testing system cmocka.
* Fixed variuos minor things incl. potential mem leaks.
* Clang fixes.
* Moved journal database to sync directory.
* Fixed more csync->ocsync renaming issues.
* Fixed statedb query below path.
* Fixed win32 Daylight Saving Time issues.
* Allow static linking with iniparser and sqlite.
* Win32: Fix CreateHandle function in local stat.
* Win32: More wide char fixes.
* Added version table to journal database.
* Fixes for HTTP reply computation.
* Stricter error checks on PROPFIND results.
* Workaround for DST influenced times from previous versions.
* Detect looping in mkdirs to fix sharing.
version 0.60.1 (released 2012-10-18)
* Fix improper memory cleanup which could
cause memory leaks and crashes
* Fix memory leak
* Allow single quote (') in file names
* Remove stray temporary files
version 0.60.0 (released 2012-10-10)
* simplification of pac based proxy support.
* syncing algorithm based on ids rather than on timestamps
* make it possible to relocate database
version 0.50.11 (third beta version, released 2012-10-05)
* Renamed ownCloud version of csync to ocsync for ownCloud.
* Migration paths for csync database and config.
* Fixed that exclude patterns are also tested on files basenames.
* Fixed return type for query function if no database exists.
* minor code fixes
version 0.50.10 (second beta version, released 2012-09-20)
* Fixed crash by removing a bogus free.
* More useful logging.
* ownCloud: Maintain the http session by handling the HTTP Cookie.
version 0.50.9 (first beta version, released 2012-08-30)
* Fixed strncpy handling (mkdir on windows problem).
* extend database with columns uniq id and type.
* Use server maintained uniq IDs for update detection instead of
mtimes.
* Maintain uniq IDs in local database
* Handle change propagation through the file tree locally and remote.
* Added module to build a file tree from the local database (dbtree.c)
* Added methods to query IDs from the server and maintain it locally.
version 0.50.8 (released 2012-08-10)
* Inode equivalent support for Win32 platforms to support rename
* ownCloud supports propagates renames from local to webdav MOVE
* ownCloud module works with proxy, settings from mirall.
* improved CMake modules (openSSL)
* Fixed namespace for lastmodified propset.
* Added cmocka based tests for ownCloud module.
* Added a config_test.h config header file.
* Fix link handling: Ignore symlinks.
* Modules can now report their capabilities to csync core.
* A lot of minor fixes and improvements.
version 0.50.7 (released 2012-06-19)
* Added ability to log to a callback, ie. let the app
catch the log output
* Added push to remote without pushing to temp file first.
* Fixed file copy function to use wide character (win32).
* Fixed loading of statedb if user has special char (win32).
version 0.50.6 (released 2012-05-18)
* Directories with 'strange' characters broke sync. (oC bug #613)
* Special characters in Windows did not sync correctly. (oC bug #478)
* Make neon redirecting
* Switch logging off on Apple to not fill the syslog. (oC bug #622)
version 0.50.5 (released 2012-04-18)
* removed argp lib dependency
* simplified and fixed CMake files
* MacOS porting efforts
* more granular error reports, thread save
version 0.50.0 (released 2013-08-01)
* Added owncloud module.
* Added support for more platforms: FreeBSD, Windows and MacOSX
* Added support for more compilers: CLang, MinGW and latest GCC
* Added a backup mode to the reconciler.
* Added new logging framework (removed log4c dependency).
* Added new config parser (removed iniparser dependency).
* Added cmocka tests.
* Added a way to exported file_tree_walk functions.
* Added capabilities for modules.
* Added possiblity to push information to the modules.
* Added iconv support to support various char sets.
* Added csync_commit() to rerun on the same context.
* Added content checking in conflict case.
* Added callbacks for progress information.
* Added get() and put() functions for modules.
* Improved database: more performance, more integrity checks
* Improved error reporting: status codes, custom errnos
* Fixed serveral bugs.
* Relicensed libcsync to LGPLv2.1+.
version 0.44.0 (released 2010-02-15)
* Migrated sftp module to libssh 0.4.
* Added more cache entries to the default config.
* Added missing requirements.
* Fixed build warnings.
* Fixed some memory leaks using sftp attributes.
* Some code cleanups.
version 0.43.0 (released 2009-05-25)
* Added SFTP support with libssh 0.3.
* Added possibility to pass userdata to the auth function.
* Added a better version function.
* Fixed CMake build.
* Fixed CMake find modules.
* Fixed some flaws in cstd functions.
* Documented all public functions.
version 0.42.0 (released 2009-02-10)
* Small fix in the userguide.
version 0.42.0 rc3 (released 2009-01-23)
libcsync:
* Added checks for unix extensions.
* Added more documentation to the userguide.
* Fixed loading of plugins.
* Fixed call for deletion functions.
* Normalize the path to <hostname>/<path> for the statedb filename.
* More change name of client options to be more descriptive.
version 0.42.0 rc2 (released 2009-01-07)
libcsync:
* Fixed a bug in the creation of the statedb
* Completed userguide
version 0.42.0 rc1 (released 2008-12-04)
libcsync:
* Reduced calls of syscall functions.
* Added own function to create a temporary filename.
* Fixed libsmbclient 3.0.x support.
version 0.42.0 beta1 (released 2008-09-10)
libcsync:
* Added a sftp module using libssh
* Added user guide (just a start)
* Added testcase for update detection
* Added a function to parse an uri to cstdlib
* Updated the manpage
* Fixed some segfaults in cstdlib
* Fixed some memory leaks
csync:
* Improved the auth callback
version 0.42.0 alpha4 (released 2008-07-02)
libcsync:
* Added the possibility to run csync completely without a journal
* Improved chmod calls during propagation. Most of the time we use the
default mode and don't need to call chmod.
* Improved the exclude list handling in the file tree walker. This
increased the speed of the update detection.
* Fixed csync on PPC
* Fixed serveral small bugs
csync:
* Added commandline option to run csync completely without a journal
* Added a manpage
version 0.42.0 alpha3 (released 2008-06-25)
libcsync:
* Added a tree merger to write a complete journal
* Added support to run csync without a journal
* Fixed kerberos support in csync_smb module
* Fixed closing of files after the copy
* Fixed update detection to detect special files (fifo, pipes,
char devices, ..)
* Fixed O_NOATIME flag on open() if we don't have the permission
csync:
* Add a variable to run csync completely without a journal
version 0.42.0 alpha2 (released 2008-06-16)
libcsync:
* Peformance improvements
* Add more directories to the standard exclude file
* Bugfixes
version 0.42.0 alpha1 (released 2008-06-02)
* Initial release

View File

@ -0,0 +1,75 @@
include(CheckIncludeFile)
include(CheckSymbolExists)
include(CheckFunctionExists)
include(CheckLibraryExists)
include(CheckTypeSize)
include(CheckCXXSourceCompiles)
set(PACKAGE ${APPLICATION_NAME})
set(VERSION ${APPLICATION_VERSION})
set(DATADIR ${DATA_INSTALL_DIR})
set(LIBDIR ${LIB_INSTALL_DIR})
set(PLUGINDIR "${PLUGIN_INSTALL_DIR}-${LIBRARY_SOVERSION}")
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
set(BINARYDIR ${CMAKE_BINARY_DIR})
set(SOURCEDIR ${CMAKE_SOURCE_DIR})
# HEADER FILES
check_include_file(argp.h HAVE_ARGP_H)
# FUNCTIONS
if (NOT LINUX)
# librt
check_library_exists(rt nanosleep "" HAVE_LIBRT)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} )
endif (NOT LINUX)
check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME)
if (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
endif (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
check_library_exists(dl dlopen "" HAVE_LIBDL)
if (HAVE_LIBDL)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} dl)
endif (HAVE_LIBDL)
check_function_exists(asprintf HAVE_ASPRINTF)
if(NOT HAVE_ASPRINTF)
if(MINGW)
add_definitions( -D__USE_MINGW_ANSI_STDIO=1 )
endif()
endif()
check_function_exists(fnmatch HAVE_FNMATCH)
if(NOT HAVE_FNMATCH AND WIN32)
find_library(SHLWAPI_LIBRARY shlwapi)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} shlwapi)
endif()
if(WIN32)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} psapi kernel32)
endif()
check_function_exists(timegm HAVE_TIMEGM)
check_function_exists(strerror_r HAVE_STRERROR_R)
check_function_exists(utimes HAVE_UTIMES)
check_function_exists(lstat HAVE_LSTAT)
check_function_exists(asprintf HAVE_ASPRINTF)
if (WIN32)
check_function_exists(__mingw_asprintf HAVE___MINGW_ASPRINTF)
endif(WIN32)
if (UNIX AND HAVE_ASPRINTF)
add_definitions(-D_GNU_SOURCE)
endif (UNIX AND HAVE_ASPRINTF)
if (WIN32)
check_function_exists(__mingw_asprintf HAVE___MINGW_ASPRINTF)
endif(WIN32)
if (UNIT_TESTING)
set(WITH_UNIT_TESTING ON)
endif (UNIT_TESTING)
set(CSYNC_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "csync required system libraries")

View File

@ -0,0 +1,5 @@
if ( NOT WIN32 )
option(WITH_ICONV "Build csync with iconv support" ON)
endif()
option(UNIT_TESTING "Build with unit tests" OFF)
option(MEM_NULL_TESTS "Enable NULL memory testing" OFF)

84
csync/INSTALL Normal file
View File

@ -0,0 +1,84 @@
# How to build from source
## Requirements
### Common requirements
In order to build csync, you need to install several components:
- A C compiler
- [CMake](http://www.cmake.org) >= 2.6.0.
- [check](http://check.sourceforge.net) >= 0.9.5
- [sqlite3](http://www.sqlite.org) >= 3.4
- [libneon](http://www.webdav.org/neon/) >= 0.29.0
optional:
- [libsmbclient](http://www.samba.org) >= 3.5
- [libssh](http://www.libssh.org) >= 0.5
sqlite3 is a runtime requirement. libsmbclient is needed for
the smb plugin, libssh for the sftp plugin. libneon is required for the
ownCloud plugin.
Note that these version numbers are version we know works correctly. If you
build and run csync successfully with an older version, please let us know.
## Building
First, you need to configure the compilation, using CMake. Go inside the
`build` dir. Create it if it doesn't exist.
GNU/Linux and MacOS X:
cmake -DCMAKE_BUILD_TYPE=Debug ..
make
### CMake standard options
Here is a list of the most interesting options provided out of the box by CMake.
- CMAKE_BUILD_TYPE: The type of build (can be Debug Release MinSizeRel RelWithDebInfo)
- CMAKE_INSTALL_PREFIX: The prefix to use when running make install (Default to
/usr/local on GNU/Linux and MacOS X)
- CMAKE_C_COMPILER: The path to the C compiler
- CMAKE_CXX_COMPILER: The path to the C++ compiler
### CMake options defined for csync
Options are defined in the following files:
- DefineOptions.cmake
They can be changed with the -D option:
`cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_LOG4C=OFF ..`
### Browsing/editing CMake options
In addition to passing options on the command line, you can browse and edit
CMake options using `cmakesetup` (Windows) or `ccmake` (GNU/Linux and MacOS X).
- Go to the build dir
- On Windows: run `cmakesetup`
- On GNU/Linux and MacOS X: run `ccmake ..`
## Installing
Befor installing you can run the tests if everything is working:
make test
If you want to install csync after compilation run:
make install
## Running
The csync binary can be found in the `build/client` directory.
## About this document
This document is written using [Markdown][] syntax, making it possible to
provide usable information in both plain text and HTML format. Whenever
modifying this document please use [Markdown][] syntax.
[markdown]: http://www.daringfireball.net/projects/markdown

34
csync/README Normal file
View File

@ -0,0 +1,34 @@
WHAT IS CSYNC?
==============
csync is a lightweight utility to synchronize files between two directories on
a system or between multiple systems.
It synchronizes bidirectionally and allows the user to keep two copies of files
and directories in sync. csync uses widely adopted protocols, such as smb or
sftp, so that there is no need for a server component. It is a user-level
program which means you dont need to be a superuser or administrator.
CONTRIBUTIONS
=============
If you want to contribute to the development of the software then please join
the mailing list. Patches are accepted preferebly created with git and we are
always glad to receive feedback or suggestions to the address
csync-devel@csync.org.
More information on the various mailing lists can be found at
http://www.csync.org/communication/.
You can also get the sourcecode straight from the git repository - see
http://git.csync.org/
DOCUMENTATION
=============
As a user you can find a userguide which is shipped with this package or is
available at the website. For developers there is doxygen documentation and
comments in the source code itself. See
http://www.csync.org/userguide/
and
http://www.csync.org/api/

41
csync/doc/CMakeLists.txt Normal file
View File

@ -0,0 +1,41 @@
project(doc C)
# Build the documentation
#
include(UseDoxygen OPTIONAL)
file(GLOB _manpages *.[0-9].txt)
add_custom_target(man
COMMAND
${CMAKE_CURRENT_SOURCE_DIR}/makeman.sh ${_manpages}
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
)
add_custom_target(userguide
COMMAND
${CMAKE_CURRENT_SOURCE_DIR}/makeguide.sh ocsync.txt
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
)
if (UNIX)
install(
FILES
ocsync.1
DESTINATION
${MAN_INSTALL_DIR}/man1
)
set(DOC_INSTALL_PATH ${SHARE_INSTALL_PREFIX}/doc/ocsync)
endif(UNIX)
if (WIN32)
set(DOC_INSTALL_PATH ${SHARE_INSTALL_PREFIX}/doc)
endif (WIN32)
install(
DIRECTORY
userguide
DESTINATION
${DOC_INSTALL_PATH}
)

8
csync/doc/asciidoc.conf Normal file
View File

@ -0,0 +1,8 @@
#
# Customization for csync documentation.
#
[specialwords]
ifndef::doctype-manpage[]
emphasizedwords=(?u)\\?\bCSYNC\b
monospacedwords=(?u)\\?\bcsync\(1\)
endif::doctype-manpage[]

20
csync/doc/codeheader.c Normal file
View File

@ -0,0 +1,20 @@
/*
* cynapses libc functions
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/

26
csync/doc/codeheader.h Normal file
View File

@ -0,0 +1,26 @@
/*
*
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
#ifndef _CSYNC_X_H
#define _CSYNC_X_H
#endif /* _CSYNC_X_H */
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */

1375
csync/doc/doxy.config.in Normal file

File diff suppressed because it is too large Load Diff

16
csync/doc/makeguide.sh Normal file
View File

@ -0,0 +1,16 @@
#!/bin/bash
# Last Change: 2008-07-03 11:08:54
for f in $@; do
test "${f##*/}" = "CMakeLists.txt" && continue
echo -e "\e[32mCreating asciidoc html document ${f%.*}.html\e[0m"
asciidoc \
--attribute=numbered \
--attribute=icons \
--attribute="iconsdir=./images/icons" \
--attribute=toc \
--backend=xhtml11 \
--out-file="$(dirname $f)/userguide/${f%.*}.html" \
$f
rm -f ${f%.*}.xml
done

9
csync/doc/makeman.sh Normal file
View File

@ -0,0 +1,9 @@
#!/bin/bash
# Last Change: 2008-07-03 11:08:54
for f in $@; do
test "${f##*/}" = "CMakeLists.txt" && continue
echo -e "\e[32mCreating manpage ${f%.*}\e[0m"
a2x --doctype=manpage --format=manpage $f
rm -f ${f%.*}.xml
done

183
csync/doc/ocsync.1 Normal file
View File

@ -0,0 +1,183 @@
'\" t
.\" Title: ocsync
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/>
.\" Date: 12/22/2012
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "OCSYNC" "1" "12/22/2012" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.\" http://bugs.debian.org/507673
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.\" -----------------------------------------------------------------
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
ocsync \- A commandline frontent for csync a user level bidirectional file synchronizer\&.
.SH "SYNOPSIS"
.sp
\fBocsync\fR [\fIOPTION\fR\&...] \fISOURCE\fR \fIDESTINATION\fR
.SH "DESCRIPTION"
.sp
ocsync is a client only bidirectional file synchronizer\&. It synchronizes the content of \fISOURCE\fR with \fIDESTINATION\fR and vice versa\&. The \fIDESTINATION\fR can be a local directory or a remote file server\&.
.sp
You can use ocsync for different things\&. The intention is to provide Roaming Home Directories for Linux but you can use it to synchronize your music collection or create a backup of a directory\&.
.SH "OPTIONS"
.PP
\fB\-\-create\-statedb\fR
.RS 4
Run update detection and write the statedb (TESTING ONLY!)
.RE
.PP
\fB\-d, \-\-disable\-statedb\fR
.RS 4
Disable the usage and creation of a statedb\&.
.RE
.PP
\fB\-\-exclude\-file=\fR\fB\fI<file>\fR\fR
.RS 4
Add an additional exclude file
.RE
.PP
\fB\-r, \-\-reconcile\fR
.RS 4
Run ONLY update detection and reconcilation This option is for debugging
.RE
.PP
\fB\-u, \-\-update\fR
.RS 4
Run ONLY the update detection This option is for debugging
.RE
.PP
\fB\-?, \-\-help\fR
.RS 4
Print the help list
.RE
.PP
\fB\-V, \-\-version\fR
.RS 4
Print program version
.RE
.SH "EXIT STATUS"
.PP
\fB0\fR
.RS 4
Success
.RE
.PP
\fB1\fR
.RS 4
Failure (syntax or usage error; configuration error; unexpected error)\&.
.RE
.SH "EXAMPLES"
.sp
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
ocsync /home/user /backup/home/user
.sp
.if n \{\
.RS 4
.\}
.nf
Synchronizer two local directories\&.
.fi
.if n \{\
.RE
.\}
.RE
.sp
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
ocsync /home/user smb://server/share/user
.sp
.if n \{\
.RS 4
.\}
.nf
Synchronize a home directory with a SMB share\&.
.fi
.if n \{\
.RE
.\}
.RE
.sp
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
ocsync /home/user smb://user:password@server/share/user
.sp
.if n \{\
.RS 4
.\}
.nf
Synchronize a home directory with a SMB share and provide username and
password directly\&.
.fi
.if n \{\
.RE
.\}
.RE
.SH "BUGS"
.sp
Please report bugs at https://dev\&.csync\&.org/\&.
.SH "SEE ALSO"
.sp
\fBlibocsync\fR(7)
.SH "AUTHORS"
.sp
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
Andreas Schneider <mail@cynapses\&.org>
.RE
.sp
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
Klaas Freitag <freitag@owncloud\&.com>
.RE
.SH "COPYING"
.sp
Copyright \e(c) 2006\-2008 Andreas Schneider\&. Free use of this software is granted under the terms of the GNU General Public License (GPL)\&.

104
csync/doc/ocsync.1.txt Normal file
View File

@ -0,0 +1,104 @@
ocsync(1)
========
NAME
----
ocsync - A commandline frontent for csync a user level bidirectional file
synchronizer.
SYNOPSIS
--------
*ocsync* ['OPTION'...] 'SOURCE' 'DESTINATION'
DESCRIPTION
-----------
ocsync is a client only bidirectional file synchronizer. It synchronizes the
content of 'SOURCE' with 'DESTINATION' and vice versa. The 'DESTINATION' can
be a local directory or a remote file server.
You can use ocsync for different things. The intention is to provide Roaming
Home Directories for Linux but you can use it to synchronize your music
collection or create a backup of a directory.
OPTIONS
-------
*--create-statedb*::
Run update detection and write the statedb
(TESTING ONLY!)
*-d, --disable-statedb*::
Disable the usage and creation of a statedb.
*--exclude-file='<file>'*::
Add an additional exclude file
*-r, --reconcile*::
Run ONLY update detection and reconcilation
This option is for debugging
*-u, --update*::
Run ONLY the update detection
This option is for debugging
*-?, --help*::
Print the help list
*-V, --version*::
Print program version
EXIT STATUS
-----------
*0*::
Success
*1*::
Failure (syntax or usage error; configuration error;
unexpected error).
EXAMPLES
--------
* ocsync /home/user /backup/home/user
Synchronizer two local directories.
* ocsync /home/user smb://server/share/user
Synchronize a home directory with a SMB share.
* ocsync /home/user smb://user:password@server/share/user
Synchronize a home directory with a SMB share and provide username and
password directly.
BUGS
----
Please report bugs at https://dev.csync.org/.
SEE ALSO
--------
*libocsync*(7)
AUTHORS
-------
* Andreas Schneider <mail@cynapses.org>
* Klaas Freitag <freitag@owncloud.com>
COPYING
-------
Copyright \(c) 2006-2008 Andreas Schneider. Free use of this software is
granted under the terms of the GNU General Public License (GPL).

315
csync/doc/ocsync.txt Normal file
View File

@ -0,0 +1,315 @@
CSYNC User Guide
================
Andreas Schneider <asn@cryptomilk.org>
:Author Initials: ADS
csync is a lightweight utility to synchronize files between two directories
on a system or between multiple systems.
It synchronizes bidirectionally and allows the user to keep two copies of files
and directories in sync. csync uses widely adopted protocols, such as smb or
sftp, so that there is no need for a server component. It is a user-level
program which means you don't need to be a superuser or administrator.
Together with a Pluggable Authentication Module (PAM), the intent is to provide
Roaming Home Directories for Linux (see <<X80, The PAM Module>>).
Introduction
------------
It is often the case that we have multiple copies (called replicas) of a
filesystem or part of a filesystem (for example on a notebook and desktop
computer). Changes to each replica are often made independently, and as a
result, they do not contain the same information. In that case, a file
synchronizer is used to make them consistent again, without losing any
information.
The goal is to detect conflicting updates (files which have been modified) and
propagate non-conflicting updates to each replica. If there are no conflicts
left, we are done, and the replicas are identical. To resolve or handle
conflicts there are several algorithms available. They will be discussed
one of the following sections.
Basics
------
This section describes some basics of file synchronization.
Paths
~~~~~
A path normally refers to a point which contains a set of files which should be
synchronized. It is specified relative to the root of the replica locally, but
has to be absolute if you use a protocol. The path is just a sequence of names
separated by '/'.
NOTE: The path separator is always a forward slash '/', even for Windows.
csync always uses the absolute path on remote replicas. This could
'sftp://gladiac:secret@myserver/home/gladiac' for sftp.
What is an update?
~~~~~~~~~~~~~~~~~~
The contents of a path could be a file, a directory or a symbolic link
(symbolic links are not supported yet). To be more precise, if the path refers
to:
- a regular file: the contents of the file are the byte stream and the
metadata of the file.
- a directory: then the content is the metadata of the directory.
- a symbolic link: the content is the named file the link points to.
csync keeps a record of each path which has been successfully synchronized. The
path gets compared with the record and if it has changed since the last
synchronization, we have an update. This is done by comparing the modification
or change (modification time of the metadata) time. This is the way how updates
are detected.
What is a conflict?
~~~~~~~~~~~~~~~~~~~
A path is conflicting if it fulfills the following conditions:
1. it has been updated in one replica,
2. it or any of its descendants has been updated on the other replica too, and
3. its contents in are not identical.
File Synchronization
--------------------
The primary goal of the file synchronizer is correctness. It may change
scattered or large parts of the filesystem. Since this in mostly not monitored
by the user, and the file synchronizer is in a position to harm the system,
csync must be safe, even in the case of unexpected errors (e.g. disk full).
What was done to make csync safe is described in the following sections.
One problem concerning correctness is the handling of conflicts. Each file
synchronizer tries to propagate conflicting changes to the other replica. At
the end both replicas should be identical. There are different strategies to
fulfill these goals.
csync is a three-phase file synchronizer. The decision for this design was that
user interaction should be possible and it should be easy to understand the
process. The three phases are update detection, reconciliation and propagation.
These will be described in the following sections.
Update detection
~~~~~~~~~~~~~~~~
There are different strategies for update detection. csync uses a state-based
modtime-inode update detector. This means it uses the modification time to
detect updates. It doesn't require many resources. A record of each file is
stored in a database (called statedb) and compared with the current
modification time during update detection. If the file has changed since the
last synchronization an instruction is set to evaluate it during the
reconciliation phase. If we don't have a record for a file we investigate, it
is marked as new.
It can be difficult to detect renaming of files. This problem is also solved
by the record we store in the statedb. If we don't find the file by the name
in the database, we search for the inode number. If the inode number is found
then the file has been renamed.
Reconciliation
~~~~~~~~~~~~~~
The most important component is the update detector, because the reconciler
depends on it. The correctness of reconciler is mandatory because it can damage
a filesystem. It decides which file:
* Stays untouched
* Has a conflict
* Gets synchronized
* or is *deleted*
A wrong decision of the reconciler leads in most cases to a loss of data. So
there are several conditions which a file synchronizer has to follow.
Algorithms
^^^^^^^^^^
For conflict resolution several different algorithms could be implemented. The
most common algorithms are the merge and the conflict algorithm. The first
is a batch algorithm and the second is one which needs user interaction.
Merge algorithm
+++++++++++++++
The merge algorithm is an algorithm which doesn't need any user interaction. It
is simple and used for example by Microsoft for Roaming Profiles. If it detects
a conflict (the same file changed on both replicas) then it will use the most
recent file and overwrite the other. This means you can loose some data, but
normally you want the latest file.
Conflict algorithm
++++++++++++++++++
This is not implemented yet.
If a file has a conflict the user has to decide which file should be used.
Propagation
~~~~~~~~~~~
The next instance of the file synchronizer is the propagator. It uses the
calculated records to apply them on the current replica.
The propagator uses a two-phase-commit mechanism to simulate an atomic
filesystem operation.
In the first phase we copy the file to a temporary file on the opposite
replica. This has the advantage that we can check if the file which has been
copied to the opposite replica has been transferred successfully. If the
connection gets interrupted during the transfer we still have the original
states of the file. This means no data will be lost.
In the second phase the file on the opposite replica will be overwritten by
the temporary file.
After a successful propagation we have to merge the trees to reflect the
current state of the filesystem tree. This updated tree will be written as a
journal into the state database. It will be used during the update detection of
the next synchronization. See above for a description of the state database
during synchronization.
Robustness
~~~~~~~~~~
This is a very important topic. The file synchronizer should not crash, and if
it has crashed, there should be no loss of data. To achieve this goal there are
several mechanisms which will be discussed in the following sections.
Crash resistance
^^^^^^^^^^^^^^^^
The synchronization process can be interrupted by different events, this can
be:
* the system could be halted due to errors.
* the disk could be full or the quota exceeded.
* the network or power cable could be pulled out.
* the user could force a stop of the synchronization process.
* various communication errors could occur.
That no data will be lost due to an event we enforce the following invariant:
IMPORTANT: At every moment of the synchronization each file, has either its
original content or its correct final content.
This means that the original content can not be incorrect, no data can be lost
until we overwrite it after a successful synchronization. Therefore, each
interrupted synchronization process is a partial sync and can be continued and
completed by simply running csync again. The only problem could be an error of
the filesystem, so we reach this invariant only approximately.
Transfer errors
^^^^^^^^^^^^^^^
With the Two-Phase-Commit we check the file size after the file has transferred
and we are able to detect transfer errors. A more robust approach would be a
transfer protocol with checksums, but this is not doable at the moment. We may
add this in the future.
Future filesystems, like btrfs, will help to compare checksums instead of the
filesize. This will make the synchronization safer. This does not imply that it
is unsafe now, but checksums are safer than simple filesize checks.
Database loss
^^^^^^^^^^^^^
It is possible that the state database could get corrupted. If this happens,
all files get evaluated. In this case the file synchronizer wont delete any
file, but it could occur that deleted files will be restored from the other
replica.
To prevent a corruption or loss of the database if an error occurs or the user
forces an abort, the synchronizer is working on a copy of the database and will
use a Two-Phase-Commit to save it at the end.
Getting started
---------------
Installing csync
~~~~~~~~~~~~~~~~
See the `README` and `INSTALL` files for install prerequisites and
procedures. Packagers should take a look at <<X90, Appendix A: Packager Notes>>.
Using the commandline client
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The synopsis of the commandline client is
csync [OPTION...] SOURCE DESTINATION
It synchronizes the content of SOURCE with DESTINATION and vice versa. The
DESTINATION can be a local directory or a remote file server.
csync /home/csync scheme://user:password@server:port/full/path
Examples
^^^^^^^^
To synchronize two local directories:
csync /home/csync/replica1 /home/csync/relplica2
Two synchronizer a local directory with an smb server, use
csync /home/csync smb://rupert.galaxy.site/Users/csync
If you use kerberos, you don't have to specify a username or a password. If you
don't use kerberos, the commandline client will ask about the user and the
password. If you don't want to be prompted, you can specify it on the
commandline:
csync /home/csync smb://csync:secret@rupert.galaxy.site/Users/csync
If you use the sftp protocol and want to specify a port, you do it the
following way:
csync /home/csync sftp://csync@krikkit.galaxy.site:2222/home/csync
The remote destination is supported by plugins. By default csync ships with smb
and sftp support. For more information, see the manpage of csync(1).
Exclude lists
~~~~~~~~~~~~~
csync provides exclude lists with simple shell wildcard patterns. There is a
global exclude list, which is normally located in
'/etc/csync/csync_exclude.conf' and it has already some sane defaults. If you
run csync the first time, it will create an empty exclude list for the user.
This file will be '~/.csync/csync_exclude.conf'. csync considers both
configuration files and an additional one if you specify it.
The entries in the file are newline separated. Use
'/etc/csync/csync_exclude.conf' as an example.
Debug messages and dry run
~~~~~~~~~~~~~~~~~~~~~~~~~~
By default the csync client logs to stderr and you can increase the debug
level with a commandline options.
To simulate a run of the file synchronizer, you should set the priority to
'debug' for the categories 'csync.updater' and 'csync.reconciler' in the config
file '~/.csync/csync_log.conf'. Then run csync with the '--dry-run' option.
This will only run update detection and reconciliation.
[[X80]]
The PAM module
~~~~~~~~~~~~~~
pam_csync is a PAM module to provide roaming home directories for a user
session. This module is aimed at environments with central file servers where a
user wishes to store his home directory. The Authentication Module verifies the
identity of a user and triggers a synchronization with the server on the first
login and the last logout. More information can be found in the manpage of the
module pam_csync(8) or pam itself pam(8).
[[X90]]
Appendix A: Packager Notes
--------------------------
Read the `README`, `INSTALL` and `FAQ` files (in the distribution root
directory).

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
Replaced the plain DocBook XSL admonition icons with Jimmac's DocBook
icons (http://jimmac.musichall.cz/ikony.php3). I dropped transparency
from the Jimmac icons to get round MS IE and FOP PNG incompatibilies.
Stuart Rackham

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

137
csync/src/CMakeLists.txt Normal file
View File

@ -0,0 +1,137 @@
project(libcsync)
add_subdirectory(std)
add_subdirectory(httpbf)
# Statically include sqlite
if (CSYNC_STATIC_COMPILE_DIR)
set(SQLITE3_INCLUDE_DIRS "")
set(SQLITE3_LIBRARIES "")
include_directories(${CSYNC_STATIC_COMPILE_DIR})
else (CSYNC_STATIC_COMPILE_DIR)
find_package(SQLite3 3.3.9 REQUIRED)
endif()
find_package(Neon 0.29.0 REQUIRED)
set(CSYNC_PUBLIC_INCLUDE_DIRS
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}
CACHE INTERNAL "csync public include directories"
)
set(CSYNC_PRIVATE_INCLUDE_DIRS
${SQLITE3_INCLUDE_DIRS}
${CSTDLIB_PUBLIC_INCLUDE_DIRS}
${HTTPBF_PUBLIC_INCLUDE_DIRS}
${CMAKE_BINARY_DIR}
)
set(CSYNC_LIBRARY
ocsync
CACHE INTERNAL "ocsync library"
)
set(CSYNC_LINK_LIBRARIES
${CSYNC_LIBRARY}
${CSTDLIB_LIBRARY}
${CSYNC_REQUIRED_LIBRARIES}
${SQLITE3_LIBRARIES}
${NEON_LIBRARIES}
${HTTPBF_LIBRARY}
)
if(HAVE_ICONV AND WITH_ICONV)
list(APPEND CSYNC_PRIVATE_INCLUDE_DIRS ${ICONV_INCLUDE_DIR})
list(APPEND CSYNC_LINK_LIBRARIES ${ICONV_LIBRARIES})
endif()
set(BLACKLIST_ON_ERROR 0 CACHE BOOL
"If an errors occurs three times on the same file, do not attempt to process that file any further.")
if(BLACKLIST_ON_ERROR)
add_definitions(-DBLACKLIST_ON_ERROR)
endif()
set(csync_SRCS
csync.c
csync_config.c
csync_exclude.c
csync_log.c
csync_statedb.c
csync_dbtree.c
csync_time.c
csync_util.c
csync_misc.c
csync_lock.c
csync_update.c
csync_reconcile.c
csync_rename.cc
vio/csync_vio.c
vio/csync_vio_handle.c
vio/csync_vio_file_stat.c
vio/csync_vio_local.c
csync_owncloud.c
csync_owncloud_recursive_propfind.c
csync_owncloud_util.c
)
configure_file(csync_version.h.in ${CMAKE_CURRENT_BINARY_DIR}/csync_version.h)
set(csync_HDRS
${CMAKE_CURRENT_BINARY_DIR}/csync_version.h
csync.h
vio/csync_vio.h
vio/csync_vio_file_stat.h
vio/csync_vio_handle.h
vio/csync_vio_method.h
vio/csync_vio_module.h
)
# Statically include sqlite
if (CSYNC_STATIC_COMPILE_DIR)
list(APPEND csync_SRCS ${CSYNC_STATIC_COMPILE_DIR}/dictionary.c ${CSYNC_STATIC_COMPILE_DIR}/sqlite3.c)
endif()
include_directories(
${CSYNC_PUBLIC_INCLUDE_DIRS}
${CSYNC_PRIVATE_INCLUDE_DIRS}
)
add_library(${CSYNC_LIBRARY} SHARED ${csync_SRCS})
target_link_libraries(${CSYNC_LINK_LIBRARIES})
set_target_properties(
${CSYNC_LIBRARY}
PROPERTIES
VERSION
${LIBRARY_VERSION}
SOVERSION
${LIBRARY_SOVERSION}
)
INSTALL(
TARGETS
${CSYNC_LIBRARY}
LIBRARY DESTINATION
${LIB_INSTALL_DIR}
ARCHIVE DESTINATION
${LIB_INSTALL_DIR}
RUNTIME DESTINATION
${BIN_INSTALL_DIR}
)
INSTALL(
FILES
${csync_HDRS}
DESTINATION
${INCLUDE_INSTALL_DIR}/${APPLICATION_NAME}
)

1070
csync/src/csync.c Normal file

File diff suppressed because it is too large Load Diff

636
csync/src/csync.h Normal file
View File

@ -0,0 +1,636 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
/**
* @file csync.h
*
* @brief Application developer interface for csync.
*
* @defgroup csyncPublicAPI csync public API
*
* @{
*/
#ifndef _CSYNC_H
#define _CSYNC_H
#include <stdbool.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <config.h>
#include "csync_version.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* csync file declarations
*/
#define CSYNC_CONF_DIR ".ocsync"
#define CSYNC_CONF_FILE "ocsync.conf"
#define CSYNC_EXCLUDE_FILE "ocsync_exclude.conf"
#define CSYNC_LOCK_FILE ".csync.lock"
/**
* Instruction enum. In the file traversal structure, it describes
* the csync state of a file.
*/
enum csync_status_codes_e {
CSYNC_STATUS_OK = 0,
CSYNC_STATUS_ERROR = 1024, /* don't use this code,
just use in csync_status_ok */
CSYNC_STATUS_UNSUCCESSFUL,
CSYNC_STATUS_NO_LOCK,
CSYNC_STATUS_STATEDB_LOAD_ERROR,
CSYNC_STATUS_STATEDB_WRITE_ERROR,
CSYNC_STATUS_NO_MODULE,
CSYNC_STATUS_TIMESKEW,
CSYNC_STATUS_FILESYSTEM_UNKNOWN,
CSYNC_STATUS_TREE_ERROR,
CSYNC_STATUS_MEMORY_ERROR,
CSYNC_STATUS_PARAM_ERROR,
CSYNC_STATUS_UPDATE_ERROR,
CSYNC_STATUS_RECONCILE_ERROR,
CSYNC_STATUS_PROPAGATE_ERROR,
CSYNC_STATUS_REMOTE_ACCESS_ERROR,
CSYNC_STATUS_REMOTE_CREATE_ERROR,
CSYNC_STATUS_REMOTE_STAT_ERROR,
CSYNC_STATUS_LOCAL_CREATE_ERROR,
CSYNC_STATUS_LOCAL_STAT_ERROR,
CSYNC_STATUS_PROXY_ERROR,
CSYNC_STATUS_LOOKUP_ERROR,
CSYNC_STATUS_SERVER_AUTH_ERROR,
CSYNC_STATUS_PROXY_AUTH_ERROR,
CSYNC_STATUS_CONNECT_ERROR,
CSYNC_STATUS_TIMEOUT,
CSYNC_STATUS_HTTP_ERROR,
CSYNC_STATUS_PERMISSION_DENIED,
CSYNC_STATUS_NOT_FOUND,
CSYNC_STATUS_FILE_EXISTS,
CSYNC_STATUS_OUT_OF_SPACE,
CSYNC_STATUS_QUOTA_EXCEEDED,
CSYNC_STATUS_SERVICE_UNAVAILABLE,
CSYNC_STATUS_FILE_SIZE_ERROR,
CSYNC_STATUS_CONTEXT_LOST,
CSYNC_STATUS_MERGE_FILETREE_ERROR,
CSYNC_STATUS_CSYNC_STATUS_ERROR,
CSYNC_STATUS_OPENDIR_ERROR,
CSYNC_STATUS_READDIR_ERROR,
CSYNC_STATUS_OPEN_ERROR,
CSYNC_STATUS_ABORTED,
/* Codes for file individual status: */
CSYNC_STATUS_INDIVIDUAL_IS_SYMLINK,
CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST,
CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS
};
typedef enum csync_status_codes_e CSYNC_STATUS;
#ifndef likely
# define likely(x) (x)
#endif
#ifndef unlikely
# define unlikely(x) (x)
#endif
#define CSYNC_STATUS_IS_OK(x) (likely((x) == CSYNC_STATUS_OK))
#define CSYNC_STATUS_IS_ERR(x) (unlikely((x) >= CSYNC_STATUS_ERROR))
#define CSYNC_STATUS_IS_EQUAL(x, y) ((x) == (y))
enum csync_instructions_e {
CSYNC_INSTRUCTION_NONE = 0x00000000, /* Nothing to do (UPDATE|RECONCILE) */
CSYNC_INSTRUCTION_EVAL = 0x00000001, /* There was changed compared to the DB (UPDATE) */
CSYNC_INSTRUCTION_REMOVE = 0x00000002, /* The file need to be removed (RECONCILE) */
CSYNC_INSTRUCTION_RENAME = 0x00000004, /* The file need to be renamed (RECONCILE) */
CSYNC_INSTRUCTION_EVAL_RENAME= 0x00000800, /* The file is new, it is the destination of a rename (UPDATE) */
CSYNC_INSTRUCTION_NEW = 0x00000008, /* The file is new compared to the db (UPDATE) */
CSYNC_INSTRUCTION_CONFLICT = 0x00000010, /* The file need to be downloaded because it is a conflict (RECONCILE) */
CSYNC_INSTRUCTION_IGNORE = 0x00000020, /* The file is ignored (UPDATE|RECONCILE) */
CSYNC_INSTRUCTION_SYNC = 0x00000040, /* The file need to be pushed to the other remote (RECONCILE) */
CSYNC_INSTRUCTION_STAT_ERROR = 0x00000080,
CSYNC_INSTRUCTION_ERROR = 0x00000100,
/* instructions for the propagator */
CSYNC_INSTRUCTION_DELETED = 0x00000200,
CSYNC_INSTRUCTION_UPDATED = 0x00000400
};
enum csync_ftw_type_e {
CSYNC_FTW_TYPE_FILE,
CSYNC_FTW_TYPE_SLINK,
CSYNC_FTW_TYPE_DIR,
CSYNC_FTW_TYPE_SKIP
};
enum csync_notify_type_e {
CSYNC_NOTIFY_INVALID,
CSYNC_NOTIFY_START_SYNC_SEQUENCE,
CSYNC_NOTIFY_START_DOWNLOAD,
CSYNC_NOTIFY_START_UPLOAD,
CSYNC_NOTIFY_PROGRESS,
CSYNC_NOTIFY_FINISHED_DOWNLOAD,
CSYNC_NOTIFY_FINISHED_UPLOAD,
CSYNC_NOTIFY_FINISHED_SYNC_SEQUENCE,
CSYNC_NOTIFY_START_DELETE,
CSYNC_NOTIFY_END_DELETE,
CSYNC_NOTIFY_ERROR
};
struct csync_progress_s {
enum csync_notify_type_e kind;
/* individual file progress information */
const char *path;
int64_t curr_bytes;
int64_t file_size;
/* overall progress */
int64_t overall_transmission_size;
int64_t current_overall_bytes;
int64_t overall_file_count;
int64_t current_file_no;
};
typedef struct csync_progress_s CSYNC_PROGRESS;
/**
* CSync File Traversal structure.
*
* This structure is passed to the visitor function for every file
* which is seen.
*
*/
struct csync_tree_walk_file_s {
const char *path;
int64_t size;
time_t modtime;
#ifdef _WIN32
uint32_t uid;
uint32_t gid;
#else
uid_t uid;
gid_t gid;
#endif
mode_t mode;
enum csync_ftw_type_e type;
enum csync_instructions_e instruction;
/* For directories: If the etag has been updated and need to be writen on the db */
int should_update_etag;
const char *rename_path;
const char *etag;
const char *file_id;
CSYNC_STATUS error_status;
};
typedef struct csync_tree_walk_file_s TREE_WALK_FILE;
/**
* csync handle
*/
typedef struct csync_s CSYNC;
typedef int (*csync_auth_callback) (const char *prompt, char *buf, size_t len,
int echo, int verify, void *userdata);
typedef void (*csync_log_callback) (int verbosity,
const char *function,
const char *buffer,
void *userdata);
/**
* @brief Check internal csync status.
*
* @param csync The context to check.
*
* @return true if status is error free, false for error states.
*/
bool csync_status_ok(CSYNC *ctx);
/**
* @brief Allocate a csync context.
*
* @param csync The context variable to allocate.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_create(CSYNC **csync, const char *local, const char *remote);
/**
* @brief Initialize the file synchronizer.
*
* This function loads the configuration, the statedb and locks the client.
*
* @param ctx The context to initialize.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_init(CSYNC *ctx);
/**
* @brief Update detection
*
* @param ctx The context to run the update detection on.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_update(CSYNC *ctx);
/**
* @brief Reconciliation
*
* @param ctx The context to run the reconciliation on.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_reconcile(CSYNC *ctx);
/**
* @brief Propagation
*
* @param ctx The context to run the propagation on.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_propagate(CSYNC *ctx);
/**
* @brief Commit the sync results to journal
*
* @param ctx The context to commit.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_commit(CSYNC *ctx);
/**
* @brief Destroy the csync context
*
* Writes the statedb, unlocks csync and frees the memory.
*
* @param ctx The context to destroy.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_destroy(CSYNC *ctx);
/**
* @brief Check if csync is the required version or get the version
* string.
*
* @param req_version The version required.
*
* @return If the version of csync is newer than the version
* required it will return a version string.
* NULL if the version is older.
*
* Example:
*
* @code
* if (csync_version(CSYNC_VERSION_INT(0,42,1)) == NULL) {
* fprintf(stderr, "libcsync version is too old!\n");
* exit(1);
* }
*
* if (debug) {
* printf("csync %s\n", csync_version(0));
* }
* @endcode
*/
const char *csync_version(int req_version);
/**
* @brief Add an additional exclude list.
*
* @param ctx The context to add the exclude list.
*
* @param path The path pointing to the file.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_add_exclude_list(CSYNC *ctx, const char *path);
/**
* @brief Removes all items imported from exclude lists.
*
* @param ctx The context to add the exclude list.
*/
void csync_clear_exclude_list(CSYNC *ctx);
/**
* @brief Get the config directory.
*
* @param ctx The csync context.
*
* @return The path of the config directory or NULL on error.
*/
const char *csync_get_config_dir(CSYNC *ctx);
/**
* @brief Change the config directory.
*
* @param ctx The csync context.
*
* @param path The path to the new config directory.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_set_config_dir(CSYNC *ctx, const char *path);
/**
* @brief Remove the complete config directory.
*
* @param ctx The csync context.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_remove_config_dir(CSYNC *ctx);
/**
* @brief Enable the usage of the statedb. It is enabled by default.
*
* @param ctx The csync context.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_enable_statedb(CSYNC *ctx);
/**
* @brief Disable the usage of the statedb. It is enabled by default.
*
* @param ctx The csync context.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_disable_statedb(CSYNC *ctx);
/**
* @brief Check if the statedb usage is enabled.
*
* @param ctx The csync context.
*
* @return 1 if it is enabled, 0 if it is disabled.
*/
int csync_is_statedb_disabled(CSYNC *ctx);
/**
* @brief Get the userdata saved in the context.
*
* @param ctx The csync context.
*
* @return The userdata saved in the context, NULL if an error
* occured.
*/
void *csync_get_userdata(CSYNC *ctx);
/**
* @brief Save userdata to the context which is passed to the auth
* callback function.
*
* @param ctx The csync context.
*
* @param userdata The userdata to be stored in the context.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_set_userdata(CSYNC *ctx, void *userdata);
/**
* @brief Get the authentication callback set.
*
* @param ctx The csync context.
*
* @return The authentication callback set or NULL if an error
* occured.
*/
csync_auth_callback csync_get_auth_callback(CSYNC *ctx);
/**
* @brief Set the authentication callback.
*
* @param ctx The csync context.
*
* @param cb The authentication callback.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb);
/**
* @brief Set the log level.
*
* @param[in] level The log verbosity.
*
* @return 0 on success, < 0 if an error occured.
*/
int csync_set_log_level(int level);
/**
* @brief Get the log verbosity
*
* @return The log verbosity, -1 on error.
*/
int csync_get_log_level(void);
/**
* @brief Get the logging callback set.
*
* @return The logging callback set or NULL if an error
* occured.
*/
csync_log_callback csync_get_log_callback(void);
/**
* @brief Set the logging callback.
*
* @param cb The logging callback.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_set_log_callback(csync_log_callback cb);
/**
* @brief get the userdata set for the logging callback.
*
* @return The userdata or NULL.
*/
void *csync_get_log_userdata(void);
/**
* @brief Set the userdata passed to the logging callback.
*
* @param[in] data The userdata to set.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_set_log_userdata(void *data);
/**
* @brief Get the path of the statedb file used.
*
* @param ctx The csync context.
*
* @return The path to the statedb file, NULL if an error occured.
*/
const char *csync_get_statedb_file(CSYNC *ctx);
/**
* @brief Enable the creation of backup copys if files are changed on both sides
*
* @param ctx The csync context.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_enable_conflictcopys(CSYNC *ctx);
/**
* @brief Flag to tell csync that only a local run is intended. Call before csync_init
*
* @param local_only Bool flag to indicate local only mode.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_set_local_only( CSYNC *ctx, bool local_only );
/**
* @brief Retrieve the flag to tell csync that only a local run is intended.
*
* @return 1: stay local only, 0: local and remote mode
*/
bool csync_get_local_only( CSYNC *ctx );
/* Used for special modes or debugging */
CSYNC_STATUS csync_get_status(CSYNC *ctx);
/* Used for special modes or debugging */
int csync_set_status(CSYNC *ctx, int status);
typedef int csync_treewalk_visit_func(TREE_WALK_FILE* ,void*);
/**
* @brief Walk the local file tree and call a visitor function for each file.
*
* @param ctx The csync context.
* @param visitor A callback function to handle the file info.
* @param filter A filter, built from or'ed csync_instructions_e
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
/**
* @brief Walk the remote file tree and call a visitor function for each file.
*
* @param ctx The csync context.
* @param visitor A callback function to handle the file info.
* @param filter A filter, built from and'ed csync_instructions_e
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
/**
* @brief Get the csync status string.
*
* @param ctx The csync context.
*
* @return A const pointer to a string with more precise status info.
*/
const char *csync_get_status_string(CSYNC *ctx);
#ifdef WITH_ICONV
/**
* @brief Set iconv source codec for filenames.
*
* @param from Source codec.
*
* @return 0 on success, or an iconv error number.
*/
int csync_set_iconv_codec(const char *from);
#endif
/**
* @brief Set a property to module
*
* @param ctx The csync context.
*
* @param key The property key
*
* @param value An opaque pointer to the data.
*
* @return 0 on success, less than 0 if an error occured.
*/
int csync_set_module_property(CSYNC *ctx, const char *key, void *value);
/**
* @brief Callback definition for file progress callback.
*
* @param progress A struct containing progress information.
*
* @param userdata User defined data for the callback.
*/
typedef void (*csync_progress_callback)( CSYNC_PROGRESS *progress, void *userdata);
/**
* @brief Set a progress callback.
*
* This callback reports about up- or download progress of a individual file
* as well as overall progress.
*/
int csync_set_progress_callback( CSYNC *ctx, csync_progress_callback cb);
csync_progress_callback csync_get_progress_callback(CSYNC *ctx);
/**
* @brief Aborts the current sync run as soon as possible. Can be called from another thread.
*
* @param ctx The csync context.
*/
void csync_request_abort(CSYNC *ctx);
/**
* @brief Clears the abort flag. Can be called from another thread.
*
* @param ctx The csync context.
*/
void csync_resume(CSYNC *ctx);
/**
* @brief Checks for the abort flag, to be used from the modules.
*
* @param ctx The csync context.
*/
int csync_abort_requested(CSYNC *ctx);
#ifdef __cplusplus
}
#endif
/**
* }@
*/
#endif /* _CSYNC_H */
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */

362
csync/src/csync_config.c Normal file
View File

@ -0,0 +1,362 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
#include "config.h"
/* #define _GNU_SOURCE */
#include <stdio.h>
#include <ctype.h>
#include "c_lib.h"
#include "c_private.h"
#include "csync_private.h"
#include "csync_config.h"
#include "csync_misc.h"
#define CSYNC_LOG_CATEGORY_NAME "csync.config"
#include "csync_log.h"
enum csync_config_opcode_e {
COC_UNSUPPORTED = -1,
COC_MAX_TIMEDIFF,
COC_MAX_DEPTH,
COC_WITH_CONFLICT_COPY,
COC_TIMEOUT
};
struct csync_config_keyword_table_s {
const char *name;
enum csync_config_opcode_e opcode;
};
static struct csync_config_keyword_table_s csync_config_keyword_table[] = {
{ "max_depth", COC_MAX_DEPTH },
{ "max_time_difference", COC_MAX_TIMEDIFF },
{ "with_confilct_copies", COC_WITH_CONFLICT_COPY },
{ "timeout", COC_TIMEOUT },
{ NULL, COC_UNSUPPORTED }
};
static enum csync_config_opcode_e csync_config_get_opcode(char *keyword) {
int i;
for (i = 0; csync_config_keyword_table[i].name != NULL; i++) {
if (strcasecmp(keyword, csync_config_keyword_table[i].name) == 0) {
return csync_config_keyword_table[i].opcode;
}
}
return COC_UNSUPPORTED;
}
static int _csync_config_copy_default (const char *config) {
int rc = 0;
#ifdef _WIN32
/* For win32, try to copy the conf file from the directory from where the app was started. */
mbchar_t tcharbuf[MAX_PATH+1];
char *buf;
int len = 0;
/* Get the path from where the application was started */
len = GetModuleFileNameW(NULL, tcharbuf, MAX_PATH);
if(len== 0) {
rc = -1;
} else {
char *last_bslash;
buf = c_utf8_from_locale(tcharbuf);
/* cut the trailing filename off */
if ((last_bslash = strrchr(buf, '\\')) != NULL) {
*last_bslash='\0';
}
strncat(buf, "\\" CSYNC_CONF_FILE, MAX_PATH);
if(c_copy(buf, config, 0644) < 0) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Could not copy /%s to %s", buf, config );
rc = -1;
}
c_free_locale_string(buf);
}
#else
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Copy %s/config/%s to %s", SYSCONFDIR,
CSYNC_CONF_FILE, config);
# ifdef WITH_UNIT_TESTING
rc = c_copy(BINARYDIR "/config/" CSYNC_CONF_FILE, config, 0644);
# else
rc = 0;
# endif
if (c_copy(SYSCONFDIR "/ocsync/" CSYNC_CONF_FILE, config, 0644) < 0) {
if (c_copy(BINARYDIR "/config/" CSYNC_CONF_FILE, config, 0644) < 0) {
rc = -1;
}
}
#endif
return rc;
}
static char *csync_config_get_cmd(char **str) {
register char *c;
char *r;
/* Ignore leading spaces */
for (c = *str; *c; c++) {
if (! isblank(*c)) {
break;
}
}
if (*c == '\"') {
for (r = ++c; *c; c++) {
if (*c == '\"') {
*c = '\0';
goto out;
}
}
}
for (r = c; *c; c++) {
if (*c == '\n') {
*c = '\0';
goto out;
}
}
out:
*str = c + 1;
return r;
}
static char *csync_config_get_token(char **str) {
register char *c;
char *r;
c = csync_config_get_cmd(str);
for (r = c; *c; c++) {
if (isblank(*c)) {
*c = '\0';
goto out;
}
}
out:
*str = c + 1;
return r;
}
static int csync_config_get_int(char **str, int notfound) {
char *p, *endp;
int i;
p = csync_config_get_token(str);
if (p && *p) {
i = strtol(p, &endp, 10);
if (p == endp) {
return notfound;
}
return i;
}
return notfound;
}
static const char *csync_config_get_str_tok(char **str, const char *def) {
char *p;
p = csync_config_get_token(str);
if (p && *p) {
return p;
}
return def;
}
static int csync_config_get_yesno(char **str, int notfound) {
const char *p;
p = csync_config_get_str_tok(str, NULL);
if (p == NULL) {
return notfound;
}
if (strncasecmp(p, "yes", 3) == 0) {
return 1;
} else if (strncasecmp(p, "no", 2) == 0) {
return 0;
}
return notfound;
}
static int csync_config_parse_line(CSYNC *ctx,
const char *line,
unsigned int count)
{
enum csync_config_opcode_e opcode;
char *s, *x;
char *keyword;
size_t len;
int i;
x = s = c_strdup(line);
if (s == NULL) {
return -1;
}
/* Remove trailing spaces */
for (len = strlen(s) - 1; len > 0; len--) {
if (! isspace(s[len])) {
break;
}
s[len] = '\0';
}
keyword = csync_config_get_token(&s);
if (keyword == NULL || keyword[0] == '#' ||
keyword[0] == '\0' || keyword[0] == '\n') {
free(x);
return 0;
}
opcode = csync_config_get_opcode(keyword);
switch (opcode) {
case COC_MAX_DEPTH:
i = csync_config_get_int(&s, 50);
if (i > 0) {
ctx->options.max_depth = i;
}
break;
case COC_MAX_TIMEDIFF:
i = csync_config_get_int(&s, 10);
if (i >= 0) {
ctx->options.max_time_difference = i;
}
break;
case COC_WITH_CONFLICT_COPY:
i = csync_config_get_yesno(&s, -1);
if (i > 0) {
ctx->options.with_conflict_copys = true;
} else {
ctx->options.with_conflict_copys = false;
}
break;
case COC_TIMEOUT:
i = csync_config_get_int(&s, 0);
if (i > 0) {
ctx->options.timeout = i;
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Config: timeout = %d",
ctx->options.timeout);
}
break;
case COC_UNSUPPORTED:
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
"Unsupported option: %s, line: %d\n",
keyword, count);
break;
}
free(x);
return 0;
}
int csync_config_parse_file(CSYNC *ctx, const char *config)
{
unsigned int count = 0;
char line[1024] = {0};
char *s;
FILE *f;
/* copy default config, if no config exists */
if (! c_isfile(config)) {
/* check if there is still one csync.conf left over in $HOME/.csync
* and copy it over (migration path)
*/
char *home = NULL;
char *home_config = NULL;
char *config_file = NULL;
/* there is no statedb at the expected place. */
home = csync_get_user_home_dir();
if( !c_streq(home, ctx->options.config_dir) ) {
int rc = -1;
config_file = c_basename(config);
if( config_file ) {
rc = asprintf(&home_config, "%s/%s/%s", home, CSYNC_CONF_DIR, config_file);
SAFE_FREE(config_file);
}
if (rc >= 0) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "config file %s not found, checking %s",
config, home_config);
/* check the home file and copy to new statedb if existing. */
if(c_isfile(home_config)) {
if (c_copy(home_config, config, 0644) < 0) {
/* copy failed, but that is not reason to die. */
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Could not copy config %s => %s",
home_config, config);
} else {
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "Copied %s => %s",
home_config, config);
}
}
}
SAFE_FREE(home_config);
}
SAFE_FREE(home);
/* Still install the default one if nothing is there. */
if( ! c_isfile(config)) {
if (_csync_config_copy_default(config) < 0) {
return -1;
}
}
}
f = fopen(config, "r");
if (f == NULL) {
return 0;
}
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
"Reading configuration data from %s",
config);
s = fgets(line, sizeof(line), f);
while (s != NULL) {
int rc;
count++;
rc = csync_config_parse_line(ctx, line, count);
if (rc < 0) {
fclose(f);
return -1;
}
s = fgets(line, sizeof(line), f);
}
fclose(f);
return 0;
}

40
csync/src/csync_config.h Normal file
View File

@ -0,0 +1,40 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
#ifndef _CSYNC_CONFIG_H
#define _CSYNC_CONFIG_H
/**
* @internal
*
* @brief Load the csync configuration.
*
* @param ctx The csync context to use.
*
* @param config The path to the config file.
*
* @return 0 on success, < 0 on error.
*/
int csync_config_load(CSYNC *ctx, const char *config);
int csync_config_parse_file(CSYNC *ctx, const char *config);
#endif /* _CSYNC_X_H */
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */

235
csync/src/csync_dbtree.c Normal file
View File

@ -0,0 +1,235 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2012 by Klaas Freitag <freitag@owncloud.com>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
#include "config.h"
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include "csync_dbtree.h"
#include "c_lib.h"
#include "csync_private.h"
#include "csync_statedb.h"
#include "csync_util.h"
#include "c_macro.h"
#define CSYNC_LOG_CATEGORY_NAME "csync.dbtree"
#include "csync_log.h"
struct dir_listing {
c_list_t *list;
unsigned int cnt;
c_list_t *entry;
char *dir;
};
csync_vio_method_handle_t *csync_dbtree_opendir(CSYNC *ctx, const char *name)
{
char *column = NULL;
const char *path = NULL;
csync_vio_file_stat_t *fs = NULL;
unsigned int c = 0;
c_strlist_t *list = NULL;
struct dir_listing *listing = NULL;
/* "phash INTEGER(8),"
"pathlen INTEGER,"
"path VARCHAR(4096),"
"inode INTEGER,"
"uid INTEGER,"
"gid INTEGER,"
"mode INTEGER,"
"modtime INTEGER(8),"
"type INTEGER,"
"md5 VARCHAR(32)," // That's the etag
*/
int col_count = 10;
if( strlen(name) < strlen(ctx->remote.uri)+1) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "name does not contain remote uri!");
return NULL;
}
path = name + strlen(ctx->remote.uri)+1;
list = csync_statedb_get_below_path(ctx, path);
if( ! list ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Query result list is NULL!");
return NULL;
}
/* list count must be a multiple of col_count */
if( list->count % col_count != 0 ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Wrong size of query result list");
c_strlist_destroy( list );
return NULL;
}
listing = c_malloc(sizeof(struct dir_listing));
ZERO_STRUCTP(listing);
if( listing == NULL ) {
c_strlist_destroy( list );
errno = ENOMEM;
return NULL;
}
listing->dir = c_strdup(path);
for( c = 0; c < (list->count / col_count); c++) {
int base = c*col_count;
int cnt = 0;
int tpath_len = 0;
int type = 0;
char *tpath = list->vector[base+1];
/* check if the result points to a file directly below the search path
* by checking if there is another / in the result.
* If yes, skip it.
* FIXME: Find a better filter solution here.
*/
tpath += strlen(path)+1; /* jump over the search path */
tpath_len = strlen( tpath );
while( cnt < tpath_len ) {
if(*(tpath+cnt) == '/') {
/* CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Skipping entry: %s", list->vector[base+1]); */
break;
}
cnt++;
}
if( cnt < tpath_len ) continue;
if (!list->vector[base+8][0])
continue; /* If etag is empty, the file was removed on the server */
fs = csync_vio_file_stat_new();
fs->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
column = list->vector[base+0]; /* phash */
column = list->vector[base+1]; /* path */
fs->name = c_strdup(column+strlen(path)+1);
column = list->vector[base+2]; /* inode */
fs->inode = atoll(column);
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_INODE;
column = list->vector[base+3]; /* uid */
fs->uid = atoi(column);
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_UID;
column = list->vector[base+4]; /* gid */
fs->gid = atoi(column);
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_GID;
column = list->vector[base+5]; /* mode */
fs->mode = atoi(column);
// fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_M;
column = list->vector[base+6]; /* modtime */
fs->mtime = strtoul(column, NULL, 10);
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
column = list->vector[base+7]; /* type */
type = atoi(column);
/* Attention: the type of csync_ftw_type_e which is the source for
* the database entry is different from csync_vio_file_type_e which
* is the target file type here. Mapping is needed!
*/
switch( type ) {
case CSYNC_FTW_TYPE_DIR:
fs->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
break;
case CSYNC_FTW_TYPE_FILE:
fs->type = CSYNC_VIO_FILE_TYPE_REGULAR;
break;
case CSYNC_FTW_TYPE_SLINK:
fs->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
break;
default:
fs->type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
}
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
column = list->vector[base+8]; /* etag */
fs->etag = c_strdup(column);
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG;
column = list->vector[base+9]; /* file id */
csync_vio_file_stat_set_file_id(fs, column);
/* store into result list. */
listing->list = c_list_append( listing->list, fs );
listing->cnt++;
}
if(listing->cnt)
listing->entry = c_list_first( listing->list );
c_strlist_destroy( list );
return listing;
}
int csync_dbtree_closedir(CSYNC *ctx, csync_vio_method_handle_t *dhandle)
{
struct dir_listing *dl = NULL;
int rc = 0;
(void) ctx;
if( dhandle != NULL ) {
dl = (struct dir_listing*) dhandle;
c_list_free(dl->list);
SAFE_FREE(dl->dir);
SAFE_FREE(dl);
}
return rc;
}
csync_vio_file_stat_t *csync_dbtree_readdir(CSYNC *ctx, csync_vio_method_handle_t *dhandle)
{
csync_vio_file_stat_t *fs = NULL;
struct dir_listing *dl = NULL;
(void) ctx;
if( dhandle != NULL ) {
dl = (struct dir_listing*) dhandle;
if( dl->entry != NULL ) {
fs = (csync_vio_file_stat_t*) dl->entry->data;
dl->entry = c_list_next( dl->entry);
}
}
return fs;
}
/* vim: set ts=8 sw=2 et cindent: */

60
csync/src/csync_dbtree.h Normal file
View File

@ -0,0 +1,60 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2012 by Klaas Freitag <freitag@owncloud.com>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
/**
* @file csync_dbtree.h
*
* @brief Private interface of csync
*
* @defgroup csyncdbtreeInternals csync statedb internals
* @ingroup csyncInternalAPI
*
* @{
*/
#ifndef _CSYNC_DBTREE_H
#define _CSYNC_DBTREE_H
#include "c_lib.h"
#include "csync_private.h"
#include "vio/csync_vio_handle.h"
/**
* @brief Open a directory based on the statedb.
*
* This function reads the list of files within a directory from statedb and
* builds up a list in memory.
*
* @param ctx The csync context.
* @param name The directory name.
*
* @return 0 on success, less than 0 if an error occured with errno set.
*/
csync_vio_method_handle_t *csync_dbtree_opendir(CSYNC *ctx, const char *name);
int csync_dbtree_closedir(CSYNC *ctx, csync_vio_method_handle_t *dhandle);
csync_vio_file_stat_t *csync_dbtree_readdir(CSYNC *ctx, csync_vio_method_handle_t *dhandle);
/**
* }@
*/
#endif /* _CSYNC_DBTREE_H */
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */

286
csync/src/csync_exclude.c Normal file
View File

@ -0,0 +1,286 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "c_lib.h"
#include "csync_private.h"
#include "csync_exclude.h"
#include "csync_misc.h"
#define CSYNC_LOG_CATEGORY_NAME "csync.exclude"
#include "csync_log.h"
static int _csync_exclude_add(CSYNC *ctx, const char *string) {
c_strlist_t *list;
if (ctx->excludes == NULL) {
ctx->excludes = c_strlist_new(32);
if (ctx->excludes == NULL) {
return -1;
}
}
if (ctx->excludes->count == ctx->excludes->size) {
list = c_strlist_expand(ctx->excludes, 2 * ctx->excludes->size);
if (list == NULL) {
return -1;
}
ctx->excludes = list;
}
return c_strlist_add(ctx->excludes, string);
}
int csync_exclude_load(CSYNC *ctx, const char *fname) {
int fd = -1;
int i = 0;
int rc = -1;
int64_t size;
char *buf = NULL;
char *entry = NULL;
mbchar_t *w_fname;
if (ctx == NULL || fname == NULL) {
return -1;
}
#ifdef _WIN32
_fmode = _O_BINARY;
#endif
w_fname = c_utf8_to_locale(fname);
if (w_fname == NULL) {
return -1;
}
fd = _topen(w_fname, O_RDONLY);
c_free_locale_string(w_fname);
if (fd < 0) {
return -1;
}
size = lseek(fd, 0, SEEK_END);
if (size < 0) {
rc = -1;
goto out;
}
lseek(fd, 0, SEEK_SET);
if (size == 0) {
rc = 0;
goto out;
}
buf = c_malloc(size + 1);
if (buf == NULL) {
rc = -1;
goto out;
}
if (read(fd, buf, size) != size) {
rc = -1;
goto out;
}
buf[size] = '\0';
/* FIXME: Use fgets and don't add duplicates */
entry = buf;
for (i = 0; i < size; i++) {
if (buf[i] == '\n' || buf[i] == '\r') {
if (entry != buf + i) {
buf[i] = '\0';
if (*entry != '#') {
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Adding entry: %s", entry);
rc = _csync_exclude_add(ctx, entry);
if (rc < 0) {
goto out;
}
}
}
entry = buf + i + 1;
}
}
rc = 0;
out:
SAFE_FREE(buf);
close(fd);
return rc;
}
void csync_exclude_clear(CSYNC *ctx) {
c_strlist_clear(ctx->excludes);
}
void csync_exclude_destroy(CSYNC *ctx) {
c_strlist_destroy(ctx->excludes);
}
CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) {
size_t i = 0;
const char *p = NULL;
char *bname = NULL;
char *dname = NULL;
char *prev_dname = NULL;
int rc = -1;
CSYNC_EXCLUDE_TYPE match = CSYNC_NOT_EXCLUDED;
CSYNC_EXCLUDE_TYPE type = CSYNC_NOT_EXCLUDED;
/* exclude the lock file */
if (c_streq( path, CSYNC_LOCK_FILE )) {
return CSYNC_FILE_SILENTLY_EXCLUDED;
}
if (! ctx->options.unix_extensions) {
for (p = path; *p; p++) {
switch (*p) {
case '\\':
case ':':
case '?':
case '*':
case '"':
case '>':
case '<':
case '|':
return CSYNC_FILE_EXCLUDE_INVALID_CHAR;
default:
break;
}
}
}
/* split up the path */
dname = c_dirname(path);
bname = c_basename(path);
if (bname == NULL || dname == NULL) {
match = CSYNC_NOT_EXCLUDED;
SAFE_FREE(bname);
SAFE_FREE(dname);
goto out;
}
rc = csync_fnmatch(".csync_journal.db*", bname, 0);
if (rc == 0) {
match = CSYNC_FILE_SILENTLY_EXCLUDED;
SAFE_FREE(bname);
SAFE_FREE(dname);
goto out;
}
SAFE_FREE(bname);
SAFE_FREE(dname);
SAFE_FREE(bname);
SAFE_FREE(dname);
if (ctx->excludes == NULL) {
goto out;
}
/* Loop over all exclude patterns and evaluate the given path */
for (i = 0; match == CSYNC_NOT_EXCLUDED && i < ctx->excludes->count; i++) {
bool match_dirs_only = false;
char *pattern_stored = c_strdup(ctx->excludes->vector[i]);
char* pattern = pattern_stored;
type = CSYNC_FILE_EXCLUDE_LIST;
if (strlen(pattern) < 1) {
continue;
}
/* Ecludes starting with ']' means it can be cleanup */
if (pattern[0] == ']') {
++pattern;
if (filetype == CSYNC_FTW_TYPE_FILE) {
type = CSYNC_FILE_EXCLUDE_AND_REMOVE;
}
}
/* Check if the pattern applies to pathes only. */
if (pattern[strlen(pattern)-1] == '/') {
match_dirs_only = true;
pattern[strlen(pattern)-1] = '\0'; /* Cut off the slash */
}
/* check if the pattern contains a / and if, compare to the whole path */
if (strchr(pattern, '/')) {
rc = csync_fnmatch(pattern, path, FNM_PATHNAME);
if( rc == 0 ) {
match = type;
}
/* if the pattern requires a dir, but path is not, its still not excluded. */
if (match_dirs_only && filetype != CSYNC_FTW_TYPE_DIR) {
match = CSYNC_NOT_EXCLUDED;
}
}
/* if still not excluded, check each component of the path */
if (match == CSYNC_NOT_EXCLUDED) {
int trailing_component = 1;
dname = c_dirname(path);
bname = c_basename(path);
if (bname == NULL || dname == NULL) {
match = CSYNC_NOT_EXCLUDED;
goto out;
}
/* Check each component of the path */
do {
/* Do not check the bname if its a file and the pattern matches dirs only. */
if ( !(trailing_component == 1 /* it is the trailing component */
&& match_dirs_only /* but only directories are matched by the pattern */
&& filetype == CSYNC_FTW_TYPE_FILE) ) {
/* Check the name component against the pattern */
rc = csync_fnmatch(pattern, bname, 0);
if (rc == 0) {
match = type;
}
}
if (!(c_streq(dname, ".") || c_streq(dname, "/"))) {
rc = csync_fnmatch(pattern, dname, 0);
if (rc == 0) {
match = type;
}
}
trailing_component = 0;
prev_dname = dname;
SAFE_FREE(bname);
bname = c_basename(prev_dname);
dname = c_dirname(prev_dname);
SAFE_FREE(prev_dname);
} while( match == CSYNC_NOT_EXCLUDED && !c_streq(dname, ".")
&& !c_streq(dname, "/") );
}
SAFE_FREE(pattern_stored);
SAFE_FREE(bname);
SAFE_FREE(dname);
}
out:
return match;
}

70
csync/src/csync_exclude.h Normal file
View File

@ -0,0 +1,70 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
#ifndef _CSYNC_EXCLUDE_H
#define _CSYNC_EXCLUDE_H
enum csync_exclude_type_e {
CSYNC_NOT_EXCLUDED = 0,
CSYNC_FILE_SILENTLY_EXCLUDED,
CSYNC_FILE_EXCLUDE_AND_REMOVE,
CSYNC_FILE_EXCLUDE_LIST,
CSYNC_FILE_EXCLUDE_INVALID_CHAR
};
typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE;
/**
* @brief Load exclude list
*
* @param ctx The context of the synchronizer.
* @param fname The filename to load.
*
* @return 0 on success, -1 if an error occured with errno set.
*/
int csync_exclude_load(CSYNC *ctx, const char *fname);
/**
* @brief Clear the exclude list in memory.
*
* @param ctx The synchronizer context.
*/
void csync_exclude_clear(CSYNC *ctx);
/**
* @brief Destroy the exclude list in memory.
*
* @param ctx The synchronizer context.
*/
void csync_exclude_destroy(CSYNC *ctx);
/**
* @brief Check if the given path should be excluded.
*
* This excludes also paths which can't be used without unix extensions.
*
* @param ctx The synchronizer context.
* @param path The patch to check.
*
* @return 2 if excluded and needs cleanup, 1 if excluded, 0 if not.
*/
CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype);
#endif /* _CSYNC_EXCLUDE_H */
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */

236
csync/src/csync_lock.c Normal file
View File

@ -0,0 +1,236 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
#include "config.h"
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "c_lib.h"
#include "csync_lock.h"
#include "csync.h"
#define CSYNC_LOG_CATEGORY_NAME "csync.lock"
#include "csync_log.h"
#ifdef _DO_CREATE_A_LOCK_FILE
static int _csync_lock_create(const char *lockfile) {
int fd = -1;
pid_t pid = 0;
int rc = -1;
char errbuf[256] = {0};
char *ctmpfile = NULL;
char *dir = NULL;
char *buf = NULL;
mode_t mask;
pid = getpid();
dir = c_dirname(lockfile);
if (dir == NULL) {
rc = -1;
goto out;
}
if (asprintf(&ctmpfile, "%s/tmp_lock_XXXXXX", dir) < 0) {
rc = -1;
goto out;
}
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Create temporary lock file: %s", ctmpfile);
mask = umask(0077);
fd = mkstemp(ctmpfile);
umask(mask);
if (fd < 0) {
strerror_r(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"Unable to create temporary lock file: %s - %s",
ctmpfile,
errbuf);
rc = -1;
goto out;
}
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Write pid (%d) to temporary lock file: %s", pid, ctmpfile);
pid = asprintf(&buf, "%d\n", pid);
if (write(fd, buf, pid) == pid) {
/* Create lock file */
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Create a hardlink from %s to %s.", ctmpfile, lockfile);
if (link(ctmpfile, lockfile) < 0 ) {
/* Oops, alredy locked */
strerror_r(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO,
"Already locked: %s - %s",
lockfile,
errbuf);
rc = -1;
goto out;
}
} else {
strerror_r(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"Can't create %s - %s",
ctmpfile,
errbuf);
rc = -1;
goto out;
}
rc = 0;
out:
if (fd > 0) {
close(fd);
}
if (ctmpfile) {
unlink(ctmpfile);
}
SAFE_FREE(buf);
SAFE_FREE(dir);
SAFE_FREE(ctmpfile);
return rc;
}
static pid_t _csync_lock_read(const char *lockfile) {
char errbuf[256] = {0};
char buf[8] = {0};
long int tmp;
ssize_t rc;
int fd;
pid_t pid;
mbchar_t *wlockfile;
/* Read PID from existing lock */
#ifdef _WIN32
_fmode = _O_BINARY;
#endif
wlockfile = c_utf8_to_locale(lockfile);
if (wlockfile == NULL) {
return -1;
}
fd = _topen(wlockfile, O_RDONLY);
c_free_locale_string(wlockfile);
if (fd < 0) {
return -1;
}
rc = read(fd, buf, sizeof(buf));
close(fd);
if (rc <= 0) {
return -1;
}
buf[sizeof(buf) - 1] = '\0';
tmp = strtol(buf, NULL, 10);
if (tmp == 0 || tmp > 0xFFFF || errno == ERANGE) {
/* Broken lock file */
strerror_r(ERANGE, errbuf, sizeof(errbuf));
if (unlink(lockfile) < 0) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"Unable to remove broken lock %s - %s",
lockfile,
errbuf);
}
return -1;
}
pid = (pid_t)(tmp & 0xFFFF);
/* Check if process is still alive */
if (kill(pid, 0) < 0 && errno == ESRCH) {
/* Process is dead. Remove stale lock. */
wlockfile = c_utf8_to_locale(lockfile);
if (_tunlink(wlockfile) < 0) {
strerror_r(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"Unable to remove stale lock %s - %s",
lockfile,
errbuf);
}
c_free_locale_string(wlockfile);
return -1;
}
return pid;
}
#endif
int csync_lock(const char *lockfile) {
#ifdef _DO_CREATE_A_LOCK_FILE /* disable lock file for ownCloud client, not only _WIN32 */
/* Check if lock already exists. */
if (_csync_lock_read(lockfile) > 0) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Aborting, another synchronization process is running.");
return -1;
}
CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "Creating lock file: %s", lockfile);
return _csync_lock_create(lockfile);
#else
(void) lockfile;
return 0;
#endif
}
void csync_lock_remove(const char *lockfile) {
#ifdef _DO_CREATE_A_LOCK_FILE
#ifndef _WIN32
char errbuf[256] = {0};
mbchar_t *wlockfile;
/* You can't remove the lock if it is from another process */
if (_csync_lock_read(lockfile) == getpid()) {
wlockfile = c_utf8_to_locale(lockfile);
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Removing lock file: %s", lockfile);
if (_tunlink(wlockfile) < 0) {
strerror_r(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"Unable to remove lock %s - %s",
lockfile,
errbuf);
}
c_free_locale_string(wlockfile);
}
#endif
#else
(void) lockfile;
#endif
}

66
csync/src/csync_lock.h Normal file
View File

@ -0,0 +1,66 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
#ifndef _CSYNC_LOCK_H
#define _CSYNC_LOCK_H
#include "csync.h"
/**
* @file csync_lock.h
*
* @brief File locking
*
* This prevents csync to start the same synchronization task twice which could
* lead to several problems.
*
* @defgroup csyncLockingInternals csync file lockling internals
* @ingroup csyncInternalAPI
*
* @{
*/
/**
* @brief Lock the client if possible.
*
* This functiion tries to lock the client with a lock file.
*
* @param lockfile The lock file to create.
*
* @return 0 if the lock was successfull, less than 0 if the lock file
* couldn't be created or if it is already locked.
*/
int csync_lock(const char *lockfile);
/**
* @brief Remove the lockfile
*
* Only our own lock can be removed. This function can't remove a lock from
* another client.
*
* @param lockfile The lock file to remove.
*/
void csync_lock_remove(const char *lockfile);
/**
* }@
*/
#endif /* _CSYNC_LOCK_H */
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */

157
csync/src/csync_log.c Normal file
View File

@ -0,0 +1,157 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
#include "config.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#ifndef _WIN32
#include <sys/time.h>
#else
#include <sys/utime.h>
#endif
#include <time.h>
#include "csync_private.h"
#include "csync_log.h"
CSYNC_THREAD int csync_log_level;
CSYNC_THREAD csync_log_callback csync_log_cb;
CSYNC_THREAD void *csync_log_userdata;
static int current_timestring(int hires, char *buf, size_t len)
{
char tbuf[64];
struct timeval tv;
struct tm *tm;
time_t t;
gettimeofday(&tv, NULL);
t = (time_t) tv.tv_sec;
tm = localtime(&t);
if (tm == NULL) {
return -1;
}
if (hires) {
strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
snprintf(buf, len, "%s.%06ld", tbuf, (long) tv.tv_usec);
} else {
strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
snprintf(buf, len, "%s", tbuf);
}
return 0;
}
static void csync_log_stderr(int verbosity,
const char *function,
const char *buffer)
{
char date[64] = {0};
int rc;
rc = current_timestring(1, date, sizeof(date));
if (rc == 0) {
fprintf(stderr, "[%s, %d] %s:", date+5, verbosity, function);
} else {
fprintf(stderr, "[%d] %s", verbosity, function);
}
fprintf(stderr, " %s\n", buffer);
}
static void csync_log_function(int verbosity,
const char *function,
const char *buffer)
{
csync_log_callback log_fn = csync_get_log_callback();
if (log_fn) {
char buf[1024];
snprintf(buf, sizeof(buf), "%s: %s", function, buffer);
log_fn(verbosity,
function,
buf,
csync_get_log_userdata());
return;
}
csync_log_stderr(verbosity, function, buffer);
}
void csync_log(int verbosity,
const char *function,
const char *format, ...)
{
char buffer[1024];
va_list va;
if (verbosity <= csync_get_log_level()) {
va_start(va, format);
vsnprintf(buffer, sizeof(buffer), format, va);
va_end(va);
csync_log_function(verbosity, function, buffer);
}
}
int csync_set_log_level(int level) {
if (level < 0) {
return -1;
}
csync_log_level = level;
return 0;
}
int csync_get_log_level(void) {
return csync_log_level;
}
int csync_set_log_callback(csync_log_callback cb) {
if (cb == NULL) {
return -1;
}
csync_log_cb = cb;
return 0;
}
csync_log_callback csync_get_log_callback(void) {
return csync_log_cb;
}
void *csync_get_log_userdata(void)
{
return csync_log_userdata;
}
int csync_set_log_userdata(void *data)
{
csync_log_userdata = data;
return 0;
}

75
csync/src/csync_log.h Normal file
View File

@ -0,0 +1,75 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
/**
* @file csync_log.h
*
* @brief Logging interface of csync
*
* @defgroup csyncLogInternals csync logging internals
* @ingroup csyncInternalAPI
*
* @{
*/
#ifndef _CSYNC_LOG_H
#define _CSYNC_LOG_H
/* GCC have printf type attribute check. */
#ifndef PRINTF_ATTRIBUTE
#ifdef __GNUC__
#ifdef _WIN32
#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__gnu_printf__, a, b)))
#else
#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
#endif
#else
#define PRINTF_ATTRIBUTE(a,b)
#endif /* __GNUC__ */
#endif /* ndef PRINTF_ATTRIBUTE */
enum csync_log_priority_e {
CSYNC_LOG_PRIORITY_NOLOG = 0,
CSYNC_LOG_PRIORITY_FATAL,
CSYNC_LOG_PRIORITY_ALERT,
CSYNC_LOG_PRIORITY_CRIT,
CSYNC_LOG_PRIORITY_ERROR,
CSYNC_LOG_PRIORITY_WARN,
CSYNC_LOG_PRIORITY_NOTICE,
CSYNC_LOG_PRIORITY_INFO,
CSYNC_LOG_PRIORITY_DEBUG,
CSYNC_LOG_PRIORITY_TRACE,
CSYNC_LOG_PRIORITY_NOTSET,
CSYNC_LOG_PRIORITY_UNKNOWN,
};
#define CSYNC_LOG(priority, ...) \
csync_log(priority, __FUNCTION__, __VA_ARGS__)
void csync_log(int verbosity,
const char *function,
const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
/**
* }@
*/
#endif /* _CSYNC_LOG_H */
/* vim: set ft=c.doxygen ts=4 sw=4 et cindent: */

52
csync/src/csync_macros.h Normal file
View File

@ -0,0 +1,52 @@
/*
* cynapses libc functions
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
#ifndef _CSYNC_MACROS_H
#define _CSYNC_MACROS_H
#include <stdlib.h>
#include <string.h>
/* How many elements there are in a static array */
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
/* Some special custom errno values to report bugs properly. The BASE value
* should always be larger than the highest system errno. */
#define CSYNC_CUSTOM_ERRNO_BASE 10000
#define ERRNO_GENERAL_ERROR CSYNC_CUSTOM_ERRNO_BASE+2
#define ERRNO_LOOKUP_ERROR CSYNC_CUSTOM_ERRNO_BASE+3
#define ERRNO_USER_UNKNOWN_ON_SERVER CSYNC_CUSTOM_ERRNO_BASE+4
#define ERRNO_PROXY_AUTH CSYNC_CUSTOM_ERRNO_BASE+5
#define ERRNO_CONNECT CSYNC_CUSTOM_ERRNO_BASE+6
#define ERRNO_TIMEOUT CSYNC_CUSTOM_ERRNO_BASE+7
#define ERRNO_PRECONDITION CSYNC_CUSTOM_ERRNO_BASE+8
#define ERRNO_RETRY CSYNC_CUSTOM_ERRNO_BASE+9
#define ERRNO_REDIRECT CSYNC_CUSTOM_ERRNO_BASE+10
#define ERRNO_WRONG_CONTENT CSYNC_CUSTOM_ERRNO_BASE+11
#define ERRNO_TIMEDELTA CSYNC_CUSTOM_ERRNO_BASE+12
#define ERRNO_ERROR_STRING CSYNC_CUSTOM_ERRNO_BASE+13
#define ERRNO_SERVICE_UNAVAILABLE CSYNC_CUSTOM_ERRNO_BASE+14
#define ERRNO_QUOTA_EXCEEDED CSYNC_CUSTOM_ERRNO_BASE+15
#define ERRNO_USER_ABORT CSYNC_CUSTOM_ERRNO_BASE+16
#endif /* _CSYNC_MACROS_H */
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */

292
csync/src/csync_misc.c Normal file
View File

@ -0,0 +1,292 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
#include "config.h"
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
#if _WIN32
# ifndef _WIN32_IE
# define _WIN32_IE 0x0501 // SHGetSpecialFolderPath
# endif
# include <shlobj.h>
#else /* _WIN32 */
# include <pwd.h>
# include <unistd.h>
#endif /* _WIN32 */
#include "c_lib.h"
#include "csync_misc.h"
#include "csync_macros.h"
#include "csync_log.h"
#ifdef _WIN32
char *csync_get_user_home_dir(void) {
wchar_t tmp[MAX_PATH];
char *szPath = NULL;
if( SHGetFolderPathW( NULL,
CSIDL_PROFILE|CSIDL_FLAG_CREATE,
NULL,
0,
tmp) == S_OK ) {
szPath = c_utf8_from_locale(tmp);
return szPath;
}
return NULL;
}
char *csync_get_local_username(void) {
DWORD size = 0;
char *user;
/* get the size */
GetUserName(NULL, &size);
user = (char *) c_malloc(size);
if (user == NULL) {
return NULL;
}
if (GetUserName(user, &size)) {
return user;
}
return NULL;
}
#else /* ************* !WIN32 ************ */
#ifndef NSS_BUFLEN_PASSWD
#define NSS_BUFLEN_PASSWD 4096
#endif /* NSS_BUFLEN_PASSWD */
char *csync_get_user_home_dir(void) {
const char *envp;
struct passwd pwd;
struct passwd *pwdbuf;
char buf[NSS_BUFLEN_PASSWD];
int rc;
envp = getenv("HOME");
if (envp != NULL && envp[0] != '\0') {
return c_strdup(envp);
}
/* Still nothing found, read the password file */
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
if (rc != 0) {
return c_strdup(pwd.pw_dir);
}
return NULL;
}
char *csync_get_local_username(void) {
struct passwd pwd;
struct passwd *pwdbuf;
char buf[NSS_BUFLEN_PASSWD];
char *name;
int rc;
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
if (rc != 0) {
return NULL;
}
name = c_strdup(pwd.pw_name);
if (name == NULL) {
return NULL;
}
return name;
}
#endif /* ************* WIN32 ************ */
#ifdef HAVE_FNMATCH
#include <fnmatch.h>
int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags) {
return fnmatch(__pattern, __name, __flags);
}
#else /* HAVE_FNMATCH */
#include <shlwapi.h>
int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags) {
(void) __flags;
/* FIXME check if we rather should use the PathMatchSpecW variant here? */
if(PathMatchSpec(__name, __pattern))
return 0;
else
return 1;
}
#endif /* HAVE_FNMATCH */
CSYNC_STATUS csync_errno_to_status(int error, CSYNC_STATUS default_status)
{
CSYNC_STATUS status = CSYNC_STATUS_OK;
switch (error) {
case 0:
status = CSYNC_STATUS_OK;
break;
/* The custom errnos first. */
case ERRNO_GENERAL_ERROR:
status = CSYNC_STATUS_UNSUCCESSFUL;
break;
case ERRNO_LOOKUP_ERROR: /* In Neon: Server or proxy hostname lookup failed */
status = CSYNC_STATUS_LOOKUP_ERROR;
break;
case ERRNO_USER_UNKNOWN_ON_SERVER: /* Neon: User authentication on server failed. */
status = CSYNC_STATUS_SERVER_AUTH_ERROR;
break;
case ERRNO_PROXY_AUTH:
status = CSYNC_STATUS_PROXY_AUTH_ERROR; /* Neon: User authentication on proxy failed */
break;
case ERRNO_CONNECT:
status = CSYNC_STATUS_CONNECT_ERROR; /* Network: Connection error */
break;
case ERRNO_TIMEOUT:
status = CSYNC_STATUS_TIMEOUT; /* Network: Timeout error */
break;
case ERRNO_QUOTA_EXCEEDED:
status = CSYNC_STATUS_QUOTA_EXCEEDED; /* Quota exceeded */
break;
case ERRNO_SERVICE_UNAVAILABLE:
status = CSYNC_STATUS_SERVICE_UNAVAILABLE; /* Service temporarily down */
break;
case EFBIG:
status = CSYNC_STATUS_FILE_SIZE_ERROR; /* File larger than 2MB */
break;
case ERRNO_PRECONDITION:
case ERRNO_RETRY:
case ERRNO_REDIRECT:
case ERRNO_WRONG_CONTENT:
status = CSYNC_STATUS_HTTP_ERROR;
break;
case ERRNO_TIMEDELTA:
status = CSYNC_STATUS_TIMESKEW;
break;
case EPERM: /* Operation not permitted */
case EACCES: /* Permission denied */
status = CSYNC_STATUS_PERMISSION_DENIED;
break;
case ENOENT: /* No such file or directory */
status = CSYNC_STATUS_NOT_FOUND;
break;
case EAGAIN: /* Try again */
status = CSYNC_STATUS_TIMEOUT;
break;
case EEXIST: /* File exists */
status = CSYNC_STATUS_FILE_EXISTS;
break;
case EINVAL:
status = CSYNC_STATUS_PARAM_ERROR;
break;
case ENOSPC:
status = CSYNC_STATUS_OUT_OF_SPACE;
break;
/* All the remaining basic errnos: */
case EIO: /* I/O error */
case ESRCH: /* No such process */
case EINTR: /* Interrupted system call */
case ENXIO: /* No such device or address */
case E2BIG: /* Argument list too long */
case ENOEXEC: /* Exec format error */
case EBADF: /* Bad file number */
case ECHILD: /* No child processes */
case ENOMEM: /* Out of memory */
case EFAULT: /* Bad address */
#ifndef _WIN32
case ENOTBLK: /* Block device required */
#endif
case EBUSY: /* Device or resource busy */
case EXDEV: /* Cross-device link */
case ENODEV: /* No such device */
case ENOTDIR: /* Not a directory */
case EISDIR: /* Is a directory */
case ENFILE: /* File table overflow */
case EMFILE: /* Too many open files */
case ENOTTY: /* Not a typewriter */
#ifndef _WIN32
case ETXTBSY: /* Text file busy */
#endif
case ESPIPE: /* Illegal seek */
case EROFS: /* Read-only file system */
case EMLINK: /* Too many links */
case EPIPE: /* Broken pipe */
case ERRNO_ERROR_STRING:
default:
status = default_status;
}
return status;
}
/* Remove possible quotes, and also the -gzip at the end
* Remove "-gzip" at the end (cf. https://github.com/owncloud/mirall/issues/1195)
* The caller must take ownership of the resulting string.
*/
char *csync_normalize_etag(const char *etag)
{
int len = 0;
char *buf = NULL;
if (!etag)
return NULL;
len = strlen(etag);
/* strip "XXXX-gzip" */
if(len >= 7 && etag[0] == '"' && c_streq(etag + len - 6, "-gzip\"")) {
etag++;
len -= 7;
}
/* strip leading -gzip */
if(len >= 5 && c_streq(etag + len - 5, "-gzip")) {
len -= 5;
}
/* strip normal quotes */
if (etag[0] == '"' && etag[len-1] == '"') {
etag++;
len -= 2;
}
buf = c_malloc( len+1 );
strncpy( buf, etag, len );
buf[len] = '\0';
return buf;
}

69
csync/src/csync_misc.h Normal file
View File

@ -0,0 +1,69 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
#ifndef _CSYNC_MISC_H
#define _CSYNC_MISC_H
#include <config.h>
#include <csync.h>
#ifdef HAVE_FNMATCH
#include <fnmatch.h>
#else
/* Steal this define to make csync_exclude compile. Note that if fnmatch
* is not defined it's probably Win32 which uses a different implementation
* than fmmatch anyway, which does not care for flags.
**/
#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
#endif
char *csync_get_user_home_dir(void);
char *csync_get_local_username(void);
int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags);
/**
* @brief csync_errno_to_status - errno to csync status code
*
* This function tries to convert the value of the current set errno
* to a csync status code.
*
* @return the corresponding csync error code.
*/
CSYNC_STATUS csync_errno_to_status(int error, CSYNC_STATUS default_status);
struct csync_hbf_info_s {
int start_id;
int transfer_id;
};
typedef struct csync_hbf_info_s csync_hbf_info_t;
typedef struct {
int64_t file_count;
int64_t current_file_no;
int64_t byte_sum;
int64_t byte_current;
} csync_overall_progress_t;
char *csync_normalize_etag(const char *);
#endif /* _CSYNC_MISC_H */

1214
csync/src/csync_owncloud.c Normal file

File diff suppressed because it is too large Load Diff

181
csync/src/csync_owncloud.h Normal file
View File

@ -0,0 +1,181 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2011 by Andreas Schneider <asn@cryptomilk.org>
* Copyright (c) 2012 by Klaas Freitag <freitag@owncloud.com>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
#ifndef CSYNC_OWNCLOUD_H
#define CSYNC_OWNCLOUD_H
#include <errno.h>
#include <stdio.h>
#include <time.h>
#include <limits.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "config.h"
#ifdef NEON_WITH_LFS /* Switch on LFS in libneon. Never remove the NE_LFS! */
#define NE_LFS
#endif
#include <neon/ne_basic.h>
#include <neon/ne_socket.h>
#include <neon/ne_session.h>
#include <neon/ne_request.h>
#include <neon/ne_props.h>
#include <neon/ne_auth.h>
#include <neon/ne_dates.h>
#include <neon/ne_compress.h>
#include <neon/ne_redirect.h>
#include "c_rbtree.h"
#include "c_lib.h"
#include "csync.h"
#include "csync_misc.h"
#include "csync_macros.h"
#include "c_private.h"
#include "httpbf.h"
#include "vio/csync_vio_module.h"
#include "vio/csync_vio_file_stat.h"
#include "vio/csync_vio.h"
#include "csync_log.h"
#define DEBUG_WEBDAV(...) csync_log( 9, "oc_module", __VA_ARGS__);
enum resource_type {
resr_normal = 0,
resr_collection,
resr_reference,
resr_error
};
/* Struct to store data for each resource found during an opendir operation.
* It represents a single file entry.
*/
typedef struct resource {
char *uri; /* The complete uri */
char *name; /* The filename only */
enum resource_type type;
int64_t size;
time_t modtime;
char* md5;
char file_id[FILE_ID_BUF_SIZE+1];
struct resource *next;
} resource;
/* Struct to hold the context of a WebDAV PropFind operation to fetch
* a directory listing from the server.
*/
struct listdir_context {
struct resource *list; /* The list of result resources */
struct resource *currResource; /* A pointer to the current resource */
char *target; /* Request-URI of the PROPFIND */
unsigned int result_count; /* number of elements stored in list */
int ref; /* reference count, only destroy when it reaches 0 */
};
/* Our cache, key is a char* */
extern c_rbtree_t *propfind_recursive_cache;
/* Values are propfind_recursive_element: */
struct propfind_recursive_element {
struct resource *self;
struct resource *children;
struct propfind_recursive_element *parent;
};
typedef struct propfind_recursive_element propfind_recursive_element_t;
void clear_propfind_recursive_cache(void);
struct listdir_context *get_listdir_context_from_recursive_cache(const char *curi);
void fill_recursive_propfind_cache(const char *uri, const char *curi);
struct listdir_context *get_listdir_context_from_cache(const char *curi);
void fetch_resource_list_recursive(const char *uri, const char *curi);
typedef int (*csync_owncloud_redirect_callback_t)(CSYNC* ctx, const char* uri);
/* Struct with the WebDAV session */
struct dav_session_s {
ne_session *ctx;
char *user;
char *pwd;
char *proxy_type;
char *proxy_host;
int proxy_port;
char *proxy_user;
char *proxy_pwd;
char *session_key;
char *error_string;
int read_timeout;
CSYNC *csync_ctx;
csync_hbf_info_t *chunk_info;
bool no_recursive_propfind;
int64_t hbf_block_size;
int64_t hbf_threshold;
/* If 0, it is disabled. If >0, in Byte/seconds. If < 0, in % of the available bandwidth*/
int bandwidth_limit_upload;
int bandwidth_limit_download;
csync_overall_progress_t *overall_progress_data;
csync_owncloud_redirect_callback_t redir_callback;
};
extern struct dav_session_s dav_session;
/* The list of properties that is fetched in PropFind on a collection */
static const ne_propname ls_props[] = {
{ "DAV:", "getlastmodified" },
{ "DAV:", "getcontentlength" },
{ "DAV:", "resourcetype" },
{ "DAV:", "getetag"},
{ "http://owncloud.org/ns", "id"},
{ NULL, NULL }
};
void set_errno_from_http_errcode( int err );
void set_error_message( const char *msg );
void set_errno_from_neon_errcode( int neon_code );
int http_result_code_from_session(void);
void set_errno_from_session(void);
time_t oc_httpdate_parse( const char *date );
char *_cleanPath( const char* uri );
int _stat_perms( int type );
csync_vio_file_stat_t *resourceToFileStat( struct resource *res );
void oc_notify_progress(const char *file, enum csync_notify_type_e kind, int64_t current_size, int64_t full_size);
#endif /* CSYNC_OWNCLOUD_H */

View File

@ -0,0 +1,339 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2011 by Andreas Schneider <asn@cryptomilk.org>
* Copyright (c) 2012 by Klaas Freitag <freitag@owncloud.com>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
#include "csync_owncloud.h"
c_rbtree_t *propfind_recursive_cache = NULL;
int propfind_recursive_cache_depth = 0;
int propfind_recursive_cache_file_count = 0;
int propfind_recursive_cache_folder_count = 0;
static struct resource* resource_dup(struct resource* o) {
struct resource *r = c_malloc (sizeof( struct resource ));
ZERO_STRUCTP(r);
r->uri = c_strdup(o->uri);
r->name = c_strdup(o->name);
r->type = o->type;
r->size = o->size;
r->modtime = o->modtime;
if( o->md5 ) {
r->md5 = c_strdup(o->md5);
}
r->next = o->next;
csync_vio_set_file_id(r->file_id, o->file_id);
return r;
}
static void resource_free(struct resource* o) {
struct resource* old = NULL;
while (o)
{
old = o;
o = o->next;
SAFE_FREE(old->uri);
SAFE_FREE(old->name);
SAFE_FREE(old->md5);
SAFE_FREE(old);
}
}
static void _tree_destructor(void *data) {
propfind_recursive_element_t *element = data;
resource_free(element->self);
resource_free(element->children);
SAFE_FREE(element);
}
void clear_propfind_recursive_cache(void)
{
if (propfind_recursive_cache) {
DEBUG_WEBDAV("clear_propfind_recursive_cache Invalidating..");
c_rbtree_destroy(propfind_recursive_cache, _tree_destructor);
propfind_recursive_cache = NULL;
}
}
struct listdir_context *get_listdir_context_from_recursive_cache(const char *curi)
{
propfind_recursive_element_t *element = NULL;
struct listdir_context *fetchCtx = NULL;
struct resource *iterator, *r;
if (!propfind_recursive_cache) {
DEBUG_WEBDAV("get_listdir_context_from_recursive_cache No cache");
return NULL;
}
element = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache, curi));
if (!element) {
DEBUG_WEBDAV("get_listdir_context_from_recursive_cache No element %s in cache found", curi);
return NULL;
}
/* Out of the element, create a listdir_context.. if we could be sure that it is immutable, we could ref instead.. need to investigate */
fetchCtx = c_malloc( sizeof( struct listdir_context ));
ZERO_STRUCTP(fetchCtx);
fetchCtx->list = NULL;
fetchCtx->target = c_strdup(curi);
fetchCtx->currResource = NULL;
fetchCtx->ref = 1;
iterator = element->children;
r = NULL;
while (iterator) {
r = resource_dup(iterator);
r->next = fetchCtx->list;
fetchCtx->list = r;
iterator = iterator->next;
fetchCtx->result_count++;
/* DEBUG_WEBDAV("get_listdir_context_from_cache Returning cache for %s element %s", fetchCtx->target, fetchCtx->list->uri); */
}
r = resource_dup(element->self);
r->next = fetchCtx->list;
fetchCtx->result_count++;
fetchCtx->list = r;
fetchCtx->currResource = fetchCtx->list;
DEBUG_WEBDAV("get_listdir_context_from_cache Returning cache for %s (%d elements)", fetchCtx->target, fetchCtx->result_count);
return fetchCtx;
}
static int _key_cmp(const void *key, const void *b) {
const char *elementAUri = (char*)key;
const propfind_recursive_element_t *elementB = b;
return ne_path_compare(elementAUri, elementB->self->uri);
}
static int _data_cmp(const void *a, const void *b) {
const propfind_recursive_element_t *elementA = a;
const propfind_recursive_element_t *elementB = b;
return ne_path_compare(elementA->self->uri, elementB->self->uri);
}
static void propfind_results_recursive(void *userdata,
const ne_uri *uri,
const ne_prop_result_set *set)
{
struct resource *newres = 0;
const char *clength, *modtime, *file_id = NULL;
const char *resourcetype = NULL;
const char *md5sum = NULL;
const ne_status *status = NULL;
char *path = ne_path_unescape( uri->path );
char *parentPath;
char *propfindRootUri = (char*) userdata;
propfind_recursive_element_t *element = NULL;
propfind_recursive_element_t *pElement = NULL;
int depth = 0;
(void) status;
(void) propfindRootUri;
if (!propfind_recursive_cache) {
c_rbtree_create(&propfind_recursive_cache, _key_cmp, _data_cmp);
}
/* Fill the resource structure with the data about the file */
newres = c_malloc(sizeof(struct resource));
ZERO_STRUCTP(newres);
newres->uri = path; /* no need to strdup because ne_path_unescape already allocates */
newres->name = c_basename( path );
modtime = ne_propset_value( set, &ls_props[0] );
clength = ne_propset_value( set, &ls_props[1] );
resourcetype = ne_propset_value( set, &ls_props[2] );
md5sum = ne_propset_value( set, &ls_props[3] );
file_id = ne_propset_value( set, &ls_props[4] );
newres->type = resr_normal;
if( resourcetype && strncmp( resourcetype, "<DAV:collection>", 16 ) == 0) {
newres->type = resr_collection;
propfind_recursive_cache_folder_count++;
} else {
/* DEBUG_WEBDAV("propfind_results_recursive %s [%d]", newres->uri, newres->type); */
propfind_recursive_cache_file_count++;
}
if (modtime) {
newres->modtime = oc_httpdate_parse(modtime);
}
/* DEBUG_WEBDAV("Parsing Modtime: %s -> %llu", modtime, (unsigned long long) newres->modtime ); */
newres->size = 0;
if (clength) {
newres->size = atoll(clength);
/* DEBUG_WEBDAV("Parsed File size for %s from %s: %lld", newres->name, clength, (long long)newres->size ); */
}
if( md5sum ) {
newres->md5 = csync_normalize_etag(md5sum);
}
csync_vio_set_file_id(newres->file_id, file_id);
/*
DEBUG_WEBDAV("propfind_results_recursive %s [%s] %s", newres->uri, newres->type == resr_collection ? "collection" : "file", newres->md5);
*/
/* Create new item in rb tree */
if (newres->type == resr_collection) {
DEBUG_WEBDAV("propfind_results_recursive %s is a folder", newres->uri);
/* Check if in rb tree */
element = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache,uri->path));
/* If not, create a new item and insert it */
if (!element) {
element = c_malloc(sizeof(propfind_recursive_element_t));
element->self = resource_dup(newres);
element->children = NULL;
element->parent = NULL;
c_rbtree_insert(propfind_recursive_cache, element);
/* DEBUG_WEBDAV("results_recursive Added collection %s", newres->uri); */
}
}
/* Check for parent in tree. If exists: Insert it into the children elements there */
parentPath = ne_path_parent(uri->path);
if (parentPath) {
propfind_recursive_element_t *parentElement = NULL;
parentElement = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache,parentPath));
free(parentPath);
if (parentElement) {
newres->next = parentElement->children;
parentElement->children = newres;
/* If the current result is a collection we also need to set its parent */
if (element)
element->parent = parentElement;
pElement = element;
while (pElement) {
depth++;
pElement = pElement->parent;
}
if (depth > propfind_recursive_cache_depth) {
DEBUG_WEBDAV("propfind_results_recursive %s new maximum tree depth %d", newres->uri, depth);
propfind_recursive_cache_depth = depth;
}
/* DEBUG_WEBDAV("results_recursive Added child %s to collection %s", newres->uri, element->self->uri); */
} else {
/* DEBUG_WEBDAV("results_recursive No parent %s found for child %s", parentPath, newres->uri); */
resource_free(newres);
newres = NULL;
}
}
}
void fetch_resource_list_recursive(const char *uri, const char *curi)
{
int ret = 0;
ne_propfind_handler *hdl = NULL;
ne_request *request = NULL;
const char *content_type = NULL;
const ne_status *req_status = NULL;
int depth = NE_DEPTH_INFINITE;
DEBUG_WEBDAV("fetch_resource_list_recursive Starting recursive propfind %s %s", uri, curi);
/* do a propfind request and parse the results in the results function, set as callback */
hdl = ne_propfind_create(dav_session.ctx, curi, depth);
if(hdl) {
ret = ne_propfind_named(hdl, ls_props, propfind_results_recursive, (void*)curi);
request = ne_propfind_get_request( hdl );
req_status = ne_get_status( request );
}
if( ret == NE_OK ) {
/* Check the request status. */
if( req_status && req_status->klass != 2 ) {
set_errno_from_http_errcode(req_status->code);
DEBUG_WEBDAV("ERROR: Request failed: status %d (%s)", req_status->code,
req_status->reason_phrase);
ret = NE_CONNECT;
set_error_message(req_status->reason_phrase);
oc_notify_progress(uri, CSYNC_NOTIFY_ERROR, req_status->code, (intptr_t)(req_status->reason_phrase));
}
DEBUG_WEBDAV("Recursive propfind result code %d.", req_status ? req_status->code : 0);
} else {
if( ret == NE_ERROR && req_status->code == 404) {
errno = ENOENT;
} else {
set_errno_from_neon_errcode(ret);
}
}
if( ret == NE_OK ) {
/* Check the content type. If the server has a problem, ie. database is gone or such,
* the content type is not xml but a html error message. Stop on processing if it's
* not XML.
* FIXME: Generate user error message from the reply content.
*/
content_type = ne_get_response_header( request, "Content-Type" );
if( !(content_type && c_streq(content_type, "application/xml; charset=utf-8") ) ) {
DEBUG_WEBDAV("ERROR: Content type of propfind request not XML: %s.",
content_type ? content_type: "<empty>");
errno = ERRNO_WRONG_CONTENT;
set_error_message("Server error: PROPFIND reply is not XML formatted!");
ret = NE_CONNECT;
}
}
if( ret != NE_OK ) {
const char *err = NULL;
err = ne_get_error( dav_session.ctx );
DEBUG_WEBDAV("WRN: propfind named failed with %d, request error: %s", ret, err ? err : "<nil>");
}
if( hdl )
ne_propfind_destroy(hdl);
if( ret != NE_OK ) {
return;
}
return;
}
/* Called by owncloud_opendir()->fetch_resource_list() to fill the cache */
extern struct listdir_context *propfind_cache;
void fill_recursive_propfind_cache(const char *uri, const char *curi) {
fetch_resource_list_recursive(uri, curi);
if (propfind_recursive_cache_depth <= 2) {
DEBUG_WEBDAV("fill_recursive_propfind_cache %s Server maybe did not give us an 'infinity' depth result", curi);
/* transform the cache to the normal cache in propfind_cache */
propfind_cache = get_listdir_context_from_recursive_cache(curi);
/* clear the cache, it is bogus since the server returned only results for Depth 1 */
clear_propfind_recursive_cache();
} else {
DEBUG_WEBDAV("fill_recursive_propfind_cache %s We received %d elements deep for 'infinity' depth (%d folders, %d files)",
curi,
propfind_recursive_cache_depth,
propfind_recursive_cache_folder_count,
propfind_recursive_cache_file_count);
}
}

View File

@ -0,0 +1,366 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2011 by Andreas Schneider <asn@cryptomilk.org>
* Copyright (c) 2012 by Klaas Freitag <freitag@owncloud.com>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
#include "csync_owncloud.h"
#include "csync_misc.h"
void set_error_message( const char *msg )
{
SAFE_FREE(dav_session.error_string);
if( msg )
dav_session.error_string = c_strdup(msg);
}
void set_errno_from_http_errcode( int err ) {
int new_errno = 0;
switch(err) {
case 200: /* OK */
case 201: /* Created */
case 202: /* Accepted */
case 203: /* Non-Authoritative Information */
case 204: /* No Content */
case 205: /* Reset Content */
case 207: /* Multi-Status */
case 304: /* Not Modified */
new_errno = 0;
break;
case 401: /* Unauthorized */
case 402: /* Payment Required */
case 407: /* Proxy Authentication Required */
case 405:
new_errno = EPERM;
break;
case 301: /* Moved Permanently */
case 303: /* See Other */
case 404: /* Not Found */
case 410: /* Gone */
new_errno = ENOENT;
break;
case 408: /* Request Timeout */
case 504: /* Gateway Timeout */
new_errno = EAGAIN;
break;
case 423: /* Locked */
new_errno = EACCES;
break;
case 400: /* Bad Request */
case 403: /* Forbidden */
case 409: /* Conflict */
case 411: /* Length Required */
case 412: /* Precondition Failed */
case 414: /* Request-URI Too Long */
case 415: /* Unsupported Media Type */
case 424: /* Failed Dependency */
case 501: /* Not Implemented */
new_errno = EINVAL;
break;
case 507: /* Insufficient Storage */
new_errno = ENOSPC;
break;
case 206: /* Partial Content */
case 300: /* Multiple Choices */
case 302: /* Found */
case 305: /* Use Proxy */
case 306: /* (Unused) */
case 307: /* Temporary Redirect */
case 406: /* Not Acceptable */
case 416: /* Requested Range Not Satisfiable */
case 417: /* Expectation Failed */
case 422: /* Unprocessable Entity */
case 500: /* Internal Server Error */
case 502: /* Bad Gateway */
case 505: /* HTTP Version Not Supported */
new_errno = EIO;
break;
case 503: /* Service Unavailable */
new_errno = ERRNO_SERVICE_UNAVAILABLE;
break;
case 413: /* Request Entity too Large */
new_errno = EFBIG;
break;
default:
new_errno = EIO;
}
errno = new_errno;
}
int http_result_code_from_session() {
const char *p = ne_get_error( dav_session.ctx );
char *q;
int err;
set_error_message(p); /* remember the error message */
err = strtol(p, &q, 10);
if (p == q) {
err = ERRNO_ERROR_STRING;
}
return err;
}
void set_errno_from_session() {
int err = http_result_code_from_session();
if( err == EIO || err == ERRNO_ERROR_STRING) {
errno = err;
} else {
set_errno_from_http_errcode(err);
}
}
void set_errno_from_neon_errcode( int neon_code ) {
if( neon_code != NE_OK ) {
DEBUG_WEBDAV("Neon error code was %d", neon_code);
}
switch(neon_code) {
case NE_OK: /* Success, but still the possiblity of problems */
case NE_ERROR: /* Generic error; use ne_get_error(session) for message */
set_errno_from_session(); /* Something wrong with http communication */
break;
case NE_LOOKUP: /* Server or proxy hostname lookup failed */
errno = ERRNO_LOOKUP_ERROR;
break;
case NE_AUTH: /* User authentication failed on server */
errno = ERRNO_USER_UNKNOWN_ON_SERVER;
break;
case NE_PROXYAUTH: /* User authentication failed on proxy */
errno = ERRNO_PROXY_AUTH;
break;
case NE_CONNECT: /* Could not connect to server */
errno = ERRNO_CONNECT;
break;
case NE_TIMEOUT: /* Connection timed out */
errno = ERRNO_TIMEOUT;
break;
case NE_FAILED: /* The precondition failed */
errno = ERRNO_PRECONDITION;
break;
case NE_RETRY: /* Retry request (ne_end_request ONLY) */
errno = ERRNO_RETRY;
break;
case NE_REDIRECT: /* See ne_redirect.h */
errno = ERRNO_REDIRECT;
break;
default:
errno = ERRNO_GENERAL_ERROR;
}
}
/* cleanPath to return an escaped path of an uri */
char *_cleanPath( const char* uri ) {
int rc = 0;
char *path = NULL;
char *re = NULL;
rc = c_parse_uri( uri, NULL, NULL, NULL, NULL, NULL, &path );
if( rc < 0 ) {
DEBUG_WEBDAV("Unable to cleanPath %s", uri ? uri: "<zero>" );
re = NULL;
} else {
if(path) {
re = ne_path_escape( path );
}
}
SAFE_FREE( path );
return re;
}
#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;
}
/*
* helper: convert a resource struct to file_stat struct.
*/
csync_vio_file_stat_t *resourceToFileStat( struct resource *res )
{
csync_vio_file_stat_t *lfs = NULL;
if( ! res ) {
return NULL;
}
lfs = c_malloc(sizeof(csync_vio_file_stat_t));
if (lfs == NULL) {
errno = ENOMEM;
return NULL;
}
lfs->name = c_strdup( res->name );
lfs->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
if( res->type == resr_normal ) {
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
lfs->type = CSYNC_VIO_FILE_TYPE_REGULAR;
} else if( res->type == resr_collection ) {
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
lfs->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
} else {
DEBUG_WEBDAV("ERROR: Unknown resource type %d", res->type);
}
lfs->mtime = res->modtime;
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
lfs->size = res->size;
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
if( res->md5 ) {
lfs->etag = c_strdup(res->md5);
}
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG;
csync_vio_file_stat_set_file_id(lfs, res->file_id);
return lfs;
}
/* WebDAV does not deliver permissions. Set a default here. */
int _stat_perms( int type ) {
int ret = 0;
if( type == CSYNC_VIO_FILE_TYPE_DIRECTORY ) {
/* DEBUG_WEBDAV("Setting mode in stat (dir)"); */
/* directory permissions */
ret = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR /* directory, rwx for user */
| S_IRGRP | S_IXGRP /* rx for group */
| S_IROTH | S_IXOTH; /* rx for others */
} else {
/* regualar file permissions */
/* DEBUG_WEBDAV("Setting mode in stat (file)"); */
ret = S_IFREG | S_IRUSR | S_IWUSR /* regular file, user read & write */
| S_IRGRP /* group read perm */
| S_IROTH; /* others read perm */
}
return ret;
}
void oc_notify_progress(const char *file, enum csync_notify_type_e kind, int64_t current_size, int64_t full_size)
{
csync_progress_callback progress_cb = csync_get_progress_callback(dav_session.csync_ctx);
csync_overall_progress_t overall_progress;
ZERO_STRUCT(overall_progress);
if( dav_session.overall_progress_data) {
overall_progress = *dav_session.overall_progress_data;
}
if (progress_cb) {
CSYNC_PROGRESS progress;
progress.kind = kind;
progress.path = file;
progress.curr_bytes = current_size;
progress.file_size = full_size;
progress.overall_transmission_size = overall_progress.byte_sum;
progress.current_overall_bytes = overall_progress.byte_current+current_size;
progress.overall_file_count = overall_progress.file_count;
progress.current_file_no = overall_progress.current_file_no;
progress_cb(&progress, csync_get_userdata(dav_session.csync_ctx));
}
}

229
csync/src/csync_private.h Normal file
View File

@ -0,0 +1,229 @@
/*
* cynapses libc functions
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
/**
* @file csync_private.h
*
* @brief Private interface of csync
*
* @defgroup csyncInternalAPI csync internal API
*
* @{
*/
#ifndef _CSYNC_PRIVATE_H
#define _CSYNC_PRIVATE_H
#include <stdint.h>
#include <stdbool.h>
#include <sqlite3.h>
#include "config.h"
#include "c_lib.h"
#include "c_private.h"
#include "csync.h"
#include "csync_misc.h"
#include "vio/csync_vio_file_stat.h"
#ifdef WITH_ICONV
#include <iconv.h>
#endif
#ifdef HAVE_ICONV_H
#include <iconv.h>
#endif
#ifdef HAVE_SYS_ICONV_H
#include <sys/iconv.h>
#endif
#include "vio/csync_vio_method.h"
#include "csync_macros.h"
/**
* How deep to scan directories.
*/
#define MAX_DEPTH 50
/**
* Maximum time difference between two replicas in seconds
*/
#define MAX_TIME_DIFFERENCE 10
/**
* Maximum size of a buffer for transfer
*/
#ifndef MAX_XFER_BUF_SIZE
#define MAX_XFER_BUF_SIZE (16 * 1024)
#endif
#define CSYNC_STATUS_INIT 1 << 0
#define CSYNC_STATUS_UPDATE 1 << 1
#define CSYNC_STATUS_RECONCILE 1 << 2
#define CSYNC_STATUS_PROPAGATE 1 << 3
#define CSYNC_STATUS_DONE (CSYNC_STATUS_INIT | \
CSYNC_STATUS_UPDATE | \
CSYNC_STATUS_RECONCILE | \
CSYNC_STATUS_PROPAGATE)
enum csync_replica_e {
LOCAL_REPLICA,
REMOTE_REPLICA
};
typedef struct csync_file_stat_s csync_file_stat_t;
/**
* @brief csync public structure
*/
struct csync_s {
struct {
csync_auth_callback auth_function;
csync_progress_callback progress_cb;
void *userdata;
} callbacks;
c_strlist_t *excludes;
struct {
char *file;
sqlite3 *db;
int exists;
int disabled;
} statedb;
struct {
char *uri;
c_rbtree_t *tree;
c_list_t *list;
enum csync_replica_e type;
c_list_t *ignored_cleanup;
} local;
struct {
char *uri;
c_rbtree_t *tree;
c_list_t *list;
enum csync_replica_e type;
int read_from_db;
c_list_t *ignored_cleanup;
} remote;
struct {
csync_vio_method_t *method;
csync_vio_method_finish_fn finish_fn;
csync_vio_capabilities_t capabilities;
} module;
struct {
int max_depth;
int max_time_difference;
int sync_symbolic_links;
int unix_extensions;
char *config_dir;
bool with_conflict_copys;
bool local_only_mode;
int timeout;
#if defined(HAVE_ICONV) && defined(WITH_ICONV)
iconv_t iconv_cd;
#endif
} options;
struct {
uid_t uid;
uid_t euid;
} pwd;
csync_overall_progress_t overall_progress;
struct csync_progressinfo_s *progress_info;
/* replica we are currently walking */
enum csync_replica_e current;
/* replica we want to work on */
enum csync_replica_e replica;
/* Used in the update phase so changes in the sub directories can be notified to
parent directories */
csync_file_stat_t *current_fs;
/* csync error code */
enum csync_status_codes_e status_code;
char *error_string;
int status;
volatile int abort;
void *rename_info;
};
#ifdef _MSC_VER
#pragma pack(1)
#endif
struct csync_file_stat_s {
uint64_t phash; /* u64 */
time_t modtime; /* u64 */
int64_t size; /* u64 */
size_t pathlen; /* u64 */
uint64_t inode; /* u64 */
uid_t uid; /* u32 */
gid_t gid; /* u32 */
mode_t mode; /* u32 */
int nlink; /* u32 */
int type; /* u32 */
int child_modified;/*bool*/
int should_update_etag; /*bool */
char *destpath; /* for renames */
const char *etag;
char file_id[FILE_ID_BUF_SIZE+1]; /* the ownCloud file id is fixed width of 21 byte. */
CSYNC_STATUS error_status;
enum csync_instructions_e instruction; /* u32 */
char path[1]; /* u8 */
}
#if !defined(__SUNPRO_C) && !defined(_MSC_VER)
__attribute__ ((packed))
#endif
#ifdef _MSC_VER
#pragma pack()
#endif
;
void csync_file_stat_free(csync_file_stat_t *st);
/*
* context for the treewalk function
*/
struct _csync_treewalk_context_s
{
csync_treewalk_visit_func *user_visitor;
int instruction_filter;
void *userdata;
};
typedef struct _csync_treewalk_context_s _csync_treewalk_context;
/**
* }@
*/
#endif /* _CSYNC_PRIVATE_H */
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */

299
csync/src/csync_reconcile.c Normal file
View File

@ -0,0 +1,299 @@
/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
*
* 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.
*
* This library 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
* Lesser General Public License for more details.
*
* 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
*/
#include "config.h"
#include "csync_private.h"
#include "csync_reconcile.h"
#include "csync_util.h"
#include "csync_statedb.h"
#include "csync_rename.h"
#include "c_jhash.h"
#define CSYNC_LOG_CATEGORY_NAME "csync.reconciler"
#include "csync_log.h"
#include "inttypes.h"
#define ACCEPTED_TIME_DIFF 5
#define ONE_HOUR 3600
/*
* We merge replicas at the file level. The merged replica contains the
* superset of files that are on the local machine and server copies of
* the replica. In the case where the same file is in both the local
* and server copy, the file that was modified most recently is used.
* This means that new files are not deleted, and updated versions of
* existing files are not overwritten.
*
* When a file is updated, the merge algorithm compares the destination
* file with the the source file. If the destination file is newer
* (timestamp is newer), it is not overwritten. If both files, on the
* source and the destination, have been changed, the newer file wins.
*/
static int _csync_merge_algorithm_visitor(void *obj, void *data) {
csync_file_stat_t *cur = NULL;
csync_file_stat_t *other = NULL;
csync_file_stat_t *tmp = NULL;
uint64_t h = 0;
int len = 0;
CSYNC *ctx = NULL;
c_rbtree_t *tree = NULL;
c_rbnode_t *node = NULL;
cur = (csync_file_stat_t *) obj;
ctx = (CSYNC *) data;
/* we need the opposite tree! */
switch (ctx->current) {
case LOCAL_REPLICA:
tree = ctx->remote.tree;
break;
case REMOTE_REPLICA:
tree = ctx->local.tree;
break;
default:
break;
}
node = c_rbtree_find(tree, &cur->phash);
if (!node) {
/* Check the renamed path as well. */
char *renamed_path = csync_rename_adjust_path(ctx, cur->path);
if (!c_streq(renamed_path, cur->path)) {
len = strlen( renamed_path );
h = c_jhash64((uint8_t *) renamed_path, len, 0);
node = c_rbtree_find(tree, &h);
}
SAFE_FREE(renamed_path);
}
/* file only found on current replica */
if (node == NULL) {
switch(cur->instruction) {
/* file has been modified */
case CSYNC_INSTRUCTION_EVAL:
cur->instruction = CSYNC_INSTRUCTION_NEW;
break;
/* file has been removed on the opposite replica */
case CSYNC_INSTRUCTION_NONE:
cur->instruction = CSYNC_INSTRUCTION_REMOVE;
break;
case CSYNC_INSTRUCTION_EVAL_RENAME:
if(ctx->current == LOCAL_REPLICA ) {
/* use the old name to find the "other" node */
tmp = csync_statedb_get_stat_by_inode(ctx->statedb.db, cur->inode);
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Finding opposite temp through inode %" PRIu64 ": %s",
cur->inode, tmp ? "true":"false");
} else if( ctx->current == REMOTE_REPLICA ) {
tmp = csync_statedb_get_stat_by_file_id(ctx->statedb.db, cur->file_id);
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Finding opposite temp through file ID %s: %s",
cur->file_id, tmp ? "true":"false");
} else {
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Unknown replica...");
}
if( tmp ) {
if( tmp->path ) {
/* Find the temporar file in the other tree. */
len = strlen( tmp->path );
h = c_jhash64((uint8_t *) tmp->path, len, 0);
node = c_rbtree_find(tree, &h);
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "PHash of temporary opposite (%s): %" PRIu64 " %s",
tmp->path , h, node ? "found": "not found" );
if (!node) {
/* the renamed file could not be found in the opposite tree. That is because it
* is not longer existing there, maybe because it was renamed or deleted.
* The journal is cleaned up later after propagation.
*/
}
}
if(node) {
other = (csync_file_stat_t*)node->data;
}
if(!other) {
cur->instruction = CSYNC_INSTRUCTION_NEW;
} else if (other->instruction == CSYNC_INSTRUCTION_NONE
|| cur->type == CSYNC_FTW_TYPE_DIR) {
other->instruction = CSYNC_INSTRUCTION_RENAME;
other->destpath = c_strdup( cur->path );
if( !c_streq(cur->file_id, "") ) {
csync_vio_set_file_id( other->file_id, cur->file_id );
}
cur->instruction = CSYNC_INSTRUCTION_NONE;
} else if (other->instruction == CSYNC_INSTRUCTION_REMOVE) {
other->instruction = CSYNC_INSTRUCTION_RENAME;
other->destpath = c_strdup( cur->path );
if( !c_streq(cur->file_id, "") ) {
csync_vio_set_file_id( other->file_id, cur->file_id );
}
cur->instruction = CSYNC_INSTRUCTION_NONE;
} else if (other->instruction == CSYNC_INSTRUCTION_NEW) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "OOOO=> NEW detected in other tree!");
cur->instruction = CSYNC_INSTRUCTION_CONFLICT;
} else {
cur->instruction = CSYNC_INSTRUCTION_NONE;
other->instruction = CSYNC_INSTRUCTION_SYNC;
}
SAFE_FREE(tmp->etag);
SAFE_FREE(tmp);
}
break;
default:
break;
}
} else {
bool is_equal_files = false;
/*
* file found on the other replica
*/
other = (csync_file_stat_t *) node->data;
switch (cur->instruction) {
case CSYNC_INSTRUCTION_EVAL_RENAME:
/* If the file already exist on the other side, we have a conflict.
Abort the rename and consider it is a new file. */
cur->instruction = CSYNC_INSTRUCTION_NEW;
/* fall trough */
/* file on current replica is changed or new */
case CSYNC_INSTRUCTION_EVAL:
case CSYNC_INSTRUCTION_NEW:
switch (other->instruction) {
/* file on other replica is changed or new */
case CSYNC_INSTRUCTION_NEW:
case CSYNC_INSTRUCTION_EVAL:
if (other->type == CSYNC_VIO_FILE_TYPE_DIRECTORY &&
cur->type == CSYNC_VIO_FILE_TYPE_DIRECTORY) {
is_equal_files = (other->modtime == cur->modtime);
} else {
is_equal_files = ((other->size == cur->size) && (other->modtime == cur->modtime));
}
if (is_equal_files) {
/* The files are considered equal. */
cur->instruction = CSYNC_INSTRUCTION_UPDATED; /* update the DB */
other->instruction = CSYNC_INSTRUCTION_NONE;
if( !cur->etag && other->etag ) cur->etag = c_strdup(other->etag);
} else if(ctx->current == REMOTE_REPLICA) {
if(ctx->options.with_conflict_copys) {
cur->instruction = CSYNC_INSTRUCTION_CONFLICT;
other->instruction = CSYNC_INSTRUCTION_NONE;
} else {
cur->instruction = CSYNC_INSTRUCTION_SYNC;
other->instruction = CSYNC_INSTRUCTION_NONE;
}
} else {
if(ctx->options.with_conflict_copys) {
cur->instruction = CSYNC_INSTRUCTION_NONE;
other->instruction = CSYNC_INSTRUCTION_CONFLICT;
} else {
cur->instruction = CSYNC_INSTRUCTION_NONE;
other->instruction = CSYNC_INSTRUCTION_SYNC;
}
}
break;
/* file on the other replica has not been modified */
case CSYNC_INSTRUCTION_NONE:
cur->instruction = CSYNC_INSTRUCTION_SYNC;
break;
case CSYNC_INSTRUCTION_IGNORE:
cur->instruction = CSYNC_INSTRUCTION_IGNORE;
break;
default:
break;
}
default:
break;
}
}
//hide instruction NONE messages when log level is set to debug,
//only show these messages on log level trace
if(cur->instruction ==CSYNC_INSTRUCTION_NONE)
{
if(cur->type == CSYNC_FTW_TYPE_DIR)
{
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,
"%-20s dir: %s",
csync_instruction_str(cur->instruction),
cur->path);
}
else
{
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,
"%-20s file: %s",
csync_instruction_str(cur->instruction),
cur->path);
}
}
else
{
if(cur->type == CSYNC_FTW_TYPE_DIR)
{
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
"%-20s dir: %s",
csync_instruction_str(cur->instruction),
cur->path);
}
else
{
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
"%-20s file: %s",
csync_instruction_str(cur->instruction),
cur->path);
}
}
return 0;
}
int csync_reconcile_updates(CSYNC *ctx) {
int rc;
c_rbtree_t *tree = NULL;
switch (ctx->current) {
case LOCAL_REPLICA:
tree = ctx->local.tree;
break;
case REMOTE_REPLICA:
tree = ctx->remote.tree;
break;
default:
break;
}
rc = c_rbtree_walk(tree, (void *) ctx, _csync_merge_algorithm_visitor);
if( rc < 0 ) {
ctx->status_code = CSYNC_STATUS_RECONCILE_ERROR;
}
return rc;
}
/* vim: set ts=8 sw=2 et cindent: */

Some files were not shown because too many files have changed in this diff Show More