summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorWayne Davison <wayned@samba.org>2013-11-25 13:12:09 -0800
committerWayne Davison <wayned@samba.org>2013-11-25 13:12:09 -0800
commit2cd87086f05d0a6d943e8fa71f7f6b53b5375d56 (patch)
tree2a79b6be4e05062c5b6a826e76f314c419576c33 /lib
parenteaa4e2d1ee5518f3d785279cacf6bf794473ef16 (diff)
downloadrsync-2cd87086f05d0a6d943e8fa71f7f6b53b5375d56.tar.gz
rsync-2cd87086f05d0a6d943e8fa71f7f6b53b5375d56.tar.bz2
rsync-2cd87086f05d0a6d943e8fa71f7f6b53b5375d56.zip
Use chunked xattr reading in OS X sys_lgetxattr().
Diffstat (limited to 'lib')
-rw-r--r--lib/sysxattrs.c23
1 files changed, 22 insertions, 1 deletions
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)