mirror of
https://github.com/nextcloud/desktop.git
synced 2025-10-26 11:17:43 +00:00
iconv support
This allows for files on mac to automatically be converted to UNC
This commit is contained in:
parent
82acccf333
commit
49d2fd685b
@ -39,6 +39,7 @@ macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source buil
|
||||
include(MacroAddPlugin)
|
||||
include(MacroCopyFile)
|
||||
|
||||
find_package(iconv)
|
||||
find_package(CMocka)
|
||||
if (CMOCKA_FOUND AND UNIT_TESTING)
|
||||
include(AddCMockaTest)
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
option(WITH_ICONV "Build csync with iconv support" ON)
|
||||
option(UNIT_TESTING "Build with unit tests" OFF)
|
||||
option(MEM_NULL_TESTS "Enable NULL memory testing" OFF)
|
||||
|
||||
@ -53,8 +53,11 @@ at LOCAL with the ones at REMOTE.\n\
|
||||
--disable-statedb Disable the usage and creation of a statedb.\n\
|
||||
--dry-run This runs only update detection and reconcilation.\n\
|
||||
\n\
|
||||
--exclude-file=<file> Add an additional exclude file\n\
|
||||
--test-statedb Test creation of the statedb. Runs update\n\
|
||||
--exclude-file=<file> Add an additional exclude file\n"
|
||||
#ifdef WITH_ICONV
|
||||
" --iconv=codec Request charset conversion of local filenames\n"
|
||||
#endif
|
||||
" --test-statedb Test creation of the statedb. Runs update\n\
|
||||
detection.\n\
|
||||
--test-update Test the update detection\n\
|
||||
-?, --help Give this help list\n\
|
||||
@ -68,6 +71,9 @@ static const struct option long_options[] =
|
||||
{"exclude-file", required_argument, 0, 0 },
|
||||
{"debug-level", required_argument, 0, 'd' },
|
||||
{"disable-statedb", no_argument, 0, 0 },
|
||||
#ifdef WITH_ICONV
|
||||
{"iconv", required_argument, 0, 0 },
|
||||
#endif
|
||||
{"dry-run", no_argument, 0, 0 },
|
||||
{"test-statedb", no_argument, 0, 0 },
|
||||
{"conflict-copies", no_argument, 0, 'c' },
|
||||
@ -82,6 +88,7 @@ struct argument_s {
|
||||
char *args[2]; /* SOURCE and DESTINATION */
|
||||
char *exclude_file;
|
||||
int debug_level;
|
||||
char *iconv;
|
||||
int disable_statedb;
|
||||
int create_statedb;
|
||||
int update;
|
||||
@ -149,7 +156,9 @@ static int parse_args(struct argument_s *csync_args, int argc, char **argv)
|
||||
csync_args->reconcile = 1;
|
||||
csync_args->propagate = 0;
|
||||
/* printf("Argument: dry-run\n" ); */
|
||||
|
||||
} else if(c_streq(opt->name, "iconv")) {
|
||||
csync_args->iconv = c_strdup(optarg);
|
||||
/* printf("Argument: iconv\n" ); */
|
||||
} else if(c_streq(opt->name, "test-statedb")) {
|
||||
csync_args->create_statedb = 1;
|
||||
csync_args->update = 1;
|
||||
@ -158,7 +167,6 @@ static int parse_args(struct argument_s *csync_args, int argc, char **argv)
|
||||
/* printf("Argument: test-statedb\n"); */
|
||||
} else {
|
||||
fprintf(stderr, "Argument: No idea what!\n");
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -181,6 +189,7 @@ int main(int argc, char **argv) {
|
||||
/* Default values. */
|
||||
arguments.exclude_file = NULL;
|
||||
arguments.debug_level = 4;
|
||||
arguments.iconv = NULL;
|
||||
arguments.disable_statedb = 0;
|
||||
arguments.create_statedb = 0;
|
||||
arguments.update = 1;
|
||||
@ -227,6 +236,12 @@ int main(int argc, char **argv) {
|
||||
csync_disable_statedb(csync);
|
||||
}
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
if (arguments.iconv) {
|
||||
csync_set_iconv_codec(arguments.iconv);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(arguments.with_conflict_copys)
|
||||
{
|
||||
csync_enable_conflictcopys(csync);
|
||||
|
||||
80
cmake/Modules/FindIconv.cmake
Normal file
80
cmake/Modules/FindIconv.cmake
Normal file
@ -0,0 +1,80 @@
|
||||
# - Try to find Iconv
|
||||
# Once done this will define
|
||||
#
|
||||
# ICONV_FOUND - system has Iconv
|
||||
# ICONV_INCLUDE_DIR - the Iconv include directory
|
||||
# ICONV_LIBRARIES - Link these to use Iconv
|
||||
# ICONV_SECOND_ARGUMENT_IS_CONST - the second argument for iconv() is const
|
||||
#
|
||||
include(CheckCCompilerFlag)
|
||||
include(CheckCSourceCompiles)
|
||||
|
||||
IF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
|
||||
# Already in cache, be silent
|
||||
SET(ICONV_FIND_QUIETLY TRUE)
|
||||
ENDIF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
|
||||
|
||||
IF(APPLE)
|
||||
FIND_PATH(ICONV_INCLUDE_DIR iconv.h
|
||||
PATHS
|
||||
/opt/local/include/
|
||||
NO_CMAKE_SYSTEM_PATH
|
||||
)
|
||||
|
||||
FIND_LIBRARY(ICONV_LIBRARIES NAMES iconv libiconv c
|
||||
PATHS
|
||||
/opt/local/lib/
|
||||
NO_CMAKE_SYSTEM_PATH
|
||||
)
|
||||
ENDIF(APPLE)
|
||||
|
||||
FIND_PATH(ICONV_INCLUDE_DIR iconv.h PATHS /opt/local/include /sw/include)
|
||||
|
||||
string(REGEX REPLACE "(.*)/include/?" "\\1" ICONV_INCLUDE_BASE_DIR "${ICONV_INCLUDE_DIR}")
|
||||
|
||||
FIND_LIBRARY(ICONV_LIBRARIES NAMES iconv libiconv c HINTS "${ICONV_INCLUDE_BASE_DIR}/lib" PATHS /opt/local/lib)
|
||||
|
||||
IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
|
||||
SET(ICONV_FOUND TRUE)
|
||||
ENDIF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARIES})
|
||||
IF(ICONV_FOUND)
|
||||
check_c_compiler_flag("-Werror" ICONV_HAVE_WERROR)
|
||||
set (CMAKE_C_FLAGS_BACKUP "${CMAKE_C_FLAGS}")
|
||||
if(ICONV_HAVE_WERROR)
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
|
||||
endif(ICONV_HAVE_WERROR)
|
||||
check_c_source_compiles("
|
||||
#include <iconv.h>
|
||||
int main(){
|
||||
iconv_t conv = 0;
|
||||
const char* in = 0;
|
||||
size_t ilen = 0;
|
||||
char* out = 0;
|
||||
size_t olen = 0;
|
||||
iconv(conv, &in, &ilen, &out, &olen);
|
||||
return 0;
|
||||
}
|
||||
" ICONV_SECOND_ARGUMENT_IS_CONST )
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS_BACKUP}")
|
||||
ENDIF(ICONV_FOUND)
|
||||
set(CMAKE_REQUIRED_INCLUDES)
|
||||
set(CMAKE_REQUIRED_LIBRARIES)
|
||||
|
||||
IF(ICONV_FOUND)
|
||||
IF(NOT ICONV_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found Iconv: ${ICONV_LIBRARIES}")
|
||||
ENDIF(NOT ICONV_FIND_QUIETLY)
|
||||
ELSE(ICONV_FOUND)
|
||||
IF(Iconv_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find Iconv")
|
||||
ENDIF(Iconv_FIND_REQUIRED)
|
||||
ENDIF(ICONV_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
ICONV_INCLUDE_DIR
|
||||
ICONV_LIBRARIES
|
||||
ICONV_SECOND_ARGUMENT_IS_CONST
|
||||
)
|
||||
@ -11,6 +11,7 @@
|
||||
#cmakedefine HAVE_CLOCK_GETTIME
|
||||
|
||||
#cmakedefine WITH_LOG4C 1
|
||||
#cmakedefine WITH_ICONV 1
|
||||
|
||||
#cmakedefine HAVE_ARGP_H 1
|
||||
|
||||
|
||||
@ -41,6 +41,11 @@ set(CSYNC_LINK_LIBRARIES
|
||||
${SQLITE3_LIBRARIES}
|
||||
)
|
||||
|
||||
if(ICONV_FOUND AND WITH_ICONV)
|
||||
list(APPEND CSYNC_PRIVATE_INCLUDE_DIRS ${ICONV_INCLUDE_DIRS})
|
||||
list(APPEND CSYNC_LINK_LIBRARIES ${ICONV_LIBRARIES})
|
||||
endif()
|
||||
|
||||
set(csync_SRCS
|
||||
csync.c
|
||||
csync_config.c
|
||||
|
||||
23
src/csync.c
23
src/csync.c
@ -32,6 +32,10 @@
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "csync_private.h"
|
||||
#include "csync_config.h"
|
||||
@ -42,6 +46,8 @@
|
||||
#include "csync_util.h"
|
||||
#include "csync_misc.h"
|
||||
#include "c_jhash.h"
|
||||
#include "std/c_private.h"
|
||||
|
||||
|
||||
#include "csync_update.h"
|
||||
#include "csync_reconcile.h"
|
||||
@ -717,6 +723,10 @@ int csync_destroy(CSYNC *ctx) {
|
||||
SAFE_FREE(ctx->options.config_dir);
|
||||
SAFE_FREE(ctx->statedb.file);
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
c_close_iconv();
|
||||
#endif
|
||||
|
||||
SAFE_FREE(ctx);
|
||||
|
||||
SAFE_FREE(lock);
|
||||
@ -1002,6 +1012,19 @@ int csync_set_module_property(CSYNC* ctx, const char* key, void* value)
|
||||
return csync_vio_set_property(ctx, key, value);
|
||||
}
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
int csync_set_iconv_codec(const char *from)
|
||||
{
|
||||
c_close_iconv();
|
||||
|
||||
if (from != NULL) {
|
||||
c_setup_iconv(from);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int csync_set_progress_callback(CSYNC* ctx, csync_progress_callback cb)
|
||||
{
|
||||
if (ctx == NULL || cb == NULL) {
|
||||
|
||||
15
src/csync.h
15
src/csync.h
@ -35,6 +35,7 @@
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <config.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -462,6 +463,18 @@ int csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int fi
|
||||
*/
|
||||
int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
|
||||
|
||||
|
||||
#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 Get the error code from the last operation.
|
||||
*
|
||||
@ -469,7 +482,6 @@ int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int f
|
||||
*/
|
||||
CSYNC_ERROR_CODE csync_get_error(CSYNC *ctx);
|
||||
|
||||
|
||||
/* dirty stuff from here on - EXPERIMENTAL */
|
||||
/* read the information if a file is known to csync ie. if it has an entry in the database */
|
||||
bool csync_file_known( char *statedb_file, const char* url );
|
||||
@ -487,7 +499,6 @@ bool csync_file_known( char *statedb_file, const char* url );
|
||||
*/
|
||||
int csync_set_module_property(CSYNC *ctx, const char *key, void *value);
|
||||
|
||||
|
||||
enum csync_notify_type_e { CSYNC_NOTIFY_START_DOWNLOAD, CSYNC_NOTIFY_START_UPLOAD, CSYNC_NOTIFY_PROGRESS,
|
||||
CSYNC_NOTIFY_FINISHED, CSYNC_NOTFY_ERROR };
|
||||
|
||||
|
||||
@ -40,6 +40,10 @@
|
||||
#include "c_private.h"
|
||||
#include "csync.h"
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
|
||||
#include "vio/csync_vio_method.h"
|
||||
#include "csync_macros.h"
|
||||
|
||||
@ -128,6 +132,9 @@ struct csync_s {
|
||||
bool local_only_mode;
|
||||
bool remote_push_atomar;
|
||||
int log_verbosity;
|
||||
#ifdef WITH_ICONV
|
||||
iconv_t iconv_cd;
|
||||
#endif
|
||||
} options;
|
||||
|
||||
struct {
|
||||
|
||||
@ -55,7 +55,7 @@ int csync_get_statedb_exists(CSYNC *ctx) {
|
||||
/* Set the hide attribute in win32. That makes it invisible in normal explorers */
|
||||
static void _csync_win32_hide_file( const char *file ) {
|
||||
#ifdef _WIN32
|
||||
const _TCHAR *fileName;
|
||||
_TCHAR *fileName;
|
||||
if( !file ) return;
|
||||
|
||||
fileName = c_multibyte( file );
|
||||
|
||||
@ -15,8 +15,8 @@
|
||||
int c_mkdirs(const char *path, mode_t mode) {
|
||||
int tmp;
|
||||
csync_stat_t sb;
|
||||
const _TCHAR *wpath = c_multibyte(path);
|
||||
const _TCHAR *swpath = NULL;
|
||||
_TCHAR *wpath = c_multibyte(path);
|
||||
_TCHAR *swpath = NULL;
|
||||
|
||||
if (path == NULL) {
|
||||
errno = EINVAL;
|
||||
@ -72,8 +72,8 @@ int c_rmdirs(const char *path) {
|
||||
struct _tdirent *dp;
|
||||
csync_stat_t sb;
|
||||
char *fname = NULL;
|
||||
const _TCHAR *wfname = NULL;
|
||||
const _TCHAR *wpath = c_multibyte(path);
|
||||
_TCHAR *wfname = NULL;
|
||||
_TCHAR *wpath = c_multibyte(path);
|
||||
|
||||
if ((d = _topendir(wpath)) != NULL) {
|
||||
while( _tstat(wpath, &sb) == 0) {
|
||||
@ -145,7 +145,7 @@ int c_rmdirs(const char *path) {
|
||||
|
||||
int c_isdir(const char *path) {
|
||||
csync_stat_t sb;
|
||||
const _TCHAR *wpath = c_multibyte(path);
|
||||
_TCHAR *wpath = c_multibyte(path);
|
||||
|
||||
if (_tstat (wpath, &sb) == 0 && S_ISDIR(sb.st_mode)) {
|
||||
return 1;
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
/* check if path is a file */
|
||||
int c_isfile(const char *path) {
|
||||
csync_stat_t sb;
|
||||
const _TCHAR *wpath = c_multibyte(path);
|
||||
_TCHAR *wpath = c_multibyte(path);
|
||||
int re = _tstat(wpath, &sb);
|
||||
c_free_multibyte(wpath);
|
||||
|
||||
@ -69,8 +69,8 @@ int c_copy(const char* src, const char *dst, mode_t mode) {
|
||||
|
||||
#ifdef _WIN32
|
||||
if(src && dst) {
|
||||
const _TCHAR *wsrc = c_multibyte(src);
|
||||
const _TCHAR *wdst = c_multibyte(dst);
|
||||
_TCHAR *wsrc = c_multibyte(src);
|
||||
_TCHAR *wdst = c_multibyte(dst);
|
||||
if (CopyFileW(wsrc, wdst, FALSE)) {
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
@ -31,7 +31,6 @@
|
||||
#include <winbase.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define EDQUOT 0
|
||||
#define ENODATA 0
|
||||
@ -114,6 +113,13 @@ typedef char _TCHAR;
|
||||
#define _trewinddir rewinddir
|
||||
#endif
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
/** @internal */
|
||||
int c_setup_iconv(const char* to);
|
||||
/** @internal */
|
||||
int c_close_iconv(void);
|
||||
#endif
|
||||
|
||||
#endif //_C_PRIVATE_H
|
||||
|
||||
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
* vim: ts=2 sw=2 et cindent
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
@ -39,6 +40,78 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
#include <iconv.h>
|
||||
|
||||
typedef struct {
|
||||
iconv_t to;
|
||||
iconv_t from;
|
||||
} iconv_conversions;
|
||||
|
||||
static iconv_conversions _iconvs = { NULL, NULL };
|
||||
|
||||
int c_setup_iconv(const char* to) {
|
||||
_iconvs.to = iconv_open(to, "UTF-8");
|
||||
_iconvs.from = iconv_open("UTF-8", to);
|
||||
|
||||
if (_iconvs.to == (iconv_t)-1 || _iconvs.from == (iconv_t)-1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int c_close_iconv() {
|
||||
int ret_to = iconv_close(_iconvs.to);
|
||||
int ret_from = iconv_close(_iconvs.from);
|
||||
|
||||
if (ret_to == -1 || ret_from == -1)
|
||||
return -1;
|
||||
|
||||
_iconvs.to = (iconv_t) 0;
|
||||
_iconvs.from = (iconv_t) 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum iconv_direction { iconv_from_native, iconv_to_native };
|
||||
|
||||
static char *c_iconv(const char* str, enum iconv_direction dir)
|
||||
{
|
||||
char *in = (char*)str;
|
||||
size_t size;
|
||||
size_t outsize;
|
||||
char *out;
|
||||
char *out_in;
|
||||
size_t ret;
|
||||
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
|
||||
if(_iconvs.from == NULL && _iconvs.to == NULL) {
|
||||
#ifdef __APPLE__
|
||||
c_setup_iconv("UTF-8-MAC");
|
||||
#else
|
||||
return c_strdup(str);
|
||||
#endif
|
||||
}
|
||||
|
||||
size = strlen(in);
|
||||
outsize = size*2;
|
||||
out = c_malloc(outsize);
|
||||
out_in = out;
|
||||
|
||||
if (dir == iconv_to_native) {
|
||||
ret = iconv(_iconvs.to, &in, &size, &out, &outsize);
|
||||
} else {
|
||||
ret = iconv(_iconvs.from, &in, &size, &out, &outsize);
|
||||
}
|
||||
|
||||
assert(ret != (size_t)-1);
|
||||
|
||||
return out_in;
|
||||
}
|
||||
#endif
|
||||
|
||||
int c_streq(const char *a, const char *b) {
|
||||
register const char *s1 = a;
|
||||
register const char *s2 = b;
|
||||
@ -197,9 +270,9 @@ char *c_lowercase(const char* str) {
|
||||
}
|
||||
|
||||
/* Convert a wide multibyte String to UTF8 */
|
||||
const char* c_utf8(const _TCHAR *wstr)
|
||||
char* c_utf8(const _TCHAR *wstr)
|
||||
{
|
||||
const char *dst = NULL;
|
||||
char *dst = NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
char *mdst = NULL;
|
||||
@ -214,48 +287,37 @@ const char* c_utf8(const _TCHAR *wstr)
|
||||
WideCharToMultiByte(CP_UTF8, 0, wstr, len, mdst, size_needed, NULL, NULL);
|
||||
dst = mdst;
|
||||
}
|
||||
#else
|
||||
#ifdef WITH_ICONV
|
||||
dst = c_iconv(wstr, iconv_from_native);
|
||||
#else
|
||||
dst = wstr;
|
||||
#endif
|
||||
#endif
|
||||
return dst;
|
||||
}
|
||||
|
||||
/* Convert a an UTF8 string to multibyte */
|
||||
const _TCHAR* c_multibyte(const char *str)
|
||||
_TCHAR* c_multibyte(const char *str)
|
||||
{
|
||||
_TCHAR *dst = NULL;
|
||||
#ifdef _WIN32
|
||||
_TCHAR *wstrTo = NULL;
|
||||
if(!str) return NULL;
|
||||
|
||||
size_t len = strlen( str );
|
||||
int size_needed = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
|
||||
if(size_needed > 0) {
|
||||
int size_char = (size_needed+1)*sizeof(_TCHAR);
|
||||
wstrTo = c_malloc(size_char);
|
||||
memset( (void*)wstrTo, 0, size_char);
|
||||
MultiByteToWideChar(CP_UTF8, 0, str, -1, wstrTo, size_needed);
|
||||
dst = c_malloc(size_char);
|
||||
memset( (void*)dst, 0, size_char);
|
||||
MultiByteToWideChar(CP_UTF8, 0, str, -1, dst, size_needed);
|
||||
}
|
||||
return wstrTo;
|
||||
#else
|
||||
return str;
|
||||
#ifdef WITH_ICONV
|
||||
dst = c_iconv(str, iconv_to_native);
|
||||
#else
|
||||
dst = str;
|
||||
#endif
|
||||
return dst;
|
||||
#endif
|
||||
}
|
||||
|
||||
void c_free_utf8(char* buf)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SAFE_FREE(buf);
|
||||
#else
|
||||
(void)buf;
|
||||
#endif
|
||||
}
|
||||
|
||||
void c_free_multibyte(const _TCHAR* buf)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SAFE_FREE(buf);
|
||||
#else
|
||||
(void)buf;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -34,6 +34,9 @@
|
||||
#define _C_STR_H
|
||||
|
||||
#include "c_private.h"
|
||||
#include "c_macro.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
struct c_strlist_s; typedef struct c_strlist_s c_strlist_t;
|
||||
|
||||
@ -146,7 +149,7 @@ char *c_lowercase(const char* str);
|
||||
*
|
||||
* @return The malloced converted string or NULL on error.
|
||||
*/
|
||||
const char* c_utf8(const _TCHAR *str);
|
||||
char* c_utf8(const _TCHAR *str);
|
||||
|
||||
/**
|
||||
* @brief Convert a utf8 encoded string to multibyte (Win32).
|
||||
@ -155,7 +158,16 @@ const char* c_utf8(const _TCHAR *str);
|
||||
*
|
||||
* @return The malloced converted multibyte string or NULL on error.
|
||||
*/
|
||||
const _TCHAR* c_multibyte(const char *wstr);
|
||||
_TCHAR* c_multibyte(const char *wstr);
|
||||
|
||||
#if defined(_WIN32) || defined(WITH_ICONV)
|
||||
/**
|
||||
* @brief Free buffer malloced by c_multibyte.
|
||||
*
|
||||
* @param buf The buffer to free.
|
||||
*/
|
||||
|
||||
#define c_free_multibyte(x) SAFE_FREE(x)
|
||||
|
||||
/**
|
||||
* @brief Free buffer malloced by c_utf8.
|
||||
@ -163,14 +175,12 @@ const _TCHAR* c_multibyte(const char *wstr);
|
||||
* @param buf The buffer to free.
|
||||
*
|
||||
*/
|
||||
void c_free_utf8(char* buf);
|
||||
#define c_free_utf8(x) SAFE_FREE(x)
|
||||
#else
|
||||
#define c_free_multibyte(x) (void)x
|
||||
#define c_free_utf8(x) (void)x
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Free buffer malloced by c_multibyte.
|
||||
*
|
||||
* @param buf The buffer to free.
|
||||
*/
|
||||
void c_free_multibyte(const _TCHAR* buf);
|
||||
|
||||
/**
|
||||
* }@
|
||||
|
||||
@ -69,7 +69,10 @@ double c_secdiff(struct timespec clock1, struct timespec clock0) {
|
||||
|
||||
#ifdef HAVE_UTIMES
|
||||
int c_utimes(const char *uri, const struct timeval *times) {
|
||||
return utimes(uri, times);
|
||||
_TCHAR *wuri = c_multibyte(uri);
|
||||
int ret = utimes(wuri, times);
|
||||
c_free_multibyte(wuri);
|
||||
return ret;
|
||||
}
|
||||
#else // HAVE_UTIMES
|
||||
|
||||
@ -93,7 +96,7 @@ int c_utimes(const char *uri, const struct timeval *times) {
|
||||
FILETIME LastAccessTime;
|
||||
FILETIME LastModificationTime;
|
||||
HANDLE hFile;
|
||||
const _TCHAR *wuri = c_multibyte( uri );
|
||||
_TCHAR *wuri = c_multibyte( uri );
|
||||
|
||||
if(times) {
|
||||
UnixTimevalToFileTime(times[0], &LastAccessTime);
|
||||
|
||||
@ -57,10 +57,10 @@ int csync_vio_init(CSYNC *ctx, const char *module, const char *args) {
|
||||
char *err = NULL;
|
||||
csync_vio_method_t *m = NULL;
|
||||
csync_vio_method_init_fn init_fn;
|
||||
const _TCHAR *mpath = NULL;
|
||||
_TCHAR *mpath = NULL;
|
||||
#ifdef _WIN32
|
||||
_TCHAR tbuf[MAX_PATH];
|
||||
const _TCHAR *pathBuf = NULL;
|
||||
_TCHAR *pathBuf = NULL;
|
||||
char *buf = NULL;
|
||||
char *last_bslash = NULL;
|
||||
#endif
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
csync_vio_method_handle_t *csync_vio_local_open(const char *durl, int flags, mode_t mode) {
|
||||
fhandle_t *handle = NULL;
|
||||
int fd = -1;
|
||||
const _TCHAR *url = c_multibyte(durl);
|
||||
_TCHAR *url = c_multibyte(durl);
|
||||
|
||||
if ((fd = _topen(url, flags, mode)) < 0) {
|
||||
return NULL;
|
||||
@ -69,7 +69,7 @@ csync_vio_method_handle_t *csync_vio_local_open(const char *durl, int flags, mod
|
||||
csync_vio_method_handle_t *csync_vio_local_creat(const char *durl, mode_t mode) {
|
||||
fhandle_t *handle = NULL;
|
||||
int fd = -1;
|
||||
const _TCHAR *url = c_multibyte(durl);
|
||||
_TCHAR *url = c_multibyte(durl);
|
||||
|
||||
if(( fd = _tcreat( url, mode)) < 0) {
|
||||
return NULL;
|
||||
@ -159,7 +159,7 @@ typedef struct dhandle_s {
|
||||
|
||||
csync_vio_method_handle_t *csync_vio_local_opendir(const char *name) {
|
||||
dhandle_t *handle = NULL;
|
||||
const _TCHAR *dirname = c_multibyte(name);
|
||||
_TCHAR *dirname = c_multibyte(name);
|
||||
handle = c_malloc(sizeof(dhandle_t));
|
||||
if (handle == NULL) {
|
||||
return NULL;
|
||||
@ -170,11 +170,7 @@ csync_vio_method_handle_t *csync_vio_local_opendir(const char *name) {
|
||||
SAFE_FREE(handle);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
handle->path = c_utf8(dirname);
|
||||
#else
|
||||
handle->path = c_strdup(dirname);
|
||||
#endif
|
||||
|
||||
return (csync_vio_method_handle_t *) handle;
|
||||
}
|
||||
@ -220,11 +216,7 @@ csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_method_handle_t *dhandl
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
file_stat->name = c_utf8(dirent->d_name);
|
||||
#else
|
||||
file_stat->name = c_strdup(dirent->d_name);
|
||||
#endif
|
||||
file_stat->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
|
||||
|
||||
#ifndef _WIN32
|
||||
@ -264,7 +256,7 @@ int csync_vio_local_mkdir(const char *uri, mode_t mode) {
|
||||
}
|
||||
|
||||
int csync_vio_local_rmdir(const char *uri) {
|
||||
const _TCHAR *dirname = c_multibyte(uri);
|
||||
_TCHAR *dirname = c_multibyte(uri);
|
||||
int re = -1;
|
||||
|
||||
re = _trmdir(dirname);
|
||||
@ -295,7 +287,7 @@ static time_t FileTimeToUnixTime(FILETIME *filetime, DWORD *remainder)
|
||||
|
||||
int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
csync_stat_t sb;
|
||||
const _TCHAR *wuri = c_multibyte( uri );
|
||||
_TCHAR *wuri = c_multibyte( uri );
|
||||
if( _tstat(wuri, &sb) < 0) {
|
||||
c_free_multibyte(wuri);
|
||||
return -1;
|
||||
@ -433,10 +425,10 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
}
|
||||
|
||||
int csync_vio_local_rename(const char *olduri, const char *newuri) {
|
||||
#ifdef _WIN32
|
||||
const _TCHAR *nuri = c_multibyte(newuri);
|
||||
const _TCHAR *ouri = c_multibyte(olduri);
|
||||
_TCHAR *nuri = c_multibyte(newuri);
|
||||
_TCHAR *ouri = c_multibyte(olduri);
|
||||
|
||||
#ifdef _WIN32
|
||||
if(ouri && nuri) {
|
||||
if (MoveFileExW(ouri, nuri, MOVEFILE_COPY_ALLOWED + MOVEFILE_REPLACE_EXISTING + MOVEFILE_WRITE_THROUGH )) {
|
||||
return 0;
|
||||
@ -445,24 +437,23 @@ int csync_vio_local_rename(const char *olduri, const char *newuri) {
|
||||
} else {
|
||||
errno = ENOENT;
|
||||
}
|
||||
#else
|
||||
return rename(ouri, nuri);
|
||||
#endif
|
||||
c_free_multibyte(nuri);
|
||||
c_free_multibyte(ouri);
|
||||
return -1;
|
||||
#else
|
||||
return rename(olduri, newuri);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int csync_vio_local_unlink(const char *uri) {
|
||||
const _TCHAR *nuri = c_multibyte(uri);
|
||||
_TCHAR *nuri = c_multibyte(uri);
|
||||
int re = _tunlink( nuri );
|
||||
c_free_multibyte(nuri);
|
||||
return re;
|
||||
}
|
||||
|
||||
int csync_vio_local_chmod(const char *uri, mode_t mode) {
|
||||
const _TCHAR *nuri = c_multibyte(uri);
|
||||
_TCHAR *nuri = c_multibyte(uri);
|
||||
int re = -1;
|
||||
|
||||
re = _tchmod(nuri, mode);
|
||||
|
||||
@ -158,10 +158,11 @@ static void teardown_toplevel_dir( void **state ) {
|
||||
|
||||
static void stat_local_file( csync_stat_t *sb, const char *file )
|
||||
{
|
||||
const _TCHAR *mpath = NULL;
|
||||
_TCHAR *mpath = NULL;
|
||||
mpath = c_multibyte(file);
|
||||
assert_int_not_equal(_tstat(mpath, sb), -1);
|
||||
c_free_multibyte(mpath);
|
||||
assert_null(mpath);
|
||||
}
|
||||
|
||||
#define BUFSIZE 4096
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
@ -173,6 +174,82 @@ static void check_c_uppercase_null(void **state)
|
||||
assert_null(str);
|
||||
}
|
||||
|
||||
static void check_iconv_setup(void **state)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
#ifdef __APPLE__
|
||||
rc = c_setup_iconv("UTF-8-MAC");
|
||||
assert_int_equal(rc, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void check_iconv_teardown(void **state)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
// this must never crash
|
||||
rc = c_close_iconv();
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void check_iconv_to_native_normalization(void **state)
|
||||
{
|
||||
const char *out = NULL;
|
||||
const char *in= "\x48\xc3\xa4"; // UTF8
|
||||
#ifdef __APPLE__
|
||||
const char *exp_out = "\x48\x61\xcc\x88"; // UTF-8-MAC
|
||||
#else
|
||||
const char *exp_out = "\x48\xc3\xa4"; // UTF8
|
||||
#endif
|
||||
|
||||
out = c_multibyte(in);
|
||||
assert_string_equal(out, exp_out);
|
||||
|
||||
c_free_multibyte(out);
|
||||
assert_null(out);
|
||||
|
||||
(void) state; /* unused */
|
||||
}
|
||||
|
||||
static void check_iconv_from_native_normalization(void **state)
|
||||
{
|
||||
const char *out = NULL;
|
||||
#ifdef __APPLE__
|
||||
const char* in = "\x48\x61\xcc\x88"; // UTF-8-MAC
|
||||
#else
|
||||
const char *in = "\x48\xc3\xa4"; // UTF-8
|
||||
#endif
|
||||
const char *exp_out = "\x48\xc3\xa4"; // UTF-8
|
||||
|
||||
out = c_utf8(in);
|
||||
assert_string_equal(out, exp_out);
|
||||
|
||||
c_free_utf8(out);
|
||||
assert_null(out);
|
||||
|
||||
(void) state; /* unused */
|
||||
}
|
||||
|
||||
static void check_iconv_ascii(void **state)
|
||||
{
|
||||
const char *out = NULL;
|
||||
const char* in = "abc/ABC\\123";
|
||||
const char *exp_out = "abc/ABC\\123";
|
||||
|
||||
out = c_utf8(in);
|
||||
assert_string_equal(out, exp_out);
|
||||
|
||||
c_free_utf8(out);
|
||||
assert_null(out);
|
||||
|
||||
(void) state; /* unused */
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
@ -189,6 +266,9 @@ int torture_run_tests(void)
|
||||
unit_test(check_c_uppercase),
|
||||
unit_test(check_c_uppercase_empty),
|
||||
unit_test(check_c_uppercase_null),
|
||||
unit_test_setup_teardown(check_iconv_ascii, check_iconv_setup, check_iconv_teardown),
|
||||
unit_test_setup_teardown(check_iconv_to_native_normalization, check_iconv_setup, check_iconv_teardown),
|
||||
unit_test_setup_teardown(check_iconv_from_native_normalization, check_iconv_setup, check_iconv_teardown),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user