mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-26 12:12:10 +01:00
Merge branch 'master' into 'master'
gio: Expose g_file_query_info_for_copy() Closes gvfs#346 See merge request GNOME/glib!1449
This commit is contained in:
commit
3573a2d32d
@ -199,6 +199,7 @@ g_file_replace_contents
|
|||||||
g_file_replace_contents_async
|
g_file_replace_contents_async
|
||||||
g_file_replace_contents_bytes_async
|
g_file_replace_contents_bytes_async
|
||||||
g_file_replace_contents_finish
|
g_file_replace_contents_finish
|
||||||
|
g_file_build_attribute_list_for_copy
|
||||||
g_file_copy_attributes
|
g_file_copy_attributes
|
||||||
g_file_create_readwrite
|
g_file_create_readwrite
|
||||||
g_file_create_readwrite_async
|
g_file_create_readwrite_async
|
||||||
|
113
gio/gfile.c
113
gio/gfile.c
@ -2695,14 +2695,36 @@ should_copy (GFileAttributeInfo *info,
|
|||||||
return info->flags & G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE;
|
return info->flags & G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
/**
|
||||||
build_attribute_list_for_copy (GFile *file,
|
* g_file_build_attribute_list_for_copy:
|
||||||
GFileCopyFlags flags,
|
* @file: a #GFile to copy attributes to
|
||||||
char **out_attributes,
|
* @flags: a set of #GFileCopyFlags
|
||||||
GCancellable *cancellable,
|
* @cancellable: (nullable): optional #GCancellable object,
|
||||||
GError **error)
|
* %NULL to ignore
|
||||||
|
* @error: a #GError, %NULL to ignore
|
||||||
|
*
|
||||||
|
* Prepares the file attribute query string for copying to @file.
|
||||||
|
*
|
||||||
|
* This function prepares an attribute query string to be
|
||||||
|
* passed to g_file_query_info() to get a list of attributes
|
||||||
|
* normally copied with the file (see g_file_copy_attributes()
|
||||||
|
* for the detailed description). This function is used by the
|
||||||
|
* implementation of g_file_copy_attributes() and is useful
|
||||||
|
* when one needs to query and set the attributes in two
|
||||||
|
* stages (e.g., for recursive move of a directory).
|
||||||
|
*
|
||||||
|
* Returns: an attribute query string for g_file_query_info(),
|
||||||
|
* or %NULL if an error occurs.
|
||||||
|
*
|
||||||
|
* Since: 2.68
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
g_file_build_attribute_list_for_copy (GFile *file,
|
||||||
|
GFileCopyFlags flags,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
char *ret = NULL;
|
||||||
GFileAttributeInfoList *attributes = NULL, *namespaces = NULL;
|
GFileAttributeInfoList *attributes = NULL, *namespaces = NULL;
|
||||||
GString *s = NULL;
|
GString *s = NULL;
|
||||||
gboolean first;
|
gboolean first;
|
||||||
@ -2710,6 +2732,10 @@ build_attribute_list_for_copy (GFile *file,
|
|||||||
gboolean copy_all_attributes;
|
gboolean copy_all_attributes;
|
||||||
gboolean skip_perms;
|
gboolean skip_perms;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
||||||
|
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
|
||||||
copy_all_attributes = flags & G_FILE_COPY_ALL_METADATA;
|
copy_all_attributes = flags & G_FILE_COPY_ALL_METADATA;
|
||||||
skip_perms = (flags & G_FILE_COPY_TARGET_DEFAULT_PERMS) != 0;
|
skip_perms = (flags & G_FILE_COPY_TARGET_DEFAULT_PERMS) != 0;
|
||||||
|
|
||||||
@ -2763,8 +2789,7 @@ build_attribute_list_for_copy (GFile *file,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = TRUE;
|
ret = g_string_free (s, FALSE);
|
||||||
*out_attributes = g_string_free (s, FALSE);
|
|
||||||
s = NULL;
|
s = NULL;
|
||||||
out:
|
out:
|
||||||
if (s)
|
if (s)
|
||||||
@ -2810,8 +2835,9 @@ g_file_copy_attributes (GFile *source,
|
|||||||
GFileInfo *info;
|
GFileInfo *info;
|
||||||
gboolean source_nofollow_symlinks;
|
gboolean source_nofollow_symlinks;
|
||||||
|
|
||||||
if (!build_attribute_list_for_copy (destination, flags, &attrs_to_read,
|
attrs_to_read = g_file_build_attribute_list_for_copy (destination, flags,
|
||||||
cancellable, error))
|
cancellable, error);
|
||||||
|
if (!attrs_to_read)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
source_nofollow_symlinks = flags & G_FILE_COPY_NOFOLLOW_SYMLINKS;
|
source_nofollow_symlinks = flags & G_FILE_COPY_NOFOLLOW_SYMLINKS;
|
||||||
@ -3157,6 +3183,7 @@ file_copy_fallback (GFile *source,
|
|||||||
char *attrs_to_read;
|
char *attrs_to_read;
|
||||||
gboolean do_set_attributes = FALSE;
|
gboolean do_set_attributes = FALSE;
|
||||||
GFileCreateFlags create_flags;
|
GFileCreateFlags create_flags;
|
||||||
|
GError *tmp_error = NULL;
|
||||||
|
|
||||||
/* need to know the file type */
|
/* need to know the file type */
|
||||||
info = g_file_query_info (source,
|
info = g_file_query_info (source,
|
||||||
@ -3198,47 +3225,43 @@ file_copy_fallback (GFile *source,
|
|||||||
goto out;
|
goto out;
|
||||||
in = G_INPUT_STREAM (file_in);
|
in = G_INPUT_STREAM (file_in);
|
||||||
|
|
||||||
if (!build_attribute_list_for_copy (destination, flags, &attrs_to_read,
|
attrs_to_read = g_file_build_attribute_list_for_copy (destination, flags,
|
||||||
cancellable, error))
|
cancellable, error);
|
||||||
|
if (!attrs_to_read)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (attrs_to_read != NULL)
|
/* Ok, ditch the previous lightweight info (on Unix we just
|
||||||
|
* called lstat()); at this point we gather all the information
|
||||||
|
* we need about the source from the opened file descriptor.
|
||||||
|
*/
|
||||||
|
g_object_unref (info);
|
||||||
|
|
||||||
|
info = g_file_input_stream_query_info (file_in, attrs_to_read,
|
||||||
|
cancellable, &tmp_error);
|
||||||
|
if (!info)
|
||||||
{
|
{
|
||||||
GError *tmp_error = NULL;
|
/* Not all gvfs backends implement query_info_on_read(), we
|
||||||
|
* can just fall back to the pathname again.
|
||||||
/* Ok, ditch the previous lightweight info (on Unix we just
|
* https://bugzilla.gnome.org/706254
|
||||||
* called lstat()); at this point we gather all the information
|
|
||||||
* we need about the source from the opened file descriptor.
|
|
||||||
*/
|
*/
|
||||||
g_object_unref (info);
|
if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
|
||||||
|
|
||||||
info = g_file_input_stream_query_info (file_in, attrs_to_read,
|
|
||||||
cancellable, &tmp_error);
|
|
||||||
if (!info)
|
|
||||||
{
|
{
|
||||||
/* Not all gvfs backends implement query_info_on_read(), we
|
g_clear_error (&tmp_error);
|
||||||
* can just fall back to the pathname again.
|
info = g_file_query_info (source, attrs_to_read, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||||
* https://bugzilla.gnome.org/706254
|
cancellable, error);
|
||||||
*/
|
}
|
||||||
if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
|
else
|
||||||
{
|
{
|
||||||
g_clear_error (&tmp_error);
|
g_free (attrs_to_read);
|
||||||
info = g_file_query_info (source, attrs_to_read, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
g_propagate_error (error, tmp_error);
|
||||||
cancellable, error);
|
goto out;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_free (attrs_to_read);
|
|
||||||
g_propagate_error (error, tmp_error);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
g_free (attrs_to_read);
|
|
||||||
if (!info)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
do_set_attributes = TRUE;
|
|
||||||
}
|
}
|
||||||
|
g_free (attrs_to_read);
|
||||||
|
if (!info)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
do_set_attributes = TRUE;
|
||||||
|
|
||||||
/* In the local file path, we pass down the source info which
|
/* In the local file path, we pass down the source info which
|
||||||
* includes things like unix::mode, to ensure that the target file
|
* includes things like unix::mode, to ensure that the target file
|
||||||
|
@ -1094,6 +1094,12 @@ gboolean g_file_eject_mountable_with_operation_finish (GFile
|
|||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_68
|
||||||
|
char * g_file_build_attribute_list_for_copy (GFile *file,
|
||||||
|
GFileCopyFlags flags,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
GLIB_AVAILABLE_IN_ALL
|
GLIB_AVAILABLE_IN_ALL
|
||||||
gboolean g_file_copy_attributes (GFile *source,
|
gboolean g_file_copy_attributes (GFile *source,
|
||||||
GFile *destination,
|
GFile *destination,
|
||||||
|
@ -1780,6 +1780,79 @@ test_writev_async_all_too_big_vectors (void)
|
|||||||
g_object_unref (file);
|
g_object_unref (file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_build_attribute_list_for_copy (void)
|
||||||
|
{
|
||||||
|
GFile *tmpfile;
|
||||||
|
GFileIOStream *iostream;
|
||||||
|
GError *error = NULL;
|
||||||
|
const GFileCopyFlags test_flags[] =
|
||||||
|
{
|
||||||
|
G_FILE_COPY_NONE,
|
||||||
|
G_FILE_COPY_TARGET_DEFAULT_PERMS,
|
||||||
|
G_FILE_COPY_ALL_METADATA,
|
||||||
|
G_FILE_COPY_ALL_METADATA | G_FILE_COPY_TARGET_DEFAULT_PERMS,
|
||||||
|
};
|
||||||
|
gsize i;
|
||||||
|
char *attrs;
|
||||||
|
gchar *attrs_with_commas;
|
||||||
|
|
||||||
|
tmpfile = g_file_new_tmp ("tmp-build-attribute-list-for-copyXXXXXX",
|
||||||
|
&iostream, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_io_stream_close ((GIOStream*)iostream, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_clear_object (&iostream);
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (test_flags); i++)
|
||||||
|
{
|
||||||
|
GFileCopyFlags flags = test_flags[i];
|
||||||
|
|
||||||
|
attrs = g_file_build_attribute_list_for_copy (tmpfile, flags, NULL, &error);
|
||||||
|
g_test_message ("Attributes for copy: %s", attrs);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_nonnull (attrs);
|
||||||
|
attrs_with_commas = g_strconcat (",", attrs, ",", NULL);
|
||||||
|
g_free (attrs);
|
||||||
|
|
||||||
|
/* See g_local_file_class_init for reference. */
|
||||||
|
if (flags & G_FILE_COPY_TARGET_DEFAULT_PERMS)
|
||||||
|
g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_MODE ","));
|
||||||
|
else
|
||||||
|
g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_MODE ","));
|
||||||
|
#ifdef G_OS_UNIX
|
||||||
|
if (flags & G_FILE_COPY_ALL_METADATA)
|
||||||
|
{
|
||||||
|
g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_UID ","));
|
||||||
|
g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_GID ","));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_UID ","));
|
||||||
|
g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_GID ","));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UTIMES
|
||||||
|
g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED ","));
|
||||||
|
g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC ","));
|
||||||
|
if (flags & G_FILE_COPY_ALL_METADATA)
|
||||||
|
{
|
||||||
|
g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_ACCESS ","));
|
||||||
|
g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_ACCESS_USEC ","));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_ACCESS ","));
|
||||||
|
g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_ACCESS_USEC ","));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
g_free (attrs_with_commas);
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) g_file_delete (tmpfile, NULL, NULL);
|
||||||
|
g_clear_object (&tmpfile);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -1817,6 +1890,7 @@ main (int argc, char *argv[])
|
|||||||
g_test_add_func ("/file/writev/async_all-no-vectors", test_writev_async_all_no_vectors);
|
g_test_add_func ("/file/writev/async_all-no-vectors", test_writev_async_all_no_vectors);
|
||||||
g_test_add_func ("/file/writev/async_all-to-big-vectors", test_writev_async_all_too_big_vectors);
|
g_test_add_func ("/file/writev/async_all-to-big-vectors", test_writev_async_all_too_big_vectors);
|
||||||
g_test_add_func ("/file/writev/async_all-cancellation", test_writev_async_all_cancellation);
|
g_test_add_func ("/file/writev/async_all-cancellation", test_writev_async_all_cancellation);
|
||||||
|
g_test_add_func ("/file/build-attribute-list-for-copy", test_build_attribute_list_for_copy);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user