Add ot_lgetxattrat and ot_lsetxattrat utils

These are implementation of the missing corresponding syscalls that
are done with the /proc/self/fd mechanism described at:

https://mail.gnome.org/archives/ostree-list/2014-February/msg00017.html

https://bugzilla.gnome.org/show_bug.cgi?id=741125
This commit is contained in:
Alexander Larsson 2014-12-03 10:58:41 +01:00
parent b8a06c11f6
commit 26a47b9cca
2 changed files with 80 additions and 0 deletions

View File

@ -21,6 +21,8 @@
#include "config.h" #include "config.h"
#include "ot-fs-utils.h" #include "ot-fs-utils.h"
#include "libgsystem.h"
#include <attr/xattr.h>
int int
ot_opendirat (int dfd, const char *path, gboolean follow) ot_opendirat (int dfd, const char *path, gboolean follow)
@ -48,3 +50,68 @@ ot_gopendirat (int dfd,
return TRUE; return TRUE;
} }
GBytes *
ot_lgetxattrat (int dfd,
const char *path,
const char *attribute,
GError **error)
{
/* A workaround for the lack of lgetxattrat(), thanks to Florian Weimer:
* https://mail.gnome.org/archives/ostree-list/2014-February/msg00017.html
*/
gs_free char *full_path = g_strdup_printf ("/proc/self/fd/%d/%s", dfd, path);
GBytes *bytes = NULL;
ssize_t bytes_read, real_size;
char *buf;
do
bytes_read = lgetxattr (full_path, attribute, NULL, 0);
while (G_UNLIKELY (bytes_read < 0 && errno == EINTR));
if (G_UNLIKELY (bytes_read < 0))
{
ot_util_set_error_from_errno (error, errno);
goto out;
}
buf = g_malloc (bytes_read);
do
real_size = lgetxattr (full_path, attribute, buf, bytes_read);
while (G_UNLIKELY (real_size < 0 && errno == EINTR));
if (G_UNLIKELY (real_size < 0))
{
ot_util_set_error_from_errno (error, errno);
g_free (buf);
goto out;
}
bytes = g_bytes_new_take (buf, real_size);
out:
return bytes;
}
gboolean
ot_lsetxattrat (int dfd,
const char *path,
const char *attribute,
const void *value,
gsize value_size,
int flags,
GError **error)
{
/* A workaround for the lack of lsetxattrat(), thanks to Florian Weimer:
* https://mail.gnome.org/archives/ostree-list/2014-February/msg00017.html
*/
gs_free char *full_path = g_strdup_printf ("/proc/self/fd/%d/%s", dfd, path);
int res;
do
res = lsetxattr (full_path, "user.ostreemeta", value, value_size, flags);
while (G_UNLIKELY (res == -1 && errno == EINTR));
if (G_UNLIKELY (res == -1))
{
ot_util_set_error_from_errno (error, errno);
return FALSE;
}
return TRUE;
}

View File

@ -31,5 +31,18 @@ gboolean ot_gopendirat (int dfd,
int *out_fd, int *out_fd,
GError **error); GError **error);
GBytes * ot_lgetxattrat (int dfd,
const char *path,
const char *attribute,
GError **error);
gboolean ot_lsetxattrat (int dfd,
const char *path,
const char *attribute,
const void *value,
gsize value_size,
int flags,
GError **error);
G_END_DECLS G_END_DECLS