Add support for extended access() in Loopback-C
This commit is contained in:
parent
8ebe884c72
commit
ca5d4b94d9
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
FUSE: Filesystem in Userspace
|
||||
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
|
||||
This program can be distributed under the terms of the GNU GPL.
|
||||
See the file LICENSE.txt.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#define HAVE_EXCHANGE 0
|
||||
#define HAVE_RENAMEX 1
|
||||
#define HAVE_ACCESS 0
|
||||
|
||||
#define FUSE_USE_VERSION 26
|
||||
|
||||
|
|
@ -63,20 +64,20 @@ static int
|
|||
loopback_getattr(const char *path, struct stat *stbuf)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
res = lstat(path, stbuf);
|
||||
|
||||
|
||||
/*
|
||||
* The optimal I/O size can be set on a per-file basis. Setting st_blksize
|
||||
* to zero will cause the kernel extension to fall back on the global I/O
|
||||
* size which can be specified at mount-time (option iosize).
|
||||
*/
|
||||
stbuf->st_blksize = 0;
|
||||
|
||||
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -85,33 +86,73 @@ loopback_fgetattr(const char *path, struct stat *stbuf,
|
|||
struct fuse_file_info *fi)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
(void)path;
|
||||
|
||||
|
||||
res = fstat(fi->fh, stbuf);
|
||||
|
||||
|
||||
// Fall back to global I/O size. See loopback_getattr().
|
||||
stbuf->st_blksize = 0;
|
||||
|
||||
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if HAVE_ACCESS
|
||||
|
||||
static int
|
||||
loopback_access(const char *path, int mask)
|
||||
{
|
||||
int res;
|
||||
|
||||
/*
|
||||
* Standard access permission flags:
|
||||
* F_OK test for existence of file
|
||||
* X_OK test for execute or search permission
|
||||
* W_OK test for write permission
|
||||
* R_OK test for read permission
|
||||
*
|
||||
* Extended access permission flags that can be enabled by setting
|
||||
* FUSE_CAP_ACCESS_EXTENDED (See loopback_init()):
|
||||
* _READ_OK read file data / read directory
|
||||
* _WRITE_OK write file data / add file to directory
|
||||
* _EXECUTE_OK execute file / search in directory
|
||||
* _DELETE_OK delete file / delete directory
|
||||
* _APPEND_OK append to file / add subdirectory to directory
|
||||
* _RMFILE_OK remove file from directory
|
||||
* _RATTR_OK read basic attributes
|
||||
* _WATTR_OK write basic attributes
|
||||
* _REXT_OK read extended attributes
|
||||
* _WEXT_OK write extended attributes
|
||||
* _RPERM_OK read permissions
|
||||
* _WPERM_OK write permissions
|
||||
* _CHOWN_OK change ownership
|
||||
*/
|
||||
|
||||
res = access(path, mask & (F_OK | X_OK | W_OK | R_OK));
|
||||
if (res == -1)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* HAVE_ACCESS */
|
||||
|
||||
static int
|
||||
loopback_readlink(const char *path, char *buf, size_t size)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
res = readlink(path, buf, size - 1);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
buf[res] = '\0';
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -125,24 +166,24 @@ static int
|
|||
loopback_opendir(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
struct loopback_dirp *d = malloc(sizeof(struct loopback_dirp));
|
||||
if (d == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
d->dp = opendir(path);
|
||||
if (d->dp == NULL) {
|
||||
res = -errno;
|
||||
free(d);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
d->offset = 0;
|
||||
d->entry = NULL;
|
||||
|
||||
|
||||
fi->fh = (unsigned long)d;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -157,9 +198,9 @@ loopback_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
|||
off_t offset, struct fuse_file_info *fi)
|
||||
{
|
||||
struct loopback_dirp *d = get_dirp(fi);
|
||||
|
||||
|
||||
(void)path;
|
||||
|
||||
|
||||
if (offset == 0) {
|
||||
rewinddir(d->dp);
|
||||
d->entry = NULL;
|
||||
|
|
@ -170,37 +211,37 @@ loopback_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
|||
d->entry = NULL;
|
||||
d->offset = offset;
|
||||
}
|
||||
|
||||
|
||||
while (1) {
|
||||
struct stat st;
|
||||
off_t nextoff;
|
||||
|
||||
|
||||
if (!d->entry) {
|
||||
d->entry = readdir(d->dp);
|
||||
if (!d->entry) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
memset(&st, 0, sizeof(st));
|
||||
st.st_ino = d->entry->d_ino;
|
||||
st.st_mode = d->entry->d_type << 12;
|
||||
|
||||
|
||||
/*
|
||||
* Under macOS, telldir() may return 0 the first time it is called.
|
||||
* But for libfuse, an offset of zero means that offsets are not
|
||||
* supported, so we shift everything by one.
|
||||
*/
|
||||
nextoff = telldir(d->dp) + 1;
|
||||
|
||||
|
||||
if (filler(buf, d->entry->d_name, &st, nextoff)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
d->entry = NULL;
|
||||
d->offset = nextoff;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -208,12 +249,12 @@ static int
|
|||
loopback_releasedir(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
struct loopback_dirp *d = get_dirp(fi);
|
||||
|
||||
|
||||
(void)path;
|
||||
|
||||
|
||||
closedir(d->dp);
|
||||
free(d);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -221,17 +262,17 @@ static int
|
|||
loopback_mknod(const char *path, mode_t mode, dev_t rdev)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
if (S_ISFIFO(mode)) {
|
||||
res = mkfifo(path, mode);
|
||||
} else {
|
||||
res = mknod(path, mode, rdev);
|
||||
}
|
||||
|
||||
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -239,12 +280,12 @@ static int
|
|||
loopback_mkdir(const char *path, mode_t mode)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
res = mkdir(path, mode);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -252,12 +293,12 @@ static int
|
|||
loopback_unlink(const char *path)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
res = unlink(path);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -265,12 +306,12 @@ static int
|
|||
loopback_rmdir(const char *path)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
res = rmdir(path);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -278,12 +319,12 @@ static int
|
|||
loopback_symlink(const char *from, const char *to)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
res = symlink(from, to);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -291,12 +332,12 @@ static int
|
|||
loopback_rename(const char *from, const char *to)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
res = rename(from, to);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -321,12 +362,12 @@ static int
|
|||
loopback_link(const char *from, const char *to)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
res = link(from, to);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -337,36 +378,36 @@ loopback_fsetattr_x(const char *path, struct setattr_x *attr,
|
|||
int res;
|
||||
uid_t uid = -1;
|
||||
gid_t gid = -1;
|
||||
|
||||
|
||||
if (SETATTR_WANTS_MODE(attr)) {
|
||||
res = fchmod(fi->fh, attr->mode);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SETATTR_WANTS_UID(attr)) {
|
||||
uid = attr->uid;
|
||||
}
|
||||
|
||||
|
||||
if (SETATTR_WANTS_GID(attr)) {
|
||||
gid = attr->gid;
|
||||
}
|
||||
|
||||
|
||||
if ((uid != -1) || (gid != -1)) {
|
||||
res = fchown(fi->fh, uid, gid);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SETATTR_WANTS_SIZE(attr)) {
|
||||
res = ftruncate(fi->fh, attr->size);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SETATTR_WANTS_MODTIME(attr)) {
|
||||
struct timeval tv[2];
|
||||
if (!SETATTR_WANTS_ACCTIME(attr)) {
|
||||
|
|
@ -382,10 +423,10 @@ loopback_fsetattr_x(const char *path, struct setattr_x *attr,
|
|||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SETATTR_WANTS_CRTIME(attr)) {
|
||||
struct attrlist attributes;
|
||||
|
||||
|
||||
attributes.bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
attributes.reserved = 0;
|
||||
attributes.commonattr = ATTR_CMN_CRTIME;
|
||||
|
|
@ -393,18 +434,18 @@ loopback_fsetattr_x(const char *path, struct setattr_x *attr,
|
|||
attributes.fileattr = 0;
|
||||
attributes.forkattr = 0;
|
||||
attributes.volattr = 0;
|
||||
|
||||
|
||||
res = fsetattrlist(fi->fh, &attributes, &attr->crtime,
|
||||
sizeof(struct timespec), FSOPT_NOFOLLOW);
|
||||
|
||||
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SETATTR_WANTS_CHGTIME(attr)) {
|
||||
struct attrlist attributes;
|
||||
|
||||
|
||||
attributes.bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
attributes.reserved = 0;
|
||||
attributes.commonattr = ATTR_CMN_CHGTIME;
|
||||
|
|
@ -412,18 +453,18 @@ loopback_fsetattr_x(const char *path, struct setattr_x *attr,
|
|||
attributes.fileattr = 0;
|
||||
attributes.forkattr = 0;
|
||||
attributes.volattr = 0;
|
||||
|
||||
|
||||
res = fsetattrlist(fi->fh, &attributes, &attr->chgtime,
|
||||
sizeof(struct timespec), FSOPT_NOFOLLOW);
|
||||
|
||||
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SETATTR_WANTS_BKUPTIME(attr)) {
|
||||
struct attrlist attributes;
|
||||
|
||||
|
||||
attributes.bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
attributes.reserved = 0;
|
||||
attributes.commonattr = ATTR_CMN_BKUPTIME;
|
||||
|
|
@ -431,22 +472,22 @@ loopback_fsetattr_x(const char *path, struct setattr_x *attr,
|
|||
attributes.fileattr = 0;
|
||||
attributes.forkattr = 0;
|
||||
attributes.volattr = 0;
|
||||
|
||||
|
||||
res = fsetattrlist(fi->fh, &attributes, &attr->bkuptime,
|
||||
sizeof(struct timespec), FSOPT_NOFOLLOW);
|
||||
|
||||
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SETATTR_WANTS_FLAGS(attr)) {
|
||||
res = fchflags(fi->fh, attr->flags);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -456,36 +497,36 @@ loopback_setattr_x(const char *path, struct setattr_x *attr)
|
|||
int res;
|
||||
uid_t uid = -1;
|
||||
gid_t gid = -1;
|
||||
|
||||
|
||||
if (SETATTR_WANTS_MODE(attr)) {
|
||||
res = lchmod(path, attr->mode);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SETATTR_WANTS_UID(attr)) {
|
||||
uid = attr->uid;
|
||||
}
|
||||
|
||||
|
||||
if (SETATTR_WANTS_GID(attr)) {
|
||||
gid = attr->gid;
|
||||
}
|
||||
|
||||
|
||||
if ((uid != -1) || (gid != -1)) {
|
||||
res = lchown(path, uid, gid);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SETATTR_WANTS_SIZE(attr)) {
|
||||
res = truncate(path, attr->size);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SETATTR_WANTS_MODTIME(attr)) {
|
||||
struct timeval tv[2];
|
||||
if (!SETATTR_WANTS_ACCTIME(attr)) {
|
||||
|
|
@ -501,10 +542,10 @@ loopback_setattr_x(const char *path, struct setattr_x *attr)
|
|||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SETATTR_WANTS_CRTIME(attr)) {
|
||||
struct attrlist attributes;
|
||||
|
||||
|
||||
attributes.bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
attributes.reserved = 0;
|
||||
attributes.commonattr = ATTR_CMN_CRTIME;
|
||||
|
|
@ -512,18 +553,18 @@ loopback_setattr_x(const char *path, struct setattr_x *attr)
|
|||
attributes.fileattr = 0;
|
||||
attributes.forkattr = 0;
|
||||
attributes.volattr = 0;
|
||||
|
||||
|
||||
res = setattrlist(path, &attributes, &attr->crtime,
|
||||
sizeof(struct timespec), FSOPT_NOFOLLOW);
|
||||
|
||||
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SETATTR_WANTS_CHGTIME(attr)) {
|
||||
struct attrlist attributes;
|
||||
|
||||
|
||||
attributes.bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
attributes.reserved = 0;
|
||||
attributes.commonattr = ATTR_CMN_CHGTIME;
|
||||
|
|
@ -531,18 +572,18 @@ loopback_setattr_x(const char *path, struct setattr_x *attr)
|
|||
attributes.fileattr = 0;
|
||||
attributes.forkattr = 0;
|
||||
attributes.volattr = 0;
|
||||
|
||||
|
||||
res = setattrlist(path, &attributes, &attr->chgtime,
|
||||
sizeof(struct timespec), FSOPT_NOFOLLOW);
|
||||
|
||||
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SETATTR_WANTS_BKUPTIME(attr)) {
|
||||
struct attrlist attributes;
|
||||
|
||||
|
||||
attributes.bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
attributes.reserved = 0;
|
||||
attributes.commonattr = ATTR_CMN_BKUPTIME;
|
||||
|
|
@ -550,22 +591,22 @@ loopback_setattr_x(const char *path, struct setattr_x *attr)
|
|||
attributes.fileattr = 0;
|
||||
attributes.forkattr = 0;
|
||||
attributes.volattr = 0;
|
||||
|
||||
|
||||
res = setattrlist(path, &attributes, &attr->bkuptime,
|
||||
sizeof(struct timespec), FSOPT_NOFOLLOW);
|
||||
|
||||
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SETATTR_WANTS_FLAGS(attr)) {
|
||||
res = lchflags(path, attr->flags);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -575,7 +616,7 @@ loopback_getxtimes(const char *path, struct timespec *bkuptime,
|
|||
{
|
||||
int res = 0;
|
||||
struct attrlist attributes;
|
||||
|
||||
|
||||
attributes.bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
attributes.reserved = 0;
|
||||
attributes.commonattr = 0;
|
||||
|
|
@ -583,17 +624,14 @@ loopback_getxtimes(const char *path, struct timespec *bkuptime,
|
|||
attributes.fileattr = 0;
|
||||
attributes.forkattr = 0;
|
||||
attributes.volattr = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
struct xtimeattrbuf {
|
||||
uint32_t size;
|
||||
struct timespec xtime;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
|
||||
struct xtimeattrbuf buf;
|
||||
|
||||
|
||||
attributes.commonattr = ATTR_CMN_BKUPTIME;
|
||||
res = getattrlist(path, &attributes, &buf, sizeof(buf), FSOPT_NOFOLLOW);
|
||||
if (res == 0) {
|
||||
|
|
@ -601,7 +639,7 @@ loopback_getxtimes(const char *path, struct timespec *bkuptime,
|
|||
} else {
|
||||
(void)memset(bkuptime, 0, sizeof(struct timespec));
|
||||
}
|
||||
|
||||
|
||||
attributes.commonattr = ATTR_CMN_CRTIME;
|
||||
res = getattrlist(path, &attributes, &buf, sizeof(buf), FSOPT_NOFOLLOW);
|
||||
if (res == 0) {
|
||||
|
|
@ -609,7 +647,7 @@ loopback_getxtimes(const char *path, struct timespec *bkuptime,
|
|||
} else {
|
||||
(void)memset(crtime, 0, sizeof(struct timespec));
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -617,12 +655,12 @@ static int
|
|||
loopback_create(const char *path, mode_t mode, struct fuse_file_info *fi)
|
||||
{
|
||||
int fd;
|
||||
|
||||
|
||||
fd = open(path, fi->flags, mode);
|
||||
if (fd == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
fi->fh = fd;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -631,12 +669,12 @@ static int
|
|||
loopback_open(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
int fd;
|
||||
|
||||
|
||||
fd = open(path, fi->flags);
|
||||
if (fd == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
fi->fh = fd;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -646,13 +684,13 @@ loopback_read(const char *path, char *buf, size_t size, off_t offset,
|
|||
struct fuse_file_info *fi)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
(void)path;
|
||||
res = pread(fi->fh, buf, size, offset);
|
||||
if (res == -1) {
|
||||
res = -errno;
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -661,14 +699,14 @@ loopback_write(const char *path, const char *buf, size_t size,
|
|||
off_t offset, struct fuse_file_info *fi)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
(void)path;
|
||||
|
||||
|
||||
res = pwrite(fi->fh, buf, size, offset);
|
||||
if (res == -1) {
|
||||
res = -errno;
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -676,14 +714,14 @@ static int
|
|||
loopback_flush(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
(void)path;
|
||||
|
||||
|
||||
res = close(dup(fi->fh));
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -691,9 +729,9 @@ static int
|
|||
loopback_release(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
(void)path;
|
||||
|
||||
|
||||
close(fi->fh);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -701,16 +739,16 @@ static int
|
|||
loopback_fsync(const char *path, int isdatasync, struct fuse_file_info *fi)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
(void)path;
|
||||
|
||||
|
||||
(void)isdatasync;
|
||||
|
||||
|
||||
res = fsync(fi->fh);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -719,28 +757,28 @@ loopback_setxattr(const char *path, const char *name, const char *value,
|
|||
size_t size, int flags, uint32_t position)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
if (!strncmp(name, XATTR_APPLE_PREFIX, sizeof(XATTR_APPLE_PREFIX) - 1)) {
|
||||
flags &= ~(XATTR_NOSECURITY);
|
||||
}
|
||||
|
||||
|
||||
if (!strcmp(name, A_KAUTH_FILESEC_XATTR)) {
|
||||
|
||||
|
||||
char new_name[MAXPATHLEN];
|
||||
|
||||
|
||||
memcpy(new_name, A_KAUTH_FILESEC_XATTR, sizeof(A_KAUTH_FILESEC_XATTR));
|
||||
memcpy(new_name, G_PREFIX, sizeof(G_PREFIX) - 1);
|
||||
|
||||
|
||||
res = setxattr(path, new_name, value, size, position, XATTR_NOFOLLOW);
|
||||
|
||||
|
||||
} else {
|
||||
res = setxattr(path, name, value, size, position, XATTR_NOFOLLOW);
|
||||
}
|
||||
|
||||
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -749,24 +787,24 @@ loopback_getxattr(const char *path, const char *name, char *value, size_t size,
|
|||
uint32_t position)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
if (strcmp(name, A_KAUTH_FILESEC_XATTR) == 0) {
|
||||
|
||||
|
||||
char new_name[MAXPATHLEN];
|
||||
|
||||
|
||||
memcpy(new_name, A_KAUTH_FILESEC_XATTR, sizeof(A_KAUTH_FILESEC_XATTR));
|
||||
memcpy(new_name, G_PREFIX, sizeof(G_PREFIX) - 1);
|
||||
|
||||
|
||||
res = getxattr(path, new_name, value, size, position, XATTR_NOFOLLOW);
|
||||
|
||||
|
||||
} else {
|
||||
res = getxattr(path, name, value, size, position, XATTR_NOFOLLOW);
|
||||
}
|
||||
|
||||
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -798,11 +836,11 @@ loopback_listxattr(const char *path, char *list, size_t size)
|
|||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -810,24 +848,24 @@ static int
|
|||
loopback_removexattr(const char *path, const char *name)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
if (strcmp(name, A_KAUTH_FILESEC_XATTR) == 0) {
|
||||
|
||||
|
||||
char new_name[MAXPATHLEN];
|
||||
|
||||
|
||||
memcpy(new_name, A_KAUTH_FILESEC_XATTR, sizeof(A_KAUTH_FILESEC_XATTR));
|
||||
memcpy(new_name, G_PREFIX, sizeof(G_PREFIX) - 1);
|
||||
|
||||
|
||||
res = removexattr(path, new_name, XATTR_NOFOLLOW);
|
||||
|
||||
|
||||
} else {
|
||||
res = removexattr(path, name, XATTR_NOFOLLOW);
|
||||
}
|
||||
|
||||
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -836,11 +874,11 @@ loopback_fallocate(const char *path, int mode, off_t offset, off_t length,
|
|||
struct fuse_file_info *fi)
|
||||
{
|
||||
fstore_t fstore;
|
||||
|
||||
|
||||
if (!(mode & PREALLOCATE)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
|
||||
fstore.fst_flags = 0;
|
||||
if (mode & ALLOCATECONTIG) {
|
||||
fstore.fst_flags |= F_ALLOCATECONTIG;
|
||||
|
|
@ -848,16 +886,16 @@ loopback_fallocate(const char *path, int mode, off_t offset, off_t length,
|
|||
if (mode & ALLOCATEALL) {
|
||||
fstore.fst_flags |= F_ALLOCATEALL;
|
||||
}
|
||||
|
||||
|
||||
if (mode & ALLOCATEFROMPEOF) {
|
||||
fstore.fst_posmode = F_PEOFPOSMODE;
|
||||
} else if (mode & ALLOCATEFROMVOL) {
|
||||
fstore.fst_posmode = F_VOLPOSMODE;
|
||||
}
|
||||
|
||||
|
||||
fstore.fst_offset = offset;
|
||||
fstore.fst_length = length;
|
||||
|
||||
|
||||
if (fcntl(fi->fh, F_PREALLOCATE, &fstore) == -1) {
|
||||
return -errno;
|
||||
} else {
|
||||
|
|
@ -875,12 +913,12 @@ static int
|
|||
loopback_statfs_x(const char *path, struct statfs *stbuf)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
res = statfs(path, stbuf);
|
||||
if (res == -1) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
stbuf->f_blocks = stbuf->f_blocks * stbuf->f_bsize / loopback.blocksize;
|
||||
stbuf->f_bavail = stbuf->f_bavail * stbuf->f_bsize / loopback.blocksize;
|
||||
stbuf->f_bfree = stbuf->f_bfree * stbuf->f_bsize / loopback.blocksize;
|
||||
|
|
@ -911,6 +949,10 @@ loopback_init(struct fuse_conn_info *conn)
|
|||
{
|
||||
conn->want |= FUSE_CAP_VOL_RENAME | FUSE_CAP_XTIMES | FUSE_CAP_NODE_RWLOCK;
|
||||
|
||||
#if HAVE_ACCESS
|
||||
conn->want |= FUSE_CAP_ACCESS_EXTENDED;
|
||||
#endif
|
||||
|
||||
#ifdef FUSE_ENABLE_CASE_INSENSITIVE
|
||||
if (loopback.case_insensitive) {
|
||||
conn->want |= FUSE_CAP_CASE_INSENSITIVE;
|
||||
|
|
@ -931,7 +973,9 @@ static struct fuse_operations loopback_oper = {
|
|||
.destroy = loopback_destroy,
|
||||
.getattr = loopback_getattr,
|
||||
.fgetattr = loopback_fgetattr,
|
||||
/* .access = loopback_access, */
|
||||
#if HAVE_ACCESS
|
||||
.access = loopback_access,
|
||||
#endif
|
||||
.readlink = loopback_readlink,
|
||||
.opendir = loopback_opendir,
|
||||
.readdir = loopback_readdir,
|
||||
|
|
@ -966,7 +1010,7 @@ static struct fuse_operations loopback_oper = {
|
|||
#if HAVE_RENAMEX
|
||||
.renamex = loopback_renamex,
|
||||
#endif
|
||||
|
||||
|
||||
.flag_nullpath_ok = 1,
|
||||
.flag_nopath = 1,
|
||||
};
|
||||
|
|
@ -982,16 +1026,16 @@ main(int argc, char *argv[])
|
|||
{
|
||||
int res = 0;
|
||||
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
|
||||
|
||||
|
||||
loopback.blocksize = 4096;
|
||||
loopback.case_insensitive = 0;
|
||||
if (fuse_opt_parse(&args, &loopback, loopback_opts, NULL) == -1) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
umask(0);
|
||||
res = fuse_main(args.argc, args.argv, &loopback_oper, NULL);
|
||||
|
||||
|
||||
fuse_opt_free_args(&args);
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue