mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-19 07:08:54 +02:00
g_file_copy(): Ensure G_FILE_COPY_OVERWRITE preserves permissions
We need to close the stream *before* applying the file modes, because
g_file_replace() allocates a temporary file. At the moment we're
applying the modes to the extant file, then immediately rename()ing
over it with the default perms.
This regressed with commit 166766a89f
.
The real fix here is to have g_file_create_with_info() so that we can
atomically create a file with the permissions we want.
https://bugzilla.gnome.org/show_bug.cgi?id=696014
This commit is contained in:
committed by
Ryan Lortie
parent
ef2aa88a4f
commit
978571d854
15
gio/gfile.c
15
gio/gfile.c
@@ -3106,7 +3106,7 @@ file_copy_fallback (GFile *source,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* A plain read/write loop */
|
/* A plain read/write loop */
|
||||||
if (!copy_stream_with_progress (in, out, source, cancellable,
|
if (!copy_stream_with_progress (in, out, source, cancellable,
|
||||||
progress_callback, progress_callback_data,
|
progress_callback, progress_callback_data,
|
||||||
@@ -3115,11 +3115,6 @@ file_copy_fallback (GFile *source,
|
|||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
out:
|
out:
|
||||||
/* Ignore errors here. Failure to copy metadata is not a hard error */
|
|
||||||
if (ret)
|
|
||||||
(void) g_file_copy_attributes (source, destination,
|
|
||||||
flags, cancellable, NULL);
|
|
||||||
|
|
||||||
if (in)
|
if (in)
|
||||||
{
|
{
|
||||||
/* Don't care about errors in source here */
|
/* Don't care about errors in source here */
|
||||||
@@ -3134,7 +3129,13 @@ file_copy_fallback (GFile *source,
|
|||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
g_object_unref (out);
|
g_object_unref (out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ignore errors here. Failure to copy metadata is not a hard error */
|
||||||
|
if (ret)
|
||||||
|
(void) g_file_copy_attributes (source, destination,
|
||||||
|
flags, cancellable, NULL);
|
||||||
|
|
||||||
|
|
||||||
g_clear_object (&info);
|
g_clear_object (&info);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -3,6 +3,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
#include <gio/gfiledescriptorbased.h>
|
#include <gio/gfiledescriptorbased.h>
|
||||||
|
#ifdef G_OS_UNIX
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_basic (void)
|
test_basic (void)
|
||||||
@@ -727,6 +730,59 @@ test_async_delete (void)
|
|||||||
g_object_unref (file);
|
g_object_unref (file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef G_OS_UNIX
|
||||||
|
static void
|
||||||
|
test_copy_preserve_mode (void)
|
||||||
|
{
|
||||||
|
GFile *tmpfile;
|
||||||
|
GFile *dest_tmpfile;
|
||||||
|
GFileInfo *dest_info;
|
||||||
|
GFileIOStream *iostream;
|
||||||
|
GError *local_error = NULL;
|
||||||
|
GError **error = &local_error;
|
||||||
|
guint32 romode = S_IFREG | 0600;
|
||||||
|
guint32 dest_mode;
|
||||||
|
|
||||||
|
tmpfile = g_file_new_tmp ("tmp-copy-preserve-modeXXXXXX",
|
||||||
|
&iostream, error);
|
||||||
|
g_assert_no_error (local_error);
|
||||||
|
g_io_stream_close ((GIOStream*)iostream, NULL, error);
|
||||||
|
g_assert_no_error (local_error);
|
||||||
|
g_clear_object (&iostream);
|
||||||
|
|
||||||
|
g_file_set_attribute (tmpfile, G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_ATTRIBUTE_TYPE_UINT32,
|
||||||
|
&romode, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
NULL, error);
|
||||||
|
g_assert_no_error (local_error);
|
||||||
|
|
||||||
|
dest_tmpfile = g_file_new_tmp ("tmp-copy-preserve-modeXXXXXX",
|
||||||
|
&iostream, error);
|
||||||
|
g_assert_no_error (local_error);
|
||||||
|
g_io_stream_close ((GIOStream*)iostream, NULL, error);
|
||||||
|
g_assert_no_error (local_error);
|
||||||
|
g_clear_object (&iostream);
|
||||||
|
|
||||||
|
g_file_copy (tmpfile, dest_tmpfile, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA,
|
||||||
|
NULL, NULL, NULL, error);
|
||||||
|
g_assert_no_error (local_error);
|
||||||
|
|
||||||
|
dest_info = g_file_query_info (dest_tmpfile, G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
|
NULL, error);
|
||||||
|
g_assert_no_error (local_error);
|
||||||
|
|
||||||
|
dest_mode = g_file_info_get_attribute_uint32 (dest_info, G_FILE_ATTRIBUTE_UNIX_MODE);
|
||||||
|
|
||||||
|
g_assert_cmpint (dest_mode, ==, romode);
|
||||||
|
|
||||||
|
(void) g_file_delete (tmpfile, NULL, NULL);
|
||||||
|
(void) g_file_delete (dest_tmpfile, NULL, NULL);
|
||||||
|
|
||||||
|
g_clear_object (&tmpfile);
|
||||||
|
g_clear_object (&dest_tmpfile);
|
||||||
|
g_clear_object (&dest_info);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@@ -746,6 +802,9 @@ main (int argc, char *argv[])
|
|||||||
g_test_add_func ("/file/replace-load", test_replace_load);
|
g_test_add_func ("/file/replace-load", test_replace_load);
|
||||||
g_test_add_func ("/file/replace-cancel", test_replace_cancel);
|
g_test_add_func ("/file/replace-cancel", test_replace_cancel);
|
||||||
g_test_add_func ("/file/async-delete", test_async_delete);
|
g_test_add_func ("/file/async-delete", test_async_delete);
|
||||||
|
#ifdef G_OS_UNIX
|
||||||
|
g_test_add_func ("/file/copy-preserve-mode", test_copy_preserve_mode);
|
||||||
|
#endif
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user