summaryrefslogtreecommitdiff
path: root/subversion/libsvn_subr/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_subr/io.c')
-rw-r--r--subversion/libsvn_subr/io.c299
1 files changed, 186 insertions, 113 deletions
diff --git a/subversion/libsvn_subr/io.c b/subversion/libsvn_subr/io.c
index 468dd1723804f..8c4f26760507e 100644
--- a/subversion/libsvn_subr/io.c
+++ b/subversion/libsvn_subr/io.c
@@ -578,10 +578,8 @@ svn_io_open_uniquely_named(apr_file_t **file,
continue;
#ifdef WIN32
- apr_err_2 = APR_TO_OS_ERROR(apr_err);
-
- if (apr_err_2 == ERROR_ACCESS_DENIED ||
- apr_err_2 == ERROR_SHARING_VIOLATION)
+ if (apr_err == APR_FROM_OS_ERROR(ERROR_ACCESS_DENIED) ||
+ apr_err == APR_FROM_OS_ERROR(ERROR_SHARING_VIOLATION))
{
/* The file is in use by another process or is hidden;
create a new name, but don't do this 99999 times in
@@ -773,7 +771,7 @@ svn_io_copy_link(const char *src,
".tmp", pool));
/* Move the tmp-link to link. */
- return svn_io_file_rename(dst_tmp, dst, pool);
+ return svn_io_file_rename2(dst_tmp, dst, FALSE, pool);
#else
return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
@@ -942,7 +940,7 @@ svn_io_copy_file(const char *src,
if (copy_perms)
SVN_ERR(svn_io_copy_perms(src, dst_tmp, pool));
- return svn_error_trace(svn_io_file_rename(dst_tmp, dst, pool));
+ return svn_error_trace(svn_io_file_rename2(dst_tmp, dst, FALSE, pool));
}
#if !defined(WIN32) && !defined(__OS2__)
@@ -1480,18 +1478,14 @@ svn_io_file_checksum2(svn_checksum_t **checksum,
apr_pool_t *pool)
{
svn_stream_t *file_stream;
- svn_stream_t *checksum_stream;
apr_file_t* f;
SVN_ERR(svn_io_file_open(&f, file, APR_READ, APR_OS_DEFAULT, pool));
file_stream = svn_stream_from_aprfile2(f, FALSE, pool);
- checksum_stream = svn_stream_checksummed2(file_stream, checksum, NULL, kind,
- TRUE, pool);
+ SVN_ERR(svn_stream_contents_checksum(checksum, file_stream, kind,
+ pool, pool));
- /* Because the checksummed stream will force the reading (and
- checksumming) of all the file's bytes, we can just close the stream
- and let its magic work. */
- return svn_stream_close(checksum_stream);
+ return SVN_NO_ERROR;
}
@@ -1527,20 +1521,23 @@ reown_file(const char *path,
SVN_ERR(svn_io_open_unique_file3(NULL, &unique_name,
svn_dirent_dirname(path, pool),
svn_io_file_del_none, pool, pool));
- SVN_ERR(svn_io_file_rename(path, unique_name, pool));
+ SVN_ERR(svn_io_file_rename2(path, unique_name, FALSE, pool));
SVN_ERR(svn_io_copy_file(unique_name, path, TRUE, pool));
return svn_error_trace(svn_io_remove_file2(unique_name, FALSE, pool));
}
/* Determine what the PERMS for a new file should be by looking at the
- permissions of a temporary file that we create.
+ permissions of a temporary file that we create in DIRECTORY.
+ DIRECTORY can be NULL in which case the system temporary dir is used.
Unfortunately, umask() as defined in POSIX provides no thread-safe way
to get at the current value of the umask, so what we're doing here is
the only way we have to determine which combination of write bits
(User/Group/World) should be set by default.
Make temporary allocations in SCRATCH_POOL. */
static svn_error_t *
-get_default_file_perms(apr_fileperms_t *perms, apr_pool_t *scratch_pool)
+get_default_file_perms(apr_fileperms_t *perms,
+ const char *directory,
+ apr_pool_t *scratch_pool)
{
/* the default permissions as read from the temp folder */
static apr_fileperms_t default_perms = 0;
@@ -1567,12 +1564,18 @@ get_default_file_perms(apr_fileperms_t *perms, apr_pool_t *scratch_pool)
Using svn_io_open_uniquely_named() here because other tempfile
creation functions tweak the permission bits of files they create.
+
+ Note that APR pool structures are allocated as the first item
+ in their first memory page (with e.g. 4kB granularity), i.e. the
+ lower bits tend to be identical between pool instances. That is
+ particularly true for the MMAPed allocator.
*/
randomish = ((apr_uint32_t)(apr_uintptr_t)scratch_pool
+ + (apr_uint32_t)((apr_uintptr_t)scratch_pool / 4096)
+ (apr_uint32_t)apr_time_now());
fname_base = apr_psprintf(scratch_pool, "svn-%08x", randomish);
- SVN_ERR(svn_io_open_uniquely_named(&fd, &fname, NULL, fname_base,
+ SVN_ERR(svn_io_open_uniquely_named(&fd, &fname, directory, fname_base,
NULL, svn_io_file_del_none,
scratch_pool, scratch_pool));
err = svn_io_file_info_get(&finfo, APR_FINFO_PROT, fd, scratch_pool);
@@ -1590,16 +1593,19 @@ get_default_file_perms(apr_fileperms_t *perms, apr_pool_t *scratch_pool)
}
/* OR together permission bits of the file FD and the default permissions
- of a file as determined by get_default_file_perms(). Do temporary
+ of a file as determined by get_default_file_perms(). DIRECTORY is used
+ to create temporary files, DIRECTORY can be NULL. Do temporary
allocations in SCRATCH_POOL. */
static svn_error_t *
-merge_default_file_perms(apr_file_t *fd, apr_fileperms_t *perms,
+merge_default_file_perms(apr_file_t *fd,
+ apr_fileperms_t *perms,
+ const char *directory,
apr_pool_t *scratch_pool)
{
apr_finfo_t finfo;
apr_fileperms_t default_perms;
- SVN_ERR(get_default_file_perms(&default_perms, scratch_pool));
+ SVN_ERR(get_default_file_perms(&default_perms, directory, scratch_pool));
SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_PROT, fd, scratch_pool));
/* Glom the perms together. */
@@ -1768,7 +1774,7 @@ svn_io__utf8_to_unicode_longpath(const WCHAR **result,
* than the original number of utf-8 narrow chars.
*/
const WCHAR *prefix = NULL;
- const int srclen = strlen(source);
+ const size_t srclen = strlen(source);
WCHAR *buffer;
if (srclen > 248)
@@ -1879,12 +1885,12 @@ io_win_file_attrs_set(const char *fname,
_("Can't set attributes of file '%s'"),
svn_dirent_local_style(fname, pool));
- return SVN_NO_ERROR;;
+ return SVN_NO_ERROR;
}
static svn_error_t *win_init_dynamic_imports(void *baton, apr_pool_t *pool)
{
- HMODULE kernel32 = GetModuleHandleA("kernel32.dll");
+ HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
if (kernel32)
{
@@ -2274,7 +2280,6 @@ svn_io_is_file_executable(svn_boolean_t *executable,
/*** File locking. ***/
-#if !defined(WIN32) && !defined(__OS2__)
/* Clear all outstanding locks on ARG, an open apr_file_t *. */
static apr_status_t
file_clear_locks(void *arg)
@@ -2289,7 +2294,6 @@ file_clear_locks(void *arg)
return 0;
}
-#endif
svn_error_t *
svn_io_lock_open_file(apr_file_t *lockfile_handle,
@@ -2347,13 +2351,14 @@ svn_io_lock_open_file(apr_file_t *lockfile_handle,
}
}
-/* On Windows and OS/2 file locks are automatically released when
- the file handle closes */
-#if !defined(WIN32) && !defined(__OS2__)
+ /* On Windows, a process may not release file locks before closing the
+ handle, and in this case the outstanding locks are unlocked by the OS.
+ However, this is not recommended, because the actual unlocking may be
+ postponed depending on available system resources. We explicitly unlock
+ the file as a part of the pool cleanup handler. */
apr_pool_cleanup_register(pool, lockfile_handle,
file_clear_locks,
apr_pool_cleanup_null);
-#endif
return SVN_NO_ERROR;
}
@@ -2377,11 +2382,7 @@ svn_io_unlock_open_file(apr_file_t *lockfile_handle,
return svn_error_wrap_apr(apr_err, _("Can't unlock file '%s'"),
try_utf8_from_internal_style(fname, pool));
-/* On Windows and OS/2 file locks are automatically released when
- the file handle closes */
-#if !defined(WIN32) && !defined(__OS2__)
apr_pool_cleanup_kill(pool, lockfile_handle, file_clear_locks);
-#endif
return SVN_NO_ERROR;
}
@@ -2455,6 +2456,14 @@ svn_error_t *svn_io_file_flush_to_disk(apr_file_t *file,
apr_pool_t *pool)
{
apr_os_file_t filehand;
+ const char *fname;
+ apr_status_t apr_err;
+
+ /* We need this only in case of an error but this is cheap to get -
+ * so we do it here for clarity. */
+ apr_err = apr_file_name_get(&fname, file);
+ if (apr_err)
+ return svn_error_wrap_apr(apr_err, _("Can't get file name"));
/* ### In apr 1.4+ we could delegate most of this function to
apr_file_sync(). The only major difference is that this doesn't
@@ -2472,7 +2481,8 @@ svn_error_t *svn_io_file_flush_to_disk(apr_file_t *file,
if (! FlushFileBuffers(filehand))
return svn_error_wrap_apr(apr_get_os_error(),
- _("Can't flush file to disk"));
+ _("Can't flush file '%s' to disk"),
+ try_utf8_from_internal_style(fname, pool));
#else
int rv;
@@ -2493,7 +2503,8 @@ svn_error_t *svn_io_file_flush_to_disk(apr_file_t *file,
if (rv == -1)
return svn_error_wrap_apr(apr_get_os_error(),
- _("Can't flush file to disk"));
+ _("Can't flush file '%s' to disk"),
+ try_utf8_from_internal_style(fname, pool));
#endif
}
@@ -2640,9 +2651,6 @@ svn_io_remove_file2(const char *path,
allow us to delete when path is read-only */
SVN_ERR(svn_io_set_file_read_write(path, ignore_enoent, scratch_pool));
apr_err = apr_file_remove(path_apr, scratch_pool);
-
- if (!apr_err)
- return SVN_NO_ERROR;
}
/* Check to make sure we aren't trying to delete a directory */
@@ -2721,7 +2729,7 @@ svn_io_remove_dir2(const char *path, svn_boolean_t ignore_enoent,
If we need to bail out, do so early. */
if (cancel_func)
- SVN_ERR((*cancel_func)(cancel_baton));
+ SVN_ERR(cancel_func(cancel_baton));
subpool = svn_pool_create(pool);
@@ -2754,7 +2762,7 @@ svn_io_remove_dir2(const char *path, svn_boolean_t ignore_enoent,
else
{
if (cancel_func)
- SVN_ERR((*cancel_func)(cancel_baton));
+ SVN_ERR(cancel_func(cancel_baton));
err = svn_io_remove_file2(fullpath, FALSE, subpool);
if (err)
@@ -3736,6 +3744,32 @@ svn_io_file_info_get(apr_finfo_t *finfo, apr_int32_t wanted,
pool);
}
+svn_error_t *
+svn_io_file_size_get(svn_filesize_t *filesize_p, apr_file_t *file,
+ apr_pool_t *pool)
+{
+ apr_finfo_t finfo;
+ SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_SIZE, file, pool));
+
+ *filesize_p = finfo.size;
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_io_file_get_offset(apr_off_t *offset_p,
+ apr_file_t *file,
+ apr_pool_t *pool)
+{
+ apr_off_t offset;
+
+ /* Note that, for buffered files, one (possibly surprising) side-effect
+ of this call is to flush any unwritten data to disk. */
+ offset = 0;
+ SVN_ERR(svn_io_file_seek(file, APR_CUR, &offset, pool));
+ *offset_p = offset;
+
+ return SVN_NO_ERROR;
+}
svn_error_t *
svn_io_file_read(apr_file_t *file, void *buf,
@@ -3906,21 +3940,20 @@ svn_io_file_write_full(apr_file_t *file, const void *buf,
apr_size_t nbytes, apr_size_t *bytes_written,
apr_pool_t *pool)
{
- /* We cannot simply call apr_file_write_full on Win32 as it may fail
- for larger values of NBYTES. In that case, we have to emulate the
- "_full" part here. Thus, always call apr_file_write directly on
- Win32 as this minimizes overhead for small data buffers. */
#ifdef WIN32
#define MAXBUFSIZE 30*1024
apr_size_t bw = nbytes;
apr_size_t to_write = nbytes;
+ apr_status_t rv;
- /* try a simple "write everything at once" first */
- apr_status_t rv = apr_file_write(file, buf, &bw);
+ rv = apr_file_write_full(file, buf, nbytes, &bw);
buf = (char *)buf + bw;
to_write -= bw;
- /* if the OS cannot handle that, use smaller chunks */
+ /* Issue #1789: On Windows, writing may fail for large values of NBYTES.
+ If that is the case, keep track of how many bytes have been written
+ by the apr_file_write_full() call, and attempt to write the remaining
+ part in smaller chunks. */
if (rv == APR_FROM_OS_ERROR(ERROR_NOT_ENOUGH_MEMORY)
&& nbytes > MAXBUFSIZE)
{
@@ -3981,11 +4014,12 @@ svn_io_write_unique(const char **tmp_path,
}
svn_error_t *
-svn_io_write_atomic(const char *final_path,
- const void *buf,
- apr_size_t nbytes,
- const char *copy_perms_path,
- apr_pool_t *scratch_pool)
+svn_io_write_atomic2(const char *final_path,
+ const void *buf,
+ apr_size_t nbytes,
+ const char *copy_perms_path,
+ svn_boolean_t flush_to_disk,
+ apr_pool_t *scratch_pool)
{
apr_file_t *tmp_file;
const char *tmp_path;
@@ -3998,7 +4032,7 @@ svn_io_write_atomic(const char *final_path,
err = svn_io_file_write_full(tmp_file, buf, nbytes, NULL, scratch_pool);
- if (!err)
+ if (!err && flush_to_disk)
err = svn_io_file_flush_to_disk(tmp_file, scratch_pool);
err = svn_error_compose_create(err,
@@ -4008,7 +4042,8 @@ svn_io_write_atomic(const char *final_path,
err = svn_io_copy_perms(copy_perms_path, tmp_path, scratch_pool);
if (!err)
- err = svn_io_file_rename(tmp_path, final_path, scratch_pool);
+ err = svn_io_file_rename2(tmp_path, final_path, flush_to_disk,
+ scratch_pool);
if (err)
{
@@ -4022,22 +4057,6 @@ svn_io_write_atomic(const char *final_path,
scratch_pool));
}
-#ifdef __linux__
- {
- /* Linux has the unusual feature that fsync() on a file is not
- enough to ensure that a file's directory entries have been
- flushed to disk; you have to fsync the directory as well.
- On other operating systems, we'd only be asking for trouble
- by trying to open and fsync a directory. */
- apr_file_t *file;
-
- SVN_ERR(svn_io_file_open(&file, dirname, APR_READ, APR_OS_DEFAULT,
- scratch_pool));
- SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool));
- SVN_ERR(svn_io_file_close(file, scratch_pool));
- }
-#endif
-
return SVN_NO_ERROR;
}
@@ -4052,7 +4071,7 @@ svn_io_file_trunc(apr_file_t *file, apr_off_t offset, apr_pool_t *pool)
To prevent this, write 1 dummy byte just after the OFFSET at which we
will trunc it. That will force the APR file into write mode
- internally and the flush() work-around below becomes affective. */
+ internally and the flush() work-around below becomes effective. */
apr_off_t position = 0;
/* A frequent usage is OFFSET==0, in which case we don't need to preserve
@@ -4186,20 +4205,53 @@ svn_io_stat(apr_finfo_t *finfo, const char *fname,
return SVN_NO_ERROR;
}
+#if defined(WIN32)
+/* Platform specific implementation of apr_file_rename() to workaround
+ APR problems on Windows. */
+static apr_status_t
+win32_file_rename(const WCHAR *from_path_w,
+ const WCHAR *to_path_w,
+ svn_boolean_t flush_to_disk)
+{
+ /* APR calls MoveFileExW() with MOVEFILE_COPY_ALLOWED, while we rely
+ * that rename is atomic operation. Call MoveFileEx directly on Windows
+ * without MOVEFILE_COPY_ALLOWED flag to workaround it.
+ */
+
+ DWORD flags = MOVEFILE_REPLACE_EXISTING;
+
+ if (flush_to_disk)
+ {
+ /* Do not return until the file has actually been moved on the disk. */
+ flags |= MOVEFILE_WRITE_THROUGH;
+ }
+
+ if (!MoveFileExW(from_path_w, to_path_w, flags))
+ return apr_get_os_error();
+
+ return APR_SUCCESS;
+}
+#endif
svn_error_t *
-svn_io_file_rename(const char *from_path, const char *to_path,
- apr_pool_t *pool)
+svn_io_file_rename2(const char *from_path, const char *to_path,
+ svn_boolean_t flush_to_disk, apr_pool_t *pool)
{
apr_status_t status = APR_SUCCESS;
const char *from_path_apr, *to_path_apr;
+#if defined(WIN32)
+ WCHAR *from_path_w;
+ WCHAR *to_path_w;
+#endif
SVN_ERR(cstring_from_utf8(&from_path_apr, from_path, pool));
SVN_ERR(cstring_from_utf8(&to_path_apr, to_path, pool));
- status = apr_file_rename(from_path_apr, to_path_apr, pool);
+#if defined(WIN32)
+ SVN_ERR(svn_io__utf8_to_unicode_longpath(&from_path_w, from_path_apr, pool));
+ SVN_ERR(svn_io__utf8_to_unicode_longpath(&to_path_w, to_path_apr, pool));
+ status = win32_file_rename(from_path_w, to_path_w, flush_to_disk);
-#if defined(WIN32) || defined(__OS2__)
/* If the target file is read only NTFS reports EACCESS and
FAT/FAT32 reports EEXIST */
if (APR_STATUS_IS_EACCES(status) || APR_STATUS_IS_EEXIST(status))
@@ -4209,9 +4261,25 @@ svn_io_file_rename(const char *from_path, const char *to_path,
allow renaming when from_path is read only. */
SVN_ERR(svn_io_set_file_read_write(to_path, TRUE, pool));
+ status = win32_file_rename(from_path_w, to_path_w, flush_to_disk);
+ }
+ WIN32_RETRY_LOOP(status, win32_file_rename(from_path_w, to_path_w,
+ flush_to_disk));
+#elif defined(__OS2__)
+ status = apr_file_rename(from_path_apr, to_path_apr, pool);
+ /* If the target file is read only NTFS reports EACCESS and
+ FAT/FAT32 reports EEXIST */
+ if (APR_STATUS_IS_EACCES(status) || APR_STATUS_IS_EEXIST(status))
+ {
+ /* Set the destination file writable because OS/2 will not
+ allow us to rename when to_path is read-only, but will
+ allow renaming when from_path is read only. */
+ SVN_ERR(svn_io_set_file_read_write(to_path, TRUE, pool));
+
status = apr_file_rename(from_path_apr, to_path_apr, pool);
}
- WIN32_RETRY_LOOP(status, apr_file_rename(from_path_apr, to_path_apr, pool));
+#else
+ status = apr_file_rename(from_path_apr, to_path_apr, pool);
#endif /* WIN32 || __OS2__ */
if (status)
@@ -4219,6 +4287,34 @@ svn_io_file_rename(const char *from_path, const char *to_path,
svn_dirent_local_style(from_path, pool),
svn_dirent_local_style(to_path, pool));
+#if defined(SVN_ON_POSIX)
+ if (flush_to_disk)
+ {
+ /* On POSIX, the file name is stored in the file's directory entry.
+ Hence, we need to fsync() that directory as well.
+ On other operating systems, we'd only be asking for trouble
+ by trying to open and fsync a directory. */
+ const char *dirname;
+ apr_file_t *file;
+
+ dirname = svn_dirent_dirname(to_path, pool);
+ SVN_ERR(svn_io_file_open(&file, dirname, APR_READ, APR_OS_DEFAULT,
+ pool));
+ SVN_ERR(svn_io_file_flush_to_disk(file, pool));
+ SVN_ERR(svn_io_file_close(file, pool));
+ }
+#elif !defined(WIN32)
+ /* Flush the target of the rename to disk. */
+ if (flush_to_disk)
+ {
+ apr_file_t *file;
+ SVN_ERR(svn_io_file_open(&file, to_path, APR_WRITE,
+ APR_OS_DEFAULT, pool));
+ SVN_ERR(svn_io_file_flush_to_disk(file, pool));
+ SVN_ERR(svn_io_file_close(file, pool));
+ }
+#endif
+
return SVN_NO_ERROR;
}
@@ -4227,37 +4323,16 @@ svn_error_t *
svn_io_file_move(const char *from_path, const char *to_path,
apr_pool_t *pool)
{
- svn_error_t *err = svn_io_file_rename(from_path, to_path, pool);
+ svn_error_t *err = svn_error_trace(svn_io_file_rename2(from_path, to_path,
+ FALSE, pool));
if (err && APR_STATUS_IS_EXDEV(err->apr_err))
{
- const char *tmp_to_path;
-
svn_error_clear(err);
- SVN_ERR(svn_io_open_unique_file3(NULL, &tmp_to_path,
- svn_dirent_dirname(to_path, pool),
- svn_io_file_del_none,
- pool, pool));
-
- err = svn_io_copy_file(from_path, tmp_to_path, TRUE, pool);
- if (err)
- goto failed_tmp;
-
- err = svn_io_file_rename(tmp_to_path, to_path, pool);
- if (err)
- goto failed_tmp;
-
- err = svn_io_remove_file2(from_path, FALSE, pool);
- if (! err)
- return SVN_NO_ERROR;
-
- svn_error_clear(svn_io_remove_file2(to_path, FALSE, pool));
-
- return err;
-
- failed_tmp:
- svn_error_clear(svn_io_remove_file2(tmp_to_path, FALSE, pool));
+ /* svn_io_copy_file() performs atomic copy via temporary file. */
+ err = svn_error_trace(svn_io_copy_file(from_path, to_path, TRUE,
+ pool));
}
return err;
@@ -4409,8 +4484,8 @@ svn_io_dir_remove_nonrecursive(const char *dirname, apr_pool_t *pool)
{
svn_boolean_t retry = TRUE;
- if (APR_TO_OS_ERROR(status) == ERROR_DIR_NOT_EMPTY)
- {
+ if (status == APR_FROM_OS_ERROR(ERROR_DIR_NOT_EMPTY))
+ {
apr_status_t empty_status = dir_is_empty(dirname_apr, pool);
if (APR_STATUS_IS_ENOTEMPTY(empty_status))
@@ -4689,7 +4764,7 @@ svn_io_write_version_file(const char *path,
#endif /* WIN32 || __OS2__ */
/* rename the temp file as the real destination */
- SVN_ERR(svn_io_file_rename(path_tmp, path, pool));
+ SVN_ERR(svn_io_file_rename2(path_tmp, path, FALSE, pool));
/* And finally remove the perms to make it read only */
return svn_io_set_file_read_only(path, FALSE, pool);
@@ -5086,7 +5161,7 @@ temp_file_create(apr_file_t **new_file,
/* Generate a number that should be unique for this application and
usually for the entire computer to reduce the number of cycles
- through this loop. (A bit of calculation is much cheaper then
+ through this loop. (A bit of calculation is much cheaper than
disk io) */
unique_nr = baseNr + 3 * i;
@@ -5117,10 +5192,8 @@ temp_file_create(apr_file_t **new_file,
if (!apr_err_2 && finfo.filetype == APR_DIR)
continue;
- apr_err_2 = APR_TO_OS_ERROR(apr_err);
-
- if (apr_err_2 == ERROR_ACCESS_DENIED ||
- apr_err_2 == ERROR_SHARING_VIOLATION)
+ if (apr_err == APR_FROM_OS_ERROR(ERROR_ACCESS_DENIED) ||
+ apr_err == APR_FROM_OS_ERROR(ERROR_SHARING_VIOLATION))
{
/* The file is in use by another process or is hidden;
create a new name, but don't do this 99999 times in
@@ -5254,7 +5327,8 @@ svn_io_open_unique_file3(apr_file_t **file,
{
svn_error_t *err;
- SVN_ERR(merge_default_file_perms(tempfile, &perms, scratch_pool));
+ SVN_ERR(merge_default_file_perms(tempfile, &perms, dirpath,
+ scratch_pool));
err = file_perms_set2(tempfile, perms, scratch_pool);
if (err)
{
@@ -5334,8 +5408,7 @@ svn_io_file_readline(apr_file_t *file,
apr_off_t pos;
/* Check for "\r\n" by peeking at the next byte. */
- pos = 0;
- SVN_ERR(svn_io_file_seek(file, APR_CUR, &pos, scratch_pool));
+ SVN_ERR(svn_io_file_get_offset(&pos, file, scratch_pool));
SVN_ERR(svn_io_file_read_full2(file, &c, sizeof(c), &numbytes,
&found_eof, scratch_pool));
if (numbytes == 1 && c == '\n')