new: use tabulated logging; add ntfs_log_enter() and ntfs_log_leave()
and convert the most commonly used functionsmaster
parent
dec6162b63
commit
c6e1991749
|
@ -76,6 +76,8 @@ int ntfs_log_redirect(const char *function, const char *file, int line,
|
|||
#define NTFS_LOG_LEVEL_ERROR (1 << 7) /* Operation failed, no damage done */
|
||||
#define NTFS_LOG_LEVEL_PERROR (1 << 8) /* Message : standard error description */
|
||||
#define NTFS_LOG_LEVEL_CRITICAL (1 << 9) /* Operation failed,damage may have occurred */
|
||||
#define NTFS_LOG_LEVEL_ENTER (1 << 10) /* Enter a function */
|
||||
#define NTFS_LOG_LEVEL_LEAVE (1 << 11) /* Leave a function */
|
||||
|
||||
/* Logging style flags - Manage the style of the output */
|
||||
#define NTFS_LOG_FLAG_PREFIX (1 << 0) /* Prefix messages with "ERROR: ", etc */
|
||||
|
@ -103,9 +105,13 @@ int ntfs_log_redirect(const char *function, const char *file, int line,
|
|||
#ifdef DEBUG
|
||||
#define ntfs_log_debug(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_DEBUG,NULL,FORMAT,##ARGS)
|
||||
#define ntfs_log_trace(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_TRACE,NULL,FORMAT,##ARGS)
|
||||
#define ntfs_log_enter(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_ENTER,NULL,FORMAT,##ARGS)
|
||||
#define ntfs_log_leave(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_LEAVE,NULL,FORMAT,##ARGS)
|
||||
#else
|
||||
#define ntfs_log_debug(FORMAT, ARGS...)do {} while (0)
|
||||
#define ntfs_log_trace(FORMAT, ARGS...)do {} while (0)
|
||||
#define ntfs_log_enter(FORMAT, ARGS...)do {} while (0)
|
||||
#define ntfs_log_leave(FORMAT, ARGS...)do {} while (0)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#endif /* _LOGGING_H_ */
|
||||
|
|
|
@ -49,7 +49,12 @@ extern int ntfs_mft_records_read(const ntfs_volume *vol, const MFT_REF mref,
|
|||
static __inline__ int ntfs_mft_record_read(const ntfs_volume *vol,
|
||||
const MFT_REF mref, MFT_RECORD *b)
|
||||
{
|
||||
return ntfs_mft_records_read(vol, mref, 1, b);
|
||||
int ret;
|
||||
|
||||
ntfs_log_enter("Entering for inode %lld\n", MREF(mref));
|
||||
ret = ntfs_mft_records_read(vol, mref, 1, b);
|
||||
ntfs_log_leave("\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern int ntfs_mft_record_check(const ntfs_volume *vol, const MFT_REF mref,
|
||||
|
@ -79,7 +84,12 @@ extern int ntfs_mft_records_write(const ntfs_volume *vol, const MFT_REF mref,
|
|||
static __inline__ int ntfs_mft_record_write(const ntfs_volume *vol,
|
||||
const MFT_REF mref, MFT_RECORD *b)
|
||||
{
|
||||
return ntfs_mft_records_write(vol, mref, 1, b);
|
||||
int ret;
|
||||
|
||||
ntfs_log_enter("Entering for inode %lld\n", MREF(mref));
|
||||
ret = ntfs_mft_records_write(vol, mref, 1, b);
|
||||
ntfs_log_leave("\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -374,19 +374,20 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
|
|||
ntfschar *name, u32 name_len)
|
||||
{
|
||||
ntfs_attr_search_ctx *ctx;
|
||||
ntfs_attr *na;
|
||||
ntfs_attr *na = NULL;
|
||||
ATTR_RECORD *a;
|
||||
BOOL cs;
|
||||
|
||||
ntfs_log_trace("Entering for inode %lld, attr 0x%x.\n",
|
||||
(unsigned long long)ni->mft_no, type);
|
||||
ntfs_log_enter("Entering for inode %lld, attr 0x%x.\n",
|
||||
(unsigned long long)ni->mft_no, type);
|
||||
|
||||
if (!ni || !ni->vol || !ni->mrec) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
na = calloc(sizeof(ntfs_attr), 1);
|
||||
if (!na)
|
||||
return NULL;
|
||||
goto out;
|
||||
if (name && name != AT_UNNAMED && name != NTFS_INDEX_I30) {
|
||||
name = ntfs_ucsndup(name, name_len);
|
||||
if (!name)
|
||||
|
@ -462,12 +463,16 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
|
|||
cs ? (l + 7) & ~7 : 0, 0);
|
||||
}
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
out:
|
||||
ntfs_log_leave("\n");
|
||||
return na;
|
||||
|
||||
put_err_out:
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
err_out:
|
||||
free(na);
|
||||
return NULL;
|
||||
na = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -772,46 +777,16 @@ map_rl:
|
|||
}
|
||||
|
||||
/**
|
||||
* ntfs_attr_pread - read from an attribute specified by an ntfs_attr structure
|
||||
* @na: ntfs attribute to read from
|
||||
* @pos: byte position in the attribute to begin reading from
|
||||
* @count: number of bytes to read
|
||||
* @b: output data buffer
|
||||
*
|
||||
* This function will read @count bytes starting at offset @pos from the ntfs
|
||||
* attribute @na into the data buffer @b.
|
||||
*
|
||||
* On success, return the number of successfully read bytes. If this number is
|
||||
* lower than @count this means that the read reached end of file or that an
|
||||
* error was encountered during the read so that the read is partial. 0 means
|
||||
* end of file or nothing was read (also return 0 when @count is 0).
|
||||
*
|
||||
* On error and nothing has been read, return -1 with errno set appropriately
|
||||
* to the return code of ntfs_pread(), or to EINVAL in case of invalid
|
||||
* arguments.
|
||||
*/
|
||||
s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count, void *b)
|
||||
* ntfs_attr_pread_i - see description at ntfs_attr_pread()
|
||||
*/
|
||||
static s64 ntfs_attr_pread_i(ntfs_attr *na, const s64 pos, s64 count, void *b)
|
||||
{
|
||||
s64 br, to_read, ofs, total, total2;
|
||||
ntfs_volume *vol;
|
||||
runlist_element *rl;
|
||||
|
||||
if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) {
|
||||
errno = EINVAL;
|
||||
ntfs_log_perror("%s: na=%p b=%p pos=%lld count=%lld",
|
||||
__FUNCTION__, na, b, (long long)pos,
|
||||
(long long)count);
|
||||
return -1;
|
||||
}
|
||||
/* Sanity checking arguments is done in ntfs_attr_pread(). */
|
||||
|
||||
ntfs_log_trace("Entering for inode %lld attr 0x%x pos %lld count "
|
||||
"%lld flags: 0x%x\n", (unsigned long long)na->ni->mft_no,
|
||||
na->type, (long long)pos, (long long)count, na->ni->flags);
|
||||
|
||||
/*
|
||||
* If this is a compressed attribute it needs special treatment, but
|
||||
* only if it is non-resident.
|
||||
*/
|
||||
if (NAttrCompressed(na) && NAttrNonResident(na))
|
||||
return ntfs_compressed_attr_pread(na, pos, count, b);
|
||||
/*
|
||||
|
@ -959,6 +934,47 @@ rl_err_out:
|
|||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_attr_pread - read from an attribute specified by an ntfs_attr structure
|
||||
* @na: ntfs attribute to read from
|
||||
* @pos: byte position in the attribute to begin reading from
|
||||
* @count: number of bytes to read
|
||||
* @b: output data buffer
|
||||
*
|
||||
* This function will read @count bytes starting at offset @pos from the ntfs
|
||||
* attribute @na into the data buffer @b.
|
||||
*
|
||||
* On success, return the number of successfully read bytes. If this number is
|
||||
* lower than @count this means that the read reached end of file or that an
|
||||
* error was encountered during the read so that the read is partial. 0 means
|
||||
* end of file or nothing was read (also return 0 when @count is 0).
|
||||
*
|
||||
* On error and nothing has been read, return -1 with errno set appropriately
|
||||
* to the return code of ntfs_pread(), or to EINVAL in case of invalid
|
||||
* arguments.
|
||||
*/
|
||||
s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count, void *b)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) {
|
||||
errno = EINVAL;
|
||||
ntfs_log_perror("%s: na=%p b=%p pos=%lld count=%lld",
|
||||
__FUNCTION__, na, b, (long long)pos,
|
||||
(long long)count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ntfs_log_enter("Entering for inode %lld attr 0x%x pos %lld count "
|
||||
"%lld\n", (unsigned long long)na->ni->mft_no,
|
||||
na->type, (long long)pos, (long long)count);
|
||||
|
||||
ret = ntfs_attr_pread_i(na, pos, count, b);
|
||||
|
||||
ntfs_log_leave("\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ntfs_attr_fill_zero(ntfs_attr *na, s64 pos, s64 count)
|
||||
{
|
||||
char *buf;
|
||||
|
@ -1148,9 +1164,10 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
|
|||
unsigned int undo_data_size : 1;
|
||||
} need_to = { 0, 0 };
|
||||
|
||||
ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, pos 0x%llx, count "
|
||||
ntfs_log_enter("Entering for inode 0x%llx, attr 0x%x, pos 0x%llx, count "
|
||||
"0x%llx.\n", na->ni->mft_no, na->type, (long long)pos,
|
||||
(long long)count);
|
||||
|
||||
if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) {
|
||||
errno = EINVAL;
|
||||
ntfs_log_perror("%s", __FUNCTION__);
|
||||
|
@ -1387,9 +1404,11 @@ done:
|
|||
* FIXME: trying to recover by goto rl_err_out;
|
||||
* could cause driver hang by infinite looping.
|
||||
*/
|
||||
return -1;
|
||||
total = -1;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
ntfs_log_leave("\n");
|
||||
return total;
|
||||
rl_err_out:
|
||||
eo = errno;
|
||||
|
@ -1900,7 +1919,7 @@ static int ntfs_external_attr_find(ATTR_TYPES type, const ntfschar *name,
|
|||
|
||||
ni = ctx->ntfs_ino;
|
||||
base_ni = ctx->base_ntfs_ino;
|
||||
ntfs_log_trace("Entering for inode 0x%llx, attribute type 0x%x.\n",
|
||||
ntfs_log_trace("Entering for inode %lld, attribute type 0x%x.\n",
|
||||
(unsigned long long)ni->mft_no, type);
|
||||
if (!base_ni) {
|
||||
/* First call happens with the base mft record. */
|
||||
|
@ -2299,22 +2318,29 @@ int ntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name,
|
|||
{
|
||||
ntfs_volume *vol;
|
||||
ntfs_inode *base_ni;
|
||||
int ret = -1;
|
||||
|
||||
ntfs_log_enter("Entering for attribute type 0x%x\n", type);
|
||||
|
||||
if (!ctx || !ctx->mrec || !ctx->attr || (name && name != AT_UNNAMED &&
|
||||
(!ctx->ntfs_ino || !(vol = ctx->ntfs_ino->vol) ||
|
||||
!vol->upcase || !vol->upcase_len))) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ctx->base_ntfs_ino)
|
||||
base_ni = ctx->base_ntfs_ino;
|
||||
else
|
||||
base_ni = ctx->ntfs_ino;
|
||||
if (!base_ni || !NInoAttrList(base_ni) || type == AT_ATTRIBUTE_LIST)
|
||||
return ntfs_attr_find(type, name, name_len, ic, val, val_len,
|
||||
ctx);
|
||||
return ntfs_external_attr_find(type, name, name_len, ic, lowest_vcn,
|
||||
val, val_len, ctx);
|
||||
ret = ntfs_attr_find(type, name, name_len, ic, val, val_len, ctx);
|
||||
else
|
||||
ret = ntfs_external_attr_find(type, name, name_len, ic,
|
||||
lowest_vcn, val, val_len, ctx);
|
||||
out:
|
||||
ntfs_log_leave("\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3617,10 +3643,8 @@ static int ntfs_attr_make_non_resident(ntfs_attr *na,
|
|||
/* Start by allocating clusters to hold the attribute value. */
|
||||
rl = ntfs_cluster_alloc(vol, 0, new_allocated_size >>
|
||||
vol->cluster_size_bits, -1, DATA_ZONE);
|
||||
if (!rl) {
|
||||
ntfs_log_perror("Failed to allocate clusters");
|
||||
if (!rl)
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
rl = NULL;
|
||||
/*
|
||||
|
@ -4233,31 +4257,9 @@ error: ret = -3; goto out;
|
|||
|
||||
#define NTFS_VCN_DELETE_MARK -2
|
||||
/**
|
||||
* ntfs_attr_update_mapping_pairs - update mapping pairs for ntfs attribute
|
||||
* @na: non-resident ntfs open attribute for which we need update
|
||||
* @from_vcn: update runlist starting this VCN
|
||||
*
|
||||
* Build mapping pairs from @na->rl and write them to the disk. Also, this
|
||||
* function updates sparse bit, allocated and compressed size (allocates/frees
|
||||
* space for this field if required).
|
||||
*
|
||||
* @na->allocated_size should be set to correct value for the new runlist before
|
||||
* call to this function. Vice-versa @na->compressed_size will be calculated and
|
||||
* set to correct value during this function.
|
||||
*
|
||||
* FIXME: This function does not update sparse bit and compressed size correctly
|
||||
* if called with @from_vcn != 0.
|
||||
*
|
||||
* FIXME: Rewrite without using NTFS_VCN_DELETE_MARK define.
|
||||
*
|
||||
* On success return 0 and on error return -1 with errno set to the error code.
|
||||
* The following error codes are defined:
|
||||
* EINVAL - Invalid arguments passed.
|
||||
* ENOMEM - Not enough memory to complete operation.
|
||||
* ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST
|
||||
* or there is no free MFT records left to allocate.
|
||||
* ntfs_attr_update_mapping_pairs_i - see ntfs_attr_update_mapping_pairs
|
||||
*/
|
||||
int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn)
|
||||
static int ntfs_attr_update_mapping_pairs_i(ntfs_attr *na, VCN from_vcn)
|
||||
{
|
||||
ntfs_attr_search_ctx *ctx;
|
||||
ntfs_inode *ni, *base_ni;
|
||||
|
@ -4547,6 +4549,41 @@ put_err_out:
|
|||
}
|
||||
#undef NTFS_VCN_DELETE_MARK
|
||||
|
||||
/**
|
||||
* ntfs_attr_update_mapping_pairs - update mapping pairs for ntfs attribute
|
||||
* @na: non-resident ntfs open attribute for which we need update
|
||||
* @from_vcn: update runlist starting this VCN
|
||||
*
|
||||
* Build mapping pairs from @na->rl and write them to the disk. Also, this
|
||||
* function updates sparse bit, allocated and compressed size (allocates/frees
|
||||
* space for this field if required).
|
||||
*
|
||||
* @na->allocated_size should be set to correct value for the new runlist before
|
||||
* call to this function. Vice-versa @na->compressed_size will be calculated and
|
||||
* set to correct value during this function.
|
||||
*
|
||||
* FIXME: This function does not update sparse bit and compressed size correctly
|
||||
* if called with @from_vcn != 0.
|
||||
*
|
||||
* FIXME: Rewrite without using NTFS_VCN_DELETE_MARK define.
|
||||
*
|
||||
* On success return 0 and on error return -1 with errno set to the error code.
|
||||
* The following error codes are defined:
|
||||
* EINVAL - Invalid arguments passed.
|
||||
* ENOMEM - Not enough memory to complete operation.
|
||||
* ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST
|
||||
* or there is no free MFT records left to allocate.
|
||||
*/
|
||||
int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ntfs_log_enter("Entering\n");
|
||||
ret = ntfs_attr_update_mapping_pairs_i(na, from_vcn);
|
||||
ntfs_log_leave("\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_non_resident_attr_shrink - shrink a non-resident, open ntfs attribute
|
||||
* @na: non-resident ntfs attribute to shrink
|
||||
|
@ -4980,12 +5017,12 @@ void *ntfs_attr_readall(ntfs_inode *ni, const ATTR_TYPES type,
|
|||
void *data, *ret = NULL;
|
||||
s64 size;
|
||||
|
||||
ntfs_log_trace("Entering\n");
|
||||
ntfs_log_enter("Entering\n");
|
||||
|
||||
na = ntfs_attr_open(ni, type, name, name_len);
|
||||
if (!na) {
|
||||
ntfs_log_perror("ntfs_attr_open failed");
|
||||
return NULL;
|
||||
goto err_exit;
|
||||
}
|
||||
data = ntfs_malloc(na->data_size);
|
||||
if (!data)
|
||||
|
@ -5002,6 +5039,8 @@ void *ntfs_attr_readall(ntfs_inode *ni, const ATTR_TYPES type,
|
|||
*data_size = size;
|
||||
out:
|
||||
ntfs_attr_close(na);
|
||||
err_exit:
|
||||
ntfs_log_leave("\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -265,7 +265,13 @@ free_err_out:
|
|||
*/
|
||||
int ntfs_bitmap_set_run(ntfs_attr *na, s64 start_bit, s64 count)
|
||||
{
|
||||
return ntfs_bitmap_set_bits_in_run(na, start_bit, count, 1);
|
||||
int ret;
|
||||
|
||||
ntfs_log_enter("Set from bit %lld, count %lld\n",
|
||||
(long long)start_bit, (long long)count);
|
||||
ret = ntfs_bitmap_set_bits_in_run(na, start_bit, count, 1);
|
||||
ntfs_log_leave("\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -281,9 +287,12 @@ int ntfs_bitmap_set_run(ntfs_attr *na, s64 start_bit, s64 count)
|
|||
*/
|
||||
int ntfs_bitmap_clear_run(ntfs_attr *na, s64 start_bit, s64 count)
|
||||
{
|
||||
ntfs_log_trace("Dealloc from bit 0x%llx, count 0x%llx.\n",
|
||||
int ret;
|
||||
|
||||
ntfs_log_enter("Clear from bit %lld, count %lld\n",
|
||||
(long long)start_bit, (long long)count);
|
||||
|
||||
return ntfs_bitmap_set_bits_in_run(na, start_bit, count, 0);
|
||||
ret = ntfs_bitmap_set_bits_in_run(na, start_bit, count, 0);
|
||||
ntfs_log_leave("\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -152,18 +152,18 @@ static void __ntfs_inode_release(ntfs_inode *ni)
|
|||
ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref)
|
||||
{
|
||||
s64 l;
|
||||
ntfs_inode *ni;
|
||||
ntfs_inode *ni = NULL;
|
||||
ntfs_attr_search_ctx *ctx;
|
||||
STANDARD_INFORMATION *std_info;
|
||||
|
||||
ntfs_log_trace("Entering for inode 0x%llx.\n", MREF(mref));
|
||||
ntfs_log_enter("Entering for inode %lld\n", MREF(mref));
|
||||
if (!vol) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
ni = __ntfs_inode_allocate(vol);
|
||||
if (!ni)
|
||||
return NULL;
|
||||
goto out;
|
||||
if (ntfs_file_record_read(vol, mref, &ni->mrec, NULL))
|
||||
goto err_out;
|
||||
if (!(ni->mrec->flags & MFT_RECORD_IN_USE)) {
|
||||
|
@ -237,12 +237,16 @@ get_size:
|
|||
}
|
||||
}
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
out:
|
||||
ntfs_log_leave("\n");
|
||||
return ni;
|
||||
|
||||
put_err_out:
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
err_out:
|
||||
__ntfs_inode_release(ni);
|
||||
return NULL;
|
||||
ni = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -269,17 +273,19 @@ err_out:
|
|||
*/
|
||||
int ntfs_inode_close(ntfs_inode *ni)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
if (!ni)
|
||||
return 0;
|
||||
|
||||
ntfs_log_trace("Entering for inode 0x%llx.\n", (long long)ni->mft_no);
|
||||
ntfs_log_enter("Entering for inode %lld\n", (long long)ni->mft_no);
|
||||
|
||||
/* If we have dirty metadata, write it out. */
|
||||
if (NInoDirty(ni) || NInoAttrListDirty(ni)) {
|
||||
if (ntfs_inode_sync(ni)) {
|
||||
if (errno != EIO)
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
/* Is this a base inode with mapped extent inodes? */
|
||||
|
@ -288,7 +294,7 @@ int ntfs_inode_close(ntfs_inode *ni)
|
|||
if (ntfs_inode_close(ni->extent_nis[0])) {
|
||||
if (errno != EIO)
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
} else if (ni->nr_extents == -1) {
|
||||
|
@ -342,7 +348,10 @@ int ntfs_inode_close(ntfs_inode *ni)
|
|||
}
|
||||
|
||||
__ntfs_inode_release(ni);
|
||||
return 0;
|
||||
ret = 0;
|
||||
err:
|
||||
ntfs_log_leave("\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -373,7 +382,7 @@ int ntfs_inode_close(ntfs_inode *ni)
|
|||
ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref)
|
||||
{
|
||||
u64 mft_no = MREF_LE(mref);
|
||||
ntfs_inode *ni;
|
||||
ntfs_inode *ni = NULL;
|
||||
ntfs_inode **extent_nis;
|
||||
int i;
|
||||
|
||||
|
@ -383,7 +392,7 @@ ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ntfs_log_trace("Opening extent inode 0x%llx (base mft record 0x%llx).\n",
|
||||
ntfs_log_enter("Opening extent inode %lld (base mft record %lld).\n",
|
||||
(unsigned long long)mft_no,
|
||||
(unsigned long long)base_ni->mft_no);
|
||||
|
||||
|
@ -404,15 +413,15 @@ ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref)
|
|||
ntfs_log_perror("Found stale extent mft "
|
||||
"reference mft=%lld",
|
||||
(long long)ni->mft_no);
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
return ni;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/* Wasn't there, we need to load the extent inode. */
|
||||
ni = __ntfs_inode_allocate(base_ni->vol);
|
||||
if (!ni)
|
||||
return NULL;
|
||||
goto out;
|
||||
if (ntfs_file_record_read(base_ni->vol, le64_to_cpu(mref), &ni->mrec,
|
||||
NULL)) {
|
||||
ntfs_log_perror("ntfs_file_record_read failed #2");
|
||||
|
@ -436,10 +445,13 @@ ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref)
|
|||
base_ni->extent_nis = extent_nis;
|
||||
}
|
||||
base_ni->extent_nis[base_ni->nr_extents++] = ni;
|
||||
out:
|
||||
ntfs_log_leave("\n");
|
||||
return ni;
|
||||
err_out:
|
||||
__ntfs_inode_release(ni);
|
||||
return NULL;
|
||||
ni = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -656,6 +668,7 @@ err_out:
|
|||
*/
|
||||
int ntfs_inode_sync(ntfs_inode *ni)
|
||||
{
|
||||
int ret = 0;
|
||||
int err = 0;
|
||||
|
||||
if (!ni) {
|
||||
|
@ -664,7 +677,7 @@ int ntfs_inode_sync(ntfs_inode *ni)
|
|||
return -1;
|
||||
}
|
||||
|
||||
ntfs_log_trace("Entering for inode %lld\n", (long long)ni->mft_no);
|
||||
ntfs_log_enter("Entering for inode %lld\n", (long long)ni->mft_no);
|
||||
|
||||
/* Update STANDARD_INFORMATION. */
|
||||
if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 &&
|
||||
|
@ -775,10 +788,13 @@ sync_inode:
|
|||
}
|
||||
}
|
||||
|
||||
if (!err)
|
||||
return 0;
|
||||
errno = err;
|
||||
return -1;
|
||||
if (err) {
|
||||
errno = err;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
ntfs_log_leave("\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -195,16 +195,17 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
|
|||
u8 has_guess, used_zone_pos;
|
||||
int err = 0, rlpos, rlsize, buf_size;
|
||||
|
||||
ntfs_log_trace("Entering with count = 0x%llx, start_lcn = 0x%llx, "
|
||||
ntfs_log_enter("Entering with count = 0x%llx, start_lcn = 0x%llx, "
|
||||
"zone = %s_ZONE.\n", (long long)count, (long long)
|
||||
start_lcn, zone == MFT_ZONE ? "MFT" : "DATA");
|
||||
|
||||
if (!vol || count < 0 || start_lcn < -1 || !vol->lcnbmp_na ||
|
||||
(s8)zone < FIRST_ZONE || zone > LAST_ZONE) {
|
||||
errno = EINVAL;
|
||||
ntfs_log_perror("%s: vcn: %lld, count: %lld, lcn: %lld",
|
||||
__FUNCTION__, (long long)start_vcn,
|
||||
(long long)count, (long long)start_lcn);
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Return empty runlist if @count == 0 */
|
||||
|
@ -215,12 +216,12 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
|
|||
rl[0].lcn = LCN_RL_NOT_MAPPED;
|
||||
rl[0].length = 0;
|
||||
}
|
||||
return rl;
|
||||
goto out;
|
||||
}
|
||||
|
||||
buf = ntfs_malloc(NTFS_LCNALLOC_BSIZE);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
goto out;
|
||||
/*
|
||||
* If no @start_lcn was requested, use the current zone
|
||||
* position otherwise use the requested @start_lcn.
|
||||
|
@ -322,20 +323,30 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
|
|||
* Coalesce with previous run if adjacent LCNs.
|
||||
* Otherwise, append a new run.
|
||||
*/
|
||||
if (prev_lcn == lcn + bmp_pos - prev_run_len && rlpos)
|
||||
if (prev_lcn == lcn + bmp_pos - prev_run_len && rlpos) {
|
||||
ntfs_log_debug("Cluster coalesce: prev_lcn: "
|
||||
"%lld lcn: %lld bmp_pos: %lld "
|
||||
"prev_run_len: %lld\n", prev_lcn,
|
||||
lcn, bmp_pos, prev_run_len);
|
||||
rl[rlpos - 1].length = ++prev_run_len;
|
||||
else {
|
||||
} else {
|
||||
if (rlpos)
|
||||
rl[rlpos].vcn = rl[rlpos - 1].vcn +
|
||||
prev_run_len;
|
||||
else
|
||||
else {
|
||||
rl[rlpos].vcn = start_vcn;
|
||||
ntfs_log_debug("Start_vcn: %lld\n",
|
||||
start_vcn);
|
||||
}
|
||||
|
||||
rl[rlpos].lcn = prev_lcn = lcn + bmp_pos;
|
||||
rl[rlpos].length = prev_run_len = 1;
|
||||
rlpos++;
|
||||
}
|
||||
|
||||
ntfs_log_debug("RUN: %-16lld %-16lld %-16lld\n",
|
||||
rl[rlpos - 1].vcn, rl[rlpos - 1].lcn,
|
||||
rl[rlpos - 1].length);
|
||||
/* Done? */
|
||||
if (!--clusters) {
|
||||
if (used_zone_pos)
|
||||
|
@ -467,13 +478,15 @@ done_ret:
|
|||
goto err_ret;
|
||||
}
|
||||
done_err_ret:
|
||||
ntfs_log_debug("At done_err_ret (follows done_ret).\n");
|
||||
free(buf);
|
||||
if (!err)
|
||||
return rl;
|
||||
ntfs_log_trace("Failed to allocate clusters (%d)", errno);
|
||||
errno = err;
|
||||
return NULL;
|
||||
if (err) {
|
||||
errno = err;
|
||||
ntfs_log_perror("Failed to allocate clusters");
|
||||
rl = NULL;
|
||||
}
|
||||
out:
|
||||
ntfs_log_leave("\n");
|
||||
return rl;
|
||||
|
||||
wb_err_ret:
|
||||
ntfs_log_trace("At wb_err_ret.\n");
|
||||
|
@ -486,6 +499,7 @@ err_ret:
|
|||
rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
|
||||
rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
|
||||
rl[rlpos].length = 0;
|
||||
ntfs_debug_runlist_dump(rl);
|
||||
ntfs_cluster_free_from_rl(vol, rl);
|
||||
free(rl);
|
||||
rl = NULL;
|
||||
|
@ -563,22 +577,23 @@ int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count)
|
|||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, count 0x%llx, "
|
||||
|
||||
ntfs_log_enter("Entering for inode 0x%llx, attr 0x%x, count 0x%llx, "
|
||||
"vcn 0x%llx.\n", (unsigned long long)na->ni->mft_no,
|
||||
na->type, (long long)count, (long long)start_vcn);
|
||||
|
||||
rl = ntfs_attr_find_vcn(na, start_vcn);
|
||||
if (!rl) {
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
return -1;
|
||||
ret = 0;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (rl->lcn < 0 && rl->lcn != LCN_HOLE) {
|
||||
errno = EIO;
|
||||
ntfs_log_perror("%s: Unexpected lcn (%lld)", __FUNCTION__,
|
||||
(long long)rl->lcn);
|
||||
return -1;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Find the starting cluster inside the run that needs freeing. */
|
||||
|
@ -593,7 +608,7 @@ int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count)
|
|||
/* Do the actual freeing of the clusters in this run. */
|
||||
if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn + delta,
|
||||
to_free))
|
||||
return -1;
|
||||
goto leave;
|
||||
nr_freed = to_free;
|
||||
}
|
||||
|
||||
|
@ -652,5 +667,7 @@ out:
|
|||
ntfs_log_error("Too many free clusters (%lld > %lld)!",
|
||||
(long long)vol->free_clusters,
|
||||
(long long)vol->nr_clusters);
|
||||
leave:
|
||||
ntfs_log_leave("\n");
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -58,6 +58,10 @@ static const char *col_red = "\e[01;31m";
|
|||
static const char *col_redinv = "\e[01;07;31m";
|
||||
static const char *col_end = "\e[0m";
|
||||
|
||||
#ifdef DEBUG
|
||||
static int tab;
|
||||
#endif
|
||||
|
||||
/* Some gcc 3.x, 4.[01].X crash with internal compiler error. */
|
||||
#if __GNUC__ <= 3 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 1)
|
||||
# define BROKEN_GCC_FORMAT_ATTRIBUTE
|
||||
|
@ -83,7 +87,8 @@ struct ntfs_logging {
|
|||
*/
|
||||
static struct ntfs_logging ntfs_log = {
|
||||
#ifdef DEBUG
|
||||
NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE |
|
||||
NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE | NTFS_LOG_LEVEL_ENTER |
|
||||
NTFS_LOG_LEVEL_LEAVE |
|
||||
#endif
|
||||
NTFS_LOG_LEVEL_INFO | NTFS_LOG_LEVEL_QUIET | NTFS_LOG_LEVEL_WARNING |
|
||||
NTFS_LOG_LEVEL_ERROR | NTFS_LOG_LEVEL_PERROR | NTFS_LOG_LEVEL_CRITICAL |
|
||||
|
@ -214,6 +219,8 @@ static FILE * ntfs_log_get_stream(u32 level)
|
|||
|
||||
case NTFS_LOG_LEVEL_DEBUG:
|
||||
case NTFS_LOG_LEVEL_TRACE:
|
||||
case NTFS_LOG_LEVEL_ENTER:
|
||||
case NTFS_LOG_LEVEL_LEAVE:
|
||||
case NTFS_LOG_LEVEL_WARNING:
|
||||
case NTFS_LOG_LEVEL_ERROR:
|
||||
case NTFS_LOG_LEVEL_CRITICAL:
|
||||
|
@ -413,6 +420,9 @@ out:
|
|||
int ntfs_log_handler_fprintf(const char *function, const char *file,
|
||||
int line, u32 level, void *data, const char *format, va_list args)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
int i;
|
||||
#endif
|
||||
int ret = 0;
|
||||
int olderr = errno;
|
||||
FILE *stream;
|
||||
|
@ -423,6 +433,13 @@ int ntfs_log_handler_fprintf(const char *function, const char *file,
|
|||
return 0; /* If it's NULL, we can't do anything. */
|
||||
stream = (FILE*)data;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (level == NTFS_LOG_LEVEL_LEAVE) {
|
||||
if (tab)
|
||||
tab--;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (ntfs_log.flags & NTFS_LOG_FLAG_COLOUR) {
|
||||
/* Pick a colour determined by the log level */
|
||||
switch (level) {
|
||||
|
@ -449,7 +466,11 @@ int ntfs_log_handler_fprintf(const char *function, const char *file,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
for (i = 0; i < tab; i++)
|
||||
ret += fprintf(stream, " ");
|
||||
#endif
|
||||
if (col_prefix)
|
||||
ret += fprintf(stream, col_prefix);
|
||||
|
||||
|
@ -467,7 +488,7 @@ int ntfs_log_handler_fprintf(const char *function, const char *file,
|
|||
ret += fprintf(stream, "(%d) ", line);
|
||||
|
||||
if ((ntfs_log.flags & NTFS_LOG_FLAG_FUNCTION) || /* Source function */
|
||||
(level & NTFS_LOG_LEVEL_TRACE))
|
||||
(level & NTFS_LOG_LEVEL_TRACE) || (level & NTFS_LOG_LEVEL_ENTER))
|
||||
ret += fprintf(stream, "%s(): ", function);
|
||||
|
||||
ret += vfprintf(stream, format, args);
|
||||
|
@ -478,7 +499,10 @@ int ntfs_log_handler_fprintf(const char *function, const char *file,
|
|||
if (col_suffix)
|
||||
ret += fprintf(stream, col_suffix);
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
if (level == NTFS_LOG_LEVEL_ENTER)
|
||||
tab++;
|
||||
#endif
|
||||
fflush(stream);
|
||||
errno = olderr;
|
||||
return ret;
|
||||
|
|
|
@ -147,7 +147,6 @@ int ntfs_mft_records_write(const ntfs_volume *vol, const MFT_REF mref,
|
|||
void *bmirr = NULL;
|
||||
int cnt = 0, res = 0;
|
||||
|
||||
ntfs_log_trace("Entering for inode 0x%llx.\n", MREF(mref));
|
||||
if (!vol || !vol->mft_na || vol->mftmirr_size <= 0 || !b || count < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
|
@ -410,9 +409,11 @@ int ntfs_mft_record_format(const ntfs_volume *vol, const MFT_REF mref)
|
|||
MFT_RECORD *m;
|
||||
int ret = -1;
|
||||
|
||||
ntfs_log_enter("Entering\n");
|
||||
|
||||
m = ntfs_calloc(vol->mft_record_size);
|
||||
if (!m)
|
||||
return -1;
|
||||
goto out;
|
||||
|
||||
if (ntfs_mft_record_layout(vol, mref, m))
|
||||
goto free_m;
|
||||
|
@ -423,6 +424,8 @@ int ntfs_mft_record_format(const ntfs_volume *vol, const MFT_REF mref)
|
|||
ret = 0;
|
||||
free_m:
|
||||
free(m);
|
||||
out:
|
||||
ntfs_log_leave("\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -794,11 +797,14 @@ static int ntfs_mft_bitmap_extend_initialized(ntfs_volume *vol)
|
|||
ntfs_attr_search_ctx *ctx;
|
||||
ATTR_RECORD *a;
|
||||
int err;
|
||||
int ret = -1;
|
||||
|
||||
ntfs_log_enter("Entering\n");
|
||||
|
||||
mftbmp_na = vol->mftbmp_na;
|
||||
ctx = ntfs_attr_get_search_ctx(mftbmp_na->ni, NULL);
|
||||
if (!ctx)
|
||||
return -1;
|
||||
goto out;
|
||||
|
||||
if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name,
|
||||
mftbmp_na->name_len, 0, 0, NULL, 0, ctx)) {
|
||||
|
@ -825,7 +831,8 @@ static int ntfs_mft_bitmap_extend_initialized(ntfs_volume *vol)
|
|||
if (ll == 8) {
|
||||
ntfs_log_debug("Wrote eight initialized bytes to mft bitmap.\n");
|
||||
vol->free_mft_records += (8 * 8);
|
||||
return 0;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
ntfs_log_error("Failed to write to mft bitmap.\n");
|
||||
err = errno;
|
||||
|
@ -860,7 +867,9 @@ put_err_out:
|
|||
(long long)mftbmp_na->initialized_size);
|
||||
err_out:
|
||||
errno = err;
|
||||
return -1;
|
||||
out:
|
||||
ntfs_log_leave("\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -463,39 +463,10 @@ static runlist_element *ntfs_rl_split(runlist_element *dst, int dsize,
|
|||
|
||||
|
||||
/**
|
||||
* ntfs_runlists_merge - merge two runlists into one
|
||||
* @drl: original runlist to be worked on
|
||||
* @srl: new runlist to be merged into @drl
|
||||
*
|
||||
* First we sanity check the two runlists @srl and @drl to make sure that they
|
||||
* are sensible and can be merged. The runlist @srl must be either after the
|
||||
* runlist @drl or completely within a hole (or unmapped region) in @drl.
|
||||
*
|
||||
* Merging of runlists is necessary in two cases:
|
||||
* 1. When attribute lists are used and a further extent is being mapped.
|
||||
* 2. When new clusters are allocated to fill a hole or extend a file.
|
||||
*
|
||||
* There are four possible ways @srl can be merged. It can:
|
||||
* - be inserted at the beginning of a hole,
|
||||
* - split the hole in two and be inserted between the two fragments,
|
||||
* - be appended at the end of a hole, or it can
|
||||
* - replace the whole hole.
|
||||
* It can also be appended to the end of the runlist, which is just a variant
|
||||
* of the insert case.
|
||||
*
|
||||
* On success, return a pointer to the new, combined, runlist. Note, both
|
||||
* runlists @drl and @srl are deallocated before returning so you cannot use
|
||||
* the pointers for anything any more. (Strictly speaking the returned runlist
|
||||
* may be the same as @dst but this is irrelevant.)
|
||||
*
|
||||
* On error, return NULL, with errno set to the error code. Both runlists are
|
||||
* left unmodified. The following error codes are defined:
|
||||
* ENOMEM Not enough memory to allocate runlist array.
|
||||
* EINVAL Invalid parameters were passed in.
|
||||
* ERANGE The runlists overlap and cannot be merged.
|
||||
* ntfs_runlists_merge_i - see ntfs_runlists_merge
|
||||
*/
|
||||
runlist_element *ntfs_runlists_merge(runlist_element *drl,
|
||||
runlist_element *srl)
|
||||
static runlist_element *ntfs_runlists_merge_i(runlist_element *drl,
|
||||
runlist_element *srl)
|
||||
{
|
||||
int di, si; /* Current index into @[ds]rl. */
|
||||
int sstart; /* First index with lcn > LCN_RL_NOT_MAPPED. */
|
||||
|
@ -701,6 +672,49 @@ critical_error:
|
|||
return drl;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_runlists_merge - merge two runlists into one
|
||||
* @drl: original runlist to be worked on
|
||||
* @srl: new runlist to be merged into @drl
|
||||
*
|
||||
* First we sanity check the two runlists @srl and @drl to make sure that they
|
||||
* are sensible and can be merged. The runlist @srl must be either after the
|
||||
* runlist @drl or completely within a hole (or unmapped region) in @drl.
|
||||
*
|
||||
* Merging of runlists is necessary in two cases:
|
||||
* 1. When attribute lists are used and a further extent is being mapped.
|
||||
* 2. When new clusters are allocated to fill a hole or extend a file.
|
||||
*
|
||||
* There are four possible ways @srl can be merged. It can:
|
||||
* - be inserted at the beginning of a hole,
|
||||
* - split the hole in two and be inserted between the two fragments,
|
||||
* - be appended at the end of a hole, or it can
|
||||
* - replace the whole hole.
|
||||
* It can also be appended to the end of the runlist, which is just a variant
|
||||
* of the insert case.
|
||||
*
|
||||
* On success, return a pointer to the new, combined, runlist. Note, both
|
||||
* runlists @drl and @srl are deallocated before returning so you cannot use
|
||||
* the pointers for anything any more. (Strictly speaking the returned runlist
|
||||
* may be the same as @dst but this is irrelevant.)
|
||||
*
|
||||
* On error, return NULL, with errno set to the error code. Both runlists are
|
||||
* left unmodified. The following error codes are defined:
|
||||
* ENOMEM Not enough memory to allocate runlist array.
|
||||
* EINVAL Invalid parameters were passed in.
|
||||
* ERANGE The runlists overlap and cannot be merged.
|
||||
*/
|
||||
runlist_element *ntfs_runlists_merge(runlist_element *drl,
|
||||
runlist_element *srl)
|
||||
{
|
||||
runlist_element *rl;
|
||||
|
||||
ntfs_log_enter("Entering\n");
|
||||
rl = ntfs_runlists_merge_i(drl, srl);
|
||||
ntfs_log_leave("\n");
|
||||
return rl;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_mapping_pairs_decompress - convert mapping pairs array to runlist
|
||||
* @vol: ntfs volume on which the attribute resides
|
||||
|
|
Loading…
Reference in New Issue