Skip to content

Commit bedd8d1

Browse files
committed
Get xattrs working on macOS.
As the position argument isn’t carried all the way down resource forks won’t work properly (though it easily could be, that would change the internal API for everyone).
1 parent f6167d3 commit bedd8d1

11 files changed

+133
-20
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ ifeq ($(PANDOC),"")
4040
$(warning "pandoc does not appear available: manpage won't be buildable")
4141
endif
4242

43-
XATTR_AVAILABLE = $(shell test ! -e /usr/include/attr/xattr.h; echo $$?)
43+
XATTR_AVAILABLE = $(shell test ! -e /usr/include/attr/xattr.h -a ! -e /usr/include/sys/xattr.h; echo $$?)
4444

4545
FUSE_AVAILABLE = $(shell ! pkg-config --exists fuse; echo $$?)
4646

src/fs_base_getxattr.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@ namespace fs
3535
const size_t size)
3636
{
3737
#ifndef WITHOUT_XATTR
38+
#if __APPLE__
39+
return ::getxattr(path.c_str(),attrname,value,size,0,XATTR_NOFOLLOW);
40+
#else
3841
return ::lgetxattr(path.c_str(),attrname,value,size);
42+
#endif /* __APPLE__ */
3943
#else
4044
return (errno=ENOTSUP,-1);
4145
#endif

src/fs_base_listxattr.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ namespace fs
3434
const size_t size)
3535
{
3636
#ifndef WITHOUT_XATTR
37+
#if __APPLE__
38+
return ::listxattr(path.c_str(),list,size,XATTR_NOFOLLOW);
39+
#else
3740
return ::llistxattr(path.c_str(),list,size);
41+
#endif /* __APPLE__ */
3842
#else
3943
return (errno=ENOTSUP,-1);
4044
#endif

src/fs_base_removexattr.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@ namespace fs
3333
const char *attrname)
3434
{
3535
#ifndef WITHOUT_XATTR
36+
#if __APPLE__
37+
return ::removexattr(path.c_str(),attrname,XATTR_NOFOLLOW);
38+
#else
3639
return ::lremovexattr(path.c_str(),attrname);
40+
#endif /* __APPLE__ */
3741
#else
3842
return (errno=ENOTSUP,-1);
3943
#endif

src/fs_base_setxattr.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ namespace fs
3636
const int flags)
3737
{
3838
#ifndef WITHOUT_XATTR
39+
#if __APPLE__
40+
return ::setxattr(path.c_str(),name,value,size,0,flags);
41+
#else
3942
return ::lsetxattr(path.c_str(),name,value,size,flags);
43+
#endif /* __APPLE__ */
4044
#else
4145
return (errno=ENOTSUP,-1);
4246
#endif

src/fs_xattr.cpp

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,60 @@ using std::vector;
3636
using std::map;
3737
using std::istringstream;
3838

39+
/*
40+
The Mac version of the get/set APIs includes a position arg to seek around the
41+
resource fork; for all other uses, the value is 0.
42+
43+
For the other APIs, there are no link-specific variants; rather the standard call
44+
has a flags argument where XATTR_NOFOLLOW is specified to address the link itself.
45+
*/
46+
47+
#if __APPLE__
48+
ssize_t
49+
_flistxattr(int fd, char* namebuf, size_t size)
50+
{
51+
return ::flistxattr(fd, namebuf, size, 0);
52+
}
53+
54+
ssize_t
55+
_llistxattr(const char* path, char* namebuf, size_t size)
56+
{
57+
return ::listxattr(path, namebuf, size, XATTR_NOFOLLOW);
58+
}
59+
60+
ssize_t
61+
_fgetxattr(int fd, const char* name, char* value, size_t size)
62+
{
63+
return ::fgetxattr(fd, name, value, size, 0, 0);
64+
}
65+
66+
int
67+
_lgetxattr(const char* path, const char* name, char* value, size_t size)
68+
{
69+
return ::getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
70+
}
71+
72+
int
73+
_fsetxattr(int fd, const char* name, const char* value, size_t size, int flags)
74+
{
75+
return ::fsetxattr(fd, name, value, size, 0, flags);
76+
}
77+
78+
int
79+
_lsetxattr(const char* path, const char* name, const char* value, size_t size, int flags)
80+
{
81+
return ::setxattr(path, name, value, size, 0, flags && XATTR_NOFOLLOW);
82+
}
83+
84+
#else
85+
#define _flistxattr ::flistxattr
86+
#define _llistxattr ::llistxattr
87+
#define _fgetxattr ::fgetxattr
88+
#define _lgetxattr ::lgetxattr
89+
#define _fsetxattr ::fsetxattr
90+
#define _lsetxattr ::lsetxattr
91+
#endif
92+
3993
namespace fs
4094
{
4195
namespace xattr
@@ -51,13 +105,13 @@ namespace fs
51105
errno = ERANGE;
52106
while((rv == -1) && (errno == ERANGE))
53107
{
54-
rv = ::flistxattr(fd,NULL,0);
108+
rv = _flistxattr(fd,NULL,0);
55109
if(rv <= 0)
56110
return rv;
57111

58112
attrs.resize(rv);
59113

60-
rv = ::flistxattr(fd,&attrs[0],rv);
114+
rv = _flistxattr(fd,&attrs[0],rv);
61115
}
62116

63117
return rv;
@@ -77,13 +131,13 @@ namespace fs
77131
errno = ERANGE;
78132
while((rv == -1) && (errno == ERANGE))
79133
{
80-
rv = ::llistxattr(path.c_str(),NULL,0);
134+
rv = _llistxattr(path.c_str(),NULL,0);
81135
if(rv <= 0)
82136
return rv;
83137

84138
attrs.resize(rv);
85139

86-
rv = ::llistxattr(path.c_str(),&attrs[0],rv);
140+
rv = _llistxattr(path.c_str(),&attrs[0],rv);
87141
}
88142

89143
return rv;
@@ -166,13 +220,13 @@ namespace fs
166220
errno = ERANGE;
167221
while((rv == -1) && (errno == ERANGE))
168222
{
169-
rv = ::fgetxattr(fd,attr.c_str(),NULL,0);
223+
rv = _fgetxattr(fd,attr.c_str(),NULL,0);
170224
if(rv <= 0)
171225
return rv;
172226

173227
value.resize(rv);
174228

175-
rv = ::fgetxattr(fd,attr.c_str(),&value[0],rv);
229+
rv = _fgetxattr(fd,attr.c_str(),&value[0],rv);
176230
}
177231

178232
return rv;
@@ -193,13 +247,13 @@ namespace fs
193247
errno = ERANGE;
194248
while((rv == -1) && (errno == ERANGE))
195249
{
196-
rv = ::lgetxattr(path.c_str(),attr.c_str(),NULL,0);
250+
rv = _lgetxattr(path.c_str(),attr.c_str(),NULL,0);
197251
if(rv <= 0)
198252
return rv;
199253

200254
value.resize(rv);
201255

202-
rv = ::lgetxattr(path.c_str(),attr.c_str(),&value[0],rv);
256+
rv = _lgetxattr(path.c_str(),attr.c_str(),&value[0],rv);
203257
}
204258

205259
return rv;
@@ -301,11 +355,11 @@ namespace fs
301355
const int flags)
302356
{
303357
#ifndef WITHOUT_XATTR
304-
return ::fsetxattr(fd,
305-
key.c_str(),
306-
value.data(),
307-
value.size(),
308-
flags);
358+
return _fsetxattr(fd,
359+
key.c_str(),
360+
value.data(),
361+
value.size(),
362+
flags);
309363
#else
310364
return (errno=ENOTSUP,-1);
311365
#endif
@@ -318,11 +372,11 @@ namespace fs
318372
const int flags)
319373
{
320374
#ifndef WITHOUT_XATTR
321-
return ::lsetxattr(path.c_str(),
322-
key.c_str(),
323-
value.data(),
324-
value.size(),
325-
flags);
375+
return _lsetxattr(path.c_str(),
376+
key.c_str(),
377+
value.data(),
378+
value.size(),
379+
flags);
326380
#else
327381
return (errno=ENOTSUP,-1);
328382
#endif

src/getxattr.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,11 +302,20 @@ namespace mergerfs
302302
{
303303
namespace fuse
304304
{
305+
#if __APPLE__
306+
int
307+
getxattr(const char *fusepath,
308+
const char *attrname,
309+
char *buf,
310+
size_t count,
311+
uint32_t position)
312+
#else
305313
int
306314
getxattr(const char *fusepath,
307315
const char *attrname,
308316
char *buf,
309317
size_t count)
318+
#endif
310319
{
311320
const fuse_context *fc = fuse_get_context();
312321
const Config &config = Config::get(fc);

src/getxattr.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,22 @@ namespace mergerfs
2121
{
2222
namespace fuse
2323
{
24+
#if __APPLE__
25+
int
26+
getxattr(const char *fusepath,
27+
const char *attrname,
28+
char *buf,
29+
size_t count,
30+
uint32_t position);
31+
}
32+
#else
2433
int
2534
getxattr(const char *fusepath,
2635
const char *attrname,
2736
char *buf,
2837
size_t count);
2938
}
39+
#endif
3040
}
3141

3242
#endif

src/setxattr.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,12 +353,22 @@ namespace mergerfs
353353
{
354354
namespace fuse
355355
{
356+
#if __APPLE__
357+
int
358+
setxattr(const char *fusepath,
359+
const char *attrname,
360+
const char *attrval,
361+
size_t attrvalsize,
362+
int flags,
363+
uint32_t position)
364+
#else
356365
int
357366
setxattr(const char *fusepath,
358367
const char *attrname,
359368
const char *attrval,
360369
size_t attrvalsize,
361370
int flags)
371+
#endif
362372
{
363373
const fuse_context *fc = fuse_get_context();
364374
const Config &config = Config::get(fc);

src/setxattr.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,22 @@ namespace mergerfs
2121
{
2222
namespace fuse
2323
{
24+
#if __APPLE__
25+
int
26+
setxattr(const char *fusepath,
27+
const char *attrname,
28+
const char *attrval,
29+
size_t attrvalsize,
30+
int flags,
31+
uint32_t position);
32+
#else
2433
int
2534
setxattr(const char *fusepath,
2635
const char *attrname,
2736
const char *attrval,
2837
size_t attrvalsize,
2938
int flags);
39+
#endif
3040
}
3141
}
3242

src/xattr.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@
1818
#define __XATTR_HPP__
1919

2020
#ifndef WITHOUT_XATTR
21+
#if __APPLE__
22+
#include <sys/xattr.h>
23+
#else
2124
#include <attr/xattr.h>
22-
#endif
25+
#endif /* __APPLE__ */
26+
#endif /* WITHOUT_XATTR */
2327

2428
#ifndef XATTR_CREATE
2529
# define XATTR_CREATE 0x1

0 commit comments

Comments
 (0)