mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-26 15:36:14 +01:00
Bug 548988 - g_file_replace fails on Windows when the target file exists
2008-08-23 Tor Lillqvist <tml@novell.com> Bug 548988 - g_file_replace fails on Windows when the target file exists already * glocalfileoutputstream.c (g_local_file_output_stream_close): On Windows, close the file before renaming it (in case we have been writing to a file with a temporary name). (g_local_file_output_stream_close, handle_overwrite_open): Use GLocalFileStat instead of plain struct stat, for passing to _g_local_file_info_create_etag(). Thus also use _fstati64() instead of plain fstat() on Windows. svn path=/trunk/; revision=7388
This commit is contained in:
parent
886c0e0d81
commit
02d9af3562
@ -1,3 +1,17 @@
|
|||||||
|
2008-08-23 Tor Lillqvist <tml@novell.com>
|
||||||
|
|
||||||
|
Bug 548988 - g_file_replace fails on Windows when the target file
|
||||||
|
exists already
|
||||||
|
|
||||||
|
* glocalfileoutputstream.c (g_local_file_output_stream_close): On
|
||||||
|
Windows, close the file before renaming it (in case we have been
|
||||||
|
writing to a file with a temporary name).
|
||||||
|
|
||||||
|
(g_local_file_output_stream_close, handle_overwrite_open): Use
|
||||||
|
GLocalFileStat instead of plain struct stat, for passing to
|
||||||
|
_g_local_file_info_create_etag(). Thus also use _fstati64()
|
||||||
|
instead of plain fstat() on Windows.
|
||||||
|
|
||||||
2008-08-18 Matthias Clasen <mclasen@redhat.com>
|
2008-08-18 Matthias Clasen <mclasen@redhat.com>
|
||||||
|
|
||||||
* === Released 2.17.7 ===
|
* === Released 2.17.7 ===
|
||||||
|
@ -185,11 +185,33 @@ g_local_file_output_stream_close (GOutputStream *stream,
|
|||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GLocalFileOutputStream *file;
|
GLocalFileOutputStream *file;
|
||||||
struct stat final_stat;
|
GLocalFileStat final_stat;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
|
file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
|
||||||
|
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
|
||||||
|
/* Must close before renaming on Windows, so just do the close first
|
||||||
|
* in all cases for now.
|
||||||
|
*/
|
||||||
|
if (_fstati64 (file->priv->fd, &final_stat) == 0)
|
||||||
|
file->priv->etag = _g_local_file_info_create_etag (&final_stat);
|
||||||
|
|
||||||
|
res = close (file->priv->fd);
|
||||||
|
if (res == -1)
|
||||||
|
{
|
||||||
|
int errsv = errno;
|
||||||
|
|
||||||
|
g_set_error (error, G_IO_ERROR,
|
||||||
|
g_io_error_from_errno (errsv),
|
||||||
|
_("Error closing file: %s"),
|
||||||
|
g_strerror (errsv));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
if (file->priv->tmp_filename)
|
if (file->priv->tmp_filename)
|
||||||
{
|
{
|
||||||
/* We need to move the temp file to its final place,
|
/* We need to move the temp file to its final place,
|
||||||
@ -264,6 +286,8 @@ g_local_file_output_stream_close (GOutputStream *stream,
|
|||||||
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
|
||||||
|
#ifndef G_OS_WIN32 /* Already did the fstat() and close() above on Win32 */
|
||||||
|
|
||||||
if (fstat (file->priv->fd, &final_stat) == 0)
|
if (fstat (file->priv->fd, &final_stat) == 0)
|
||||||
file->priv->etag = _g_local_file_info_create_etag (&final_stat);
|
file->priv->etag = _g_local_file_info_create_etag (&final_stat);
|
||||||
|
|
||||||
@ -284,9 +308,18 @@ g_local_file_output_stream_close (GOutputStream *stream,
|
|||||||
|
|
||||||
return res != -1;
|
return res != -1;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
err_out:
|
err_out:
|
||||||
|
|
||||||
|
#ifndef G_OS_WIN32
|
||||||
/* A simple try to close the fd in case we fail before the actual close */
|
/* A simple try to close the fd in case we fail before the actual close */
|
||||||
close (file->priv->fd);
|
close (file->priv->fd);
|
||||||
|
#endif
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -615,10 +648,11 @@ handle_overwrite_open (const char *filename,
|
|||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
struct stat original_stat;
|
GLocalFileStat original_stat;
|
||||||
char *current_etag;
|
char *current_etag;
|
||||||
gboolean is_symlink;
|
gboolean is_symlink;
|
||||||
int open_flags;
|
int open_flags;
|
||||||
|
int res;
|
||||||
|
|
||||||
/* We only need read access to the original file if we are creating a backup.
|
/* We only need read access to the original file if we are creating a backup.
|
||||||
* We also add O_CREATE to avoid a race if the file was just removed */
|
* We also add O_CREATE to avoid a race if the file was just removed */
|
||||||
@ -657,7 +691,13 @@ handle_overwrite_open (const char *filename,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fstat (fd, &original_stat) != 0)
|
#ifdef G_OS_WIN32
|
||||||
|
res = _fstati64 (fd, &original_stat);
|
||||||
|
#else
|
||||||
|
res = fstat (fd, &original_stat);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (res != 0)
|
||||||
{
|
{
|
||||||
int errsv = errno;
|
int errsv = errno;
|
||||||
char *display_name = g_filename_display_name (filename);
|
char *display_name = g_filename_display_name (filename);
|
||||||
@ -763,7 +803,9 @@ handle_overwrite_open (const char *filename,
|
|||||||
|
|
||||||
if (create_backup)
|
if (create_backup)
|
||||||
{
|
{
|
||||||
|
#if defined(HAVE_FCHOWN) && defined(HAVE_FCHMOD)
|
||||||
struct stat tmp_statbuf;
|
struct stat tmp_statbuf;
|
||||||
|
#endif
|
||||||
char *backup_filename;
|
char *backup_filename;
|
||||||
int bfd;
|
int bfd;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user