From 2cd87086f05d0a6d943e8fa71f7f6b53b5375d56 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Mon, 25 Nov 2013 13:12:09 -0800 Subject: [PATCH] Use chunked xattr reading in OS X sys_lgetxattr(). --- lib/sysxattrs.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/sysxattrs.c b/lib/sysxattrs.c index d55ee0c2..ba1a2905 100644 --- a/lib/sysxattrs.c +++ b/lib/sysxattrs.c @@ -24,6 +24,10 @@ #ifdef SUPPORT_XATTRS +#ifdef HAVE_OSX_XATTRS +#define GETXATTR_FETCH_LIMIT (64*1024*1024) +#endif + #if defined HAVE_LINUX_XATTRS ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size) @@ -55,7 +59,24 @@ ssize_t sys_llistxattr(const char *path, char *list, size_t size) ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size) { - return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW); + ssize_t len = getxattr(path, name, value, size, 0, XATTR_NOFOLLOW); + + /* If we're retrieving data, handle resource forks > 64MB specially */ + if (value != NULL && len == GETXATTR_FETCH_LIMIT && (size_t)len < size) { + /* getxattr will only return 64MB of data at a time, need to call again with a new offset */ + u_int32_t offset = len; + size_t data_retrieved = len; + while (data_retrieved < size) { + len = getxattr(path, name, value + offset, size - data_retrieved, offset, XATTR_NOFOLLOW); + if (len <= 0) + break; + data_retrieved += len; + offset += (u_int32_t)len; + } + len = data_retrieved; + } + + return len; } ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size) -- 2.47.2