diff --git a/include/ntfs/attrib.h b/include/ntfs/attrib.h index 0918b0ce..0597f493 100644 --- a/include/ntfs/attrib.h +++ b/include/ntfs/attrib.h @@ -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 diff --git a/include/ntfs/inode.h b/include/ntfs/inode.h index b251fc48..4b9c2c48 100644 --- a/include/ntfs/inode.h +++ b/include/ntfs/inode.h @@ -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 */ - diff --git a/include/ntfs/volume.h b/include/ntfs/volume.h index 6fb3be5d..23f57bec 100644 --- a/include/ntfs/volume.h +++ b/include/ntfs/volume.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. diff --git a/libntfs/attrib.c b/libntfs/attrib.c index a3e2767a..61be9484 100644 --- a/libntfs/attrib.c +++ b/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; +} diff --git a/libntfs/inode.c b/libntfs/inode.c index 841b873a..89c506d5 100644 --- a/libntfs/inode.c +++ b/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; -} diff --git a/ntfsprogs/mkntfs.c b/ntfsprogs/mkntfs.c index 7ced1c7f..a58498c6 100644 --- a/ntfsprogs/mkntfs.c +++ b/ntfsprogs/mkntfs.c @@ -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. */ diff --git a/ntfsprogs/ntfsmftalloc.c b/ntfsprogs/ntfsmftalloc.c index 5da3bbbc..6e75ed29 100644 --- a/ntfsprogs/ntfsmftalloc.c +++ b/ntfsprogs/ntfsmftalloc.c @@ -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); } diff --git a/ntfsprogs/ntfstruncate.c b/ntfsprogs/ntfstruncate.c index 4bf5e8cc..f0e0ba0b 100644 --- a/ntfsprogs/ntfstruncate.c +++ b/ntfsprogs/ntfstruncate.c @@ -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); }