Index: subversion/include/svn_io.h =================================================================== --- subversion/include/svn_io.h (revision 19916) +++ subversion/include/svn_io.h (working copy) @@ -305,7 +305,8 @@ apr_pool_t *pool); -/** Minimally change the read-write permissions of a file. +/** Similar to svn_io_set_file_read_* functions. + * Change the read-write permissions of a file. * @since New in 1.1. * * When making @a path read-write on operating systems with unix style @@ -321,8 +322,10 @@ * * @a path is the utf8-encoded path to the file. If @a enable_write * is @c TRUE, then make the file read-write. If @c FALSE, make it - * write-only. If @a ignore_enoent is @c TRUE, don't fail if the target + * read-only. If @a ignore_enoent is @c TRUE, don't fail if the target * file doesn't exist. + * + * @deprecated Provided for backward compatibility with the 1.1 API. */ svn_error_t *svn_io_set_file_read_write_carefully(const char *path, svn_boolean_t enable_write, Index: subversion/libsvn_wc/props.c =================================================================== --- subversion/libsvn_wc/props.c (revision 19916) +++ subversion/libsvn_wc/props.c (working copy) @@ -1598,8 +1598,7 @@ to read-write */ if (value == NULL) { - SVN_ERR(svn_io_set_file_read_write_carefully(path, TRUE, - FALSE, pool)); + SVN_ERR(svn_io_set_file_read_write(path, FALSE, pool)); } else { Index: subversion/libsvn_wc/log.c =================================================================== --- subversion/libsvn_wc/log.c (revision 19916) +++ subversion/libsvn_wc/log.c (working copy) @@ -425,8 +425,7 @@ { /* No need to make a new file read_write: new files already are. */ if (same) - SVN_ERR(svn_io_set_file_read_write_carefully(filepath, TRUE, - FALSE, pool)); + SVN_ERR(svn_io_set_file_read_write(filepath, FALSE, pool)); *overwrote_working = TRUE; /* entry needs wc-file's timestamp */ } else Index: subversion/libsvn_wc/adm_ops.c =================================================================== --- subversion/libsvn_wc/adm_ops.c (revision 19916) +++ subversion/libsvn_wc/adm_ops.c (working copy) @@ -2348,8 +2348,7 @@ SVN_ERR(svn_wc_prop_get(&needs_lock, SVN_PROP_NEEDS_LOCK, path, adm_access, pool)); if (needs_lock) - SVN_ERR(svn_io_set_file_read_write_carefully(path, TRUE, - FALSE, pool)); + SVN_ERR(svn_io_set_file_read_write(path, FALSE, pool)); } return SVN_NO_ERROR; @@ -2382,8 +2381,7 @@ SVN_ERR(svn_wc_prop_get(&needs_lock, SVN_PROP_NEEDS_LOCK, path, adm_access, pool)); if (needs_lock) - SVN_ERR(svn_io_set_file_read_write_carefully(path, FALSE, - FALSE, pool)); + SVN_ERR(svn_io_set_file_read_only(path, FALSE, pool)); } return SVN_NO_ERROR; Index: subversion/libsvn_wc/translate.c =================================================================== --- subversion/libsvn_wc/translate.c (revision 19916) +++ subversion/libsvn_wc/translate.c (working copy) @@ -270,8 +270,7 @@ if (needs_lock != NULL) { - SVN_ERR(svn_io_set_file_read_write_carefully(path, FALSE, - FALSE, pool)); + SVN_ERR(svn_io_set_file_read_only(path, FALSE, pool)); if (did_set) *did_set = TRUE; } Index: subversion/libsvn_subr/io.c =================================================================== --- subversion/libsvn_subr/io.c (revision 19916) +++ subversion/libsvn_subr/io.c (working copy) @@ -1135,55 +1135,6 @@ /*** Permissions and modes. ***/ -svn_error_t * -svn_io_set_file_read_only(const char *path, - svn_boolean_t ignore_enoent, - apr_pool_t *pool) -{ - apr_status_t status; - const char *path_apr; - - SVN_ERR(svn_path_cstring_from_utf8(&path_apr, path, pool)); - - status = apr_file_attrs_set(path_apr, - APR_FILE_ATTR_READONLY, - APR_FILE_ATTR_READONLY, - pool); - - if (status && status != APR_ENOTIMPL) - if (!ignore_enoent || !APR_STATUS_IS_ENOENT(status)) - return svn_error_wrap_apr(status, - _("Can't set file '%s' read-only"), - svn_path_local_style(path, pool)); - - return SVN_NO_ERROR; -} - - -svn_error_t * -svn_io_set_file_read_write(const char *path, - svn_boolean_t ignore_enoent, - apr_pool_t *pool) -{ - apr_status_t status; - const char *path_apr; - - SVN_ERR(svn_path_cstring_from_utf8(&path_apr, path, pool)); - - status = apr_file_attrs_set(path_apr, - 0, - APR_FILE_ATTR_READONLY, - pool); - - if (status && status != APR_ENOTIMPL) - if (!ignore_enoent || !APR_STATUS_IS_ENOENT(status)) - return svn_error_wrap_apr(status, - _("Can't set file '%s' read-write"), - svn_path_local_style(path, pool)); - - return SVN_NO_ERROR; -} - /* Given the file specified by PATH_APR, attempt to create an identical version of it owned by the current user. This is done by moving it to a temporary location, copying the file back to its old @@ -1256,6 +1207,23 @@ 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); +} + +/* This is a helper function for the svn_io_set_file_read* functions + that attempts to honor the users umask when dealing with + permission changes. */ +static svn_error_t * +io_set_file_perms(const char *path, + svn_boolean_t change_readwrite, + svn_boolean_t enable_write, + svn_boolean_t change_executable, + svn_boolean_t executable, + svn_boolean_t ignore_enoent, + apr_pool_t *pool) +{ apr_status_t status; const char *path_apr; apr_finfo_t finfo; @@ -1264,9 +1232,9 @@ SVN_ERR(svn_path_cstring_from_utf8(&path_apr, path, pool)); /* Try to change only a minimal amount of the perms first - by getting the current perms and adding execute bits + by getting the current perms and adding bits only on where read perms are granted. If this fails - fall through to the svn_io_set_file* calls. */ + fall through to just setting file attributes. */ status = apr_stat(&finfo, path_apr, APR_FINFO_PROT, pool); if (status) { @@ -1274,17 +1242,17 @@ return SVN_NO_ERROR; else if (status != APR_ENOTIMPL) return svn_error_wrap_apr(status, - _("Can't change read-write perms of " - "file '%s'"), + _("Can't change perms of file '%s'"), svn_path_local_style(path, pool)); - } - else + return SVN_NO_ERROR; + } + + perms_to_set = finfo.protection; + if (change_readwrite) { - perms_to_set = finfo.protection; if (enable_write) /* Make read-write. */ - SVN_ERR(get_default_file_perms(path, &perms_to_set, - pool)); - else /* Make read-only. */ + SVN_ERR(get_default_file_perms(path, &perms_to_set, pool)); + else { if (finfo.protection & APR_UREAD) perms_to_set &= ~APR_UWRITE; @@ -1293,161 +1261,166 @@ if (finfo.protection & APR_WREAD) perms_to_set &= ~APR_WWRITE; } + } - /* If we aren't changing anything then just return, this save - some system calls and helps with shared working copies */ - if (perms_to_set == finfo.protection) - return SVN_NO_ERROR; + if (change_executable) + { + if (executable) + { + if (finfo.protection & APR_UREAD) + perms_to_set |= APR_UEXECUTE; + if (finfo.protection & APR_GREAD) + perms_to_set |= APR_GEXECUTE; + if (finfo.protection & APR_WREAD) + perms_to_set |= APR_WEXECUTE; + } + else + { + if (finfo.protection & APR_UREAD) + perms_to_set &= ~APR_UEXECUTE; + if (finfo.protection & APR_GREAD) + perms_to_set &= ~APR_GEXECUTE; + if (finfo.protection & APR_WREAD) + perms_to_set &= ~APR_WEXECUTE; + } + } + /* 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_apr, pool)); status = apr_file_perms_set(path_apr, perms_to_set); - if (status) - { - 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_apr, pool)); - status = apr_file_perms_set(path_apr, perms_to_set); - } + if (!status) + return SVN_NO_ERROR; - if (status) - { - if (ignore_enoent && APR_STATUS_IS_ENOENT(status)) - return SVN_NO_ERROR; - else if (status == APR_ENOTIMPL) /* on win32, for example. */ - { - if (enable_write) - SVN_ERR(svn_io_set_file_read_write(path, ignore_enoent, - pool)); + 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; - else - SVN_ERR(svn_io_set_file_read_only(path, ignore_enoent, - pool)); - } - else - return svn_error_wrap_apr - (status, _("Can't change read-write perms of file '%s'"), - svn_path_local_style(path, pool)); - } - else - return SVN_NO_ERROR; + if (change_readwrite) + { + attrs = APR_FILE_ATTR_READONLY; + if (!enable_write) + attrs_values = APR_FILE_ATTR_READONLY; } - else - return SVN_NO_ERROR; - } - return SVN_NO_ERROR; + 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_path_local_style(path, pool)); } svn_error_t * -svn_io_set_file_executable(const char *path, - svn_boolean_t executable, - svn_boolean_t ignore_enoent, - apr_pool_t *pool) +svn_io_set_file_read_only(const char *path, + svn_boolean_t ignore_enoent, + apr_pool_t *pool) { + /* On Windows, just set the file attributes -- on unix call + our internal function which attempts to honor the umask. */ +#ifndef WIN32 + return io_set_file_perms(path, TRUE, FALSE, FALSE, FALSE, + ignore_enoent, pool); +#else apr_status_t status; const char *path_apr; SVN_ERR(svn_path_cstring_from_utf8(&path_apr, path, pool)); - if (executable) - { - apr_finfo_t finfo; - apr_fileperms_t perms_to_set; + status = apr_file_attrs_set(path_apr, + APR_FILE_ATTR_READONLY, + APR_FILE_ATTR_READONLY, + pool); - /* Try to change only a minimal amount of the perms first - by getting the current perms and adding execute bits - only on where read perms are granted. If this fails - fall through to the apr_file_perms_set() call. */ - status = apr_stat(&finfo, path_apr, APR_FINFO_PROT, pool); - if (status) - { - if (ignore_enoent && APR_STATUS_IS_ENOENT(status)) - return SVN_NO_ERROR; - else if (status != APR_ENOTIMPL) - return svn_error_wrap_apr(status, - _("Can't change executability of " - "file '%s'"), - svn_path_local_style(path, pool)); - } - else - { - perms_to_set = finfo.protection; - if (finfo.protection & APR_UREAD) - perms_to_set |= APR_UEXECUTE; - if (finfo.protection & APR_GREAD) - perms_to_set |= APR_GEXECUTE; - if (finfo.protection & APR_WREAD) - perms_to_set |= APR_WEXECUTE; + if (status && status != APR_ENOTIMPL) + if (!ignore_enoent || !APR_STATUS_IS_ENOENT(status)) + return svn_error_wrap_apr(status, + _("Can't set file '%s' read-only"), + svn_path_local_style(path, pool)); - /* If we aren't changing anything then just return, this save - some system calls and helps with shared working copies */ - if (perms_to_set == finfo.protection) - return SVN_NO_ERROR; + return SVN_NO_ERROR; +#endif +} - status = apr_file_perms_set(path_apr, perms_to_set); - if (status) - { - 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_apr, pool)); - status = apr_file_perms_set(path_apr, perms_to_set); - } +svn_error_t * +svn_io_set_file_read_write(const char *path, + svn_boolean_t ignore_enoent, + apr_pool_t *pool) +{ + /* On Windows, just set the file attributes -- on unix call + our internal function which attempts to honor the umask. */ +#ifndef WIN32 + return io_set_file_perms(path, TRUE, TRUE, FALSE, FALSE, + ignore_enoent, pool); +#else + apr_status_t status; + const char *path_apr; - if (status) - { - if (ignore_enoent && APR_STATUS_IS_ENOENT(status)) - return SVN_NO_ERROR; - else if (status != APR_ENOTIMPL) - return svn_error_wrap_apr - (status, _("Can't change executability of file '%s'"), - svn_path_local_style(path, pool)); - } - else - return SVN_NO_ERROR; - } - else - return SVN_NO_ERROR; - } - - status = apr_file_attrs_set(path_apr, - APR_FILE_ATTR_EXECUTABLE, - APR_FILE_ATTR_EXECUTABLE, - pool); - } - else - status = apr_file_attrs_set(path_apr, - 0, - APR_FILE_ATTR_EXECUTABLE, - pool); - + SVN_ERR(svn_path_cstring_from_utf8(&path_apr, path, pool)); + + status = apr_file_attrs_set(path_apr, + 0, + APR_FILE_ATTR_READONLY, + pool); + if (status && status != APR_ENOTIMPL) if (!ignore_enoent || !APR_STATUS_IS_ENOENT(status)) return svn_error_wrap_apr(status, - _("Can't change executability of file '%s'"), + _("Can't set file '%s' read-write"), svn_path_local_style(path, pool)); - + return SVN_NO_ERROR; +#endif } +svn_error_t * +svn_io_set_file_executable(const char *path, + svn_boolean_t executable, + svn_boolean_t ignore_enoent, + apr_pool_t *pool) +{ + /* On Windows, just exit -- on unix call our internal function + which attempts to honor the umask. */ +#ifndef WIN32 + return io_set_file_perms(path, FALSE, FALSE, TRUE, executable, + ignore_enoent, pool); +#else + return SVN_NO_ERROR; +#endif +} + svn_error_t * svn_io_is_file_executable(svn_boolean_t *executable, const char *path,