#endif
}
+char *
+do_getxattr (const char *path, const char *name, size_t *size_r)
+{
+ ssize_t r;
+ char *buf;
+ size_t len;
+
+ CHROOT_IN;
+ r = getxattr (path, name, NULL, 0);
+ CHROOT_OUT;
+ if (r == -1) {
+ reply_with_perror ("getxattr");
+ return NULL;
+ }
+
+ len = r;
+ buf = malloc (len);
+ if (buf == NULL) {
+ reply_with_perror ("malloc");
+ return NULL;
+ }
+
+ CHROOT_IN;
+ r = getxattr (path, name, buf, len);
+ CHROOT_OUT;
+ if (r == -1) {
+ reply_with_perror ("getxattr");
+ free (buf);
+ return NULL;
+ }
+
+ if (len != (size_t) r) {
+ reply_with_error ("getxattr: unexpected size (%zu/%zd)", len, r);
+ free (buf);
+ return NULL;
+ }
+
+ /* Must set size_r last thing before returning. */
+ *size_r = len;
+ return buf; /* caller frees */
+}
+
+char *
+do_lgetxattr (const char *path, const char *name, size_t *size_r)
+{
+ ssize_t r;
+ char *buf;
+ size_t len;
+
+ CHROOT_IN;
+ r = lgetxattr (path, name, NULL, 0);
+ CHROOT_OUT;
+ if (r == -1) {
+ reply_with_perror ("lgetxattr");
+ return NULL;
+ }
+
+ len = r;
+ buf = malloc (len);
+ if (buf == NULL) {
+ reply_with_perror ("malloc");
+ return NULL;
+ }
+
+ CHROOT_IN;
+ r = lgetxattr (path, name, buf, len);
+ CHROOT_OUT;
+ if (r == -1) {
+ reply_with_perror ("lgetxattr");
+ free (buf);
+ return NULL;
+ }
+
+ if (len != (size_t) r) {
+ reply_with_error ("lgetxattr: unexpected size (%zu/%zd)", len, r);
+ free (buf);
+ return NULL;
+ }
+
+ /* Must set size_r last thing before returning. */
+ *size_r = len;
+ return buf; /* caller frees */
+}
+
#else /* no xattr.h */
int
optgroup_linuxxattrs_available (void)
NOT_AVAILABLE (NULL);
}
+char *
+do_getxattr (const char *path, const char *name, size_t *size_r)
+{
+ NOT_AVAILABLE (NULL);
+}
+
+char *
+do_lgetxattr (const char *path, const char *name, size_t *size_r)
+{
+ NOT_AVAILABLE (NULL);
+}
+
#endif /* no xattr.h */
=back");
+ ("getxattr", (RBufferOut "xattr", [Pathname "path"; String "name"], []), 279, [Optional "linuxxattrs"],
+ [],
+ "get a single extended attribute",
+ "\
+Get a single extended attribute from file C<path> named C<name>.
+This call follows symlinks. If you want to lookup an extended
+attribute for the symlink itself, use C<guestfs_lgetxattr>.
+
+Normally it is better to get all extended attributes from a file
+in one go by calling C<guestfs_getxattrs>. However some Linux
+filesystem implementations are buggy and do not provide a way to
+list out attributes. For these filesystems (notably ntfs-3g)
+you have to know the names of the extended attributes you want
+in advance and call this function.
+
+Extended attribute values are blobs of binary data. If there
+is no extended attribute named C<name>, this returns an error.
+
+See also: C<guestfs_getxattrs>, C<guestfs_lgetxattr>, L<attr(5)>.");
+
+ ("lgetxattr", (RBufferOut "xattr", [Pathname "path"; String "name"], []), 280, [Optional "linuxxattrs"],
+ [],
+ "get a single extended attribute",
+ "\
+Get a single extended attribute from file C<path> named C<name>.
+If C<path> is a symlink, then this call returns an extended
+attribute from the symlink.
+
+Normally it is better to get all extended attributes from a file
+in one go by calling C<guestfs_getxattrs>. However some Linux
+filesystem implementations are buggy and do not provide a way to
+list out attributes. For these filesystems (notably ntfs-3g)
+you have to know the names of the extended attributes you want
+in advance and call this function.
+
+Extended attribute values are blobs of binary data. If there
+is no extended attribute named C<name>, this returns an error.
+
+See also: C<guestfs_lgetxattrs>, C<guestfs_getxattr>, L<attr(5)>.");
+
]
let all_functions = non_daemon_functions @ daemon_functions