Fixed creating empty encrypted extended attributes
parent
5533eb565f
commit
09df7eade5
|
@ -304,6 +304,7 @@ extern int ntfs_attr_can_be_resident(const ntfs_volume *vol,
|
|||
const ATTR_TYPES type);
|
||||
int ntfs_attr_make_non_resident(ntfs_attr *na,
|
||||
ntfs_attr_search_ctx *ctx);
|
||||
int ntfs_attr_force_non_resident(ntfs_attr *na);
|
||||
extern int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size);
|
||||
|
||||
extern int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
|
||||
|
|
|
@ -4681,6 +4681,8 @@ static int ntfs_resident_attr_resize(ntfs_attr *na, const s64 newsize);
|
|||
* @newsize: new size (in bytes) to which to resize the attribute
|
||||
*
|
||||
* Change the size of a resident, open ntfs attribute @na to @newsize bytes.
|
||||
* Can also be used to force an attribute non-resident. In this case, the
|
||||
* size cannot be changed.
|
||||
*
|
||||
* On success return 0
|
||||
* On error return values are:
|
||||
|
@ -4691,7 +4693,8 @@ static int ntfs_resident_attr_resize(ntfs_attr *na, const s64 newsize);
|
|||
* ERANGE - @newsize is not valid for the attribute type of @na.
|
||||
* ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST.
|
||||
*/
|
||||
static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize)
|
||||
static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize,
|
||||
BOOL force_non_resident)
|
||||
{
|
||||
ntfs_attr_search_ctx *ctx;
|
||||
ntfs_volume *vol;
|
||||
|
@ -4729,7 +4732,7 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize)
|
|||
* attribute non-resident if the attribute type supports it. If it is
|
||||
* smaller we can go ahead and attempt the resize.
|
||||
*/
|
||||
if (newsize < vol->mft_record_size) {
|
||||
if ((newsize < vol->mft_record_size) && !force_non_resident) {
|
||||
/* Perform the resize of the attribute record. */
|
||||
if (!(ret = ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr,
|
||||
newsize))) {
|
||||
|
@ -4769,6 +4772,21 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize)
|
|||
if (!ntfs_attr_make_non_resident(na, ctx)) {
|
||||
ntfs_inode_mark_dirty(ctx->ntfs_ino);
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
/*
|
||||
* do not truncate when forcing non-resident, this
|
||||
* could cause the attribute to be made resident again,
|
||||
* so size changes are not allowed.
|
||||
*/
|
||||
if (force_non_resident) {
|
||||
ret = 0;
|
||||
if (newsize != na->data_size) {
|
||||
ntfs_log_error("Cannot change size when"
|
||||
" forcing non-resident\n");
|
||||
errno = EIO;
|
||||
ret = STATUS_ERROR;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
/* Resize non-resident attribute */
|
||||
return ntfs_attr_truncate(na, newsize);
|
||||
} else if (errno != ENOSPC && errno != EPERM) {
|
||||
|
@ -4817,7 +4835,7 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize)
|
|||
ntfs_inode_mark_dirty(tna->ni);
|
||||
ntfs_attr_close(tna);
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
return ntfs_resident_attr_resize(na, newsize);
|
||||
return ntfs_resident_attr_resize_i(na, newsize, force_non_resident);
|
||||
}
|
||||
/* Check whether error occurred. */
|
||||
if (errno != ENOENT) {
|
||||
|
@ -4837,7 +4855,7 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize)
|
|||
ntfs_log_perror("Could not free space in MFT record");
|
||||
return -1;
|
||||
}
|
||||
return ntfs_resident_attr_resize(na, newsize);
|
||||
return ntfs_resident_attr_resize_i(na, newsize, force_non_resident);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4876,7 +4894,7 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize)
|
|||
ntfs_attr_put_search_ctx(ctx);
|
||||
if (ntfs_inode_add_attrlist(ni))
|
||||
return -1;
|
||||
return ntfs_resident_attr_resize(na, newsize);
|
||||
return ntfs_resident_attr_resize_i(na, newsize, force_non_resident);
|
||||
}
|
||||
/* Allocate new mft record. */
|
||||
ni = ntfs_mft_record_alloc(vol, ni);
|
||||
|
@ -4897,7 +4915,7 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize)
|
|||
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
/* Try to perform resize once again. */
|
||||
return ntfs_resident_attr_resize(na, newsize);
|
||||
return ntfs_resident_attr_resize_i(na, newsize, force_non_resident);
|
||||
|
||||
resize_done:
|
||||
/*
|
||||
|
@ -4918,11 +4936,39 @@ static int ntfs_resident_attr_resize(ntfs_attr *na, const s64 newsize)
|
|||
int ret;
|
||||
|
||||
ntfs_log_enter("Entering\n");
|
||||
ret = ntfs_resident_attr_resize_i(na, newsize);
|
||||
ret = ntfs_resident_attr_resize_i(na, newsize, FALSE);
|
||||
ntfs_log_leave("\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Force an attribute to be made non-resident without
|
||||
* changing its size.
|
||||
*
|
||||
* This is particularly needed when the attribute has no data,
|
||||
* as the non-resident variant requires more space in the MFT
|
||||
* record, and may imply expelling some other attribute.
|
||||
*
|
||||
* As a consequence the existing ntfs_attr_search_ctx's have to
|
||||
* be closed or reinitialized.
|
||||
*
|
||||
* returns 0 if successful,
|
||||
* < 0 if failed, with errno telling why
|
||||
*/
|
||||
|
||||
int ntfs_attr_force_non_resident(ntfs_attr *na)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ntfs_resident_attr_resize_i(na, na->data_size, TRUE);
|
||||
if (!res && !NAttrNonResident(na)) {
|
||||
res = -1;
|
||||
errno = EIO;
|
||||
ntfs_log_error("Failed to force non-resident\n");
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_attr_make_resident - convert a non-resident to a resident attribute
|
||||
* @na: open ntfs attribute to make resident
|
||||
|
|
221
libntfs-3g/efs.c
221
libntfs-3g/efs.c
|
@ -4,7 +4,7 @@
|
|||
* This module is part of ntfs-3g library
|
||||
*
|
||||
* Copyright (c) 2009 Martin Bene
|
||||
* Copyright (c) 2009 Jean-Pierre Andre
|
||||
* Copyright (c) 2009-2010 Jean-Pierre Andre
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -120,6 +120,93 @@ int ntfs_get_efs_info(ntfs_inode *ni, char *value, size_t size)
|
|||
return (attr_size ? (int)attr_size : -errno);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix all encrypted AT_DATA attributes of an inode
|
||||
*
|
||||
* The fix may require making an attribute non resident, which
|
||||
* requires more space in the MFT record, and may cause some
|
||||
* attribute to be expelled and the full record to be reorganized.
|
||||
* When this happens, the search for data attributes has to be
|
||||
* reinitialized.
|
||||
*
|
||||
* Returns zero if successful.
|
||||
* -1 if there is a problem.
|
||||
*/
|
||||
|
||||
static int fixup_loop(ntfs_inode *ni)
|
||||
{
|
||||
ntfs_attr_search_ctx *ctx;
|
||||
ntfs_attr *na;
|
||||
ATTR_RECORD *a;
|
||||
BOOL restart;
|
||||
BOOL first;
|
||||
int cnt;
|
||||
int maxcnt;
|
||||
int res = 0;
|
||||
|
||||
maxcnt = 0;
|
||||
do {
|
||||
restart = FALSE;
|
||||
ctx = ntfs_attr_get_search_ctx(ni, NULL);
|
||||
if (!ctx) {
|
||||
ntfs_log_error("Failed to get ctx for efs\n");
|
||||
res = -1;
|
||||
}
|
||||
cnt = 0;
|
||||
while (!restart && !res
|
||||
&& !ntfs_attr_lookup(AT_DATA, NULL, 0,
|
||||
CASE_SENSITIVE, 0, NULL, 0, ctx)) {
|
||||
cnt++;
|
||||
a = ctx->attr;
|
||||
na = ntfs_attr_open(ctx->ntfs_ino, AT_DATA,
|
||||
(ntfschar*)((u8*)a + le16_to_cpu(a->name_offset)),
|
||||
a->name_length);
|
||||
if (!na) {
|
||||
ntfs_log_error("can't open DATA Attribute\n");
|
||||
res = -1;
|
||||
}
|
||||
if (na && !(ctx->attr->flags & ATTR_IS_ENCRYPTED)) {
|
||||
if (!NAttrNonResident(na)
|
||||
&& ntfs_attr_make_non_resident(na, ctx)) {
|
||||
/*
|
||||
* ntfs_attr_make_non_resident fails if there
|
||||
* is not enough space in the MFT record.
|
||||
* When this happens, force making non-resident
|
||||
* so that some other attribute is expelled.
|
||||
*/
|
||||
if (ntfs_attr_force_non_resident(na)) {
|
||||
res = -1;
|
||||
} else {
|
||||
/* make sure there is some progress */
|
||||
if (cnt <= maxcnt) {
|
||||
errno = EIO;
|
||||
ntfs_log_error("Multiple failure"
|
||||
" making non resident\n");
|
||||
res = -1;
|
||||
} else {
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
ctx = (ntfs_attr_search_ctx*)NULL;
|
||||
restart = TRUE;
|
||||
maxcnt = cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!restart && !res
|
||||
&& ntfs_efs_fixup_attribute(ctx, na)) {
|
||||
ntfs_log_error("Error in efs fixup of AT_DATA Attribute\n");
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
if (na)
|
||||
ntfs_attr_close(na);
|
||||
}
|
||||
first = FALSE;
|
||||
} while (restart && !res);
|
||||
if (ctx)
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
return (res);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the efs data from an extended attribute
|
||||
* Warning : the new data is not checked
|
||||
|
@ -134,7 +221,6 @@ int ntfs_set_efs_info(ntfs_inode *ni, const char *value, size_t size,
|
|||
int written;
|
||||
ntfs_attr *na;
|
||||
const EFS_ATTR_HEADER *info_header;
|
||||
ntfs_attr_search_ctx *ctx;
|
||||
|
||||
res = 0;
|
||||
if (ni && value && size) {
|
||||
|
@ -210,20 +296,8 @@ int ntfs_set_efs_info(ntfs_inode *ni, const char *value, size_t size,
|
|||
/* iterate over AT_DATA attributes */
|
||||
/* set encrypted flag, truncate attribute to match padding bytes */
|
||||
|
||||
ctx = ntfs_attr_get_search_ctx(ni, NULL);
|
||||
if (!ctx) {
|
||||
ntfs_log_error("Failed to get ctx for efs\n");
|
||||
return (-1);
|
||||
}
|
||||
while (!ntfs_attr_lookup(AT_DATA, NULL, 0,
|
||||
CASE_SENSITIVE, 0, NULL, 0, ctx)) {
|
||||
if (ntfs_efs_fixup_attribute(ctx, NULL)) {
|
||||
ntfs_log_error("Error in efs fixup of AT_DATA Attribute\n");
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
if (fixup_loop(ni))
|
||||
return -1;
|
||||
}
|
||||
ni->flags |= FILE_ATTR_ENCRYPTED;
|
||||
NInoSetDirty(ni);
|
||||
|
@ -250,15 +324,14 @@ int ntfs_set_efs_info(ntfs_inode *ni, const char *value, size_t size,
|
|||
int ntfs_efs_fixup_attribute(ntfs_attr_search_ctx *ctx, ntfs_attr *na)
|
||||
{
|
||||
u64 newsize;
|
||||
u64 oldsize;
|
||||
le16 appended_bytes;
|
||||
u16 padding_length;
|
||||
ATTR_RECORD *a;
|
||||
ntfs_inode *ni;
|
||||
BOOL close_na = FALSE;
|
||||
BOOL close_ctx = FALSE;
|
||||
|
||||
if (!ctx && !na) {
|
||||
ntfs_log_error("neither ctx nor na specified for efs_fixup_attribute\n");
|
||||
if (!na) {
|
||||
ntfs_log_error("no na specified for efs_fixup_attribute\n");
|
||||
goto err_out;
|
||||
}
|
||||
if (!ctx) {
|
||||
|
@ -267,55 +340,79 @@ int ntfs_efs_fixup_attribute(ntfs_attr_search_ctx *ctx, ntfs_attr *na)
|
|||
ntfs_log_error("Failed to get ctx for efs\n");
|
||||
goto err_out;
|
||||
}
|
||||
close_ctx=TRUE;
|
||||
close_ctx = TRUE;
|
||||
if (ntfs_attr_lookup(AT_DATA, na->name, na->name_len,
|
||||
CASE_SENSITIVE, 0, NULL, 0, ctx)) {
|
||||
ntfs_log_error("attr lookup for AT_DATA attribute failed in efs fixup\n");
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
a = ctx->attr;
|
||||
if (!na) {
|
||||
na = ntfs_attr_open(ctx->ntfs_ino, AT_DATA,
|
||||
(ntfschar*)((u8*)a + le16_to_cpu(a->name_offset)),
|
||||
a->name_length);
|
||||
if (!na) {
|
||||
ntfs_log_error("can't open DATA Attribute\n");
|
||||
return (-1);
|
||||
} else {
|
||||
if (!NAttrNonResident(na)) {
|
||||
ntfs_log_error("Cannot make non resident"
|
||||
" when a context has been allocated\n");
|
||||
goto err_out;
|
||||
}
|
||||
close_na = TRUE;
|
||||
}
|
||||
/* make sure size is valid for a raw encrypted stream */
|
||||
if ((na->data_size & 511) != 2) {
|
||||
ntfs_log_error("Bad raw encrypted stream\n");
|
||||
goto err_out;
|
||||
}
|
||||
/* read padding length from last two bytes of attribute */
|
||||
if (ntfs_attr_pread(na, na->data_size-2, 2, &appended_bytes) != 2) {
|
||||
ntfs_log_error("Error reading padding length\n");
|
||||
goto err_out;
|
||||
}
|
||||
padding_length = le16_to_cpu(appended_bytes);
|
||||
if (padding_length > 511 || padding_length > na->data_size-2) {
|
||||
errno = EINVAL;
|
||||
ntfs_log_error("invalid padding length %d for data_size %lld\n",
|
||||
padding_length, (long long)na->data_size);
|
||||
goto err_out;
|
||||
}
|
||||
newsize = na->data_size - padding_length - 2;
|
||||
/* truncate attribute to possibly free clusters allocated
|
||||
for the last two bytes */
|
||||
if (ntfs_attr_truncate(na, na->data_size-2)) {
|
||||
ntfs_log_error("Error truncating attribute\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* Encrypted AT_DATA Attributes MUST be non-resident */
|
||||
/* no extra bytes are added to void attributes */
|
||||
oldsize = na->data_size;
|
||||
if (oldsize) {
|
||||
/* make sure size is valid for a raw encrypted stream */
|
||||
if ((oldsize & 511) != 2) {
|
||||
ntfs_log_error("Bad raw encrypted stream\n");
|
||||
goto err_out;
|
||||
}
|
||||
/* read padding length from last two bytes of attribute */
|
||||
if (ntfs_attr_pread(na, oldsize - 2, 2, &appended_bytes) != 2) {
|
||||
ntfs_log_error("Error reading padding length\n");
|
||||
goto err_out;
|
||||
}
|
||||
padding_length = le16_to_cpu(appended_bytes);
|
||||
if (padding_length > 511 || padding_length > na->data_size-2) {
|
||||
errno = EINVAL;
|
||||
ntfs_log_error("invalid padding length %d for data_size %lld\n",
|
||||
padding_length, (long long)oldsize);
|
||||
goto err_out;
|
||||
}
|
||||
newsize = oldsize - padding_length - 2;
|
||||
/*
|
||||
* truncate attribute to possibly free clusters allocated
|
||||
* for the last two bytes, but do not truncate to new size
|
||||
* to avoid losing useful data
|
||||
*/
|
||||
if (ntfs_attr_truncate(na, oldsize - 2)) {
|
||||
ntfs_log_error("Error truncating attribute\n");
|
||||
goto err_out;
|
||||
}
|
||||
} else
|
||||
newsize = 0;
|
||||
|
||||
/*
|
||||
* Encrypted AT_DATA Attributes MUST be non-resident
|
||||
* This has to be done after the attribute is resized, as
|
||||
* resizing down to zero may cause the attribute to be made
|
||||
* resident.
|
||||
*/
|
||||
if (!NAttrNonResident(na)
|
||||
&& ntfs_attr_make_non_resident(na, ctx)) {
|
||||
ntfs_log_error("Error making DATA attribute non-resident\n");
|
||||
goto err_out;
|
||||
&& ntfs_attr_make_non_resident(na, ctx)) {
|
||||
if (!close_ctx
|
||||
|| ntfs_attr_force_non_resident(na)) {
|
||||
ntfs_log_error("Error making DATA attribute non-resident\n");
|
||||
goto err_out;
|
||||
} else {
|
||||
/*
|
||||
* must reinitialize context after forcing
|
||||
* non-resident. We need a context for updating
|
||||
* the state, and at this point, we are sure
|
||||
* the context is not used elsewhere.
|
||||
*/
|
||||
ntfs_attr_reinit_search_ctx(ctx);
|
||||
if (ntfs_attr_lookup(AT_DATA, na->name, na->name_len,
|
||||
CASE_SENSITIVE, 0, NULL, 0, ctx)) {
|
||||
ntfs_log_error("attr lookup for AT_DATA attribute failed in efs fixup\n");
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
}
|
||||
ni = na->ni;
|
||||
if (!na->name_len) {
|
||||
|
@ -324,8 +421,6 @@ int ntfs_efs_fixup_attribute(ntfs_attr_search_ctx *ctx, ntfs_attr *na)
|
|||
}
|
||||
NInoSetDirty(ni);
|
||||
NInoFileNameSetDirty(ni);
|
||||
if (close_na)
|
||||
ntfs_attr_close(na);
|
||||
|
||||
ctx->attr->data_size = cpu_to_le64(newsize);
|
||||
if (le64_to_cpu(ctx->attr->initialized_size) > newsize)
|
||||
|
@ -336,8 +431,6 @@ int ntfs_efs_fixup_attribute(ntfs_attr_search_ctx *ctx, ntfs_attr *na)
|
|||
|
||||
return (0);
|
||||
err_out:
|
||||
if (close_na && na)
|
||||
ntfs_attr_close(na);
|
||||
if (close_ctx && ctx)
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
return (-1);
|
||||
|
|
|
@ -695,7 +695,9 @@ static int ntfs_fuse_getstat(struct SECURITY_CONTEXT *scx,
|
|||
* encrypted files to include padding required for decryption
|
||||
* also include 2 bytes for padding info
|
||||
*/
|
||||
if (ctx->efs_raw && ni->flags & FILE_ATTR_ENCRYPTED)
|
||||
if (ctx->efs_raw
|
||||
&& (ni->flags & FILE_ATTR_ENCRYPTED)
|
||||
&& ni->data_size)
|
||||
stbuf->st_size = ((ni->data_size + 511) & ~511) + 2;
|
||||
#endif /* HAVE_SETXATTR */
|
||||
/*
|
||||
|
@ -1325,8 +1327,10 @@ static void ntfs_fuse_read(fuse_req_t req, fuse_ino_t ino, size_t size,
|
|||
max_read = na->data_size;
|
||||
#ifdef HAVE_SETXATTR /* extended attributes interface required */
|
||||
/* limit reads at next 512 byte boundary for encrypted attributes */
|
||||
if (ctx->efs_raw && (na->data_flags & ATTR_IS_ENCRYPTED) &&
|
||||
NAttrNonResident(na)) {
|
||||
if (ctx->efs_raw
|
||||
&& max_read
|
||||
&& (na->data_flags & ATTR_IS_ENCRYPTED)
|
||||
&& NAttrNonResident(na)) {
|
||||
max_read = ((na->data_size+511) & ~511) + 2;
|
||||
}
|
||||
#endif /* HAVE_SETXATTR */
|
||||
|
@ -3069,10 +3073,11 @@ static void ntfs_fuse_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
|||
goto exit;
|
||||
}
|
||||
rsize = na->data_size;
|
||||
if (ctx->efs_raw &&
|
||||
(na->data_flags & ATTR_IS_ENCRYPTED) &&
|
||||
NAttrNonResident(na))
|
||||
rsize = ((na->data_size + 511) & ~511)+2;
|
||||
if (ctx->efs_raw
|
||||
&& rsize
|
||||
&& (na->data_flags & ATTR_IS_ENCRYPTED)
|
||||
&& NAttrNonResident(na))
|
||||
rsize = ((na->data_size + 511) & ~511) + 2;
|
||||
if (size) {
|
||||
if (size >= (size_t)rsize) {
|
||||
value = (char*)ntfs_malloc(rsize);
|
||||
|
@ -3311,6 +3316,7 @@ static void ntfs_fuse_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
|||
}
|
||||
}
|
||||
total = 0;
|
||||
res = 0;
|
||||
if (size) {
|
||||
do {
|
||||
part = ntfs_attr_pwrite(na, total, size - total,
|
||||
|
@ -3318,20 +3324,20 @@ static void ntfs_fuse_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
|||
if (part > 0)
|
||||
total += part;
|
||||
} while ((part > 0) && (total < size));
|
||||
if (total != size)
|
||||
res = -errno;
|
||||
else
|
||||
if (!(res = ntfs_attr_pclose(na)))
|
||||
if (ctx->efs_raw
|
||||
&& (ni->flags & FILE_ATTR_ENCRYPTED))
|
||||
res = ntfs_efs_fixup_attribute(NULL,
|
||||
na);
|
||||
if (total && !(ni->flags & FILE_ATTR_ARCHIVE)) {
|
||||
set_archive(ni);
|
||||
NInoFileNameSetDirty(ni);
|
||||
}
|
||||
if ((total != size) || ntfs_attr_pclose(na))
|
||||
res = -errno;
|
||||
else {
|
||||
if (ctx->efs_raw
|
||||
&& (ni->flags & FILE_ATTR_ENCRYPTED)) {
|
||||
if (ntfs_efs_fixup_attribute(NULL,na))
|
||||
res = -errno;
|
||||
}
|
||||
} else
|
||||
res = 0;
|
||||
}
|
||||
if (!res && !(ni->flags & FILE_ATTR_ARCHIVE)) {
|
||||
set_archive(ni);
|
||||
NInoFileNameSetDirty(ni);
|
||||
}
|
||||
exit:
|
||||
if (na)
|
||||
ntfs_attr_close(na);
|
||||
|
|
|
@ -768,7 +768,9 @@ static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf)
|
|||
* encrypted files to include padding required for decryption
|
||||
* also include 2 bytes for padding info
|
||||
*/
|
||||
if (ctx->efs_raw && ni->flags & FILE_ATTR_ENCRYPTED)
|
||||
if (ctx->efs_raw
|
||||
&& (ni->flags & FILE_ATTR_ENCRYPTED)
|
||||
&& ni->data_size)
|
||||
stbuf->st_size = ((ni->data_size + 511) & ~511) + 2;
|
||||
#endif /* HAVE_SETXATTR */
|
||||
/*
|
||||
|
@ -1230,8 +1232,10 @@ static int ntfs_fuse_read(const char *org_path, char *buf, size_t size,
|
|||
max_read = na->data_size;
|
||||
#ifdef HAVE_SETXATTR /* extended attributes interface required */
|
||||
/* limit reads at next 512 byte boundary for encrypted attributes */
|
||||
if (ctx->efs_raw && (na->data_flags & ATTR_IS_ENCRYPTED) &&
|
||||
NAttrNonResident(na)) {
|
||||
if (ctx->efs_raw
|
||||
&& max_read
|
||||
&& (na->data_flags & ATTR_IS_ENCRYPTED)
|
||||
&& NAttrNonResident(na)) {
|
||||
max_read = ((na->data_size+511) & ~511) + 2;
|
||||
}
|
||||
#endif /* HAVE_SETXATTR */
|
||||
|
@ -2984,10 +2988,11 @@ static int ntfs_fuse_getxattr(const char *path, const char *name,
|
|||
goto exit;
|
||||
}
|
||||
rsize = na->data_size;
|
||||
if (ctx->efs_raw &&
|
||||
(na->data_flags & ATTR_IS_ENCRYPTED) &&
|
||||
NAttrNonResident(na))
|
||||
rsize = ((na->data_size + 511) & ~511)+2;
|
||||
if (ctx->efs_raw
|
||||
&& rsize
|
||||
&& (na->data_flags & ATTR_IS_ENCRYPTED)
|
||||
&& NAttrNonResident(na))
|
||||
rsize = ((na->data_size + 511) & ~511) + 2;
|
||||
if (size) {
|
||||
if (size >= (size_t)rsize) {
|
||||
res = ntfs_attr_pread(na, 0, rsize, value);
|
||||
|
@ -3235,6 +3240,7 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
|
|||
}
|
||||
}
|
||||
total = 0;
|
||||
res = 0;
|
||||
if (size) {
|
||||
do {
|
||||
part = ntfs_attr_pwrite(na, total, size - total,
|
||||
|
@ -3242,20 +3248,20 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
|
|||
if (part > 0)
|
||||
total += part;
|
||||
} while ((part > 0) && (total < size));
|
||||
if (total != size)
|
||||
res = -errno;
|
||||
else
|
||||
if (!(res = ntfs_attr_pclose(na)))
|
||||
if (ctx->efs_raw
|
||||
&& (ni->flags & FILE_ATTR_ENCRYPTED))
|
||||
res = ntfs_efs_fixup_attribute(NULL,
|
||||
na);
|
||||
if (total && !(ni->flags & FILE_ATTR_ARCHIVE)) {
|
||||
set_archive(ni);
|
||||
NInoFileNameSetDirty(ni);
|
||||
}
|
||||
if ((total != size) || ntfs_attr_pclose(na))
|
||||
res = -errno;
|
||||
else {
|
||||
if (ctx->efs_raw
|
||||
&& (ni->flags & FILE_ATTR_ENCRYPTED)) {
|
||||
if (ntfs_efs_fixup_attribute(NULL,na))
|
||||
res = -errno;
|
||||
}
|
||||
} else
|
||||
res = 0;
|
||||
}
|
||||
if (!res && !(ni->flags & FILE_ATTR_ARCHIVE)) {
|
||||
set_archive(ni);
|
||||
NInoFileNameSetDirty(ni);
|
||||
}
|
||||
exit:
|
||||
if (na)
|
||||
ntfs_attr_close(na);
|
||||
|
|
Loading…
Reference in New Issue