📄 fs_fs.c
字号:
local_value = apr_pstrdup (pool, value);
apr_hash_set (*headers, local_name, APR_HASH_KEY_STRING, local_value);
}
return SVN_NO_ERROR;
}
/* Open the revision file for revision REV in filesystem FS and store
the newly opened file in FILE. Seek to location OFFSET before
returning. Perform temporary allocations in POOL. */
static svn_error_t *
open_and_seek_revision (apr_file_t **file,
svn_fs_t *fs,
svn_revnum_t rev,
apr_off_t offset,
apr_pool_t *pool)
{
apr_file_t *rev_file;
SVN_ERR (svn_io_file_open (&rev_file, path_rev (fs, rev, pool),
APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool));
SVN_ERR (svn_io_file_seek (rev_file, APR_SET, &offset, pool));
*file = rev_file;
return SVN_NO_ERROR;
}
/* Open the representation for a node-revision in transaction TXN_ID
in filesystem FS and store the newly opened file in FILE. Seek to
location OFFSET before returning. Perform temporary allocations in
POOL. Only appropriate for file contents, nor props or directory
contents. */
static svn_error_t *
open_and_seek_transaction (apr_file_t **file,
svn_fs_t *fs,
const char *txn_id,
representation_t *rep,
apr_pool_t *pool)
{
apr_file_t *rev_file;
apr_off_t offset;
SVN_ERR (svn_io_file_open (&rev_file, path_txn_proto_rev (fs, txn_id, pool),
APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool));
offset = rep->offset;
SVN_ERR (svn_io_file_seek (rev_file, APR_SET, &offset, pool));
*file = rev_file;
return SVN_NO_ERROR;
}
/* Given a node-id ID, and a representation REP in filesystem FS, open
the correct file and seek to the correction location. Store this
file in *FILE_P. Perform any allocations in POOL. */
static svn_error_t *
open_and_seek_representation (apr_file_t **file_p,
svn_fs_t *fs,
representation_t *rep,
apr_pool_t *pool)
{
if (! rep->txn_id)
return open_and_seek_revision (file_p, fs, rep->revision, rep->offset,
pool);
else
return open_and_seek_transaction (file_p, fs, rep->txn_id, rep, pool);
}
/* Parse the description of a representation from STRING and store it
into *REP_P. If the representation is mutable (the revision is
given as -1), then use TXN_ID for the representation's txn_id
field. If MUTABLE_REP_TRUNCATED is true, then this representation
is for property or directory contents, and no information will be
expected except the "-1" revision number for a mutable
representation. Allocate *REP_P in POOL. */
static svn_error_t *
read_rep_offsets (representation_t **rep_p,
char *string,
const char *txn_id,
svn_boolean_t mutable_rep_truncated,
apr_pool_t *pool)
{
representation_t *rep;
char *str, *last_str;
int i;
rep = apr_pcalloc (pool, sizeof (*rep));
*rep_p = rep;
str = apr_strtok (string, " ", &last_str);
if (str == NULL)
return svn_error_create (SVN_ERR_FS_CORRUPT, NULL,
_("Malformed text rep offset line in node-rev"));
rep->revision = SVN_STR_TO_REV (str);
if (rep->revision == SVN_INVALID_REVNUM)
{
rep->txn_id = txn_id;
if (mutable_rep_truncated)
return SVN_NO_ERROR;
}
str = apr_strtok (NULL, " ", &last_str);
if (str == NULL)
return svn_error_create (SVN_ERR_FS_CORRUPT, NULL,
_("Malformed text rep offset line in node-rev"));
rep->offset = apr_atoi64 (str);
str = apr_strtok (NULL, " ", &last_str);
if (str == NULL)
return svn_error_create (SVN_ERR_FS_CORRUPT, NULL,
_("Malformed text rep offset line in node-rev"));
rep->size = apr_atoi64 (str);
str = apr_strtok (NULL, " ", &last_str);
if (str == NULL)
return svn_error_create (SVN_ERR_FS_CORRUPT, NULL,
_("Malformed text rep offset line in node-rev"));
rep->expanded_size = apr_atoi64 (str);
/* Read in the MD5 hash. */
str = apr_strtok (NULL, " ", &last_str);
if ((str == NULL) || (strlen (str) != (APR_MD5_DIGESTSIZE * 2)))
return svn_error_create (SVN_ERR_FS_CORRUPT, NULL,
_("Malformed text rep offset line in node-rev"));
/* Parse the hex MD5 hash into digest form. */
for (i = 0; i < APR_MD5_DIGESTSIZE; i++)
{
if ((! isxdigit (str[i * 2])) || (! isxdigit (str[i * 2 + 1])))
return svn_error_create
(SVN_ERR_FS_CORRUPT, NULL,
_("Malformed text rep offset line in node-rev"));
str[i * 2] = tolower (str[i * 2]);
rep->checksum[i] = (str[i * 2] -
((str[i * 2] <= '9') ? '0' : ('a' - 10))) << 4;
str[i * 2 + 1] = tolower (str[i * 2 + 1]);
rep->checksum[i] |= (str[i * 2 + 1] -
((str[i * 2 + 1] <= '9') ? '0' : ('a' - 10)));
}
return SVN_NO_ERROR;
}
svn_error_t *
svn_fs_fs__get_node_revision (node_revision_t **noderev_p,
svn_fs_t *fs,
const svn_fs_id_t *id,
apr_pool_t *pool)
{
apr_file_t *revision_file;
apr_hash_t *headers;
node_revision_t *noderev;
char *value;
svn_error_t *err;
if (svn_fs_fs__id_txn_id (id))
{
/* This is a transaction node-rev. */
err = svn_io_file_open (&revision_file, path_txn_node_rev (fs, id, pool),
APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool);
}
else
{
/* This is a revision node-rev. */
err = open_and_seek_revision (&revision_file, fs,
svn_fs_fs__id_rev (id),
svn_fs_fs__id_offset (id),
pool);
}
if (err)
{
if (APR_STATUS_IS_ENOENT (err->apr_err))
{
svn_error_clear (err);
return svn_fs_fs__err_dangling_id (fs, id);
}
return err;
}
SVN_ERR (read_header_block (&headers, revision_file, pool) );
noderev = apr_pcalloc (pool, sizeof (*noderev));
/* Read the node-rev id. */
value = apr_hash_get (headers, HEADER_ID, APR_HASH_KEY_STRING);
SVN_ERR (svn_io_file_close (revision_file, pool));
noderev->id = svn_fs_fs__id_parse (value, strlen (value), pool);
/* Read the type. */
value = apr_hash_get (headers, HEADER_TYPE, APR_HASH_KEY_STRING);
if ((value == NULL) ||
(strcmp (value, KIND_FILE) != 0 && strcmp (value, KIND_DIR)))
return svn_error_create (SVN_ERR_FS_CORRUPT, NULL,
_("Missing kind field in node-rev"));
noderev->kind = (strcmp (value, KIND_FILE) == 0) ? svn_node_file
: svn_node_dir;
/* Read the 'count' field. */
value = apr_hash_get (headers, HEADER_COUNT, APR_HASH_KEY_STRING);
noderev->predecessor_count = (value == NULL) ? 0 : atoi (value);
/* Get the properties location. */
value = apr_hash_get (headers, HEADER_PROPS, APR_HASH_KEY_STRING);
if (value)
{
SVN_ERR (read_rep_offsets (&noderev->prop_rep, value,
svn_fs_fs__id_txn_id (id), TRUE, pool));
}
/* Get the data location. */
value = apr_hash_get (headers, HEADER_TEXT, APR_HASH_KEY_STRING);
if (value)
{
SVN_ERR (read_rep_offsets (&noderev->data_rep, value,
svn_fs_fs__id_txn_id (id),
(noderev->kind == svn_node_dir), pool));
}
/* Get the created path. */
value = apr_hash_get (headers, HEADER_CPATH, APR_HASH_KEY_STRING);
if (value == NULL)
{
return svn_error_create (SVN_ERR_FS_CORRUPT, NULL,
_("Missing cpath in node-rev"));
}
else
{
noderev->created_path = apr_pstrdup (pool, value);
}
/* Get the predecessor ID. */
value = apr_hash_get (headers, HEADER_PRED, APR_HASH_KEY_STRING);
if (value)
noderev->predecessor_id = svn_fs_fs__id_parse (value, strlen (value),
pool);
/* Get the copyroot. */
value = apr_hash_get (headers, HEADER_COPYROOT, APR_HASH_KEY_STRING);
if (value == NULL)
{
noderev->copyroot_path = apr_pstrdup (pool, noderev->created_path);
noderev->copyroot_rev = svn_fs_fs__id_rev (noderev->id);
}
else
{
char *str, *last_str;
str = apr_strtok (value, " ", &last_str);
if (str == NULL)
return svn_error_create (SVN_ERR_FS_CORRUPT, NULL,
_("Malformed copyroot line in node-rev"));
noderev->copyroot_rev = atoi (str);
if (last_str == NULL)
return svn_error_create (SVN_ERR_FS_CORRUPT, NULL,
_("Malformed copyroot line in node-rev"));
noderev->copyroot_path = apr_pstrdup (pool, last_str);
}
/* Get the copyfrom. */
value = apr_hash_get (headers, HEADER_COPYFROM, APR_HASH_KEY_STRING);
if (value == NULL)
{
noderev->copyfrom_path = NULL;
noderev->copyfrom_rev = SVN_INVALID_REVNUM;
}
else
{
char *str, *last_str;
str = apr_strtok (value, " ", &last_str);
if (str == NULL)
return svn_error_create (SVN_ERR_FS_CORRUPT, NULL,
_("Malformed copyfrom line in node-rev"));
noderev->copyfrom_rev = atoi (str);
if (last_str == NULL)
return svn_error_create (SVN_ERR_FS_CORRUPT, NULL,
_("Malformed copyfrom line in node-rev"));
noderev->copyfrom_path = apr_pstrdup (pool, last_str);
}
*noderev_p = noderev;
return SVN_NO_ERROR;
}
/* Return a formatted string that represents the location of
representation REP. If MUTABLE_REP_TRUNCATED is given, the rep is
for props or dir contents, and only a "-1" revision number will be
given for a mutable rep. Perform the allocation from POOL. */
static const char *
representation_string (representation_t *rep,
svn_boolean_t mutable_rep_truncated, apr_pool_t *pool)
{
if (rep->txn_id && mutable_rep_truncated)
return "-1";
else
return apr_psprintf (pool, "%ld %" APR_OFF_T_FMT " %" SVN_FILESIZE_T_FMT
" %" SVN_FILESIZE_T_FMT " %s",
rep->revision, rep->offset, rep->size,
rep->expanded_size,
svn_md5_digest_to_cstring (rep->checksum, pool));
}
/* Write the node-revision NODEREV into the file FILE. Temporary
allocations are from POOL. */
static svn_error_t *
write_noderev_txn (apr_file_t *file,
node_revision_t *noderev,
apr_pool_t *pool)
{
svn_stream_t *outfile;
outfile = svn_stream_from_aprfile (file, pool);
SVN_ERR (svn_stream_printf (outfile, pool, HEADER_ID ": %s\n",
svn_fs_fs__id_unparse (noderev->id,
pool)->data));
SVN_ERR (svn_stream_printf (outfile, pool, HEADER_TYPE ": %s\n",
(noderev->kind == svn_node_file) ?
KIND_FILE : KIND_DIR));
if (noderev->predecessor_id)
SVN_ERR (svn_stream_printf (outfile, pool, HEADER_PRED ": %s\n",
svn_fs_fs__id_unparse (noderev->predecessor_id,
pool)->data));
SVN_ERR (svn_stream_printf (outfile, pool, HEADER_COUNT ": %d\n",
noderev->predecessor_count));
if (noderev->data_rep)
SVN_ERR (svn_stream_printf (outfile, pool, HEADER_TEXT ": %s\n",
representation_string (noderev->data_rep,
(noderev->kind
== svn_node_dir),
pool)));
if (noderev->prop_rep)
SVN_ERR (svn_stream_printf (outfile, pool, HEADER_PROPS ": %s\n",
representation_string (noderev->prop_rep, TRUE,
pool)));
SVN_ERR (svn_stream_printf (outfile, pool, HEADER_CPATH ": %s\n",
noderev->created_path));
if (noderev->copyfrom_path)
SVN_ERR (svn_stream_printf (outfile, pool, HEADER_COPYFROM ": %ld"
" %s\n",
noderev->copyfrom_rev,
noderev->copyfrom_path));
if ((noderev->copyroot_rev != svn_fs_fs__id_rev (noderev->id)) ||
(strcmp (noderev->copyroot_path, noderev->created_path) != 0))
SVN_ERR (svn_stream_printf (outfile, pool, HEADER_COPYROOT ": %ld"
" %s\n",
noderev->copyroot_rev,
noderev->copyroot_path));
SVN_ERR (svn_stream_printf (outfile, pool, "\n"));
return SVN_NO_ERROR;
}
svn_error_t *
svn_fs_fs__put_node_revision (svn_fs_t *fs,
const svn_fs_id_t *id,
node_revision_t *noderev,
apr_pool_t *pool)
{
apr_file_t *noderev_file;
const char *txn_id = svn_fs_fs__id_txn_id (id);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -