]> git.ipfire.org Git - thirdparty/rsync.git/commitdiff
Use chunked xattr reading in OS X sys_lgetxattr().
authorWayne Davison <wayned@samba.org>
Mon, 25 Nov 2013 21:12:09 +0000 (13:12 -0800)
committerWayne Davison <wayned@samba.org>
Mon, 25 Nov 2013 21:12:09 +0000 (13:12 -0800)
lib/sysxattrs.c

index d55ee0c2fbe9154ada7ed4f761ef1e311e13631c..ba1a29055a688c9ed6328ed19558e58c56d30c3c 100644 (file)
 
 #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)