1251881Speter/* fs_skels.c --- conversion between fs native types and skeletons 2251881Speter * 3251881Speter * ==================================================================== 4251881Speter * Licensed to the Apache Software Foundation (ASF) under one 5251881Speter * or more contributor license agreements. See the NOTICE file 6251881Speter * distributed with this work for additional information 7251881Speter * regarding copyright ownership. The ASF licenses this file 8251881Speter * to you under the Apache License, Version 2.0 (the 9251881Speter * "License"); you may not use this file except in compliance 10251881Speter * with the License. You may obtain a copy of the License at 11251881Speter * 12251881Speter * http://www.apache.org/licenses/LICENSE-2.0 13251881Speter * 14251881Speter * Unless required by applicable law or agreed to in writing, 15251881Speter * software distributed under the License is distributed on an 16251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17251881Speter * KIND, either express or implied. See the License for the 18251881Speter * specific language governing permissions and limitations 19251881Speter * under the License. 20251881Speter * ==================================================================== 21251881Speter */ 22251881Speter 23251881Speter#include <string.h> 24251881Speter 25251881Speter#include <apr_md5.h> 26251881Speter#include <apr_sha1.h> 27251881Speter 28251881Speter#include "svn_error.h" 29251881Speter#include "svn_string.h" 30251881Speter#include "svn_types.h" 31251881Speter#include "svn_time.h" 32251881Speter 33251881Speter#include "private/svn_skel.h" 34251881Speter#include "private/svn_dep_compat.h" 35251881Speter#include "private/svn_subr_private.h" 36251881Speter 37251881Speter#include "svn_checksum.h" 38251881Speter#include "fs_skels.h" 39251881Speter#include "../id.h" 40251881Speter 41251881Speter 42251881Speterstatic svn_error_t * 43251881Speterskel_err(const char *skel_type) 44251881Speter{ 45251881Speter return svn_error_createf(SVN_ERR_FS_MALFORMED_SKEL, NULL, 46251881Speter "Malformed%s%s skeleton", 47251881Speter skel_type ? " " : "", 48251881Speter skel_type ? skel_type : ""); 49251881Speter} 50251881Speter 51251881Speter 52251881Speter 53251881Speter/*** Validity Checking ***/ 54251881Speter 55251881Speterstatic svn_boolean_t 56251881Speteris_valid_checksum_skel(svn_skel_t *skel) 57251881Speter{ 58251881Speter if (svn_skel__list_length(skel) != 2) 59251881Speter return FALSE; 60251881Speter 61251881Speter if (svn_skel__matches_atom(skel->children, "md5") 62251881Speter && skel->children->next->is_atom) 63251881Speter return TRUE; 64251881Speter 65251881Speter if (svn_skel__matches_atom(skel->children, "sha1") 66251881Speter && skel->children->next->is_atom) 67251881Speter return TRUE; 68251881Speter 69251881Speter return FALSE; 70251881Speter} 71251881Speter 72251881Speter 73251881Speterstatic svn_boolean_t 74251881Speteris_valid_revision_skel(svn_skel_t *skel) 75251881Speter{ 76251881Speter int len = svn_skel__list_length(skel); 77251881Speter 78251881Speter if ((len == 2) 79251881Speter && svn_skel__matches_atom(skel->children, "revision") 80251881Speter && skel->children->next->is_atom) 81251881Speter return TRUE; 82251881Speter 83251881Speter return FALSE; 84251881Speter} 85251881Speter 86251881Speter 87251881Speterstatic svn_boolean_t 88251881Speteris_valid_transaction_skel(svn_skel_t *skel, transaction_kind_t *kind) 89251881Speter{ 90251881Speter int len = svn_skel__list_length(skel); 91251881Speter 92251881Speter if (len != 5) 93251881Speter return FALSE; 94251881Speter 95251881Speter /* Determine (and verify) the kind. */ 96251881Speter if (svn_skel__matches_atom(skel->children, "transaction")) 97251881Speter *kind = transaction_kind_normal; 98251881Speter else if (svn_skel__matches_atom(skel->children, "committed")) 99251881Speter *kind = transaction_kind_committed; 100251881Speter else if (svn_skel__matches_atom(skel->children, "dead")) 101251881Speter *kind = transaction_kind_dead; 102251881Speter else 103251881Speter return FALSE; 104251881Speter 105251881Speter if (skel->children->next->is_atom 106251881Speter && skel->children->next->next->is_atom 107251881Speter && (! skel->children->next->next->next->is_atom) 108251881Speter && (! skel->children->next->next->next->next->is_atom)) 109251881Speter return TRUE; 110251881Speter 111251881Speter return FALSE; 112251881Speter} 113251881Speter 114251881Speter 115251881Speterstatic svn_boolean_t 116251881Speteris_valid_rep_delta_chunk_skel(svn_skel_t *skel) 117251881Speter{ 118251881Speter int len; 119251881Speter svn_skel_t *window; 120251881Speter svn_skel_t *diff; 121251881Speter 122251881Speter /* check the delta skel. */ 123251881Speter if ((svn_skel__list_length(skel) != 2) 124251881Speter || (! skel->children->is_atom)) 125251881Speter return FALSE; 126251881Speter 127251881Speter /* check the window. */ 128251881Speter window = skel->children->next; 129251881Speter len = svn_skel__list_length(window); 130251881Speter if ((len < 3) || (len > 4)) 131251881Speter return FALSE; 132251881Speter if (! ((! window->children->is_atom) 133251881Speter && (window->children->next->is_atom) 134251881Speter && (window->children->next->next->is_atom))) 135251881Speter return FALSE; 136251881Speter if ((len == 4) 137251881Speter && (! window->children->next->next->next->is_atom)) 138251881Speter return FALSE; 139251881Speter 140251881Speter /* check the diff. ### currently we support only svndiff version 141251881Speter 0 delta data. */ 142251881Speter diff = window->children; 143251881Speter if ((svn_skel__list_length(diff) == 3) 144251881Speter && (svn_skel__matches_atom(diff->children, "svndiff")) 145251881Speter && ((svn_skel__matches_atom(diff->children->next, "0")) 146251881Speter || (svn_skel__matches_atom(diff->children->next, "1"))) 147251881Speter && (diff->children->next->next->is_atom)) 148251881Speter return TRUE; 149251881Speter 150251881Speter return FALSE; 151251881Speter} 152251881Speter 153251881Speter 154251881Speterstatic svn_boolean_t 155251881Speteris_valid_representation_skel(svn_skel_t *skel) 156251881Speter{ 157251881Speter int len = svn_skel__list_length(skel); 158251881Speter svn_skel_t *header; 159251881Speter int header_len; 160251881Speter 161251881Speter /* the rep has at least two items in it, a HEADER list, and at least 162251881Speter one piece of kind-specific data. */ 163251881Speter if (len < 2) 164251881Speter return FALSE; 165251881Speter 166251881Speter /* check the header. it must have KIND and TXN atoms, and 167251881Speter optionally 1 or 2 checksums (which is a list form). */ 168251881Speter header = skel->children; 169251881Speter header_len = svn_skel__list_length(header); 170251881Speter if (! (((header_len == 2) /* 2 means old repository, checksum absent */ 171251881Speter && (header->children->is_atom) 172251881Speter && (header->children->next->is_atom)) 173251881Speter || ((header_len == 3) /* 3 means md5 checksum present */ 174251881Speter && (header->children->is_atom) 175251881Speter && (header->children->next->is_atom) 176251881Speter && (is_valid_checksum_skel(header->children->next->next))) 177251881Speter || ((header_len == 4) /* 3 means md5 and sha1 checksums present */ 178251881Speter && (header->children->is_atom) 179251881Speter && (header->children->next->is_atom) 180251881Speter && (is_valid_checksum_skel(header->children->next->next)) 181251881Speter && (is_valid_checksum_skel(header->children->next->next->next))))) 182251881Speter return FALSE; 183251881Speter 184251881Speter /* check for fulltext rep. */ 185251881Speter if ((len == 2) 186251881Speter && (svn_skel__matches_atom(header->children, "fulltext"))) 187251881Speter return TRUE; 188251881Speter 189251881Speter /* check for delta rep. */ 190251881Speter if ((len >= 2) 191251881Speter && (svn_skel__matches_atom(header->children, "delta"))) 192251881Speter { 193251881Speter /* it's a delta rep. check the validity. */ 194251881Speter svn_skel_t *chunk = skel->children->next; 195251881Speter 196251881Speter /* loop over chunks, checking each one. */ 197251881Speter while (chunk) 198251881Speter { 199251881Speter if (! is_valid_rep_delta_chunk_skel(chunk)) 200251881Speter return FALSE; 201251881Speter chunk = chunk->next; 202251881Speter } 203251881Speter 204251881Speter /* all good on this delta rep. */ 205251881Speter return TRUE; 206251881Speter } 207251881Speter 208251881Speter return FALSE; 209251881Speter} 210251881Speter 211251881Speter 212251881Speterstatic svn_boolean_t 213251881Speteris_valid_node_revision_header_skel(svn_skel_t *skel, svn_skel_t **kind_p) 214251881Speter{ 215251881Speter int len = svn_skel__list_length(skel); 216251881Speter 217251881Speter if (len < 2) 218251881Speter return FALSE; 219251881Speter 220251881Speter /* set the *KIND_P pointer. */ 221251881Speter *kind_p = skel->children; 222251881Speter 223251881Speter /* check for valid lengths. */ 224251881Speter if (! ((len == 2) || (len == 3) || (len == 4) || (len == 6))) 225251881Speter return FALSE; 226251881Speter 227251881Speter /* got mergeinfo stuff? */ 228251881Speter if ((len > 4) 229251881Speter && (! (skel->children->next->next->next->next->is_atom 230251881Speter && skel->children->next->next->next->next->next->is_atom))) 231251881Speter return FALSE; 232251881Speter 233251881Speter /* got predecessor count? */ 234251881Speter if ((len > 3) 235251881Speter && (! skel->children->next->next->next->is_atom)) 236251881Speter return FALSE; 237251881Speter 238251881Speter /* got predecessor? */ 239251881Speter if ((len > 2) 240251881Speter && (! skel->children->next->next->is_atom)) 241251881Speter return FALSE; 242251881Speter 243251881Speter /* got the basics? */ 244251881Speter if (! (skel->children->is_atom 245251881Speter && skel->children->next->is_atom 246251881Speter && (skel->children->next->data[0] == '/'))) 247251881Speter return FALSE; 248251881Speter 249251881Speter return TRUE; 250251881Speter} 251251881Speter 252251881Speter 253251881Speterstatic svn_boolean_t 254251881Speteris_valid_node_revision_skel(svn_skel_t *skel) 255251881Speter{ 256251881Speter int len = svn_skel__list_length(skel); 257251881Speter svn_skel_t *header = skel->children; 258251881Speter svn_skel_t *kind; 259251881Speter 260251881Speter if (len < 1) 261251881Speter return FALSE; 262251881Speter 263251881Speter if (! is_valid_node_revision_header_skel(header, &kind)) 264251881Speter return FALSE; 265251881Speter 266251881Speter if (svn_skel__matches_atom(kind, "dir")) 267251881Speter { 268251881Speter if (! ((len == 3) 269251881Speter && header->next->is_atom 270251881Speter && header->next->next->is_atom)) 271251881Speter return FALSE; 272251881Speter } 273251881Speter else if (svn_skel__matches_atom(kind, "file")) 274251881Speter { 275251881Speter if (len < 3) 276251881Speter return FALSE; 277251881Speter 278251881Speter if (! header->next->is_atom) 279251881Speter return FALSE; 280251881Speter 281251881Speter /* As of SVN_FS_BASE__MIN_REP_SHARING_FORMAT version, the 282251881Speter DATA-KEY slot can be a 2-tuple. */ 283251881Speter if (! header->next->next->is_atom) 284251881Speter { 285251881Speter if (! ((svn_skel__list_length(header->next->next) == 2) 286251881Speter && header->next->next->children->is_atom 287251881Speter && header->next->next->children->len 288251881Speter && header->next->next->children->next->is_atom 289251881Speter && header->next->next->children->next->len)) 290251881Speter return FALSE; 291251881Speter } 292251881Speter 293251881Speter if ((len > 3) && (! header->next->next->next->is_atom)) 294251881Speter return FALSE; 295251881Speter 296251881Speter if (len > 4) 297251881Speter return FALSE; 298251881Speter } 299251881Speter 300251881Speter return TRUE; 301251881Speter} 302251881Speter 303251881Speter 304251881Speterstatic svn_boolean_t 305251881Speteris_valid_copy_skel(svn_skel_t *skel) 306251881Speter{ 307251881Speter return ((svn_skel__list_length(skel) == 4) 308251881Speter && (svn_skel__matches_atom(skel->children, "copy") 309251881Speter || svn_skel__matches_atom(skel->children, "soft-copy")) 310251881Speter && skel->children->next->is_atom 311251881Speter && skel->children->next->next->is_atom 312251881Speter && skel->children->next->next->next->is_atom); 313251881Speter} 314251881Speter 315251881Speter 316251881Speterstatic svn_boolean_t 317251881Speteris_valid_change_skel(svn_skel_t *skel, svn_fs_path_change_kind_t *kind) 318251881Speter{ 319251881Speter if ((svn_skel__list_length(skel) == 6) 320251881Speter && svn_skel__matches_atom(skel->children, "change") 321251881Speter && skel->children->next->is_atom 322251881Speter && skel->children->next->next->is_atom 323251881Speter && skel->children->next->next->next->is_atom 324251881Speter && skel->children->next->next->next->next->is_atom 325251881Speter && skel->children->next->next->next->next->next->is_atom) 326251881Speter { 327251881Speter svn_skel_t *kind_skel = skel->children->next->next->next; 328251881Speter 329251881Speter /* check the kind (and return it) */ 330251881Speter if (svn_skel__matches_atom(kind_skel, "reset")) 331251881Speter { 332251881Speter if (kind) 333251881Speter *kind = svn_fs_path_change_reset; 334251881Speter return TRUE; 335251881Speter } 336251881Speter if (svn_skel__matches_atom(kind_skel, "add")) 337251881Speter { 338251881Speter if (kind) 339251881Speter *kind = svn_fs_path_change_add; 340251881Speter return TRUE; 341251881Speter } 342251881Speter if (svn_skel__matches_atom(kind_skel, "delete")) 343251881Speter { 344251881Speter if (kind) 345251881Speter *kind = svn_fs_path_change_delete; 346251881Speter return TRUE; 347251881Speter } 348251881Speter if (svn_skel__matches_atom(kind_skel, "replace")) 349251881Speter { 350251881Speter if (kind) 351251881Speter *kind = svn_fs_path_change_replace; 352251881Speter return TRUE; 353251881Speter } 354251881Speter if (svn_skel__matches_atom(kind_skel, "modify")) 355251881Speter { 356251881Speter if (kind) 357251881Speter *kind = svn_fs_path_change_modify; 358251881Speter return TRUE; 359251881Speter } 360251881Speter } 361251881Speter return FALSE; 362251881Speter} 363251881Speter 364251881Speter 365251881Speterstatic svn_boolean_t 366251881Speteris_valid_lock_skel(svn_skel_t *skel) 367251881Speter{ 368251881Speter if ((svn_skel__list_length(skel) == 8) 369251881Speter && svn_skel__matches_atom(skel->children, "lock") 370251881Speter && skel->children->next->is_atom 371251881Speter && skel->children->next->next->is_atom 372251881Speter && skel->children->next->next->next->is_atom 373251881Speter && skel->children->next->next->next->next->is_atom 374251881Speter && skel->children->next->next->next->next->next->is_atom 375251881Speter && skel->children->next->next->next->next->next->next->is_atom 376251881Speter && skel->children->next->next->next->next->next->next->next->is_atom) 377251881Speter return TRUE; 378251881Speter 379251881Speter return FALSE; 380251881Speter} 381251881Speter 382251881Speter 383251881Speter 384251881Speter/*** Parsing (conversion from skeleton to native FS type) ***/ 385251881Speter 386251881Spetersvn_error_t * 387251881Spetersvn_fs_base__parse_revision_skel(revision_t **revision_p, 388251881Speter svn_skel_t *skel, 389251881Speter apr_pool_t *pool) 390251881Speter{ 391251881Speter revision_t *revision; 392251881Speter 393251881Speter /* Validate the skel. */ 394251881Speter if (! is_valid_revision_skel(skel)) 395251881Speter return skel_err("revision"); 396251881Speter 397251881Speter /* Create the returned structure */ 398251881Speter revision = apr_pcalloc(pool, sizeof(*revision)); 399251881Speter revision->txn_id = apr_pstrmemdup(pool, skel->children->next->data, 400251881Speter skel->children->next->len); 401251881Speter 402251881Speter /* Return the structure. */ 403251881Speter *revision_p = revision; 404251881Speter return SVN_NO_ERROR; 405251881Speter} 406251881Speter 407251881Speter 408251881Spetersvn_error_t * 409251881Spetersvn_fs_base__parse_transaction_skel(transaction_t **transaction_p, 410251881Speter svn_skel_t *skel, 411251881Speter apr_pool_t *pool) 412251881Speter{ 413251881Speter transaction_t *transaction; 414251881Speter transaction_kind_t kind; 415251881Speter svn_skel_t *root_id, *base_id_or_rev, *proplist, *copies; 416251881Speter int len; 417251881Speter 418251881Speter /* Validate the skel. */ 419251881Speter if (! is_valid_transaction_skel(skel, &kind)) 420251881Speter return skel_err("transaction"); 421251881Speter 422251881Speter root_id = skel->children->next; 423251881Speter base_id_or_rev = skel->children->next->next; 424251881Speter proplist = skel->children->next->next->next; 425251881Speter copies = skel->children->next->next->next->next; 426251881Speter 427251881Speter /* Create the returned structure */ 428251881Speter transaction = apr_pcalloc(pool, sizeof(*transaction)); 429251881Speter 430251881Speter /* KIND */ 431251881Speter transaction->kind = kind; 432251881Speter 433251881Speter /* REVISION or BASE-ID */ 434251881Speter if (kind == transaction_kind_committed) 435251881Speter { 436251881Speter /* Committed transactions have a revision number... */ 437251881Speter transaction->base_id = NULL; 438251881Speter transaction->revision = 439251881Speter SVN_STR_TO_REV(apr_pstrmemdup(pool, base_id_or_rev->data, 440251881Speter base_id_or_rev->len)); 441251881Speter if (! SVN_IS_VALID_REVNUM(transaction->revision)) 442251881Speter return skel_err("transaction"); 443251881Speter 444251881Speter } 445251881Speter else 446251881Speter { 447251881Speter /* ...where unfinished transactions have a base node-revision-id. */ 448251881Speter transaction->revision = SVN_INVALID_REVNUM; 449251881Speter transaction->base_id = svn_fs_base__id_parse(base_id_or_rev->data, 450251881Speter base_id_or_rev->len, pool); 451251881Speter } 452251881Speter 453251881Speter /* ROOT-ID */ 454251881Speter transaction->root_id = svn_fs_base__id_parse(root_id->data, 455251881Speter root_id->len, pool); 456251881Speter 457251881Speter /* PROPLIST */ 458251881Speter SVN_ERR(svn_skel__parse_proplist(&(transaction->proplist), 459251881Speter proplist, pool)); 460251881Speter 461251881Speter /* COPIES */ 462251881Speter if ((len = svn_skel__list_length(copies))) 463251881Speter { 464251881Speter const char *copy_id; 465251881Speter apr_array_header_t *txncopies; 466251881Speter svn_skel_t *cpy = copies->children; 467251881Speter 468251881Speter txncopies = apr_array_make(pool, len, sizeof(copy_id)); 469251881Speter while (cpy) 470251881Speter { 471251881Speter copy_id = apr_pstrmemdup(pool, cpy->data, cpy->len); 472251881Speter APR_ARRAY_PUSH(txncopies, const char *) = copy_id; 473251881Speter cpy = cpy->next; 474251881Speter } 475251881Speter transaction->copies = txncopies; 476251881Speter } 477251881Speter 478251881Speter /* Return the structure. */ 479251881Speter *transaction_p = transaction; 480251881Speter return SVN_NO_ERROR; 481251881Speter} 482251881Speter 483251881Speter 484251881Spetersvn_error_t * 485251881Spetersvn_fs_base__parse_representation_skel(representation_t **rep_p, 486251881Speter svn_skel_t *skel, 487251881Speter apr_pool_t *pool) 488251881Speter{ 489251881Speter representation_t *rep; 490251881Speter svn_skel_t *header_skel; 491251881Speter 492251881Speter /* Validate the skel. */ 493251881Speter if (! is_valid_representation_skel(skel)) 494251881Speter return skel_err("representation"); 495251881Speter header_skel = skel->children; 496251881Speter 497251881Speter /* Create the returned structure */ 498251881Speter rep = apr_pcalloc(pool, sizeof(*rep)); 499251881Speter 500251881Speter /* KIND */ 501251881Speter if (svn_skel__matches_atom(header_skel->children, "fulltext")) 502251881Speter rep->kind = rep_kind_fulltext; 503251881Speter else 504251881Speter rep->kind = rep_kind_delta; 505251881Speter 506251881Speter /* TXN */ 507251881Speter rep->txn_id = apr_pstrmemdup(pool, header_skel->children->next->data, 508251881Speter header_skel->children->next->len); 509251881Speter 510251881Speter /* MD5 */ 511251881Speter if (header_skel->children->next->next) 512251881Speter { 513251881Speter svn_skel_t *checksum_skel = header_skel->children->next->next; 514251881Speter rep->md5_checksum = 515251881Speter svn_checksum__from_digest_md5((const unsigned char *) 516251881Speter (checksum_skel->children->next->data), 517251881Speter pool); 518251881Speter 519251881Speter /* SHA1 */ 520251881Speter if (header_skel->children->next->next->next) 521251881Speter { 522251881Speter checksum_skel = header_skel->children->next->next->next; 523251881Speter rep->sha1_checksum = 524251881Speter svn_checksum__from_digest_sha1( 525251881Speter (const unsigned char *)(checksum_skel->children->next->data), 526251881Speter pool); 527251881Speter } 528251881Speter } 529251881Speter 530251881Speter /* KIND-SPECIFIC stuff */ 531251881Speter if (rep->kind == rep_kind_fulltext) 532251881Speter { 533251881Speter /* "fulltext"-specific. */ 534251881Speter rep->contents.fulltext.string_key 535251881Speter = apr_pstrmemdup(pool, 536251881Speter skel->children->next->data, 537251881Speter skel->children->next->len); 538251881Speter } 539251881Speter else 540251881Speter { 541251881Speter /* "delta"-specific. */ 542251881Speter svn_skel_t *chunk_skel = skel->children->next; 543251881Speter rep_delta_chunk_t *chunk; 544251881Speter apr_array_header_t *chunks; 545251881Speter 546251881Speter /* Alloc the chunk array. */ 547251881Speter chunks = apr_array_make(pool, svn_skel__list_length(skel) - 1, 548251881Speter sizeof(chunk)); 549251881Speter 550251881Speter /* Process the chunks. */ 551251881Speter while (chunk_skel) 552251881Speter { 553251881Speter svn_skel_t *window_skel = chunk_skel->children->next; 554251881Speter svn_skel_t *diff_skel = window_skel->children; 555251881Speter apr_int64_t val; 556251881Speter apr_uint64_t uval; 557251881Speter const char *str; 558251881Speter 559251881Speter /* Allocate a chunk and its window */ 560251881Speter chunk = apr_palloc(pool, sizeof(*chunk)); 561251881Speter 562251881Speter /* Populate the window */ 563251881Speter str = apr_pstrmemdup(pool, diff_skel->children->next->data, 564251881Speter diff_skel->children->next->len); 565251881Speter SVN_ERR(svn_cstring_strtoui64(&uval, str, 0, 255, 10)); 566251881Speter chunk->version = (apr_byte_t)uval; 567251881Speter 568251881Speter chunk->string_key 569251881Speter = apr_pstrmemdup(pool, 570251881Speter diff_skel->children->next->next->data, 571251881Speter diff_skel->children->next->next->len); 572251881Speter 573251881Speter str = apr_pstrmemdup(pool, window_skel->children->next->data, 574251881Speter window_skel->children->next->len); 575251881Speter SVN_ERR(svn_cstring_strtoui64(&uval, str, 0, APR_SIZE_MAX, 10)); 576251881Speter chunk->size = (apr_size_t)uval; 577251881Speter 578251881Speter chunk->rep_key 579251881Speter = apr_pstrmemdup(pool, 580251881Speter window_skel->children->next->next->data, 581251881Speter window_skel->children->next->next->len); 582251881Speter 583251881Speter str = apr_pstrmemdup(pool, chunk_skel->children->data, 584251881Speter chunk_skel->children->len); 585251881Speter SVN_ERR(svn_cstring_strtoi64(&val, str, 0, APR_INT64_MAX, 10)); 586251881Speter chunk->offset = (svn_filesize_t)val; 587251881Speter 588251881Speter /* Add this chunk to the array. */ 589251881Speter APR_ARRAY_PUSH(chunks, rep_delta_chunk_t *) = chunk; 590251881Speter 591251881Speter /* Next... */ 592251881Speter chunk_skel = chunk_skel->next; 593251881Speter } 594251881Speter 595251881Speter /* Add the chunks array to the representation. */ 596251881Speter rep->contents.delta.chunks = chunks; 597251881Speter } 598251881Speter 599251881Speter /* Return the structure. */ 600251881Speter *rep_p = rep; 601251881Speter return SVN_NO_ERROR; 602251881Speter} 603251881Speter 604251881Speter 605251881Spetersvn_error_t * 606251881Spetersvn_fs_base__parse_node_revision_skel(node_revision_t **noderev_p, 607251881Speter svn_skel_t *skel, 608251881Speter apr_pool_t *pool) 609251881Speter{ 610251881Speter node_revision_t *noderev; 611251881Speter svn_skel_t *header_skel, *cur_skel; 612251881Speter 613251881Speter /* Validate the skel. */ 614251881Speter if (! is_valid_node_revision_skel(skel)) 615251881Speter return skel_err("node-revision"); 616251881Speter header_skel = skel->children; 617251881Speter 618251881Speter /* Create the returned structure */ 619251881Speter noderev = apr_pcalloc(pool, sizeof(*noderev)); 620251881Speter 621251881Speter /* KIND */ 622251881Speter if (svn_skel__matches_atom(header_skel->children, "dir")) 623251881Speter noderev->kind = svn_node_dir; 624251881Speter else 625251881Speter noderev->kind = svn_node_file; 626251881Speter 627251881Speter /* CREATED-PATH */ 628251881Speter noderev->created_path = apr_pstrmemdup(pool, 629251881Speter header_skel->children->next->data, 630251881Speter header_skel->children->next->len); 631251881Speter 632251881Speter /* PREDECESSOR-ID */ 633251881Speter if (header_skel->children->next->next) 634251881Speter { 635251881Speter cur_skel = header_skel->children->next->next; 636251881Speter if (cur_skel->len) 637251881Speter noderev->predecessor_id = svn_fs_base__id_parse(cur_skel->data, 638251881Speter cur_skel->len, pool); 639251881Speter 640251881Speter /* PREDECESSOR-COUNT */ 641251881Speter noderev->predecessor_count = -1; 642251881Speter if (cur_skel->next) 643251881Speter { 644251881Speter const char *str; 645251881Speter 646251881Speter cur_skel = cur_skel->next; 647251881Speter if (cur_skel->len) 648251881Speter { 649251881Speter str = apr_pstrmemdup(pool, cur_skel->data, cur_skel->len); 650251881Speter SVN_ERR(svn_cstring_atoi(&noderev->predecessor_count, str)); 651251881Speter } 652251881Speter 653251881Speter /* HAS-MERGEINFO and MERGEINFO-COUNT */ 654251881Speter if (cur_skel->next) 655251881Speter { 656251881Speter int val; 657251881Speter 658251881Speter cur_skel = cur_skel->next; 659251881Speter str = apr_pstrmemdup(pool, cur_skel->data, cur_skel->len); 660251881Speter SVN_ERR(svn_cstring_atoi(&val, str)); 661251881Speter noderev->has_mergeinfo = (val != 0); 662251881Speter 663251881Speter str = apr_pstrmemdup(pool, cur_skel->next->data, 664251881Speter cur_skel->next->len); 665251881Speter SVN_ERR(svn_cstring_atoi64(&noderev->mergeinfo_count, str)); 666251881Speter } 667251881Speter } 668251881Speter } 669251881Speter 670251881Speter /* PROP-KEY */ 671251881Speter if (skel->children->next->len) 672251881Speter noderev->prop_key = apr_pstrmemdup(pool, skel->children->next->data, 673251881Speter skel->children->next->len); 674251881Speter 675251881Speter /* DATA-KEY */ 676251881Speter if (skel->children->next->next->is_atom) 677251881Speter { 678251881Speter /* This is a real data rep key. */ 679251881Speter if (skel->children->next->next->len) 680251881Speter noderev->data_key = apr_pstrmemdup(pool, 681251881Speter skel->children->next->next->data, 682251881Speter skel->children->next->next->len); 683251881Speter noderev->data_key_uniquifier = NULL; 684251881Speter } 685251881Speter else 686251881Speter { 687251881Speter /* This is a 2-tuple with a data rep key and a uniquifier. */ 688251881Speter noderev->data_key = 689251881Speter apr_pstrmemdup(pool, 690251881Speter skel->children->next->next->children->data, 691251881Speter skel->children->next->next->children->len); 692251881Speter noderev->data_key_uniquifier = 693251881Speter apr_pstrmemdup(pool, 694251881Speter skel->children->next->next->children->next->data, 695251881Speter skel->children->next->next->children->next->len); 696251881Speter } 697251881Speter 698251881Speter /* EDIT-DATA-KEY (optional, files only) */ 699251881Speter if ((noderev->kind == svn_node_file) 700251881Speter && skel->children->next->next->next 701251881Speter && skel->children->next->next->next->len) 702251881Speter noderev->edit_key 703251881Speter = apr_pstrmemdup(pool, skel->children->next->next->next->data, 704251881Speter skel->children->next->next->next->len); 705251881Speter 706251881Speter /* Return the structure. */ 707251881Speter *noderev_p = noderev; 708251881Speter return SVN_NO_ERROR; 709251881Speter} 710251881Speter 711251881Speter 712251881Spetersvn_error_t * 713251881Spetersvn_fs_base__parse_copy_skel(copy_t **copy_p, 714251881Speter svn_skel_t *skel, 715251881Speter apr_pool_t *pool) 716251881Speter{ 717251881Speter copy_t *copy; 718251881Speter 719251881Speter /* Validate the skel. */ 720251881Speter if (! is_valid_copy_skel(skel)) 721251881Speter return skel_err("copy"); 722251881Speter 723251881Speter /* Create the returned structure */ 724251881Speter copy = apr_pcalloc(pool, sizeof(*copy)); 725251881Speter 726251881Speter /* KIND */ 727251881Speter if (svn_skel__matches_atom(skel->children, "soft-copy")) 728251881Speter copy->kind = copy_kind_soft; 729251881Speter else 730251881Speter copy->kind = copy_kind_real; 731251881Speter 732251881Speter /* SRC-PATH */ 733251881Speter copy->src_path = apr_pstrmemdup(pool, 734251881Speter skel->children->next->data, 735251881Speter skel->children->next->len); 736251881Speter 737251881Speter /* SRC-TXN-ID */ 738251881Speter copy->src_txn_id = apr_pstrmemdup(pool, 739251881Speter skel->children->next->next->data, 740251881Speter skel->children->next->next->len); 741251881Speter 742251881Speter /* DST-NODE-ID */ 743251881Speter copy->dst_noderev_id 744251881Speter = svn_fs_base__id_parse(skel->children->next->next->next->data, 745251881Speter skel->children->next->next->next->len, pool); 746251881Speter 747251881Speter /* Return the structure. */ 748251881Speter *copy_p = copy; 749251881Speter return SVN_NO_ERROR; 750251881Speter} 751251881Speter 752251881Speter 753251881Spetersvn_error_t * 754251881Spetersvn_fs_base__parse_entries_skel(apr_hash_t **entries_p, 755251881Speter svn_skel_t *skel, 756251881Speter apr_pool_t *pool) 757251881Speter{ 758251881Speter apr_hash_t *entries = NULL; 759251881Speter int len = svn_skel__list_length(skel); 760251881Speter svn_skel_t *elt; 761251881Speter 762251881Speter if (! (len >= 0)) 763251881Speter return skel_err("entries"); 764251881Speter 765251881Speter if (len > 0) 766251881Speter { 767251881Speter /* Else, allocate a hash and populate it. */ 768251881Speter entries = apr_hash_make(pool); 769251881Speter 770251881Speter /* Check entries are well-formed as we go along. */ 771251881Speter for (elt = skel->children; elt; elt = elt->next) 772251881Speter { 773251881Speter const char *name; 774251881Speter svn_fs_id_t *id; 775251881Speter 776251881Speter /* ENTRY must be a list of two elements. */ 777251881Speter if (svn_skel__list_length(elt) != 2) 778251881Speter return skel_err("entries"); 779251881Speter 780251881Speter /* Get the entry's name and ID. */ 781251881Speter name = apr_pstrmemdup(pool, elt->children->data, 782251881Speter elt->children->len); 783251881Speter id = svn_fs_base__id_parse(elt->children->next->data, 784251881Speter elt->children->next->len, pool); 785251881Speter 786251881Speter /* Add the entry to the hash. */ 787251881Speter apr_hash_set(entries, name, elt->children->len, id); 788251881Speter } 789251881Speter } 790251881Speter 791251881Speter /* Return the structure. */ 792251881Speter *entries_p = entries; 793251881Speter return SVN_NO_ERROR; 794251881Speter} 795251881Speter 796251881Speter 797251881Spetersvn_error_t * 798251881Spetersvn_fs_base__parse_change_skel(change_t **change_p, 799251881Speter svn_skel_t *skel, 800251881Speter apr_pool_t *pool) 801251881Speter{ 802251881Speter change_t *change; 803251881Speter svn_fs_path_change_kind_t kind; 804251881Speter 805251881Speter /* Validate the skel. */ 806251881Speter if (! is_valid_change_skel(skel, &kind)) 807251881Speter return skel_err("change"); 808251881Speter 809251881Speter /* Create the returned structure */ 810251881Speter change = apr_pcalloc(pool, sizeof(*change)); 811251881Speter 812251881Speter /* PATH */ 813251881Speter change->path = apr_pstrmemdup(pool, skel->children->next->data, 814251881Speter skel->children->next->len); 815251881Speter 816251881Speter /* NODE-REV-ID */ 817251881Speter if (skel->children->next->next->len) 818251881Speter change->noderev_id = svn_fs_base__id_parse 819251881Speter (skel->children->next->next->data, skel->children->next->next->len, 820251881Speter pool); 821251881Speter 822251881Speter /* KIND */ 823251881Speter change->kind = kind; 824251881Speter 825251881Speter /* TEXT-MOD */ 826251881Speter if (skel->children->next->next->next->next->len) 827251881Speter change->text_mod = TRUE; 828251881Speter 829251881Speter /* PROP-MOD */ 830251881Speter if (skel->children->next->next->next->next->next->len) 831251881Speter change->prop_mod = TRUE; 832251881Speter 833251881Speter /* Return the structure. */ 834251881Speter *change_p = change; 835251881Speter return SVN_NO_ERROR; 836251881Speter} 837251881Speter 838251881Speter 839251881Spetersvn_error_t * 840251881Spetersvn_fs_base__parse_lock_skel(svn_lock_t **lock_p, 841251881Speter svn_skel_t *skel, 842251881Speter apr_pool_t *pool) 843251881Speter{ 844251881Speter svn_lock_t *lock; 845251881Speter const char *timestr; 846251881Speter 847251881Speter /* Validate the skel. */ 848251881Speter if (! is_valid_lock_skel(skel)) 849251881Speter return skel_err("lock"); 850251881Speter 851251881Speter /* Create the returned structure */ 852251881Speter lock = apr_pcalloc(pool, sizeof(*lock)); 853251881Speter 854251881Speter /* PATH */ 855251881Speter lock->path = apr_pstrmemdup(pool, skel->children->next->data, 856251881Speter skel->children->next->len); 857251881Speter 858251881Speter /* LOCK-TOKEN */ 859251881Speter lock->token = apr_pstrmemdup(pool, 860251881Speter skel->children->next->next->data, 861251881Speter skel->children->next->next->len); 862251881Speter 863251881Speter /* OWNER */ 864251881Speter lock->owner = apr_pstrmemdup(pool, 865251881Speter skel->children->next->next->next->data, 866251881Speter skel->children->next->next->next->len); 867251881Speter 868251881Speter /* COMMENT (could be just an empty atom) */ 869251881Speter if (skel->children->next->next->next->next->len) 870251881Speter lock->comment = 871251881Speter apr_pstrmemdup(pool, 872251881Speter skel->children->next->next->next->next->data, 873251881Speter skel->children->next->next->next->next->len); 874251881Speter 875251881Speter /* XML_P */ 876251881Speter if (svn_skel__matches_atom 877251881Speter (skel->children->next->next->next->next->next, "1")) 878251881Speter lock->is_dav_comment = TRUE; 879251881Speter else 880251881Speter lock->is_dav_comment = FALSE; 881251881Speter 882251881Speter /* CREATION-DATE */ 883251881Speter timestr = apr_pstrmemdup 884251881Speter (pool, 885251881Speter skel->children->next->next->next->next->next->next->data, 886251881Speter skel->children->next->next->next->next->next->next->len); 887251881Speter SVN_ERR(svn_time_from_cstring(&(lock->creation_date), 888251881Speter timestr, pool)); 889251881Speter 890251881Speter /* EXPIRATION-DATE (could be just an empty atom) */ 891251881Speter if (skel->children->next->next->next->next->next->next->next->len) 892251881Speter { 893251881Speter timestr = 894251881Speter apr_pstrmemdup 895251881Speter (pool, 896251881Speter skel->children->next->next->next->next->next->next->next->data, 897251881Speter skel->children->next->next->next->next->next->next->next->len); 898251881Speter SVN_ERR(svn_time_from_cstring(&(lock->expiration_date), 899251881Speter timestr, pool)); 900251881Speter } 901251881Speter 902251881Speter /* Return the structure. */ 903251881Speter *lock_p = lock; 904251881Speter return SVN_NO_ERROR; 905251881Speter} 906251881Speter 907251881Speter 908251881Speter 909251881Speter/*** Unparsing (conversion from native FS type to skeleton) ***/ 910251881Speter 911251881Spetersvn_error_t * 912251881Spetersvn_fs_base__unparse_revision_skel(svn_skel_t **skel_p, 913251881Speter const revision_t *revision, 914251881Speter apr_pool_t *pool) 915251881Speter{ 916251881Speter svn_skel_t *skel; 917251881Speter 918251881Speter /* Create the skel. */ 919251881Speter skel = svn_skel__make_empty_list(pool); 920251881Speter 921251881Speter /* TXN_ID */ 922251881Speter svn_skel__prepend(svn_skel__str_atom(revision->txn_id, pool), skel); 923251881Speter 924251881Speter /* "revision" */ 925251881Speter svn_skel__prepend(svn_skel__str_atom("revision", pool), skel); 926251881Speter 927251881Speter /* Validate and return the skel. */ 928251881Speter if (! is_valid_revision_skel(skel)) 929251881Speter return skel_err("revision"); 930251881Speter *skel_p = skel; 931251881Speter return SVN_NO_ERROR; 932251881Speter} 933251881Speter 934251881Speter 935251881Spetersvn_error_t * 936251881Spetersvn_fs_base__unparse_transaction_skel(svn_skel_t **skel_p, 937251881Speter const transaction_t *transaction, 938251881Speter apr_pool_t *pool) 939251881Speter{ 940251881Speter svn_skel_t *skel; 941251881Speter svn_skel_t *proplist_skel, *copies_skel, *header_skel; 942251881Speter svn_string_t *id_str; 943251881Speter transaction_kind_t kind; 944251881Speter 945251881Speter /* Create the skel. */ 946251881Speter skel = svn_skel__make_empty_list(pool); 947251881Speter 948251881Speter switch (transaction->kind) 949251881Speter { 950251881Speter case transaction_kind_committed: 951251881Speter header_skel = svn_skel__str_atom("committed", pool); 952251881Speter if ((transaction->base_id) 953251881Speter || (! SVN_IS_VALID_REVNUM(transaction->revision))) 954251881Speter return skel_err("transaction"); 955251881Speter break; 956251881Speter case transaction_kind_dead: 957251881Speter header_skel = svn_skel__str_atom("dead", pool); 958251881Speter if ((! transaction->base_id) 959251881Speter || (SVN_IS_VALID_REVNUM(transaction->revision))) 960251881Speter return skel_err("transaction"); 961251881Speter break; 962251881Speter case transaction_kind_normal: 963251881Speter header_skel = svn_skel__str_atom("transaction", pool); 964251881Speter if ((! transaction->base_id) 965251881Speter || (SVN_IS_VALID_REVNUM(transaction->revision))) 966251881Speter return skel_err("transaction"); 967251881Speter break; 968251881Speter default: 969251881Speter return skel_err("transaction"); 970251881Speter } 971251881Speter 972251881Speter 973251881Speter /* COPIES */ 974251881Speter copies_skel = svn_skel__make_empty_list(pool); 975251881Speter if (transaction->copies && transaction->copies->nelts) 976251881Speter { 977251881Speter int i; 978251881Speter for (i = transaction->copies->nelts - 1; i >= 0; i--) 979251881Speter { 980251881Speter svn_skel__prepend(svn_skel__str_atom( 981251881Speter APR_ARRAY_IDX(transaction->copies, i, 982251881Speter const char *), 983251881Speter pool), 984251881Speter copies_skel); 985251881Speter } 986251881Speter } 987251881Speter svn_skel__prepend(copies_skel, skel); 988251881Speter 989251881Speter /* PROPLIST */ 990251881Speter SVN_ERR(svn_skel__unparse_proplist(&proplist_skel, 991251881Speter transaction->proplist, pool)); 992251881Speter svn_skel__prepend(proplist_skel, skel); 993251881Speter 994251881Speter /* REVISION or BASE-ID */ 995251881Speter if (transaction->kind == transaction_kind_committed) 996251881Speter { 997251881Speter /* Committed transactions have a revision number... */ 998251881Speter svn_skel__prepend(svn_skel__str_atom(apr_psprintf(pool, "%ld", 999251881Speter transaction->revision), 1000251881Speter pool), skel); 1001251881Speter } 1002251881Speter else 1003251881Speter { 1004251881Speter /* ...where other transactions have a base node revision ID. */ 1005251881Speter id_str = svn_fs_base__id_unparse(transaction->base_id, pool); 1006251881Speter svn_skel__prepend(svn_skel__mem_atom(id_str->data, id_str->len, pool), 1007251881Speter skel); 1008251881Speter } 1009251881Speter 1010251881Speter /* ROOT-ID */ 1011251881Speter id_str = svn_fs_base__id_unparse(transaction->root_id, pool); 1012251881Speter svn_skel__prepend(svn_skel__mem_atom(id_str->data, id_str->len, pool), skel); 1013251881Speter 1014251881Speter /* KIND (see above) */ 1015251881Speter svn_skel__prepend(header_skel, skel); 1016251881Speter 1017251881Speter /* Validate and return the skel. */ 1018251881Speter if (! is_valid_transaction_skel(skel, &kind)) 1019251881Speter return skel_err("transaction"); 1020251881Speter if (kind != transaction->kind) 1021251881Speter return skel_err("transaction"); 1022251881Speter *skel_p = skel; 1023251881Speter return SVN_NO_ERROR; 1024251881Speter} 1025251881Speter 1026251881Speter 1027251881Speter/* Construct a skel representing CHECKSUM, allocated in POOL, and prepend 1028251881Speter * it onto the existing skel SKEL. */ 1029251881Speterstatic svn_error_t * 1030251881Speterprepend_checksum(svn_skel_t *skel, 1031251881Speter svn_checksum_t *checksum, 1032251881Speter apr_pool_t *pool) 1033251881Speter{ 1034251881Speter svn_skel_t *checksum_skel = svn_skel__make_empty_list(pool); 1035251881Speter 1036251881Speter switch (checksum->kind) 1037251881Speter { 1038251881Speter case svn_checksum_md5: 1039251881Speter svn_skel__prepend(svn_skel__mem_atom(checksum->digest, 1040251881Speter APR_MD5_DIGESTSIZE, pool), 1041251881Speter checksum_skel); 1042251881Speter svn_skel__prepend(svn_skel__str_atom("md5", pool), checksum_skel); 1043251881Speter break; 1044251881Speter 1045251881Speter case svn_checksum_sha1: 1046251881Speter svn_skel__prepend(svn_skel__mem_atom(checksum->digest, 1047251881Speter APR_SHA1_DIGESTSIZE, pool), 1048251881Speter checksum_skel); 1049251881Speter svn_skel__prepend(svn_skel__str_atom("sha1", pool), checksum_skel); 1050251881Speter break; 1051251881Speter 1052251881Speter default: 1053251881Speter return skel_err("checksum"); 1054251881Speter } 1055251881Speter svn_skel__prepend(checksum_skel, skel); 1056251881Speter 1057251881Speter return SVN_NO_ERROR; 1058251881Speter} 1059251881Speter 1060251881Speter 1061251881Spetersvn_error_t * 1062251881Spetersvn_fs_base__unparse_representation_skel(svn_skel_t **skel_p, 1063251881Speter const representation_t *rep, 1064251881Speter int format, 1065251881Speter apr_pool_t *pool) 1066251881Speter{ 1067251881Speter svn_skel_t *skel = svn_skel__make_empty_list(pool); 1068251881Speter svn_skel_t *header_skel = svn_skel__make_empty_list(pool); 1069251881Speter 1070251881Speter /** Some parts of the header are common to all representations; do 1071251881Speter those parts first. **/ 1072251881Speter 1073251881Speter /* SHA1 */ 1074251881Speter if ((format >= SVN_FS_BASE__MIN_REP_SHARING_FORMAT) && rep->sha1_checksum) 1075251881Speter SVN_ERR(prepend_checksum(header_skel, rep->sha1_checksum, pool)); 1076251881Speter 1077251881Speter /* MD5 */ 1078251881Speter { 1079251881Speter svn_checksum_t *md5_checksum = rep->md5_checksum; 1080251881Speter if (! md5_checksum) 1081251881Speter md5_checksum = svn_checksum_create(svn_checksum_md5, pool); 1082251881Speter SVN_ERR(prepend_checksum(header_skel, md5_checksum, pool)); 1083251881Speter } 1084251881Speter 1085251881Speter /* TXN */ 1086251881Speter if (rep->txn_id) 1087251881Speter svn_skel__prepend(svn_skel__str_atom(rep->txn_id, pool), header_skel); 1088251881Speter else 1089251881Speter svn_skel__prepend(svn_skel__mem_atom(NULL, 0, pool), header_skel); 1090251881Speter 1091251881Speter /** Do the kind-specific stuff. **/ 1092251881Speter 1093251881Speter if (rep->kind == rep_kind_fulltext) 1094251881Speter { 1095251881Speter /*** Fulltext Representation. ***/ 1096251881Speter 1097251881Speter /* STRING-KEY */ 1098251881Speter if ((! rep->contents.fulltext.string_key) 1099251881Speter || (! *rep->contents.fulltext.string_key)) 1100251881Speter svn_skel__prepend(svn_skel__mem_atom(NULL, 0, pool), skel); 1101251881Speter else 1102251881Speter svn_skel__prepend(svn_skel__str_atom(rep->contents.fulltext.string_key, 1103251881Speter pool), skel); 1104251881Speter 1105251881Speter /* "fulltext" */ 1106251881Speter svn_skel__prepend(svn_skel__str_atom("fulltext", pool), header_skel); 1107251881Speter 1108251881Speter /* header */ 1109251881Speter svn_skel__prepend(header_skel, skel); 1110251881Speter } 1111251881Speter else if (rep->kind == rep_kind_delta) 1112251881Speter { 1113251881Speter /*** Delta Representation. ***/ 1114251881Speter int i; 1115251881Speter apr_array_header_t *chunks = rep->contents.delta.chunks; 1116251881Speter 1117251881Speter /* Loop backwards through the windows, creating and prepending skels. */ 1118251881Speter for (i = chunks->nelts; i > 0; i--) 1119251881Speter { 1120251881Speter svn_skel_t *window_skel = svn_skel__make_empty_list(pool); 1121251881Speter svn_skel_t *chunk_skel = svn_skel__make_empty_list(pool); 1122251881Speter svn_skel_t *diff_skel = svn_skel__make_empty_list(pool); 1123251881Speter const char *size_str, *offset_str, *version_str; 1124251881Speter rep_delta_chunk_t *chunk = APR_ARRAY_IDX(chunks, i - 1, 1125251881Speter rep_delta_chunk_t *); 1126251881Speter 1127251881Speter /* OFFSET */ 1128251881Speter offset_str = apr_psprintf(pool, "%" SVN_FILESIZE_T_FMT, 1129251881Speter chunk->offset); 1130251881Speter 1131251881Speter /* SIZE */ 1132251881Speter size_str = apr_psprintf(pool, "%" APR_SIZE_T_FMT, chunk->size); 1133251881Speter 1134251881Speter /* VERSION */ 1135251881Speter version_str = apr_psprintf(pool, "%d", chunk->version); 1136251881Speter 1137251881Speter /* DIFF */ 1138251881Speter if ((! chunk->string_key) || (! *chunk->string_key)) 1139251881Speter svn_skel__prepend(svn_skel__mem_atom(NULL, 0, pool), diff_skel); 1140251881Speter else 1141251881Speter svn_skel__prepend(svn_skel__str_atom(chunk->string_key, pool), 1142251881Speter diff_skel); 1143251881Speter svn_skel__prepend(svn_skel__str_atom(version_str, pool), diff_skel); 1144251881Speter svn_skel__prepend(svn_skel__str_atom("svndiff", pool), diff_skel); 1145251881Speter 1146251881Speter /* REP-KEY */ 1147251881Speter if ((! chunk->rep_key) || (! *(chunk->rep_key))) 1148251881Speter svn_skel__prepend(svn_skel__mem_atom(NULL, 0, pool), 1149251881Speter window_skel); 1150251881Speter else 1151251881Speter svn_skel__prepend(svn_skel__str_atom(chunk->rep_key, pool), 1152251881Speter window_skel); 1153251881Speter svn_skel__prepend(svn_skel__str_atom(size_str, pool), window_skel); 1154251881Speter svn_skel__prepend(diff_skel, window_skel); 1155251881Speter 1156251881Speter /* window header. */ 1157251881Speter svn_skel__prepend(window_skel, chunk_skel); 1158251881Speter svn_skel__prepend(svn_skel__str_atom(offset_str, pool), 1159251881Speter chunk_skel); 1160251881Speter 1161251881Speter /* Add this window item to the main skel. */ 1162251881Speter svn_skel__prepend(chunk_skel, skel); 1163251881Speter } 1164251881Speter 1165251881Speter /* "delta" */ 1166251881Speter svn_skel__prepend(svn_skel__str_atom("delta", pool), header_skel); 1167251881Speter 1168251881Speter /* header */ 1169251881Speter svn_skel__prepend(header_skel, skel); 1170251881Speter } 1171251881Speter else /* unknown kind */ 1172251881Speter SVN_ERR_MALFUNCTION(); 1173251881Speter 1174251881Speter /* Validate and return the skel. */ 1175251881Speter if (! is_valid_representation_skel(skel)) 1176251881Speter return skel_err("representation"); 1177251881Speter *skel_p = skel; 1178251881Speter return SVN_NO_ERROR; 1179251881Speter} 1180251881Speter 1181251881Speter 1182251881Spetersvn_error_t * 1183251881Spetersvn_fs_base__unparse_node_revision_skel(svn_skel_t **skel_p, 1184251881Speter const node_revision_t *noderev, 1185251881Speter int format, 1186251881Speter apr_pool_t *pool) 1187251881Speter{ 1188251881Speter svn_skel_t *skel; 1189251881Speter svn_skel_t *header_skel; 1190251881Speter const char *num_str; 1191251881Speter 1192251881Speter /* Create the skel. */ 1193251881Speter skel = svn_skel__make_empty_list(pool); 1194251881Speter header_skel = svn_skel__make_empty_list(pool); 1195251881Speter 1196251881Speter /* Store mergeinfo stuffs only if the schema level supports it. */ 1197251881Speter if (format >= SVN_FS_BASE__MIN_MERGEINFO_FORMAT) 1198251881Speter { 1199251881Speter /* MERGEINFO-COUNT */ 1200251881Speter num_str = apr_psprintf(pool, "%" APR_INT64_T_FMT, 1201251881Speter noderev->mergeinfo_count); 1202251881Speter svn_skel__prepend(svn_skel__str_atom(num_str, pool), header_skel); 1203251881Speter 1204251881Speter /* HAS-MERGEINFO */ 1205251881Speter svn_skel__prepend(svn_skel__mem_atom(noderev->has_mergeinfo ? "1" : "0", 1206251881Speter 1, pool), header_skel); 1207251881Speter 1208251881Speter /* PREDECESSOR-COUNT padding (only if we *don't* have a valid 1209251881Speter value; if we do, we'll pick that up below) */ 1210251881Speter if (noderev->predecessor_count == -1) 1211251881Speter { 1212251881Speter svn_skel__prepend(svn_skel__mem_atom(NULL, 0, pool), header_skel); 1213251881Speter } 1214251881Speter } 1215251881Speter 1216251881Speter /* PREDECESSOR-COUNT */ 1217251881Speter if (noderev->predecessor_count != -1) 1218251881Speter { 1219251881Speter const char *count_str = apr_psprintf(pool, "%d", 1220251881Speter noderev->predecessor_count); 1221251881Speter svn_skel__prepend(svn_skel__str_atom(count_str, pool), header_skel); 1222251881Speter } 1223251881Speter 1224251881Speter /* PREDECESSOR-ID */ 1225251881Speter if (noderev->predecessor_id) 1226251881Speter { 1227251881Speter svn_string_t *id_str = svn_fs_base__id_unparse(noderev->predecessor_id, 1228251881Speter pool); 1229251881Speter svn_skel__prepend(svn_skel__mem_atom(id_str->data, id_str->len, pool), 1230251881Speter header_skel); 1231251881Speter } 1232251881Speter else 1233251881Speter { 1234251881Speter svn_skel__prepend(svn_skel__mem_atom(NULL, 0, pool), header_skel); 1235251881Speter } 1236251881Speter 1237251881Speter /* CREATED-PATH */ 1238251881Speter svn_skel__prepend(svn_skel__str_atom(noderev->created_path, pool), 1239251881Speter header_skel); 1240251881Speter 1241251881Speter /* KIND */ 1242251881Speter if (noderev->kind == svn_node_file) 1243251881Speter svn_skel__prepend(svn_skel__str_atom("file", pool), header_skel); 1244251881Speter else if (noderev->kind == svn_node_dir) 1245251881Speter svn_skel__prepend(svn_skel__str_atom("dir", pool), header_skel); 1246251881Speter else 1247251881Speter SVN_ERR_MALFUNCTION(); 1248251881Speter 1249251881Speter /* ### do we really need to check *node->FOO_key ? if a key doesn't 1250251881Speter ### exist, then the field should be NULL ... */ 1251251881Speter 1252251881Speter /* EDIT-DATA-KEY (optional) */ 1253251881Speter if ((noderev->edit_key) && (*noderev->edit_key)) 1254251881Speter svn_skel__prepend(svn_skel__str_atom(noderev->edit_key, pool), skel); 1255251881Speter 1256251881Speter /* DATA-KEY | (DATA-KEY DATA-KEY-UNIQID) */ 1257251881Speter if ((noderev->data_key_uniquifier) && (*noderev->data_key_uniquifier)) 1258251881Speter { 1259251881Speter /* Build a 2-tuple with a rep key and uniquifier. */ 1260251881Speter svn_skel_t *data_key_skel = svn_skel__make_empty_list(pool); 1261251881Speter 1262251881Speter /* DATA-KEY-UNIQID */ 1263251881Speter svn_skel__prepend(svn_skel__str_atom(noderev->data_key_uniquifier, 1264251881Speter pool), 1265251881Speter data_key_skel); 1266251881Speter 1267251881Speter /* DATA-KEY */ 1268251881Speter if ((noderev->data_key) && (*noderev->data_key)) 1269251881Speter svn_skel__prepend(svn_skel__str_atom(noderev->data_key, pool), 1270251881Speter data_key_skel); 1271251881Speter else 1272251881Speter svn_skel__prepend(svn_skel__mem_atom(NULL, 0, pool), data_key_skel); 1273251881Speter 1274251881Speter /* Add our 2-tuple to the main skel. */ 1275251881Speter svn_skel__prepend(data_key_skel, skel); 1276251881Speter } 1277251881Speter else 1278251881Speter { 1279251881Speter /* Just store the rep key (or empty placeholder) in the main skel. */ 1280251881Speter if ((noderev->data_key) && (*noderev->data_key)) 1281251881Speter svn_skel__prepend(svn_skel__str_atom(noderev->data_key, pool), skel); 1282251881Speter else 1283251881Speter svn_skel__prepend(svn_skel__mem_atom(NULL, 0, pool), skel); 1284251881Speter } 1285251881Speter 1286251881Speter /* PROP-KEY */ 1287251881Speter if ((noderev->prop_key) && (*noderev->prop_key)) 1288251881Speter svn_skel__prepend(svn_skel__str_atom(noderev->prop_key, pool), skel); 1289251881Speter else 1290251881Speter svn_skel__prepend(svn_skel__mem_atom(NULL, 0, pool), skel); 1291251881Speter 1292251881Speter /* HEADER */ 1293251881Speter svn_skel__prepend(header_skel, skel); 1294251881Speter 1295251881Speter /* Validate and return the skel. */ 1296251881Speter if (! is_valid_node_revision_skel(skel)) 1297251881Speter return skel_err("node-revision"); 1298251881Speter *skel_p = skel; 1299251881Speter return SVN_NO_ERROR; 1300251881Speter} 1301251881Speter 1302251881Speter 1303251881Spetersvn_error_t * 1304251881Spetersvn_fs_base__unparse_copy_skel(svn_skel_t **skel_p, 1305251881Speter const copy_t *copy, 1306251881Speter apr_pool_t *pool) 1307251881Speter{ 1308251881Speter svn_skel_t *skel; 1309251881Speter svn_string_t *tmp_str; 1310251881Speter 1311251881Speter /* Create the skel. */ 1312251881Speter skel = svn_skel__make_empty_list(pool); 1313251881Speter 1314251881Speter /* DST-NODE-ID */ 1315251881Speter tmp_str = svn_fs_base__id_unparse(copy->dst_noderev_id, pool); 1316251881Speter svn_skel__prepend(svn_skel__mem_atom(tmp_str->data, tmp_str->len, pool), 1317251881Speter skel); 1318251881Speter 1319251881Speter /* SRC-TXN-ID */ 1320251881Speter if ((copy->src_txn_id) && (*copy->src_txn_id)) 1321251881Speter svn_skel__prepend(svn_skel__str_atom(copy->src_txn_id, pool), skel); 1322251881Speter else 1323251881Speter svn_skel__prepend(svn_skel__mem_atom(NULL, 0, pool), skel); 1324251881Speter 1325251881Speter /* SRC-PATH */ 1326251881Speter if ((copy->src_path) && (*copy->src_path)) 1327251881Speter svn_skel__prepend(svn_skel__str_atom(copy->src_path, pool), skel); 1328251881Speter else 1329251881Speter svn_skel__prepend(svn_skel__mem_atom(NULL, 0, pool), skel); 1330251881Speter 1331251881Speter /* "copy" */ 1332251881Speter if (copy->kind == copy_kind_real) 1333251881Speter svn_skel__prepend(svn_skel__str_atom("copy", pool), skel); 1334251881Speter else 1335251881Speter svn_skel__prepend(svn_skel__str_atom("soft-copy", pool), skel); 1336251881Speter 1337251881Speter /* Validate and return the skel. */ 1338251881Speter if (! is_valid_copy_skel(skel)) 1339251881Speter return skel_err("copy"); 1340251881Speter *skel_p = skel; 1341251881Speter return SVN_NO_ERROR; 1342251881Speter} 1343251881Speter 1344251881Speter 1345251881Spetersvn_error_t * 1346251881Spetersvn_fs_base__unparse_entries_skel(svn_skel_t **skel_p, 1347251881Speter apr_hash_t *entries, 1348251881Speter apr_pool_t *pool) 1349251881Speter{ 1350251881Speter svn_skel_t *skel = svn_skel__make_empty_list(pool); 1351251881Speter apr_hash_index_t *hi; 1352251881Speter 1353251881Speter /* Create the skel. */ 1354251881Speter if (entries) 1355251881Speter { 1356251881Speter /* Loop over hash entries */ 1357251881Speter for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi)) 1358251881Speter { 1359251881Speter const void *key; 1360251881Speter void *val; 1361251881Speter apr_ssize_t klen; 1362251881Speter svn_fs_id_t *value; 1363251881Speter svn_string_t *id_str; 1364251881Speter svn_skel_t *entry_skel = svn_skel__make_empty_list(pool); 1365251881Speter 1366251881Speter apr_hash_this(hi, &key, &klen, &val); 1367251881Speter value = val; 1368251881Speter 1369251881Speter /* VALUE */ 1370251881Speter id_str = svn_fs_base__id_unparse(value, pool); 1371251881Speter svn_skel__prepend(svn_skel__mem_atom(id_str->data, id_str->len, 1372251881Speter pool), 1373251881Speter entry_skel); 1374251881Speter 1375251881Speter /* NAME */ 1376251881Speter svn_skel__prepend(svn_skel__mem_atom(key, klen, pool), entry_skel); 1377251881Speter 1378251881Speter /* Add entry to the entries skel. */ 1379251881Speter svn_skel__prepend(entry_skel, skel); 1380251881Speter } 1381251881Speter } 1382251881Speter 1383251881Speter /* Return the skel. */ 1384251881Speter *skel_p = skel; 1385251881Speter return SVN_NO_ERROR; 1386251881Speter} 1387251881Speter 1388251881Speter 1389251881Spetersvn_error_t * 1390251881Spetersvn_fs_base__unparse_change_skel(svn_skel_t **skel_p, 1391251881Speter const change_t *change, 1392251881Speter apr_pool_t *pool) 1393251881Speter{ 1394251881Speter svn_skel_t *skel; 1395251881Speter svn_string_t *tmp_str; 1396251881Speter svn_fs_path_change_kind_t kind; 1397251881Speter 1398251881Speter /* Create the skel. */ 1399251881Speter skel = svn_skel__make_empty_list(pool); 1400251881Speter 1401251881Speter /* PROP-MOD */ 1402251881Speter if (change->prop_mod) 1403251881Speter svn_skel__prepend(svn_skel__str_atom("1", pool), skel); 1404251881Speter else 1405251881Speter svn_skel__prepend(svn_skel__mem_atom(NULL, 0, pool), skel); 1406251881Speter 1407251881Speter /* TEXT-MOD */ 1408251881Speter if (change->text_mod) 1409251881Speter svn_skel__prepend(svn_skel__str_atom("1", pool), skel); 1410251881Speter else 1411251881Speter svn_skel__prepend(svn_skel__mem_atom(NULL, 0, pool), skel); 1412251881Speter 1413251881Speter /* KIND */ 1414251881Speter switch (change->kind) 1415251881Speter { 1416251881Speter case svn_fs_path_change_reset: 1417251881Speter svn_skel__prepend(svn_skel__str_atom("reset", pool), skel); 1418251881Speter break; 1419251881Speter case svn_fs_path_change_add: 1420251881Speter svn_skel__prepend(svn_skel__str_atom("add", pool), skel); 1421251881Speter break; 1422251881Speter case svn_fs_path_change_delete: 1423251881Speter svn_skel__prepend(svn_skel__str_atom("delete", pool), skel); 1424251881Speter break; 1425251881Speter case svn_fs_path_change_replace: 1426251881Speter svn_skel__prepend(svn_skel__str_atom("replace", pool), skel); 1427251881Speter break; 1428251881Speter case svn_fs_path_change_modify: 1429251881Speter default: 1430251881Speter svn_skel__prepend(svn_skel__str_atom("modify", pool), skel); 1431251881Speter break; 1432251881Speter } 1433251881Speter 1434251881Speter /* NODE-REV-ID */ 1435251881Speter if (change->noderev_id) 1436251881Speter { 1437251881Speter tmp_str = svn_fs_base__id_unparse(change->noderev_id, pool); 1438251881Speter svn_skel__prepend(svn_skel__mem_atom(tmp_str->data, tmp_str->len, pool), 1439251881Speter skel); 1440251881Speter } 1441251881Speter else 1442251881Speter { 1443251881Speter svn_skel__prepend(svn_skel__mem_atom(NULL, 0, pool), skel); 1444251881Speter } 1445251881Speter 1446251881Speter /* PATH */ 1447251881Speter svn_skel__prepend(svn_skel__str_atom(change->path, pool), skel); 1448251881Speter 1449251881Speter /* "change" */ 1450251881Speter svn_skel__prepend(svn_skel__str_atom("change", pool), skel); 1451251881Speter 1452251881Speter /* Validate and return the skel. */ 1453251881Speter if (! is_valid_change_skel(skel, &kind)) 1454251881Speter return skel_err("change"); 1455251881Speter if (kind != change->kind) 1456251881Speter return skel_err("change"); 1457251881Speter *skel_p = skel; 1458251881Speter return SVN_NO_ERROR; 1459251881Speter} 1460251881Speter 1461251881Speter 1462251881Spetersvn_error_t * 1463251881Spetersvn_fs_base__unparse_lock_skel(svn_skel_t **skel_p, 1464251881Speter const svn_lock_t *lock, 1465251881Speter apr_pool_t *pool) 1466251881Speter{ 1467251881Speter svn_skel_t *skel; 1468251881Speter 1469251881Speter /* Create the skel. */ 1470251881Speter skel = svn_skel__make_empty_list(pool); 1471251881Speter 1472251881Speter /* EXP-DATE is optional. If not present, just use an empty atom. */ 1473251881Speter if (lock->expiration_date) 1474251881Speter svn_skel__prepend(svn_skel__str_atom( 1475251881Speter svn_time_to_cstring(lock->expiration_date, pool), 1476251881Speter pool), skel); 1477251881Speter else 1478251881Speter svn_skel__prepend(svn_skel__mem_atom(NULL, 0, pool), skel); 1479251881Speter 1480251881Speter /* CREATION-DATE */ 1481251881Speter svn_skel__prepend(svn_skel__str_atom( 1482251881Speter svn_time_to_cstring(lock->creation_date, pool), 1483251881Speter pool), skel); 1484251881Speter 1485251881Speter /* XML_P */ 1486251881Speter if (lock->is_dav_comment) 1487251881Speter svn_skel__prepend(svn_skel__str_atom("1", pool), skel); 1488251881Speter else 1489251881Speter svn_skel__prepend(svn_skel__str_atom("0", pool), skel); 1490251881Speter 1491251881Speter /* COMMENT */ 1492251881Speter if (lock->comment) 1493251881Speter svn_skel__prepend(svn_skel__str_atom(lock->comment, pool), skel); 1494251881Speter else 1495251881Speter svn_skel__prepend(svn_skel__mem_atom(NULL, 0, pool), skel); 1496251881Speter 1497251881Speter /* OWNER */ 1498251881Speter svn_skel__prepend(svn_skel__str_atom(lock->owner, pool), skel); 1499251881Speter 1500251881Speter /* LOCK-TOKEN */ 1501251881Speter svn_skel__prepend(svn_skel__str_atom(lock->token, pool), skel); 1502251881Speter 1503251881Speter /* PATH */ 1504251881Speter svn_skel__prepend(svn_skel__str_atom(lock->path, pool), skel); 1505251881Speter 1506251881Speter /* "lock" */ 1507251881Speter svn_skel__prepend(svn_skel__str_atom("lock", pool), skel); 1508251881Speter 1509251881Speter /* Validate and return the skel. */ 1510251881Speter if (! is_valid_lock_skel(skel)) 1511251881Speter return skel_err("lock"); 1512251881Speter 1513251881Speter *skel_p = skel; 1514251881Speter return SVN_NO_ERROR; 1515251881Speter} 1516