@@ -32,6 +32,8 @@ FedFsStatus junction_is_sticky_bit_set(int fd, const char *path);
FedFsStatus junction_set_sticky_bit(int fd, const char *path);
FedFsStatus junction_is_xattr_present(int fd, const char *path,
const char *name);
+FedFsStatus junction_read_xattr(int fd, const char *path, const char *name,
+ char **contents);
FedFsStatus junction_get_xattr(int fd, const char *path, const char *name,
void **contents, size_t *contentlen);
FedFsStatus junction_set_xattr(int fd, const char *path, const char *name,
@@ -221,6 +221,54 @@ junction_is_xattr_present(int fd, const char *path, const char *name)
}
/**
+ * Read the contents of xattr "name"
+ *
+ * @param fd an open file descriptor
+ * @param path NUL-terminated C string containing pathname of a directory
+ * @param name NUL-terminated C string containing name of xattr to retrieve
+ * @param contents OUT: NUL-terminated C string containing contents of xattr
+ * @return a FedFsStatus code
+ *
+ * If junction_read_xattr() returns FEDFS_OK, the caller must free "*contents"
+ * with free(3).
+ *
+ * @note Access to trusted attributes requires CAP_SYS_ADMIN.
+ */
+FedFsStatus
+junction_read_xattr(int fd, const char *path, const char *name, char **contents)
+{
+ char *xattrbuf = NULL;
+ ssize_t len;
+
+ len = fgetxattr(fd, name, xattrbuf, 0);
+ if (len == -1) {
+ xlog(D_GENERAL, "%s: failed to get size of xattr %s on %s: %m",
+ __func__, name, path);
+ return FEDFS_ERR_ACCESS;
+ }
+
+ xattrbuf = malloc(len + 1);
+ if (xattrbuf == NULL) {
+ xlog(D_GENERAL, "%s: failed to get buffer for xattr %s on %s",
+ __func__, name, path);
+ return FEDFS_ERR_SVRFAULT;
+ }
+
+ if (fgetxattr(fd, name, xattrbuf, len) == -1) {
+ xlog(D_GENERAL, "%s: failed to get xattr %s on %s: %m",
+ __func__, name, path);
+ free(xattrbuf);
+ return FEDFS_ERR_ACCESS;
+ }
+ xattrbuf[len] = '\0';
+
+ xlog(D_CALL, "%s: read xattr %s from path %s",
+ __func__, name, path);
+ *contents = xattrbuf;
+ return FEDFS_OK;
+}
+
+/**
* Retrieve the contents of xattr "name"
*
* @param fd an open file descriptor
@@ -230,6 +278,9 @@ junction_is_xattr_present(int fd, const char *path, const char *name)
* @param contentlen OUT: size of "contents"
* @return a FedFsStatus code
*
+ * If junction_get_xattr() returns FEDFS_OK, the caller must free "*contents"
+ * with free(3).
+ *
* @note Access to trusted attributes requires CAP_SYS_ADMIN.
*/
FedFsStatus
@@ -386,17 +437,15 @@ FedFsStatus
junction_restore_mode(const char *pathname)
{
FedFsStatus retval;
+ char *buf = NULL;
mode_t mode;
- size_t len;
- void *buf;
int fd;
retval = junction_open_path(pathname, &fd);
if (retval != FEDFS_OK)
return retval;
- retval = junction_get_xattr(fd, pathname, JUNCTION_XATTR_NAME_MODE,
- &buf, &len);
+ retval = junction_read_xattr(fd, pathname, JUNCTION_XATTR_NAME_MODE, &buf);
if (retval != FEDFS_OK)
goto out;
junction_get_xattr() returns an opaque byte array, but junction_restore_mode() treats it like a NUL-terminated string. Bad function, no biscuit. Fork off a second API that can return a NUL-terminated string. Callers will have to take care to choose the correct API. Introduced in commit 0520ee72: "Initial commit," (March 29, 2011). Signed-off-by: Chuck Lever <chuck.lever@oracle.com> --- src/libjunction/junction-internal.h | 2 + src/libjunction/junction.c | 57 +++++++++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 4 deletions(-)