1 This patch handles the creation time on OS X by putting it into an
2 extended attribute. This is a modified version of a patch that was
3 provided by Wesley W. Terpstra.
5 To use this patch, run these commands for a successful build:
7 patch -p1 <patches/osx-create-time.diff
8 ./configure (optional if already run)
11 --- old/lib/sysxattrs.c
12 +++ new/lib/sysxattrs.c
13 @@ -52,29 +52,106 @@ ssize_t sys_llistxattr(const char *path,
17 +#include <sys/attr.h>
19 +#define CRTIME_XATTR "com.apple.crtime96"
20 +#define IS_CRTIME(name) (*(name) == *CRTIME_XATTR && strcmp(name, CRTIME_XATTR) == 0)
21 +#define CRTIME_XATTR_LEN (8+4)
23 +struct CreationTime {
24 + unsigned long length;
25 + struct timespec date;
28 +static ssize_t getCreationTime(const char *path, char *buf, size_t size)
30 + struct attrlist attrList;
31 + struct CreationTime attrBuf;
34 + return CRTIME_XATTR_LEN;
35 + if (size < CRTIME_XATTR_LEN)
36 + return -1; /* Doesn't happen with rsync code... */
38 + memset(&attrList, 0, sizeof attrList);
39 + attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
40 + attrList.commonattr = ATTR_CMN_CRTIME;
41 + if (getattrlist(path, &attrList, &attrBuf, sizeof attrBuf, FSOPT_NOFOLLOW) < 0)
44 + SIVAL(buf, 0, attrBuf.date.tv_sec);
45 +#if SIZEOF_TIME_T > 4
46 + SIVAL(buf, 4, attrBuf.date.tv_sec >> 32);
50 + SIVAL(buf, 8, attrBuf.date.tv_nsec);
52 + return CRTIME_XATTR_LEN;
55 +static int setCreationTime(const char *path, const char *buf, size_t size)
57 + struct attrlist attrList;
58 + struct timespec date;
60 + if (size != CRTIME_XATTR_LEN)
63 + date.tv_sec = IVAL(buf, 0);
64 +#if SIZEOF_TIME_T > 4
65 + date.tv_sec += (time_t)IVAL(buf, 4) << 32;
67 + date.tv_nsec = IVAL(buf, 8);
69 + memset(&attrList, 0, sizeof attrList);
70 + attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
71 + attrList.commonattr = ATTR_CMN_CRTIME;
72 + return setattrlist(path, &attrList, &date, sizeof date, FSOPT_NOFOLLOW);
75 ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
77 + if (IS_CRTIME(name))
78 + return getCreationTime(path, value, size);
79 return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
82 ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
84 + /* XXX Figure out how to get creation date from an open filedes? */
85 return fgetxattr(filedes, name, value, size, 0, 0);
88 int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
90 + if (IS_CRTIME(name))
91 + return setCreationTime(path, value, size);
92 return setxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
95 int sys_lremovexattr(const char *path, const char *name)
97 + /* Every file on hfs+ has this; you can't remove it... */
98 + if (IS_CRTIME(name))
100 return removexattr(path, name, XATTR_NOFOLLOW);
103 ssize_t sys_llistxattr(const char *path, char *list, size_t size)
105 - return listxattr(path, list, size, XATTR_NOFOLLOW);
106 + ssize_t ret = listxattr(path, list, size, XATTR_NOFOLLOW);
109 + ret += sizeof CRTIME_XATTR;
111 + if ((size_t)ret > size) {
115 + memcpy(list + ret - sizeof CRTIME_XATTR, CRTIME_XATTR, sizeof CRTIME_XATTR);
120 #elif HAVE_FREEBSD_XATTRS