📄 fs_skels.c
字号:
/* fs_skels.c --- conversion between fs native types and skeletons * * ==================================================================== * Copyright (c) 2000-2004 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */#include <string.h>#include "svn_error.h"#include "svn_string.h"#include "svn_types.h"#include "svn_time.h"#include "fs_skels.h"#include "skel.h"#include "../id.h"static svn_error_t *skel_err(const char *skel_type){ return svn_error_createf(SVN_ERR_FS_MALFORMED_SKEL, NULL, "Malformed%s%s skeleton", skel_type ? " " : "", skel_type ? skel_type : "");}/*** Validity Checking ***/static svn_boolean_tis_valid_checksum_skel(skel_t *skel){ if (svn_fs_base__list_length(skel) != 2) return FALSE; if (svn_fs_base__matches_atom(skel->children, "md5") && skel->children->next->is_atom) return TRUE; return FALSE;}static svn_boolean_tis_valid_proplist_skel(skel_t *skel){ int len = svn_fs_base__list_length(skel); if ((len >= 0) && (len & 1) == 0) { skel_t *elt; for (elt = skel->children; elt; elt = elt->next) if (! elt->is_atom) return FALSE; return TRUE; } return FALSE;}static svn_boolean_tis_valid_revision_skel(skel_t *skel){ int len = svn_fs_base__list_length(skel); if ((len == 2) && svn_fs_base__matches_atom(skel->children, "revision") && skel->children->next->is_atom) return TRUE; return FALSE;}static svn_boolean_tis_valid_transaction_skel(skel_t *skel, transaction_kind_t *kind){ int len = svn_fs_base__list_length(skel); if (len != 5) return FALSE; /* Determine (and verify) the kind. */ if (svn_fs_base__matches_atom(skel->children, "transaction")) *kind = transaction_kind_normal; else if (svn_fs_base__matches_atom(skel->children, "committed")) *kind = transaction_kind_committed; else if (svn_fs_base__matches_atom(skel->children, "dead")) *kind = transaction_kind_dead; else return FALSE; if (skel->children->next->is_atom && skel->children->next->next->is_atom && (! skel->children->next->next->next->is_atom) && (! skel->children->next->next->next->next->is_atom)) return TRUE; return FALSE;}static svn_boolean_tis_valid_rep_delta_chunk_skel(skel_t *skel){ int len; skel_t *window; skel_t *diff; /* check the delta skel. */ if ((svn_fs_base__list_length(skel) != 2) || (! skel->children->is_atom)) return FALSE; /* check the window. */ window = skel->children->next; len = svn_fs_base__list_length(window); if ((len < 3) || (len > 4)) return FALSE; if (! ((! window->children->is_atom) && (window->children->next->is_atom) && (window->children->next->next->is_atom))) return FALSE; if ((len == 4) && (! window->children->next->next->next->is_atom)) return FALSE; /* check the diff. ### currently we support only svndiff version 0 delta data. */ diff = window->children; if ((svn_fs_base__list_length(diff) == 3) && (svn_fs_base__matches_atom(diff->children, "svndiff")) && ((svn_fs_base__matches_atom(diff->children->next, "0")) || (svn_fs_base__matches_atom(diff->children->next, "1"))) && (diff->children->next->next->is_atom)) return TRUE; return FALSE;}static svn_boolean_tis_valid_representation_skel(skel_t *skel){ int len = svn_fs_base__list_length(skel); skel_t *header; int header_len; /* the rep has at least two items in it, a HEADER list, and at least one piece of kind-specific data. */ if (len < 2) return FALSE; /* check the header. it must have KIND and TXN atoms, and optionally a CHECKSUM (which is a list form). */ header = skel->children; header_len = svn_fs_base__list_length(header); if (! (((header_len == 2) /* 2 means old repository, checksum absent */ && (header->children->is_atom) && (header->children->next->is_atom)) || ((header_len == 3) /* 3 means checksum present */ && (header->children->is_atom) && (header->children->next->is_atom) && (is_valid_checksum_skel(header->children->next->next))))) return FALSE; /* check for fulltext rep. */ if ((len == 2) && (svn_fs_base__matches_atom(header->children, "fulltext"))) return TRUE; /* check for delta rep. */ if ((len >= 2) && (svn_fs_base__matches_atom(header->children, "delta"))) { /* it's a delta rep. check the validity. */ skel_t *chunk = skel->children->next; /* loop over chunks, checking each one. */ while (chunk) { if (! is_valid_rep_delta_chunk_skel(chunk)) return FALSE; chunk = chunk->next; } /* all good on this delta rep. */ return TRUE; } return FALSE;}static svn_boolean_tis_valid_node_revision_header_skel(skel_t *skel, skel_t **kind_p){ int len = svn_fs_base__list_length(skel); if (len < 2) return FALSE; /* set the *KIND_P pointer. */ *kind_p = skel->children; /* without predecessor... */ if ((len == 2) && skel->children->is_atom && skel->children->next->is_atom && (skel->children->next->data[0] == '/')) return TRUE; /* or with predecessor... */ if ((len == 3) && skel->children->is_atom && skel->children->next->is_atom && (skel->children->next->data[0] == '/') && skel->children->next->next->is_atom) return TRUE; /* or with predecessor and predecessor count... */ if ((len == 4) && skel->children->is_atom && skel->children->next->is_atom && (skel->children->next->data[0] == '/') && skel->children->next->next->is_atom && skel->children->next->next->next->is_atom) return TRUE; return FALSE;}static svn_boolean_tis_valid_node_revision_skel(skel_t *skel){ int len = svn_fs_base__list_length(skel); if (len >= 1) { skel_t *header = skel->children; skel_t *kind; if (is_valid_node_revision_header_skel(header, &kind)) { if (svn_fs_base__matches_atom(kind, "dir") && len == 3 && header->next->is_atom && header->next->next->is_atom) return TRUE; if (svn_fs_base__matches_atom(kind, "file") && ((len == 3) || (len == 4)) && header->next->is_atom && header->next->next->is_atom) { if ((len == 4) && (! header->next->next->next->is_atom)) return FALSE; return TRUE; } } } return FALSE;}static svn_boolean_tis_valid_copy_skel(skel_t *skel){ return (((svn_fs_base__list_length(skel) == 4) && (svn_fs_base__matches_atom(skel->children, "copy") || svn_fs_base__matches_atom(skel->children, "soft-copy")) && skel->children->next->is_atom && skel->children->next->next->is_atom && skel->children->next->next->next->is_atom) ? TRUE : FALSE);}static svn_boolean_tis_valid_change_skel(skel_t *skel, svn_fs_path_change_kind_t *kind){ if ((svn_fs_base__list_length(skel) == 6) && svn_fs_base__matches_atom(skel->children, "change") && skel->children->next->is_atom && skel->children->next->next->is_atom && skel->children->next->next->next->is_atom && skel->children->next->next->next->next->is_atom && skel->children->next->next->next->next->next->is_atom) { skel_t *kind_skel = skel->children->next->next->next; /* check the kind (and return it) */ if (svn_fs_base__matches_atom(kind_skel, "reset")) { if (kind) *kind = svn_fs_path_change_reset; return TRUE; } if (svn_fs_base__matches_atom(kind_skel, "add")) { if (kind) *kind = svn_fs_path_change_add; return TRUE; } if (svn_fs_base__matches_atom(kind_skel, "delete")) { if (kind) *kind = svn_fs_path_change_delete; return TRUE; } if (svn_fs_base__matches_atom(kind_skel, "replace")) { if (kind) *kind = svn_fs_path_change_replace; return TRUE; } if (svn_fs_base__matches_atom(kind_skel, "modify")) { if (kind) *kind = svn_fs_path_change_modify; return TRUE; } } return FALSE;}static svn_boolean_tis_valid_lock_skel(skel_t *skel){ if ((svn_fs_base__list_length(skel) == 8) && svn_fs_base__matches_atom(skel->children, "lock") && skel->children->next->is_atom && skel->children->next->next->is_atom && skel->children->next->next->next->is_atom && skel->children->next->next->next->next->is_atom && skel->children->next->next->next->next->next->is_atom && skel->children->next->next->next->next->next->next->is_atom && skel->children->next->next->next->next->next->next->next->is_atom) return TRUE; return FALSE;}/*** Parsing (conversion from skeleton to native FS type) ***/svn_error_t *svn_fs_base__parse_proplist_skel(apr_hash_t **proplist_p, skel_t *skel, apr_pool_t *pool){ apr_hash_t *proplist = NULL; skel_t *elt; /* Validate the skel. */ if (! is_valid_proplist_skel(skel)) return skel_err("proplist"); /* Create the returned structure */ if (skel->children) proplist = apr_hash_make(pool); for (elt = skel->children; elt; elt = elt->next->next) { svn_string_t *value = svn_string_ncreate(elt->next->data, elt->next->len, pool); apr_hash_set(proplist, apr_pstrmemdup(pool, elt->data, elt->len), elt->len, value); } /* Return the structure. */ *proplist_p = proplist; return SVN_NO_ERROR;}svn_error_t *svn_fs_base__parse_revision_skel(revision_t **revision_p, skel_t *skel, apr_pool_t *pool){ revision_t *revision; /* Validate the skel. */ if (! is_valid_revision_skel(skel)) return skel_err("revision"); /* Create the returned structure */ revision = apr_pcalloc(pool, sizeof(*revision)); revision->txn_id = apr_pstrmemdup(pool, skel->children->next->data, skel->children->next->len); /* Return the structure. */ *revision_p = revision; return SVN_NO_ERROR;}svn_error_t *svn_fs_base__parse_transaction_skel(transaction_t **transaction_p, skel_t *skel, apr_pool_t *pool){ transaction_t *transaction; transaction_kind_t kind; skel_t *root_id, *base_id_or_rev, *proplist, *copies; int len; /* Validate the skel. */ if (! is_valid_transaction_skel(skel, &kind)) return skel_err("transaction"); root_id = skel->children->next; base_id_or_rev = skel->children->next->next; proplist = skel->children->next->next->next; copies = skel->children->next->next->next->next; /* Create the returned structure */ transaction = apr_pcalloc(pool, sizeof(*transaction)); /* KIND */ transaction->kind = kind; /* REVISION or BASE-ID */ if (kind == transaction_kind_committed) { /* Committed transactions have a revision number... */ transaction->base_id = NULL; transaction->revision = atoi(apr_pstrmemdup(pool, base_id_or_rev->data, base_id_or_rev->len)); if (! SVN_IS_VALID_REVNUM(transaction->revision)) return skel_err("transaction"); } else { /* ...where unfinished transactions have a base node-revision-id. */ transaction->revision = SVN_INVALID_REVNUM; transaction->base_id = svn_fs_base__id_parse(base_id_or_rev->data, base_id_or_rev->len, pool); } /* ROOT-ID */ transaction->root_id = svn_fs_base__id_parse(root_id->data, root_id->len, pool); /* PROPLIST */ SVN_ERR(svn_fs_base__parse_proplist_skel(&(transaction->proplist), proplist, pool)); /* COPIES */ if ((len = svn_fs_base__list_length(copies))) { const char *copy_id; apr_array_header_t *txncopies; skel_t *cpy = copies->children; txncopies = apr_array_make(pool, len, sizeof(copy_id)); while (cpy) { copy_id = apr_pstrmemdup(pool, cpy->data, cpy->len); (*((const char **)(apr_array_push(txncopies)))) = copy_id; cpy = cpy->next;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -