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

📄 io.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Try to open a temporary file in the temporary dir, write to it,
   and then close it. */
static int test_tempdir(const char *temp_dir, apr_pool_t *p)
{
    apr_file_t *dummy_file;
    const char *path = apr_pstrcat(p, temp_dir, "/apr-tmp.XXXXXX", NULL);

    if (apr_file_mktemp(&dummy_file, (char *)path, 0, p) == APR_SUCCESS) {
        if (apr_file_putc('!', dummy_file) == APR_SUCCESS) {
            if (apr_file_close(dummy_file) == APR_SUCCESS) {
                return 1;
            }
        }
    }
    return 0;
}
#endif

svn_error_t *
svn_io_temp_dir (const char **dir,
                 apr_pool_t *pool)
{
#if 1  /* TODO: Remove this code when APR 0.9.6 is released. */
  apr_status_t apr_err;
  static const char *try_dirs[] = { "/tmp", "/usr/tmp", "/var/tmp" };
  static const char *try_envs[] = { "TMP", "TEMP", "TMPDIR" };
  const char *temp_dir;
  char *cwd;
  apr_size_t i;

  /* Our goal is to find a temporary directory suitable for writing
     into.  We'll only pay the price once if we're successful -- we
     cache our successful find.  Here's the order in which we'll try
     various paths:

       $TMP
       $TEMP
       $TMPDIR
       "C:\TEMP"     (windows only)
       "/tmp"
       "/var/tmp"
       "/usr/tmp"
       `pwd` 

     NOTE: This algorithm is basically the same one used by Python
     2.2's tempfile.py module. */

  /* Try the environment first. */
  for (i = 0; i < (sizeof(try_envs) / sizeof(const char *)); i++)
    {
      char *value;
      apr_err = apr_env_get(&value, try_envs[i], pool);
      if ((apr_err == APR_SUCCESS) && value)
        {
          apr_size_t len = strlen(value);
          if (len && (len < APR_PATH_MAX) && test_tempdir(value, pool))
	    {
              temp_dir = value;
              goto end;
            }
        }
    }
#ifdef WIN32
  /* Next, on Win32, try the C:\TEMP directory. */
  if (test_tempdir("C:\\TEMP", pool))
    {
      temp_dir = "C:\\TEMP";
      goto end;
    }
#endif /* WIN32 */
			    
  /* Next, try a set of hard-coded paths. */
  for (i = 0; i < (sizeof(try_dirs) / sizeof(const char *)); i++)
    {
      if (test_tempdir(try_dirs[i], pool))
        {
	  temp_dir = try_dirs[i];
          goto end;
        }
    }

  /* Finally, try the current working directory. */
  if (APR_SUCCESS == apr_filepath_get(&cwd, APR_FILEPATH_NATIVE, pool))
    {
      if (test_tempdir(cwd, pool))
        {
          temp_dir = cwd;
	  goto end;
        }
    }

  return svn_error_create
           (APR_EGENERAL, NULL, "Can't find a temporary directory");

end:
  *dir = svn_path_canonicalize(temp_dir, pool);
  return SVN_NO_ERROR;

#else
  apr_status_t apr_err = apr_temp_dir_get (dir, pool);

  if (apr_err)
    return svn_error_wrap_apr (apr_err, "Can't find a temporary directory");

  *dir = svn_path_canonicalize (*dir, pool);

  return SVN_NO_ERROR;
#endif
}




/*** Creating, copying and appending files. ***/

svn_error_t *
svn_io_copy_file (const char *src,
                  const char *dst,
                  svn_boolean_t copy_perms,
                  apr_pool_t *pool)
{
  apr_file_t *d;
  apr_status_t apr_err;
  const char *src_apr, *dst_tmp_apr;
  const char *dst_tmp;

  SVN_ERR (svn_path_cstring_from_utf8 (&src_apr, src, pool));

  /* For atomicity, we translate to a tmp file and then rename the tmp
     file over the real destination. */

  SVN_ERR (svn_io_open_unique_file (&d, &dst_tmp, dst, ".tmp", FALSE, pool));
  SVN_ERR (svn_path_cstring_from_utf8 (&dst_tmp_apr, dst_tmp, pool));

  SVN_ERR (svn_io_file_close (d, pool));

  apr_err = apr_file_copy (src_apr, dst_tmp_apr, APR_OS_DEFAULT, pool);
  if (apr_err)
    return svn_error_wrap_apr
      (apr_err, "Can't copy '%s' to '%s'", src, dst_tmp);

  /* If copying perms, set the perms on dst_tmp now, so they will be
     atomically inherited in the upcoming rename.  But note that we
     had to wait until now to set perms, because if they say
     read-only, then we'd have failed filling dst_tmp's contents. */

  /* ### FIXME: apr_file_copy with perms may fail on Win32.  We need a
     platform-specific implementation to get the permissions right. */
#ifndef WIN32
  if (copy_perms)
    {
      apr_file_t *s;
      apr_finfo_t finfo;

      SVN_ERR (svn_io_file_open (&s, src, APR_READ, APR_OS_DEFAULT, pool));
      SVN_ERR (svn_io_file_info_get (&finfo, APR_FINFO_PROT, s, pool));
      SVN_ERR (svn_io_file_close (s, pool));

      apr_err = apr_file_perms_set (dst_tmp_apr, finfo.protection);

      /* We shouldn't be able to get APR_INCOMPLETE or APR_ENOTIMPL
         here under normal circumstances, because the perms themselves
         came from a call to apr_file_info_get(), and we already know
         this is the non-Win32 case.  But if it does happen, it's not
         an error. */ 
      if ((apr_err != APR_SUCCESS)
          && (apr_err != APR_INCOMPLETE)
          && (apr_err != APR_ENOTIMPL))
        {
          return svn_error_wrap_apr
            (apr_err, "Can't set permissions on '%s'", dst_tmp);
        }
    }
#endif /* ! WIN32 */

  return svn_io_file_rename (dst_tmp, dst, pool);
}


svn_error_t *
svn_io_append_file (const char *src, const char *dst, apr_pool_t *pool)
{
  apr_status_t apr_err;
  const char *src_apr, *dst_apr;

  SVN_ERR (svn_path_cstring_from_utf8 (&src_apr, src, pool));
  SVN_ERR (svn_path_cstring_from_utf8 (&dst_apr, dst, pool));

  apr_err = apr_file_append (src_apr, dst_apr, APR_OS_DEFAULT, pool);

  if (apr_err)
    return svn_error_wrap_apr (apr_err, "Can't append '%s' to '%s'", src, dst);
  
  return SVN_NO_ERROR;
}


svn_error_t *svn_io_copy_dir_recursively (const char *src,
                                          const char *dst_parent,
                                          const char *dst_basename,
                                          svn_boolean_t copy_perms,
                                          svn_cancel_func_t cancel_func,
                                          void *cancel_baton,
                                          apr_pool_t *pool)
{
  svn_node_kind_t kind;
  apr_status_t status;
  const char *dst_path;
  apr_dir_t *this_dir;
  apr_finfo_t this_entry;
  apr_int32_t flags = APR_FINFO_TYPE | APR_FINFO_NAME;

  /* Make a subpool for recursion */
  apr_pool_t *subpool = svn_pool_create (pool);

  /* The 'dst_path' is simply dst_parent/dst_basename */
  dst_path = svn_path_join (dst_parent, dst_basename, pool);

  /* Sanity checks:  SRC and DST_PARENT are directories, and
     DST_BASENAME doesn't already exist in DST_PARENT. */
  SVN_ERR (svn_io_check_path (src, &kind, subpool));
  if (kind != svn_node_dir)
    return svn_error_createf (SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
                              "Source '%s' is not a directory",
                              src);

  SVN_ERR (svn_io_check_path (dst_parent, &kind, subpool));
  if (kind != svn_node_dir)
    return svn_error_createf (SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
                              "Destination '%s' is not a directory",
                              dst_parent);

  SVN_ERR (svn_io_check_path (dst_path, &kind, subpool));
  if (kind != svn_node_none)
    return svn_error_createf (SVN_ERR_ENTRY_EXISTS, NULL,
                              "Destination '%s' already exists",
                              dst_path);
  
  /* Create the new directory. */
  /* ### TODO: copy permissions? */
  SVN_ERR (svn_io_dir_make (dst_path, APR_OS_DEFAULT, pool));

  /* Loop over the dirents in SRC.  ('.' and '..' are auto-excluded) */
  SVN_ERR (svn_io_dir_open (&this_dir, src, subpool));

  for (status = apr_dir_read (&this_entry, flags, this_dir);
       status == APR_SUCCESS;
       status = apr_dir_read (&this_entry, flags, this_dir))
    {
      if ((this_entry.name[0] == '.')
          && ((this_entry.name[1] == '\0')
              || ((this_entry.name[1] == '.')
                  && (this_entry.name[2] == '\0'))))
        {
          continue;
        }
      else
        {
          const char *src_target, *entryname_utf8;

          if (cancel_func)
            SVN_ERR (cancel_func (cancel_baton));

          SVN_ERR (svn_path_cstring_to_utf8 (&entryname_utf8,
                                             this_entry.name, subpool));
          src_target = svn_path_join (src, entryname_utf8, subpool);
          
          if (this_entry.filetype == APR_REG) /* regular file */
            {
              const char *dst_target = svn_path_join (dst_path, entryname_utf8,
                                                      subpool);
              SVN_ERR (svn_io_copy_file (src_target, dst_target,
                                         copy_perms, subpool));
            }
          else if (this_entry.filetype == APR_LNK) /* symlink */
            {
              const char *dst_target = svn_path_join (dst_path, entryname_utf8,
                                                      subpool);
              SVN_ERR (svn_io_copy_link (src_target, dst_target,
                                         subpool));
            }
          else if (this_entry.filetype == APR_DIR) /* recurse */
            {
              SVN_ERR (svn_io_copy_dir_recursively 
                       (src_target,
                        dst_path,
                        entryname_utf8,
                        copy_perms,
                        cancel_func,
                        cancel_baton,
                        subpool));
            }
          /* ### support other APR node types someday?? */

        }
    }

  if (! (APR_STATUS_IS_ENOENT (status)))
    return svn_error_wrap_apr (status, "Can't read directory '%s'", src);

  status = apr_dir_close (this_dir);
  if (status)
    return svn_error_wrap_apr (status, "Error closing directory '%s'", src);

  /* Free any memory used by recursion */
  apr_pool_destroy (subpool);
           
  return SVN_NO_ERROR;
}


svn_error_t *
svn_io_make_dir_recursively (const char *path, apr_pool_t *pool)
{
  svn_error_t *err;
  char *dir;

  if (svn_path_is_empty (path))
    /* Empty path (current dir) is assumed to always exist,
       so we do nothing, per docs. */
    return SVN_NO_ERROR;

#if 0
  /* ### Use this implementation if/when apr_dir_make_recursive is
     available on all platforms, not just on Unix. --xbc */
  apr_err = apr_dir_make_recursive (path_apr, APR_OS_DEFAULT, pool);

  if (apr_err)
    return svn_error_wrap_apr (apr_err, "Can't make directory '%s'", path);

  return SVN_NO_ERROR;
#else

  /* Try to make PATH right out */
  err = svn_io_dir_make (path, APR_OS_DEFAULT, pool);

  if (! err || APR_STATUS_IS_EEXIST (err->apr_err))
    {
      /* We succeeded, or path already exists; either way we're done. */
      svn_error_clear (err);
      return SVN_NO_ERROR;
    }
  else if (APR_STATUS_IS_ENOENT (err->apr_err))
    {
      /* Missing an intermediate dir. */
      dir = svn_path_dirname (path, pool);
      SVN_ERR (svn_io_make_dir_recursively (dir, pool));
      return svn_io_dir_make (path, APR_OS_DEFAULT, pool);
    }
  else
    return err;
#endif
}

svn_error_t *svn_io_file_create (const char *file,
                                 const char *contents,
                                 apr_pool_t *pool)
{
  apr_file_t *f;
  apr_size_t written;

  SVN_ERR (svn_io_file_open (&f, file,
                             (APR_WRITE | APR_CREATE | APR_EXCL),
                             APR_OS_DEFAULT,
                             pool));
  SVN_ERR (svn_io_file_write_full (f, contents, strlen (contents), 
                                   &written, pool));
  SVN_ERR (svn_io_file_close (f, pool));

  return SVN_NO_ERROR;
}

svn_error_t *svn_io_dir_file_copy (const char *src_path, 
                                   const char *dest_path, 
                                   const char *file,
                                   apr_pool_t *pool)
{
  const char *file_dest_path = svn_path_join (dest_path, file, pool);
  const char *file_src_path = svn_path_join (src_path, file, pool);

  SVN_ERR (svn_io_copy_file (file_src_path, file_dest_path, TRUE, pool));

  return SVN_NO_ERROR;
}


/*** Modtime checking. ***/

svn_error_t *
svn_io_file_affected_time (apr_time_t *apr_time,
                           const char *path,
                           apr_pool_t *pool)
{
  apr_finfo_t finfo;

  SVN_ERR (svn_io_stat (&finfo, path, APR_FINFO_MIN | APR_FINFO_LINK, pool));

  *apr_time = finfo.mtime;

  return SVN_NO_ERROR;
}


svn_error_t *
svn_io_set_file_affected_time (apr_time_t apr_time,
                               const char *path,
                               apr_pool_t *pool)
{
  apr_status_t status;

⌨️ 快捷键说明

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