diff options
author | Colin Walters <walters@verbum.org> | 2014-04-29 07:35:05 -0400 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2014-04-29 07:39:42 -0400 |
commit | 8b726cd97bbaa9f7ce57ddbe0e16e96176761c21 (patch) | |
tree | bb1c1dac40ba6b138d3d4f10d26584ff88202b4e /src/gsystem-file-utils.c | |
parent | 1afbc2e476331f2cef3e46dee7a7fbcd9485535c (diff) | |
download | libgsystem-8b726cd97bbaa9f7ce57ddbe0e16e96176761c21.tar.gz |
fileutil: Add API to retrieve xattrs relative to a directory fd
This is the only safe way to get xattrs for a symlink relative to a
dirfd.
Diffstat (limited to 'src/gsystem-file-utils.c')
-rw-r--r-- | src/gsystem-file-utils.c | 79 |
1 files changed, 51 insertions, 28 deletions
diff --git a/src/gsystem-file-utils.c b/src/gsystem-file-utils.c index e507d21..6a35ed7 100644 --- a/src/gsystem-file-utils.c +++ b/src/gsystem-file-utils.c @@ -1467,19 +1467,22 @@ read_xattr_name_array (const char *path, #endif static gboolean -get_xattrs_impl (GFile *f, - GVariantBuilder *builder, +get_xattrs_impl (const char *path, + GVariant **out_xattrs, GCancellable *cancellable, GError **error) { #ifdef GSYSTEM_CONFIG_XATTRS gboolean ret = FALSE; - const char *path; ssize_t bytes_read; char *xattr_names = NULL; char *xattr_names_canonical = NULL; + GVariantBuilder builder; + gboolean builder_initialized = FALSE; + GVariant *ret_xattrs = NULL; - path = gs_file_get_path_cached (f); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ayay)")); + builder_initialized = TRUE; bytes_read = llistxattr (path, NULL, 0); @@ -1501,14 +1504,22 @@ get_xattrs_impl (GFile *f, } xattr_names_canonical = canonicalize_xattrs (xattr_names, bytes_read); - if (!read_xattr_name_array (path, xattr_names_canonical, bytes_read, builder, error)) + if (!read_xattr_name_array (path, xattr_names_canonical, bytes_read, &builder, error)) goto out; } + ret_xattrs = g_variant_builder_end (&builder); + builder_initialized = FALSE; + g_variant_ref_sink (ret_xattrs); + ret = TRUE; + gs_transfer_out_value (out_xattrs, &ret_xattrs); out: g_clear_pointer (&xattr_names, g_free); g_clear_pointer (&xattr_names_canonical, g_free); + g_clear_pointer (&ret_xattrs, g_variant_unref); + if (!builder_initialized) + g_variant_builder_clear (&builder); return ret; #else return TRUE; @@ -1516,6 +1527,39 @@ get_xattrs_impl (GFile *f, } /** + * gs_dfd_and_name_get_all_xattrs: + * @dfd: Parent directory file descriptor + * @name: File name + * @out_xattrs: (out): Extended attribute set + * @cancellable: Cancellable + * @error: Error + * + * Load all extended attributes for the file named @name residing in + * directory @dfd. + */ +gboolean +gs_dfd_and_name_get_all_xattrs (int dfd, + const char *name, + GVariant **out_xattrs, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + /* A workaround for the lack of lgetxattrat(), thanks to Florian Weimer: + * https://mail.gnome.org/archives/ostree-list/2014-February/msg00017.html + */ + char *path = g_strdup_printf ("/proc/self/fd/%d/%s", dfd, name); + if (!get_xattrs_impl (path, out_xattrs, + cancellable, error)) + goto out; + + ret = TRUE; + out: + g_free (path); + return ret; +} + +/** * gs_file_get_all_xattrs: * @f: a #GFile * @out_xattrs: (out): A new #GVariant containing the extended attributes @@ -1534,29 +1578,8 @@ gs_file_get_all_xattrs (GFile *f, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - GVariantBuilder builder; - gboolean builder_initialized = FALSE; - GVariant *ret_xattrs = NULL; - - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ayay)")); - builder_initialized = TRUE; - - if (!get_xattrs_impl (f, &builder, - cancellable, error)) - goto out; - - ret_xattrs = g_variant_builder_end (&builder); - builder_initialized = FALSE; - g_variant_ref_sink (ret_xattrs); - - ret = TRUE; - gs_transfer_out_value (out_xattrs, &ret_xattrs); - out: - g_clear_pointer (&ret_xattrs, g_variant_unref); - if (!builder_initialized) - g_variant_builder_clear (&builder); - return ret; + return get_xattrs_impl (gs_file_get_path_cached (f), out_xattrs, + cancellable, error); } /** |