⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adm_files.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * adm_files.c: helper routines for handling files & dirs in the
 *              working copy administrative area (creating,
 *              deleting, opening, and closing).  This is the only
 *              code that actually knows where administrative
 *              information is kept.  
 *
 * ====================================================================
 * 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 <stdarg.h>
#include <assert.h>
#include <apr_pools.h>
#include <apr_hash.h>
#include <apr_file_io.h>
#include <apr_time.h>
#include <apr_strings.h>
#include "svn_types.h"
#include "svn_string.h"
#include "svn_error.h"
#include "svn_hash.h"
#include "svn_io.h"
#include "svn_path.h"
#include "svn_wc.h"

#include "wc.h"
#include "adm_files.h"
#include "entries.h"

#include "svn_private_config.h"


/*** File names in the adm area. ***/


/* Return the path to something in PATH's administrative area.
 * 
 * First, the adm subdir is appended to PATH as a component, then the
 * "tmp" directory is added iff USE_TMP is set, then each of the
 * varargs in AP (char *'s) is appended as a path component.  The list
 * must be terminated with a NULL argument.
 *
 * Adding an empty component results in no effect (i.e., the separator
 * char is not doubled).
 *
 * If EXTENSION is non-null, it will be appended to the final string
 * without a separator character.
 */
static const char *
v_extend_with_adm_name (const char *path,
                        const char *extension,
                        svn_boolean_t use_tmp,
                        apr_pool_t *pool,
                        va_list ap)
{
  const char *this;

  /* Tack on the administrative subdirectory. */
  path = svn_path_join (path, SVN_WC_ADM_DIR_NAME, pool);

  /* If this is a tmp file, name it into the tmp area. */
  if (use_tmp)
    path = svn_path_join (path, SVN_WC__ADM_TMP, pool);

  /* Tack on everything else. */
  while ((this = va_arg (ap, const char *)) != NULL)
    {
      if (this[0] == '\0')
        continue;

      path = svn_path_join (path, this, pool);
    }

  if (extension)
    path = apr_pstrcat (pool, path, extension, NULL);

  return path;
}


/* See v_extend_with_adm_name() for details. */
static const char *
extend_with_adm_name (const char *path,
                      const char *extension,
                      svn_boolean_t use_tmp,
                      apr_pool_t *pool,
                      ...)
{
  va_list ap;

  va_start (ap, pool);
  path = v_extend_with_adm_name (path, extension, use_tmp, pool, ap);
  va_end (ap);

  return path;
}


const char *
svn_wc__adm_path (const char *path,
                  svn_boolean_t tmp,
                  apr_pool_t *pool, 
                  ...)
{
  va_list ap;

  va_start (ap, pool);
  path = v_extend_with_adm_name (path, NULL, tmp, pool, ap);
  va_end (ap);

  return path;
}


svn_boolean_t
svn_wc__adm_path_exists (const char *path,
                         svn_boolean_t tmp,
                         apr_pool_t *pool, 
                         ...)
{
  svn_node_kind_t kind;
  svn_error_t *err;
  va_list ap;

  va_start (ap, pool);
  path = v_extend_with_adm_name (path, NULL, tmp, pool, ap);
  va_end (ap);

  err = svn_io_check_path (path, &kind, pool);
  if (err)
    svn_error_clear (err);
  if (kind == svn_node_none)
    return FALSE;
  else
    return TRUE;
}



/*** Making and using files in the adm area. ***/


/* Create an empty THING in the adm area with permissions set to PERMS. 
 * If TMP is non-zero, then create THING in the tmp dir.
 *
 * Does not check if THING already exists, so be careful -- THING will
 * be empty after this no matter what.
 */
svn_error_t *
svn_wc__make_adm_thing (svn_wc_adm_access_t *adm_access,
                        const char *thing,
                        svn_node_kind_t type,
                        apr_fileperms_t perms,
                        svn_boolean_t tmp,
                        apr_pool_t *pool)
{
  svn_error_t *err = SVN_NO_ERROR;
  apr_file_t *f = NULL;
  const char *path;

  SVN_ERR (svn_wc__adm_write_check (adm_access));

  path = extend_with_adm_name (svn_wc_adm_access_path (adm_access),
                               NULL, tmp, pool, thing, NULL);

  if (type == svn_node_file)
    {
      SVN_ERR (svn_io_file_open (&f, path,
                                 (APR_WRITE | APR_CREATE | APR_EXCL),
                                 perms,
                                 pool));

      /* Creation succeeded, so close immediately. */
      SVN_ERR (svn_io_file_close (f, pool));
    }
  else if (type == svn_node_dir)
    {
      SVN_ERR (svn_io_dir_make (path, perms, pool));
    }
  else   /* unknown type argument, wrongness */
    {
      /* We're only capturing this here because there wouldn't be a
         segfault or other obvious indicator that something went
         wrong.  Even so, not sure if it's appropriate.  Thoughts? */
      err = svn_error_create 
        (0, NULL, _("Bad type indicator"));
    }

  return err;
}



/*** Syncing files in the adm area. ***/

static svn_error_t *
sync_adm_file (const char *path,
               const char *extension,
               apr_pool_t *pool,
               ...)
{
  /* Some code duplication with close_adm_file() seems unavoidable,
     given how C va_lists work. */

  const char *tmp_path;
  va_list ap;
  
  /* Extend tmp name. */
  va_start (ap, pool);
  tmp_path = v_extend_with_adm_name (path, extension, 1, pool, ap);
  va_end (ap);
  
  /* Extend real name. */
  va_start (ap, pool);
  path = v_extend_with_adm_name (path, extension, 0, pool, ap);
  va_end (ap);
  
  /* Rename. */
  SVN_ERR (svn_wc__prep_file_for_replacement (path, TRUE, pool));
  SVN_ERR (svn_io_file_rename (tmp_path, path, pool));
  SVN_ERR (svn_io_set_file_read_only (path, FALSE, pool));

  return SVN_NO_ERROR;
}


/* Rename a tmp text-base file to its real text-base name.
   The file had better already be closed. */
svn_error_t *
svn_wc__sync_text_base (const char *path, apr_pool_t *pool)
{
  const char *parent_path, *base_name;
  svn_path_split (path, &parent_path, &base_name, pool);
  return sync_adm_file (parent_path,
                        SVN_WC__BASE_EXT,
                        pool,
                        SVN_WC__ADM_TEXT_BASE,
                        base_name,
                        NULL);
}

const char *
svn_wc__text_base_path (const char *path,
                        svn_boolean_t tmp,
                        apr_pool_t *pool)
{
  const char *newpath, *base_name;

  svn_path_split (path, &newpath, &base_name, pool);
  return extend_with_adm_name (newpath,
                               SVN_WC__BASE_EXT,
                               tmp,
                               pool,
                               SVN_WC__ADM_TEXT_BASE,
                               base_name,
                               NULL);
}


static svn_error_t *
prop_path_internal (const char **prop_path,
                    const char *path,
                    svn_wc_adm_access_t *adm_access,
                    svn_boolean_t base,
                    svn_boolean_t wcprop,
                    svn_boolean_t tmp,
                    apr_pool_t *pool)
{
  const svn_wc_entry_t *entry;
  const char *entry_name;

  SVN_ERR (svn_wc_entry (&entry, path, adm_access, FALSE, pool));

  if (entry && entry->kind == svn_node_dir)  /* It's a working copy dir */
    {
      *prop_path = extend_with_adm_name
        (path,
         NULL,
         tmp,
         pool,
         base ? SVN_WC__ADM_DIR_PROP_BASE
         : (wcprop ? SVN_WC__ADM_DIR_WCPROPS : SVN_WC__ADM_DIR_PROPS),
         NULL);
    }
  else  /* It's either a file, or a non-wc dir (i.e., maybe an ex-file) */
    {
      int wc_format = svn_wc__adm_wc_format (adm_access);
      svn_path_split (path, prop_path, &entry_name, pool);
      if (wc_format <= SVN_WC__OLD_PROPNAMES_VERSION)
        {
          *prop_path = extend_with_adm_name
            (*prop_path,
             base ? SVN_WC__BASE_EXT : NULL,
             tmp,
             pool,
             base ? SVN_WC__ADM_PROP_BASE
             : (wcprop ? SVN_WC__ADM_WCPROPS : SVN_WC__ADM_PROPS),
             entry_name,
             NULL);
        }
      else
        {
          *prop_path = extend_with_adm_name
            (*prop_path,
             base ? SVN_WC__BASE_EXT : SVN_WC__WORK_EXT,
             tmp,
             pool,
             base ? SVN_WC__ADM_PROP_BASE
             : (wcprop ? SVN_WC__ADM_WCPROPS : SVN_WC__ADM_PROPS),
             entry_name,
             NULL);
        }
    }

  return SVN_NO_ERROR;
}



/* Return a path to the 'wcprop' file for PATH, possibly in TMP area.  */
svn_error_t *
svn_wc__wcprop_path (const char **wcprop_path,
                     const char *path,
                     svn_wc_adm_access_t *adm_access,
                     svn_boolean_t tmp,
                     apr_pool_t *pool)
{
  return prop_path_internal (wcprop_path, path, adm_access, FALSE, TRUE, tmp,
                             pool);
}




svn_error_t *
svn_wc__prop_path (const char **prop_path,
                   const char *path,
                   svn_wc_adm_access_t *adm_access,
                   svn_boolean_t tmp,
                   apr_pool_t *pool)
{
  return prop_path_internal (prop_path, path, adm_access, FALSE, FALSE, tmp,
                             pool);
}


svn_error_t *
svn_wc__prop_base_path (const char **prop_path,
                        const char *path,
                        svn_wc_adm_access_t *adm_access,
                        svn_boolean_t tmp,
                        apr_pool_t *pool)
{
  return prop_path_internal (prop_path, path, adm_access, TRUE, FALSE, tmp,
                             pool);
}




/*** Opening and closing files in the adm area. ***/

/* Open a file somewhere in the adm area for directory PATH.
 * First, add the adm subdir as the next component of PATH, then add
 * each of the varargs (they are char *'s), then add EXTENSION if it
 * is non-null, then open the resulting file as *HANDLE.
 *
 * If FLAGS indicates writing, open the file in the adm tmp area.
 * This means the file will probably need to be renamed from there,
 * either by passing the sync flag to close_adm_file() later, or with
 * an explicit call to sync_adm_file().
 */
static svn_error_t *
open_adm_file (apr_file_t **handle,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -