1/* low_level.c --- low level r/w access to fs_fs file structures 2 * 3 * ==================================================================== 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 * ==================================================================== 21 */ 22 23#include "svn_fs.h" 24 25#include "fs_fs.h" 26#include "id.h" 27 28/* Kinds that a node-rev can be. */ 29#define SVN_FS_FS__KIND_FILE "file" 30#define SVN_FS_FS__KIND_DIR "dir" 31 32/* The functions are grouped as follows: 33 * 34 * - revision trailer (up to format 6) 35 * - revision footer (since format 7) 36 * - changed path list 37 * - node revision 38 * - representation (as in "text:" and "props:" lines) 39 * - representation header ("PLAIN" and "DELTA" lines) 40 */ 41 42/* Given the last "few" bytes (should be at least 40) of revision REV in 43 * TRAILER, parse the last line and return the offset of the root noderev 44 * in *ROOT_OFFSET and the offset of the changed paths list in 45 * *CHANGES_OFFSET. Offsets are relative to the revision's start offset. 46 * ROOT_OFFSET and / or CHANGES_OFFSET may be NULL. 47 * 48 * Note that REV is only used to construct nicer error objects. 49 */ 50svn_error_t * 51svn_fs_fs__parse_revision_trailer(apr_off_t *root_offset, 52 apr_off_t *changes_offset, 53 svn_stringbuf_t *trailer, 54 svn_revnum_t rev); 55 56/* Given the offset of the root noderev in ROOT_OFFSET and the offset of 57 * the changed paths list in CHANGES_OFFSET, return the corresponding 58 * revision's trailer. Allocate it in RESULT_POOL. 59 */ 60svn_stringbuf_t * 61svn_fs_fs__unparse_revision_trailer(apr_off_t root_offset, 62 apr_off_t changes_offset, 63 apr_pool_t *result_pool); 64 65/* Given the format 7+ revision / pack FOOTER, parse it destructively 66 * and return the start offsets of the index data in *L2P_OFFSET and 67 * *P2L_OFFSET, respectively. Also, return the expected checksums in 68 * in *L2P_CHECKSUM and *P2L_CHECKSUM. 69 * 70 * FOOTER_OFFSET is used for validation. 71 * 72 * Note that REV is only used to construct nicer error objects that 73 * mention this revision. Allocate the checksums in RESULT_POOL. 74 */ 75svn_error_t * 76svn_fs_fs__parse_footer(apr_off_t *l2p_offset, 77 svn_checksum_t **l2p_checksum, 78 apr_off_t *p2l_offset, 79 svn_checksum_t **p2l_checksum, 80 svn_stringbuf_t *footer, 81 svn_revnum_t rev, 82 apr_off_t footer_offset, 83 apr_pool_t *result_pool); 84 85/* Given the offset of the L2P index data in L2P_OFFSET, the content 86 * checksum in L2P_CHECKSUM and the offset plus checksum of the P2L 87 * index data in P2L_OFFSET and P2L_CHECKSUM. 88 * 89 * Return the corresponding format 7+ revision / pack file footer. 90 * Allocate it in RESULT_POOL and use SCRATCH_POOL for temporary. 91 */ 92svn_stringbuf_t * 93svn_fs_fs__unparse_footer(apr_off_t l2p_offset, 94 svn_checksum_t *l2p_checksum, 95 apr_off_t p2l_offset, 96 svn_checksum_t *p2l_checksum, 97 apr_pool_t *result_pool, 98 apr_pool_t *scratch_pool); 99 100/* Read up to MAX_COUNT of the changes from STREAM and store them in 101 *CHANGES, allocated in RESULT_POOL. Do temporary allocations in 102 SCRATCH_POOL. */ 103svn_error_t * 104svn_fs_fs__read_changes(apr_array_header_t **changes, 105 svn_stream_t *stream, 106 int max_count, 107 apr_pool_t *result_pool, 108 apr_pool_t *scratch_pool); 109 110/* Callback function used by svn_fs_fs__read_changes_incrementally(), 111 * asking the receiver to process to process CHANGE using BATON. CHANGE 112 * and SCRATCH_POOL will not be valid beyond the current callback invocation. 113 */ 114typedef svn_error_t *(*svn_fs_fs__change_receiver_t)( 115 void *baton, 116 change_t *change, 117 apr_pool_t *scratch_pool); 118 119/* Read all the changes from STREAM and invoke CHANGE_RECEIVER on each change. 120 Do all allocations in SCRATCH_POOL. */ 121svn_error_t * 122svn_fs_fs__read_changes_incrementally(svn_stream_t *stream, 123 svn_fs_fs__change_receiver_t 124 change_receiver, 125 void *change_receiver_baton, 126 apr_pool_t *scratch_pool); 127 128/* Write the changed path info from CHANGES in filesystem FS to the 129 output stream STREAM. You may call this function multiple time on 130 the same stream. If you are writing to a (proto-)revision file, 131 the last call must set TERMINATE_LIST to write an extra empty line 132 that marks the end of the changed paths list. 133 Perform temporary allocations in SCRATCH_POOL. 134 */ 135svn_error_t * 136svn_fs_fs__write_changes(svn_stream_t *stream, 137 svn_fs_t *fs, 138 apr_hash_t *changes, 139 svn_boolean_t terminate_list, 140 apr_pool_t *scratch_pool); 141 142/* Read a node-revision from STREAM. Set *NODEREV to the new structure, 143 allocated in RESULT_POOL. */ 144svn_error_t * 145svn_fs_fs__read_noderev(node_revision_t **noderev, 146 svn_stream_t *stream, 147 apr_pool_t *result_pool, 148 apr_pool_t *scratch_pool); 149 150/* Write the node-revision NODEREV into the stream OUTFILE, compatible with 151 filesystem format FORMAT. Only write mergeinfo-related metadata if 152 INCLUDE_MERGEINFO is true. Temporary allocations are from SCRATCH_POOL. */ 153svn_error_t * 154svn_fs_fs__write_noderev(svn_stream_t *outfile, 155 node_revision_t *noderev, 156 int format, 157 svn_boolean_t include_mergeinfo, 158 apr_pool_t *scratch_pool); 159 160/* Parse the description of a representation from TEXT and store it 161 into *REP_P. TEXT will be invalidated by this call. Allocate *REP_P in 162 RESULT_POOL and use SCRATCH_POOL for temporaries. */ 163svn_error_t * 164svn_fs_fs__parse_representation(representation_t **rep_p, 165 svn_stringbuf_t *text, 166 apr_pool_t *result_pool, 167 apr_pool_t *scratch_pool); 168 169/* Return a formatted string, compatible with filesystem format FORMAT, 170 that represents the location of representation REP. If 171 MUTABLE_REP_TRUNCATED is given, the rep is for props or dir contents, 172 and only a "-1" revision number will be given for a mutable rep. 173 If MAY_BE_CORRUPT is true, guard for NULL when constructing the string. 174 Allocate the result in RESULT_POOL and temporaries in SCRATCH_POOL. */ 175svn_stringbuf_t * 176svn_fs_fs__unparse_representation(representation_t *rep, 177 int format, 178 svn_boolean_t mutable_rep_truncated, 179 apr_pool_t *result_pool, 180 apr_pool_t *scratch_pool); 181 182/* This type enumerates all forms of representations that we support. */ 183typedef enum svn_fs_fs__rep_type_t 184{ 185 /* this is a PLAIN representation */ 186 svn_fs_fs__rep_plain, 187 188 /* this is a DELTA representation with no base representation */ 189 svn_fs_fs__rep_self_delta, 190 191 /* this is a DELTA representation against some base representation */ 192 svn_fs_fs__rep_delta 193} svn_fs_fs__rep_type_t; 194 195/* This structure is used to hold the information stored in a representation 196 * header. */ 197typedef struct svn_fs_fs__rep_header_t 198{ 199 /* type of the representation, i.e. whether it is PLAIN, self-DELTA etc. */ 200 svn_fs_fs__rep_type_t type; 201 202 /* if this rep is a delta against some other rep, that base rep can 203 * be found in this revision. Should be 0 if there is no base rep. */ 204 svn_revnum_t base_revision; 205 206 /* if this rep is a delta against some other rep, that base rep can 207 * be found at this item index within the base rep's revision. Should 208 * be 0 if there is no base rep. */ 209 apr_off_t base_item_index; 210 211 /* if this rep is a delta against some other rep, this is the (deltified) 212 * size of that base rep. Should be 0 if there is no base rep. */ 213 svn_filesize_t base_length; 214 215 /* length of the textual representation of the header in the rep or pack 216 * file, including EOL. Only valid after reading it from disk. 217 * Should be 0 otherwise. */ 218 apr_size_t header_size; 219} svn_fs_fs__rep_header_t; 220 221/* Read the next line from STREAM and parse it as a text 222 representation header. Return the parsed entry in *HEADER, allocated 223 in RESULT_POOL. Perform temporary allocations in SCRATCH_POOL. */ 224svn_error_t * 225svn_fs_fs__read_rep_header(svn_fs_fs__rep_header_t **header, 226 svn_stream_t *stream, 227 apr_pool_t *result_pool, 228 apr_pool_t *scratch_pool); 229 230/* Write the representation HEADER to STREAM. 231 * Use SCRATCH_POOL for temporary allocations. */ 232svn_error_t * 233svn_fs_fs__write_rep_header(svn_fs_fs__rep_header_t *header, 234 svn_stream_t *stream, 235 apr_pool_t *scratch_pool); 236