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; }
/* Conforms to svn_ra_serf__xml_opened_t */ static svn_error_t * blame_opened(svn_ra_serf__xml_estate_t *xes, void *baton, int entered_state, const svn_ra_serf__dav_props_t *tag, apr_pool_t *scratch_pool) { blame_context_t *blame_ctx = baton; if (entered_state == FILE_REV) { apr_pool_t *state_pool = svn_ra_serf__xml_state_pool(xes); /* Child elements will store properties in these structures. */ blame_ctx->rev_props = apr_hash_make(state_pool); blame_ctx->prop_diffs = apr_array_make(state_pool, 5, sizeof(svn_prop_t)); blame_ctx->state_pool = state_pool; /* Clear this, so we can detect the absence of a TXDELTA. */ blame_ctx->stream = NULL; } else if (entered_state == TXDELTA) { apr_pool_t *state_pool = svn_ra_serf__xml_state_pool(xes); apr_hash_t *gathered = svn_ra_serf__xml_gather_since(xes, FILE_REV); const char *path; const char *rev_str; const char *merged_revision; svn_txdelta_window_handler_t txdelta; void *txdelta_baton; apr_int64_t rev; path = svn_hash_gets(gathered, "path"); rev_str = svn_hash_gets(gathered, "rev"); SVN_ERR(svn_cstring_atoi64(&rev, rev_str)); merged_revision = svn_hash_gets(gathered, "merged-revision"); SVN_ERR(blame_ctx->file_rev(blame_ctx->file_rev_baton, path, (svn_revnum_t)rev, blame_ctx->rev_props, merged_revision != NULL, &txdelta, &txdelta_baton, blame_ctx->prop_diffs, state_pool)); blame_ctx->stream = svn_base64_decode(svn_txdelta_parse_svndiff( txdelta, txdelta_baton, TRUE /* error_on_early_close */, state_pool), state_pool); } return SVN_NO_ERROR; }
svn_error_t * svn_skel__parse_int(apr_int64_t *n, const svn_skel_t *skel, apr_pool_t *scratch_pool) { const char *str; /* We need to duplicate the SKEL contents in order to get a NUL-terminated version of it. The SKEL may not have valid memory at DATA[LEN]. */ str = apr_pstrmemdup(scratch_pool, skel->data, skel->len); return svn_error_trace(svn_cstring_atoi64(n, str)); }
/* * Contact the server (using CONN) to calculate baseline * information for BASELINE_URL at REVISION (which may be * SVN_INVALID_REVNUM to query the HEAD revision). * * If ACTUAL_REVISION is non-NULL, set *ACTUAL_REVISION to revision * retrieved from the server as part of this process (which should * match REVISION when REVISION is valid). Set *BASECOLL_URL_P to the * baseline collection URL. */ static svn_error_t * retrieve_baseline_info(svn_revnum_t *actual_revision, const char **basecoll_url_p, svn_ra_serf__session_t *session, const char *baseline_url, svn_revnum_t revision, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { apr_hash_t *props; apr_hash_t *dav_props; const char *basecoll_url; SVN_ERR(svn_ra_serf__fetch_node_props(&props, session, baseline_url, revision, baseline_props, scratch_pool, scratch_pool)); dav_props = apr_hash_get(props, "DAV:", 4); /* If DAV_PROPS is NULL, then svn_prop_get_value() will return NULL. */ basecoll_url = svn_prop_get_value(dav_props, "baseline-collection"); if (!basecoll_url) { return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL, _("The PROPFIND response did not include " "the requested baseline-collection value")); } *basecoll_url_p = svn_urlpath__canonicalize(basecoll_url, result_pool); if (actual_revision) { const char *version_name; version_name = svn_prop_get_value(dav_props, SVN_DAV__VERSION_NAME); if (version_name) { apr_int64_t rev; SVN_ERR(svn_cstring_atoi64(&rev, version_name)); *actual_revision = (svn_revnum_t)rev; } if (!version_name || !SVN_IS_VALID_REVNUM(*actual_revision)) return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL, _("The PROPFIND response did not include " "the requested version-name value")); } return SVN_NO_ERROR; }
/* Parse / process non-empty the LINE from an strace output. */ static void parse_line(svn_stringbuf_t *line) { /* determine function name, first parameter and return value */ char *func_end = strchr(line->data, '('); char *return_value = strrchr(line->data, ' '); char *first_param_end; apr_int64_t func_return = 0; char *func_start = strchr(line->data, ' '); if (func_end == NULL || return_value == NULL) return; if (func_start == NULL || func_start > func_end) func_start = line->data; else while(*func_start == ' ') func_start++; first_param_end = strchr(func_end, ','); if (first_param_end == NULL) first_param_end = strchr(func_end, ')'); if (first_param_end == NULL) return; *func_end++ = 0; *first_param_end = 0; ++return_value; /* (try to) convert the return value into an integer. * If that fails, continue anyway as defaulting to 0 will be safe for us. */ svn_error_clear(svn_cstring_atoi64(&func_return, return_value)); /* process those operations that we care about */ if (strcmp(func_start, "open") == 0) { /* remove double quotes from file name parameter */ *func_end++ = 0; *--first_param_end = 0; open_file(func_end, (int)func_return); } else if (strcmp(func_start, "read") == 0) read_file(atoi(func_end), func_return); else if (strcmp(func_start, "lseek") == 0) seek_file(atoi(func_end), func_return); else if (strcmp(func_start, "close") == 0) close_file(atoi(func_end)); }
/* Conforms to svn_ra_serf__xml_closed_t */ static svn_error_t * date_closed(svn_ra_serf__xml_estate_t *xes, void *baton, int leaving_state, const svn_string_t *cdata, apr_hash_t *attrs, apr_pool_t *scratch_pool) { date_context_t *date_ctx = baton; apr_int64_t rev; SVN_ERR_ASSERT(leaving_state == VERSION_NAME); SVN_ERR_ASSERT(cdata != NULL); SVN_ERR(svn_cstring_atoi64(&rev, cdata->data)); *date_ctx->revision = (svn_revnum_t)rev; return SVN_NO_ERROR; }
static WId get_wid(void) { WId wid = 1; const char *wid_env_string = getenv("WINDOWID"); if (wid_env_string) { apr_int64_t wid_env; svn_error_t *err; err = svn_cstring_atoi64(&wid_env, wid_env_string); if (err) svn_error_clear(err); else wid = (WId)wid_env; } return wid; }
svn_error_t * svn_fs_fs__read_noderev(node_revision_t **noderev_p, svn_stream_t *stream, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { apr_hash_t *headers; node_revision_t *noderev; char *value; const char *noderev_id; SVN_ERR(read_header_block(&headers, stream, scratch_pool)); noderev = apr_pcalloc(result_pool, sizeof(*noderev)); /* Read the node-rev id. */ value = svn_hash_gets(headers, HEADER_ID); if (value == NULL) /* ### More information: filename/offset coordinates */ return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Missing id field in node-rev")); SVN_ERR(svn_stream_close(stream)); SVN_ERR(svn_fs_fs__id_parse(&noderev->id, value, result_pool)); noderev_id = value; /* for error messages later */ /* Read the type. */ value = svn_hash_gets(headers, HEADER_TYPE); if ((value == NULL) || ( strcmp(value, SVN_FS_FS__KIND_FILE) && strcmp(value, SVN_FS_FS__KIND_DIR))) /* ### s/kind/type/ */ return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("Missing kind field in node-rev '%s'"), noderev_id); noderev->kind = (strcmp(value, SVN_FS_FS__KIND_FILE) == 0) ? svn_node_file : svn_node_dir; /* Read the 'count' field. */ value = svn_hash_gets(headers, HEADER_COUNT); if (value) SVN_ERR(svn_cstring_atoi(&noderev->predecessor_count, value)); else noderev->predecessor_count = 0; /* Get the properties location. */ value = svn_hash_gets(headers, HEADER_PROPS); if (value) { SVN_ERR(read_rep_offsets(&noderev->prop_rep, value, noderev->id, result_pool, scratch_pool)); } /* Get the data location. */ value = svn_hash_gets(headers, HEADER_TEXT); if (value) { SVN_ERR(read_rep_offsets(&noderev->data_rep, value, noderev->id, result_pool, scratch_pool)); } /* Get the created path. */ value = svn_hash_gets(headers, HEADER_CPATH); if (value == NULL) { return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("Missing cpath field in node-rev '%s'"), noderev_id); } else { if (!svn_fspath__is_canonical(value)) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("Non-canonical cpath field in node-rev '%s'"), noderev_id); noderev->created_path = apr_pstrdup(result_pool, value); } /* Get the predecessor ID. */ value = svn_hash_gets(headers, HEADER_PRED); if (value) SVN_ERR(svn_fs_fs__id_parse(&noderev->predecessor_id, value, result_pool)); /* Get the copyroot. */ value = svn_hash_gets(headers, HEADER_COPYROOT); if (value == NULL) { noderev->copyroot_path = apr_pstrdup(result_pool, noderev->created_path); noderev->copyroot_rev = svn_fs_fs__id_rev(noderev->id); } else { SVN_ERR(parse_revnum(&noderev->copyroot_rev, (const char **)&value)); if (!svn_fspath__is_canonical(value)) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("Malformed copyroot line in node-rev '%s'"), noderev_id); noderev->copyroot_path = apr_pstrdup(result_pool, value); } /* Get the copyfrom. */ value = svn_hash_gets(headers, HEADER_COPYFROM); if (value == NULL) { noderev->copyfrom_path = NULL; noderev->copyfrom_rev = SVN_INVALID_REVNUM; } else { SVN_ERR(parse_revnum(&noderev->copyfrom_rev, (const char **)&value)); if (*value == 0) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("Malformed copyfrom line in node-rev '%s'"), noderev_id); noderev->copyfrom_path = apr_pstrdup(result_pool, value); } /* Get whether this is a fresh txn root. */ value = svn_hash_gets(headers, HEADER_FRESHTXNRT); noderev->is_fresh_txn_root = (value != NULL); /* Get the mergeinfo count. */ value = svn_hash_gets(headers, HEADER_MINFO_CNT); if (value) SVN_ERR(svn_cstring_atoi64(&noderev->mergeinfo_count, value)); else noderev->mergeinfo_count = 0; /* Get whether *this* node has mergeinfo. */ value = svn_hash_gets(headers, HEADER_MINFO_HERE); noderev->has_mergeinfo = (value != NULL); *noderev_p = noderev; return SVN_NO_ERROR; }
static svn_error_t * multistatus_closed(svn_ra_serf__xml_estate_t *xes, void *baton, int leaving_state, const svn_string_t *cdata, apr_hash_t *attrs, apr_pool_t *scratch_pool) { struct svn_ra_serf__server_error_t *server_error = baton; const char *errcode; const char *status; switch (leaving_state) { case MS_RESPONSE_HREF: { apr_status_t result; apr_uri_t uri; result = apr_uri_parse(scratch_pool, cdata->data, &uri); if (result) return svn_ra_serf__wrap_err(result, NULL); svn_ra_serf__xml_note(xes, MS_RESPONSE, "path", svn_urlpath__canonicalize(uri.path, scratch_pool)); } break; case MS_RESPONSE_STATUS: svn_ra_serf__xml_note(xes, MS_RESPONSE, "status", cdata->data); break; case MS_RESPONSE_ERROR_HUMANREADABLE: svn_ra_serf__xml_note(xes, MS_RESPONSE, "human-readable", cdata->data); errcode = svn_hash_gets(attrs, "errcode"); if (errcode) svn_ra_serf__xml_note(xes, MS_RESPONSE, "errcode", errcode); break; case MS_RESPONSE: if ((status = svn_hash__get_cstring(attrs, "status", NULL)) != NULL) { error_item_t *item; item = apr_pcalloc(server_error->pool, sizeof(*item)); item->path = apr_pstrdup(server_error->pool, svn_hash_gets(attrs, "path")); SVN_ERR(parse_status_line(&item->http_status, &item->http_reason, status, server_error->pool, scratch_pool)); /* Do we have a mod_dav specific message? */ item->message = svn_hash_gets(attrs, "human-readable"); if (item->message) { if ((errcode = svn_hash_gets(attrs, "errcode")) != NULL) { apr_int64_t val; SVN_ERR(svn_cstring_atoi64(&val, errcode)); item->apr_err = (apr_status_t)val; } item->message = apr_pstrdup(server_error->pool, item->message); } else item->message = apr_pstrdup(server_error->pool, svn_hash_gets(attrs, "description")); APR_ARRAY_PUSH(server_error->items, error_item_t *) = item; } break; case MS_PROPSTAT_STATUS: svn_ra_serf__xml_note(xes, MS_PROPSTAT, "status", cdata->data); break; case MS_PROPSTAT_ERROR_HUMANREADABLE: svn_ra_serf__xml_note(xes, MS_PROPSTAT, "human-readable", cdata->data); errcode = svn_hash_gets(attrs, "errcode"); if (errcode) svn_ra_serf__xml_note(xes, MS_PROPSTAT, "errcode", errcode); break; case MS_PROPSTAT_RESPONSEDESCRIPTION: svn_ra_serf__xml_note(xes, MS_PROPSTAT, "description", cdata->data); break; case MS_PROPSTAT: if ((status = svn_hash__get_cstring(attrs, "status", NULL)) != NULL) { apr_hash_t *response_attrs; error_item_t *item; response_attrs = svn_ra_serf__xml_gather_since(xes, MS_RESPONSE); item = apr_pcalloc(server_error->pool, sizeof(*item)); item->path = apr_pstrdup(server_error->pool, svn_hash_gets(response_attrs, "path")); item->propname = apr_pstrdup(server_error->pool, svn_hash_gets(attrs, "propname")); SVN_ERR(parse_status_line(&item->http_status, &item->http_reason, status, server_error->pool, scratch_pool)); /* Do we have a mod_dav specific message? */ item->message = svn_hash_gets(attrs, "human-readable"); if (item->message) { if ((errcode = svn_hash_gets(attrs, "errcode")) != NULL) { apr_int64_t val; SVN_ERR(svn_cstring_atoi64(&val, errcode)); item->apr_err = (apr_status_t)val; } item->message = apr_pstrdup(server_error->pool, item->message); } else item->message = apr_pstrdup(server_error->pool, svn_hash_gets(attrs, "description")); APR_ARRAY_PUSH(server_error->items, error_item_t *) = item; }
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_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; }
svn_fs_id_t * svn_fs_fs__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, *last_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 apr_strtok, 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 = apr_strtok(data_copy, ".", &last_str); if (str == NULL) return NULL; pvt->node_id = str; /* Copy Id */ str = apr_strtok(NULL, ".", &last_str); if (str == NULL) return NULL; pvt->copy_id = str; /* Txn/Rev Id */ str = apr_strtok(NULL, ".", &last_str); if (str == NULL) return NULL; if (str[0] == 'r') { apr_int64_t val; svn_error_t *err; /* This is a revision type ID */ pvt->txn_id = NULL; str = apr_strtok(str + 1, "/", &last_str); if (str == NULL) return NULL; pvt->rev = SVN_STR_TO_REV(str); str = apr_strtok(NULL, "/", &last_str); if (str == NULL) return NULL; err = svn_cstring_atoi64(&val, str); if (err) { svn_error_clear(err); return NULL; } pvt->offset = (apr_off_t)val; } else if (str[0] == 't') { /* This is a transaction type ID */ pvt->txn_id = str + 1; pvt->rev = SVN_INVALID_REVNUM; pvt->offset = -1; } else return NULL; return id; }
svn_error_t * svn_fs_fs__parse_revision_trailer(apr_off_t *root_offset, apr_off_t *changes_offset, svn_stringbuf_t *trailer, svn_revnum_t rev) { int i, num_bytes; const char *str; /* This cast should be safe since the maximum amount read, 64, will never be bigger than the size of an int. */ num_bytes = (int) trailer->len; /* The last byte should be a newline. */ if (trailer->len == 0 || trailer->data[trailer->len - 1] != '\n') { return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("Revision file (r%ld) lacks trailing newline"), rev); } /* Look for the next previous newline. */ for (i = num_bytes - 2; i >= 0; i--) { if (trailer->data[i] == '\n') break; } if (i < 0) { return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("Final line in revision file (r%ld) longer " "than 64 characters"), rev); } i++; str = &trailer->data[i]; /* find the next space */ for ( ; i < (num_bytes - 2) ; i++) if (trailer->data[i] == ' ') break; if (i == (num_bytes - 2)) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("Final line in revision file r%ld missing space"), rev); if (root_offset) { apr_int64_t val; trailer->data[i] = '\0'; SVN_ERR(svn_cstring_atoi64(&val, str)); *root_offset = (apr_off_t)val; } i++; str = &trailer->data[i]; /* find the next newline */ for ( ; i < num_bytes; i++) if (trailer->data[i] == '\n') break; if (changes_offset) { apr_int64_t val; trailer->data[i] = '\0'; SVN_ERR(svn_cstring_atoi64(&val, str)); *changes_offset = (apr_off_t)val; } 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; }
static int start_err_element(void *baton, int parent, const char *nspace, const char *name, const char **atts) { const svn_ra_neon__xml_elm_t *elm = svn_ra_neon__lookup_xml_elem(error_elements, nspace, name); int acc = elm ? validate_error_elements(parent, elm->id) : SVN_RA_NEON__XML_DECLINE; error_parser_baton_t *b = baton; svn_error_t **err = &(b->tmp_err); if (acc < 1) /* ! > 0 */ return acc; switch (elm->id) { case ELEM_svn_error: { /* allocate the svn_error_t. Hopefully the value will be overwritten by the <human-readable> tag, or even someday by a <D:failed-precondition/> tag. */ *err = svn_error_create(APR_EGENERAL, NULL, _("General svn error from server")); break; } case ELEM_human_readable: { /* get the errorcode attribute if present */ const char *errcode_str = svn_xml_get_attr_value("errcode", /* ### make constant in some mod_dav header? */ atts); if (errcode_str && *err) { apr_int64_t val; svn_error_t *err2; err2 = svn_cstring_atoi64(&val, errcode_str); if (err2) { svn_error_clear(err2); break; } (*err)->apr_err = (apr_status_t)val; } break; } default: break; } switch (elm->id) { case ELEM_human_readable: b->want_cdata = b->cdata; svn_stringbuf_setempty(b->want_cdata); break; default: b->want_cdata = NULL; break; } return elm->id; }
/* Conforms to svn_ra_serf__xml_closed_t */ static svn_error_t * merge_closed(svn_ra_serf__xml_estate_t *xes, void *baton, int leaving_state, const svn_string_t *cdata, apr_hash_t *attrs, apr_pool_t *scratch_pool) { merge_context_t *merge_ctx = baton; if (leaving_state == RESPONSE) { const char *rtype; rtype = svn_hash_gets(attrs, "resourcetype"); /* rtype can only be "baseline" or "collection" (or NULL). We can keep this check simple. */ if (rtype && *rtype == 'b') { const char *rev_str; rev_str = svn_hash_gets(attrs, "revision"); if (rev_str) { apr_int64_t rev; SVN_ERR(svn_cstring_atoi64(&rev, rev_str)); merge_ctx->commit_info->revision = (svn_revnum_t)rev; } else merge_ctx->commit_info->revision = SVN_INVALID_REVNUM; merge_ctx->commit_info->date = apr_pstrdup(merge_ctx->pool, svn_hash_gets(attrs, "date")); merge_ctx->commit_info->author = apr_pstrdup(merge_ctx->pool, svn_hash_gets(attrs, "author")); merge_ctx->commit_info->post_commit_err = apr_pstrdup(merge_ctx->pool, svn_hash_gets(attrs, "post-commit-err")); } else { const char *href; href = svn_urlpath__skip_ancestor( merge_ctx->merge_url, svn_hash_gets(attrs, "href")); if (href == NULL) return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL, _("A MERGE response for '%s' is not " "a child of the destination ('%s')"), href, merge_ctx->merge_url); /* We now need to dive all the way into the WC to update the base VCC url. */ if (!SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(merge_ctx->session) && merge_ctx->session->wc_callbacks->push_wc_prop) { const char *checked_in; svn_string_t checked_in_str; checked_in = svn_hash_gets(attrs, "checked-in"); checked_in_str.data = checked_in; checked_in_str.len = strlen(checked_in); SVN_ERR(merge_ctx->session->wc_callbacks->push_wc_prop( merge_ctx->session->wc_callback_baton, href, SVN_RA_SERF__WC_CHECKED_IN_URL, &checked_in_str, scratch_pool)); } } } else if (leaving_state == BASELINE) { svn_ra_serf__xml_note(xes, RESPONSE, "resourcetype", "baseline"); } else if (leaving_state == COLLECTION) { svn_ra_serf__xml_note(xes, RESPONSE, "resourcetype", "collection"); } else { const char *name; const char *value = cdata->data; if (leaving_state == HREF) { name = "href"; value = svn_urlpath__canonicalize(value, scratch_pool); } else if (leaving_state == CHECKED_IN) { name = "checked-in"; value = svn_urlpath__canonicalize(value, scratch_pool); } else if (leaving_state == VERSION_NAME) name = "revision"; else if (leaving_state == DATE) name = "date"; else if (leaving_state == AUTHOR) name = "author"; else if (leaving_state == POST_COMMIT_ERR) name = "post-commit-err"; else SVN_ERR_MALFUNCTION(); svn_ra_serf__xml_note(xes, RESPONSE, name, value); } return SVN_NO_ERROR; }
/* Read CONTENT_LENGTH bytes from STREAM, parsing the bytes as an encoded Subversion properties hash, and making multiple calls to PARSE_FNS->set_*_property on RECORD_BATON (depending on the value of IS_NODE.) Set *ACTUAL_LENGTH to the number of bytes consumed from STREAM. If an error is returned, the value of *ACTUAL_LENGTH is undefined. Use POOL for all allocations. */ static svn_error_t * parse_property_block(svn_stream_t *stream, svn_filesize_t content_length, const svn_repos_parse_fns3_t *parse_fns, void *record_baton, void *parse_baton, svn_boolean_t is_node, svn_filesize_t *actual_length, apr_pool_t *pool) { svn_stringbuf_t *strbuf; apr_pool_t *proppool = svn_pool_create(pool); *actual_length = 0; while (content_length != *actual_length) { char *buf; /* a pointer into the stringbuf's data */ svn_boolean_t eof; svn_pool_clear(proppool); /* Read a key length line. (Actually, it might be PROPS_END). */ SVN_ERR(svn_stream_readline(stream, &strbuf, "\n", &eof, proppool)); if (eof) { /* We could just use stream_ran_dry() or stream_malformed(), but better to give a non-generic property block error. */ return svn_error_create (SVN_ERR_STREAM_MALFORMED_DATA, NULL, _("Incomplete or unterminated property block")); } *actual_length += (strbuf->len + 1); /* +1 because we read a \n too. */ buf = strbuf->data; if (! strcmp(buf, "PROPS-END")) break; /* no more properties. */ else if ((buf[0] == 'K') && (buf[1] == ' ')) { char *keybuf; apr_uint64_t len; SVN_ERR(svn_cstring_strtoui64(&len, buf + 2, 0, APR_SIZE_MAX, 10)); SVN_ERR(read_key_or_val(&keybuf, actual_length, stream, (apr_size_t)len, proppool)); /* Read a val length line */ SVN_ERR(svn_stream_readline(stream, &strbuf, "\n", &eof, proppool)); if (eof) return stream_ran_dry(); *actual_length += (strbuf->len + 1); /* +1 because we read \n too */ buf = strbuf->data; if ((buf[0] == 'V') && (buf[1] == ' ')) { svn_string_t propstring; char *valbuf; apr_int64_t val; SVN_ERR(svn_cstring_atoi64(&val, buf + 2)); propstring.len = (apr_size_t)val; SVN_ERR(read_key_or_val(&valbuf, actual_length, stream, propstring.len, proppool)); propstring.data = valbuf; /* Now, send the property pair to the vtable! */ if (is_node) { SVN_ERR(parse_fns->set_node_property(record_baton, keybuf, &propstring)); } else { SVN_ERR(parse_fns->set_revision_property(record_baton, keybuf, &propstring)); } } else return stream_malformed(); /* didn't find expected 'V' line */ } else if ((buf[0] == 'D') && (buf[1] == ' ')) { char *keybuf; apr_uint64_t len; SVN_ERR(svn_cstring_strtoui64(&len, buf + 2, 0, APR_SIZE_MAX, 10)); SVN_ERR(read_key_or_val(&keybuf, actual_length, stream, (apr_size_t)len, proppool)); /* We don't expect these in revision properties, and if we see one when we don't have a delete_node_property callback, then we're seeing a v3 feature in a v2 dump. */ if (!is_node || !parse_fns->delete_node_property) return stream_malformed(); SVN_ERR(parse_fns->delete_node_property(record_baton, keybuf)); } else return stream_malformed(); /* didn't find expected 'K' line */ } /* while (1) */ svn_pool_destroy(proppool); return SVN_NO_ERROR; }
/* Conforms to svn_ra_serf__xml_closed_t */ static svn_error_t * item_closed(svn_ra_serf__xml_estate_t *xes, void *baton, int leaving_state, const svn_string_t *cdata, apr_hash_t *attrs, apr_pool_t *scratch_pool) { list_context_t *list_ctx = baton; if (leaving_state == AUTHOR) { /* For compatibility with liveprops, current servers will not use * base64-encoding for "binary" user names bu simply drop the * offending control chars. * * We might want to switch to revprop-style encoding, though, * and this is the code to do that. */ const char *encoding = svn_hash_gets(attrs, "encoding"); if (encoding) { /* Check for a known encoding type. This is easy -- there's only one. */ if (strcmp(encoding, "base64") != 0) { return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, _("Unsupported encoding '%s'"), encoding); } cdata = svn_base64_decode_string(cdata, scratch_pool); } /* Remember until the next ITEM closing tag. */ svn_stringbuf_set(list_ctx->author_buf, cdata->data); list_ctx->author = list_ctx->author_buf->data; } else if (leaving_state == ITEM) { const char *dirent_path = cdata->data; const char *kind_word, *date, *crev, *size; svn_dirent_t dirent = { 0 }; kind_word = svn_hash_gets(attrs, "node-kind"); size = svn_hash_gets(attrs, "size"); dirent.has_props = svn_hash__get_bool(attrs, "has-props", FALSE); crev = svn_hash_gets(attrs, "created-rev"); date = svn_hash_gets(attrs, "date"); /* Convert data. */ dirent.kind = svn_node_kind_from_word(kind_word); if (size) SVN_ERR(svn_cstring_atoi64(&dirent.size, size)); else dirent.size = SVN_INVALID_FILESIZE; if (crev) SVN_ERR(svn_revnum_parse(&dirent.created_rev, crev, NULL)); else dirent.created_rev = SVN_INVALID_REVNUM; if (date) SVN_ERR(svn_time_from_cstring(&dirent.time, date, scratch_pool)); if (list_ctx->author) dirent.last_author = list_ctx->author; /* Invoke RECEIVER */ SVN_ERR(list_ctx->receiver(dirent_path, &dirent, list_ctx->receiver_baton, scratch_pool)); /* Reset buffered info. */ list_ctx->author = NULL; } return SVN_NO_ERROR; }