int csync_create(CSYNC **csync, const char *local, const char *remote) { CSYNC *ctx; size_t len = 0; ctx = c_malloc(sizeof(CSYNC)); if (ctx == NULL) { return -1; } ctx->status_code = CSYNC_STATUS_OK; /* remove trailing slashes */ len = strlen(local); while(len > 0 && local[len - 1] == '/') --len; ctx->local.uri = c_strndup(local, len); /* remove trailing slashes */ len = strlen(remote); while(len > 0 && remote[len - 1] == '/') --len; ctx->remote.uri = c_strndup(remote, len); ctx->status_code = CSYNC_STATUS_OK; ctx->current_fs = NULL; ctx->abort = false; *csync = ctx; return 0; }
END_TEST START_TEST (check_c_strndup_nomem) { const char *str = "test"; char *tdup = NULL; tdup = c_strndup(str, 3); fail_unless(tdup == NULL, NULL); }
static void check_c_strndup(void **state) { const char *str = "test"; char *tdup = NULL; (void) state; /* unused */ tdup = c_strndup(str, 3); assert_memory_equal(tdup, "tes", 3); free(tdup); }
END_TEST START_TEST (check_c_strndup) { const char *str = "test"; char *tdup = NULL; tdup = c_strndup(str, 3); fail_unless(strncmp(tdup, "tes", 3) == 0, NULL); free(tdup); }
char * c_strdup(const char *s) { char *ret; if (!s) { ret = stp_malloc(1); ret[0] = 0; return ret; } else return c_strndup(s, c_strlen(s)); }
static csync_vio_file_stat_t *_readdir(csync_vio_method_handle_t *dhandle) { struct smbc_dirent *dirent = NULL; smb_dhandle_t *handle = NULL; csync_vio_file_stat_t *file_stat = NULL; handle = (smb_dhandle_t *) dhandle; errno = 0; dirent = smbc_readdir(handle->dh); if (dirent == NULL) { return NULL; } file_stat = c_malloc(sizeof(csync_vio_file_stat_t)); if (file_stat == NULL) { return NULL; } file_stat->name = c_strndup(dirent->name, dirent->namelen); file_stat->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE; switch (dirent->smbc_type) { case SMBC_FILE_SHARE: file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; file_stat->type = CSYNC_VIO_FILE_TYPE_DIRECTORY; break; case SMBC_WORKGROUP: case SMBC_SERVER: case SMBC_COMMS_SHARE: case SMBC_IPC_SHARE: break; case SMBC_DIR: case SMBC_FILE: file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; if (dirent->smbc_type == SMBC_DIR) { file_stat->type = CSYNC_VIO_FILE_TYPE_DIRECTORY; } else { file_stat->type = CSYNC_VIO_FILE_TYPE_REGULAR; } break; default: break; } return file_stat; }
struct c_ptr_vector * http_list_parse(const char *string) { struct c_ptr_vector *entries; const char *ptr, *start; entries = c_ptr_vector_new(); ptr = string; start = NULL; for (;;) { if (*ptr == '\0' || *ptr == ',' || *ptr == ' ' || *ptr == '\t') { if (start) { char *token; token = c_strndup(start, (size_t)(ptr - start)); c_ptr_vector_append(entries, token); start = NULL; } if (*ptr == '\0') break; } else { if (!start) start = ptr; } ptr++; } if (c_ptr_vector_length(entries) == 0) { c_ptr_vector_delete(entries); c_set_error("empty list"); return NULL; } return entries; }
void sircc_chan_add_user(struct sircc_chan *chan, const char *user, size_t sz) { if (sz == (size_t)-1) sz = strlen(user); for (size_t i = 0; i < chan->nb_users; i++) { if (memcmp(chan->users[i], user, sz) == 0) return; } if (!chan->users) { chan->nb_users = 0; chan->users = c_malloc(sizeof(char *)); } else { chan->users = c_realloc(chan->users, (chan->nb_users + 1) * sizeof(char *)); } chan->users[chan->nb_users] = c_strndup(user, sz); chan->nb_users++; chan->users_sorted = false; }
int csync_create(CSYNC **csync, const char *local, const char *remote) { CSYNC *ctx; size_t len = 0; char *home; int rc; ctx = c_malloc(sizeof(CSYNC)); if (ctx == NULL) { return -1; } ctx->status_code = CSYNC_STATUS_OK; /* remove trailing slashes */ len = strlen(local); while(len > 0 && local[len - 1] == '/') --len; ctx->local.uri = c_strndup(local, len); if (ctx->local.uri == NULL) { ctx->status_code = CSYNC_STATUS_MEMORY_ERROR; free(ctx); return -1; } /* remove trailing slashes */ len = strlen(remote); while(len > 0 && remote[len - 1] == '/') --len; ctx->remote.uri = c_strndup(remote, len); if (ctx->remote.uri == NULL) { ctx->status_code = CSYNC_STATUS_MEMORY_ERROR; free(ctx); return -1; } ctx->status_code = CSYNC_STATUS_OK; ctx->options.local_only_mode = false; ctx->pwd.uid = getuid(); ctx->pwd.euid = geteuid(); home = csync_get_user_home_dir(); if (home == NULL) { SAFE_FREE(ctx->local.uri); SAFE_FREE(ctx->remote.uri); SAFE_FREE(ctx); errno = ENOMEM; ctx->status_code = CSYNC_STATUS_MEMORY_ERROR; return -1; } rc = asprintf(&ctx->options.config_dir, "%s/%s", home, CSYNC_CONF_DIR); SAFE_FREE(home); if (rc < 0) { SAFE_FREE(ctx->local.uri); SAFE_FREE(ctx->remote.uri); SAFE_FREE(ctx); errno = ENOMEM; ctx->status_code = CSYNC_STATUS_MEMORY_ERROR; return -1; } ctx->local.list = 0; ctx->remote.list = 0; ctx->current_fs = NULL; ctx->abort = false; *csync = ctx; return 0; }
int http_response_parse(const char *data, size_t sz, uint32_t flags, struct http_response **presponse, size_t *psz) { struct http_response *response; const char *ptr; size_t len, toklen; char status_string[4]; size_t status_sz; int32_t status_value; int ret; ptr = data; len = sz; #define HTTP_FAIL(fmt_, ...) \ do { \ if (fmt_) \ c_set_error(fmt_, ##__VA_ARGS__); \ http_response_delete(response); \ return -1; \ } while (0) #define HTTP_TRUNCATED() \ do { \ http_response_delete(response); \ return 0; \ } while (0) response = http_response_new(); /* Version */ toklen = c_memcspn(ptr, len, " "); if (toklen == len) { if (len > HTTP_VERSION_MAX_LENGTH) HTTP_FAIL("invalid version"); HTTP_TRUNCATED(); } if (http_version_parse(ptr, toklen, &response->version) == -1) HTTP_FAIL(NULL); ptr += toklen + 1; len -= toklen + 1; /* Status */ toklen = c_memcspn(ptr, len, " "); if (toklen == len) { if (len > 3) HTTP_FAIL("invalid status code"); HTTP_TRUNCATED(); } if (toklen > 3) HTTP_FAIL("invalid status code"); memcpy(status_string, ptr, toklen); status_string[toklen] = '\0'; if (c_parse_i32(status_string, &status_value, &status_sz) == -1) HTTP_FAIL("invalid status code"); if (status_sz != toklen) HTTP_FAIL("invalid trailing data after status code"); response->status = (enum http_status)status_value; ptr += toklen + 1; len -= toklen + 1; /* Reason */ toklen = c_memcspn(ptr, len, "\r"); if (toklen == len) { if (len > HTTP_REASON_MAX_LENGTH) HTTP_FAIL("reason string too long"); HTTP_TRUNCATED(); } response->reason = c_strndup(ptr, toklen); ptr += toklen; len -= toklen; /* End of status line */ if (len < 2) HTTP_TRUNCATED(); if (ptr[0] != '\r' || ptr[1] != '\n') HTTP_FAIL("malformed status line"); ptr += 2; len -= 2; /* Headers */ http_headers_delete(response->headers); response->headers = NULL; ret = http_headers_parse(ptr, len, &response->headers, NULL, &toklen); if (ret == -1) HTTP_FAIL(NULL); if (ret == 0) HTTP_TRUNCATED(); ptr += toklen; len -= toklen; if (http_response_preprocess_headers(response) == -1) { http_response_delete(response); return -1; } /* Body */ if (!http_response_can_have_body(response)) goto end; if (response->has_content_length) { if (response->content_length > HTTP_RESPONSE_MAX_CONTENT_LENGTH) HTTP_FAIL("payload too large"); if (len < response->content_length) HTTP_TRUNCATED(); response->body_sz = response->content_length; response->body = c_strndup(ptr, response->content_length); ptr += response->body_sz; len -= response->body_sz; } else if (response->is_body_chunked) { struct http_headers *trailer; size_t chunked_data_sz; ret = http_chunked_data_parse(ptr, len, &response->body, &response->body_sz, &chunked_data_sz); if (ret == -1) HTTP_FAIL("invalid chunked body: %s", c_get_error()); if (ret == 0) HTTP_TRUNCATED(); ptr += chunked_data_sz; len -= chunked_data_sz; /* Trailer */ ret = http_headers_parse(ptr, len, &trailer, NULL, &toklen); if (ret == -1) HTTP_FAIL(NULL); if (ret == 0) HTTP_TRUNCATED(); http_headers_merge_nocopy(response->headers, trailer); http_headers_delete(trailer); ptr += toklen; len -= toklen; } else if (response->has_connection_close) { size_t content_length; if (flags & HTTP_RESPONSE_PARSE_EOF) { content_length = len; if (content_length > HTTP_RESPONSE_MAX_CONTENT_LENGTH) HTTP_FAIL("payload too large"); response->body_sz = content_length; response->body = c_strndup(ptr, content_length); ptr += response->body_sz; len -= response->body_sz; } else { HTTP_TRUNCATED(); } } else { HTTP_FAIL("missing content length"); } #undef HTTP_FAIL #undef HTTP_TRUNCATED end: *presponse = response; *psz = sz - len; return 1; }
int c_parse_uri(const char *uri, char **scheme, char **user, char **passwd, char **host, unsigned int *port, char **path) { const char *p, *z; if (uri == NULL || *uri == '\0') { return -1; } /* * uri = scheme://user:password@host:port/path * p = ^ * z = ^ */ p = z = uri; /* check for valid scheme; git+ssh, pop3 */ while (isalpha((int) *p) || isdigit((int) *p) || *p == '+' || *p == '-') { /* * uri = scheme://user:password@host:port/path * p = ^ * z = ^ */ p++; } /* get scheme */ if (*p == ':') { if (scheme != NULL) { *scheme = c_strndup(z, p - z); if (*scheme == NULL) { errno = ENOMEM; return -1; } } p++; z = p; } /* * uri = scheme://user:password@host:port/path * p = ^ * z = ^ */ p = z; /* do we have a hostname */ if (p[0] == '/' && p[1] == '/') { /* * uri = scheme://user:password@host:port/path * p = ^ * z = ^ */ z += 2; p = z; /* check for user and passwd */ while (*p && *p != '@' && *p != '/') { /* * uri = scheme://user:password@host:port/path * p = ^ or ^ * z = ^ */ p++; } /* check for user and password */ if (*p == '@') { const char *q; q = p; /* check if we have a password */ while (q > z && *q != ':') { /* * uri = scheme://user:password@host:port/path * p = ^ * z = ^ * q = ^ */ q--; } /* password found */ if (*q == ':') { if (user != NULL) { *user = c_strndup(z, q - z); if (*user == NULL) { errno = ENOMEM; if (scheme != NULL) SAFE_FREE(*scheme); return -1; } } if (passwd != NULL) { *passwd = c_strndup(q + 1, p - (q + 1)); if (*passwd == NULL) { if (scheme != NULL) SAFE_FREE(*scheme); if (user != NULL) SAFE_FREE(*user); errno = ENOMEM; return -1; } } } else { /* user only */ if (user != NULL) { *user = c_strndup(z, p - z); if( *user == NULL) { if (scheme != NULL) SAFE_FREE(*scheme); errno = ENOMEM; return -1; } } } p++; z = p; } /* * uri = scheme://user:password@host:port/path * p = ^ * z = ^ */ p = z; /* check for IPv6 address */ if (*p == '[') { /* * uri = scheme://user:password@[2001:0db8:85a3:08d3:1319:8a2e:0370:7344]:port/path * p = ^ * z = ^ */ p++; /* check if we have a valid IPv6 address */ while (*p && (isxdigit((int) *p) || *p == '.' || *p == ':')) { /* * uri = scheme://user:password@[2001:0db8:85a3:08d3:1319:8a2e:0370:7344]:port/path * p = ^ * z = ^ */ p++; } /* valid IPv6 address found */ if (*p == ']') { /* * uri = scheme://user:password@[2001:0db8:85a3:08d3:1319:8a2e:0370:7344]:port/path * p = ^ * z = ^ */ z++; if (host != NULL) { *host = c_strndup(z, p - z); if (*host == NULL) { if (scheme != NULL) SAFE_FREE(*scheme); if (user != NULL) SAFE_FREE(*user); if (passwd != NULL) SAFE_FREE(*passwd); errno = ENOMEM; return -1; } } /* * uri = scheme://user:password@[2001:0db8:85a3:08d3:1319:8a2e:0370:7344]:port/path * p = ^ * z = ^ */ p++; } else { /* invalid IPv6 address, assume a hostname */ p = z; while (*p && *p != ':' && *p != '/') { p++; /* * uri = scheme://user:password@host:port/path * p = ^ or ^ * z = ^ */ } if (host != NULL) { *host = c_strndup(z, p - z); if (*host == NULL) { if (scheme != NULL) SAFE_FREE(*scheme); if (user != NULL) SAFE_FREE(*user); if (passwd != NULL) SAFE_FREE(*passwd); errno = ENOMEM; return -1; } } } } else { /* check for hostname */ while (*p && *p != ':' && *p != '/') { /* * uri = scheme://user:password@host:port/path * p = ^ ^ * z = ^ */ p++; } if (host != NULL) { *host = c_strndup(z, p - z); if (*host == NULL) { if (scheme != NULL) SAFE_FREE(*scheme); if (user != NULL) SAFE_FREE(*user); if (passwd != NULL) SAFE_FREE(*passwd); errno = ENOMEM; return -1; } } } /* check for port */ if (*p == ':') { char **e = NULL; /* * uri = scheme://user:password@host:port/path * p = ^ * z = ^ */ z = ++p; /* get only the digits */ while (isdigit((int) *p)) { /* * uri = scheme://user:password@host:port/path * p = ^ * z = ^ */ e = (char **) &p; p++; } if (port != NULL) { *port = strtoul(z, e, 0); } /* * uri = scheme://user:password@host:port/path * p = ^ */ } } if (*p == '\0') { return 0; } /* get the path with the leading slash */ if (*p == '/') { if (path != NULL) { *path = c_strdup(p); if (*path == NULL) { if (scheme != NULL) SAFE_FREE(*scheme); if (user != NULL) SAFE_FREE(*user); if (passwd != NULL) SAFE_FREE(*passwd); if (host != NULL) SAFE_FREE(*host); errno = ENOMEM; return -1; } } return 0; } return -1; }
int csync_create(CSYNC **csync, const char *local, const char *remote) { CSYNC *ctx; size_t len = 0; char *home; int rc; ctx = c_malloc(sizeof(CSYNC)); if (ctx == NULL) { return -1; } ctx->error_code = CSYNC_ERR_NONE; /* remove trailing slashes */ len = strlen(local); while(len > 0 && local[len - 1] == '/') --len; ctx->local.uri = c_strndup(local, len); if (ctx->local.uri == NULL) { ctx->error_code = CSYNC_ERR_MEM; return -1; } /* remove trailing slashes */ len = strlen(remote); while(len > 0 && remote[len - 1] == '/') --len; ctx->remote.uri = c_strndup(remote, len); if (ctx->remote.uri == NULL) { SAFE_FREE(ctx->remote.uri); ctx->error_code = CSYNC_ERR_MEM; return -1; } ctx->options.max_depth = MAX_DEPTH; ctx->options.max_time_difference = MAX_TIME_DIFFERENCE; ctx->options.unix_extensions = 0; ctx->options.with_conflict_copys=false; ctx->options.local_only_mode = false; ctx->pwd.uid = getuid(); ctx->pwd.euid = geteuid(); home = csync_get_user_home_dir(); if (home == NULL) { SAFE_FREE(ctx->local.uri); SAFE_FREE(ctx->remote.uri); SAFE_FREE(ctx); errno = ENOMEM; ctx->error_code = CSYNC_ERR_MEM; return -1; } rc = asprintf(&ctx->options.config_dir, "%s/%s", home, CSYNC_CONF_DIR); SAFE_FREE(home); if (rc < 0) { SAFE_FREE(ctx->local.uri); SAFE_FREE(ctx->remote.uri); SAFE_FREE(ctx); errno = ENOMEM; ctx->error_code = CSYNC_ERR_MEM; return -1; } *csync = ctx; return 0; }
int csync_init(CSYNC *ctx) { int rc; time_t timediff = -1; char *log = NULL; char *exclude = NULL; char *lock = NULL; char *config = NULL; #ifndef _WIN32 char errbuf[256] = {0}; #endif if (ctx == NULL) { errno = EBADF; return -1; } ctx->error_code = CSYNC_ERR_NONE; /* Do not initialize twice */ if (ctx->status & CSYNC_STATUS_INIT) { return 1; } /* load log file */ if (csync_log_init() < 0) { ctx->error_code = CSYNC_ERR_LOG; fprintf(stderr, "csync_init: logger init failed\n"); return -1; } /* create dir if it doesn't exist */ if (! c_isdir(ctx->options.config_dir)) { c_mkdirs(ctx->options.config_dir, 0700); } if (asprintf(&log, "%s/%s", ctx->options.config_dir, CSYNC_LOG_FILE) < 0) { ctx->error_code = CSYNC_ERR_UNSPEC; rc = -1; goto out; } /* load log if it exists */ if (c_isfile(log)) { csync_log_load(log); } else { #ifndef _WIN32 if (c_copy(SYSCONFDIR "/csync/" CSYNC_LOG_FILE, log, 0644) == 0) { csync_log_load(log); } #endif } /* create lock file */ if (asprintf(&lock, "%s/%s", ctx->options.config_dir, CSYNC_LOCK_FILE) < 0) { ctx->error_code = CSYNC_ERR_UNSPEC; rc = -1; goto out; } #ifndef _WIN32 if (csync_lock(lock) < 0) { ctx->error_code = CSYNC_ERR_LOCK; rc = -1; goto out; } #endif /* load config file */ if (asprintf(&config, "%s/%s", ctx->options.config_dir, CSYNC_CONF_FILE) < 0) { rc = -1; goto out; } if (csync_config_load(ctx, config) < 0) { CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Could not load config file %s, using defaults.", config); } #ifndef _WIN32 /* load global exclude list */ if (asprintf(&exclude, "%s/csync/%s", SYSCONFDIR, CSYNC_EXCLUDE_FILE) < 0) { ctx->error_code = CSYNC_ERR_UNSPEC; rc = -1; goto out; } if (csync_exclude_load(ctx, exclude) < 0) { strerror_r(errno, errbuf, sizeof(errbuf)); CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "Could not load %s - %s", exclude, errbuf); } SAFE_FREE(exclude); /* load exclude list */ if (asprintf(&exclude, "%s/%s", ctx->options.config_dir, CSYNC_EXCLUDE_FILE) < 0) { ctx->error_code = CSYNC_ERR_UNSPEC; rc = -1; goto out; } if (csync_exclude_load(ctx, exclude) < 0) { strerror_r(errno, errbuf, sizeof(errbuf)); CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "Could not load %s - %s", exclude, errbuf); } #endif /* create/load statedb */ if (! csync_is_statedb_disabled(ctx)) { uint64_t h = csync_create_statedb_hash(ctx); if (asprintf(&ctx->statedb.file, "%s/csync_statedb_%llu.db", ctx->options.config_dir, (long long unsigned int) h) < 0) { ctx->error_code = CSYNC_ERR_UNSPEC; rc = -1; goto out; } CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Remote replica: %s", ctx->remote.uri); CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Statedb: %s", ctx->statedb.file); if (csync_statedb_load(ctx, ctx->statedb.file) < 0) { ctx->error_code = CSYNC_ERR_STATEDB_LOAD; rc = -1; goto out; } } ctx->local.type = LOCAL_REPLICA; /* check for uri */ if ( !ctx->options.local_only_mode && csync_fnmatch("*://*", ctx->remote.uri, 0) == 0) { size_t len; len = strstr(ctx->remote.uri, "://") - ctx->remote.uri; /* get protocol */ if (len > 0) { char *module = NULL; /* module name */ module = c_strndup(ctx->remote.uri, len); if (module == NULL) { ctx->error_code = CSYNC_ERR_MODULE; rc = -1; goto out; } /* load module */ retry_vio_init: rc = csync_vio_init(ctx, module, NULL); if (rc < 0) { len = strlen(module); if (len > 0 && module[len-1] == 's') { module[len-1] = '\0'; goto retry_vio_init; } /* Now vio init finally failed which means a module could not be found. */ ctx->error_code = CSYNC_ERR_MODULE; CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "The csync module %s could not be loaded.", module); SAFE_FREE(module); goto out; } SAFE_FREE(module); ctx->remote.type = REMOTE_REPLCIA; } } else { ctx->remote.type = LOCAL_REPLICA; } if(!ctx->options.local_only_mode) { if(ctx->module.capabilities.time_sync_required) { timediff = csync_timediff(ctx); if (timediff > ctx->options.max_time_difference) { CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "Clock skew detected. The time difference is greater than %d seconds!", ctx->options.max_time_difference); ctx->error_code = CSYNC_ERR_TIMESKEW; rc = -1; goto out; } else if (timediff < 0) { /* error code was set in csync_timediff() */ CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "Synchronisation is not possible!"); /* do not override error code set by timediff */ if(ctx->error_code == CSYNC_ERR_NONE) { ctx->error_code = CSYNC_ERR_TIMESKEW; } rc = -1; goto out; } } else { CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Module does not need time synchronization."); } if(ctx->module.capabilities.unix_extensions == -1) { /* detect */ if (csync_unix_extensions(ctx) < 0) { CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "Could not detect filesystem type."); ctx->error_code = CSYNC_ERR_FILESYSTEM; rc = -1; goto out; } } else { /* The module specifies the value for the unix_extensions. */ ctx->options.unix_extensions = ctx->module.capabilities.unix_extensions; } } if (c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp) < 0) { ctx->error_code = CSYNC_ERR_TREE; rc = -1; goto out; } if (c_rbtree_create(&ctx->remote.tree, _key_cmp, _data_cmp) < 0) { ctx->error_code = CSYNC_ERR_TREE; rc = -1; goto out; } ctx->status = CSYNC_STATUS_INIT; /* initialize random generator */ srand(time(NULL)); rc = 0; out: SAFE_FREE(log); SAFE_FREE(lock); SAFE_FREE(exclude); SAFE_FREE(config); return rc; }
int csync_init(CSYNC *ctx) { int rc; time_t timediff = -1; char *exclude = NULL; char *lock = NULL; char *config = NULL; char errbuf[256] = {0}; if (ctx == NULL) { errno = EBADF; return -1; } ctx->status_code = CSYNC_STATUS_OK; /* Do not initialize twice */ if (ctx->status & CSYNC_STATUS_INIT) { return 1; } /* create dir if it doesn't exist */ if (! c_isdir(ctx->options.config_dir)) { c_mkdirs(ctx->options.config_dir, 0700); } /* create lock file */ if (asprintf(&lock, "%s/%s", ctx->options.config_dir, CSYNC_LOCK_FILE) < 0) { rc = -1; ctx->status_code = CSYNC_STATUS_MEMORY_ERROR; goto out; } #ifndef _WIN32 if (csync_lock(lock) < 0) { rc = -1; ctx->status_code = CSYNC_STATUS_NO_LOCK; goto out; } #endif /* load config file */ if (asprintf(&config, "%s/%s", ctx->options.config_dir, CSYNC_CONF_FILE) < 0) { ctx->status_code = CSYNC_STATUS_MEMORY_ERROR; rc = -1; goto out; } rc = csync_config_parse_file(ctx, config); if (rc < 0) { CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Could not load config file %s, using defaults.", config); } #ifndef _WIN32 /* load global exclude list */ if (asprintf(&exclude, "%s/csync/%s", SYSCONFDIR, CSYNC_EXCLUDE_FILE) < 0) { rc = -1; ctx->status_code = CSYNC_STATUS_MEMORY_ERROR; goto out; } if (csync_exclude_load(ctx, exclude) < 0) { strerror_r(errno, errbuf, sizeof(errbuf)); CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Could not load %s - %s", exclude, errbuf); } SAFE_FREE(exclude); #endif /* load exclude list */ if (asprintf(&exclude, "%s/%s", ctx->options.config_dir, CSYNC_EXCLUDE_FILE) < 0) { ctx->status_code = CSYNC_STATUS_MEMORY_ERROR; rc = -1; goto out; } if (csync_exclude_load(ctx, exclude) < 0) { strerror_r(errno, errbuf, sizeof(errbuf)); CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "Could not load %s - %s", exclude, errbuf); } /* create/load statedb */ if (! csync_is_statedb_disabled(ctx)) { rc = asprintf(&ctx->statedb.file, "%s/.csync_journal.db", ctx->local.uri); if (rc < 0) { ctx->status_code = CSYNC_STATUS_MEMORY_ERROR; goto out; } CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Journal: %s", ctx->statedb.file); rc = csync_statedb_load(ctx, ctx->statedb.file, &ctx->statedb.db); if (rc < 0) { ctx->status_code = CSYNC_STATUS_STATEDB_LOAD_ERROR; goto out; } } ctx->local.type = LOCAL_REPLICA; /* check for uri */ if ( !ctx->options.local_only_mode && csync_fnmatch("*://*", ctx->remote.uri, 0) == 0) { size_t len; len = strstr(ctx->remote.uri, "://") - ctx->remote.uri; /* get protocol */ if (len > 0) { char *module = NULL; /* module name */ module = c_strndup(ctx->remote.uri, len); if (module == NULL) { rc = -1; ctx->status_code = CSYNC_STATUS_MEMORY_ERROR; goto out; } /* load module */ retry_vio_init: rc = csync_vio_init(ctx, module, NULL); if (rc < 0) { len = strlen(module); if (module[len-1] == 's') { module[len-1] = '\0'; goto retry_vio_init; } SAFE_FREE(module); ctx->status_code = CSYNC_STATUS_NO_MODULE; goto out; } SAFE_FREE(module); ctx->remote.type = REMOTE_REPLICA; } } else { ctx->remote.type = LOCAL_REPLICA; } if( !ctx->options.local_only_mode ) { timediff = csync_timediff(ctx); if (timediff > ctx->options.max_time_difference) { CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "Clock skew detected. The time difference is greater than %d seconds!", ctx->options.max_time_difference); ctx->status_code = CSYNC_STATUS_TIMESKEW; rc = -1; goto out; } else if (timediff < 0) { CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "Synchronisation is not possible!"); ctx->status_code = CSYNC_STATUS_TIMESKEW; rc = -1; goto out; } if (csync_unix_extensions(ctx) < 0) { CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "Could not detect filesystem type."); ctx->status_code = CSYNC_STATUS_FILESYSTEM_UNKNOWN; rc = -1; goto out; } } /* Install progress callbacks in the module. */ if (ctx->callbacks.file_progress_cb != NULL) { int prc; prc = csync_vio_set_property(ctx, "file_progress_callback", &ctx->callbacks.file_progress_cb); if (prc == -1) { /* The module does not support the callbacks */ CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Could not install file progress callback!"); ctx->callbacks.file_progress_cb = NULL; } } if (ctx->callbacks.overall_progress_cb != NULL) { int prc; prc = csync_vio_set_property(ctx, "overall_progress_callback", &ctx->callbacks.overall_progress_cb); if (prc == -1) { /* The module does not support the callbacks */ CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Could not install overall progress callback!"); ctx->callbacks.overall_progress_cb = NULL; } } if (c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp) < 0) { ctx->status_code = CSYNC_STATUS_TREE_ERROR; rc = -1; goto out; } if (c_rbtree_create(&ctx->remote.tree, _key_cmp, _data_cmp) < 0) { ctx->status_code = CSYNC_STATUS_TREE_ERROR; rc = -1; goto out; } ctx->status = CSYNC_STATUS_INIT; /* initialize random generator */ srand(time(NULL)); rc = 0; out: SAFE_FREE(lock); SAFE_FREE(exclude); SAFE_FREE(config); return rc; }
struct http_url * http_url_parse(const char *string) { struct http_url *url; const char *ptr, *start, *end, *at, *colon; size_t toklen; url = http_url_new(); ptr = string; #define HTTP_FAIL(fmt_, ...) \ do { \ c_set_error(fmt_, ##__VA_ARGS__); \ goto error; \ } while (0) /* Scheme */ if (ptr[0] == '/') { if (ptr[1] == '/') { goto authority; } else { goto path; } } start = ptr; if (!(http_url_is_scheme_first_char(*ptr))) HTTP_FAIL("invalid first character in scheme"); for (;;) { if (*ptr == '\0' || *ptr == ':') { toklen = (size_t)(ptr - start); if (toklen == 0) HTTP_FAIL("empty scheme"); url->scheme = c_strndup(start, toklen); break; } else if (!http_url_is_scheme_char(*ptr)) { HTTP_FAIL("invalid character in scheme"); } ptr++; } if (*ptr == ':') ptr++; authority: /* Authority */ if (ptr[0] != '/' || ptr[1] != '/') HTTP_FAIL("invalid characters after scheme"); ptr += 2; end = ptr + strcspn(ptr, "/?#"); at = strchr(ptr, '@'); if (at && at < end) { /* User */ colon = strchr(ptr, ':'); if (colon) { toklen = (size_t)(colon - ptr); } else { toklen = (size_t)(at - ptr); } url->user = http_url_userinfo_decode(ptr, toklen); if (!url->user) HTTP_FAIL("cannot decode user: %s", c_get_error()); if (colon) { /* Password */ toklen = (size_t)(at - colon - 1); url->password = http_url_userinfo_decode(colon + 1, toklen); if (!url->password) HTTP_FAIL("cannot decode password: %s", c_get_error()); } ptr = at + 1; } /* Host */ if (*ptr == '[') { /* IPv6 address */ ptr++; toklen = strcspn(ptr, "]"); } else { toklen = strcspn(ptr, ":/?#"); } url->host = http_url_host_decode(ptr, toklen); if (!url->host) HTTP_FAIL("cannot decode host: %s", c_get_error()); ptr += toklen; if (*ptr == ']') ptr++; if (*ptr == ':') { size_t port_sz; ptr++; /* Port */ toklen = strcspn(ptr, "/?#"); if (toklen == 0) HTTP_FAIL("empty port number"); url->port = c_strndup(ptr, toklen); if (c_parse_u16(url->port, &url->port_number, &port_sz) == -1) HTTP_FAIL("invalid port number: %s", c_get_error()); if (port_sz != strlen(url->port)) HTTP_FAIL("invalid trailing data after port number"); if (url->port_number == 0) HTTP_FAIL("invalid port number"); ptr += toklen; } path: if (*ptr == '/') { /* Path */ toklen = strcspn(ptr, "?#"); url->path = http_url_path_decode(ptr, toklen); if (!url->path) HTTP_FAIL("cannot decode path: %s", c_get_error()); ptr += toklen; } if (*ptr == '?') { ptr++; /* Query */ toklen = strcspn(ptr, "#"); url->query = c_strndup(ptr, toklen); if (!url->query) HTTP_FAIL("cannot decode query: %s", c_get_error()); url->query_parameters = http_query_parameters_parse(url->query); if (!url->query_parameters) HTTP_FAIL("cannot parse query parameters: %s", c_get_error()); ptr += toklen; } if (*ptr == '#') { ptr++; /* Fragment */ toklen = strlen(ptr); url->fragment = http_url_fragment_decode(ptr, toklen); if (!url->fragment) HTTP_FAIL("cannot decode fragment: %s", c_get_error()); ptr += toklen; } #undef HTTP_FAIL return url; error: http_url_delete(url); return NULL; }