see changelog
parent
23a84fe825
commit
a732881c5e
|
@ -58,6 +58,15 @@ xx/xx/2005 - 1.12.2-WIP
|
|||
- ntfsinfo: dump index attribute keys. (Szaka)
|
||||
- mkntfs: don't fill the last $MFT cluster with empty MFT records.
|
||||
This is needed to conform to Windows' format behavior. (Szaka)
|
||||
- Add @flags field to struct ntfs_inode. Remove NIno{Sparse,Compressed,
|
||||
Encrypted}, update all users to use @(ntfs_inode)->flags. (Yura)
|
||||
- Make @(ntfs_inode)->data_size and @(ntfs_inode)->allocated_size to
|
||||
always contain valid value. (Yura)
|
||||
- Always set correct file size and attributes in ntfs_link(). (Yura)
|
||||
- Add info about Interix special files (symbolic links, character and
|
||||
block devices, FIFOs and sockets) to layout.h. Teech ntfsmount to
|
||||
handle them. (Yura)
|
||||
- Fix allocated data size for resident attributes. (Yura)
|
||||
|
||||
10/10/2005 - 1.12.1 - Minor fix to location of mount.ntfs-fuse and mkfs.ntfs.
|
||||
|
||||
|
|
|
@ -203,30 +203,30 @@ typedef enum {
|
|||
#define NAttrSetNonResident(na) set_nattr_flag(na, NonResident)
|
||||
#define NAttrClearNonResident(na) clear_nattr_flag(na, NonResident)
|
||||
|
||||
#define GenNAttrIno(flag) \
|
||||
static inline int NAttr##flag(ntfs_attr *na) \
|
||||
#define GenNAttrIno(func_name,flag) \
|
||||
static inline int NAttr##func_name(ntfs_attr *na) \
|
||||
{ \
|
||||
if (na->type == AT_DATA && na->name == AT_UNNAMED) \
|
||||
return NIno##flag(na->ni); \
|
||||
return (na->ni->flags & FILE_ATTR_##flag); \
|
||||
return 0; \
|
||||
} \
|
||||
static inline void NAttrSet##flag(ntfs_attr *na) \
|
||||
static inline void NAttrSet##func_name(ntfs_attr *na) \
|
||||
{ \
|
||||
if (na->type == AT_DATA && na->name == AT_UNNAMED) \
|
||||
NInoSet##flag(na->ni); \
|
||||
na->ni->flags |= FILE_ATTR_##flag; \
|
||||
else \
|
||||
ntfs_log_trace("BUG! Should be called only for "\
|
||||
"unnamed data attribute.\n"); \
|
||||
} \
|
||||
static inline void NAttrClear##flag(ntfs_attr *na) \
|
||||
static inline void NAttrClear##func_name(ntfs_attr *na) \
|
||||
{ \
|
||||
if (na->type == AT_DATA && na->name == AT_UNNAMED) \
|
||||
NInoClear##flag(na->ni); \
|
||||
na->ni->flags &= ~FILE_ATTR_##flag; \
|
||||
}
|
||||
|
||||
GenNAttrIno(Compressed)
|
||||
GenNAttrIno(Encrypted)
|
||||
GenNAttrIno(Sparse)
|
||||
GenNAttrIno(Compressed, COMPRESSED)
|
||||
GenNAttrIno(Encrypted, ENCRYPTED)
|
||||
GenNAttrIno(Sparse, SPARSE_FILE)
|
||||
|
||||
/*
|
||||
* Union of all known attribute values. For convenience. Used in the attr
|
||||
|
|
|
@ -45,9 +45,6 @@ typedef enum {
|
|||
NI_AttrList, /* 1: Mft record contains an attribute list. */
|
||||
NI_AttrListDirty, /* 1: Attribute list needs to be written to the
|
||||
mft record and then to disk. */
|
||||
NI_Compressed, /* 1: Inode is compressed. */
|
||||
NI_Encrypted, /* 1: Inode is encrypted. */
|
||||
NI_Sparse, /* 1: Inode is sparse. */
|
||||
NI_FileNameDirty, /* 1: FILE_NAME attributes need to be updated
|
||||
in the index. */
|
||||
} ntfs_inode_state_bits;
|
||||
|
@ -87,18 +84,6 @@ typedef enum {
|
|||
#define NInoAttrListTestAndSetDirty(ni) test_and_set_nino_al_flag(ni, Dirty)
|
||||
#define NInoAttrListTestAndClearDirty(ni) test_and_clear_nino_al_flag(ni, Dirty)
|
||||
|
||||
#define NInoCompressed(ni) test_nino_flag(ni, Compressed)
|
||||
#define NInoSetCompressed(ni) set_nino_flag(ni, Compressed)
|
||||
#define NInoClearCompressed(ni) clear_nino_flag(ni, Compressed)
|
||||
|
||||
#define NInoEncrypted(ni) test_nino_flag(ni, Encrypted)
|
||||
#define NInoSetEncrypted(ni) set_nino_flag(ni, Encrypted)
|
||||
#define NInoClearEncrypted(ni) clear_nino_flag(ni, Encrypted)
|
||||
|
||||
#define NInoSparse(ni) test_nino_flag(ni, Sparse)
|
||||
#define NInoSetSparse(ni) set_nino_flag(ni, Sparse)
|
||||
#define NInoClearSparse(ni) clear_nino_flag(ni, Sparse)
|
||||
|
||||
#define NInoFileNameDirty(ni) \
|
||||
test_nino_flag(ni, FileNameDirty)
|
||||
#define NInoFileNameSetDirty(ni) \
|
||||
|
@ -148,7 +133,7 @@ struct _ntfs_inode {
|
|||
void *private_data; /* ntfs_dt containing this inode */
|
||||
int ref_count;
|
||||
|
||||
/* Below 2 fields needed to update indexes. They valid if != -1. */
|
||||
/* Below fields are valid only for base inode. */
|
||||
s64 data_size;
|
||||
s64 allocated_size;
|
||||
|
||||
|
|
|
@ -852,9 +852,10 @@ typedef enum {
|
|||
is used to obtain all flags that are valid for reading. */
|
||||
FILE_ATTR_VALID_SET_FLAGS = const_cpu_to_le32(0x000031a7),
|
||||
/* FILE_ATTR_VALID_SET_FLAGS masks out the old DOS VolId, the
|
||||
F_A_DEVICE, F_A_DIRECTORY, F_A_SPARSE_FILE, F_A_REPARSE_POINT,
|
||||
F_A_COMPRESSED and F_A_ENCRYPTED and preserves the rest. This mask
|
||||
is used to to obtain all flags that are valid for setting. */
|
||||
FILE_ATTR_DEVICE, FILE_ATTR_DIRECTORY, FILE_ATTR_SPARSE_FILE,
|
||||
FILE_ATTR_REPARSE_POINT, FILE_ATRE_COMPRESSED and FILE_ATTR_ENCRYPTED
|
||||
and preserves the rest. This mask is used to to obtain all flags that
|
||||
are valid for setting. */
|
||||
|
||||
/*
|
||||
* These flags are only present in the FILE_NAME attribute (in the
|
||||
|
|
|
@ -409,9 +409,8 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
|
|||
s64 l = le32_to_cpu(a->value_length);
|
||||
ntfs_attr_init(na, FALSE, a->flags & ATTR_IS_COMPRESSED,
|
||||
a->flags & ATTR_IS_ENCRYPTED,
|
||||
a->flags & ATTR_IS_SPARSE, l, l, l,
|
||||
cs ? sle64_to_cpu(a->compressed_size) : 0,
|
||||
cs ? a->compression_unit : 0);
|
||||
a->flags & ATTR_IS_SPARSE, (l + 7) & ~7, l, l,
|
||||
cs ? (l + 7) & ~7 : 0, 0);
|
||||
}
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
return na;
|
||||
|
@ -3702,10 +3701,10 @@ static int ntfs_resident_attr_resize(ntfs_attr *na, const s64 newsize)
|
|||
if (!ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr,
|
||||
newsize)) {
|
||||
/* Update the ntfs attribute structure, too. */
|
||||
na->allocated_size = na->data_size =
|
||||
na->initialized_size = newsize;
|
||||
na->data_size = na->initialized_size = newsize;
|
||||
na->allocated_size = (newsize + 7) & ~7;
|
||||
if (NAttrCompressed(na) || NAttrSparse(na))
|
||||
na->compressed_size = newsize;
|
||||
na->compressed_size = na->allocated_size;
|
||||
goto resize_done;
|
||||
}
|
||||
/* Error! If not enough space, just continue. */
|
||||
|
@ -4027,8 +4026,8 @@ static int ntfs_attr_make_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx)
|
|||
NAttrClearCompressed(na);
|
||||
NAttrClearSparse(na);
|
||||
NAttrClearEncrypted(na);
|
||||
na->allocated_size = na->initialized_size = na->compressed_size =
|
||||
na->data_size;
|
||||
na->initialized_size = na->data_size;
|
||||
na->allocated_size = na->compressed_size = (na->data_size + 7) & ~7;
|
||||
na->compression_block_size = 0;
|
||||
na->compression_block_size_bits = na->compression_block_clusters = 0;
|
||||
return 0;
|
||||
|
|
|
@ -1465,8 +1465,11 @@ int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len)
|
|||
le16_to_cpu(dir_ni->mrec->sequence_number));
|
||||
fn->file_name_length = name_len;
|
||||
fn->file_name_type = FILE_NAME_POSIX;
|
||||
fn->file_attributes = ni->flags;
|
||||
if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
|
||||
fn->file_attributes = FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT;
|
||||
fn->file_attributes |= FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT;
|
||||
fn->allocated_size = cpu_to_sle64(ni->allocated_size);
|
||||
fn->data_size = cpu_to_sle64(ni->data_size);
|
||||
fn->creation_time = utc2ntfs(ni->creation_time);
|
||||
fn->last_data_change_time = utc2ntfs(ni->last_data_change_time);
|
||||
fn->last_mft_change_time = utc2ntfs(ni->last_mft_change_time);
|
||||
|
@ -1502,15 +1505,6 @@ int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len)
|
|||
/* Increment hard links count. */
|
||||
ni->mrec->link_count = cpu_to_le16(le16_to_cpu(
|
||||
ni->mrec->link_count) + 1);
|
||||
/*
|
||||
* Do not set attributes and file size, instead of this mark filenames
|
||||
* dirty to force attribute and size update during sync.
|
||||
* NOTE: File size may will be not updated and not all attributes will
|
||||
* be set, but it is acceptable since windows driver does not update
|
||||
* all file names when one of the hard links changed.
|
||||
* FIXME: It will be nice to update them all.
|
||||
*/
|
||||
NInoFileNameSetDirty(ni);
|
||||
/* Done! */
|
||||
ntfs_inode_mark_dirty(ni);
|
||||
free(fn);
|
||||
|
|
|
@ -145,8 +145,6 @@ ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref)
|
|||
goto err_out;
|
||||
}
|
||||
ni->mft_no = MREF(mref);
|
||||
ni->data_size = -1;
|
||||
ni->allocated_size = -1;
|
||||
ctx = ntfs_attr_get_search_ctx(ni, NULL);
|
||||
if (!ctx)
|
||||
goto err_out;
|
||||
|
@ -160,12 +158,6 @@ ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref)
|
|||
}
|
||||
std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr +
|
||||
le16_to_cpu(ctx->attr->value_offset));
|
||||
if (std_info->file_attributes & FILE_ATTR_COMPRESSED)
|
||||
NInoSetCompressed(ni);
|
||||
if (std_info->file_attributes & FILE_ATTR_ENCRYPTED)
|
||||
NInoSetEncrypted(ni);
|
||||
if (std_info->file_attributes & FILE_ATTR_SPARSE_FILE)
|
||||
NInoSetSparse(ni);
|
||||
ni->flags = std_info->file_attributes;
|
||||
ni->creation_time = ntfs2utc(std_info->creation_time);
|
||||
ni->last_data_change_time = ntfs2utc(std_info->last_data_change_time);
|
||||
|
@ -176,9 +168,8 @@ ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref)
|
|||
ctx)) {
|
||||
if (errno != ENOENT)
|
||||
goto put_err_out;
|
||||
/* Attribute list attribute not present so we are done. */
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
return ni;
|
||||
/* Attribute list attribute does not present. */
|
||||
goto get_size;
|
||||
}
|
||||
NInoSetAttrList(ni);
|
||||
l = ntfs_get_attribute_value_length(ctx->attr);
|
||||
|
@ -199,6 +190,27 @@ ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref)
|
|||
err = EIO;
|
||||
goto put_err_out;
|
||||
}
|
||||
get_size:
|
||||
if (ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
|
||||
if (errno != ENOENT)
|
||||
goto put_err_out;
|
||||
/* Directory or special file. */
|
||||
ni->data_size = ni->allocated_size = 0;
|
||||
} else {
|
||||
if (ctx->attr->non_resident) {
|
||||
ni->data_size = sle64_to_cpu(ctx->attr->data_size);
|
||||
if (ctx->attr->flags &
|
||||
(ATTR_IS_COMPRESSED & ATTR_IS_SPARSE))
|
||||
ni->allocated_size = sle64_to_cpu(
|
||||
ctx->attr->compressed_size);
|
||||
else
|
||||
ni->allocated_size = sle64_to_cpu(
|
||||
ctx->attr->allocated_size);
|
||||
} else {
|
||||
ni->data_size = le32_to_cpu(ctx->attr->value_length);
|
||||
ni->allocated_size = (ni->data_size + 7) & ~7;
|
||||
}
|
||||
}
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
return ni;
|
||||
put_err_out:
|
||||
|
@ -475,18 +487,7 @@ static int ntfs_inode_sync_standard_information(ntfs_inode *ni)
|
|||
}
|
||||
std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr +
|
||||
le16_to_cpu(ctx->attr->value_offset));
|
||||
if (NInoCompressed(ni))
|
||||
std_info->file_attributes |= FILE_ATTR_COMPRESSED;
|
||||
else
|
||||
std_info->file_attributes &= ~FILE_ATTR_COMPRESSED;
|
||||
if (NInoEncrypted(ni))
|
||||
std_info->file_attributes |= FILE_ATTR_ENCRYPTED;
|
||||
else
|
||||
std_info->file_attributes &= ~FILE_ATTR_ENCRYPTED;
|
||||
if (NInoSparse(ni))
|
||||
std_info->file_attributes |= FILE_ATTR_SPARSE_FILE;
|
||||
else
|
||||
std_info->file_attributes &= ~FILE_ATTR_SPARSE_FILE;
|
||||
std_info->file_attributes = ni->flags;
|
||||
std_info->creation_time = utc2ntfs(ni->creation_time);
|
||||
std_info->last_data_change_time = utc2ntfs(ni->last_data_change_time);
|
||||
std_info->last_mft_change_time = utc2ntfs(ni->last_mft_change_time);
|
||||
|
@ -562,22 +563,11 @@ static int ntfs_inode_sync_file_name(ntfs_inode *ni)
|
|||
}
|
||||
/* Update flags and file size. */
|
||||
fn = (FILE_NAME_ATTR *)ictx->data;
|
||||
if (NInoCompressed(ni))
|
||||
fn->file_attributes |= FILE_ATTR_COMPRESSED;
|
||||
else
|
||||
fn->file_attributes &= ~FILE_ATTR_COMPRESSED;
|
||||
if (NInoEncrypted(ni))
|
||||
fn->file_attributes |= FILE_ATTR_ENCRYPTED;
|
||||
else
|
||||
fn->file_attributes &= ~FILE_ATTR_ENCRYPTED;
|
||||
if (NInoSparse(ni))
|
||||
fn->file_attributes |= FILE_ATTR_SPARSE_FILE;
|
||||
else
|
||||
fn->file_attributes &= ~FILE_ATTR_SPARSE_FILE;
|
||||
if (ni->allocated_size != -1)
|
||||
fn->allocated_size = cpu_to_sle64(ni->allocated_size);
|
||||
if (ni->data_size != -1)
|
||||
fn->data_size = cpu_to_sle64(ni->data_size);
|
||||
fn->file_attributes =
|
||||
(fn->file_attributes & ~FILE_ATTR_VALID_FLAGS) |
|
||||
(ni->flags & FILE_ATTR_VALID_FLAGS);
|
||||
fn->allocated_size = cpu_to_sle64(ni->allocated_size);
|
||||
fn->data_size = cpu_to_sle64(ni->data_size);
|
||||
fn->creation_time = utc2ntfs(ni->creation_time);
|
||||
fn->last_data_change_time = utc2ntfs(ni->last_data_change_time);
|
||||
fn->last_mft_change_time = utc2ntfs(ni->last_mft_change_time);
|
||||
|
|
|
@ -1459,7 +1459,8 @@ mft_rec_already_initialized:
|
|||
/* Make sure the allocated inode is written out to disk later. */
|
||||
ntfs_inode_mark_dirty(ni);
|
||||
/* Initialize time, allocated and data size in ntfs_inode struct. */
|
||||
ni->data_size = ni->allocated_size = -1;
|
||||
ni->data_size = ni->allocated_size = 0;
|
||||
ni->flags = 0;
|
||||
ni->creation_time = ni->last_data_change_time =
|
||||
ni->last_mft_change_time =
|
||||
ni->last_access_time = time(NULL);
|
||||
|
|
|
@ -22,9 +22,11 @@ is recommended, but not mandatory.
|
|||
.TP
|
||||
.B Fully implemented ntfsmount features are:
|
||||
|
||||
* Read-only access to normal, sparse and compressed files.
|
||||
* Read-write access to normal and sparse files.
|
||||
|
||||
* Overwrite normal and sparse files *with* changes to size.
|
||||
* Read-only access to compressed files.
|
||||
|
||||
* Access to special Interix files (symlinks, devices, FIFOs).
|
||||
|
||||
* List/Read/Write/Add/Remove named data streams.
|
||||
|
||||
|
|
|
@ -312,13 +312,40 @@ static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf)
|
|||
}
|
||||
stbuf->st_nlink = 1; /* Needed for correct find work. */
|
||||
} else {
|
||||
/* Regular or INTX file. */
|
||||
/* Regular or Interix (INTX) file. */
|
||||
stbuf->st_mode = S_IFREG;
|
||||
na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
|
||||
if (na) {
|
||||
/* Check whether it's special INTX file. */
|
||||
if ((ni->flags & FILE_ATTR_SYSTEM) && na->data_size <=
|
||||
sizeof(INTX_FILE_TYPES) + sizeof(
|
||||
stbuf->st_size = ni->data_size;
|
||||
stbuf->st_blocks = ni->allocated_size >> vol->sector_size_bits;
|
||||
stbuf->st_mode |= (0777 & ~ctx->fmask);
|
||||
stbuf->st_nlink = le16_to_cpu(ni->mrec->link_count);
|
||||
if (ni->flags & FILE_ATTR_SYSTEM || stream_name_len) {
|
||||
na = ntfs_attr_open(ni, AT_DATA, stream_name,
|
||||
stream_name_len);
|
||||
if (!na) {
|
||||
if (stream_name_len)
|
||||
res = -ENOENT;
|
||||
goto exit;
|
||||
}
|
||||
if (stream_name_len) {
|
||||
stbuf->st_size = na->data_size;
|
||||
stbuf->st_blocks = na->allocated_size >>
|
||||
vol->sector_size_bits;
|
||||
}
|
||||
/* Check whether it's Interix fifo or socket. */
|
||||
if (!(ni->flags & FILE_ATTR_HIDDEN) &&
|
||||
!stream_name_len) {
|
||||
/* FIFO. */
|
||||
if (na->data_size == 0)
|
||||
stbuf->st_mode = S_IFIFO;
|
||||
/* Socket link. */
|
||||
if (na->data_size == 1)
|
||||
stbuf->st_mode = S_IFSOCK;
|
||||
}
|
||||
/*
|
||||
* Check wheter it's Interix symbolic link, block or
|
||||
* character device.
|
||||
*/
|
||||
if (na->data_size <= sizeof(INTX_FILE_TYPES) + sizeof(
|
||||
ntfschar) * MAX_PATH && na->data_size >
|
||||
sizeof(INTX_FILE_TYPES) &&
|
||||
!stream_name_len) {
|
||||
|
@ -359,18 +386,8 @@ static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf)
|
|||
stbuf->st_mode = S_IFLNK;
|
||||
free(intx_file);
|
||||
}
|
||||
stbuf->st_size = na->data_size;
|
||||
stbuf->st_blocks = na->allocated_size >>
|
||||
vol->sector_size_bits;
|
||||
ntfs_attr_close(na);
|
||||
} else {
|
||||
stbuf->st_size = 0;
|
||||
stbuf->st_blocks = 0;
|
||||
if (stream_name_len)
|
||||
res = -ENOENT;
|
||||
}
|
||||
stbuf->st_mode |= (0777 & ~ctx->fmask);
|
||||
stbuf->st_nlink = le16_to_cpu(ni->mrec->link_count);
|
||||
}
|
||||
stbuf->st_uid = ctx->uid;
|
||||
stbuf->st_gid = ctx->gid;
|
||||
|
|
Loading…
Reference in New Issue