see changelog

edge.strict_endians
cha0smaster 2005-11-07 20:37:07 +00:00
parent 23a84fe825
commit a732881c5e
10 changed files with 103 additions and 105 deletions

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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;