svn_error_t * svn_fs_fs__read_rep_header(svn_fs_fs__rep_header_t **header, svn_stream_t *stream, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_stringbuf_t *buffer; char *str, *last_str; apr_int64_t val; svn_boolean_t eol = FALSE; SVN_ERR(svn_stream_readline(stream, &buffer, "\n", &eol, scratch_pool)); *header = apr_pcalloc(result_pool, sizeof(**header)); (*header)->header_size = buffer->len + 1; if (strcmp(buffer->data, REP_PLAIN) == 0) { (*header)->type = svn_fs_fs__rep_plain; return SVN_NO_ERROR; } if (strcmp(buffer->data, REP_DELTA) == 0) { /* This is a delta against the empty stream. */ (*header)->type = svn_fs_fs__rep_self_delta; return SVN_NO_ERROR; } (*header)->type = svn_fs_fs__rep_delta; /* We have hopefully a DELTA vs. a non-empty base revision. */ last_str = buffer->data; str = svn_cstring_tokenize(" ", &last_str); if (! str || (strcmp(str, REP_DELTA) != 0)) goto error; SVN_ERR(parse_revnum(&(*header)->base_revision, (const char **)&last_str)); str = svn_cstring_tokenize(" ", &last_str); if (! str) goto error; SVN_ERR(svn_cstring_atoi64(&val, str)); (*header)->base_item_index = (apr_off_t)val; str = svn_cstring_tokenize(" ", &last_str); if (! str) goto error; SVN_ERR(svn_cstring_atoi64(&val, str)); (*header)->base_length = (svn_filesize_t)val; return SVN_NO_ERROR; error: return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("Malformed representation header")); }
svn_error_t * svn_fs_fs__parse_footer(apr_off_t *l2p_offset, svn_checksum_t **l2p_checksum, apr_off_t *p2l_offset, svn_checksum_t **p2l_checksum, svn_stringbuf_t *footer, svn_revnum_t rev, apr_pool_t *result_pool) { apr_int64_t val; char *last_str = footer->data; /* Get the L2P offset. */ const char *str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid revision footer")); SVN_ERR(svn_cstring_atoi64(&val, str)); *l2p_offset = (apr_off_t)val; /* Get the L2P checksum. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid revision footer")); SVN_ERR(svn_checksum_parse_hex(l2p_checksum, svn_checksum_md5, str, result_pool)); /* Get the P2L offset. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid revision footer")); SVN_ERR(svn_cstring_atoi64(&val, str)); *p2l_offset = (apr_off_t)val; /* Get the P2L checksum. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid revision footer")); SVN_ERR(svn_checksum_parse_hex(p2l_checksum, svn_checksum_md5, str, result_pool)); return SVN_NO_ERROR; }
svn_fs_id_t * svn_fs_base__id_parse(const char *data, apr_size_t len, apr_pool_t *pool) { svn_fs_id_t *id; id_private_t *pvt; char *data_copy, *str; /* Dup the ID data into POOL. Our returned ID will have references into this memory. */ data_copy = apr_pstrmemdup(pool, data, len); /* Alloc a new svn_fs_id_t structure. */ id = apr_palloc(pool, sizeof(*id)); pvt = apr_palloc(pool, sizeof(*pvt)); id->vtable = &id_vtable; id->fsap_data = pvt; /* Now, we basically just need to "split" this data on `.' characters. We will use svn_cstring_tokenize, which will put terminators where each of the '.'s used to be. Then our new id field will reference string locations inside our duplicate string.*/ /* Node Id */ str = svn_cstring_tokenize(".", &data_copy); if (str == NULL) return NULL; pvt->node_id = str; /* Copy Id */ str = svn_cstring_tokenize(".", &data_copy); if (str == NULL) return NULL; pvt->copy_id = str; /* Txn Id */ str = svn_cstring_tokenize(".", &data_copy); if (str == NULL) return NULL; pvt->txn_id = str; return id; }
void svn_cstring_split_append(apr_array_header_t *array, const char *input, const char *sep_chars, svn_boolean_t chop_whitespace, apr_pool_t *pool) { char *pats; char *p; pats = apr_pstrdup(pool, input); /* strtok wants non-const data */ p = svn_cstring_tokenize(sep_chars, &pats); while (p) { if (chop_whitespace) { while (svn_ctype_isspace(*p)) p++; { char *e = p + (strlen(p) - 1); while ((e >= p) && (svn_ctype_isspace(*e))) e--; *(++e) = '\0'; } } if (p[0] != '\0') APR_ARRAY_PUSH(array, const char *) = p; p = svn_cstring_tokenize(sep_chars, &pats); } return; }
/* Load the setting http-auth-types from the global or server specific section, parse its value and set the types of authentication we should accept from the server. */ static svn_error_t * load_http_auth_types(apr_pool_t *pool, svn_config_t *config, const char *server_group, int *authn_types) { const char *http_auth_types = NULL; *authn_types = SERF_AUTHN_NONE; svn_config_get(config, &http_auth_types, SVN_CONFIG_SECTION_GLOBAL, SVN_CONFIG_OPTION_HTTP_AUTH_TYPES, NULL); if (server_group) { svn_config_get(config, &http_auth_types, server_group, SVN_CONFIG_OPTION_HTTP_AUTH_TYPES, http_auth_types); } if (http_auth_types) { char *token; char *auth_types_list = apr_palloc(pool, strlen(http_auth_types) + 1); apr_collapse_spaces(auth_types_list, http_auth_types); while ((token = svn_cstring_tokenize(";", &auth_types_list)) != NULL) { if (svn_cstring_casecmp("basic", token) == 0) *authn_types |= SERF_AUTHN_BASIC; else if (svn_cstring_casecmp("digest", token) == 0) *authn_types |= SERF_AUTHN_DIGEST; else if (svn_cstring_casecmp("ntlm", token) == 0) *authn_types |= SERF_AUTHN_NTLM; else if (svn_cstring_casecmp("negotiate", token) == 0) *authn_types |= SERF_AUTHN_NEGOTIATE; else return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL, _("Invalid config: unknown %s " "'%s'"), SVN_CONFIG_OPTION_HTTP_AUTH_TYPES, token); } } else { /* Nothing specified by the user, so accept all types. */ *authn_types = SERF_AUTHN_ALL; } return SVN_NO_ERROR; }
svn_error_t * svn_fs_fs__parse_representation(representation_t **rep_p, svn_stringbuf_t *text, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { representation_t *rep; char *str; apr_int64_t val; char *string = text->data; svn_checksum_t *checksum; const char *end; rep = apr_pcalloc(result_pool, sizeof(*rep)); *rep_p = rep; SVN_ERR(parse_revnum(&rep->revision, (const char **)&string)); /* initialize transaction info (never stored) */ svn_fs_fs__id_txn_reset(&rep->txn_id); /* while in transactions, it is legal to simply write "-1" */ str = svn_cstring_tokenize(" ", &string); if (str == NULL) { if (rep->revision == SVN_INVALID_REVNUM) return SVN_NO_ERROR; return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); } SVN_ERR(svn_cstring_atoi64(&val, str)); rep->item_index = (apr_uint64_t)val; str = svn_cstring_tokenize(" ", &string); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); SVN_ERR(svn_cstring_atoi64(&val, str)); rep->size = (svn_filesize_t)val; str = svn_cstring_tokenize(" ", &string); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); SVN_ERR(svn_cstring_atoi64(&val, str)); rep->expanded_size = (svn_filesize_t)val; /* Read in the MD5 hash. */ str = svn_cstring_tokenize(" ", &string); if ((str == NULL) || (strlen(str) != (APR_MD5_DIGESTSIZE * 2))) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_md5, str, scratch_pool)); memcpy(rep->md5_digest, checksum->digest, sizeof(rep->md5_digest)); /* The remaining fields are only used for formats >= 4, so check that. */ str = svn_cstring_tokenize(" ", &string); if (str == NULL) return SVN_NO_ERROR; /* Read the SHA1 hash. */ if (strlen(str) != (APR_SHA1_DIGESTSIZE * 2)) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_sha1, str, scratch_pool)); rep->has_sha1 = checksum != NULL; memcpy(rep->sha1_digest, checksum->digest, sizeof(rep->sha1_digest)); /* Read the uniquifier. */ str = svn_cstring_tokenize("/", &string); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); SVN_ERR(svn_fs_fs__id_txn_parse(&rep->uniquifier.noderev_txn_id, str)); str = svn_cstring_tokenize(" ", &string); if (str == NULL || *str != '_') return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); ++str; rep->uniquifier.number = svn__base36toui64(&end, str); if (*end) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); return SVN_NO_ERROR; }
/* Read the next entry in the changes record from file FILE and store the resulting change in *CHANGE_P. If there is no next record, store NULL there. Perform all allocations from POOL. */ static svn_error_t * read_change(change_t **change_p, svn_stream_t *stream, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_stringbuf_t *line; svn_boolean_t eof = TRUE; change_t *change; char *str, *last_str, *kind_str; svn_fs_path_change2_t *info; /* Default return value. */ *change_p = NULL; SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, scratch_pool)); /* Check for a blank line. */ if (eof || (line->len == 0)) return SVN_NO_ERROR; change = apr_pcalloc(result_pool, sizeof(*change)); info = &change->info; last_str = line->data; /* Get the node-id of the change. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid changes line in rev-file")); SVN_ERR(svn_fs_fs__id_parse(&info->node_rev_id, str, result_pool)); if (info->node_rev_id == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid changes line in rev-file")); /* Get the change type. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid changes line in rev-file")); /* Don't bother to check the format number before looking for * node-kinds: just read them if you find them. */ info->node_kind = svn_node_unknown; kind_str = strchr(str, '-'); if (kind_str) { /* Cap off the end of "str" (the action). */ *kind_str = '\0'; kind_str++; if (strcmp(kind_str, SVN_FS_FS__KIND_FILE) == 0) info->node_kind = svn_node_file; else if (strcmp(kind_str, SVN_FS_FS__KIND_DIR) == 0) info->node_kind = svn_node_dir; else return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid changes line in rev-file")); } if (strcmp(str, ACTION_MODIFY) == 0) { info->change_kind = svn_fs_path_change_modify; } else if (strcmp(str, ACTION_ADD) == 0) { info->change_kind = svn_fs_path_change_add; } else if (strcmp(str, ACTION_DELETE) == 0) { info->change_kind = svn_fs_path_change_delete; } else if (strcmp(str, ACTION_REPLACE) == 0) { info->change_kind = svn_fs_path_change_replace; } else if (strcmp(str, ACTION_RESET) == 0) { info->change_kind = svn_fs_path_change_reset; } else { return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid change kind in rev file")); } /* Get the text-mod flag. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid changes line in rev-file")); if (strcmp(str, FLAG_TRUE) == 0) { info->text_mod = TRUE; } else if (strcmp(str, FLAG_FALSE) == 0) { info->text_mod = FALSE; } else { return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid text-mod flag in rev-file")); } /* Get the prop-mod flag. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid changes line in rev-file")); if (strcmp(str, FLAG_TRUE) == 0) { info->prop_mod = TRUE; } else if (strcmp(str, FLAG_FALSE) == 0) { info->prop_mod = FALSE; } else { return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid prop-mod flag in rev-file")); } /* Get the mergeinfo-mod flag if given. Otherwise, the next thing is the path starting with a slash. Also, we must initialize the flag explicitly because 0 is not valid for a svn_tristate_t. */ info->mergeinfo_mod = svn_tristate_unknown; if (*last_str != '/') { str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid changes line in rev-file")); if (strcmp(str, FLAG_TRUE) == 0) { info->mergeinfo_mod = svn_tristate_true; } else if (strcmp(str, FLAG_FALSE) == 0) { info->mergeinfo_mod = svn_tristate_false; } else { return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid mergeinfo-mod flag in rev-file")); } } /* Get the changed path. */ if (!svn_fspath__is_canonical(last_str)) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid path in changes line")); change->path.len = strlen(last_str); change->path.data = apr_pstrdup(result_pool, last_str); /* Read the next line, the copyfrom line. */ SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, scratch_pool)); info->copyfrom_known = TRUE; if (eof || line->len == 0) { info->copyfrom_rev = SVN_INVALID_REVNUM; info->copyfrom_path = NULL; } else { last_str = line->data; SVN_ERR(parse_revnum(&info->copyfrom_rev, (const char **)&last_str)); if (!svn_fspath__is_canonical(last_str)) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Invalid copy-from path in changes line")); info->copyfrom_path = apr_pstrdup(result_pool, last_str); } *change_p = change; return SVN_NO_ERROR; }
/* Return an ID resulting from parsing the string DATA, or NULL if DATA is an invalid ID string. *DATA will be modified / invalidated by this call. */ static svn_fs_id_t * id_parse(char *data, apr_pool_t *pool) { fs_fs__id_t *id; char *str; /* Alloc a new svn_fs_id_t structure. */ id = apr_pcalloc(pool, sizeof(*id)); id->generic_id.vtable = &id_vtable; id->generic_id.fsap_data = id; /* Now, we basically just need to "split" this data on `.' characters. We will use svn_cstring_tokenize, which will put terminators where each of the '.'s used to be. Then our new id field will reference string locations inside our duplicate string.*/ /* Node Id */ str = svn_cstring_tokenize(".", &data); if (str == NULL) return NULL; if (! part_parse(&id->private_id.node_id, str)) return NULL; /* Copy Id */ str = svn_cstring_tokenize(".", &data); if (str == NULL) return NULL; if (! part_parse(&id->private_id.copy_id, str)) return NULL; /* Txn/Rev Id */ str = svn_cstring_tokenize(".", &data); if (str == NULL) return NULL; if (str[0] == 'r') { apr_int64_t val; const char *tmp; svn_error_t *err; /* This is a revision type ID */ id->private_id.txn_id.revision = SVN_INVALID_REVNUM; id->private_id.txn_id.number = 0; data = str + 1; str = svn_cstring_tokenize("/", &data); if (str == NULL) return NULL; if (!locale_independent_strtol(&id->private_id.rev_item.revision, str, &tmp)) return NULL; err = svn_cstring_atoi64(&val, data); if (err) { svn_error_clear(err); return NULL; } id->private_id.rev_item.number = (apr_uint64_t)val; } else if (str[0] == 't') { /* This is a transaction type ID */ id->private_id.rev_item.revision = SVN_INVALID_REVNUM; id->private_id.rev_item.number = 0; if (! txn_id_parse(&id->private_id.txn_id, str + 1)) return NULL; } else return NULL; return (svn_fs_id_t *)id; }
svn_error_t * svn_fs_x__parse_representation(svn_fs_x__representation_t **rep_p, svn_stringbuf_t *text, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_fs_x__representation_t *rep; char *str; apr_int64_t val; char *string = text->data; svn_checksum_t *checksum; rep = apr_pcalloc(result_pool, sizeof(*rep)); *rep_p = rep; str = svn_cstring_tokenize(" ", &string); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); SVN_ERR(svn_cstring_atoi64(&rep->id.change_set, str)); /* while in transactions, it is legal to simply write "-1" */ if (rep->id.change_set == -1) return SVN_NO_ERROR; str = svn_cstring_tokenize(" ", &string); if (str == NULL) { if (rep->id.change_set == SVN_FS_X__INVALID_CHANGE_SET) return SVN_NO_ERROR; return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); } SVN_ERR(svn_cstring_atoi64(&val, str)); rep->id.number = (apr_off_t)val; str = svn_cstring_tokenize(" ", &string); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); SVN_ERR(svn_cstring_atoi64(&val, str)); rep->size = (svn_filesize_t)val; str = svn_cstring_tokenize(" ", &string); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); SVN_ERR(svn_cstring_atoi64(&val, str)); rep->expanded_size = (svn_filesize_t)val; /* Read in the MD5 hash. */ str = svn_cstring_tokenize(" ", &string); if ((str == NULL) || (strlen(str) != (APR_MD5_DIGESTSIZE * 2))) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_md5, str, scratch_pool)); if (checksum) memcpy(rep->md5_digest, checksum->digest, sizeof(rep->md5_digest)); /* The remaining fields are only used for formats >= 4, so check that. */ str = svn_cstring_tokenize(" ", &string); if (str == NULL) return SVN_NO_ERROR; /* Read the SHA1 hash. */ if (strlen(str) != (APR_SHA1_DIGESTSIZE * 2)) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_sha1, str, scratch_pool)); rep->has_sha1 = checksum != NULL; if (checksum) memcpy(rep->sha1_digest, checksum->digest, sizeof(rep->sha1_digest)); return SVN_NO_ERROR; }
svn_error_t * svn_fs_x__parse_footer(apr_off_t *l2p_offset, svn_checksum_t **l2p_checksum, apr_off_t *p2l_offset, svn_checksum_t **p2l_checksum, svn_stringbuf_t *footer, svn_revnum_t rev, apr_off_t footer_offset, apr_pool_t *result_pool) { apr_int64_t val; char *last_str = footer->data; /* Get the L2P offset. */ const char *str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, "Invalid r%ld footer", rev); SVN_ERR(wrap_footer_error(svn_cstring_strtoi64(&val, str, 0, footer_offset - 1, 10), "Invalid L2P offset in r%ld footer", rev)); *l2p_offset = (apr_off_t)val; /* Get the L2P checksum. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, "Invalid r%ld footer", rev); SVN_ERR(svn_checksum_parse_hex(l2p_checksum, svn_checksum_md5, str, result_pool)); /* Get the P2L offset. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, "Invalid r%ld footer", rev); SVN_ERR(wrap_footer_error(svn_cstring_strtoi64(&val, str, 0, footer_offset - 1, 10), "Invalid P2L offset in r%ld footer", rev)); *p2l_offset = (apr_off_t)val; /* The P2L indes follows the L2P index */ if (*p2l_offset <= *l2p_offset) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, "P2L offset %s must be larger than L2P offset %s" " in r%ld footer", apr_psprintf(result_pool, "%" APR_UINT64_T_HEX_FMT, (apr_uint64_t)*p2l_offset), apr_psprintf(result_pool, "%" APR_UINT64_T_HEX_FMT, (apr_uint64_t)*l2p_offset), rev); /* Get the P2L checksum. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, "Invalid r%ld footer", rev); SVN_ERR(svn_checksum_parse_hex(p2l_checksum, svn_checksum_md5, str, result_pool)); return SVN_NO_ERROR; }