Commit | Line | Data |
---|---|---|
55175a2c WD |
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. | |
4 | ||
5 | To 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 | ||
11 | --- old/lib/sysxattrs.c | |
12 | +++ new/lib/sysxattrs.c | |
42d12f3d | 13 | @@ -52,29 +52,118 @@ ssize_t sys_llistxattr(const char *path, |
55175a2c WD |
14 | |
15 | #elif HAVE_OSX_XATTRS | |
16 | ||
17 | +#include <sys/attr.h> | |
18 | + | |
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) | |
22 | + | |
23 | +struct CreationTime { | |
24 | + unsigned long length; | |
42d12f3d | 25 | + struct timespec crtime; |
55175a2c WD |
26 | +}; |
27 | + | |
42d12f3d | 28 | +static struct timespec *getCreationTime(const char *path) |
55175a2c | 29 | +{ |
42d12f3d | 30 | + static struct CreationTime attrBuf; |
55175a2c | 31 | + struct attrlist attrList; |
42d12f3d WD |
32 | + |
33 | + memset(&attrList, 0, sizeof attrList); | |
34 | + attrList.bitmapcount = ATTR_BIT_MAP_COUNT; | |
35 | + attrList.commonattr = ATTR_CMN_CRTIME; | |
36 | + if (getattrlist(path, &attrList, &attrBuf, sizeof attrBuf, FSOPT_NOFOLLOW) < 0) | |
37 | + return NULL; | |
38 | + return &attrBuf.crtime; | |
39 | +} | |
40 | + | |
41 | +static ssize_t get_crtime_xattr(const char *path, char *buf, size_t size) | |
42 | +{ | |
43 | + struct timespec *crtime_p; | |
55175a2c WD |
44 | + |
45 | + if (buf == NULL) | |
46 | + return CRTIME_XATTR_LEN; | |
47 | + if (size < CRTIME_XATTR_LEN) | |
48 | + return -1; /* Doesn't happen with rsync code... */ | |
49 | + | |
42d12f3d | 50 | + if ((crtime_p = getCreationTime(path)) == NULL) |
55175a2c WD |
51 | + return -1; |
52 | + | |
42d12f3d | 53 | + SIVAL(buf, 0, crtime_p->tv_sec); |
55175a2c | 54 | +#if SIZEOF_TIME_T > 4 |
42d12f3d | 55 | + SIVAL(buf, 4, crtime_p->tv_sec >> 32); |
55175a2c WD |
56 | +#else |
57 | + SIVAL(buf, 4, 0); | |
58 | +#endif | |
42d12f3d | 59 | + SIVAL(buf, 8, crtime_p->tv_nsec); |
55175a2c WD |
60 | + |
61 | + return CRTIME_XATTR_LEN; | |
62 | +} | |
63 | + | |
42d12f3d | 64 | +static int set_crtime_xattr(const char *path, const char *buf, size_t size) |
55175a2c WD |
65 | +{ |
66 | + struct attrlist attrList; | |
42d12f3d | 67 | + struct timespec crtime; |
55175a2c WD |
68 | + |
69 | + if (size != CRTIME_XATTR_LEN) | |
70 | + return -1; | |
71 | + | |
42d12f3d | 72 | + crtime.tv_sec = IVAL(buf, 0); |
55175a2c | 73 | +#if SIZEOF_TIME_T > 4 |
42d12f3d | 74 | + crtime.tv_sec += (time_t)IVAL(buf, 4) << 32; |
55175a2c | 75 | +#endif |
42d12f3d | 76 | + crtime.tv_nsec = IVAL(buf, 8); |
55175a2c WD |
77 | + |
78 | + memset(&attrList, 0, sizeof attrList); | |
79 | + attrList.bitmapcount = ATTR_BIT_MAP_COUNT; | |
80 | + attrList.commonattr = ATTR_CMN_CRTIME; | |
42d12f3d | 81 | + return setattrlist(path, &attrList, &crtime, sizeof crtime, FSOPT_NOFOLLOW); |
55175a2c WD |
82 | +} |
83 | + | |
84 | ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size) | |
85 | { | |
86 | + if (IS_CRTIME(name)) | |
42d12f3d | 87 | + return get_crtime_xattr(path, value, size); |
55175a2c WD |
88 | return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW); |
89 | } | |
90 | ||
91 | ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size) | |
92 | { | |
42d12f3d | 93 | + /* XXX Figure out how to get creation time from an open filedes? */ |
55175a2c WD |
94 | return fgetxattr(filedes, name, value, size, 0, 0); |
95 | } | |
96 | ||
97 | int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size) | |
98 | { | |
99 | + if (IS_CRTIME(name)) | |
42d12f3d | 100 | + return set_crtime_xattr(path, value, size); |
55175a2c WD |
101 | return setxattr(path, name, value, size, 0, XATTR_NOFOLLOW); |
102 | } | |
103 | ||
104 | int sys_lremovexattr(const char *path, const char *name) | |
105 | { | |
106 | + /* Every file on hfs+ has this; you can't remove it... */ | |
107 | + if (IS_CRTIME(name)) | |
108 | + return 0; | |
109 | return removexattr(path, name, XATTR_NOFOLLOW); | |
110 | } | |
111 | ||
112 | ssize_t sys_llistxattr(const char *path, char *list, size_t size) | |
113 | { | |
114 | - return listxattr(path, list, size, XATTR_NOFOLLOW); | |
115 | + ssize_t ret = listxattr(path, list, size, XATTR_NOFOLLOW); | |
116 | + if (ret < 0) | |
117 | + return ret; | |
42d12f3d WD |
118 | + if (getCreationTime(path) != NULL) { |
119 | + ret += sizeof CRTIME_XATTR; | |
120 | + if (list) { | |
121 | + if ((size_t)ret > size) { | |
122 | + errno = ERANGE; | |
123 | + return -1; | |
124 | + } | |
125 | + memcpy(list + ret - sizeof CRTIME_XATTR, | |
126 | + CRTIME_XATTR, sizeof CRTIME_XATTR); | |
55175a2c | 127 | + } |
55175a2c WD |
128 | + } |
129 | + return ret; | |
130 | } | |
131 | ||
132 | #elif HAVE_FREEBSD_XATTRS |