mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-11-01 08:52:18 +01: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
|
||||
|
||||
|
||||
/* A plain read/write loop */
|
||||
if (!copy_stream_with_progress (in, out, source, cancellable,
|
||||
progress_callback, progress_callback_data,
|
||||
@@ -3115,11 +3115,6 @@ file_copy_fallback (GFile *source,
|
||||
|
||||
ret = TRUE;
|
||||
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)
|
||||
{
|
||||
/* Don't care about errors in source here */
|
||||
@@ -3134,7 +3129,13 @@ file_copy_fallback (GFile *source,
|
||||
ret = FALSE;
|
||||
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);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <gio/gfiledescriptorbased.h>
|
||||
#ifdef G_OS_UNIX
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
static void
|
||||
test_basic (void)
|
||||
@@ -727,6 +730,59 @@ test_async_delete (void)
|
||||
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
|
||||
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-cancel", test_replace_cancel);
|
||||
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 ();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user