2012-03-02 16:35:02 +04:00
|
|
|
/*
|
|
|
|
* libcsync -- a library to sync a directory with another
|
|
|
|
*
|
2012-03-02 16:47:45 +04:00
|
|
|
* Copyright (c) 2012 by Andreas Schneider <asn@cryptomilk.org>
|
2012-03-02 16:35:02 +04:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2012-03-02 19:47:34 +04:00
|
|
|
#include "config.h"
|
|
|
|
|
2012-03-02 16:35:02 +04:00
|
|
|
#ifndef _GNU_SOURCE
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <limits.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
2013-03-05 13:45:33 +04:00
|
|
|
#include <stdio.h>
|
2012-03-02 16:35:02 +04:00
|
|
|
#include <sys/types.h>
|
2013-03-08 21:50:10 +04:00
|
|
|
#include <errno.h>
|
2012-03-02 16:35:02 +04:00
|
|
|
|
|
|
|
#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"
|
2013-03-08 21:50:10 +04:00
|
|
|
#include "csync_macros.h"
|
2012-03-02 16:35:02 +04:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
char *csync_get_user_home_dir(void) {
|
|
|
|
char tmp[MAX_PATH] = {0};
|
|
|
|
char *szPath = NULL;
|
|
|
|
|
|
|
|
if (SHGetSpecialFolderPathA(NULL, tmp, CSIDL_PROFILE, TRUE)) {
|
2012-03-02 17:45:31 +04:00
|
|
|
szPath = c_malloc(strlen(tmp) + 1);
|
2012-03-02 16:35:02 +04:00
|
|
|
if (szPath == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
strcpy(szPath, tmp);
|
|
|
|
return szPath;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *csync_get_local_username(void) {
|
|
|
|
DWORD size = 0;
|
|
|
|
char *user;
|
|
|
|
|
|
|
|
/* get the size */
|
|
|
|
GetUserName(NULL, &size);
|
|
|
|
|
2012-03-02 17:45:31 +04:00
|
|
|
user = (char *) c_malloc(size);
|
2012-03-02 16:35:02 +04:00
|
|
|
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) {
|
2013-03-05 13:24:34 +04:00
|
|
|
char home[PATH_MAX] = {0};
|
|
|
|
const char *envp;
|
2012-03-02 16:35:02 +04:00
|
|
|
struct passwd pwd;
|
|
|
|
struct passwd *pwdbuf;
|
|
|
|
char buf[NSS_BUFLEN_PASSWD];
|
|
|
|
int rc;
|
|
|
|
|
2013-03-05 13:24:34 +04:00
|
|
|
envp = getenv("HOME");
|
|
|
|
if (envp != NULL) {
|
|
|
|
snprintf(home, sizeof(home), "%s", envp);
|
|
|
|
if (home[0] != '\0') {
|
|
|
|
return c_strdup(home);
|
|
|
|
}
|
2012-03-18 18:29:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Still nothing found, read the password file */
|
2012-03-02 16:35:02 +04:00
|
|
|
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
|
|
|
|
if (rc != 0) {
|
2013-03-05 13:24:34 +04:00
|
|
|
return c_strdup(pwd.pw_dir);
|
2012-03-02 16:35:02 +04:00
|
|
|
}
|
|
|
|
|
2013-03-05 13:24:34 +04:00
|
|
|
return NULL;
|
2012-03-02 16:35:02 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
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 ************ */
|
2012-03-02 17:54:53 +04:00
|
|
|
|
|
|
|
#ifdef HAVE_FNMATCH
|
|
|
|
#include <fnmatch.h>
|
|
|
|
|
|
|
|
int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags) {
|
|
|
|
return fnmatch(__pattern, __name, __flags);
|
|
|
|
}
|
|
|
|
|
2012-03-02 19:47:34 +04:00
|
|
|
#else /* HAVE_FNMATCH */
|
2012-03-02 17:54:53 +04:00
|
|
|
|
|
|
|
#include <shlwapi.h>
|
|
|
|
int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags) {
|
|
|
|
if(PathMatchSpec(__name, __pattern))
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-03-02 19:47:34 +04:00
|
|
|
#endif /* HAVE_FNMATCH */
|
2013-03-08 21:50:10 +04:00
|
|
|
|
2013-04-06 20:45:06 +04:00
|
|
|
CSYNC_STATUS csync_errno_to_status(int error, CSYNC_STATUS default_status)
|
2013-03-08 21:50:10 +04:00
|
|
|
{
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Defined csync error codes:
|
|
|
|
CSYNC_ERR_NONE = 0,
|
|
|
|
CSYNC_ERR_LOG,
|
|
|
|
CSYNC_ERR_LOCK,
|
|
|
|
CSYNC_ERR_STATEDB_LOAD,
|
2013-04-20 13:07:20 +04:00
|
|
|
CSYNC_ERR_STATEDB_WRITE,
|
2013-03-08 21:50:10 +04:00
|
|
|
CSYNC_ERR_MODULE,
|
|
|
|
CSYNC_ERR_TIMESKEW,
|
|
|
|
CSYNC_ERR_FILESYSTEM,
|
|
|
|
CSYNC_ERR_TREE,
|
|
|
|
CSYNC_ERR_MEM,
|
|
|
|
CSYNC_ERR_PARAM,
|
|
|
|
CSYNC_ERR_UPDATE,
|
|
|
|
CSYNC_ERR_RECONCILE,
|
|
|
|
CSYNC_ERR_PROPAGATE,
|
|
|
|
CSYNC_ERR_ACCESS_FAILED,
|
|
|
|
CSYNC_ERR_REMOTE_CREATE,
|
|
|
|
CSYNC_ERR_REMOTE_STAT,
|
|
|
|
CSYNC_ERR_LOCAL_CREATE,
|
|
|
|
CSYNC_ERR_LOCAL_STAT,
|
|
|
|
CSYNC_ERR_PROXY,
|
|
|
|
CSYNC_ERR_LOOKUP,
|
|
|
|
CSYNC_ERR_AUTH_SERVER,
|
|
|
|
CSYNC_ERR_AUTH_PROXY,
|
|
|
|
CSYNC_ERR_CONNECT,
|
|
|
|
CSYNC_ERR_TIMEOUT,
|
|
|
|
CSYNC_ERR_HTTP,
|
|
|
|
CSYNC_ERR_PERM,
|
|
|
|
CSYNC_ERR_NOT_FOUND,
|
|
|
|
CSYNC_ERR_EXISTS,
|
|
|
|
CSYNC_ERR_NOSPC,
|
|
|
|
CSYNC_ERR_QUOTA,
|
|
|
|
CSYNC_ERR_SERVICE_UNAVAILABLE,
|
|
|
|
CSYNC_ERR_FILE_TOO_BIG,
|
|
|
|
|
|
|
|
CSYNC_ERR_UNSPEC
|
|
|
|
*/
|
|
|
|
|
2013-04-06 20:45:06 +04:00
|
|
|
CSYNC_STATUS status = CSYNC_STATUS_OK;
|
2013-03-08 21:50:10 +04:00
|
|
|
|
2013-04-06 20:45:06 +04:00
|
|
|
switch (error) {
|
2013-03-08 21:50:10 +04:00
|
|
|
case 0:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_OK;
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
/* The custom errnos first. */
|
|
|
|
case ERRNO_GENERAL_ERROR:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_UNSUCCESSFUL;
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
case ERRNO_LOOKUP_ERROR: /* In Neon: Server or proxy hostname lookup failed */
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_LOOKUP_ERROR;
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
case ERRNO_USER_UNKNOWN_ON_SERVER: /* Neon: User authentication on server failed. */
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_SERVER_AUTH_ERROR;
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
case ERRNO_PROXY_AUTH:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_PROXY_AUTH_ERROR; /* Neon: User authentication on proxy failed */
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
case ERRNO_CONNECT:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_CONNECT_ERROR; /* Network: Connection error */
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
case ERRNO_TIMEOUT:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_TIMEOUT; /* Network: Timeout error */
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
case ERRNO_QUOTA_EXCEEDED:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_QUOTA_EXCEEDED; /* Quota exceeded */
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
case ERRNO_SERVICE_UNAVAILABLE:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_SERVICE_UNAVAILABLE; /* Service temporarily down */
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
case EFBIG:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_FILE_SIZE_ERROR; /* File larger than 2MB */
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
case ERRNO_PRECONDITION:
|
|
|
|
case ERRNO_RETRY:
|
|
|
|
case ERRNO_REDIRECT:
|
|
|
|
case ERRNO_WRONG_CONTENT:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_HTTP_ERROR;
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ERRNO_TIMEDELTA:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_TIMESKEW;
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
case EPERM: /* Operation not permitted */
|
|
|
|
case EACCES: /* Permission denied */
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_PERMISSION_DENIED;
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
case ENOENT: /* No such file or directory */
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_NOT_FOUND;
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
case EAGAIN: /* Try again */
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_TIMEOUT;
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
case EEXIST: /* File exists */
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_FILE_EXISTS;
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
case EINVAL:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_PARAM_ERROR;
|
2013-03-08 21:50:10 +04:00
|
|
|
break;
|
|
|
|
case ENOSPC:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_OUT_OF_SPACE;
|
2013-03-08 21:50:10 +04:00
|
|
|
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:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = default_status;
|
2013-03-08 21:50:10 +04:00
|
|
|
}
|
|
|
|
|
2013-04-06 20:45:06 +04:00
|
|
|
return status;
|
2013-03-08 21:50:10 +04:00
|
|
|
}
|