Renamed flags.diff fileflags.diff.
[rsync-patches.git] / osx-create-time.diff
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 diff --git a/lib/sysxattrs.c b/lib/sysxattrs.c
12 --- a/lib/sysxattrs.c
13 +++ b/lib/sysxattrs.c
14 @@ -52,29 +52,118 @@ ssize_t sys_llistxattr(const char *path, char *list, size_t size)
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;
26 +       struct timespec crtime;
27 +};
28 +
29 +static struct timespec *getCreationTime(const char *path)
30 +{
31 +       static struct CreationTime attrBuf;
32 +       struct attrlist attrList;
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;
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 +
51 +       if ((crtime_p = getCreationTime(path)) == NULL)
52 +               return -1;
53 +
54 +       SIVAL(buf, 0, crtime_p->tv_sec);
55 +#if SIZEOF_TIME_T > 4
56 +       SIVAL(buf, 4, crtime_p->tv_sec >> 32);
57 +#else
58 +       SIVAL(buf, 4, 0);
59 +#endif
60 +       SIVAL(buf, 8, crtime_p->tv_nsec);
61 +
62 +       return CRTIME_XATTR_LEN;
63 +}
64 +
65 +static int set_crtime_xattr(const char *path, const char *buf, size_t size)
66 +{
67 +       struct attrlist attrList;
68 +       struct timespec crtime;
69 +
70 +       if (size != CRTIME_XATTR_LEN)
71 +               return -1;
72 +
73 +       crtime.tv_sec = IVAL(buf, 0);
74 +#if SIZEOF_TIME_T > 4
75 +       crtime.tv_sec += (time_t)IVAL(buf, 4) << 32;
76 +#endif
77 +       crtime.tv_nsec = IVAL(buf, 8);
78 +
79 +       memset(&attrList, 0, sizeof attrList);
80 +       attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
81 +       attrList.commonattr = ATTR_CMN_CRTIME;
82 +       return setattrlist(path, &attrList, &crtime, sizeof crtime, FSOPT_NOFOLLOW);
83 +}
84 +
85  ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
86  {
87 +       if (IS_CRTIME(name))
88 +               return get_crtime_xattr(path, value, size);
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  {
94 +       /* XXX Figure out how to get creation time from an open filedes? */
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))
101 +               return set_crtime_xattr(path, value, size);
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;
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);
128 +               }
129 +       }
130 +       return ret;
131  }
132  
133  #elif HAVE_FREEBSD_XATTRS