2012-03-02 16:35:02 +04:00
|
|
|
/*
|
|
|
|
* libcsync -- a library to sync a directory with another
|
|
|
|
*
|
2013-07-23 19:31:55 +04:00
|
|
|
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
|
|
|
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>wie
|
2012-03-02 16:35:02 +04:00
|
|
|
*
|
2013-07-23 19:31:55 +04:00
|
|
|
* 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.
|
2012-03-02 16:35:02 +04:00
|
|
|
*
|
2013-07-23 19:31:55 +04:00
|
|
|
* This library is distributed in the hope that it will be useful,
|
2012-03-02 16:35:02 +04:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2013-07-23 19:31:55 +04:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
2012-03-02 16:35:02 +04:00
|
|
|
*
|
2013-07-23 19:31:55 +04:00
|
|
|
* 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
|
2012-03-02 16:35:02 +04:00
|
|
|
*/
|
|
|
|
|
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>
|
2012-12-17 20:22:24 +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"
|
2012-12-17 20:22:24 +04:00
|
|
|
#include "csync_macros.h"
|
2013-11-25 19:19:59 +04:00
|
|
|
#include "csync_log.h"
|
2012-03-02 16:35:02 +04:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
char *csync_get_user_home_dir(void) {
|
2012-06-13 19:30:50 +04:00
|
|
|
wchar_t tmp[MAX_PATH];
|
2013-03-19 19:23:05 +04:00
|
|
|
char *szPath = NULL;
|
2012-06-13 19:30:50 +04:00
|
|
|
|
|
|
|
if( SHGetFolderPathW( NULL,
|
|
|
|
CSIDL_PROFILE|CSIDL_FLAG_CREATE,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
tmp) == S_OK ) {
|
2013-09-10 14:59:29 +04:00
|
|
|
szPath = c_utf8_from_locale(tmp);
|
2012-03-02 16:35:02 +04:00
|
|
|
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) {
|
2013-07-31 15:12:10 +04:00
|
|
|
(void) __flags;
|
2013-09-18 18:15:08 +04:00
|
|
|
/* FIXME check if we rather should use the PathMatchSpecW variant here? */
|
2012-03-02 17:54:53 +04:00
|
|
|
if(PathMatchSpec(__name, __pattern))
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
}
|
2012-03-02 19:47:34 +04:00
|
|
|
#endif /* HAVE_FNMATCH */
|
2012-12-17 20:22:24 +04:00
|
|
|
|
2013-04-06 20:45:06 +04:00
|
|
|
CSYNC_STATUS csync_errno_to_status(int error, CSYNC_STATUS default_status)
|
2012-12-17 20:22:24 +04:00
|
|
|
{
|
2013-04-06 20:45:06 +04:00
|
|
|
CSYNC_STATUS status = CSYNC_STATUS_OK;
|
2012-12-17 20:22:24 +04:00
|
|
|
|
2013-04-06 20:45:06 +04:00
|
|
|
switch (error) {
|
2012-12-17 20:22:24 +04:00
|
|
|
case 0:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_OK;
|
2012-12-17 20:22:24 +04:00
|
|
|
break;
|
|
|
|
/* The custom errnos first. */
|
|
|
|
case ERRNO_GENERAL_ERROR:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_UNSUCCESSFUL;
|
2012-12-17 20:22:24 +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;
|
2012-12-17 20:22:24 +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;
|
2012-12-17 20:22:24 +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 */
|
2012-12-17 20:22:24 +04:00
|
|
|
break;
|
|
|
|
case ERRNO_CONNECT:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_CONNECT_ERROR; /* Network: Connection error */
|
2012-12-17 20:22:24 +04:00
|
|
|
break;
|
|
|
|
case ERRNO_TIMEOUT:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_TIMEOUT; /* Network: Timeout error */
|
2012-12-17 20:22:24 +04:00
|
|
|
break;
|
2013-01-14 00:39:54 +04:00
|
|
|
case ERRNO_QUOTA_EXCEEDED:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_QUOTA_EXCEEDED; /* Quota exceeded */
|
2013-01-14 00:39:54 +04:00
|
|
|
break;
|
|
|
|
case ERRNO_SERVICE_UNAVAILABLE:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_SERVICE_UNAVAILABLE; /* Service temporarily down */
|
2013-01-14 00:39:54 +04:00
|
|
|
break;
|
|
|
|
case EFBIG:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_FILE_SIZE_ERROR; /* File larger than 2MB */
|
2013-01-14 00:39:54 +04:00
|
|
|
break;
|
2012-12-17 20:22:24 +04:00
|
|
|
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;
|
2012-12-17 20:22:24 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ERRNO_TIMEDELTA:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_TIMESKEW;
|
2012-12-17 20:22:24 +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;
|
2012-12-17 20:22:24 +04:00
|
|
|
break;
|
|
|
|
case ENOENT: /* No such file or directory */
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_NOT_FOUND;
|
2012-12-17 20:22:24 +04:00
|
|
|
break;
|
|
|
|
case EAGAIN: /* Try again */
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_TIMEOUT;
|
2012-12-17 20:22:24 +04:00
|
|
|
break;
|
|
|
|
case EEXIST: /* File exists */
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_FILE_EXISTS;
|
2012-12-17 20:22:24 +04:00
|
|
|
break;
|
|
|
|
case EINVAL:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_PARAM_ERROR;
|
2012-12-17 20:22:24 +04:00
|
|
|
break;
|
|
|
|
case ENOSPC:
|
2013-04-06 20:45:06 +04:00
|
|
|
status = CSYNC_STATUS_OUT_OF_SPACE;
|
2012-12-17 20:22:24 +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 */
|
2012-12-19 23:20:26 +04:00
|
|
|
#ifndef _WIN32
|
2012-12-17 20:22:24 +04:00
|
|
|
case ENOTBLK: /* Block device required */
|
2012-12-19 23:20:26 +04:00
|
|
|
#endif
|
2012-12-17 20:22:24 +04:00
|
|
|
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 */
|
2012-12-19 23:20:26 +04:00
|
|
|
#ifndef _WIN32
|
2012-12-17 20:22:24 +04:00
|
|
|
case ETXTBSY: /* Text file busy */
|
2012-12-19 23:20:26 +04:00
|
|
|
#endif
|
2012-12-17 20:22:24 +04:00
|
|
|
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;
|
2012-12-17 20:22:24 +04:00
|
|
|
}
|
|
|
|
|
2013-04-06 20:45:06 +04:00
|
|
|
return status;
|
2012-12-17 20:22:24 +04:00
|
|
|
}
|
2013-11-25 19:19:59 +04:00
|
|
|
|
|
|
|
/* Remove "-gzip" at the end (cf. https://github.com/owncloud/mirall/issues/1195)
|
|
|
|
* (work in place)
|
|
|
|
*/
|
|
|
|
char *csync_normalize_etag(char *etag)
|
|
|
|
{
|
2013-11-25 21:27:37 +04:00
|
|
|
int len = 0;
|
2013-11-25 19:19:59 +04:00
|
|
|
if (!etag) return etag;
|
2013-11-25 21:27:37 +04:00
|
|
|
|
|
|
|
len = strlen(etag);
|
2013-11-25 19:19:59 +04:00
|
|
|
if (len > 5 && c_streq(etag + len - 5, "-gzip")) {
|
|
|
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Removing -gzip from etag: %s", etag);
|
|
|
|
etag[len-5] = '\0';
|
|
|
|
}
|
|
|
|
return etag;
|
|
|
|
}
|
|
|
|
|