The patches for 3.0.0.
[rsync/rsync-patches.git] / osx-create-time.diff
CommitLineData
55175a2c
WD
1This patch handles the creation time on OS X by putting it into an
2extended attribute. This is a modified version of a patch that was
3provided by Wesley W. Terpstra.
4
5To use this patch, run these commands for a successful build:
6
7 patch -p1 <patches/osx-create-time.diff
8 ./configure (optional if already run)
9 make
10
cc3e685d
WD
11diff --git a/lib/sysxattrs.c b/lib/sysxattrs.c
12--- a/lib/sysxattrs.c
13+++ b/lib/sysxattrs.c
f9df736a 14@@ -53,29 +53,118 @@ ssize_t sys_llistxattr(const char *path, char *list, size_t size)
55175a2c
WD
15
16 #elif HAVE_OSX_XATTRS
17
18+#include <sys/attr.h>
19+
20+#define CRTIME_XATTR "com.apple.crtime96"
21+#define IS_CRTIME(name) (*(name) == *CRTIME_XATTR && strcmp(name, CRTIME_XATTR) == 0)
22+#define CRTIME_XATTR_LEN (8+4)
23+
24+struct CreationTime {
25+ unsigned long length;
42d12f3d 26+ struct timespec crtime;
55175a2c
WD
27+};
28+
42d12f3d 29+static struct timespec *getCreationTime(const char *path)
55175a2c 30+{
42d12f3d 31+ static struct CreationTime attrBuf;
55175a2c 32+ struct attrlist attrList;
42d12f3d
WD
33+
34+ memset(&attrList, 0, sizeof attrList);
35+ attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
36+ attrList.commonattr = ATTR_CMN_CRTIME;
37+ if (getattrlist(path, &attrList, &attrBuf, sizeof attrBuf, FSOPT_NOFOLLOW) < 0)
38+ return NULL;
39+ return &attrBuf.crtime;
40+}
41+
42+static ssize_t get_crtime_xattr(const char *path, char *buf, size_t size)
43+{
44+ struct timespec *crtime_p;
55175a2c
WD
45+
46+ if (buf == NULL)
47+ return CRTIME_XATTR_LEN;
48+ if (size < CRTIME_XATTR_LEN)
49+ return -1; /* Doesn't happen with rsync code... */
50+
42d12f3d 51+ if ((crtime_p = getCreationTime(path)) == NULL)
55175a2c
WD
52+ return -1;
53+
42d12f3d 54+ SIVAL(buf, 0, crtime_p->tv_sec);
55175a2c 55+#if SIZEOF_TIME_T > 4
42d12f3d 56+ SIVAL(buf, 4, crtime_p->tv_sec >> 32);
55175a2c
WD
57+#else
58+ SIVAL(buf, 4, 0);
59+#endif
42d12f3d 60+ SIVAL(buf, 8, crtime_p->tv_nsec);
55175a2c
WD
61+
62+ return CRTIME_XATTR_LEN;
63+}
64+
42d12f3d 65+static int set_crtime_xattr(const char *path, const char *buf, size_t size)
55175a2c
WD
66+{
67+ struct attrlist attrList;
42d12f3d 68+ struct timespec crtime;
55175a2c
WD
69+
70+ if (size != CRTIME_XATTR_LEN)
71+ return -1;
72+
42d12f3d 73+ crtime.tv_sec = IVAL(buf, 0);
55175a2c 74+#if SIZEOF_TIME_T > 4
42d12f3d 75+ crtime.tv_sec += (time_t)IVAL(buf, 4) << 32;
55175a2c 76+#endif
42d12f3d 77+ crtime.tv_nsec = IVAL(buf, 8);
55175a2c
WD
78+
79+ memset(&attrList, 0, sizeof attrList);
80+ attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
81+ attrList.commonattr = ATTR_CMN_CRTIME;
42d12f3d 82+ return setattrlist(path, &attrList, &crtime, sizeof crtime, FSOPT_NOFOLLOW);
55175a2c
WD
83+}
84+
85 ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
86 {
87+ if (IS_CRTIME(name))
42d12f3d 88+ return get_crtime_xattr(path, value, size);
55175a2c
WD
89 return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
90 }
91
92 ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
93 {
42d12f3d 94+ /* XXX Figure out how to get creation time from an open filedes? */
55175a2c
WD
95 return fgetxattr(filedes, name, value, size, 0, 0);
96 }
97
98 int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
99 {
100+ if (IS_CRTIME(name))
42d12f3d 101+ return set_crtime_xattr(path, value, size);
55175a2c
WD
102 return setxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
103 }
104
105 int sys_lremovexattr(const char *path, const char *name)
106 {
107+ /* Every file on hfs+ has this; you can't remove it... */
108+ if (IS_CRTIME(name))
109+ return 0;
110 return removexattr(path, name, XATTR_NOFOLLOW);
111 }
112
113 ssize_t sys_llistxattr(const char *path, char *list, size_t size)
114 {
115- return listxattr(path, list, size, XATTR_NOFOLLOW);
116+ ssize_t ret = listxattr(path, list, size, XATTR_NOFOLLOW);
117+ if (ret < 0)
118+ return ret;
42d12f3d
WD
119+ if (getCreationTime(path) != NULL) {
120+ ret += sizeof CRTIME_XATTR;
121+ if (list) {
122+ if ((size_t)ret > size) {
123+ errno = ERANGE;
124+ return -1;
125+ }
126+ memcpy(list + ret - sizeof CRTIME_XATTR,
127+ CRTIME_XATTR, sizeof CRTIME_XATTR);
55175a2c 128+ }
55175a2c
WD
129+ }
130+ return ret;
131 }
132
133 #elif HAVE_FREEBSD_XATTRS