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 )