Alien-SVN

 view release on metacpan or  search on metacpan

src/subversion/subversion/libsvn_subr/io.c  view on Meta::CPAN


  /* If we aren't changing anything then just return, this saves
     some system calls and helps with shared working copies */
  if (perms_to_set == finfo.protection)
    return SVN_NO_ERROR;

  status = apr_file_perms_set(path_apr, perms_to_set);
  if (!status)
    return SVN_NO_ERROR;

  if (APR_STATUS_IS_EPERM(status))
    {
      /* We don't have permissions to change the
         permissions!  Try a move, copy, and delete
         workaround to see if we can get the file owned by
         us.  If these succeed, try the permissions set
         again.

         Note that we only attempt this in the
         stat-available path.  This assumes that the
         move-copy workaround will only be helpful on
         platforms that implement apr_stat. */
      SVN_ERR(reown_file(path, pool));
      status = apr_file_perms_set(path_apr, perms_to_set);
    }

  if (!status)
    return SVN_NO_ERROR;

  if (ignore_enoent && APR_STATUS_IS_ENOENT(status))
    return SVN_NO_ERROR;
  else if (status == APR_ENOTIMPL)
    {
      /* At least try to set the attributes. */
      apr_fileattrs_t attrs = 0;
      apr_fileattrs_t attrs_values = 0;

      if (change_readwrite)
        {
          attrs = APR_FILE_ATTR_READONLY;
          if (!enable_write)
            attrs_values = APR_FILE_ATTR_READONLY;
        }
      if (change_executable)
        {
          attrs = APR_FILE_ATTR_EXECUTABLE;
          if (executable)
            attrs_values = APR_FILE_ATTR_EXECUTABLE;
        }
      status = apr_file_attrs_set(path_apr, attrs, attrs_values, pool);
    }

  return svn_error_wrap_apr(status,
                            _("Can't change perms of file '%s'"),
                            svn_dirent_local_style(path, pool));
}
#endif /* !WIN32 && !__OS2__ */

#ifdef WIN32
#if APR_HAS_UNICODE_FS
/* copy of the apr function utf8_to_unicode_path since apr doesn't export this one */
static apr_status_t io_utf8_to_unicode_path(apr_wchar_t* retstr, apr_size_t retlen,
                                            const char* srcstr)
{
    /* TODO: The computations could preconvert the string to determine
     * the true size of the retstr, but that's a memory over speed
     * tradeoff that isn't appropriate this early in development.
     *
     * Allocate the maximum string length based on leading 4
     * characters of \\?\ (allowing nearly unlimited path lengths)
     * plus the trailing null, then transform /'s into \\'s since
     * the \\?\ form doesn't allow '/' path separators.
     *
     * Note that the \\?\ form only works for local drive paths, and
     * \\?\UNC\ is needed UNC paths.
     */
    apr_size_t srcremains = strlen(srcstr) + 1;
    apr_wchar_t *t = retstr;
    apr_status_t rv;

    /* This is correct, we don't twist the filename if it will
     * definitely be shorter than 248 characters.  It merits some
     * performance testing to see if this has any effect, but there
     * seem to be applications that get confused by the resulting
     * Unicode \\?\ style file names, especially if they use argv[0]
     * or call the Win32 API functions such as GetModuleName, etc.
     * Not every application is prepared to handle such names.
     *
     * Note also this is shorter than MAX_PATH, as directory paths
     * are actually limited to 248 characters.
     *
     * Note that a utf-8 name can never result in more wide chars
     * than the original number of utf-8 narrow chars.
     */
    if (srcremains > 248) {
        if (srcstr[1] == ':' && (srcstr[2] == '/' || srcstr[2] == '\\')) {
            wcscpy (retstr, L"\\\\?\\");
            retlen -= 4;
            t += 4;
        }
        else if ((srcstr[0] == '/' || srcstr[0] == '\\')
              && (srcstr[1] == '/' || srcstr[1] == '\\')
              && (srcstr[2] != '?')) {
            /* Skip the slashes */
            srcstr += 2;
            srcremains -= 2;
            wcscpy (retstr, L"\\\\?\\UNC\\");
            retlen -= 8;
            t += 8;
        }
    }

    if (rv = apr_conv_utf8_to_ucs2(srcstr, &srcremains, t, &retlen)) {
        return (rv == APR_INCOMPLETE) ? APR_EINVAL : rv;
    }
    if (srcremains) {
        return APR_ENAMETOOLONG;
    }
    for (; *t; ++t)
        if (*t == L'/')
            *t = L'\\';
    return APR_SUCCESS;
}
#endif

static apr_status_t io_win_file_attrs_set(const char *fname,
                                          DWORD attributes,
                                          DWORD attr_mask,
                                          apr_pool_t *pool)
{
    /* this is an implementation of apr_file_attrs_set() but one
       that uses the proper Windows attributes instead of the apr
       attributes. This way, we can apply any Windows file and
       folder attributes even if apr doesn't implement them */
    DWORD flags;
    apr_status_t rv;
#if APR_HAS_UNICODE_FS
    apr_wchar_t wfname[APR_PATH_MAX];
#endif

#if APR_HAS_UNICODE_FS
    IF_WIN_OS_IS_UNICODE
    {
        if (rv = io_utf8_to_unicode_path(wfname,
                                         sizeof(wfname) / sizeof(wfname[0]),
                                         fname))
            return rv;
        flags = GetFileAttributesW(wfname);
    }
#endif
#if APR_HAS_ANSI_FS
    ELSE_WIN_OS_IS_ANSI
    {
        flags = GetFileAttributesA(fname);
    }
#endif

    if (flags == 0xFFFFFFFF)
        return apr_get_os_error();

    flags &= ~attr_mask;
    flags |= (attributes & attr_mask);

#if APR_HAS_UNICODE_FS
    IF_WIN_OS_IS_UNICODE
    {
        rv = SetFileAttributesW(wfname, flags);
    }
#endif
#if APR_HAS_ANSI_FS
    ELSE_WIN_OS_IS_ANSI
    {
        rv = SetFileAttributesA(fname, flags);
    }
#endif

    if (rv == 0)
        return apr_get_os_error();

    return APR_SUCCESS;
}

#endif

svn_error_t *
svn_io_set_file_read_write_carefully(const char *path,
                                     svn_boolean_t enable_write,
                                     svn_boolean_t ignore_enoent,
                                     apr_pool_t *pool)
{
  if (enable_write)
    return svn_io_set_file_read_write(path, ignore_enoent, pool);
  return svn_io_set_file_read_only(path, ignore_enoent, pool);
}

svn_error_t *
svn_io_set_file_read_only(const char *path,
                          svn_boolean_t ignore_enoent,
                          apr_pool_t *pool)
{
  /* On Windows and OS/2, just set the file attributes -- on unix call
     our internal function which attempts to honor the umask. */
#if !defined(WIN32) && !defined(__OS2__)
  return io_set_file_perms(path, TRUE, FALSE, FALSE, FALSE,



( run in 1.091 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )