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