mirror of
https://git.code.sf.net/p/ntfs-3g/ntfs-3g.git
synced 2024-11-23 10:04:00 +08:00
Add support for 'position' argument in macOS xattr functions.
The 'position' argument is only used for the legacy resource fork and is disallowed for other extended attributes. The name check is placed first in the functions as this is how macOS behaves (EINVAL is returned if the attribute is not the resource fork attribute and the position is non-0 even when the attribute does not exist).
This commit is contained in:
parent
4ecc13c0ac
commit
1511a5ca51
@ -3373,9 +3373,18 @@ out :
|
||||
free(list);
|
||||
}
|
||||
|
||||
#if defined(__APPLE__) || defined(__DARWIN__)
|
||||
static void ntfs_fuse_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
||||
size_t size, uint32_t position)
|
||||
#else
|
||||
static void ntfs_fuse_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
||||
size_t size)
|
||||
#endif
|
||||
{
|
||||
#if !(defined(__APPLE__) || defined(__DARWIN__))
|
||||
static const unsigned int position = 0U;
|
||||
#endif
|
||||
|
||||
ntfs_inode *ni;
|
||||
ntfs_inode *dir_ni;
|
||||
ntfs_attr *na = NULL;
|
||||
@ -3388,6 +3397,16 @@ static void ntfs_fuse_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
||||
int namespace;
|
||||
struct SECURITY_CONTEXT security;
|
||||
|
||||
#if defined(__APPLE__) || defined(__DARWIN__)
|
||||
/* If the attribute is not a resource fork attribute and the position
|
||||
* parameter is non-zero, we return with EINVAL as requesting position
|
||||
* is not permitted for non-resource fork attributes. */
|
||||
if (position && strcmp(name, XATTR_RESOURCEFORK_NAME)) {
|
||||
fuse_reply_err(req, EINVAL);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
attr = ntfs_xattr_system_type(name,ctx->vol);
|
||||
if (attr != XATTR_UNMAPPED) {
|
||||
/*
|
||||
@ -3502,11 +3521,13 @@ static void ntfs_fuse_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
||||
&& (na->data_flags & ATTR_IS_ENCRYPTED)
|
||||
&& NAttrNonResident(na))
|
||||
rsize = ((na->data_size + 511) & ~511) + 2;
|
||||
rsize -= position;
|
||||
if (size) {
|
||||
if (size >= (size_t)rsize) {
|
||||
value = (char*)ntfs_malloc(rsize);
|
||||
if (value)
|
||||
res = ntfs_attr_pread(na, 0, rsize, value);
|
||||
res = ntfs_attr_pread(na, position, rsize,
|
||||
value);
|
||||
if (!value || (res != rsize))
|
||||
res = -errno;
|
||||
} else
|
||||
@ -3531,9 +3552,21 @@ out :
|
||||
free(value);
|
||||
}
|
||||
|
||||
#if defined(__APPLE__) || defined(__DARWIN__)
|
||||
static void ntfs_fuse_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
||||
const char *value, size_t size, int flags,
|
||||
uint32_t position)
|
||||
#else
|
||||
static void ntfs_fuse_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
||||
const char *value, size_t size, int flags)
|
||||
#endif
|
||||
{
|
||||
#if !(defined(__APPLE__) || defined(__DARWIN__))
|
||||
static const unsigned int position = 0U;
|
||||
#else
|
||||
BOOL is_resource_fork;
|
||||
#endif
|
||||
|
||||
ntfs_inode *ni;
|
||||
ntfs_inode *dir_ni;
|
||||
ntfs_attr *na = NULL;
|
||||
@ -3545,6 +3578,17 @@ static void ntfs_fuse_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
||||
int namespace;
|
||||
struct SECURITY_CONTEXT security;
|
||||
|
||||
#if defined(__APPLE__) || defined(__DARWIN__)
|
||||
/* If the attribute is not a resource fork attribute and the position
|
||||
* parameter is non-zero, we return with EINVAL as requesting position
|
||||
* is not permitted for non-resource fork attributes. */
|
||||
is_resource_fork = strcmp(name, XATTR_RESOURCEFORK_NAME) ? FALSE : TRUE;
|
||||
if (position && !is_resource_fork) {
|
||||
fuse_reply_err(req, EINVAL);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
attr = ntfs_xattr_system_type(name,ctx->vol);
|
||||
if (attr != XATTR_UNMAPPED) {
|
||||
/*
|
||||
@ -3720,6 +3764,11 @@ static void ntfs_fuse_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
||||
res = -errno;
|
||||
goto exit;
|
||||
}
|
||||
#if defined(__APPLE__) || defined(__DARWIN__)
|
||||
} else if (is_resource_fork) {
|
||||
/* In macOS, the resource fork is a special case. It doesn't
|
||||
* ever shrink (it would have to be removed and re-added). */
|
||||
#endif
|
||||
} else {
|
||||
/* currently compressed streams can only be wiped out */
|
||||
if (ntfs_attr_truncate(na, (s64)0 /* size */)) {
|
||||
@ -3731,8 +3780,8 @@ static void ntfs_fuse_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
||||
res = 0;
|
||||
if (size) {
|
||||
do {
|
||||
part = ntfs_attr_pwrite(na, total, size - total,
|
||||
&value[total]);
|
||||
part = ntfs_attr_pwrite(na, position + total,
|
||||
size - total, &value[total]);
|
||||
if (part > 0)
|
||||
total += part;
|
||||
} while ((part > 0) && (total < size));
|
||||
|
@ -3151,9 +3151,18 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(__APPLE__) || defined(__DARWIN__)
|
||||
static int ntfs_fuse_getxattr(const char *path, const char *name,
|
||||
char *value, size_t size, uint32_t position)
|
||||
#else
|
||||
static int ntfs_fuse_getxattr(const char *path, const char *name,
|
||||
char *value, size_t size)
|
||||
#endif
|
||||
{
|
||||
#if !(defined(__APPLE__) || defined(__DARWIN__))
|
||||
static const unsigned int position = 0U;
|
||||
#endif
|
||||
|
||||
ntfs_inode *ni;
|
||||
ntfs_inode *dir_ni;
|
||||
ntfs_attr *na = NULL;
|
||||
@ -3164,6 +3173,15 @@ static int ntfs_fuse_getxattr(const char *path, const char *name,
|
||||
int namespace;
|
||||
struct SECURITY_CONTEXT security;
|
||||
|
||||
#if defined(__APPLE__) || defined(__DARWIN__)
|
||||
/* If the attribute is not a resource fork attribute and the position
|
||||
* parameter is non-zero, we return with EINVAL as requesting position
|
||||
* is not permitted for non-resource fork attributes. */
|
||||
if (position && strcmp(name, XATTR_RESOURCEFORK_NAME)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
attr = ntfs_xattr_system_type(name,ctx->vol);
|
||||
if (attr != XATTR_UNMAPPED) {
|
||||
#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
|
||||
@ -3269,9 +3287,10 @@ static int ntfs_fuse_getxattr(const char *path, const char *name,
|
||||
&& (na->data_flags & ATTR_IS_ENCRYPTED)
|
||||
&& NAttrNonResident(na))
|
||||
rsize = ((na->data_size + 511) & ~511) + 2;
|
||||
rsize -= position;
|
||||
if (size) {
|
||||
if (size >= (size_t)rsize) {
|
||||
res = ntfs_attr_pread(na, 0, rsize, value);
|
||||
res = ntfs_attr_pread(na, position, rsize, value);
|
||||
if (res != rsize)
|
||||
res = -errno;
|
||||
} else
|
||||
@ -3287,9 +3306,21 @@ exit:
|
||||
return res;
|
||||
}
|
||||
|
||||
#if defined(__APPLE__) || defined(__DARWIN__)
|
||||
static int ntfs_fuse_setxattr(const char *path, const char *name,
|
||||
const char *value, size_t size, int flags,
|
||||
uint32_t position)
|
||||
#else
|
||||
static int ntfs_fuse_setxattr(const char *path, const char *name,
|
||||
const char *value, size_t size, int flags)
|
||||
#endif
|
||||
{
|
||||
#if !(defined(__APPLE__) || defined(__DARWIN__))
|
||||
static const unsigned int position = 0U;
|
||||
#else
|
||||
BOOL is_resource_fork;
|
||||
#endif
|
||||
|
||||
ntfs_inode *ni;
|
||||
ntfs_inode *dir_ni;
|
||||
ntfs_attr *na = NULL;
|
||||
@ -3301,6 +3332,16 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
|
||||
int namespace;
|
||||
struct SECURITY_CONTEXT security;
|
||||
|
||||
#if defined(__APPLE__) || defined(__DARWIN__)
|
||||
/* If the attribute is not a resource fork attribute and the position
|
||||
* parameter is non-zero, we return with EINVAL as requesting position
|
||||
* is not permitted for non-resource fork attributes. */
|
||||
is_resource_fork = strcmp(name, XATTR_RESOURCEFORK_NAME) ? FALSE : TRUE;
|
||||
if (position && !is_resource_fork) {
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
attr = ntfs_xattr_system_type(name,ctx->vol);
|
||||
if (attr != XATTR_UNMAPPED) {
|
||||
#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
|
||||
@ -3466,6 +3507,11 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
|
||||
res = -errno;
|
||||
goto exit;
|
||||
}
|
||||
#if defined(__APPLE__) || defined(__DARWIN__)
|
||||
} else if (is_resource_fork) {
|
||||
/* In macOS, the resource fork is a special case. It doesn't
|
||||
* ever shrink (it would have to be removed and re-added). */
|
||||
#endif
|
||||
} else {
|
||||
/* currently compressed streams can only be wiped out */
|
||||
if (ntfs_attr_truncate(na, (s64)0 /* size */)) {
|
||||
@ -3477,8 +3523,8 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
|
||||
res = 0;
|
||||
if (size) {
|
||||
do {
|
||||
part = ntfs_attr_pwrite(na, total, size - total,
|
||||
&value[total]);
|
||||
part = ntfs_attr_pwrite(na, position + total,
|
||||
size - total, &value[total]);
|
||||
if (part > 0)
|
||||
total += part;
|
||||
} while ((part > 0) && (total < size));
|
||||
|
Loading…
Reference in New Issue
Block a user