Move NAttr{Sparse,Compressed,Encrypted} to inode struct preserving
the previous interface. (Yura, with fixes from Anton) (Logical change 1.645)edge.strict_endians
parent
003b867d71
commit
db7c9da42f
|
@ -28,9 +28,11 @@ typedef struct _ntfs_attr ntfs_attr;
|
|||
typedef struct _ntfs_attr_search_ctx ntfs_attr_search_ctx;
|
||||
|
||||
#include "types.h"
|
||||
#include "inode.h"
|
||||
#include "unistr.h"
|
||||
#include "runlist.h"
|
||||
#include "volume.h"
|
||||
#include "debug.h"
|
||||
|
||||
extern ntfschar AT_UNNAMED[];
|
||||
|
||||
|
@ -122,41 +124,6 @@ static __inline__ int ntfs_attrs_walk(ntfs_attr_search_ctx *ctx)
|
|||
NULL, 0, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_attr_state_bits - bits for the state field in the ntfs_attr structure
|
||||
*/
|
||||
typedef enum {
|
||||
NA_Initialized, /* 1: structure is initialized. */
|
||||
NA_NonResident, /* 1: Attribute is not resident. */
|
||||
NA_Compressed, /* 1: Attribute is compressed. */
|
||||
NA_Encrypted, /* 1: Attribute is encrypted. */
|
||||
NA_Sparse, /* 1: Attribute is sparse. */
|
||||
} ntfs_attr_state_bits;
|
||||
|
||||
#define test_nattr_flag(na, flag) test_bit(NA_##flag, (na)->state)
|
||||
#define set_nattr_flag(na, flag) set_bit(NA_##flag, (na)->state)
|
||||
#define clear_nattr_flag(na, flag) clear_bit(NA_##flag, (na)->state)
|
||||
|
||||
#define NAttrInitialized(na) test_nattr_flag(na, Initialized)
|
||||
#define NAttrSetInitialized(na) set_nattr_flag(na, Initialized)
|
||||
#define NAttrClearInitialized(na) clear_nattr_flag(na, Initialized)
|
||||
|
||||
#define NAttrNonResident(na) test_nattr_flag(na, NonResident)
|
||||
#define NAttrSetNonResident(na) set_nattr_flag(na, NonResident)
|
||||
#define NAttrClearNonResident(na) clear_nattr_flag(na, NonResident)
|
||||
|
||||
#define NAttrCompressed(na) test_nattr_flag(na, Compressed)
|
||||
#define NAttrSetCompressed(na) set_nattr_flag(na, Compressed)
|
||||
#define NAttrClearCompressed(na) clear_nattr_flag(na, Compressed)
|
||||
|
||||
#define NAttrEncrypted(na) test_nattr_flag(na, Encrypted)
|
||||
#define NAttrSetEncrypted(na) set_nattr_flag(na, Encrypted)
|
||||
#define NAttrClearEncrypted(na) clear_nattr_flag(na, Encrypted)
|
||||
|
||||
#define NAttrSparse(na) test_nattr_flag(na, Sparse)
|
||||
#define NAttrSetSparse(na) set_nattr_flag(na, Sparse)
|
||||
#define NAttrClearSparse(na) clear_nattr_flag(na, Sparse)
|
||||
|
||||
/**
|
||||
* ntfs_attr - ntfs in memory non-resident attribute structure
|
||||
* @rl: if not NULL, the decompressed runlist
|
||||
|
@ -215,6 +182,51 @@ struct _ntfs_attr {
|
|||
u8 compression_block_clusters;
|
||||
};
|
||||
|
||||
/**
|
||||
* ntfs_attr_state_bits - bits for the state field in the ntfs_attr structure
|
||||
*/
|
||||
typedef enum {
|
||||
NA_Initialized, /* 1: structure is initialized. */
|
||||
NA_NonResident, /* 1: Attribute is not resident. */
|
||||
} ntfs_attr_state_bits;
|
||||
|
||||
#define test_nattr_flag(na, flag) test_bit(NA_##flag, (na)->state)
|
||||
#define set_nattr_flag(na, flag) set_bit(NA_##flag, (na)->state)
|
||||
#define clear_nattr_flag(na, flag) clear_bit(NA_##flag, (na)->state)
|
||||
|
||||
#define NAttrInitialized(na) test_nattr_flag(na, Initialized)
|
||||
#define NAttrSetInitialized(na) set_nattr_flag(na, Initialized)
|
||||
#define NAttrClearInitialized(na) clear_nattr_flag(na, Initialized)
|
||||
|
||||
#define NAttrNonResident(na) test_nattr_flag(na, NonResident)
|
||||
#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) \
|
||||
{ \
|
||||
if (na->type == AT_DATA && na->name == AT_UNNAMED) \
|
||||
return NIno##flag(na->ni); \
|
||||
return 0; \
|
||||
} \
|
||||
static inline void NAttrSet##flag(ntfs_attr *na) \
|
||||
{ \
|
||||
if (na->type == AT_DATA && na->name == AT_UNNAMED) \
|
||||
NInoSet##flag(na->ni); \
|
||||
else \
|
||||
Dprintf("%s(): BUG! Called for named data " \
|
||||
"attribute.\n", __FUNCTION__); \
|
||||
} \
|
||||
static inline void NAttrClear##flag(ntfs_attr *na) \
|
||||
{ \
|
||||
if (na->type == AT_DATA && na->name == AT_UNNAMED) \
|
||||
NInoClear##flag(na->ni); \
|
||||
}
|
||||
|
||||
GenNAttrIno(Compressed)
|
||||
GenNAttrIno(Encrypted)
|
||||
GenNAttrIno(Sparse)
|
||||
|
||||
/*
|
||||
* Union of all known attribute values. For convenience. Used in the attr
|
||||
* structure.
|
||||
|
@ -295,6 +307,11 @@ extern int ntfs_attr_update_mapping_pairs(ntfs_attr *na);
|
|||
|
||||
extern int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize);
|
||||
|
||||
extern ntfs_attr *ntfs_inode_add_attr(ntfs_inode *ni, ATTR_TYPES type,
|
||||
ntfschar *name, u8 name_len, s64 size);
|
||||
|
||||
extern int ntfs_inode_rm_attr(ntfs_attr *na);
|
||||
|
||||
// FIXME / TODO: Above here the file is cleaned up. (AIA)
|
||||
/**
|
||||
* get_attribute_value_length - return the length of the value of an attribute
|
||||
|
|
|
@ -27,8 +27,9 @@
|
|||
typedef struct _ntfs_inode ntfs_inode;
|
||||
|
||||
#include "types.h"
|
||||
#include "layout.h"
|
||||
#include "support.h"
|
||||
#include "runlist.h"
|
||||
#include "volume.h"
|
||||
|
||||
/*
|
||||
* Defined bits for the state field in the ntfs_inode structure.
|
||||
|
@ -41,6 +42,9 @@ 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. */
|
||||
} ntfs_inode_state_bits;
|
||||
|
||||
#define test_nino_flag(ni, flag) test_bit(NI_##flag, (ni)->state)
|
||||
|
@ -78,6 +82,18 @@ 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)
|
||||
|
||||
/*
|
||||
* The NTFS in-memory inode structure. It is just used as an extension to the
|
||||
* fields already provided in the VFS inode.
|
||||
|
@ -145,10 +161,4 @@ extern int ntfs_inode_add_attrlist(ntfs_inode *ni);
|
|||
|
||||
extern int ntfs_inode_free_space(ntfs_inode *ni, int size);
|
||||
|
||||
extern ntfs_attr *ntfs_inode_add_attr(ntfs_inode *ni, ATTR_TYPES type,
|
||||
ntfschar *name, u8 name_len, s64 size);
|
||||
|
||||
extern int ntfs_inode_rm_attr(ntfs_attr *na);
|
||||
|
||||
#endif /* defined _NTFS_INODE_H */
|
||||
|
||||
|
|
|
@ -49,8 +49,9 @@ typedef struct _ntfs_volume ntfs_volume;
|
|||
|
||||
#include "types.h"
|
||||
#include "support.h"
|
||||
#include "inode.h"
|
||||
#include "device.h"
|
||||
#include "inode.h"
|
||||
#include "attrib.h"
|
||||
|
||||
/*
|
||||
* Flags returned by the ntfs_check_if_mounted() function.
|
||||
|
|
251
libntfs/attrib.c
251
libntfs/attrib.c
|
@ -4588,3 +4588,254 @@ int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize)
|
|||
}
|
||||
return ntfs_resident_attr_resize(na, newsize);
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_inode_add_attr - add attribute to inode
|
||||
* @ni: opened ntfs inode to which add attribute
|
||||
* @type: type of the new attribute
|
||||
* @name: name in unicode of the new attribute
|
||||
* @name_len: name length in unicode charcters of the new attribute
|
||||
* @size: size of the new attribute
|
||||
*
|
||||
* If inode haven't got enogh space to add attribute, add attribute to one of it
|
||||
* extents, if no extents present or no one of them have enough space, than
|
||||
* allocate new extent and add attribute to it.
|
||||
*
|
||||
* If on one of this steps attribute list is needed but not present, than it is
|
||||
* added transparently to caller. So, this function should not be called with
|
||||
* @type == AT_ATTRIBUTE_LIST, if you really need to add attribute list call
|
||||
* ntfs_inode_add_attrlist instead.
|
||||
*
|
||||
* On success return opened new ntfs attribute. On error return NULL with errno
|
||||
* set to the error code.
|
||||
*/
|
||||
ntfs_attr *ntfs_inode_add_attr(ntfs_inode *ni, ATTR_TYPES type,
|
||||
ntfschar *name, u8 name_len, s64 size)
|
||||
{
|
||||
u32 attr_rec_size;
|
||||
int err, i, offset;
|
||||
ntfs_inode *attr_ni;
|
||||
ntfs_attr *na;
|
||||
|
||||
if (!ni || size < 0 || type == AT_ATTRIBUTE_LIST) {
|
||||
Dprintf("%s(): Invalid arguments passed.\n", __FUNCTION__);
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Dprintf("%s(): Entering for inode 0x%llx, attr %x, size %lld.\n",
|
||||
__FUNCTION__, (long long) ni->mft_no, type, size);
|
||||
|
||||
if (ni->nr_extents == -1)
|
||||
ni = ni->base_ni;
|
||||
|
||||
/* Validate attribute type. */
|
||||
if (!ntfs_attr_find_in_attrdef(ni->vol, type)) {
|
||||
if (errno == ENOENT) {
|
||||
Dprintf("%s(): Invalid attribute type.\n",
|
||||
__FUNCTION__);
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
} else {
|
||||
err = errno;
|
||||
Dprintf("%s(): ntfs_attr_find_in_attrdef failed.\n",
|
||||
__FUNCTION__);
|
||||
errno = err;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine resident or not will be new attribute. We add 8 to size in
|
||||
* non resident case for mapping pairs.
|
||||
*/
|
||||
if (ntfs_attr_can_be_resident(ni->vol, type)) {
|
||||
if (errno != EPERM) {
|
||||
err = errno;
|
||||
Dprintf("%s(): ntfs_attr_can_be resident failed.\n",
|
||||
__FUNCTION__);
|
||||
goto err_out;
|
||||
}
|
||||
/* Attribute can't be resident. */
|
||||
attr_rec_size = offsetof(ATTR_RECORD, non_resident_end) +
|
||||
((name_len * sizeof(ntfschar) + 7) & ~7) + 8;
|
||||
} else {
|
||||
/* Attribute can be resident. */
|
||||
attr_rec_size = offsetof(ATTR_RECORD, resident_end) +
|
||||
((name_len * sizeof(ntfschar) + 7) & ~7);
|
||||
/* Check whether attribute will fit into the MFT record. */
|
||||
if (size + attr_rec_size >= ni->vol->mft_record_size)
|
||||
/* Will not fit, make it non resident. */
|
||||
attr_rec_size = offsetof(ATTR_RECORD,
|
||||
non_resident_end) + ((name_len *
|
||||
sizeof(ntfschar) + 7) & ~7) + 8;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(ni->mrec->bytes_allocated) -
|
||||
le32_to_cpu(ni->mrec->bytes_in_use) >= attr_rec_size) {
|
||||
attr_ni = ni;
|
||||
goto add_attr_record;
|
||||
}
|
||||
|
||||
/* Try to add to extent inodes. */
|
||||
if (ntfs_inode_attach_all_extents(ni)) {
|
||||
err = errno;
|
||||
Dprintf("%s(): Failed to attach all extents to inode.\n",
|
||||
__FUNCTION__);
|
||||
goto err_out;
|
||||
}
|
||||
for (i = 0; i < ni->nr_extents; i++) {
|
||||
attr_ni = ni->extent_nis[i];
|
||||
if (le32_to_cpu(attr_ni->mrec->bytes_allocated) -
|
||||
le32_to_cpu(attr_ni->mrec->bytes_in_use) >=
|
||||
attr_rec_size)
|
||||
goto add_attr_record;
|
||||
}
|
||||
|
||||
/* There is no extent that contain enough space for new attribute. */
|
||||
if (!NInoAttrList(ni)) {
|
||||
/* Add attribute list not present, add it and retry. */
|
||||
if (ntfs_inode_add_attrlist(ni)) {
|
||||
err = errno;
|
||||
Dprintf("%s(): Failed to add attribute list.\n",
|
||||
__FUNCTION__);
|
||||
goto err_out;
|
||||
}
|
||||
return ntfs_inode_add_attr(ni, type, name, name_len, size);
|
||||
}
|
||||
/* Allocate new extent. */
|
||||
attr_ni = ntfs_mft_record_alloc(ni->vol, ni);
|
||||
if (!attr_ni) {
|
||||
err = errno;
|
||||
Dprintf("%s(): Failed to allocate extent record.\n",
|
||||
__FUNCTION__);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
add_attr_record:
|
||||
if (attr_rec_size == offsetof(ATTR_RECORD, resident_end) +
|
||||
((name_len * sizeof(ntfschar) + 7) & ~7)) {
|
||||
/* Add resident attribute. */
|
||||
offset = ntfs_resident_attr_record_add(attr_ni, type, name,
|
||||
name_len, 0);
|
||||
if (offset < 0) {
|
||||
err = errno;
|
||||
Dprintf("%s(): Failed to add resident attribute.\n",
|
||||
__FUNCTION__);
|
||||
goto free_err_out;
|
||||
}
|
||||
} else {
|
||||
/* Add non resident attribute. */
|
||||
offset = ntfs_non_resident_attr_record_add(attr_ni, type, name,
|
||||
name_len, 0, 8, 0);
|
||||
if (offset < 0) {
|
||||
err = errno;
|
||||
Dprintf("%s(): Failed to add non resident attribute.\n",
|
||||
__FUNCTION__);
|
||||
goto free_err_out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Open new attribute and resize it. */
|
||||
na = ntfs_attr_open(ni, type, name, name_len);
|
||||
if (!na) {
|
||||
err = errno;
|
||||
Dprintf("%s(): Failed to open just added attribute.\n",
|
||||
__FUNCTION__);
|
||||
goto rm_attr_err_out;
|
||||
}
|
||||
if (!size)
|
||||
return na;
|
||||
if (ntfs_attr_truncate(na, size)) {
|
||||
err = errno;
|
||||
Dprintf("%s(): Failed to resize just added attribute.\n",
|
||||
__FUNCTION__);
|
||||
if (ntfs_inode_rm_attr(na)) {
|
||||
Dprintf("%s(): Failed to remove just added attribute. "
|
||||
"Probably leaving inconsist metadata.\n",
|
||||
__FUNCTION__);
|
||||
}
|
||||
goto err_out;
|
||||
}
|
||||
/* Done !*/
|
||||
return na;
|
||||
|
||||
rm_attr_err_out:
|
||||
/* Remove just added attribute. */
|
||||
if (ntfs_attr_record_resize(attr_ni->mrec,
|
||||
(ATTR_RECORD*)((u8*)attr_ni->mrec + offset), 0)) {
|
||||
Dprintf("%s(): Failed to remove just added attribute.\n",
|
||||
__FUNCTION__);
|
||||
}
|
||||
free_err_out:
|
||||
/* Free MFT record, if it isn't contain attributes. */
|
||||
if (le32_to_cpu(attr_ni->mrec->bytes_in_use) -
|
||||
le32_to_cpu(attr_ni->mrec->attrs_offset) == 8) {
|
||||
if (ntfs_mft_record_free(attr_ni->vol, attr_ni)) {
|
||||
Dprintf("%s(): Failed to free MFT record. Leaving "
|
||||
"inconsist metadata.\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
err_out:
|
||||
errno = err;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_inode_rm_attr - remove attribute from ntfs inode
|
||||
* @na: opened ntfs attribute to delete
|
||||
*
|
||||
* Remove attribute and all it's extents from ntfs inode. If attribute was non
|
||||
* resident also free all clusters allocated by attribute.
|
||||
*
|
||||
* Return 0 on success or -1 on error with errno set to the error code.
|
||||
*/
|
||||
int ntfs_inode_rm_attr(ntfs_attr *na)
|
||||
{
|
||||
ntfs_attr_search_ctx *ctx;
|
||||
int ret = 0;
|
||||
|
||||
if (!na) {
|
||||
Dprintf("%s(): Invalid arguments passed.\n", __FUNCTION__);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Dprintf("%s(): Entering for inode 0x%llx, attr 0x%x.\n",
|
||||
__FUNCTION__, (long long) na->ni->mft_no, na->type);
|
||||
|
||||
/* Free cluster allocation. */
|
||||
if (NAttrNonResident(na)) {
|
||||
if (ntfs_attr_map_whole_runlist(na))
|
||||
return -1;
|
||||
if (ntfs_cluster_free(na->ni->vol, na, 0, -1) < 0) {
|
||||
Dprintf("%s(): Failed to free cluster allocation. "
|
||||
"Leaving inconsist metadata.\n", __FUNCTION__);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Search for attribute extents and remove them all. */
|
||||
ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
|
||||
if (!ctx)
|
||||
return -1;
|
||||
while (!ntfs_attr_lookup(na->type, na->name, na->name_len,
|
||||
CASE_SENSITIVE, 0, NULL, 0, ctx)) {
|
||||
if (ntfs_attr_record_rm(ctx)) {
|
||||
Dprintf("%s(): Failed to remove attribute extent. "
|
||||
"Leaving inconsist metadata.\n", __FUNCTION__);
|
||||
ret = -1;
|
||||
}
|
||||
ntfs_attr_reinit_search_ctx(ctx);
|
||||
}
|
||||
if (errno != ENOENT) {
|
||||
Dprintf("%s(): Attribute lookup failed. Probably leaving "
|
||||
"inconsist metadata.\n", __FUNCTION__);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
/* Throw away now non-exist attribute. */
|
||||
ntfs_attr_close(na);
|
||||
/* Done. */
|
||||
return ret;
|
||||
}
|
||||
|
|
253
libntfs/inode.c
253
libntfs/inode.c
|
@ -29,10 +29,10 @@
|
|||
#include "compat.h"
|
||||
|
||||
#include "types.h"
|
||||
#include "attrib.h"
|
||||
#include "inode.h"
|
||||
#include "debug.h"
|
||||
#include "mft.h"
|
||||
#include "attrib.h"
|
||||
#include "attrlist.h"
|
||||
#include "runlist.h"
|
||||
#include "lcnalloc.h"
|
||||
|
@ -848,254 +848,3 @@ put_err_out:
|
|||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_inode_add_attr - add attribute to inode
|
||||
* @ni: opened ntfs inode to which add attribute
|
||||
* @type: type of the new attribute
|
||||
* @name: name in unicode of the new attribute
|
||||
* @name_len: name length in unicode charcters of the new attribute
|
||||
* @size: size of the new attribute
|
||||
*
|
||||
* If inode haven't got enogh space to add attribute, add attribute to one of it
|
||||
* extents, if no extents present or no one of them have enough space, than
|
||||
* allocate new extent and add attribute to it.
|
||||
*
|
||||
* If on one of this steps attribute list is needed but not present, than it is
|
||||
* added transparently to caller. So, this function should not be called with
|
||||
* @type == AT_ATTRIBUTE_LIST, if you really need to add attribute list call
|
||||
* ntfs_inode_add_attrlist instead.
|
||||
*
|
||||
* On success return opened new ntfs attribute. On error return NULL with errno
|
||||
* set to the error code.
|
||||
*/
|
||||
ntfs_attr *ntfs_inode_add_attr(ntfs_inode *ni, ATTR_TYPES type,
|
||||
ntfschar *name, u8 name_len, s64 size)
|
||||
{
|
||||
u32 attr_rec_size;
|
||||
int err, i, offset;
|
||||
ntfs_inode *attr_ni;
|
||||
ntfs_attr *na;
|
||||
|
||||
if (!ni || size < 0 || type == AT_ATTRIBUTE_LIST) {
|
||||
Dprintf("%s(): Invalid arguments passed.\n", __FUNCTION__);
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Dprintf("%s(): Entering for inode 0x%llx, attr %x, size %lld.\n",
|
||||
__FUNCTION__, (long long) ni->mft_no, type, size);
|
||||
|
||||
if (ni->nr_extents == -1)
|
||||
ni = ni->base_ni;
|
||||
|
||||
/* Validate attribute type. */
|
||||
if (!ntfs_attr_find_in_attrdef(ni->vol, type)) {
|
||||
if (errno == ENOENT) {
|
||||
Dprintf("%s(): Invalid attribute type.\n",
|
||||
__FUNCTION__);
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
} else {
|
||||
err = errno;
|
||||
Dprintf("%s(): ntfs_attr_find_in_attrdef failed.\n",
|
||||
__FUNCTION__);
|
||||
errno = err;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine resident or not will be new attribute. We add 8 to size in
|
||||
* non resident case for mapping pairs.
|
||||
*/
|
||||
if (ntfs_attr_can_be_resident(ni->vol, type)) {
|
||||
if (errno != EPERM) {
|
||||
err = errno;
|
||||
Dprintf("%s(): ntfs_attr_can_be resident failed.\n",
|
||||
__FUNCTION__);
|
||||
goto err_out;
|
||||
}
|
||||
/* Attribute can't be resident. */
|
||||
attr_rec_size = offsetof(ATTR_RECORD, non_resident_end) +
|
||||
((name_len * sizeof(ntfschar) + 7) & ~7) + 8;
|
||||
} else {
|
||||
/* Attribute can be resident. */
|
||||
attr_rec_size = offsetof(ATTR_RECORD, resident_end) +
|
||||
((name_len * sizeof(ntfschar) + 7) & ~7);
|
||||
/* Check whether attribute will fit into the MFT record. */
|
||||
if (size + attr_rec_size >= ni->vol->mft_record_size)
|
||||
/* Will not fit, make it non resident. */
|
||||
attr_rec_size = offsetof(ATTR_RECORD,
|
||||
non_resident_end) + ((name_len *
|
||||
sizeof(ntfschar) + 7) & ~7) + 8;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(ni->mrec->bytes_allocated) -
|
||||
le32_to_cpu(ni->mrec->bytes_in_use) >= attr_rec_size) {
|
||||
attr_ni = ni;
|
||||
goto add_attr_record;
|
||||
}
|
||||
|
||||
/* Try to add to extent inodes. */
|
||||
if (ntfs_inode_attach_all_extents(ni)) {
|
||||
err = errno;
|
||||
Dprintf("%s(): Failed to attach all extents to inode.\n",
|
||||
__FUNCTION__);
|
||||
goto err_out;
|
||||
}
|
||||
for (i = 0; i < ni->nr_extents; i++) {
|
||||
attr_ni = ni->extent_nis[i];
|
||||
if (le32_to_cpu(attr_ni->mrec->bytes_allocated) -
|
||||
le32_to_cpu(attr_ni->mrec->bytes_in_use) >=
|
||||
attr_rec_size)
|
||||
goto add_attr_record;
|
||||
}
|
||||
|
||||
/* There is no extent that contain enough space for new attribute. */
|
||||
if (!NInoAttrList(ni)) {
|
||||
/* Add attribute list not present, add it and retry. */
|
||||
if (ntfs_inode_add_attrlist(ni)) {
|
||||
err = errno;
|
||||
Dprintf("%s(): Failed to add attribute list.\n",
|
||||
__FUNCTION__);
|
||||
goto err_out;
|
||||
}
|
||||
return ntfs_inode_add_attr(ni, type, name, name_len, size);
|
||||
}
|
||||
/* Allocate new extent. */
|
||||
attr_ni = ntfs_mft_record_alloc(ni->vol, ni);
|
||||
if (!attr_ni) {
|
||||
err = errno;
|
||||
Dprintf("%s(): Failed to allocate extent record.\n",
|
||||
__FUNCTION__);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
add_attr_record:
|
||||
if (attr_rec_size == offsetof(ATTR_RECORD, resident_end) +
|
||||
((name_len * sizeof(ntfschar) + 7) & ~7)) {
|
||||
/* Add resident attribute. */
|
||||
offset = ntfs_resident_attr_record_add(attr_ni, type, name,
|
||||
name_len, 0);
|
||||
if (offset < 0) {
|
||||
err = errno;
|
||||
Dprintf("%s(): Failed to add resident attribute.\n",
|
||||
__FUNCTION__);
|
||||
goto free_err_out;
|
||||
}
|
||||
} else {
|
||||
/* Add non resident attribute. */
|
||||
offset = ntfs_non_resident_attr_record_add(attr_ni, type, name,
|
||||
name_len, 0, 8, 0);
|
||||
if (offset < 0) {
|
||||
err = errno;
|
||||
Dprintf("%s(): Failed to add non resident attribute.\n",
|
||||
__FUNCTION__);
|
||||
goto free_err_out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Open new attribute and resize it. */
|
||||
na = ntfs_attr_open(ni, type, name, name_len);
|
||||
if (!na) {
|
||||
err = errno;
|
||||
Dprintf("%s(): Failed to open just added attribute.\n",
|
||||
__FUNCTION__);
|
||||
goto rm_attr_err_out;
|
||||
}
|
||||
if (!size)
|
||||
return na;
|
||||
if (ntfs_attr_truncate(na, size)) {
|
||||
err = errno;
|
||||
Dprintf("%s(): Failed to resize just added attribute.\n",
|
||||
__FUNCTION__);
|
||||
if (ntfs_inode_rm_attr(na)) {
|
||||
Dprintf("%s(): Failed to remove just added attribute. "
|
||||
"Probably leaving inconsist metadata.\n",
|
||||
__FUNCTION__);
|
||||
}
|
||||
goto err_out;
|
||||
}
|
||||
/* Done !*/
|
||||
return na;
|
||||
|
||||
rm_attr_err_out:
|
||||
/* Remove just added attribute. */
|
||||
if (ntfs_attr_record_resize(attr_ni->mrec,
|
||||
(ATTR_RECORD*)((u8*)attr_ni->mrec + offset), 0)) {
|
||||
Dprintf("%s(): Failed to remove just added attribute.\n",
|
||||
__FUNCTION__);
|
||||
}
|
||||
free_err_out:
|
||||
/* Free MFT record, if it isn't contain attributes. */
|
||||
if (le32_to_cpu(attr_ni->mrec->bytes_in_use) -
|
||||
le32_to_cpu(attr_ni->mrec->attrs_offset) == 8) {
|
||||
if (ntfs_mft_record_free(attr_ni->vol, attr_ni)) {
|
||||
Dprintf("%s(): Failed to free MFT record. Leaving "
|
||||
"inconsist metadata.\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
err_out:
|
||||
errno = err;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_inode_rm_attr - remove attribute from ntfs inode
|
||||
* @na: opened ntfs attribute to delete
|
||||
*
|
||||
* Remove attribute and all it's extents from ntfs inode. If attribute was non
|
||||
* resident also free all clusters allocated by attribute.
|
||||
*
|
||||
* Return 0 on success or -1 on error with errno set to the error code.
|
||||
*/
|
||||
int ntfs_inode_rm_attr(ntfs_attr *na)
|
||||
{
|
||||
ntfs_attr_search_ctx *ctx;
|
||||
int ret = 0;
|
||||
|
||||
if (!na) {
|
||||
Dprintf("%s(): Invalid arguments passed.\n", __FUNCTION__);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Dprintf("%s(): Entering for inode 0x%llx, attr 0x%x.\n",
|
||||
__FUNCTION__, (long long) na->ni->mft_no, na->type);
|
||||
|
||||
/* Free cluster allocation. */
|
||||
if (NAttrNonResident(na)) {
|
||||
if (ntfs_attr_map_whole_runlist(na))
|
||||
return -1;
|
||||
if (ntfs_cluster_free(na->ni->vol, na, 0, -1) < 0) {
|
||||
Dprintf("%s(): Failed to free cluster allocation. "
|
||||
"Leaving inconsist metadata.\n", __FUNCTION__);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Search for attribute extents and remove them all. */
|
||||
ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
|
||||
if (!ctx)
|
||||
return -1;
|
||||
while (!ntfs_attr_lookup(na->type, na->name, na->name_len,
|
||||
CASE_SENSITIVE, 0, NULL, 0, ctx)) {
|
||||
if (ntfs_attr_record_rm(ctx)) {
|
||||
Dprintf("%s(): Failed to remove attribute extent. "
|
||||
"Leaving inconsist metadata.\n", __FUNCTION__);
|
||||
ret = -1;
|
||||
}
|
||||
ntfs_attr_reinit_search_ctx(ctx);
|
||||
}
|
||||
if (errno != ENOENT) {
|
||||
Dprintf("%s(): Attribute lookup failed. Probably leaving "
|
||||
"inconsist metadata.\n", __FUNCTION__);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
/* Throw away now non-exist attribute. */
|
||||
ntfs_attr_close(na);
|
||||
/* Done. */
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -117,14 +117,14 @@
|
|||
#endif
|
||||
|
||||
#include "types.h"
|
||||
#include "bootsect.h"
|
||||
#include "device.h"
|
||||
#include "attrib.h"
|
||||
#include "bitmap.h"
|
||||
#include "mst.h"
|
||||
#include "bootsect.h"
|
||||
#include "device.h"
|
||||
#include "dir.h"
|
||||
#include "runlist.h"
|
||||
#include "mft.h"
|
||||
#include "mst.h"
|
||||
#include "runlist.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef NO_NTFS_DEVICE_DEFAULT_IO_OPS
|
||||
|
@ -210,10 +210,11 @@ struct {
|
|||
} opts;
|
||||
|
||||
/**
|
||||
* Dprintf - debugging output (-vv); overriden by quiet (-q)
|
||||
* mkDprintf - debugging output (-vv); overriden by quiet (-q)
|
||||
*/
|
||||
static void Dprintf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
|
||||
static void Dprintf(const char *fmt, ...)
|
||||
static void mkDprintf(const char *fmt, ...)
|
||||
__attribute__((format(printf, 1, 2)));
|
||||
static void mkDprintf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
|
@ -2297,7 +2298,7 @@ static int insert_file_link_in_dir_index(INDEX_BLOCK *idx, MFT_REF file_ref,
|
|||
while ((char*)ie < index_end && !(ie->flags & INDEX_ENTRY_END)) {
|
||||
/*
|
||||
#ifdef DEBUG
|
||||
Dprintf("file_name_attr1->file_name_length = %i\n",
|
||||
mkDprintf("file_name_attr1->file_name_length = %i\n",
|
||||
file_name->file_name_length);
|
||||
if (file_name->file_name_length) {
|
||||
char *__buf;
|
||||
|
@ -2309,12 +2310,12 @@ static int insert_file_link_in_dir_index(INDEX_BLOCK *idx, MFT_REF file_ref,
|
|||
i = ucstos(__buf, (ntfschar*)&file_name->file_name,
|
||||
file_name->file_name_length + 1);
|
||||
if (i == -1)
|
||||
Dprintf("Name contains non-displayable "
|
||||
mkDprintf("Name contains non-displayable "
|
||||
"Unicode characters.\n");
|
||||
Dprintf("file_name_attr1->file_name = %s\n", __buf);
|
||||
mkDprintf("file_name_attr1->file_name = %s\n", __buf);
|
||||
free(__buf);
|
||||
}
|
||||
Dprintf("file_name_attr2->file_name_length = %i\n",
|
||||
mkDprintf("file_name_attr2->file_name_length = %i\n",
|
||||
ie->key.file_name.file_name_length);
|
||||
if (ie->key.file_name.file_name_length) {
|
||||
char *__buf;
|
||||
|
@ -2326,9 +2327,9 @@ static int insert_file_link_in_dir_index(INDEX_BLOCK *idx, MFT_REF file_ref,
|
|||
i = ucstos(__buf, ie->key.file_name.file_name,
|
||||
ie->key.file_name.file_name_length + 1);
|
||||
if (i == -1)
|
||||
Dprintf("Name contains non-displayable "
|
||||
mkDprintf("Name contains non-displayable "
|
||||
"Unicode characters.\n");
|
||||
Dprintf("file_name_attr2->file_name = %s\n", __buf);
|
||||
mkDprintf("file_name_attr2->file_name = %s\n", __buf);
|
||||
free(__buf);
|
||||
}
|
||||
#endif
|
||||
|
@ -2369,7 +2370,7 @@ do_next:
|
|||
#ifdef DEBUG
|
||||
/* Next entry. */
|
||||
if (!ie->length) {
|
||||
Dprintf("BUG: ie->length is zero, breaking out of "
|
||||
mkDprintf("BUG: ie->length is zero, breaking out of "
|
||||
"loop.\n");
|
||||
break;
|
||||
}
|
||||
|
@ -2502,7 +2503,7 @@ static void init_options(void)
|
|||
opts.index_block_size = 4096;
|
||||
opts.attr_defs = (ATTR_DEF*)&attrdef_ntfs12_array;
|
||||
opts.attr_defs_len = sizeof(attrdef_ntfs12_array);
|
||||
//Dprintf("Attr_defs table length = %u\n", opts.attr_defs_len);
|
||||
//mkDprintf("Attr_defs table length = %u\n", opts.attr_defs_len);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2668,7 +2669,7 @@ static void mkntfs_override_phys_params(void)
|
|||
err_exit("sector_size is invalid. It must be a power "
|
||||
"of two, and it must be\n greater or equal 256 and "
|
||||
"less than or equal 4096 bytes.\n");
|
||||
Dprintf("sector size = %i bytes\n", opts.sector_size);
|
||||
mkDprintf("sector size = %i bytes\n", opts.sector_size);
|
||||
/* If user didn't specify the number of sectors, determine it now. */
|
||||
if (!opts.nr_sectors) {
|
||||
opts.nr_sectors = ntfs_device_size_get(vol->dev,
|
||||
|
@ -2678,7 +2679,7 @@ static void mkntfs_override_phys_params(void)
|
|||
"specify it manually.\n",
|
||||
vol->dev->d_name);
|
||||
}
|
||||
Dprintf("number of sectors = %lld (0x%llx)\n", opts.nr_sectors,
|
||||
mkDprintf("number of sectors = %lld (0x%llx)\n", opts.nr_sectors,
|
||||
opts.nr_sectors);
|
||||
/* Reserve the last sector for the backup boot sector. */
|
||||
opts.nr_sectors--;
|
||||
|
@ -2763,7 +2764,7 @@ static void mkntfs_override_phys_params(void)
|
|||
if (opts.volume_size < 1 << 20 /* 1MiB */)
|
||||
err_exit("Device is too small (%llikiB). Minimum NTFS volume "
|
||||
"size is 1MiB.\n", opts.volume_size / 1024);
|
||||
Dprintf("volume size = %llikiB\n", opts.volume_size / 1024);
|
||||
mkDprintf("volume size = %llikiB\n", opts.volume_size / 1024);
|
||||
/* If user didn't specify the cluster size, determine it now. */
|
||||
if (!vol->cluster_size) {
|
||||
if (opts.volume_size <= 512LL << 20) /* <= 512MB */
|
||||
|
@ -2801,7 +2802,7 @@ static void mkntfs_override_phys_params(void)
|
|||
"to fit inside eight bits. (We do not support larger "
|
||||
"cluster sizes yet.)\n");
|
||||
vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
|
||||
Dprintf("cluster size = %u bytes\n", (unsigned int)vol->cluster_size);
|
||||
mkDprintf("cluster size = %u bytes\n", (unsigned int)vol->cluster_size);
|
||||
if (vol->cluster_size > 4096) {
|
||||
if (opts.enable_compression) {
|
||||
if (!opts.force)
|
||||
|
@ -2833,7 +2834,7 @@ static void mkntfs_override_phys_params(void)
|
|||
opts.volume_size / vol->cluster_size != opts.nr_clusters)
|
||||
err_exit("Illegal combination of volume/cluster/sector size "
|
||||
"and/or cluster/sector number.\n");
|
||||
Dprintf("number of clusters = %llu (0x%llx)\n", opts.nr_clusters,
|
||||
mkDprintf("number of clusters = %llu (0x%llx)\n", opts.nr_clusters,
|
||||
opts.nr_clusters);
|
||||
/* Number of clusters must fit within 32 bits (Win2k limitation). */
|
||||
if (opts.nr_clusters >> 32) {
|
||||
|
@ -2863,7 +2864,7 @@ static void mkntfs_initialize_bitmaps(void)
|
|||
lcn_bitmap_byte_size = (lcn_bitmap_byte_size + 7) & ~7;
|
||||
i = (lcn_bitmap_byte_size + vol->cluster_size - 1) &
|
||||
~(vol->cluster_size - 1);
|
||||
Dprintf("lcn_bitmap_byte_size = %i, allocated = %i\n",
|
||||
mkDprintf("lcn_bitmap_byte_size = %i, allocated = %i\n",
|
||||
lcn_bitmap_byte_size, i);
|
||||
lcn_bitmap = (unsigned char *)calloc(1, lcn_bitmap_byte_size);
|
||||
if (!lcn_bitmap)
|
||||
|
@ -2881,14 +2882,14 @@ static void mkntfs_initialize_bitmaps(void)
|
|||
*/
|
||||
opts.mft_size = (16 * vol->mft_record_size + vol->cluster_size - 1)
|
||||
& ~(vol->cluster_size - 1);
|
||||
Dprintf("MFT size = %i (0x%x) bytes\n", opts.mft_size, opts.mft_size);
|
||||
mkDprintf("MFT size = %i (0x%x) bytes\n", opts.mft_size, opts.mft_size);
|
||||
/* Determine mft bitmap size and allocate it. */
|
||||
mft_bitmap_size = opts.mft_size / vol->mft_record_size;
|
||||
/* Convert to bytes, at least one. */
|
||||
mft_bitmap_byte_size = (mft_bitmap_size + 7) >> 3;
|
||||
/* Mft bitmap is allocated in multiples of 8 bytes. */
|
||||
mft_bitmap_byte_size = (mft_bitmap_byte_size + 7) & ~7;
|
||||
Dprintf("mft_bitmap_size = %i, mft_bitmap_byte_size = %i\n",
|
||||
mkDprintf("mft_bitmap_size = %i, mft_bitmap_byte_size = %i\n",
|
||||
mft_bitmap_size, mft_bitmap_byte_size);
|
||||
mft_bitmap = (unsigned char *)calloc(1, mft_bitmap_byte_size);
|
||||
if (!mft_bitmap)
|
||||
|
@ -2934,7 +2935,7 @@ static void mkntfs_initialize_rl_mft(void)
|
|||
opts.mft_lcn = (16 * 1024 + vol->cluster_size - 1) /
|
||||
vol->cluster_size;
|
||||
}
|
||||
Dprintf("$MFT logical cluster number = 0x%llx\n", opts.mft_lcn);
|
||||
mkDprintf("$MFT logical cluster number = 0x%llx\n", opts.mft_lcn);
|
||||
/* Determine MFT zone size. */
|
||||
opts.mft_zone_end = opts.nr_clusters;
|
||||
switch (opts.mft_zone_multiplier) { /* % of volume size in clusters */
|
||||
|
@ -2952,7 +2953,7 @@ static void mkntfs_initialize_rl_mft(void)
|
|||
opts.mft_zone_end = opts.mft_zone_end >> 3; /* 12.5% */
|
||||
break;
|
||||
}
|
||||
Dprintf("MFT zone size = %lldkiB\n", opts.mft_zone_end / 1024);
|
||||
mkDprintf("MFT zone size = %lldkiB\n", opts.mft_zone_end / 1024);
|
||||
/*
|
||||
* The mft zone begins with the mft data attribute, not at the beginning
|
||||
* of the device.
|
||||
|
@ -2975,8 +2976,9 @@ static void mkntfs_initialize_rl_mft(void)
|
|||
ntfs_bit_set(lcn_bitmap, opts.mft_lcn + i, 1);
|
||||
/* Determine mftmirr_lcn (middle of volume). */
|
||||
opts.mftmirr_lcn = (opts.nr_sectors * opts.sector_size >> 1)
|
||||
/ vol->cluster_size;
|
||||
Dprintf("$MFTMirr logical cluster number = 0x%llx\n", opts.mftmirr_lcn);
|
||||
/ vol->cluster_size;
|
||||
mkDprintf("$MFTMirr logical cluster number = 0x%llx\n",
|
||||
opts.mftmirr_lcn);
|
||||
/* Create runlist for mft mirror. */
|
||||
rl_mftmirr = (runlist *)malloc(2 * sizeof(runlist));
|
||||
if (!rl_mftmirr)
|
||||
|
@ -2999,7 +3001,8 @@ static void mkntfs_initialize_rl_mft(void)
|
|||
for (i = 0; i < j; i++)
|
||||
ntfs_bit_set(lcn_bitmap, opts.mftmirr_lcn + i, 1);
|
||||
opts.logfile_lcn = opts.mftmirr_lcn + j;
|
||||
Dprintf("$LogFile logical cluster number = 0x%llx\n", opts.logfile_lcn);
|
||||
mkDprintf("$LogFile logical cluster number = 0x%llx\n",
|
||||
opts.logfile_lcn);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3045,7 +3048,8 @@ static void mkntfs_initialize_rl_logfile(void)
|
|||
}
|
||||
opts.logfile_size = (opts.logfile_size + vol->cluster_size - 1) &
|
||||
~(vol->cluster_size - 1);
|
||||
Dprintf("$LogFile (journal) size = %ikiB\n", opts.logfile_size / 1024);
|
||||
mkDprintf("$LogFile (journal) size = %ikiB\n",
|
||||
opts.logfile_size / 1024);
|
||||
/*
|
||||
* FIXME: The 256kiB limit is arbitrary. Should find out what the real
|
||||
* minimum requirement for Windows is so it doesn't blue screen.
|
||||
|
@ -3453,12 +3457,12 @@ static void mkntfs_create_root_structures(void)
|
|||
opts.sector_size);
|
||||
bs->bpb.media_type = 0xf8; /* hard disk */
|
||||
bs->bpb.sectors_per_track = cpu_to_le16(opts.sectors_per_track);
|
||||
Dprintf("sectors per track = %u (0x%x)\n", opts.sectors_per_track,
|
||||
mkDprintf("sectors per track = %u (0x%x)\n", opts.sectors_per_track,
|
||||
opts.sectors_per_track);
|
||||
bs->bpb.heads = cpu_to_le16(opts.heads);
|
||||
Dprintf("heads = %u (0x%x)\n", opts.heads, opts.heads);
|
||||
mkDprintf("heads = %u (0x%x)\n", opts.heads, opts.heads);
|
||||
bs->bpb.hidden_sectors = cpu_to_le32(opts.part_start_sect);
|
||||
Dprintf("hidden sectors = %llu (0x%llx)\n", opts.part_start_sect,
|
||||
mkDprintf("hidden sectors = %llu (0x%llx)\n", opts.part_start_sect,
|
||||
opts.part_start_sect);
|
||||
/*
|
||||
* If there are problems go back to bs->unused[0-3] and set them. See
|
||||
|
@ -3478,7 +3482,7 @@ static void mkntfs_create_root_structures(void)
|
|||
"is wrong (= 0x%x)\n",
|
||||
bs->clusters_per_mft_record);
|
||||
}
|
||||
Dprintf("clusters per mft record = %i (0x%x)\n",
|
||||
mkDprintf("clusters per mft record = %i (0x%x)\n",
|
||||
bs->clusters_per_mft_record,
|
||||
bs->clusters_per_mft_record);
|
||||
if (opts.index_block_size >= (int)vol->cluster_size)
|
||||
|
@ -3492,7 +3496,7 @@ static void mkntfs_create_root_structures(void)
|
|||
"is wrong (= 0x%x)\n",
|
||||
bs->clusters_per_index_record);
|
||||
}
|
||||
Dprintf("clusters per index block = %i (0x%x)\n",
|
||||
mkDprintf("clusters per index block = %i (0x%x)\n",
|
||||
bs->clusters_per_index_record,
|
||||
bs->clusters_per_index_record);
|
||||
/* Generate a 64-bit random number for the serial number. */
|
||||
|
|
|
@ -84,10 +84,11 @@ static struct {
|
|||
} opts;
|
||||
|
||||
/**
|
||||
* Dprintf - debugging output (-vv); overriden by quiet (-q)
|
||||
* mkDprintf - debugging output (-vv); overriden by quiet (-q)
|
||||
*/
|
||||
static void Dprintf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
|
||||
static void Dprintf(const char *fmt, ...)
|
||||
static void mkDprintf(const char *fmt, ...)
|
||||
__attribute__((format(printf, 1, 2)));
|
||||
static void mkDprintf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
|
@ -220,7 +221,7 @@ static void parse_options(int argc, char *argv[])
|
|||
usage();
|
||||
/* Get the device. */
|
||||
dev_name = argv[optind++];
|
||||
Dprintf("device name = %s\n", dev_name);
|
||||
mkDprintf("device name = %s\n", dev_name);
|
||||
if (optind != argc) {
|
||||
/* Get the base mft record number. */
|
||||
ll = strtoll(argv[optind++], &s, 0);
|
||||
|
@ -228,7 +229,7 @@ static void parse_options(int argc, char *argv[])
|
|||
err_exit("Invalid base mft record number: %s\n",
|
||||
argv[optind - 1]);
|
||||
base_mft_no = ll;
|
||||
Dprintf("base mft record number = 0x%llx\n", (long long)ll);
|
||||
mkDprintf("base mft record number = 0x%llx\n", (long long)ll);
|
||||
}
|
||||
if (optind != argc)
|
||||
usage();
|
||||
|
@ -366,7 +367,7 @@ int main(int argc, char **argv)
|
|||
(long long)base_mft_no);
|
||||
printf(".\n");
|
||||
if (!opts.quiet && opts.verbose > 1) {
|
||||
Dprintf("Dumping allocated mft record 0x%llx:\n",
|
||||
mkDprintf("Dumping allocated mft record 0x%llx:\n",
|
||||
(long long)ni->mft_no);
|
||||
dump_mft_record(ni->mrec);
|
||||
}
|
||||
|
|
|
@ -93,10 +93,11 @@ struct {
|
|||
} opts;
|
||||
|
||||
/**
|
||||
* Dprintf - debugging output (-vv); overriden by quiet (-q)
|
||||
* mkDprintf - debugging output (-vv); overriden by quiet (-q)
|
||||
*/
|
||||
static void Dprintf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
|
||||
static void Dprintf(const char *fmt, ...)
|
||||
static void mkDprintf(const char *fmt, ...)
|
||||
__attribute__((format(printf, 1, 2)));
|
||||
static void mkDprintf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
|
@ -233,7 +234,7 @@ static void parse_options(int argc, char *argv[])
|
|||
|
||||
/* Get the device. */
|
||||
dev_name = argv[optind++];
|
||||
Dprintf("device name = %s\n", dev_name);
|
||||
mkDprintf("device name = %s\n", dev_name);
|
||||
|
||||
if (optind == argc)
|
||||
usage();
|
||||
|
@ -243,7 +244,7 @@ static void parse_options(int argc, char *argv[])
|
|||
if (*s || !ll || (ll >= LLONG_MAX && errno == ERANGE))
|
||||
err_exit("Invalid inode number: %s\n", argv[optind - 1]);
|
||||
inode = ll;
|
||||
Dprintf("inode = %lli\n", (long long)inode);
|
||||
mkDprintf("inode = %lli\n", (long long)inode);
|
||||
|
||||
if (optind == argc)
|
||||
usage();
|
||||
|
@ -283,11 +284,11 @@ static void parse_options(int argc, char *argv[])
|
|||
attr_name_len = 0;
|
||||
}
|
||||
}
|
||||
Dprintf("attribute type = 0x%x\n", (unsigned int)attr_type);
|
||||
mkDprintf("attribute type = 0x%x\n", (unsigned int)attr_type);
|
||||
if (attr_name == AT_UNNAMED)
|
||||
Dprintf("attribute name = \"\" (UNNAMED)\n");
|
||||
mkDprintf("attribute name = \"\" (UNNAMED)\n");
|
||||
else
|
||||
Dprintf("attribute name = \"%s\" (length %u Unicode "
|
||||
mkDprintf("attribute name = \"%s\" (length %u Unicode "
|
||||
"characters)\n", s2,
|
||||
(unsigned int)attr_name_len);
|
||||
|
||||
|
@ -296,7 +297,7 @@ static void parse_options(int argc, char *argv[])
|
|||
if (*s2 || ll < 0 || (ll >= LLONG_MAX && errno == ERANGE))
|
||||
err_exit("Invalid new length: %s\n", s);
|
||||
new_len = ll;
|
||||
Dprintf("new length = %lli\n", new_len);
|
||||
mkDprintf("new length = %lli\n", new_len);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -791,7 +792,7 @@ int main(int argc, char **argv)
|
|||
(unsigned int)attr_type, strerror(errno));
|
||||
|
||||
if (!opts.quiet && opts.verbose > 1) {
|
||||
Dprintf("Dumping mft record before calling "
|
||||
mkDprintf("Dumping mft record before calling "
|
||||
"ntfs_attr_truncate():\n");
|
||||
dump_mft_record(ni->mrec);
|
||||
}
|
||||
|
@ -803,7 +804,7 @@ int main(int argc, char **argv)
|
|||
(unsigned int)attr_type, strerror(errno));
|
||||
|
||||
if (!opts.quiet && opts.verbose > 1) {
|
||||
Dprintf("Dumping mft record after calling "
|
||||
mkDprintf("Dumping mft record after calling "
|
||||
"ntfs_attr_truncate():\n");
|
||||
dump_mft_record(ni->mrec);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue