New APIs: getxattr and lgetxattr to get single extended attributes.
authorRichard W.M. Jones <rjones@redhat.com>
Thu, 16 Dec 2010 20:05:48 +0000 (20:05 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Thu, 16 Dec 2010 20:05:48 +0000 (20:05 +0000)
These APIs are essentially required to work around a problem
with ntfs-3g.  This filesystem (or FUSE?) does not list all
extended attributes of a file when you call listxattr(2).  However
if you know the name of an extended attribute, you can retrieve
it directly using getxattr(2).

The current APIs (getxattrs etc) are simple to use, but they
don't work if we can't list out the extended attributes (ie.
by calling listxattr(2)).

Example using the new APIs on an ntfs-3g filesystem:

><fs> lgetxattr "/Documents and Settings" system.ntfs_attrib | hexdump -C
00000000  16 24 00 00                                       |.$..|
00000004
><fs> lgetxattr "/Documents and Settings" system.ntfs_reparse_data | hexdump -C
00000000  03 00 00 a0 34 00 00 00  00 00 18 00 1a 00 10 00  |....4...........|
00000010  5c 00 3f 00 3f 00 5c 00  43 00 3a 00 5c 00 55 00  |\.?.?.\.C.:.\.U.|
00000020  73 00 65 00 72 00 73 00  00 00 43 00 3a 00 5c 00  |s.e.r.s...C.:.\.|
00000030  55 00 73 00 65 00 72 00  73 00 00 00              |U.s.e.r.s...|
0000003c
><fs> getxattr "/Documents and Settings" system.ntfs_reparse_data | hexdump -C
libguestfs: error: getxattr: getxattr: No such file or directory
><fs> getxattr "/Documents and Settings" system.ntfs_attrib | hexdump -C
libguestfs: error: getxattr: getxattr: No such file or directory
><fs> lgetxattr "/Documents and Settings" system.ntfs_attrib | hexdump -C
00000000  16 24 00 00                                       |.$..|
00000004
><fs> getxattr "/Users" system.ntfs_attrib | hexdump -C
00000000  11 00 00 00                                       |....|
00000004

daemon/xattr.c
generator/generator_actions.ml
src/MAX_PROC_NR

index a5169cf..bbccc5c 100644 (file)
@@ -448,6 +448,90 @@ do_lxattrlist (const char *path, char *const *names)
 #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)
@@ -497,4 +581,16 @@ do_lxattrlist (const char *path, char *const *names)
   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 */
index 5624dec..84e8eee 100644 (file)
@@ -5633,6 +5633,46 @@ the requested cluster size.
 
 =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
index 3d242f5..1b1c131 100644 (file)
@@ -1 +1 @@
-278
+280