*Enabled NTFS writing

*Fixed favorite sorting
This commit is contained in:
dimok321 2010-09-19 15:12:16 +00:00
parent 6012536f67
commit 9594155a8d
80 changed files with 34319 additions and 37977 deletions

View File

@ -2,8 +2,8 @@
<app version="1"> <app version="1">
<name> USB Loader GX</name> <name> USB Loader GX</name>
<coder>USB Loader GX Team</coder> <coder>USB Loader GX Team</coder>
<version>1.0 r953</version> <version>1.0 r957</version>
<release_date>201009190727</release_date> <release_date>201009191357</release_date>
<short_description>Loads games from USB-devices</short_description> <short_description>Loads games from USB-devices</short_description>
<long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times. <long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times.
The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller. The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller.

View File

@ -41,15 +41,9 @@ SOURCES := source \
source/libfat \ source/libfat \
source/memory \ source/memory \
source/libntfs \ source/libntfs \
source/usbloader/wbfs \ source/usbloader/wbfs
# source/libhfs+ \
# source/libhfs+/hfscommon/BTree \
# source/libhfs+/hfscommon/Catalog \
# source/libhfs+/hfscommon/Misc \
# source/libhfs+/hfscommon/Unicode
DATA := data DATA := data
INCLUDES := source INCLUDES := source
#source/libhfs+/hfscommon/headers
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# options for code generation # options for code generation

View File

@ -9,8 +9,8 @@
#include "usbloader/usbstorage2.h" #include "usbloader/usbstorage2.h"
#include "usbloader/sdhc.h" #include "usbloader/sdhc.h"
#include "usbloader/wbfs.h" #include "usbloader/wbfs.h"
#include "libfat/fat.h"
#include "libntfs/ntfs.h" #include "libntfs/ntfs.h"
#include "libfat/fat.h"
#include "gecko.h" #include "gecko.h"
//these are the only stable and speed is good //these are the only stable and speed is good
@ -215,7 +215,7 @@ s32 MountNTFS( u32 sector )
// } // }
/* Mount device */ /* Mount device */
// if (!ntfsMount("NTFS", &__io_wiiums, sector, CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_RECOVER)) { // if (!ntfsMount("NTFS", &__io_wiiums, sector, CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_RECOVER)) {
ret = ntfsMount( "NTFS", &__io_usbstorage2, sector, CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_READ_ONLY | NTFS_RECOVER ); ret = ntfsMount( "NTFS", &__io_usbstorage2, sector, CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_RECOVER );
if ( !ret ) if ( !ret )
{ {
return -2; return -2;
@ -226,11 +226,11 @@ s32 MountNTFS( u32 sector )
{ {
if ( sdhc_mode_sd == 0 ) if ( sdhc_mode_sd == 0 )
{ {
ret = ntfsMount( "NTFS", &__io_sdhc, 0, CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_READ_ONLY | NTFS_RECOVER ); ret = ntfsMount( "NTFS", &__io_sdhc, 0, CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_RECOVER );
} }
else else
{ {
ret = ntfsMount( "NTFS", &__io_sdhc, 0, CACHE, SECTORS_SD, NTFS_SHOW_HIDDEN_FILES | NTFS_READ_ONLY | NTFS_RECOVER ); ret = ntfsMount( "NTFS", &__io_sdhc, 0, CACHE, SECTORS_SD, NTFS_SHOW_HIDDEN_FILES | NTFS_RECOVER );
} }
if ( !ret ) if ( !ret )
{ {

File diff suppressed because it is too large Load Diff

View File

@ -122,8 +122,7 @@ typedef char BIGSID[40];
* (private to this module) * (private to this module)
*/ */
struct MAPLIST struct MAPLIST {
{
struct MAPLIST *next; struct MAPLIST *next;
char *uidstr; /* uid text from the same record */ char *uidstr; /* uid text from the same record */
char *gidstr; /* gid text from the same record */ char *gidstr; /* gid text from the same record */

File diff suppressed because it is too large Load Diff

View File

@ -49,8 +49,7 @@ extern ntfschar TXF_DATA[10];
* *
* TODO: Describe them. * TODO: Describe them.
*/ */
typedef enum typedef enum {
{
LCN_HOLE = -1, /* Keep this as highest value or die! */ LCN_HOLE = -1, /* Keep this as highest value or die! */
LCN_RL_NOT_MAPPED = -2, LCN_RL_NOT_MAPPED = -2,
LCN_ENOENT = -3, LCN_ENOENT = -3,
@ -76,8 +75,7 @@ typedef enum
* any modification of the search context, to automagically get the next * any modification of the search context, to automagically get the next
* matching attribute. * matching attribute.
*/ */
struct _ntfs_attr_search_ctx struct _ntfs_attr_search_ctx {
{
MFT_RECORD *mrec; MFT_RECORD *mrec;
ATTR_RECORD *attr; ATTR_RECORD *attr;
BOOL is_first; BOOL is_first;
@ -176,8 +174,7 @@ static __inline__ int ntfs_attrs_walk( ntfs_attr_search_ctx *ctx )
* @state contains NTFS attribute specific flags describing this attribute * @state contains NTFS attribute specific flags describing this attribute
* structure. See ntfs_attr_state_bits above. * structure. See ntfs_attr_state_bits above.
*/ */
struct _ntfs_attr struct _ntfs_attr {
{
runlist_element *rl; runlist_element *rl;
ntfs_inode *ni; ntfs_inode *ni;
ATTR_TYPES type; ATTR_TYPES type;
@ -199,8 +196,7 @@ struct _ntfs_attr
* enum ntfs_attr_state_bits - bits for the state field in the ntfs_attr * enum ntfs_attr_state_bits - bits for the state field in the ntfs_attr
* structure * structure
*/ */
typedef enum typedef enum {
{
NA_Initialized, /* 1: structure is initialized. */ NA_Initialized, /* 1: structure is initialized. */
NA_NonResident, /* 1: Attribute is not resident. */ NA_NonResident, /* 1: Attribute is not resident. */
NA_BeingNonResident, /* 1: Attribute is being made not resident. */ NA_BeingNonResident, /* 1: Attribute is being made not resident. */
@ -247,8 +243,7 @@ GenNAttrIno( Sparse, FILE_ATTR_SPARSE_FILE )
* *
* For convenience. Used in the attr structure. * For convenience. Used in the attr structure.
*/ */
typedef union typedef union {
{
u8 _default; /* Unnamed u8 to serve as default when just using u8 _default; /* Unnamed u8 to serve as default when just using
a_val without specifying any of the below. */ a_val without specifying any of the below. */
STANDARD_INFORMATION std_inf; STANDARD_INFORMATION std_inf;

View File

@ -62,8 +62,7 @@ int ntfs_attrlist_need( ntfs_inode *ni )
{ {
ATTR_LIST_ENTRY *ale; ATTR_LIST_ENTRY *ale;
if ( !ni ) if (!ni) {
{
ntfs_log_trace("Invalid arguments.\n"); ntfs_log_trace("Invalid arguments.\n");
errno = EINVAL; errno = EINVAL;
return -1; return -1;
@ -71,15 +70,13 @@ int ntfs_attrlist_need( ntfs_inode *ni )
ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no);
if ( !NInoAttrList( ni ) ) if (!NInoAttrList(ni)) {
{
ntfs_log_trace("Inode haven't got attribute list.\n"); ntfs_log_trace("Inode haven't got attribute list.\n");
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
if ( !ni->attr_list ) if (!ni->attr_list) {
{
ntfs_log_trace("Corrupt in-memory struct.\n"); ntfs_log_trace("Corrupt in-memory struct.\n");
errno = EINVAL; errno = EINVAL;
return -1; return -1;
@ -87,8 +84,7 @@ int ntfs_attrlist_need( ntfs_inode *ni )
errno = 0; errno = 0;
ale = (ATTR_LIST_ENTRY *)ni->attr_list; ale = (ATTR_LIST_ENTRY *)ni->attr_list;
while ( ( u8* )ale < ni->attr_list + ni->attr_list_size ) while ((u8*)ale < ni->attr_list + ni->attr_list_size) {
{
if (MREF_LE(ale->mft_reference) != ni->mft_no) if (MREF_LE(ale->mft_reference) != ni->mft_no)
return 1; return 1;
ale = (ATTR_LIST_ENTRY *)((u8*)ale + le16_to_cpu(ale->length)); ale = (ATTR_LIST_ENTRY *)((u8*)ale + le16_to_cpu(ale->length));
@ -121,8 +117,7 @@ int ntfs_attrlist_entry_add( ntfs_inode *ni, ATTR_RECORD *attr )
(long long) ni->mft_no, (long long) ni->mft_no,
(unsigned) le32_to_cpu(attr->type)); (unsigned) le32_to_cpu(attr->type));
if ( !ni || !attr ) if (!ni || !attr) {
{
ntfs_log_trace("Invalid arguments.\n"); ntfs_log_trace("Invalid arguments.\n");
errno = EINVAL; errno = EINVAL;
return -1; return -1;
@ -133,8 +128,7 @@ int ntfs_attrlist_entry_add( ntfs_inode *ni, ATTR_RECORD *attr )
if (ni->nr_extents == -1) if (ni->nr_extents == -1)
ni = ni->base_ni; ni = ni->base_ni;
if ( !NInoAttrList( ni ) ) if (!NInoAttrList(ni)) {
{
ntfs_log_trace("Attribute list isn't present.\n"); ntfs_log_trace("Attribute list isn't present.\n");
errno = ENOENT; errno = ENOENT;
return -1; return -1;
@ -149,8 +143,7 @@ int ntfs_attrlist_entry_add( ntfs_inode *ni, ATTR_RECORD *attr )
/* Find place for the new entry. */ /* Find place for the new entry. */
ctx = ntfs_attr_get_search_ctx(ni, NULL); ctx = ntfs_attr_get_search_ctx(ni, NULL);
if ( !ctx ) if (!ctx) {
{
err = errno; err = errno;
goto err_out; goto err_out;
} }
@ -160,11 +153,9 @@ int ntfs_attrlist_entry_add( ntfs_inode *ni, ATTR_RECORD *attr )
(attr->non_resident) ? le64_to_cpu(attr->lowest_vcn) : (attr->non_resident) ? le64_to_cpu(attr->lowest_vcn) :
0, (attr->non_resident) ? NULL : ((u8*)attr + 0, (attr->non_resident) ? NULL : ((u8*)attr +
le16_to_cpu(attr->value_offset)), (attr->non_resident) ? le16_to_cpu(attr->value_offset)), (attr->non_resident) ?
0 : le32_to_cpu( attr->value_length ), ctx ) ) 0 : le32_to_cpu(attr->value_length), ctx)) {
{
/* Found some extent, check it to be before new extent. */ /* Found some extent, check it to be before new extent. */
if ( ctx->al_entry->lowest_vcn == attr->lowest_vcn ) if (ctx->al_entry->lowest_vcn == attr->lowest_vcn) {
{
err = EEXIST; err = EEXIST;
ntfs_log_trace("Such attribute already present in the " ntfs_log_trace("Such attribute already present in the "
"attribute list.\n"); "attribute list.\n");
@ -174,12 +165,9 @@ int ntfs_attrlist_entry_add( ntfs_inode *ni, ATTR_RECORD *attr )
/* Add new entry after this extent. */ /* Add new entry after this extent. */
ale = (ATTR_LIST_ENTRY*)((u8*)ctx->al_entry + ale = (ATTR_LIST_ENTRY*)((u8*)ctx->al_entry +
le16_to_cpu(ctx->al_entry->length)); le16_to_cpu(ctx->al_entry->length));
} } else {
else
{
/* Check for real errors. */ /* Check for real errors. */
if ( errno != ENOENT ) if (errno != ENOENT) {
{
err = errno; err = errno;
ntfs_log_trace("Attribute lookup failed.\n"); ntfs_log_trace("Attribute lookup failed.\n");
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
@ -213,14 +201,12 @@ int ntfs_attrlist_entry_add( ntfs_inode *ni, ATTR_RECORD *attr )
/* Resize $ATTRIBUTE_LIST to new length. */ /* Resize $ATTRIBUTE_LIST to new length. */
na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);
if ( !na ) if (!na) {
{
err = errno; err = errno;
ntfs_log_trace("Failed to open $ATTRIBUTE_LIST attribute.\n"); ntfs_log_trace("Failed to open $ATTRIBUTE_LIST attribute.\n");
goto err_out; goto err_out;
} }
if ( ntfs_attr_truncate( na, ni->attr_list_size + entry_len ) ) if (ntfs_attr_truncate(na, ni->attr_list_size + entry_len)) {
{
err = errno; err = errno;
ntfs_log_trace("$ATTRIBUTE_LIST resize failed.\n"); ntfs_log_trace("$ATTRIBUTE_LIST resize failed.\n");
goto err_out; goto err_out;
@ -264,8 +250,7 @@ int ntfs_attrlist_entry_rm( ntfs_attr_search_ctx *ctx )
ATTR_LIST_ENTRY *ale; ATTR_LIST_ENTRY *ale;
int err; int err;
if ( !ctx || !ctx->ntfs_ino || !ctx->al_entry ) if (!ctx || !ctx->ntfs_ino || !ctx->al_entry) {
{
ntfs_log_trace("Invalid arguments.\n"); ntfs_log_trace("Invalid arguments.\n");
errno = EINVAL; errno = EINVAL;
return -1; return -1;
@ -282,8 +267,7 @@ int ntfs_attrlist_entry_rm( ntfs_attr_search_ctx *ctx )
(unsigned) le32_to_cpu(ctx->al_entry->type), (unsigned) le32_to_cpu(ctx->al_entry->type),
(long long) le64_to_cpu(ctx->al_entry->lowest_vcn)); (long long) le64_to_cpu(ctx->al_entry->lowest_vcn));
if ( !NInoAttrList( base_ni ) ) if (!NInoAttrList(base_ni)) {
{
ntfs_log_trace("Attribute list isn't present.\n"); ntfs_log_trace("Attribute list isn't present.\n");
errno = ENOENT; errno = ENOENT;
return -1; return -1;
@ -297,14 +281,12 @@ int ntfs_attrlist_entry_rm( ntfs_attr_search_ctx *ctx )
/* Reisze $ATTRIBUTE_LIST to new length. */ /* Reisze $ATTRIBUTE_LIST to new length. */
na = ntfs_attr_open(base_ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); na = ntfs_attr_open(base_ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);
if ( !na ) if (!na) {
{
err = errno; err = errno;
ntfs_log_trace("Failed to open $ATTRIBUTE_LIST attribute.\n"); ntfs_log_trace("Failed to open $ATTRIBUTE_LIST attribute.\n");
goto err_out; goto err_out;
} }
if ( ntfs_attr_truncate( na, new_al_len ) ) if (ntfs_attr_truncate(na, new_al_len)) {
{
err = errno; err = errno;
ntfs_log_trace("$ATTRIBUTE_LIST resize failed.\n"); ntfs_log_trace("$ATTRIBUTE_LIST resize failed.\n");
goto err_out; goto err_out;

View File

@ -34,24 +34,20 @@
/*----------------------------------------------------------------- /*-----------------------------------------------------------------
Functions to deal with little endian values stored in uint8_t arrays Functions to deal with little endian values stored in uint8_t arrays
-----------------------------------------------------------------*/ -----------------------------------------------------------------*/
static inline uint16_t u8array_to_u16 ( const uint8_t* item, int offset ) static inline uint16_t u8array_to_u16 (const uint8_t* item, int offset) {
{
return ( item[offset] | (item[offset + 1] << 8)); return ( item[offset] | (item[offset + 1] << 8));
} }
static inline uint32_t u8array_to_u32 ( const uint8_t* item, int offset ) static inline uint32_t u8array_to_u32 (const uint8_t* item, int offset) {
{
return ( item[offset] | (item[offset + 1] << 8) | (item[offset + 2] << 16) | (item[offset + 3] << 24)); return ( item[offset] | (item[offset + 1] << 8) | (item[offset + 2] << 16) | (item[offset + 3] << 24));
} }
static inline void u16_to_u8array ( uint8_t* item, int offset, uint16_t value ) static inline void u16_to_u8array (uint8_t* item, int offset, uint16_t value) {
{
item[offset] = (uint8_t) value; item[offset] = (uint8_t) value;
item[offset + 1] = (uint8_t)(value >> 8); item[offset + 1] = (uint8_t)(value >> 8);
} }
static inline void u32_to_u8array ( uint8_t* item, int offset, uint32_t value ) static inline void u32_to_u8array (uint8_t* item, int offset, uint32_t value) {
{
item[offset] = (uint8_t) value; item[offset] = (uint8_t) value;
item[offset + 1] = (uint8_t)(value >> 8); item[offset + 1] = (uint8_t)(value >> 8);
item[offset + 2] = (uint8_t)(value >> 16); item[offset + 2] = (uint8_t)(value >> 16);

View File

@ -119,8 +119,7 @@ static int ntfs_bitmap_set_bits_in_run( ntfs_attr *na, s64 start_bit,
u8 *buf, *lastbyte_buf; u8 *buf, *lastbyte_buf;
int bit, firstbyte, lastbyte, lastbyte_pos, tmp, ret = -1; int bit, firstbyte, lastbyte, lastbyte_pos, tmp, ret = -1;
if ( !na || start_bit < 0 || count < 0 ) if (!na || start_bit < 0 || count < 0) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s: Invalid argument (%p, %lld, %lld)", ntfs_log_perror("%s: Invalid argument (%p, %lld, %lld)",
__FUNCTION__, na, (long long)start_bit, (long long)count); __FUNCTION__, na, (long long)start_bit, (long long)count);
@ -146,19 +145,16 @@ static int ntfs_bitmap_set_bits_in_run( ntfs_attr *na, s64 start_bit,
memset(buf, value ? 0xff : 0, bufsize); memset(buf, value ? 0xff : 0, bufsize);
/* If there is a first partial byte... */ /* If there is a first partial byte... */
if ( bit ) if (bit) {
{
/* read it in... */ /* read it in... */
br = ntfs_attr_pread(na, start_bit >> 3, 1, buf); br = ntfs_attr_pread(na, start_bit >> 3, 1, buf);
if ( br != 1 ) if (br != 1) {
{
if (br >= 0) if (br >= 0)
errno = EIO; errno = EIO;
goto free_err_out; goto free_err_out;
} }
/* and set or clear the appropriate bits in it. */ /* and set or clear the appropriate bits in it. */
while ( ( bit & 7 ) && count-- ) while ((bit & 7) && count--) {
{
if (value) if (value)
*buf |= 1 << bit++; *buf |= 1 << bit++;
else else
@ -172,14 +168,11 @@ static int ntfs_bitmap_set_bits_in_run( ntfs_attr *na, s64 start_bit,
lastbyte = 0; lastbyte = 0;
lastbyte_buf = NULL; lastbyte_buf = NULL;
bit = count & 7; bit = count & 7;
do do {
{
/* If there is a last partial byte... */ /* If there is a last partial byte... */
if ( count > 0 && bit ) if (count > 0 && bit) {
{
lastbyte_pos = ((count + 7) >> 3) + firstbyte; lastbyte_pos = ((count + 7) >> 3) + firstbyte;
if ( !lastbyte_pos ) if (!lastbyte_pos) {
{
// FIXME: Eeek! BUG! // FIXME: Eeek! BUG!
ntfs_log_error("Lastbyte is zero. Leaving " ntfs_log_error("Lastbyte is zero. Leaving "
"inconsistent metadata.\n"); "inconsistent metadata.\n");
@ -187,15 +180,13 @@ static int ntfs_bitmap_set_bits_in_run( ntfs_attr *na, s64 start_bit,
goto free_err_out; goto free_err_out;
} }
/* and it is in the currently loaded bitmap window... */ /* and it is in the currently loaded bitmap window... */
if ( lastbyte_pos <= bufsize ) if (lastbyte_pos <= bufsize) {
{
lastbyte_buf = buf + lastbyte_pos - 1; lastbyte_buf = buf + lastbyte_pos - 1;
/* read the byte in... */ /* read the byte in... */
br = ntfs_attr_pread(na, (start_bit + count) >> br = ntfs_attr_pread(na, (start_bit + count) >>
3, 1, lastbyte_buf); 3, 1, lastbyte_buf);
if ( br != 1 ) if (br != 1) {
{
// FIXME: Eeek! We need rollback! (AIA) // FIXME: Eeek! We need rollback! (AIA)
if (br >= 0) if (br >= 0)
errno = EIO; errno = EIO;
@ -205,8 +196,7 @@ static int ntfs_bitmap_set_bits_in_run( ntfs_attr *na, s64 start_bit,
goto free_err_out; goto free_err_out;
} }
/* and set/clear the appropriate bits in it. */ /* and set/clear the appropriate bits in it. */
while ( bit && count-- ) while (bit && count--) {
{
if (value) if (value)
*lastbyte_buf |= 1 << --bit; *lastbyte_buf |= 1 << --bit;
else else
@ -222,8 +212,7 @@ static int ntfs_bitmap_set_bits_in_run( ntfs_attr *na, s64 start_bit,
/* Write the prepared buffer to disk. */ /* Write the prepared buffer to disk. */
tmp = (start_bit >> 3) - firstbyte; tmp = (start_bit >> 3) - firstbyte;
br = ntfs_attr_pwrite(na, tmp, bufsize, buf); br = ntfs_attr_pwrite(na, tmp, bufsize, buf);
if ( br != bufsize ) if (br != bufsize) {
{
// FIXME: Eeek! We need rollback! (AIA) // FIXME: Eeek! We need rollback! (AIA)
if (br >= 0) if (br >= 0)
errno = EIO; errno = EIO;
@ -235,8 +224,7 @@ static int ntfs_bitmap_set_bits_in_run( ntfs_attr *na, s64 start_bit,
/* Update counters. */ /* Update counters. */
tmp = (bufsize - firstbyte - lastbyte) << 3; tmp = (bufsize - firstbyte - lastbyte) << 3;
if ( firstbyte ) if (firstbyte) {
{
firstbyte = 0; firstbyte = 0;
/* /*
* Re-set the partial first byte so a subsequent write * Re-set the partial first byte so a subsequent write
@ -249,8 +237,7 @@ static int ntfs_bitmap_set_bits_in_run( ntfs_attr *na, s64 start_bit,
if (bufsize > (tmp = (count + 7) >> 3)) if (bufsize > (tmp = (count + 7) >> 3))
bufsize = tmp; bufsize = tmp;
if ( lastbyte && count != 0 ) if (lastbyte && count != 0) {
{
// FIXME: Eeek! BUG! // FIXME: Eeek! BUG!
ntfs_log_error("Last buffer but count is not zero " ntfs_log_error("Last buffer but count is not zero "
"(%lld). Leaving inconsistent metadata.\n", "(%lld). Leaving inconsistent metadata.\n",
@ -258,8 +245,7 @@ static int ntfs_bitmap_set_bits_in_run( ntfs_attr *na, s64 start_bit,
errno = EIO; errno = EIO;
goto free_err_out; goto free_err_out;
} }
} } while (count > 0);
while ( count > 0 );
ret = 0; ret = 0;

View File

@ -65,24 +65,21 @@ BOOL ntfs_boot_sector_is_ntfs( NTFS_BOOT_SECTOR *b )
ntfs_log_debug("Beginning bootsector check.\n"); ntfs_log_debug("Beginning bootsector check.\n");
ntfs_log_debug("Checking OEMid, NTFS signature.\n"); ntfs_log_debug("Checking OEMid, NTFS signature.\n");
if ( b->oem_id != cpu_to_le64( 0x202020205346544eULL ) ) /* "NTFS " */ if (b->oem_id != cpu_to_le64(0x202020205346544eULL)) { /* "NTFS " */
{
ntfs_log_error("NTFS signature is missing.\n"); ntfs_log_error("NTFS signature is missing.\n");
goto not_ntfs; goto not_ntfs;
} }
ntfs_log_debug("Checking bytes per sector.\n"); ntfs_log_debug("Checking bytes per sector.\n");
if (le16_to_cpu(b->bpb.bytes_per_sector) < 256 || if (le16_to_cpu(b->bpb.bytes_per_sector) < 256 ||
le16_to_cpu( b->bpb.bytes_per_sector ) > 4096 ) le16_to_cpu(b->bpb.bytes_per_sector) > 4096) {
{
ntfs_log_error("Unexpected bytes per sector value (%d).\n", ntfs_log_error("Unexpected bytes per sector value (%d).\n",
le16_to_cpu(b->bpb.bytes_per_sector)); le16_to_cpu(b->bpb.bytes_per_sector));
goto not_ntfs; goto not_ntfs;
} }
ntfs_log_debug("Checking sectors per cluster.\n"); ntfs_log_debug("Checking sectors per cluster.\n");
switch ( b->bpb.sectors_per_cluster ) switch (b->bpb.sectors_per_cluster) {
{
case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128:
break; break;
default: default:
@ -94,8 +91,7 @@ BOOL ntfs_boot_sector_is_ntfs( NTFS_BOOT_SECTOR *b )
ntfs_log_debug("Checking cluster size.\n"); ntfs_log_debug("Checking cluster size.\n");
i = (u32)le16_to_cpu(b->bpb.bytes_per_sector) * i = (u32)le16_to_cpu(b->bpb.bytes_per_sector) *
b->bpb.sectors_per_cluster; b->bpb.sectors_per_cluster;
if ( i > 65536 ) if (i > 65536) {
{
ntfs_log_error("Unexpected cluster size (%d).\n", i); ntfs_log_error("Unexpected cluster size (%d).\n", i);
goto not_ntfs; goto not_ntfs;
} }
@ -106,8 +102,7 @@ BOOL ntfs_boot_sector_is_ntfs( NTFS_BOOT_SECTOR *b )
le16_to_cpu(b->bpb.sectors) || le16_to_cpu(b->bpb.sectors) ||
le16_to_cpu(b->bpb.sectors_per_fat) || le16_to_cpu(b->bpb.sectors_per_fat) ||
le32_to_cpu(b->bpb.large_sectors) || le32_to_cpu(b->bpb.large_sectors) ||
b->bpb.fats ) b->bpb.fats) {
{
ntfs_log_error("Reserved fields aren't zero " ntfs_log_error("Reserved fields aren't zero "
"(%d, %d, %d, %d, %d, %d).\n", "(%d, %d, %d, %d, %d, %d).\n",
le16_to_cpu(b->bpb.reserved_sectors), le16_to_cpu(b->bpb.reserved_sectors),
@ -121,10 +116,8 @@ BOOL ntfs_boot_sector_is_ntfs( NTFS_BOOT_SECTOR *b )
ntfs_log_debug("Checking clusters per mft record.\n"); ntfs_log_debug("Checking clusters per mft record.\n");
if ((u8)b->clusters_per_mft_record < 0xe1 || if ((u8)b->clusters_per_mft_record < 0xe1 ||
( u8 )b->clusters_per_mft_record > 0xf7 ) (u8)b->clusters_per_mft_record > 0xf7) {
{ switch (b->clusters_per_mft_record) {
switch ( b->clusters_per_mft_record )
{
case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40: case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40:
break; break;
default: default:
@ -136,10 +129,8 @@ BOOL ntfs_boot_sector_is_ntfs( NTFS_BOOT_SECTOR *b )
ntfs_log_debug("Checking clusters per index block.\n"); ntfs_log_debug("Checking clusters per index block.\n");
if ((u8)b->clusters_per_index_record < 0xe1 || if ((u8)b->clusters_per_index_record < 0xe1 ||
( u8 )b->clusters_per_index_record > 0xf7 ) (u8)b->clusters_per_index_record > 0xf7) {
{ switch (b->clusters_per_index_record) {
switch ( b->clusters_per_index_record )
{
case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40: case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40:
break; break;
default: default:
@ -197,8 +188,7 @@ int ntfs_boot_sector_parse( ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs )
*/ */
sectors_per_cluster = bs->bpb.sectors_per_cluster; sectors_per_cluster = bs->bpb.sectors_per_cluster;
ntfs_log_debug("SectorsPerCluster = 0x%x\n", sectors_per_cluster); ntfs_log_debug("SectorsPerCluster = 0x%x\n", sectors_per_cluster);
if ( sectors_per_cluster & ( sectors_per_cluster - 1 ) ) if (sectors_per_cluster & (sectors_per_cluster - 1)) {
{
ntfs_log_error("sectors_per_cluster (%d) is not a power of 2." ntfs_log_error("sectors_per_cluster (%d) is not a power of 2."
"\n", sectors_per_cluster); "\n", sectors_per_cluster);
return -1; return -1;
@ -206,15 +196,13 @@ int ntfs_boot_sector_parse( ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs )
sectors = sle64_to_cpu(bs->number_of_sectors); sectors = sle64_to_cpu(bs->number_of_sectors);
ntfs_log_debug("NumberOfSectors = %lld\n", (long long)sectors); ntfs_log_debug("NumberOfSectors = %lld\n", (long long)sectors);
if ( !sectors ) if (!sectors) {
{
ntfs_log_error("Volume size is set to zero.\n"); ntfs_log_error("Volume size is set to zero.\n");
return -1; return -1;
} }
if (vol->dev->d_ops->seek(vol->dev, if (vol->dev->d_ops->seek(vol->dev,
(sectors - 1) << vol->sector_size_bits, (sectors - 1) << vol->sector_size_bits,
SEEK_SET ) == -1 ) SEEK_SET) == -1) {
{
ntfs_log_perror("Failed to read last sector (%lld)", ntfs_log_perror("Failed to read last sector (%lld)",
(long long)sectors); (long long)sectors);
ntfs_log_error("%s", last_sector_error); ntfs_log_error("%s", last_sector_error);
@ -228,8 +216,7 @@ int ntfs_boot_sector_parse( ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs )
ntfs_log_debug("MFT LCN = %lld\n", (long long)vol->mft_lcn); ntfs_log_debug("MFT LCN = %lld\n", (long long)vol->mft_lcn);
ntfs_log_debug("MFTMirr LCN = %lld\n", (long long)vol->mftmirr_lcn); ntfs_log_debug("MFTMirr LCN = %lld\n", (long long)vol->mftmirr_lcn);
if (vol->mft_lcn > vol->nr_clusters || if (vol->mft_lcn > vol->nr_clusters ||
vol->mftmirr_lcn > vol->nr_clusters ) vol->mftmirr_lcn > vol->nr_clusters) {
{
ntfs_log_error("$MFT LCN (%lld) or $MFTMirr LCN (%lld) is " ntfs_log_error("$MFT LCN (%lld) or $MFTMirr LCN (%lld) is "
"greater than the number of clusters (%lld).\n", "greater than the number of clusters (%lld).\n",
(long long)vol->mft_lcn, (long long)vol->mftmirr_lcn, (long long)vol->mft_lcn, (long long)vol->mftmirr_lcn,
@ -238,8 +225,7 @@ int ntfs_boot_sector_parse( ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs )
} }
vol->cluster_size = sectors_per_cluster * vol->sector_size; vol->cluster_size = sectors_per_cluster * vol->sector_size;
if ( vol->cluster_size & ( vol->cluster_size - 1 ) ) if (vol->cluster_size & (vol->cluster_size - 1)) {
{
ntfs_log_error("cluster_size (%d) is not a power of 2.\n", ntfs_log_error("cluster_size (%d) is not a power of 2.\n",
vol->cluster_size); vol->cluster_size);
return -1; return -1;
@ -264,8 +250,7 @@ int ntfs_boot_sector_parse( ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs )
vol->mft_record_size = 1 << -c; vol->mft_record_size = 1 << -c;
else else
vol->mft_record_size = c << vol->cluster_size_bits; vol->mft_record_size = c << vol->cluster_size_bits;
if ( vol->mft_record_size & ( vol->mft_record_size - 1 ) ) if (vol->mft_record_size & (vol->mft_record_size - 1)) {
{
ntfs_log_error("mft_record_size (%d) is not a power of 2.\n", ntfs_log_error("mft_record_size (%d) is not a power of 2.\n",
vol->mft_record_size); vol->mft_record_size);
return -1; return -1;

View File

@ -67,15 +67,12 @@ static void inserthashindex( struct CACHE_HEADER *cache,
struct HASH_ENTRY *link; struct HASH_ENTRY *link;
struct HASH_ENTRY *first; struct HASH_ENTRY *first;
if ( cache->dohash ) if (cache->dohash) {
{
h = cache->dohash(current); h = cache->dohash(current);
if ( ( h >= 0 ) && ( h < cache->max_hash ) ) if ((h >= 0) && (h < cache->max_hash)) {
{
/* get a free link and insert at top of hash list */ /* get a free link and insert at top of hash list */
link = cache->free_hash; link = cache->free_hash;
if ( link ) if (link) {
{
cache->free_hash = link->next; cache->free_hash = link->next;
first = cache->first_hash[h]; first = cache->first_hash[h];
if (first) if (first)
@ -84,17 +81,13 @@ static void inserthashindex( struct CACHE_HEADER *cache,
link->next = NULL; link->next = NULL;
link->entry = current; link->entry = current;
cache->first_hash[h] = link; cache->first_hash[h] = link;
} } else {
else
{
ntfs_log_error("No more hash entries," ntfs_log_error("No more hash entries,"
" cache %s hashing dropped\n", " cache %s hashing dropped\n",
cache->name); cache->name);
cache->dohash = (cache_hash)NULL; cache->dohash = (cache_hash)NULL;
} }
} } else {
else
{
ntfs_log_error("Illegal hash value," ntfs_log_error("Illegal hash value,"
" cache %s hashing dropped\n", " cache %s hashing dropped\n",
cache->name); cache->name);
@ -113,37 +106,29 @@ static void drophashindex( struct CACHE_HEADER *cache,
struct HASH_ENTRY *link; struct HASH_ENTRY *link;
struct HASH_ENTRY *previous; struct HASH_ENTRY *previous;
if ( cache->dohash ) if (cache->dohash) {
{ if ((hash >= 0) && (hash < cache->max_hash)) {
if ( ( hash >= 0 ) && ( hash < cache->max_hash ) )
{
/* find the link and unlink */ /* find the link and unlink */
link = cache->first_hash[hash]; link = cache->first_hash[hash];
previous = (struct HASH_ENTRY*)NULL; previous = (struct HASH_ENTRY*)NULL;
while ( link && ( link->entry != current ) ) while (link && (link->entry != current)) {
{
previous = link; previous = link;
link = link->next; link = link->next;
} }
if ( link ) if (link) {
{
if (previous) if (previous)
previous->next = link->next; previous->next = link->next;
else else
cache->first_hash[hash] = link->next; cache->first_hash[hash] = link->next;
link->next = cache->free_hash; link->next = cache->free_hash;
cache->free_hash = link; cache->free_hash = link;
} } else {
else
{
ntfs_log_error("Bad hash list," ntfs_log_error("Bad hash list,"
" cache %s hashing dropped\n", " cache %s hashing dropped\n",
cache->name); cache->name);
cache->dohash = (cache_hash)NULL; cache->dohash = (cache_hash)NULL;
} }
} } else {
else
{
ntfs_log_error("Illegal hash value," ntfs_log_error("Illegal hash value,"
" cache %s hashing dropped\n", " cache %s hashing dropped\n",
cache->name); cache->name);
@ -168,10 +153,8 @@ struct CACHED_GENERIC *ntfs_fetch_cache( struct CACHE_HEADER *cache,
int h; int h;
current = (struct CACHED_GENERIC*)NULL; current = (struct CACHED_GENERIC*)NULL;
if ( cache ) if (cache) {
{ if (cache->dohash) {
if ( cache->dohash )
{
/* /*
* When possible, use the hash table to * When possible, use the hash table to
* locate the entry if present * locate the entry if present
@ -183,25 +166,21 @@ struct CACHED_GENERIC *ntfs_fetch_cache( struct CACHE_HEADER *cache,
if (link) if (link)
current = link->entry; current = link->entry;
} }
if ( !cache->dohash ) if (!cache->dohash) {
{
/* /*
* Search sequentially in LRU list if no hash table * Search sequentially in LRU list if no hash table
* or if hashing has just failed * or if hashing has just failed
*/ */
current = cache->most_recent_entry; current = cache->most_recent_entry;
while (current while (current
&& compare( current, wanted ) ) && compare(current, wanted)) {
{
current = current->next; current = current->next;
} }
} }
if ( current ) if (current) {
{
previous = current->previous; previous = current->previous;
cache->hits++; cache->hits++;
if ( previous ) if (previous) {
{
/* /*
* found and not at head of list, unlink from current * found and not at head of list, unlink from current
* position and relink as head of list * position and relink as head of list
@ -240,10 +219,8 @@ struct CACHED_GENERIC *ntfs_enter_cache( struct CACHE_HEADER *cache,
int h; int h;
current = (struct CACHED_GENERIC*)NULL; current = (struct CACHED_GENERIC*)NULL;
if ( cache ) if (cache) {
{ if (cache->dohash) {
if ( cache->dohash )
{
/* /*
* When possible, use the hash table to * When possible, use the hash table to
* find out whether the entry if present * find out whether the entry if present
@ -252,13 +229,11 @@ struct CACHED_GENERIC *ntfs_enter_cache( struct CACHE_HEADER *cache,
link = cache->first_hash[h]; link = cache->first_hash[h];
while (link && compare(link->entry, item)) while (link && compare(link->entry, item))
link = link->next; link = link->next;
if ( link ) if (link) {
{
current = link->entry; current = link->entry;
} }
} }
if ( !cache->dohash ) if (!cache->dohash) {
{
/* /*
* Search sequentially in LRU list to locate the end, * Search sequentially in LRU list to locate the end,
* and find out whether the entry is already in list * and find out whether the entry is already in list
@ -267,14 +242,12 @@ struct CACHED_GENERIC *ntfs_enter_cache( struct CACHE_HEADER *cache,
*/ */
current = cache->most_recent_entry; current = cache->most_recent_entry;
while (current while (current
&& compare( current, item ) ) && compare(current, item)) {
{
current = current->next; current = current->next;
} }
} }
if ( !current ) if (!current) {
{
/* /*
* Not in list, get a free entry or reuse the * Not in list, get a free entry or reuse the
* last entry, and relink as head of list * last entry, and relink as head of list
@ -283,23 +256,18 @@ struct CACHED_GENERIC *ntfs_enter_cache( struct CACHE_HEADER *cache,
* an entry is reused. * an entry is reused.
*/ */
if ( cache->free_entry ) if (cache->free_entry) {
{
current = cache->free_entry; current = cache->free_entry;
cache->free_entry = cache->free_entry->next; cache->free_entry = cache->free_entry->next;
if ( item->varsize ) if (item->varsize) {
{
current->variable = ntfs_malloc( current->variable = ntfs_malloc(
item->varsize); item->varsize);
} } else
else
current->variable = (void*)NULL; current->variable = (void*)NULL;
current->varsize = item->varsize; current->varsize = item->varsize;
if (!cache->oldest_entry) if (!cache->oldest_entry)
cache->oldest_entry = current; cache->oldest_entry = current;
} } else {
else
{
/* reusing the oldest entry */ /* reusing the oldest entry */
current = cache->oldest_entry; current = cache->oldest_entry;
before = current->previous; before = current->previous;
@ -310,8 +278,7 @@ struct CACHED_GENERIC *ntfs_enter_cache( struct CACHE_HEADER *cache,
if (cache->dofree) if (cache->dofree)
cache->dofree(current); cache->dofree(current);
cache->oldest_entry = current->previous; cache->oldest_entry = current->previous;
if ( item->varsize ) if (item->varsize) {
{
if (current->varsize) if (current->varsize)
current->variable = realloc( current->variable = realloc(
current->variable, current->variable,
@ -319,9 +286,7 @@ struct CACHED_GENERIC *ntfs_enter_cache( struct CACHE_HEADER *cache,
else else
current->variable = ntfs_malloc( current->variable = ntfs_malloc(
item->varsize); item->varsize);
} } else {
else
{
if (current->varsize) if (current->varsize)
free(current->variable); free(current->variable);
current->variable = (void*)NULL; current->variable = (void*)NULL;
@ -334,15 +299,11 @@ struct CACHED_GENERIC *ntfs_enter_cache( struct CACHE_HEADER *cache,
cache->most_recent_entry->previous = current; cache->most_recent_entry->previous = current;
cache->most_recent_entry = current; cache->most_recent_entry = current;
memcpy(current->fixed, item->fixed, cache->fixed_size); memcpy(current->fixed, item->fixed, cache->fixed_size);
if ( item->varsize ) if (item->varsize) {
{ if (current->variable) {
if ( current->variable )
{
memcpy(current->variable, memcpy(current->variable,
item->variable, item->varsize); item->variable, item->varsize);
} } else {
else
{
/* /*
* no more memory for variable part * no more memory for variable part
* recycle entry in free list * recycle entry in free list
@ -353,9 +314,7 @@ struct CACHED_GENERIC *ntfs_enter_cache( struct CACHE_HEADER *cache,
cache->free_entry = current; cache->free_entry = current;
current = (struct CACHED_GENERIC*)NULL; current = (struct CACHED_GENERIC*)NULL;
} }
} } else {
else
{
current->variable = (void*)NULL; current->variable = (void*)NULL;
current->varsize = 0; current->varsize = 0;
} }
@ -425,26 +384,21 @@ int ntfs_invalidate_cache( struct CACHE_HEADER *cache,
current = (struct CACHED_GENERIC*)NULL; current = (struct CACHED_GENERIC*)NULL;
count = 0; count = 0;
if ( cache ) if (cache) {
{ if (!(flags & CACHE_NOHASH) && cache->dohash) {
if ( !( flags & CACHE_NOHASH ) && cache->dohash )
{
/* /*
* When possible, use the hash table to * When possible, use the hash table to
* find out whether the entry if present * find out whether the entry if present
*/ */
h = cache->dohash(item); h = cache->dohash(item);
link = cache->first_hash[h]; link = cache->first_hash[h];
while ( link ) while (link) {
{
if (compare(link->entry, item)) if (compare(link->entry, item))
link = link->next; link = link->next;
else else {
{
current = link->entry; current = link->entry;
link = link->next; link = link->next;
if ( current ) if (current) {
{
drophashindex(cache,current,h); drophashindex(cache,current,h);
do_invalidate(cache, do_invalidate(cache,
current,flags); current,flags);
@ -453,17 +407,14 @@ int ntfs_invalidate_cache( struct CACHE_HEADER *cache,
} }
} }
} }
if ( ( flags & CACHE_NOHASH ) || !cache->dohash ) if ((flags & CACHE_NOHASH) || !cache->dohash) {
{
/* /*
* Search sequentially in LRU list * Search sequentially in LRU list
*/ */
current = cache->most_recent_entry; current = cache->most_recent_entry;
previous = (struct CACHED_GENERIC*)NULL; previous = (struct CACHED_GENERIC*)NULL;
while ( current ) while (current) {
{ if (!compare(current, item)) {
if ( !compare( current, item ) )
{
next = current->next; next = current->next;
if (cache->dohash) if (cache->dohash)
drophashindex(cache,current, drophashindex(cache,current,
@ -471,9 +422,7 @@ int ntfs_invalidate_cache( struct CACHE_HEADER *cache,
do_invalidate(cache,current,flags); do_invalidate(cache,current,flags);
current = next; current = next;
count++; count++;
} } else {
else
{
previous = current; previous = current;
current = current->next; current = current->next;
} }
@ -489,8 +438,7 @@ int ntfs_remove_cache( struct CACHE_HEADER *cache,
int count; int count;
count = 0; count = 0;
if ( cache ) if (cache) {
{
if (cache->dohash) if (cache->dohash)
drophashindex(cache,item,cache->dohash(item)); drophashindex(cache,item,cache->dohash(item));
do_invalidate(cache,item,flags); do_invalidate(cache,item,flags);
@ -507,10 +455,8 @@ static void ntfs_free_cache( struct CACHE_HEADER *cache )
{ {
struct CACHED_GENERIC *entry; struct CACHED_GENERIC *entry;
if ( cache ) if (cache) {
{ for (entry=cache->most_recent_entry; entry; entry=entry->next) {
for ( entry = cache->most_recent_entry; entry; entry = entry->next )
{
if (cache->dofree) if (cache->dofree)
cache->dofree(entry); cache->dofree(entry);
if (entry->variable) if (entry->variable)
@ -545,18 +491,14 @@ static struct CACHE_HEADER *ntfs_create_cache( const char *name,
size += item_count*sizeof(struct HASH_ENTRY) size += item_count*sizeof(struct HASH_ENTRY)
+ max_hash*sizeof(struct HASH_ENTRY*); + max_hash*sizeof(struct HASH_ENTRY*);
cache = (struct CACHE_HEADER*)ntfs_malloc(size); cache = (struct CACHE_HEADER*)ntfs_malloc(size);
if ( cache ) if (cache) {
{
/* header */ /* header */
cache->name = name; cache->name = name;
cache->dofree = dofree; cache->dofree = dofree;
if ( dohash && max_hash ) if (dohash && max_hash) {
{
cache->dohash = dohash; cache->dohash = dohash;
cache->max_hash = max_hash; cache->max_hash = max_hash;
} } else {
else
{
cache->dohash = (cache_hash)NULL; cache->dohash = (cache_hash)NULL;
cache->max_hash = 0; cache->max_hash = 0;
} }
@ -569,8 +511,7 @@ static struct CACHE_HEADER *ntfs_create_cache( const char *name,
cache->oldest_entry = (struct CACHED_GENERIC*)NULL; cache->oldest_entry = (struct CACHED_GENERIC*)NULL;
cache->free_entry = &cache->entry[0]; cache->free_entry = &cache->entry[0];
pc = &cache->entry[0]; pc = &cache->entry[0];
for ( i = 0; i < ( item_count - 1 ); i++ ) for (i=0; i<(item_count - 1); i++) {
{
qc = (struct CACHED_GENERIC*)((char*)pc qc = (struct CACHED_GENERIC*)((char*)pc
+ full_item_size); + full_item_size);
pc->next = qc; pc->next = qc;
@ -583,20 +524,17 @@ static struct CACHE_HEADER *ntfs_create_cache( const char *name,
pc->variable = (void*)NULL; pc->variable = (void*)NULL;
pc->varsize = 0; pc->varsize = 0;
if ( max_hash ) if (max_hash) {
{
/* chain the hash entries */ /* chain the hash entries */
ph = (struct HASH_ENTRY*)(((char*)pc) + full_item_size); ph = (struct HASH_ENTRY*)(((char*)pc) + full_item_size);
cache->free_hash = ph; cache->free_hash = ph;
for ( i = 0; i < ( item_count - 1 ); i++ ) for (i=0; i<(item_count - 1); i++) {
{
qh = &ph[1]; qh = &ph[1];
ph->next = qh; ph->next = qh;
ph = qh; ph = qh;
} }
/* special for the last entry */ /* special for the last entry */
if ( item_count ) if (item_count) {
{
ph->next = (struct HASH_ENTRY*)NULL; ph->next = (struct HASH_ENTRY*)NULL;
} }
/* create and initialize the hash indexes */ /* create and initialize the hash indexes */
@ -604,9 +542,7 @@ static struct CACHE_HEADER *ntfs_create_cache( const char *name,
cache->first_hash = px; cache->first_hash = px;
for (i=0; i<max_hash; i++) for (i=0; i<max_hash; i++)
px[i] = (struct HASH_ENTRY*)NULL; px[i] = (struct HASH_ENTRY*)NULL;
} } else {
else
{
cache->free_hash = (struct HASH_ENTRY*)NULL; cache->free_hash = (struct HASH_ENTRY*)NULL;
cache->first_hash = (struct HASH_ENTRY**)NULL; cache->first_hash = (struct HASH_ENTRY**)NULL;
} }

View File

@ -24,22 +24,19 @@
#include "volume.h" #include "volume.h"
struct CACHED_GENERIC struct CACHED_GENERIC {
{
struct CACHED_GENERIC *next; struct CACHED_GENERIC *next;
struct CACHED_GENERIC *previous; struct CACHED_GENERIC *previous;
void *variable; void *variable;
size_t varsize; size_t varsize;
union union {
{
/* force alignment for pointers and u64 */ /* force alignment for pointers and u64 */
u64 u64align; u64 u64align;
void *ptralign; void *ptralign;
} fixed[0]; } fixed[0];
} ; } ;
struct CACHED_INODE struct CACHED_INODE {
{
struct CACHED_INODE *next; struct CACHED_INODE *next;
struct CACHED_INODE *previous; struct CACHED_INODE *previous;
const char *pathname; const char *pathname;
@ -48,8 +45,7 @@ struct CACHED_INODE
u64 inum; u64 inum;
} ; } ;
struct CACHED_NIDATA struct CACHED_NIDATA {
{
struct CACHED_NIDATA *next; struct CACHED_NIDATA *next;
struct CACHED_NIDATA *previous; struct CACHED_NIDATA *previous;
const char *pathname; /* not used */ const char *pathname; /* not used */
@ -59,8 +55,7 @@ struct CACHED_NIDATA
ntfs_inode *ni; ntfs_inode *ni;
} ; } ;
struct CACHED_LOOKUP struct CACHED_LOOKUP {
{
struct CACHED_LOOKUP *next; struct CACHED_LOOKUP *next;
struct CACHED_LOOKUP *previous; struct CACHED_LOOKUP *previous;
const char *name; const char *name;
@ -70,8 +65,7 @@ struct CACHED_LOOKUP
u64 inum; u64 inum;
} ; } ;
enum enum {
{
CACHE_FREE = 1, CACHE_FREE = 1,
CACHE_NOHASH = 2 CACHE_NOHASH = 2
} ; } ;
@ -81,14 +75,12 @@ typedef int ( *cache_compare )( const struct CACHED_GENERIC *cached,
typedef void (*cache_free)(const struct CACHED_GENERIC *cached); typedef void (*cache_free)(const struct CACHED_GENERIC *cached);
typedef int (*cache_hash)(const struct CACHED_GENERIC *cached); typedef int (*cache_hash)(const struct CACHED_GENERIC *cached);
struct HASH_ENTRY struct HASH_ENTRY {
{
struct HASH_ENTRY *next; struct HASH_ENTRY *next;
struct CACHED_GENERIC *entry; struct CACHED_GENERIC *entry;
} ; } ;
struct CACHE_HEADER struct CACHE_HEADER {
{
const char *name; const char *name;
struct CACHED_GENERIC *most_recent_entry; struct CACHED_GENERIC *most_recent_entry;
struct CACHED_GENERIC *oldest_entry; struct CACHED_GENERIC *oldest_entry;

View File

@ -45,27 +45,23 @@
#define CACHE_FREE UINT_MAX #define CACHE_FREE UINT_MAX
NTFS_CACHE* _NTFS_cache_constructor ( unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition, sec_t sectorSize ) NTFS_CACHE* _NTFS_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition, sec_t sectorSize) {
{
NTFS_CACHE* cache; NTFS_CACHE* cache;
unsigned int i; unsigned int i;
NTFS_CACHE_ENTRY* cacheEntries; NTFS_CACHE_ENTRY* cacheEntries;
if(numberOfPages==0 || sectorsPerPage==0) return NULL; if(numberOfPages==0 || sectorsPerPage==0) return NULL;
if ( numberOfPages < 4 ) if (numberOfPages < 4) {
{
numberOfPages = 4; numberOfPages = 4;
} }
if ( sectorsPerPage < 32 ) if (sectorsPerPage < 32) {
{
sectorsPerPage = 32; sectorsPerPage = 32;
} }
cache = (NTFS_CACHE*) ntfs_alloc (sizeof(NTFS_CACHE)); cache = (NTFS_CACHE*) ntfs_alloc (sizeof(NTFS_CACHE));
if ( cache == NULL ) if (cache == NULL) {
{
return NULL; return NULL;
} }
@ -77,14 +73,12 @@ NTFS_CACHE* _NTFS_cache_constructor ( unsigned int numberOfPages, unsigned int s
cacheEntries = (NTFS_CACHE_ENTRY*) ntfs_alloc ( sizeof(NTFS_CACHE_ENTRY) * numberOfPages); cacheEntries = (NTFS_CACHE_ENTRY*) ntfs_alloc ( sizeof(NTFS_CACHE_ENTRY) * numberOfPages);
if ( cacheEntries == NULL ) if (cacheEntries == NULL) {
{
ntfs_free (cache); ntfs_free (cache);
return NULL; return NULL;
} }
for ( i = 0; i < numberOfPages; i++ ) for (i = 0; i < numberOfPages; i++) {
{
cacheEntries[i].sector = CACHE_FREE; cacheEntries[i].sector = CACHE_FREE;
cacheEntries[i].count = 0; cacheEntries[i].count = 0;
cacheEntries[i].last_access = 0; cacheEntries[i].last_access = 0;
@ -97,8 +91,7 @@ NTFS_CACHE* _NTFS_cache_constructor ( unsigned int numberOfPages, unsigned int s
return cache; return cache;
} }
void _NTFS_cache_destructor ( NTFS_CACHE* cache ) void _NTFS_cache_destructor (NTFS_CACHE* cache) {
{
unsigned int i; unsigned int i;
if(cache==NULL) return; if(cache==NULL) return;
@ -107,8 +100,7 @@ void _NTFS_cache_destructor ( NTFS_CACHE* cache )
_NTFS_cache_flush(cache); _NTFS_cache_flush(cache);
// Free memory in reverse allocation order // Free memory in reverse allocation order
for ( i = 0; i < cache->numberOfPages; i++ ) for (i = 0; i < cache->numberOfPages; i++) {
{
ntfs_free (cache->cacheEntries[i].cache); ntfs_free (cache->cacheEntries[i].cache);
} }
ntfs_free (cache->cacheEntries); ntfs_free (cache->cacheEntries);
@ -117,8 +109,7 @@ void _NTFS_cache_destructor ( NTFS_CACHE* cache )
static u32 accessCounter = 0; static u32 accessCounter = 0;
static u32 accessTime() static u32 accessTime(){
{
accessCounter++; accessCounter++;
return accessCounter; return accessCounter;
} }
@ -134,24 +125,20 @@ static NTFS_CACHE_ENTRY* _NTFS_cache_getPage( NTFS_CACHE *cache, sec_t sector )
unsigned int oldUsed = 0; unsigned int oldUsed = 0;
unsigned int oldAccess = UINT_MAX; unsigned int oldAccess = UINT_MAX;
for ( i = 0; i < numberOfPages; i++ ) for(i=0;i<numberOfPages;i++) {
{ if(sector>=cacheEntries[i].sector && sector<(cacheEntries[i].sector + cacheEntries[i].count)) {
if ( sector >= cacheEntries[i].sector && sector < ( cacheEntries[i].sector + cacheEntries[i].count ) )
{
cacheEntries[i].last_access = accessTime(); cacheEntries[i].last_access = accessTime();
return &(cacheEntries[i]); return &(cacheEntries[i]);
} }
if ( foundFree == false && ( cacheEntries[i].sector == CACHE_FREE || cacheEntries[i].last_access < oldAccess ) ) if(foundFree==false && (cacheEntries[i].sector==CACHE_FREE || cacheEntries[i].last_access<oldAccess)) {
{
if(cacheEntries[i].sector==CACHE_FREE) foundFree = true; if(cacheEntries[i].sector==CACHE_FREE) foundFree = true;
oldUsed = i; oldUsed = i;
oldAccess = cacheEntries[i].last_access; oldAccess = cacheEntries[i].last_access;
} }
} }
if ( foundFree == false && cacheEntries[oldUsed].dirty == true ) if(foundFree==false && cacheEntries[oldUsed].dirty==true) {
{
if(!cache->disc->writeSectors(cacheEntries[oldUsed].sector,cacheEntries[oldUsed].count,cacheEntries[oldUsed].cache)) return NULL; if(!cache->disc->writeSectors(cacheEntries[oldUsed].sector,cacheEntries[oldUsed].count,cacheEntries[oldUsed].cache)) return NULL;
cacheEntries[oldUsed].dirty = false; cacheEntries[oldUsed].dirty = false;
} }
@ -168,8 +155,7 @@ static NTFS_CACHE_ENTRY* _NTFS_cache_getPage( NTFS_CACHE *cache, sec_t sector )
return &(cacheEntries[oldUsed]); return &(cacheEntries[oldUsed]);
} }
static NTFS_CACHE_ENTRY* _NTFS_cache_findPage( NTFS_CACHE *cache, sec_t sector, sec_t count ) static NTFS_CACHE_ENTRY* _NTFS_cache_findPage(NTFS_CACHE *cache, sec_t sector, sec_t count) {
{
unsigned int i; unsigned int i;
NTFS_CACHE_ENTRY* cacheEntries = cache->cacheEntries; NTFS_CACHE_ENTRY* cacheEntries = cache->cacheEntries;
@ -177,22 +163,16 @@ static NTFS_CACHE_ENTRY* _NTFS_cache_findPage( NTFS_CACHE *cache, sec_t sector,
NTFS_CACHE_ENTRY *entry = NULL; NTFS_CACHE_ENTRY *entry = NULL;
sec_t lowest = UINT_MAX; sec_t lowest = UINT_MAX;
for ( i = 0; i < numberOfPages; i++ ) for(i=0;i<numberOfPages;i++) {
{ if (cacheEntries[i].sector != CACHE_FREE) {
if ( cacheEntries[i].sector != CACHE_FREE )
{
bool intersect; bool intersect;
if ( sector > cacheEntries[i].sector ) if (sector > cacheEntries[i].sector) {
{
intersect = sector - cacheEntries[i].sector < cacheEntries[i].count; intersect = sector - cacheEntries[i].sector < cacheEntries[i].count;
} } else {
else
{
intersect = cacheEntries[i].sector - sector < count; intersect = cacheEntries[i].sector - sector < count;
} }
if ( intersect && ( cacheEntries[i].sector < lowest ) ) if ( intersect && (cacheEntries[i].sector < lowest)) {
{
lowest = cacheEntries[i].sector; lowest = cacheEntries[i].sector;
entry = &cacheEntries[i]; entry = &cacheEntries[i];
} }
@ -209,8 +189,7 @@ bool _NTFS_cache_readSectors( NTFS_CACHE *cache, sec_t sector, sec_t numSectors,
NTFS_CACHE_ENTRY *entry; NTFS_CACHE_ENTRY *entry;
uint8_t *dest = buffer; uint8_t *dest = buffer;
while ( numSectors > 0 ) while(numSectors>0) {
{
entry = _NTFS_cache_getPage(cache,sector); entry = _NTFS_cache_getPage(cache,sector);
if(entry==NULL) return false; if(entry==NULL) return false;
@ -248,13 +227,11 @@ bool _NTFS_cache_readPartialSector ( NTFS_CACHE* cache, void* buffer, sec_t sect
return true; return true;
} }
bool _NTFS_cache_readLittleEndianValue ( NTFS_CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes ) bool _NTFS_cache_readLittleEndianValue (NTFS_CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes) {
{
uint8_t buf[4]; uint8_t buf[4];
if (!_NTFS_cache_readPartialSector(cache, buf, sector, offset, num_bytes)) return false; if (!_NTFS_cache_readPartialSector(cache, buf, sector, offset, num_bytes)) return false;
switch ( num_bytes ) switch(num_bytes) {
{
case 1: *value = buf[0]; break; case 1: *value = buf[0]; break;
case 2: *value = u8array_to_u16(buf,0); break; case 2: *value = u8array_to_u16(buf,0); break;
case 4: *value = u8array_to_u32(buf,0); break; case 4: *value = u8array_to_u32(buf,0); break;
@ -284,12 +261,10 @@ bool _NTFS_cache_writePartialSector ( NTFS_CACHE* cache, const void* buffer, sec
return true; return true;
} }
bool _NTFS_cache_writeLittleEndianValue ( NTFS_CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int size ) bool _NTFS_cache_writeLittleEndianValue (NTFS_CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int size) {
{
uint8_t buf[4] = {0, 0, 0, 0}; uint8_t buf[4] = {0, 0, 0, 0};
switch ( size ) switch(size) {
{
case 1: buf[0] = value; break; case 1: buf[0] = value; break;
case 2: u16_to_u8array(buf, 0, value); break; case 2: u16_to_u8array(buf, 0, value); break;
case 4: u32_to_u8array(buf, 0, value); break; case 4: u32_to_u8array(buf, 0, value); break;
@ -332,11 +307,9 @@ bool _NTFS_cache_writeSectors ( NTFS_CACHE* cache, sec_t sector, sec_t numSector
{ {
entry = _NTFS_cache_findPage(cache,sector,numSectors); entry = _NTFS_cache_findPage(cache,sector,numSectors);
if ( entry != NULL ) if(entry!=NULL) {
{
if ( entry->sector > sector ) if ( entry->sector > sector) {
{
secs_to_write = entry->sector - sector; secs_to_write = entry->sector - sector;
@ -359,9 +332,7 @@ bool _NTFS_cache_writeSectors ( NTFS_CACHE* cache, sec_t sector, sec_t numSector
entry->dirty = true; entry->dirty = true;
} } else {
else
{
cache->disc->writeSectors(sector,numSectors,src); cache->disc->writeSectors(sector,numSectors,src);
numSectors=0; numSectors=0;
} }
@ -372,17 +343,13 @@ bool _NTFS_cache_writeSectors ( NTFS_CACHE* cache, sec_t sector, sec_t numSector
/* /*
Flushes all dirty pages to disc, clearing the dirty flag. Flushes all dirty pages to disc, clearing the dirty flag.
*/ */
bool _NTFS_cache_flush ( NTFS_CACHE* cache ) bool _NTFS_cache_flush (NTFS_CACHE* cache) {
{
unsigned int i; unsigned int i;
if(cache==NULL) return true; if(cache==NULL) return true;
for ( i = 0; i < cache->numberOfPages; i++ ) for (i = 0; i < cache->numberOfPages; i++) {
{ if (cache->cacheEntries[i].dirty) {
if ( cache->cacheEntries[i].dirty ) if (!cache->disc->writeSectors (cache->cacheEntries[i].sector, cache->cacheEntries[i].count, cache->cacheEntries[i].cache)) {
{
if ( !cache->disc->writeSectors ( cache->cacheEntries[i].sector, cache->cacheEntries[i].count, cache->cacheEntries[i].cache ) )
{
return false; return false;
} }
} }
@ -392,15 +359,13 @@ bool _NTFS_cache_flush ( NTFS_CACHE* cache )
return true; return true;
} }
void _NTFS_cache_invalidate ( NTFS_CACHE* cache ) void _NTFS_cache_invalidate (NTFS_CACHE* cache) {
{
unsigned int i; unsigned int i;
if(cache==NULL) if(cache==NULL)
return; return;
_NTFS_cache_flush(cache); _NTFS_cache_flush(cache);
for ( i = 0; i < cache->numberOfPages; i++ ) for (i = 0; i < cache->numberOfPages; i++) {
{
cache->cacheEntries[i].sector = CACHE_FREE; cache->cacheEntries[i].sector = CACHE_FREE;
cache->cacheEntries[i].last_access = 0; cache->cacheEntries[i].last_access = 0;
cache->cacheEntries[i].count = 0; cache->cacheEntries[i].count = 0;

View File

@ -46,8 +46,7 @@
#include <ogc/disc_io.h> #include <ogc/disc_io.h>
#include <gccore.h> #include <gccore.h>
typedef struct typedef struct {
{
sec_t sector; sec_t sector;
unsigned int count; unsigned int count;
u64 last_access; u64 last_access;
@ -55,8 +54,7 @@ typedef struct
u8* cache; u8* cache;
} NTFS_CACHE_ENTRY; } NTFS_CACHE_ENTRY;
typedef struct typedef struct {
{
const DISC_INTERFACE* disc; const DISC_INTERFACE* disc;
sec_t endOfPartition; sec_t endOfPartition;
unsigned int numberOfPages; unsigned int numberOfPages;

View File

@ -60,8 +60,7 @@ static int ntfs_collate_binary( ntfs_volume *vol __attribute__( ( unused ) ),
ntfs_log_trace("Entering.\n"); ntfs_log_trace("Entering.\n");
rc = memcmp(data1, data2, min(data1_len, data2_len)); rc = memcmp(data1, data2, min(data1_len, data2_len));
if ( !rc && ( data1_len != data2_len ) ) if (!rc && (data1_len != data2_len)) {
{
if (data1_len < data2_len) if (data1_len < data2_len)
rc = -1; rc = -1;
else else
@ -91,8 +90,7 @@ static int ntfs_collate_ntofs_ulong( ntfs_volume *vol __attribute__( ( unused )
u32 d1, d2; u32 d1, d2;
ntfs_log_trace("Entering.\n"); ntfs_log_trace("Entering.\n");
if ( data1_len != data2_len || data1_len != 4 ) if (data1_len != data2_len || data1_len != 4) {
{
ntfs_log_error("data1_len or/and data2_len not equal to 4.\n"); ntfs_log_error("data1_len or/and data2_len not equal to 4.\n");
return NTFS_COLLATION_ERROR; return NTFS_COLLATION_ERROR;
} }
@ -100,8 +98,7 @@ static int ntfs_collate_ntofs_ulong( ntfs_volume *vol __attribute__( ( unused )
d2 = le32_to_cpup(data2); d2 = le32_to_cpup(data2);
if (d1 < d2) if (d1 < d2)
rc = -1; rc = -1;
else else {
{
if (d1 == d2) if (d1 == d2)
rc = 0; rc = 0;
else else
@ -127,26 +124,22 @@ static int ntfs_collate_ntofs_ulongs( ntfs_volume *vol __attribute__( ( unused )
u32 d1, d2; u32 d1, d2;
ntfs_log_trace("Entering.\n"); ntfs_log_trace("Entering.\n");
if ( ( data1_len != data2_len ) || ( data1_len <= 0 ) || ( data1_len & 3 ) ) if ((data1_len != data2_len) || (data1_len <= 0) || (data1_len & 3)) {
{
ntfs_log_error("data1_len or data2_len not valid\n"); ntfs_log_error("data1_len or data2_len not valid\n");
return NTFS_COLLATION_ERROR; return NTFS_COLLATION_ERROR;
} }
p1 = (const le32*)data1; p1 = (const le32*)data1;
p2 = (const le32*)data2; p2 = (const le32*)data2;
len = data1_len; len = data1_len;
do do {
{
d1 = le32_to_cpup(p1); d1 = le32_to_cpup(p1);
p1++; p1++;
d2 = le32_to_cpup(p2); d2 = le32_to_cpup(p2);
p2++; p2++;
} } while ((d1 == d2) && ((len -= 4) > 0));
while ( ( d1 == d2 ) && ( ( len -= 4 ) > 0 ) );
if (d1 < d2) if (d1 < d2)
rc = -1; rc = -1;
else else {
{
if (d1 == d2) if (d1 == d2)
rc = 0; rc = 0;
else else
@ -178,8 +171,7 @@ static int ntfs_collate_ntofs_security_hash( ntfs_volume *vol __attribute__( ( u
const le32 *p1, *p2; const le32 *p1, *p2;
ntfs_log_trace("Entering.\n"); ntfs_log_trace("Entering.\n");
if ( data1_len != data2_len || data1_len != 8 ) if (data1_len != data2_len || data1_len != 8) {
{
ntfs_log_error("data1_len or/and data2_len not equal to 8.\n"); ntfs_log_error("data1_len or/and data2_len not equal to 8.\n");
return NTFS_COLLATION_ERROR; return NTFS_COLLATION_ERROR;
} }
@ -189,20 +181,17 @@ static int ntfs_collate_ntofs_security_hash( ntfs_volume *vol __attribute__( ( u
d2 = le32_to_cpup(p2); d2 = le32_to_cpup(p2);
if (d1 < d2) if (d1 < d2)
rc = -1; rc = -1;
else else {
{
if (d1 > d2) if (d1 > d2)
rc = 1; rc = 1;
else else {
{
p1++; p1++;
p2++; p2++;
d1 = le32_to_cpup(p1); d1 = le32_to_cpup(p1);
d2 = le32_to_cpup(p2); d2 = le32_to_cpup(p2);
if (d1 < d2) if (d1 < d2)
rc = -1; rc = -1;
else else {
{
if (d1 > d2) if (d1 > d2)
rc = 1; rc = 1;
else else
@ -257,8 +246,7 @@ COLLATE ntfs_get_collate_function( COLLATION_RULES cr )
{ {
COLLATE collate; COLLATE collate;
switch ( cr ) switch (cr) {
{
case COLLATION_BINARY : case COLLATION_BINARY :
collate = ntfs_collate_binary; collate = ntfs_collate_binary;
break; break;

View File

@ -41,28 +41,23 @@ int ffs( int x )
if (!x) if (!x)
return 0; return 0;
if ( !( x & 0xffff ) ) if (!(x & 0xffff)) {
{
x >>= 16; x >>= 16;
r += 16; r += 16;
} }
if ( !( x & 0xff ) ) if (!(x & 0xff)) {
{
x >>= 8; x >>= 8;
r += 8; r += 8;
} }
if ( !( x & 0xf ) ) if (!(x & 0xf)) {
{
x >>= 4; x >>= 4;
r += 4; r += 4;
} }
if ( !( x & 3 ) ) if (!(x & 3)) {
{
x >>= 2; x >>= 2;
r += 2; r += 2;
} }
if ( !( x & 1 ) ) if (!(x & 1)) {
{
x >>= 1; x >>= 1;
r += 1; r += 1;
} }
@ -125,12 +120,10 @@ static const char rcsid[] = "$Id: compat.c,v 1.1.1.1.2.1 2008-08-16 15:17:44 jpa
#include <unistd.h> #include <unistd.h>
#endif #endif
int daemon( int nochdir, int noclose ) int daemon(int nochdir, int noclose) {
{
int fd; int fd;
switch ( fork() ) switch (fork()) {
{
case -1: case -1:
return (-1); return (-1);
case 0: case 0:
@ -145,8 +138,7 @@ int daemon( int nochdir, int noclose )
if (!nochdir) if (!nochdir)
(void)chdir("/"); (void)chdir("/");
if ( !noclose && ( fd = open( "/dev/null", O_RDWR, 0 ) ) != -1 ) if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
{
(void)dup2(fd, 0); (void)dup2(fd, 0);
(void)dup2(fd, 1); (void)dup2(fd, 1);
(void)dup2(fd, 2); (void)dup2(fd, 2);
@ -226,8 +218,7 @@ static const char rcsid[] = "$Id: compat.c,v 1.1.1.1.2.1 2008-08-16 15:17:44 jpa
* *
* If *stringp is NULL, strsep returns NULL. * If *stringp is NULL, strsep returns NULL.
*/ */
char *strsep( char **stringp, const char *delim ) char *strsep(char **stringp, const char *delim) {
{
char *s; char *s;
const char *spanp; const char *spanp;
int c, sc; int c, sc;
@ -235,14 +226,11 @@ char *strsep( char **stringp, const char *delim )
if ((s = *stringp) == NULL) if ((s = *stringp) == NULL)
return (NULL); return (NULL);
for ( tok = s;; ) for (tok = s;;) {
{
c = *s++; c = *s++;
spanp = delim; spanp = delim;
do do {
{ if ((sc = *spanp++) == c) {
if ( ( sc = *spanp++ ) == c )
{
if (c == 0) if (c == 0)
s = NULL; s = NULL;
else else
@ -250,8 +238,7 @@ char *strsep( char **stringp, const char *delim )
*stringp = s; *stringp = s;
return (tok); return (tok);
} }
} } while (sc != 0);
while ( sc != 0 );
} }
/* NOTREACHED */ /* NOTREACHED */
} }

File diff suppressed because it is too large Load Diff

View File

@ -47,22 +47,18 @@ void ntfs_debug_runlist_dump( const runlist_element *rl )
int i = 0; int i = 0;
const char *lcn_str[5] = { "LCN_HOLE ", "LCN_RL_NOT_MAPPED", const char *lcn_str[5] = { "LCN_HOLE ", "LCN_RL_NOT_MAPPED",
"LCN_ENOENT ", "LCN_EINVAL ", "LCN_ENOENT ", "LCN_EINVAL ",
"LCN_unknown " "LCN_unknown " };
};
ntfs_log_debug("NTFS-fs DEBUG: Dumping runlist (values in hex):\n"); ntfs_log_debug("NTFS-fs DEBUG: Dumping runlist (values in hex):\n");
if ( !rl ) if (!rl) {
{
ntfs_log_debug("Run list not present.\n"); ntfs_log_debug("Run list not present.\n");
return; return;
} }
ntfs_log_debug("VCN LCN Run length\n"); ntfs_log_debug("VCN LCN Run length\n");
do do {
{
LCN lcn = (rl + i)->lcn; LCN lcn = (rl + i)->lcn;
if ( lcn < ( LCN )0 ) if (lcn < (LCN)0) {
{
int idx = -lcn - 1; int idx = -lcn - 1;
if (idx > -LCN_EINVAL - 1) if (idx > -LCN_EINVAL - 1)
@ -71,14 +67,12 @@ void ntfs_debug_runlist_dump( const runlist_element *rl )
(long long)rl[i].vcn, lcn_str[idx], (long long)rl[i].vcn, lcn_str[idx],
(long long)rl[i].length, (long long)rl[i].length,
rl[i].length ? "" : " (runlist end)"); rl[i].length ? "" : " (runlist end)");
} } else
else
ntfs_log_debug("%-16lld %-16lld %-16lld%s\n", ntfs_log_debug("%-16lld %-16lld %-16lld%s\n",
(long long)rl[i].vcn, (long long)rl[i].lcn, (long long)rl[i].vcn, (long long)rl[i].lcn,
(long long)rl[i].length, (long long)rl[i].length,
rl[i].length ? "" : " (runlist end)"); rl[i].length ? "" : " (runlist end)");
} } while (rl[i++].length);
while ( rl[i++].length );
} }
#endif #endif

View File

@ -108,17 +108,14 @@ struct ntfs_device *ntfs_device_alloc( const char *name, const long state,
{ {
struct ntfs_device *dev; struct ntfs_device *dev;
if ( !name ) if (!name) {
{
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} }
dev = ntfs_malloc(sizeof(struct ntfs_device)); dev = ntfs_malloc(sizeof(struct ntfs_device));
if ( dev ) if (dev) {
{ if (!(dev->d_name = strdup(name))) {
if ( !( dev->d_name = strdup( name ) ) )
{
int eo = errno; int eo = errno;
free(dev); free(dev);
errno = eo; errno = eo;
@ -144,13 +141,11 @@ struct ntfs_device *ntfs_device_alloc( const char *name, const long state,
*/ */
int ntfs_device_free(struct ntfs_device *dev) int ntfs_device_free(struct ntfs_device *dev)
{ {
if ( !dev ) if (!dev) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
if ( NDevOpen( dev ) ) if (NDevOpen(dev)) {
{
errno = EBUSY; errno = EBUSY;
return -1; return -1;
} }
@ -185,8 +180,7 @@ s64 ntfs_pread( struct ntfs_device *dev, const s64 pos, s64 count, void *b )
ntfs_log_trace("pos %lld, count %lld\n",(long long)pos,(long long)count); ntfs_log_trace("pos %lld, count %lld\n",(long long)pos,(long long)count);
if ( !b || count < 0 || pos < 0 ) if (!b || count < 0 || pos < 0) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@ -195,8 +189,7 @@ s64 ntfs_pread( struct ntfs_device *dev, const s64 pos, s64 count, void *b )
dops = dev->d_ops; dops = dev->d_ops;
for ( total = 0; count; count -= br, total += br ) for (total = 0; count; count -= br, total += br) {
{
br = dops->pread(dev, (char*)b + total, count, pos + total); br = dops->pread(dev, (char*)b + total, count, pos + total);
/* If everything ok, continue. */ /* If everything ok, continue. */
if (br > 0) if (br > 0)
@ -238,15 +231,13 @@ s64 ntfs_pwrite( struct ntfs_device *dev, const s64 pos, s64 count,
ntfs_log_trace("pos %lld, count %lld\n",(long long)pos,(long long)count); ntfs_log_trace("pos %lld, count %lld\n",(long long)pos,(long long)count);
if ( !b || count < 0 || pos < 0 ) if (!b || count < 0 || pos < 0) {
{
errno = EINVAL; errno = EINVAL;
goto out; goto out;
} }
if (!count) if (!count)
return 0; return 0;
if ( NDevReadOnly( dev ) ) if (NDevReadOnly(dev)) {
{
errno = EROFS; errno = EROFS;
goto out; goto out;
} }
@ -254,8 +245,7 @@ s64 ntfs_pwrite( struct ntfs_device *dev, const s64 pos, s64 count,
dops = dev->d_ops; dops = dev->d_ops;
NDevSetDirty(dev); NDevSetDirty(dev);
for ( total = 0; count; count -= written, total += written ) for (total = 0; count; count -= written, total += written) {
{
written = dops->pwrite(dev, (const char*)b + total, count, written = dops->pwrite(dev, (const char*)b + total, count,
pos + total); pos + total);
/* If everything ok, continue. */ /* If everything ok, continue. */
@ -309,8 +299,7 @@ s64 ntfs_mst_pread( struct ntfs_device *dev, const s64 pos, s64 count,
{ {
s64 br, i; s64 br, i;
if ( bksize & ( bksize - 1 ) || bksize % NTFS_BLOCK_SIZE ) if (bksize & (bksize - 1) || bksize % NTFS_BLOCK_SIZE) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@ -367,22 +356,19 @@ s64 ntfs_mst_pwrite( struct ntfs_device *dev, const s64 pos, s64 count,
{ {
s64 written, i; s64 written, i;
if ( count < 0 || bksize % NTFS_BLOCK_SIZE ) if (count < 0 || bksize % NTFS_BLOCK_SIZE) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
if (!count) if (!count)
return 0; return 0;
/* Prepare data for writing. */ /* Prepare data for writing. */
for ( i = 0; i < count; ++i ) for (i = 0; i < count; ++i) {
{
int err; int err;
err = ntfs_mst_pre_write_fixup((NTFS_RECORD*) err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)
((u8*)b + i * bksize), bksize); ((u8*)b + i * bksize), bksize);
if ( err < 0 ) if (err < 0) {
{
/* Abort write at this position. */ /* Abort write at this position. */
if (!i) if (!i)
return err; return err;
@ -417,13 +403,11 @@ s64 ntfs_cluster_read( const ntfs_volume *vol, const s64 lcn, const s64 count,
{ {
s64 br; s64 br;
if ( !vol || lcn < 0 || count < 0 ) if (!vol || lcn < 0 || count < 0) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
if ( vol->nr_clusters < lcn + count ) if (vol->nr_clusters < lcn + count) {
{
errno = ESPIPE; errno = ESPIPE;
ntfs_log_perror("Trying to read outside of volume " ntfs_log_perror("Trying to read outside of volume "
"(%lld < %lld)", (long long)vol->nr_clusters, "(%lld < %lld)", (long long)vol->nr_clusters,
@ -432,8 +416,7 @@ s64 ntfs_cluster_read( const ntfs_volume *vol, const s64 lcn, const s64 count,
} }
br = ntfs_pread(vol->dev, lcn << vol->cluster_size_bits, br = ntfs_pread(vol->dev, lcn << vol->cluster_size_bits,
count << vol->cluster_size_bits, b); count << vol->cluster_size_bits, b);
if ( br < 0 ) if (br < 0) {
{
ntfs_log_perror("Error reading cluster(s)"); ntfs_log_perror("Error reading cluster(s)");
return br; return br;
} }
@ -456,13 +439,11 @@ s64 ntfs_cluster_write( const ntfs_volume *vol, const s64 lcn,
{ {
s64 bw; s64 bw;
if ( !vol || lcn < 0 || count < 0 ) if (!vol || lcn < 0 || count < 0) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
if ( vol->nr_clusters < lcn + count ) if (vol->nr_clusters < lcn + count) {
{
errno = ESPIPE; errno = ESPIPE;
ntfs_log_perror("Trying to write outside of volume " ntfs_log_perror("Trying to write outside of volume "
"(%lld < %lld)", (long long)vol->nr_clusters, "(%lld < %lld)", (long long)vol->nr_clusters,
@ -474,8 +455,7 @@ s64 ntfs_cluster_write( const ntfs_volume *vol, const s64 lcn,
count << vol->cluster_size_bits, b); count << vol->cluster_size_bits, b);
else else
bw = count << vol->cluster_size_bits; bw = count << vol->cluster_size_bits;
if ( bw < 0 ) if (bw < 0) {
{
ntfs_log_perror("Error writing cluster(s)"); ntfs_log_perror("Error writing cluster(s)");
return bw; return bw;
} }
@ -518,16 +498,14 @@ s64 ntfs_device_size_get( struct ntfs_device *dev, int block_size )
{ {
s64 high, low; s64 high, low;
if ( !dev || block_size <= 0 || ( block_size - 1 ) & block_size ) if (!dev || block_size <= 0 || (block_size - 1) & block_size) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
#ifdef BLKGETSIZE64 #ifdef BLKGETSIZE64
{ u64 size; { u64 size;
if ( dev->d_ops->ioctl( dev, BLKGETSIZE64, &size ) >= 0 ) if (dev->d_ops->ioctl(dev, BLKGETSIZE64, &size) >= 0) {
{
ntfs_log_debug("BLKGETSIZE64 nr bytes = %llu (0x%llx)\n", ntfs_log_debug("BLKGETSIZE64 nr bytes = %llu (0x%llx)\n",
(unsigned long long)size, (unsigned long long)size,
(unsigned long long)size); (unsigned long long)size);
@ -538,8 +516,7 @@ s64 ntfs_device_size_get( struct ntfs_device *dev, int block_size )
#ifdef BLKGETSIZE #ifdef BLKGETSIZE
{ unsigned long size; { unsigned long size;
if ( dev->d_ops->ioctl( dev, BLKGETSIZE, &size ) >= 0 ) if (dev->d_ops->ioctl(dev, BLKGETSIZE, &size) >= 0) {
{
ntfs_log_debug("BLKGETSIZE nr 512 byte blocks = %lu (0x%lx)\n", ntfs_log_debug("BLKGETSIZE nr 512 byte blocks = %lu (0x%lx)\n",
size, size); size, size);
return (s64)size * 512 / block_size; return (s64)size * 512 / block_size;
@ -549,8 +526,7 @@ s64 ntfs_device_size_get( struct ntfs_device *dev, int block_size )
#ifdef FDGETPRM #ifdef FDGETPRM
{ struct floppy_struct this_floppy; { struct floppy_struct this_floppy;
if ( dev->d_ops->ioctl( dev, FDGETPRM, &this_floppy ) >= 0 ) if (dev->d_ops->ioctl(dev, FDGETPRM, &this_floppy) >= 0) {
{
ntfs_log_debug("FDGETPRM nr 512 byte blocks = %lu (0x%lx)\n", ntfs_log_debug("FDGETPRM nr 512 byte blocks = %lu (0x%lx)\n",
(unsigned long)this_floppy.size, (unsigned long)this_floppy.size,
(unsigned long)this_floppy.size); (unsigned long)this_floppy.size);
@ -565,8 +541,7 @@ s64 ntfs_device_size_get( struct ntfs_device *dev, int block_size )
low = 0LL; low = 0LL;
for (high = 1024LL; !ntfs_device_offset_valid(dev, high); high <<= 1) for (high = 1024LL; !ntfs_device_offset_valid(dev, high); high <<= 1)
low = high; low = high;
while ( low < high - 1LL ) while (low < high - 1LL) {
{
const s64 mid = (low + high) / 2; const s64 mid = (low + high) / 2;
if (!ntfs_device_offset_valid(dev, mid)) if (!ntfs_device_offset_valid(dev, mid))
@ -592,16 +567,14 @@ s64 ntfs_device_size_get( struct ntfs_device *dev, int block_size )
*/ */
s64 ntfs_device_partition_start_sector_get(struct ntfs_device *dev) s64 ntfs_device_partition_start_sector_get(struct ntfs_device *dev)
{ {
if ( !dev ) if (!dev) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
#ifdef HDIO_GETGEO #ifdef HDIO_GETGEO
{ struct hd_geometry geo; { struct hd_geometry geo;
if ( !dev->d_ops->ioctl( dev, HDIO_GETGEO, &geo ) ) if (!dev->d_ops->ioctl(dev, HDIO_GETGEO, &geo)) {
{
ntfs_log_debug("HDIO_GETGEO start_sect = %lu (0x%lx)\n", ntfs_log_debug("HDIO_GETGEO start_sect = %lu (0x%lx)\n",
geo.start, geo.start); geo.start, geo.start);
return geo.start; return geo.start;
@ -627,16 +600,14 @@ s64 ntfs_device_partition_start_sector_get( struct ntfs_device *dev )
*/ */
int ntfs_device_heads_get(struct ntfs_device *dev) int ntfs_device_heads_get(struct ntfs_device *dev)
{ {
if ( !dev ) if (!dev) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
#ifdef HDIO_GETGEO #ifdef HDIO_GETGEO
{ struct hd_geometry geo; { struct hd_geometry geo;
if ( !dev->d_ops->ioctl( dev, HDIO_GETGEO, &geo ) ) if (!dev->d_ops->ioctl(dev, HDIO_GETGEO, &geo)) {
{
ntfs_log_debug("HDIO_GETGEO heads = %u (0x%x)\n", ntfs_log_debug("HDIO_GETGEO heads = %u (0x%x)\n",
(unsigned)geo.heads, (unsigned)geo.heads,
(unsigned)geo.heads); (unsigned)geo.heads);
@ -663,16 +634,14 @@ int ntfs_device_heads_get( struct ntfs_device *dev )
*/ */
int ntfs_device_sectors_per_track_get(struct ntfs_device *dev) int ntfs_device_sectors_per_track_get(struct ntfs_device *dev)
{ {
if ( !dev ) if (!dev) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
#ifdef HDIO_GETGEO #ifdef HDIO_GETGEO
{ struct hd_geometry geo; { struct hd_geometry geo;
if ( !dev->d_ops->ioctl( dev, HDIO_GETGEO, &geo ) ) if (!dev->d_ops->ioctl(dev, HDIO_GETGEO, &geo)) {
{
ntfs_log_debug("HDIO_GETGEO sectors_per_track = %u (0x%x)\n", ntfs_log_debug("HDIO_GETGEO sectors_per_track = %u (0x%x)\n",
(unsigned)geo.sectors, (unsigned)geo.sectors,
(unsigned)geo.sectors); (unsigned)geo.sectors);
@ -699,8 +668,7 @@ int ntfs_device_sectors_per_track_get( struct ntfs_device *dev )
*/ */
int ntfs_device_sector_size_get(struct ntfs_device *dev) int ntfs_device_sector_size_get(struct ntfs_device *dev)
{ {
if ( !dev ) if (!dev) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@ -708,8 +676,7 @@ int ntfs_device_sector_size_get( struct ntfs_device *dev )
{ {
int sect_size = 0; int sect_size = 0;
if ( !dev->d_ops->ioctl( dev, BLKSSZGET, &sect_size ) ) if (!dev->d_ops->ioctl(dev, BLKSSZGET, &sect_size)) {
{
ntfs_log_debug("BLKSSZGET sector size = %d bytes\n", ntfs_log_debug("BLKSSZGET sector size = %d bytes\n",
sect_size); sect_size);
return sect_size; return sect_size;
@ -737,16 +704,14 @@ int ntfs_device_sector_size_get( struct ntfs_device *dev )
int ntfs_device_block_size_set(struct ntfs_device *dev, int ntfs_device_block_size_set(struct ntfs_device *dev,
int block_size __attribute__((unused))) int block_size __attribute__((unused)))
{ {
if ( !dev ) if (!dev) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
#ifdef BLKBSZSET #ifdef BLKBSZSET
{ {
size_t s_block_size = block_size; size_t s_block_size = block_size;
if ( !dev->d_ops->ioctl( dev, BLKBSZSET, &s_block_size ) ) if (!dev->d_ops->ioctl(dev, BLKBSZSET, &s_block_size)) {
{
ntfs_log_debug("Used BLKBSZSET to set block size to " ntfs_log_debug("Used BLKBSZSET to set block size to "
"%d bytes.\n", block_size); "%d bytes.\n", block_size);
return 0; return 0;

View File

@ -36,8 +36,7 @@
* *
* Defined bits for the state field in the ntfs_device structure. * Defined bits for the state field in the ntfs_device structure.
*/ */
typedef enum typedef enum {
{
ND_Open, /* 1: Device is open. */ ND_Open, /* 1: Device is open. */
ND_ReadOnly, /* 1: Device is read-only. */ ND_ReadOnly, /* 1: Device is read-only. */
ND_Dirty, /* 1: Device is dirty, needs sync. */ ND_Dirty, /* 1: Device is dirty, needs sync. */
@ -70,8 +69,7 @@ typedef enum
* The ntfs device structure defining all operations needed to access the low * The ntfs device structure defining all operations needed to access the low
* level device underlying the ntfs volume. * level device underlying the ntfs volume.
*/ */
struct ntfs_device struct ntfs_device {
{
struct ntfs_device_operations *d_ops; /* Device operations. */ struct ntfs_device_operations *d_ops; /* Device operations. */
unsigned long d_state; /* State of the device. */ unsigned long d_state; /* State of the device. */
char *d_name; /* Name of device. */ char *d_name; /* Name of device. */
@ -87,8 +85,7 @@ struct stat;
* The ntfs device operations defining all operations that can be performed on * The ntfs device operations defining all operations that can be performed on
* the low level device described by an ntfs device structure. * the low level device described by an ntfs device structure.
*/ */
struct ntfs_device_operations struct ntfs_device_operations {
{
int (*open)(struct ntfs_device *dev, int flags); int (*open)(struct ntfs_device *dev, int flags);
int (*close)(struct ntfs_device *dev); int (*close)(struct ntfs_device *dev);
s64 (*seek)(struct ntfs_device *dev, s64 offset, int whence); s64 (*seek)(struct ntfs_device *dev, s64 offset, int whence);

View File

@ -45,8 +45,7 @@
/** /**
* struct hd_geometry - * struct hd_geometry -
*/ */
struct hd_geometry struct hd_geometry {
{
unsigned char heads; unsigned char heads;
unsigned char sectors; unsigned char sectors;
unsigned short cylinders; unsigned short cylinders;

File diff suppressed because it is too large Load Diff

View File

@ -60,8 +60,7 @@
#ifdef HAVE_SETXATTR /* extended attributes interface required */ #ifdef HAVE_SETXATTR /* extended attributes interface required */
static ntfschar logged_utility_stream_name[] = static ntfschar logged_utility_stream_name[] = {
{
const_cpu_to_le16('$'), const_cpu_to_le16('$'),
const_cpu_to_le16('E'), const_cpu_to_le16('E'),
const_cpu_to_le16('F'), const_cpu_to_le16('F'),
@ -79,43 +78,32 @@ int ntfs_get_efs_info( ntfs_inode *ni, char *value, size_t size )
EFS_ATTR_HEADER *efs_info; EFS_ATTR_HEADER *efs_info;
s64 attr_size = 0; s64 attr_size = 0;
if ( ni ) if (ni) {
{ if (ni->flags & FILE_ATTR_ENCRYPTED) {
if ( ni->flags & FILE_ATTR_ENCRYPTED )
{
efs_info = (EFS_ATTR_HEADER*)ntfs_attr_readall(ni, efs_info = (EFS_ATTR_HEADER*)ntfs_attr_readall(ni,
AT_LOGGED_UTILITY_STREAM,(ntfschar*)NULL, 0, AT_LOGGED_UTILITY_STREAM,(ntfschar*)NULL, 0,
&attr_size); &attr_size);
if (efs_info if (efs_info
&& ( le32_to_cpu( efs_info->length ) == attr_size ) ) && (le32_to_cpu(efs_info->length) == attr_size)) {
{ if (attr_size <= (s64)size) {
if ( attr_size <= ( s64 )size )
{
if (value) if (value)
memcpy(value,efs_info,attr_size); memcpy(value,efs_info,attr_size);
else else {
{
errno = EFAULT; errno = EFAULT;
attr_size = 0; attr_size = 0;
} }
} } else
else if ( size ) if (size) {
{
errno = ERANGE; errno = ERANGE;
attr_size = 0; attr_size = 0;
} }
free (efs_info); free (efs_info);
} } else {
else if (efs_info) {
{
if ( efs_info )
{
free(efs_info); free(efs_info);
ntfs_log_error("Bad efs_info for inode %lld\n", ntfs_log_error("Bad efs_info for inode %lld\n",
(long long)ni->mft_no); (long long)ni->mft_no);
} } else {
else
{
ntfs_log_error("Could not get efsinfo" ntfs_log_error("Could not get efsinfo"
" for inode %lld\n", " for inode %lld\n",
(long long)ni->mft_no); (long long)ni->mft_no);
@ -123,9 +111,7 @@ int ntfs_get_efs_info( ntfs_inode *ni, char *value, size_t size )
errno = EIO; errno = EIO;
attr_size = 0; attr_size = 0;
} }
} } else {
else
{
errno = ENODATA; errno = ENODATA;
ntfs_log_trace("Inode %lld is not encrypted\n", ntfs_log_trace("Inode %lld is not encrypted\n",
(long long)ni->mft_no); (long long)ni->mft_no);
@ -159,57 +145,45 @@ static int fixup_loop( ntfs_inode *ni )
int res = 0; int res = 0;
maxcnt = 0; maxcnt = 0;
do do {
{
restart = FALSE; restart = FALSE;
ctx = ntfs_attr_get_search_ctx(ni, NULL); ctx = ntfs_attr_get_search_ctx(ni, NULL);
if ( !ctx ) if (!ctx) {
{
ntfs_log_error("Failed to get ctx for efs\n"); ntfs_log_error("Failed to get ctx for efs\n");
res = -1; res = -1;
} }
cnt = 0; cnt = 0;
while (!restart && !res while (!restart && !res
&& !ntfs_attr_lookup(AT_DATA, NULL, 0, && !ntfs_attr_lookup(AT_DATA, NULL, 0,
CASE_SENSITIVE, 0, NULL, 0, ctx ) ) CASE_SENSITIVE, 0, NULL, 0, ctx)) {
{
cnt++; cnt++;
a = ctx->attr; a = ctx->attr;
na = ntfs_attr_open(ctx->ntfs_ino, AT_DATA, na = ntfs_attr_open(ctx->ntfs_ino, AT_DATA,
(ntfschar*)((u8*)a + le16_to_cpu(a->name_offset)), (ntfschar*)((u8*)a + le16_to_cpu(a->name_offset)),
a->name_length); a->name_length);
if ( !na ) if (!na) {
{
ntfs_log_error("can't open DATA Attribute\n"); ntfs_log_error("can't open DATA Attribute\n");
res = -1; res = -1;
} }
if ( na && !( ctx->attr->flags & ATTR_IS_ENCRYPTED ) ) if (na && !(ctx->attr->flags & ATTR_IS_ENCRYPTED)) {
{
if (!NAttrNonResident(na) if (!NAttrNonResident(na)
&& ntfs_attr_make_non_resident( na, ctx ) ) && ntfs_attr_make_non_resident(na, ctx)) {
{
/* /*
* ntfs_attr_make_non_resident fails if there * ntfs_attr_make_non_resident fails if there
* is not enough space in the MFT record. * is not enough space in the MFT record.
* When this happens, force making non-resident * When this happens, force making non-resident
* so that some other attribute is expelled. * so that some other attribute is expelled.
*/ */
if ( ntfs_attr_force_non_resident( na ) ) if (ntfs_attr_force_non_resident(na)) {
{
res = -1; res = -1;
} } else {
else
{
/* make sure there is some progress */ /* make sure there is some progress */
if ( cnt <= maxcnt ) if (cnt <= maxcnt) {
{
errno = EIO; errno = EIO;
ntfs_log_error("Multiple failure" ntfs_log_error("Multiple failure"
" making non resident\n"); " making non resident\n");
res = -1; res = -1;
} } else {
else
{
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
ctx = (ntfs_attr_search_ctx*)NULL; ctx = (ntfs_attr_search_ctx*)NULL;
restart = TRUE; restart = TRUE;
@ -218,8 +192,7 @@ static int fixup_loop( ntfs_inode *ni )
} }
} }
if (!restart && !res if (!restart && !res
&& ntfs_efs_fixup_attribute( ctx, na ) ) && ntfs_efs_fixup_attribute(ctx, na)) {
{
ntfs_log_error("Error in efs fixup of AT_DATA Attribute\n"); ntfs_log_error("Error in efs fixup of AT_DATA Attribute\n");
res = -1; res = -1;
} }
@ -228,8 +201,7 @@ static int fixup_loop( ntfs_inode *ni )
ntfs_attr_close(na); ntfs_attr_close(na);
} }
first = FALSE; first = FALSE;
} } while (restart && !res);
while ( restart && !res );
if (ctx) if (ctx)
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
return (res); return (res);
@ -251,18 +223,13 @@ int ntfs_set_efs_info( ntfs_inode *ni, const char *value, size_t size,
const EFS_ATTR_HEADER *info_header; const EFS_ATTR_HEADER *info_header;
res = 0; res = 0;
if ( ni && value && size ) if (ni && value && size) {
{ if (ni->flags & (FILE_ATTR_ENCRYPTED | FILE_ATTR_COMPRESSED)) {
if ( ni->flags & ( FILE_ATTR_ENCRYPTED | FILE_ATTR_COMPRESSED ) ) if (ni->flags & FILE_ATTR_ENCRYPTED) {
{
if ( ni->flags & FILE_ATTR_ENCRYPTED )
{
ntfs_log_trace("Inode %lld already encrypted\n", ntfs_log_trace("Inode %lld already encrypted\n",
(long long)ni->mft_no); (long long)ni->mft_no);
errno = EEXIST; errno = EEXIST;
} } else {
else
{
/* /*
* Possible problem : if encrypted file was * Possible problem : if encrypted file was
* restored in a compressed directory, it was * restored in a compressed directory, it was
@ -277,16 +244,13 @@ int ntfs_set_efs_info( ntfs_inode *ni, const char *value, size_t size,
} }
info_header = (const EFS_ATTR_HEADER*)value; info_header = (const EFS_ATTR_HEADER*)value;
/* make sure we get a likely efsinfo */ /* make sure we get a likely efsinfo */
if ( le32_to_cpu( info_header->length ) != size ) if (le32_to_cpu(info_header->length) != size) {
{
errno = EINVAL; errno = EINVAL;
return (-1); return (-1);
} }
if (!ntfs_attr_exist(ni,AT_LOGGED_UTILITY_STREAM, if (!ntfs_attr_exist(ni,AT_LOGGED_UTILITY_STREAM,
( ntfschar* )NULL, 0 ) ) (ntfschar*)NULL,0)) {
{ if (!(flags & XATTR_REPLACE)) {
if ( !( flags & XATTR_REPLACE ) )
{
/* /*
* no logged_utility_stream attribute : add one, * no logged_utility_stream attribute : add one,
* apparently, this does not feed the new value in * apparently, this does not feed the new value in
@ -294,36 +258,28 @@ int ntfs_set_efs_info( ntfs_inode *ni, const char *value, size_t size,
res = ntfs_attr_add(ni,AT_LOGGED_UTILITY_STREAM, res = ntfs_attr_add(ni,AT_LOGGED_UTILITY_STREAM,
logged_utility_stream_name,4, logged_utility_stream_name,4,
(u8*)NULL,(s64)size); (u8*)NULL,(s64)size);
} } else {
else
{
errno = ENODATA; errno = ENODATA;
res = -1; res = -1;
} }
} } else {
else
{
errno = EEXIST; errno = EEXIST;
res = -1; res = -1;
} }
if ( !res ) if (!res) {
{
/* /*
* open and update the existing efs data * open and update the existing efs data
*/ */
na = ntfs_attr_open(ni, AT_LOGGED_UTILITY_STREAM, na = ntfs_attr_open(ni, AT_LOGGED_UTILITY_STREAM,
logged_utility_stream_name, 4); logged_utility_stream_name, 4);
if ( na ) if (na) {
{
/* resize attribute */ /* resize attribute */
res = ntfs_attr_truncate(na, (s64)size); res = ntfs_attr_truncate(na, (s64)size);
/* overwrite value if any */ /* overwrite value if any */
if ( !res && value ) if (!res && value) {
{
written = (int)ntfs_attr_pwrite(na, written = (int)ntfs_attr_pwrite(na,
(s64)0, (s64)size, value); (s64)0, (s64)size, value);
if ( written != ( s64 )size ) if (written != (s64)size) {
{
ntfs_log_error("Failed to " ntfs_log_error("Failed to "
"update efs data\n"); "update efs data\n");
errno = EIO; errno = EIO;
@ -331,15 +287,12 @@ int ntfs_set_efs_info( ntfs_inode *ni, const char *value, size_t size,
} }
} }
ntfs_attr_close(na); ntfs_attr_close(na);
} } else
else
res = -1; res = -1;
} }
if ( !res ) if (!res) {
{
/* Don't handle AT_DATA Attribute(s) if inode is a directory */ /* Don't handle AT_DATA Attribute(s) if inode is a directory */
if ( !( ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ) ) if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
{
/* iterate over AT_DATA attributes */ /* iterate over AT_DATA attributes */
/* set encrypted flag, truncate attribute to match padding bytes */ /* set encrypted flag, truncate attribute to match padding bytes */
@ -350,9 +303,7 @@ int ntfs_set_efs_info( ntfs_inode *ni, const char *value, size_t size,
NInoSetDirty(ni); NInoSetDirty(ni);
NInoFileNameSetDirty(ni); NInoFileNameSetDirty(ni);
} }
} } else {
else
{
errno = EINVAL; errno = EINVAL;
res = -1; res = -1;
} }
@ -379,31 +330,24 @@ int ntfs_efs_fixup_attribute( ntfs_attr_search_ctx *ctx, ntfs_attr *na )
ntfs_inode *ni; ntfs_inode *ni;
BOOL close_ctx = FALSE; BOOL close_ctx = FALSE;
if ( !na ) if (!na) {
{
ntfs_log_error("no na specified for efs_fixup_attribute\n"); ntfs_log_error("no na specified for efs_fixup_attribute\n");
goto err_out; goto err_out;
} }
if ( !ctx ) if (!ctx) {
{
ctx = ntfs_attr_get_search_ctx(na->ni, NULL); ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
if ( !ctx ) if (!ctx) {
{
ntfs_log_error("Failed to get ctx for efs\n"); ntfs_log_error("Failed to get ctx for efs\n");
goto err_out; goto err_out;
} }
close_ctx = TRUE; close_ctx = TRUE;
if (ntfs_attr_lookup(AT_DATA, na->name, na->name_len, if (ntfs_attr_lookup(AT_DATA, na->name, na->name_len,
CASE_SENSITIVE, 0, NULL, 0, ctx ) ) CASE_SENSITIVE, 0, NULL, 0, ctx)) {
{
ntfs_log_error("attr lookup for AT_DATA attribute failed in efs fixup\n"); ntfs_log_error("attr lookup for AT_DATA attribute failed in efs fixup\n");
goto err_out; goto err_out;
} }
} } else {
else if (!NAttrNonResident(na)) {
{
if ( !NAttrNonResident( na ) )
{
ntfs_log_error("Cannot make non resident" ntfs_log_error("Cannot make non resident"
" when a context has been allocated\n"); " when a context has been allocated\n");
goto err_out; goto err_out;
@ -412,23 +356,19 @@ int ntfs_efs_fixup_attribute( ntfs_attr_search_ctx *ctx, ntfs_attr *na )
/* no extra bytes are added to void attributes */ /* no extra bytes are added to void attributes */
oldsize = na->data_size; oldsize = na->data_size;
if ( oldsize ) if (oldsize) {
{
/* make sure size is valid for a raw encrypted stream */ /* make sure size is valid for a raw encrypted stream */
if ( ( oldsize & 511 ) != 2 ) if ((oldsize & 511) != 2) {
{
ntfs_log_error("Bad raw encrypted stream\n"); ntfs_log_error("Bad raw encrypted stream\n");
goto err_out; goto err_out;
} }
/* read padding length from last two bytes of attribute */ /* read padding length from last two bytes of attribute */
if ( ntfs_attr_pread( na, oldsize - 2, 2, &appended_bytes ) != 2 ) if (ntfs_attr_pread(na, oldsize - 2, 2, &appended_bytes) != 2) {
{
ntfs_log_error("Error reading padding length\n"); ntfs_log_error("Error reading padding length\n");
goto err_out; goto err_out;
} }
padding_length = le16_to_cpu(appended_bytes); padding_length = le16_to_cpu(appended_bytes);
if ( padding_length > 511 || padding_length > na->data_size - 2 ) if (padding_length > 511 || padding_length > na->data_size-2) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_error("invalid padding length %d for data_size %lld\n", ntfs_log_error("invalid padding length %d for data_size %lld\n",
padding_length, (long long)oldsize); padding_length, (long long)oldsize);
@ -440,13 +380,11 @@ int ntfs_efs_fixup_attribute( ntfs_attr_search_ctx *ctx, ntfs_attr *na )
* for the last two bytes, but do not truncate to new size * for the last two bytes, but do not truncate to new size
* to avoid losing useful data * to avoid losing useful data
*/ */
if ( ntfs_attr_truncate( na, oldsize - 2 ) ) if (ntfs_attr_truncate(na, oldsize - 2)) {
{
ntfs_log_error("Error truncating attribute\n"); ntfs_log_error("Error truncating attribute\n");
goto err_out; goto err_out;
} }
} } else
else
newsize = 0; newsize = 0;
/* /*
@ -456,16 +394,12 @@ int ntfs_efs_fixup_attribute( ntfs_attr_search_ctx *ctx, ntfs_attr *na )
* resident. * resident.
*/ */
if (!NAttrNonResident(na) if (!NAttrNonResident(na)
&& ntfs_attr_make_non_resident( na, ctx ) ) && ntfs_attr_make_non_resident(na, ctx)) {
{
if (!close_ctx if (!close_ctx
|| ntfs_attr_force_non_resident( na ) ) || ntfs_attr_force_non_resident(na)) {
{
ntfs_log_error("Error making DATA attribute non-resident\n"); ntfs_log_error("Error making DATA attribute non-resident\n");
goto err_out; goto err_out;
} } else {
else
{
/* /*
* must reinitialize context after forcing * must reinitialize context after forcing
* non-resident. We need a context for updating * non-resident. We need a context for updating
@ -474,16 +408,14 @@ int ntfs_efs_fixup_attribute( ntfs_attr_search_ctx *ctx, ntfs_attr *na )
*/ */
ntfs_attr_reinit_search_ctx(ctx); ntfs_attr_reinit_search_ctx(ctx);
if (ntfs_attr_lookup(AT_DATA, na->name, na->name_len, if (ntfs_attr_lookup(AT_DATA, na->name, na->name_len,
CASE_SENSITIVE, 0, NULL, 0, ctx ) ) CASE_SENSITIVE, 0, NULL, 0, ctx)) {
{
ntfs_log_error("attr lookup for AT_DATA attribute failed in efs fixup\n"); ntfs_log_error("attr lookup for AT_DATA attribute failed in efs fixup\n");
goto err_out; goto err_out;
} }
} }
} }
ni = na->ni; ni = na->ni;
if ( !na->name_len ) if (!na->name_len) {
{
ni->data_size = newsize; ni->data_size = newsize;
ni->allocated_size = na->allocated_size; ni->allocated_size = na->allocated_size;
} }

View File

@ -80,37 +80,32 @@ static int ntfs_device_gekko_io_open( struct ntfs_device *dev, int flags )
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD(dev);
if ( !fd ) if (!fd) {
{
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
// Get the device interface // Get the device interface
const DISC_INTERFACE* interface = fd->interface; const DISC_INTERFACE* interface = fd->interface;
if ( !interface ) if (!interface) {
{
errno = ENODEV; errno = ENODEV;
return -1; return -1;
} }
// Start the device interface and ensure that it is inserted // Start the device interface and ensure that it is inserted
if ( !interface->startup() ) if (!interface->startup()) {
{
ntfs_log_perror("device failed to start\n"); ntfs_log_perror("device failed to start\n");
errno = EIO; errno = EIO;
return -1; return -1;
} }
if ( !interface->isInserted() ) if (!interface->isInserted()) {
{
ntfs_log_perror("device media is not inserted\n"); ntfs_log_perror("device media is not inserted\n");
errno = EIO; errno = EIO;
return -1; return -1;
} }
// Check that the device isn't already open (used by another volume?) // Check that the device isn't already open (used by another volume?)
if ( NDevOpen( dev ) ) if (NDevOpen(dev)) {
{
ntfs_log_perror("device is busy (already open)\n"); ntfs_log_perror("device is busy (already open)\n");
errno = EBUSY; errno = EBUSY;
return -1; return -1;
@ -118,16 +113,12 @@ static int ntfs_device_gekko_io_open( struct ntfs_device *dev, int flags )
// Check that there is a valid NTFS boot sector at the start of the device // Check that there is a valid NTFS boot sector at the start of the device
NTFS_BOOT_SECTOR boot; NTFS_BOOT_SECTOR boot;
if ( interface->readSectors( fd->startSector, 1, &boot ) ) if (interface->readSectors(fd->startSector, 1, &boot)) {
{ if (!ntfs_boot_sector_is_ntfs(&boot)) {
if ( !ntfs_boot_sector_is_ntfs( &boot ) )
{
errno = EINVALPART; errno = EINVALPART;
return -1; return -1;
} }
} } else {
else
{
ntfs_log_perror("read failure @ sector %d\n", fd->startSector); ntfs_log_perror("read failure @ sector %d\n", fd->startSector);
errno = EIO; errno = EIO;
return -1; return -1;
@ -142,8 +133,7 @@ static int ntfs_device_gekko_io_open( struct ntfs_device *dev, int flags )
fd->ino = le64_to_cpu(boot.volume_serial_number); fd->ino = le64_to_cpu(boot.volume_serial_number);
// Mark the device as read-only (if required) // Mark the device as read-only (if required)
if ( flags & O_RDONLY ) if (flags & O_RDONLY) {
{
NDevSetReadOnly(dev); NDevSetReadOnly(dev);
} }
@ -166,15 +156,13 @@ static int ntfs_device_gekko_io_close( struct ntfs_device *dev )
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD(dev);
if ( !fd ) if (!fd) {
{
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
// Check that the device is actually open // Check that the device is actually open
if ( !NDevOpen( dev ) ) if (!NDevOpen(dev)) {
{
ntfs_log_perror("device is not open\n"); ntfs_log_perror("device is not open\n");
errno = EIO; errno = EIO;
return -1; return -1;
@ -185,8 +173,7 @@ static int ntfs_device_gekko_io_close( struct ntfs_device *dev )
NDevClearBlock(dev); NDevClearBlock(dev);
// Flush the device (if dirty and not read-only) // Flush the device (if dirty and not read-only)
if ( NDevDirty( dev ) && !NDevReadOnly( dev ) ) if (NDevDirty(dev) && !NDevReadOnly(dev)) {
{
ntfs_log_debug("device is dirty, will now sync\n"); ntfs_log_debug("device is dirty, will now sync\n");
// ...? // ...?
@ -197,8 +184,7 @@ static int ntfs_device_gekko_io_close( struct ntfs_device *dev )
} }
// Flush and destroy the cache (if required) // Flush and destroy the cache (if required)
if ( fd->cache ) if (fd->cache) {
{
_NTFS_cache_flush(fd->cache); _NTFS_cache_flush(fd->cache);
_NTFS_cache_destructor(fd->cache); _NTFS_cache_destructor(fd->cache);
} }
@ -225,15 +211,13 @@ static s64 ntfs_device_gekko_io_seek( struct ntfs_device *dev, s64 offset, int w
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD(dev);
if ( !fd ) if (!fd) {
{
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
// Set the current position on the device (in bytes) // Set the current position on the device (in bytes)
switch ( whence ) switch(whence) {
{
case SEEK_SET: fd->pos = MIN(MAX(offset, 0), fd->len); break; case SEEK_SET: fd->pos = MIN(MAX(offset, 0), fd->len); break;
case SEEK_CUR: fd->pos = MIN(MAX(fd->pos + offset, 0), fd->len); break; case SEEK_CUR: fd->pos = MIN(MAX(fd->pos + offset, 0), fd->len); break;
case SEEK_END: fd->pos = MIN(MAX(fd->len + offset, 0), fd->len); break; case SEEK_END: fd->pos = MIN(MAX(fd->len + offset, 0), fd->len); break;
@ -283,16 +267,14 @@ static s64 ntfs_device_gekko_io_readbytes( struct ntfs_device *dev, s64 offset,
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD(dev);
if ( !fd ) if (!fd) {
{
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
// Get the device interface // Get the device interface
const DISC_INTERFACE* interface = fd->interface; const DISC_INTERFACE* interface = fd->interface;
if ( !interface ) if (!interface) {
{
errno = ENODEV; errno = ENODEV;
return -1; return -1;
} }
@ -312,24 +294,20 @@ static s64 ntfs_device_gekko_io_readbytes( struct ntfs_device *dev, s64 offset,
u8 *buffer = NULL; u8 *buffer = NULL;
// Determine the range of sectors required for this read // Determine the range of sectors required for this read
if ( offset > 0 ) if (offset > 0) {
{
sec_start += (sec_t) floor((f64) offset / (f64) fd->sectorSize); sec_start += (sec_t) floor((f64) offset / (f64) fd->sectorSize);
} }
if ( buffer_offset + count > fd->sectorSize ) if (buffer_offset+count > fd->sectorSize) {
{
sec_count = (sec_t) ceil((f64) (buffer_offset+count) / (f64) fd->sectorSize); sec_count = (sec_t) ceil((f64) (buffer_offset+count) / (f64) fd->sectorSize);
} }
// If this read happens to be on the sector boundaries then do the read straight into the destination buffer // If this read happens to be on the sector boundaries then do the read straight into the destination buffer
if ( ( buffer_offset == 0 ) && ( count % fd->sectorSize == 0 ) ) if((buffer_offset == 0) && (count % fd->sectorSize == 0)) {
{
// Read from the device // Read from the device
ntfs_log_trace("direct read from sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_trace("direct read from sector %d (%d sector(s) long)\n", sec_start, sec_count);
if ( !ntfs_device_gekko_io_readsectors( dev, sec_start, sec_count, buf ) ) if (!ntfs_device_gekko_io_readsectors(dev, sec_start, sec_count, buf)) {
{
ntfs_log_perror("direct read failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_perror("direct read failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count);
errno = EIO; errno = EIO;
return -1; return -1;
@ -342,8 +320,7 @@ static s64 ntfs_device_gekko_io_readbytes( struct ntfs_device *dev, s64 offset,
// Allocate a buffer to hold the read data // Allocate a buffer to hold the read data
buffer = (u8*)ntfs_alloc(sec_count * fd->sectorSize); buffer = (u8*)ntfs_alloc(sec_count * fd->sectorSize);
if ( !buffer ) if (!buffer) {
{
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
} }
@ -351,8 +328,7 @@ static s64 ntfs_device_gekko_io_readbytes( struct ntfs_device *dev, s64 offset,
// Read from the device // Read from the device
ntfs_log_trace("buffered read from sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_trace("buffered read from sector %d (%d sector(s) long)\n", sec_start, sec_count);
ntfs_log_trace("count: %d sec_count:%d fd->sectorSize: %d )\n", (u32)count, (u32)sec_count,(u32)fd->sectorSize); ntfs_log_trace("count: %d sec_count:%d fd->sectorSize: %d )\n", (u32)count, (u32)sec_count,(u32)fd->sectorSize);
if ( !ntfs_device_gekko_io_readsectors( dev, sec_start, sec_count, buffer ) ) if (!ntfs_device_gekko_io_readsectors(dev, sec_start, sec_count, buffer)) {
{
ntfs_log_perror("buffered read failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_perror("buffered read failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count);
ntfs_free(buffer); ntfs_free(buffer);
errno = EIO; errno = EIO;
@ -377,29 +353,25 @@ static s64 ntfs_device_gekko_io_writebytes( struct ntfs_device *dev, s64 offset,
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD(dev);
if ( !fd ) if (!fd) {
{
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
// Get the device interface // Get the device interface
const DISC_INTERFACE* interface = fd->interface; const DISC_INTERFACE* interface = fd->interface;
if ( !interface ) if (!interface) {
{
errno = ENODEV; errno = ENODEV;
return -1; return -1;
} }
// Check that the device can be written to // Check that the device can be written to
if ( NDevReadOnly( dev ) ) if (NDevReadOnly(dev)) {
{
errno = EROFS; errno = EROFS;
return -1; return -1;
} }
if ( count < 0 || offset < 0 ) if(count < 0 || offset < 0) {
{
errno = EROFS; errno = EROFS;
return -1; return -1;
} }
@ -413,12 +385,10 @@ static s64 ntfs_device_gekko_io_writebytes( struct ntfs_device *dev, s64 offset,
u8 *buffer = NULL; u8 *buffer = NULL;
// Determine the range of sectors required for this write // Determine the range of sectors required for this write
if ( offset > 0 ) if (offset > 0) {
{
sec_start += (sec_t) floor((f64) offset / (f64) fd->sectorSize); sec_start += (sec_t) floor((f64) offset / (f64) fd->sectorSize);
} }
if ( ( buffer_offset + count ) > fd->sectorSize ) if ((buffer_offset+count) > fd->sectorSize) {
{
sec_count = (sec_t) ceil((f64) (buffer_offset+count) / (f64) fd->sectorSize); sec_count = (sec_t) ceil((f64) (buffer_offset+count) / (f64) fd->sectorSize);
} }
@ -427,8 +397,7 @@ static s64 ntfs_device_gekko_io_writebytes( struct ntfs_device *dev, s64 offset,
{ {
// Write to the device // Write to the device
ntfs_log_trace("direct write to sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_trace("direct write to sector %d (%d sector(s) long)\n", sec_start, sec_count);
if ( !ntfs_device_gekko_io_writesectors( dev, sec_start, sec_count, buf ) ) if (!ntfs_device_gekko_io_writesectors(dev, sec_start, sec_count, buf)) {
{
ntfs_log_perror("direct write failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_perror("direct write failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count);
errno = EIO; errno = EIO;
return -1; return -1;
@ -439,8 +408,7 @@ static s64 ntfs_device_gekko_io_writebytes( struct ntfs_device *dev, s64 offset,
{ {
// Allocate a buffer to hold the write data // Allocate a buffer to hold the write data
buffer = (u8 *) ntfs_alloc(sec_count * fd->sectorSize); buffer = (u8 *) ntfs_alloc(sec_count * fd->sectorSize);
if ( !buffer ) if (!buffer) {
{
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
} }
@ -449,8 +417,7 @@ static s64 ntfs_device_gekko_io_writebytes( struct ntfs_device *dev, s64 offset,
// we just read in the buffer edges where the data overlaps with the rest of the disc // we just read in the buffer edges where the data overlaps with the rest of the disc
if(buffer_offset != 0) if(buffer_offset != 0)
{ {
if ( !ntfs_device_gekko_io_readsectors( dev, sec_start, 1, buffer ) ) if (!ntfs_device_gekko_io_readsectors(dev, sec_start, 1, buffer)) {
{
ntfs_log_perror("read failure @ sector %d\n", sec_start); ntfs_log_perror("read failure @ sector %d\n", sec_start);
ntfs_free(buffer); ntfs_free(buffer);
errno = EIO; errno = EIO;
@ -459,8 +426,7 @@ static s64 ntfs_device_gekko_io_writebytes( struct ntfs_device *dev, s64 offset,
} }
if((buffer_offset+count) % fd->sectorSize != 0) if((buffer_offset+count) % fd->sectorSize != 0)
{ {
if ( !ntfs_device_gekko_io_readsectors( dev, sec_start + sec_count - 1, 1, buffer + ( ( sec_count - 1 ) * fd->sectorSize ) ) ) if (!ntfs_device_gekko_io_readsectors(dev, sec_start + sec_count - 1, 1, buffer + ((sec_count-1) * fd->sectorSize))) {
{
ntfs_log_perror("read failure @ sector %d\n", sec_start + sec_count - 1); ntfs_log_perror("read failure @ sector %d\n", sec_start + sec_count - 1);
ntfs_free(buffer); ntfs_free(buffer);
errno = EIO; errno = EIO;
@ -473,8 +439,7 @@ static s64 ntfs_device_gekko_io_writebytes( struct ntfs_device *dev, s64 offset,
// Write to the device // Write to the device
ntfs_log_trace("buffered write to sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_trace("buffered write to sector %d (%d sector(s) long)\n", sec_start, sec_count);
if ( !ntfs_device_gekko_io_writesectors( dev, sec_start, sec_count, buffer ) ) if (!ntfs_device_gekko_io_writesectors(dev, sec_start, sec_count, buffer)) {
{
ntfs_log_perror("buffered write failure @ sector %d\n", sec_start); ntfs_log_perror("buffered write failure @ sector %d\n", sec_start);
ntfs_free(buffer); ntfs_free(buffer);
errno = EIO; errno = EIO;
@ -495,8 +460,7 @@ static bool ntfs_device_gekko_io_readsectors( struct ntfs_device *dev, sec_t sec
{ {
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD(dev);
if ( !fd ) if (!fd) {
{
errno = EBADF; errno = EBADF;
return false; return false;
} }
@ -513,8 +477,7 @@ static bool ntfs_device_gekko_io_writesectors( struct ntfs_device *dev, sec_t se
{ {
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD(dev);
if ( !fd ) if (!fd) {
{
errno = EBADF; errno = EBADF;
return false; return false;
} }
@ -537,8 +500,7 @@ static int ntfs_device_gekko_io_sync( struct ntfs_device *dev )
ntfs_log_trace("dev %p\n", dev); ntfs_log_trace("dev %p\n", dev);
// Check that the device can be written to // Check that the device can be written to
if ( NDevReadOnly( dev ) ) if (NDevReadOnly(dev)) {
{
errno = EROFS; errno = EROFS;
return -1; return -1;
} }
@ -547,10 +509,8 @@ static int ntfs_device_gekko_io_sync( struct ntfs_device *dev )
NDevClearDirty(dev); NDevClearDirty(dev);
// Flush any sectors in the disc cache (if required) // Flush any sectors in the disc cache (if required)
if ( fd->cache ) if (fd->cache) {
{ if (!_NTFS_cache_flush(fd->cache)) {
if ( !_NTFS_cache_flush( fd->cache ) )
{
errno = EIO; errno = EIO;
return -1; return -1;
} }
@ -568,8 +528,7 @@ static int ntfs_device_gekko_io_stat( struct ntfs_device *dev, struct stat *buf
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD(dev);
if ( !fd ) if (!fd) {
{
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
@ -606,20 +565,17 @@ static int ntfs_device_gekko_io_ioctl( struct ntfs_device *dev, int request, voi
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD(dev);
if ( !fd ) if (!fd) {
{
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
// Figure out which i/o control was requested // Figure out which i/o control was requested
switch ( request ) switch (request) {
{
// Get block device size (sectors) // Get block device size (sectors)
#if defined(BLKGETSIZE) #if defined(BLKGETSIZE)
case BLKGETSIZE: case BLKGETSIZE: {
{
*(u32*)argp = fd->sectorCount; *(u32*)argp = fd->sectorCount;
return 0; return 0;
} }
@ -627,8 +583,7 @@ static int ntfs_device_gekko_io_ioctl( struct ntfs_device *dev, int request, voi
// Get block device size (bytes) // Get block device size (bytes)
#if defined(BLKGETSIZE64) #if defined(BLKGETSIZE64)
case BLKGETSIZE64: case BLKGETSIZE64: {
{
*(u64*)argp = (fd->sectorCount * fd->sectorSize); *(u64*)argp = (fd->sectorCount * fd->sectorSize);
return 0; return 0;
} }
@ -636,8 +591,7 @@ static int ntfs_device_gekko_io_ioctl( struct ntfs_device *dev, int request, voi
// Get hard drive geometry // Get hard drive geometry
#if defined(HDIO_GETGEO) #if defined(HDIO_GETGEO)
case HDIO_GETGEO: case HDIO_GETGEO: {
{
struct hd_geometry *geo = (struct hd_geometry*)argp; struct hd_geometry *geo = (struct hd_geometry*)argp;
geo->sectors = 0; geo->sectors = 0;
geo->heads = 0; geo->heads = 0;
@ -649,8 +603,7 @@ static int ntfs_device_gekko_io_ioctl( struct ntfs_device *dev, int request, voi
// Get block device sector size (bytes) // Get block device sector size (bytes)
#if defined(BLKSSZGET) #if defined(BLKSSZGET)
case BLKSSZGET: case BLKSSZGET: {
{
*(int*)argp = fd->sectorSize; *(int*)argp = fd->sectorSize;
return 0; return 0;
} }
@ -658,8 +611,7 @@ static int ntfs_device_gekko_io_ioctl( struct ntfs_device *dev, int request, voi
// Set block device block size (bytes) // Set block device block size (bytes)
#if defined(BLKBSZSET) #if defined(BLKBSZSET)
case BLKBSZSET: case BLKBSZSET: {
{
int sectorSize = *(int*)argp; int sectorSize = *(int*)argp;
fd->sectorSize = sectorSize; fd->sectorSize = sectorSize;
return 0; return 0;
@ -667,8 +619,7 @@ static int ntfs_device_gekko_io_ioctl( struct ntfs_device *dev, int request, voi
#endif #endif
// Unimplemented ioctrl // Unimplemented ioctrl
default: default: {
{
ntfs_log_perror("Unimplemented ioctrl %i\n", request); ntfs_log_perror("Unimplemented ioctrl %i\n", request);
errno = EOPNOTSUPP; errno = EOPNOTSUPP;
return -1; return -1;
@ -682,8 +633,7 @@ static int ntfs_device_gekko_io_ioctl( struct ntfs_device *dev, int request, voi
/** /**
* Device operations for working with gekko style devices and files. * Device operations for working with gekko style devices and files.
*/ */
struct ntfs_device_operations ntfs_device_gekko_io_ops = struct ntfs_device_operations ntfs_device_gekko_io_ops = {
{
.open = ntfs_device_gekko_io_open, .open = ntfs_device_gekko_io_open,
.close = ntfs_device_gekko_io_close, .close = ntfs_device_gekko_io_close,
.seek = ntfs_device_gekko_io_seek, .seek = ntfs_device_gekko_io_seek,

View File

@ -33,8 +33,7 @@
/** /**
* gekko_fd - Gekko device driver descriptor * gekko_fd - Gekko device driver descriptor
*/ */
typedef struct _gekko_fd typedef struct _gekko_fd {
{
const DISC_INTERFACE* interface; /* Device disc interface */ const DISC_INTERFACE* interface; /* Device disc interface */
sec_t startSector; /* LBA of partition start */ sec_t startSector; /* LBA of partition start */
sec_t hiddenSectors; /* LBA offset to true partition start (as described by boot sector) */ sec_t hiddenSectors; /* LBA offset to true partition start (as described by boot sector) */

View File

@ -88,8 +88,7 @@ static int ntfs_ib_write( ntfs_index_context *icx, INDEX_BLOCK *ib )
ret = ntfs_attr_mst_pwrite(icx->ia_na, ntfs_ib_vcn_to_pos(icx, vcn), ret = ntfs_attr_mst_pwrite(icx->ia_na, ntfs_ib_vcn_to_pos(icx, vcn),
1, icx->block_size, ib); 1, icx->block_size, ib);
if ( ret != 1 ) if (ret != 1) {
{
ntfs_log_perror("Failed to write index block %lld, inode %llu", ntfs_log_perror("Failed to write index block %lld, inode %llu",
(long long)vcn, (unsigned long long)icx->ni->mft_no); (long long)vcn, (unsigned long long)icx->ni->mft_no);
return STATUS_ERROR; return STATUS_ERROR;
@ -124,8 +123,7 @@ ntfs_index_context *ntfs_index_ctx_get( ntfs_inode *ni,
ntfs_log_trace("Entering\n"); ntfs_log_trace("Entering\n");
if ( !ni ) if (!ni) {
{
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} }
@ -133,8 +131,7 @@ ntfs_index_context *ntfs_index_ctx_get( ntfs_inode *ni,
ni = ni->base_ni; ni = ni->base_ni;
icx = ntfs_calloc(sizeof(ntfs_index_context)); icx = ntfs_calloc(sizeof(ntfs_index_context));
if (icx) if (icx)
*icx = ( ntfs_index_context ) *icx = (ntfs_index_context) {
{
.ni = ni, .ni = ni,
.name = name, .name = name,
.name_len = name_len, .name_len = name_len,
@ -152,10 +149,8 @@ static void ntfs_index_ctx_free( ntfs_index_context *icx )
if (icx->actx) if (icx->actx)
ntfs_attr_put_search_ctx(icx->actx); ntfs_attr_put_search_ctx(icx->actx);
if ( !icx->is_in_root ) if (!icx->is_in_root) {
{ if (icx->ib_dirty) {
if ( icx->ib_dirty )
{
/* FIXME: Error handling!!! */ /* FIXME: Error handling!!! */
ntfs_ib_write(icx, icx->ib); ntfs_ib_write(icx, icx->ib);
} }
@ -189,8 +184,7 @@ void ntfs_index_ctx_reinit( ntfs_index_context *icx )
ntfs_index_ctx_free(icx); ntfs_index_ctx_free(icx);
*icx = ( ntfs_index_context ) *icx = (ntfs_index_context) {
{
.ni = icx->ni, .ni = icx->ni,
.name = icx->name, .name = icx->name,
.name_len = icx->name_len, .name_len = icx->name_len,
@ -267,8 +261,7 @@ static INDEX_ENTRY *ntfs_ie_prev( INDEX_HEADER *ih, INDEX_ENTRY *ie )
tmp = ntfs_ie_get_first(ih); tmp = ntfs_ie_get_first(ih);
while ( tmp != ie ) while (tmp != ie) {
{
ie_prev = tmp; ie_prev = tmp;
tmp = ntfs_ie_get_next(tmp); tmp = ntfs_ie_get_next(tmp);
} }
@ -300,8 +293,7 @@ void ntfs_ih_filename_dump( INDEX_HEADER *ih )
ntfs_log_trace("Entering\n"); ntfs_log_trace("Entering\n");
ie = ntfs_ie_get_first(ih); ie = ntfs_ie_get_first(ih);
while ( !ntfs_ie_end( ie ) ) while (!ntfs_ie_end(ie)) {
{
ntfs_ie_filename_dump(ie); ntfs_ie_filename_dump(ie);
ie = ntfs_ie_get_next(ie); ie = ntfs_ie_get_next(ie);
} }
@ -388,8 +380,7 @@ static INDEX_ENTRY *ntfs_ie_dup_novcn( INDEX_ENTRY *ie )
size -= sizeof(VCN); size -= sizeof(VCN);
dup = ntfs_malloc(size); dup = ntfs_malloc(size);
if ( dup ) if (dup) {
{
memcpy(dup, ie, size); memcpy(dup, ie, size);
dup->ie_flags &= ~INDEX_ENTRY_NODE; dup->ie_flags &= ~INDEX_ENTRY_NODE;
dup->length = cpu_to_le16(size); dup->length = cpu_to_le16(size);
@ -403,8 +394,7 @@ static int ntfs_ia_check( ntfs_index_context *icx, INDEX_BLOCK *ib, VCN vcn )
ntfs_log_trace("Entering\n"); ntfs_log_trace("Entering\n");
if ( !ntfs_is_indx_record( ib->magic ) ) if (!ntfs_is_indx_record(ib->magic)) {
{
ntfs_log_error("Corrupt index block signature: vcn %lld inode " ntfs_log_error("Corrupt index block signature: vcn %lld inode "
"%llu\n", (long long)vcn, "%llu\n", (long long)vcn,
@ -412,8 +402,7 @@ static int ntfs_ia_check( ntfs_index_context *icx, INDEX_BLOCK *ib, VCN vcn )
return -1; return -1;
} }
if ( sle64_to_cpu( ib->index_block_vcn ) != vcn ) if (sle64_to_cpu(ib->index_block_vcn) != vcn) {
{
ntfs_log_error("Corrupt index block: VCN (%lld) is different " ntfs_log_error("Corrupt index block: VCN (%lld) is different "
"from expected VCN (%lld) in inode %llu\n", "from expected VCN (%lld) in inode %llu\n",
@ -423,8 +412,7 @@ static int ntfs_ia_check( ntfs_index_context *icx, INDEX_BLOCK *ib, VCN vcn )
return -1; return -1;
} }
if ( ib_size != icx->block_size ) if (ib_size != icx->block_size) {
{
ntfs_log_error("Corrupt index block : VCN (%lld) of inode %llu " ntfs_log_error("Corrupt index block : VCN (%lld) of inode %llu "
"has a size (%u) differing from the index " "has a size (%u) differing from the index "
@ -449,15 +437,13 @@ static INDEX_ROOT *ntfs_ir_lookup( ntfs_inode *ni, ntfschar *name,
return NULL; return NULL;
if (ntfs_attr_lookup(AT_INDEX_ROOT, name, name_len, CASE_SENSITIVE, if (ntfs_attr_lookup(AT_INDEX_ROOT, name, name_len, CASE_SENSITIVE,
0, NULL, 0, *ctx ) ) 0, NULL, 0, *ctx)) {
{
ntfs_log_perror("Failed to lookup $INDEX_ROOT"); ntfs_log_perror("Failed to lookup $INDEX_ROOT");
goto err_out; goto err_out;
} }
a = (*ctx)->attr; a = (*ctx)->attr;
if ( a->non_resident ) if (a->non_resident) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("Non-resident $INDEX_ROOT detected"); ntfs_log_perror("Non-resident $INDEX_ROOT detected");
goto err_out; goto err_out;
@ -465,8 +451,7 @@ static INDEX_ROOT *ntfs_ir_lookup( ntfs_inode *ni, ntfschar *name,
ir = (INDEX_ROOT *)((char *)a + le16_to_cpu(a->value_offset)); ir = (INDEX_ROOT *)((char *)a + le16_to_cpu(a->value_offset));
err_out: err_out:
if ( !ir ) if (!ir) {
{
ntfs_attr_put_search_ctx(*ctx); ntfs_attr_put_search_ctx(*ctx);
*ctx = NULL; *ctx = NULL;
} }
@ -512,12 +497,10 @@ static int ntfs_ie_lookup( const void *key, const int key_len,
* Loop until we exceed valid memory (corruption case) or until we * Loop until we exceed valid memory (corruption case) or until we
* reach the last entry. * reach the last entry.
*/ */
for ( ie = ntfs_ie_get_first( ih ); ; ie = ntfs_ie_get_next( ie ) ) for (ie = ntfs_ie_get_first(ih); ; ie = ntfs_ie_get_next(ie)) {
{
/* Bounds checks. */ /* Bounds checks. */
if ((u8 *)ie + sizeof(INDEX_ENTRY_HEADER) > index_end || if ((u8 *)ie + sizeof(INDEX_ENTRY_HEADER) > index_end ||
( u8 * )ie + le16_to_cpu( ie->length ) > index_end ) (u8 *)ie + le16_to_cpu(ie->length) > index_end) {
{
errno = ERANGE; errno = ERANGE;
ntfs_log_error("Index entry out of bounds in inode " ntfs_log_error("Index entry out of bounds in inode "
"%llu.\n", "%llu.\n",
@ -534,16 +517,14 @@ static int ntfs_ie_lookup( const void *key, const int key_len,
* Not a perfect match, need to do full blown collation so we * Not a perfect match, need to do full blown collation so we
* know which way in the B+tree we have to go. * know which way in the B+tree we have to go.
*/ */
if ( !icx->collate ) if (!icx->collate) {
{
ntfs_log_error("Collation function not defined\n"); ntfs_log_error("Collation function not defined\n");
errno = EOPNOTSUPP; errno = EOPNOTSUPP;
return STATUS_ERROR; return STATUS_ERROR;
} }
rc = icx->collate(icx->ni->vol, key, key_len, rc = icx->collate(icx->ni->vol, key, key_len,
&ie->key, le16_to_cpu(ie->key_length)); &ie->key, le16_to_cpu(ie->key_length));
if ( rc == NTFS_COLLATION_ERROR ) if (rc == NTFS_COLLATION_ERROR) {
{
ntfs_log_error("Collation error. Perhaps a filename " ntfs_log_error("Collation error. Perhaps a filename "
"contains invalid characters?\n"); "contains invalid characters?\n");
errno = ERANGE; errno = ERANGE;
@ -557,8 +538,7 @@ static int ntfs_ie_lookup( const void *key, const int key_len,
if (rc == -1) if (rc == -1)
break; break;
if ( !rc ) if (!rc) {
{
*ie_out = ie; *ie_out = ie;
errno = 0; errno = 0;
icx->parent_pos[icx->pindex] = item; icx->parent_pos[icx->pindex] = item;
@ -572,8 +552,7 @@ static int ntfs_ie_lookup( const void *key, const int key_len,
* presence of a child node and if not present return with errno ENOENT, * presence of a child node and if not present return with errno ENOENT,
* otherwise we will keep searching in another index block. * otherwise we will keep searching in another index block.
*/ */
if ( !( ie->ie_flags & INDEX_ENTRY_NODE ) ) if (!(ie->ie_flags & INDEX_ENTRY_NODE)) {
{
ntfs_log_debug("Index entry wasn't found.\n"); ntfs_log_debug("Index entry wasn't found.\n");
*ie_out = ie; *ie_out = ie;
errno = ENOENT; errno = ENOENT;
@ -582,8 +561,7 @@ static int ntfs_ie_lookup( const void *key, const int key_len,
/* Get the starting vcn of the index_block holding the child node. */ /* Get the starting vcn of the index_block holding the child node. */
*vcn = ntfs_ie_get_vcn(ie); *vcn = ntfs_ie_get_vcn(ie);
if ( *vcn < 0 ) if (*vcn < 0) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("Negative vcn in inode %llu", ntfs_log_perror("Negative vcn in inode %llu",
(unsigned long long)icx->ni->mft_no); (unsigned long long)icx->ni->mft_no);
@ -601,8 +579,7 @@ static ntfs_attr *ntfs_ia_open( ntfs_index_context *icx, ntfs_inode *ni )
ntfs_attr *na; ntfs_attr *na;
na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, icx->name, icx->name_len); na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, icx->name, icx->name_len);
if ( !na ) if (!na) {
{
ntfs_log_perror("Failed to open index allocation of inode " ntfs_log_perror("Failed to open index allocation of inode "
"%llu", (unsigned long long)ni->mft_no); "%llu", (unsigned long long)ni->mft_no);
return NULL; return NULL;
@ -620,8 +597,7 @@ static int ntfs_ib_read( ntfs_index_context *icx, VCN vcn, INDEX_BLOCK *dst )
pos = ntfs_ib_vcn_to_pos(icx, vcn); pos = ntfs_ib_vcn_to_pos(icx, vcn);
ret = ntfs_attr_mst_pread(icx->ia_na, pos, 1, icx->block_size, (u8 *)dst); ret = ntfs_attr_mst_pread(icx->ia_na, pos, 1, icx->block_size, (u8 *)dst);
if ( ret != 1 ) if (ret != 1) {
{
if (ret == -1) if (ret == -1)
ntfs_log_perror("Failed to read index block"); ntfs_log_perror("Failed to read index block");
else else
@ -639,8 +615,7 @@ static int ntfs_ib_read( ntfs_index_context *icx, VCN vcn, INDEX_BLOCK *dst )
static int ntfs_icx_parent_inc(ntfs_index_context *icx) static int ntfs_icx_parent_inc(ntfs_index_context *icx)
{ {
icx->pindex++; icx->pindex++;
if ( icx->pindex >= MAX_PARENT_VCN ) if (icx->pindex >= MAX_PARENT_VCN) {
{
errno = EOPNOTSUPP; errno = EOPNOTSUPP;
ntfs_log_perror("Index is over %d level deep", MAX_PARENT_VCN); ntfs_log_perror("Index is over %d level deep", MAX_PARENT_VCN);
return STATUS_ERROR; return STATUS_ERROR;
@ -651,8 +626,7 @@ static int ntfs_icx_parent_inc( ntfs_index_context *icx )
static int ntfs_icx_parent_dec(ntfs_index_context *icx) static int ntfs_icx_parent_dec(ntfs_index_context *icx)
{ {
icx->pindex--; icx->pindex--;
if ( icx->pindex < 0 ) if (icx->pindex < 0) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("Corrupt index pointer (%d)", icx->pindex); ntfs_log_perror("Corrupt index pointer (%d)", icx->pindex);
return STATUS_ERROR; return STATUS_ERROR;
@ -703,24 +677,21 @@ int ntfs_index_lookup( const void *key, const int key_len, ntfs_index_context *i
ntfs_log_trace("Entering\n"); ntfs_log_trace("Entering\n");
if ( !key || key_len <= 0 ) if (!key || key_len <= 0) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("key: %p key_len: %d", key, key_len); ntfs_log_perror("key: %p key_len: %d", key, key_len);
return -1; return -1;
} }
ir = ntfs_ir_lookup(ni, icx->name, icx->name_len, &icx->actx); ir = ntfs_ir_lookup(ni, icx->name, icx->name_len, &icx->actx);
if ( !ir ) if (!ir) {
{
if (errno == ENOENT) if (errno == ENOENT)
errno = EIO; errno = EIO;
return -1; return -1;
} }
icx->block_size = le32_to_cpu(ir->index_block_size); icx->block_size = le32_to_cpu(ir->index_block_size);
if ( icx->block_size < NTFS_BLOCK_SIZE ) if (icx->block_size < NTFS_BLOCK_SIZE) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("Index block size (%d) is smaller than the " ntfs_log_perror("Index block size (%d) is smaller than the "
"sector size (%d)", icx->block_size, NTFS_BLOCK_SIZE); "sector size (%d)", icx->block_size, NTFS_BLOCK_SIZE);
@ -733,8 +704,7 @@ int ntfs_index_lookup( const void *key, const int key_len, ntfs_index_context *i
icx->vcn_size_bits = ni->vol->sector_size_bits; icx->vcn_size_bits = ni->vol->sector_size_bits;
/* get the appropriate collation function */ /* get the appropriate collation function */
icx->collate = ntfs_get_collate_function(ir->collation_rule); icx->collate = ntfs_get_collate_function(ir->collation_rule);
if ( !icx->collate ) if (!icx->collate) {
{
err = errno = EOPNOTSUPP; err = errno = EOPNOTSUPP;
ntfs_log_perror("Unknown collation rule 0x%x", ntfs_log_perror("Unknown collation rule 0x%x",
(unsigned)le32_to_cpu(ir->collation_rule)); (unsigned)le32_to_cpu(ir->collation_rule));
@ -747,16 +717,14 @@ int ntfs_index_lookup( const void *key, const int key_len, ntfs_index_context *i
* within the index block. * within the index block.
*/ */
ret = ntfs_ie_lookup(key, key_len, icx, &ir->index, &vcn, &ie); ret = ntfs_ie_lookup(key, key_len, icx, &ir->index, &vcn, &ie);
if ( ret == STATUS_ERROR ) if (ret == STATUS_ERROR) {
{
err = errno; err = errno;
goto err_out; goto err_out;
} }
icx->ir = ir; icx->ir = ir;
if ( ret != STATUS_KEEP_SEARCHING ) if (ret != STATUS_KEEP_SEARCHING) {
{
/* STATUS_OK or STATUS_NOT_FOUND */ /* STATUS_OK or STATUS_NOT_FOUND */
err = errno; err = errno;
icx->is_in_root = TRUE; icx->is_in_root = TRUE;
@ -771,8 +739,7 @@ int ntfs_index_lookup( const void *key, const int key_len, ntfs_index_context *i
goto err_out; goto err_out;
ib = ntfs_malloc(icx->block_size); ib = ntfs_malloc(icx->block_size);
if ( !ib ) if (!ib) {
{
err = errno; err = errno;
goto err_out; goto err_out;
} }
@ -780,8 +747,7 @@ int ntfs_index_lookup( const void *key, const int key_len, ntfs_index_context *i
descend_into_child_node: descend_into_child_node:
icx->parent_vcn[icx->pindex] = old_vcn; icx->parent_vcn[icx->pindex] = old_vcn;
if ( ntfs_icx_parent_inc( icx ) ) if (ntfs_icx_parent_inc(icx)) {
{
err = errno; err = errno;
goto err_out; goto err_out;
} }
@ -793,8 +759,7 @@ descend_into_child_node:
goto err_out; goto err_out;
ret = ntfs_ie_lookup(key, key_len, icx, &ib->index, &vcn, &ie); ret = ntfs_ie_lookup(key, key_len, icx, &ib->index, &vcn, &ie);
if ( ret != STATUS_KEEP_SEARCHING ) if (ret != STATUS_KEEP_SEARCHING) {
{
err = errno; err = errno;
if (ret == STATUS_ERROR) if (ret == STATUS_ERROR)
goto err_out; goto err_out;
@ -806,8 +771,7 @@ descend_into_child_node:
goto done; goto done;
} }
if ( ( ib->index.ih_flags & NODE_MASK ) == LEAF_NODE ) if ((ib->index.ih_flags & NODE_MASK) == LEAF_NODE) {
{
ntfs_log_error("Index entry with child node found in a leaf " ntfs_log_error("Index entry with child node found in a leaf "
"node in inode 0x%llx.\n", "node in inode 0x%llx.\n",
(unsigned long long)ni->mft_no); (unsigned long long)ni->mft_no);
@ -826,8 +790,7 @@ done:
icx->data = (u8 *)ie + offsetof(INDEX_ENTRY, key); icx->data = (u8 *)ie + offsetof(INDEX_ENTRY, key);
icx->data_len = le16_to_cpu(ie->key_length); icx->data_len = le16_to_cpu(ie->key_length);
ntfs_log_trace("Done.\n"); ntfs_log_trace("Done.\n");
if ( err ) if (err) {
{
errno = err; errno = err;
return -1; return -1;
} }
@ -880,8 +843,7 @@ static INDEX_ENTRY *ntfs_ie_get_median( INDEX_HEADER *ih )
ie = ie_start = ntfs_ie_get_first(ih); ie = ie_start = ntfs_ie_get_first(ih);
ie_end = (u8 *)ntfs_ie_get_end(ih); ie_end = (u8 *)ntfs_ie_get_end(ih);
while ( ( u8 * )ie < ie_end && !ntfs_ie_end( ie ) ) while ((u8 *)ie < ie_end && !ntfs_ie_end(ie)) {
{
ie = ntfs_ie_get_next(ie); ie = ntfs_ie_get_next(ie);
i++; i++;
} }
@ -921,8 +883,7 @@ static int ntfs_ibm_add( ntfs_index_context *icx )
*/ */
memset(bmp, 0, sizeof(bmp)); memset(bmp, 0, sizeof(bmp));
if (ntfs_attr_add(icx->ni, AT_BITMAP, icx->name, icx->name_len, if (ntfs_attr_add(icx->ni, AT_BITMAP, icx->name, icx->name_len,
bmp, sizeof( bmp ) ) ) bmp, sizeof(bmp))) {
{
ntfs_log_perror("Failed to add AT_BITMAP"); ntfs_log_perror("Failed to add AT_BITMAP");
return STATUS_ERROR; return STATUS_ERROR;
} }
@ -942,26 +903,21 @@ static int ntfs_ibm_modify( ntfs_index_context *icx, VCN vcn, int set )
ntfs_log_trace("%s vcn: %lld\n", set ? "set" : "clear", (long long)vcn); ntfs_log_trace("%s vcn: %lld\n", set ? "set" : "clear", (long long)vcn);
na = ntfs_attr_open(icx->ni, AT_BITMAP, icx->name, icx->name_len); na = ntfs_attr_open(icx->ni, AT_BITMAP, icx->name, icx->name_len);
if ( !na ) if (!na) {
{
ntfs_log_perror("Failed to open $BITMAP attribute"); ntfs_log_perror("Failed to open $BITMAP attribute");
return -1; return -1;
} }
if ( set ) if (set) {
{ if (na->data_size < bpos + 1) {
if ( na->data_size < bpos + 1 ) if (ntfs_attr_truncate(na, (na->data_size + 8) & ~7)) {
{
if ( ntfs_attr_truncate( na, ( na->data_size + 8 ) & ~7 ) )
{
ntfs_log_perror("Failed to truncate AT_BITMAP"); ntfs_log_perror("Failed to truncate AT_BITMAP");
goto err_na; goto err_na;
} }
} }
} }
if ( ntfs_attr_pread( na, bpos, 1, &byte ) != 1 ) if (ntfs_attr_pread(na, bpos, 1, &byte) != 1) {
{
ntfs_log_perror("Failed to read $BITMAP"); ntfs_log_perror("Failed to read $BITMAP");
goto err_na; goto err_na;
} }
@ -971,8 +927,7 @@ static int ntfs_ibm_modify( ntfs_index_context *icx, VCN vcn, int set )
else else
byte &= ~bit; byte &= ~bit;
if ( ntfs_attr_pwrite( na, bpos, 1, &byte ) != 1 ) if (ntfs_attr_pwrite(na, bpos, 1, &byte) != 1) {
{
ntfs_log_perror("Failed to write $Bitmap"); ntfs_log_perror("Failed to write $Bitmap");
goto err_na; goto err_na;
} }
@ -1007,16 +962,13 @@ static VCN ntfs_ibm_get_free( ntfs_index_context *icx )
if (!bm) if (!bm)
return (VCN)-1; return (VCN)-1;
for ( byte = 0; byte < size; byte++ ) for (byte = 0; byte < size; byte++) {
{
if (bm[byte] == 255) if (bm[byte] == 255)
continue; continue;
for ( bit = 0; bit < 8; bit++ ) for (bit = 0; bit < 8; bit++) {
{ if (!(bm[byte] & (1 << bit))) {
if ( !( bm[byte] & ( 1 << bit ) ) )
{
vcn = ntfs_ibm_pos_to_vcn(icx, byte * 8 + bit); vcn = ntfs_ibm_pos_to_vcn(icx, byte * 8 + bit);
goto out; goto out;
} }
@ -1078,8 +1030,7 @@ static void ntfs_ir_nill( INDEX_ROOT *ir )
/* /*
* Move the index root termination entry forward * Move the index root termination entry forward
*/ */
if ( ( char * )ie_last > ies_start ) if ((char *)ie_last > ies_start) {
{
memmove(ies_start, (char *)ie_last, le16_to_cpu(ie_last->length)); memmove(ies_start, (char *)ie_last, le16_to_cpu(ie_last->length));
ie_last = (INDEX_ENTRY *)ies_start; ie_last = (INDEX_ENTRY *)ies_start;
} }
@ -1147,12 +1098,10 @@ static int ntfs_ia_add( ntfs_index_context *icx )
if (ntfs_ibm_add(icx)) if (ntfs_ibm_add(icx))
return -1; return -1;
if ( !ntfs_attr_exist( icx->ni, AT_INDEX_ALLOCATION, icx->name, icx->name_len ) ) if (!ntfs_attr_exist(icx->ni, AT_INDEX_ALLOCATION, icx->name, icx->name_len)) {
{
if (ntfs_attr_add(icx->ni, AT_INDEX_ALLOCATION, icx->name, if (ntfs_attr_add(icx->ni, AT_INDEX_ALLOCATION, icx->name,
icx->name_len, NULL, 0 ) ) icx->name_len, NULL, 0)) {
{
ntfs_log_perror("Failed to add AT_INDEX_ALLOCATION"); ntfs_log_perror("Failed to add AT_INDEX_ALLOCATION");
return -1; return -1;
} }
@ -1193,8 +1142,7 @@ static int ntfs_ir_reparent( ntfs_index_context *icx )
goto clear_bmp; goto clear_bmp;
ib = ntfs_ir_to_ib(ir, new_ib_vcn); ib = ntfs_ir_to_ib(ir, new_ib_vcn);
if ( ib == NULL ) if (ib == NULL) {
{
ntfs_log_perror("Failed to move index root to index block"); ntfs_log_perror("Failed to move index root to index block");
goto clear_bmp; goto clear_bmp;
} }
@ -1252,8 +1200,7 @@ static int ntfs_ir_truncate( ntfs_index_context *icx, int data_size )
ntfs_log_trace("Entering\n"); ntfs_log_trace("Entering\n");
na = ntfs_attr_open(icx->ni, AT_INDEX_ROOT, icx->name, icx->name_len); na = ntfs_attr_open(icx->ni, AT_INDEX_ROOT, icx->name, icx->name_len);
if ( !na ) if (!na) {
{
ntfs_log_perror("Failed to open INDEX_ROOT"); ntfs_log_perror("Failed to open INDEX_ROOT");
return STATUS_ERROR; return STATUS_ERROR;
} }
@ -1262,8 +1209,7 @@ static int ntfs_ir_truncate( ntfs_index_context *icx, int data_size )
* INDEX_BLOCK, so ENOSPC isn't a real error. * INDEX_BLOCK, so ENOSPC isn't a real error.
*/ */
ret = ntfs_attr_truncate(na, data_size + offsetof(INDEX_ROOT, index)); ret = ntfs_attr_truncate(na, data_size + offsetof(INDEX_ROOT, index));
if ( ret == STATUS_OK ) if (ret == STATUS_OK) {
{
icx->ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len); icx->ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len);
if (!icx->ir) if (!icx->ir)
@ -1271,8 +1217,7 @@ static int ntfs_ir_truncate( ntfs_index_context *icx, int data_size )
icx->ir->index.allocated_size = cpu_to_le32(data_size); icx->ir->index.allocated_size = cpu_to_le32(data_size);
} } else if (ret == STATUS_ERROR)
else if ( ret == STATUS_ERROR )
ntfs_log_perror("Failed to truncate INDEX_ROOT"); ntfs_log_perror("Failed to truncate INDEX_ROOT");
ntfs_attr_close(na); ntfs_attr_close(na);
@ -1292,8 +1237,7 @@ static int ntfs_ir_make_space( ntfs_index_context *icx, int data_size )
ntfs_log_trace("Entering\n"); ntfs_log_trace("Entering\n");
ret = ntfs_ir_truncate(icx, data_size); ret = ntfs_ir_truncate(icx, data_size);
if ( ret == STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT ) if (ret == STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT) {
{
ret = ntfs_ir_reparent(icx); ret = ntfs_ir_reparent(icx);
if (ret == STATUS_OK) if (ret == STATUS_OK)
@ -1420,8 +1364,7 @@ static int ntfs_ib_insert( ntfs_index_context *icx, INDEX_ENTRY *ie, VCN new_vcn
idx_size = le32_to_cpu(ib->index.index_length); idx_size = le32_to_cpu(ib->index.index_length);
allocated_size = le32_to_cpu(ib->index.allocated_size); allocated_size = le32_to_cpu(ib->index.allocated_size);
/* FIXME: sizeof(VCN) should be included only if ie has no VCN */ /* FIXME: sizeof(VCN) should be included only if ie has no VCN */
if ( idx_size + le16_to_cpu( ie->length ) + sizeof( VCN ) > allocated_size ) if (idx_size + le16_to_cpu(ie->length) + sizeof(VCN) > allocated_size) {
{
err = ntfs_ib_split(icx, ib); err = ntfs_ib_split(icx, ib);
if (err == STATUS_OK) if (err == STATUS_OK)
err = STATUS_KEEP_SEARCHING; err = STATUS_KEEP_SEARCHING;
@ -1462,8 +1405,7 @@ static int ntfs_ib_split( ntfs_index_context *icx, INDEX_BLOCK *ib )
if (new_vcn == -1) if (new_vcn == -1)
return STATUS_ERROR; return STATUS_ERROR;
if ( ntfs_ib_copy_tail( icx, ib, median, new_vcn ) ) if (ntfs_ib_copy_tail(icx, ib, median, new_vcn)) {
{
ntfs_ibm_clear(icx, new_vcn); ntfs_ibm_clear(icx, new_vcn);
return STATUS_ERROR; return STATUS_ERROR;
} }
@ -1473,8 +1415,7 @@ static int ntfs_ib_split( ntfs_index_context *icx, INDEX_BLOCK *ib )
else else
ret = ntfs_ib_insert(icx, median, new_vcn); ret = ntfs_ib_insert(icx, median, new_vcn);
if ( ret != STATUS_OK ) if (ret != STATUS_OK) {
{
ntfs_ibm_clear(icx, new_vcn); ntfs_ibm_clear(icx, new_vcn);
return ret; return ret;
} }
@ -1500,17 +1441,14 @@ int ntfs_ie_add( ntfs_index_context *icx, INDEX_ENTRY *ie )
*/ */
#endif #endif
while ( 1 ) while (1) {
{
if ( !ntfs_index_lookup( &ie->key, le16_to_cpu( ie->key_length ), icx ) ) if (!ntfs_index_lookup(&ie->key, le16_to_cpu(ie->key_length), icx)) {
{
errno = EEXIST; errno = EEXIST;
ntfs_log_perror("Index already have such entry"); ntfs_log_perror("Index already have such entry");
goto err_out; goto err_out;
} }
if ( errno != ENOENT ) if (errno != ENOENT) {
{
ntfs_log_perror("Failed to find place for new entry"); ntfs_log_perror("Failed to find place for new entry");
goto err_out; goto err_out;
} }
@ -1529,13 +1467,10 @@ int ntfs_ie_add( ntfs_index_context *icx, INDEX_ENTRY *ie )
ntfs_log_trace("index block sizes: allocated: %d needed: %d\n", ntfs_log_trace("index block sizes: allocated: %d needed: %d\n",
allocated_size, new_size); allocated_size, new_size);
if ( icx->is_in_root ) if (icx->is_in_root) {
{
if (ntfs_ir_make_space(icx, new_size) == STATUS_ERROR) if (ntfs_ir_make_space(icx, new_size) == STATUS_ERROR)
goto err_out; goto err_out;
} } else {
else
{
if (ntfs_ib_split(icx, icx->ib) == STATUS_ERROR) if (ntfs_ib_split(icx, icx->ib) == STATUS_ERROR)
goto err_out; goto err_out;
} }
@ -1569,8 +1504,7 @@ int ntfs_index_add_filename( ntfs_inode *ni, FILE_NAME_ATTR *fn, MFT_REF mref )
ntfs_log_trace("Entering\n"); ntfs_log_trace("Entering\n");
if ( !ni || !fn ) if (!ni || !fn) {
{
ntfs_log_error("Invalid arguments.\n"); ntfs_log_error("Invalid arguments.\n");
errno = EINVAL; errno = EINVAL;
return -1; return -1;
@ -1618,7 +1552,8 @@ static int ntfs_ih_takeout( ntfs_index_context *icx, INDEX_HEADER *ih,
if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT)
ntfs_inode_mark_dirty(icx->actx->ntfs_ino); ntfs_inode_mark_dirty(icx->actx->ntfs_ino);
else if ( ntfs_ib_write( icx, ib ) ) else
if (ntfs_ib_write(icx, ib))
goto out; goto out;
ntfs_index_ctx_reinit(icx); ntfs_index_ctx_reinit(icx);
@ -1686,8 +1621,7 @@ static int ntfs_index_rm_leaf( ntfs_index_context *icx )
if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT)
parent_ih = &icx->ir->index; parent_ih = &icx->ir->index;
else else {
{
ib = ntfs_malloc(icx->block_size); ib = ntfs_malloc(icx->block_size);
if (!ib) if (!ib)
return STATUS_ERROR; return STATUS_ERROR;
@ -1699,17 +1633,14 @@ static int ntfs_index_rm_leaf( ntfs_index_context *icx )
} }
ie = ntfs_ie_get_by_pos(parent_ih, ntfs_icx_parent_pos(icx)); ie = ntfs_ie_get_by_pos(parent_ih, ntfs_icx_parent_pos(icx));
if ( !ntfs_ie_end( ie ) ) if (!ntfs_ie_end(ie)) {
{
ret = ntfs_ih_takeout(icx, parent_ih, ie, ib); ret = ntfs_ih_takeout(icx, parent_ih, ie, ib);
goto out; goto out;
} }
if ( ntfs_ih_zero_entry( parent_ih ) ) if (ntfs_ih_zero_entry(parent_ih)) {
{
if ( ntfs_icx_parent_vcn( icx ) == VCN_INDEX_ROOT_PARENT ) if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) {
{
ntfs_ir_leafify(icx, parent_ih); ntfs_ir_leafify(icx, parent_ih);
goto ok; goto ok;
} }
@ -1739,8 +1670,7 @@ static int ntfs_index_rm_node( ntfs_index_context *icx )
ntfs_log_trace("Entering\n"); ntfs_log_trace("Entering\n");
if ( !icx->ia_na ) if (!icx->ia_na) {
{
icx->ia_na = ntfs_ia_open(icx, icx->ni); icx->ia_na = ntfs_ia_open(icx, icx->ni);
if (!icx->ia_na) if (!icx->ia_na)
return STATUS_ERROR; return STATUS_ERROR;
@ -1769,8 +1699,7 @@ descend:
if ((ib->index.ih_flags & NODE_MASK) == INDEX_NODE) if ((ib->index.ih_flags & NODE_MASK) == INDEX_NODE)
goto descend; goto descend;
if ( ntfs_ih_zero_entry( &ib->index ) ) if (ntfs_ih_zero_entry(&ib->index)) {
{
errno = EIO; errno = EIO;
ntfs_log_perror("Empty index block"); ntfs_log_perror("Empty index block");
goto out; goto out;
@ -1792,10 +1721,8 @@ descend:
delta = le16_to_cpu(ie->length) - le16_to_cpu(icx->entry->length); delta = le16_to_cpu(ie->length) - le16_to_cpu(icx->entry->length);
new_size = le32_to_cpu(ih->index_length) + delta; new_size = le32_to_cpu(ih->index_length) + delta;
if ( delta > 0 ) if (delta > 0) {
{ if (icx->is_in_root) {
if ( icx->is_in_root )
{
ret = ntfs_ir_make_space(icx, new_size); ret = ntfs_ir_make_space(icx, new_size);
if (ret != STATUS_OK) if (ret != STATUS_OK)
goto out2; goto out2;
@ -1803,9 +1730,7 @@ descend:
ih = &icx->ir->index; ih = &icx->ir->index;
entry = ntfs_ie_get_by_pos(ih, entry_pos); entry = ntfs_ie_get_by_pos(ih, entry_pos);
} } else if (new_size > le32_to_cpu(ih->allocated_size)) {
else if ( new_size > le32_to_cpu( ih->allocated_size ) )
{
icx->pindex = pindex; icx->pindex = pindex;
ret = ntfs_ib_split(icx, icx->ib); ret = ntfs_ib_split(icx, icx->ib);
if (ret == STATUS_OK) if (ret == STATUS_OK)
@ -1817,22 +1742,20 @@ descend:
ntfs_ie_delete(ih, entry); ntfs_ie_delete(ih, entry);
ntfs_ie_insert(ih, ie, entry); ntfs_ie_insert(ih, ie, entry);
if ( icx->is_in_root ) if (icx->is_in_root) {
{
if (ntfs_ir_truncate(icx, new_size)) if (ntfs_ir_truncate(icx, new_size))
goto out2; goto out2;
} } else
else if ( ntfs_icx_ib_write( icx ) ) if (ntfs_icx_ib_write(icx))
goto out2; goto out2;
ntfs_ie_delete(&ib->index, ie_succ); ntfs_ie_delete(&ib->index, ie_succ);
if ( ntfs_ih_zero_entry( &ib->index ) ) if (ntfs_ih_zero_entry(&ib->index)) {
{
if (ntfs_index_rm_leaf(icx)) if (ntfs_index_rm_leaf(icx))
goto out2; goto out2;
} } else
else if ( ntfs_ib_write( icx, ib ) ) if (ntfs_ib_write(icx, ib))
goto out2; goto out2;
ret = STATUS_OK; ret = STATUS_OK;
@ -1861,8 +1784,7 @@ int ntfs_index_rm( ntfs_index_context *icx )
ntfs_log_trace("Entering\n"); ntfs_log_trace("Entering\n");
if ( !icx || ( !icx->ib && !icx->ir ) || ntfs_ie_end( icx->entry ) ) if (!icx || (!icx->ib && !icx->ir) || ntfs_ie_end(icx->entry)) {
{
ntfs_log_error("Invalid arguments.\n"); ntfs_log_error("Invalid arguments.\n");
errno = EINVAL; errno = EINVAL;
goto err_out; goto err_out;
@ -1872,28 +1794,22 @@ int ntfs_index_rm( ntfs_index_context *icx )
else else
ih = &icx->ib->index; ih = &icx->ib->index;
if ( icx->entry->ie_flags & INDEX_ENTRY_NODE ) if (icx->entry->ie_flags & INDEX_ENTRY_NODE) {
{
ret = ntfs_index_rm_node(icx); ret = ntfs_index_rm_node(icx);
} } else if (icx->is_in_root || !ntfs_ih_one_entry(ih)) {
else if ( icx->is_in_root || !ntfs_ih_one_entry( ih ) )
{
ntfs_ie_delete(ih, icx->entry); ntfs_ie_delete(ih, icx->entry);
if ( icx->is_in_root ) if (icx->is_in_root) {
{
err = ntfs_ir_truncate(icx, le32_to_cpu(ih->index_length)); err = ntfs_ir_truncate(icx, le32_to_cpu(ih->index_length));
if (err != STATUS_OK) if (err != STATUS_OK)
goto err_out; goto err_out;
} } else
else if ( ntfs_icx_ib_write( icx ) ) if (ntfs_icx_ib_write(icx))
goto err_out; goto err_out;
} } else {
else
{
if (ntfs_index_rm_leaf(icx)) if (ntfs_index_rm_leaf(icx))
goto err_out; goto err_out;
} }
@ -1914,16 +1830,14 @@ int ntfs_index_remove( ntfs_inode *dir_ni, ntfs_inode *ni,
if (!icx) if (!icx)
return -1; return -1;
while ( 1 ) while (1) {
{
if (ntfs_index_lookup(key, keylen, icx)) if (ntfs_index_lookup(key, keylen, icx))
goto err_out; goto err_out;
if ((((FILE_NAME_ATTR *)icx->data)->file_attributes & if ((((FILE_NAME_ATTR *)icx->data)->file_attributes &
FILE_ATTR_REPARSE_POINT) FILE_ATTR_REPARSE_POINT)
&& !ntfs_possible_symlink( ni ) ) && !ntfs_possible_symlink(ni)) {
{
errno = EOPNOTSUPP; errno = EOPNOTSUPP;
goto err_out; goto err_out;
} }
@ -1996,11 +1910,9 @@ static INDEX_ENTRY *ntfs_index_walk_down( INDEX_ENTRY *ie,
s64 vcn; s64 vcn;
entry = ie; entry = ie;
do do {
{
vcn = ntfs_ie_get_vcn(entry); vcn = ntfs_ie_get_vcn(entry);
if ( ictx->is_in_root ) if (ictx->is_in_root) {
{
/* down from level zero */ /* down from level zero */
@ -2008,9 +1920,7 @@ static INDEX_ENTRY *ntfs_index_walk_down( INDEX_ENTRY *ie,
ictx->ib = (INDEX_BLOCK*)ntfs_malloc(ictx->block_size); ictx->ib = (INDEX_BLOCK*)ntfs_malloc(ictx->block_size);
ictx->pindex = 1; ictx->pindex = 1;
ictx->is_in_root = FALSE; ictx->is_in_root = FALSE;
} } else {
else
{
/* down from non-zero level */ /* down from non-zero level */
@ -2018,15 +1928,12 @@ static INDEX_ENTRY *ntfs_index_walk_down( INDEX_ENTRY *ie,
} }
ictx->parent_pos[ictx->pindex] = 0; ictx->parent_pos[ictx->pindex] = 0;
ictx->parent_vcn[ictx->pindex] = vcn; ictx->parent_vcn[ictx->pindex] = vcn;
if ( !ntfs_ib_read( ictx, vcn, ictx->ib ) ) if (!ntfs_ib_read(ictx,vcn,ictx->ib)) {
{
ictx->entry = ntfs_ie_get_first(&ictx->ib->index); ictx->entry = ntfs_ie_get_first(&ictx->ib->index);
entry = ictx->entry; entry = ictx->entry;
} } else
else
entry = (INDEX_ENTRY*)NULL; entry = (INDEX_ENTRY*)NULL;
} } while (entry && (entry->ie_flags & INDEX_ENTRY_NODE));
while ( entry && ( entry->ie_flags & INDEX_ENTRY_NODE ) );
return (entry); return (entry);
} }
@ -2043,13 +1950,10 @@ static INDEX_ENTRY *ntfs_index_walk_up( INDEX_ENTRY *ie,
s64 vcn; s64 vcn;
entry = ie; entry = ie;
if ( ictx->pindex > 0 ) if (ictx->pindex > 0) {
{ do {
do
{
ictx->pindex--; ictx->pindex--;
if ( !ictx->pindex ) if (!ictx->pindex) {
{
/* we have reached the root */ /* we have reached the root */
@ -2068,26 +1972,20 @@ static INDEX_ENTRY *ntfs_index_walk_up( INDEX_ENTRY *ie,
ictx->parent_pos[ictx->pindex]); ictx->parent_pos[ictx->pindex]);
else else
entry = (INDEX_ENTRY*)NULL; entry = (INDEX_ENTRY*)NULL;
} } else {
else
{
/* up into non-root node */ /* up into non-root node */
vcn = ictx->parent_vcn[ictx->pindex]; vcn = ictx->parent_vcn[ictx->pindex];
if ( !ntfs_ib_read( ictx, vcn, ictx->ib ) ) if (!ntfs_ib_read(ictx,vcn,ictx->ib)) {
{
entry = ntfs_ie_get_by_pos( entry = ntfs_ie_get_by_pos(
&ictx->ib->index, &ictx->ib->index,
ictx->parent_pos[ictx->pindex]); ictx->parent_pos[ictx->pindex]);
} } else
else
entry = (INDEX_ENTRY*)NULL; entry = (INDEX_ENTRY*)NULL;
} }
ictx->entry = entry; ictx->entry = entry;
} } while (entry && (ictx->pindex > 0)
while ( entry && ( ictx->pindex > 0 )
&& (entry->ie_flags & INDEX_ENTRY_END)); && (entry->ie_flags & INDEX_ENTRY_END));
} } else
else
entry = (INDEX_ENTRY*)NULL; entry = (INDEX_ENTRY*)NULL;
return (entry); return (entry);
} }
@ -2132,8 +2030,7 @@ INDEX_ENTRY *ntfs_index_next( INDEX_ENTRY *ie, ntfs_index_context *ictx )
if (ie->ie_flags & INDEX_ENTRY_END) if (ie->ie_flags & INDEX_ENTRY_END)
next = ntfs_index_walk_up(ie, ictx); next = ntfs_index_walk_up(ie, ictx);
else else {
{
/* /*
* get next entry in same node * get next entry in same node
* there is always one after any entry with data * there is always one after any entry with data
@ -2145,17 +2042,13 @@ INDEX_ENTRY *ntfs_index_next( INDEX_ENTRY *ie, ntfs_index_context *ictx )
/* walk down if it has a subnode */ /* walk down if it has a subnode */
if ( flags & INDEX_ENTRY_NODE ) if (flags & INDEX_ENTRY_NODE) {
{
next = ntfs_index_walk_down(next,ictx); next = ntfs_index_walk_down(next,ictx);
} } else {
else
{
/* walk up it has no subnode, nor data */ /* walk up it has no subnode, nor data */
if ( flags & INDEX_ENTRY_END ) if (flags & INDEX_ENTRY_END) {
{
next = ntfs_index_walk_up(next, ictx); next = ntfs_index_walk_up(next, ictx);
} }
} }

View File

@ -112,8 +112,7 @@ typedef int ( *COLLATE )( ntfs_volume *vol, const void *data1, int len1,
* the call to ntfs_index_ctx_put() to ensure that the changes are written * the call to ntfs_index_ctx_put() to ensure that the changes are written
* to disk. * to disk.
*/ */
typedef struct typedef struct {
{
ntfs_inode *ni; ntfs_inode *ni;
ntfschar *name; ntfschar *name;
u32 name_len; u32 name_len;

View File

@ -166,8 +166,7 @@ static ntfs_inode *ntfs_inode_real_open( ntfs_volume *vol, const MFT_REF mref )
int olderrno; int olderrno;
ntfs_log_enter("Entering for inode %lld\n", (long long)MREF(mref)); ntfs_log_enter("Entering for inode %lld\n", (long long)MREF(mref));
if ( !vol ) if (!vol) {
{
errno = EINVAL; errno = EINVAL;
goto out; goto out;
} }
@ -176,8 +175,7 @@ static ntfs_inode *ntfs_inode_real_open( ntfs_volume *vol, const MFT_REF mref )
goto out; goto out;
if (ntfs_file_record_read(vol, mref, &ni->mrec, NULL)) if (ntfs_file_record_read(vol, mref, &ni->mrec, NULL))
goto err_out; goto err_out;
if ( !( ni->mrec->flags & MFT_RECORD_IN_USE ) ) if (!(ni->mrec->flags & MFT_RECORD_IN_USE)) {
{
errno = ENOENT; errno = ENOENT;
goto err_out; goto err_out;
} }
@ -187,8 +185,7 @@ static ntfs_inode *ntfs_inode_real_open( ntfs_volume *vol, const MFT_REF mref )
goto err_out; goto err_out;
/* Receive some basic information about inode. */ /* Receive some basic information about inode. */
if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED,
0, CASE_SENSITIVE, 0, NULL, 0, ctx ) ) 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) {
{
if (!ni->mrec->base_mft_record) if (!ni->mrec->base_mft_record)
ntfs_log_perror("No STANDARD_INFORMATION in base record" ntfs_log_perror("No STANDARD_INFORMATION in base record"
" %lld", (long long)MREF(mref)); " %lld", (long long)MREF(mref));
@ -204,16 +201,13 @@ static ntfs_inode *ntfs_inode_real_open( ntfs_volume *vol, const MFT_REF mref )
/* JPA insert v3 extensions if present */ /* JPA insert v3 extensions if present */
/* length may be seen as 72 (v1.x) or 96 (v3.x) */ /* length may be seen as 72 (v1.x) or 96 (v3.x) */
lthle = ctx->attr->length; lthle = ctx->attr->length;
if ( le32_to_cpu( lthle ) > sizeof( STANDARD_INFORMATION ) ) if (le32_to_cpu(lthle) > sizeof(STANDARD_INFORMATION)) {
{
set_nino_flag(ni, v3_Extensions); set_nino_flag(ni, v3_Extensions);
ni->owner_id = std_info->owner_id; ni->owner_id = std_info->owner_id;
ni->security_id = std_info->security_id; ni->security_id = std_info->security_id;
ni->quota_charged = std_info->quota_charged; ni->quota_charged = std_info->quota_charged;
ni->usn = std_info->usn; ni->usn = std_info->usn;
} } else {
else
{
clear_nino_flag(ni, v3_Extensions); clear_nino_flag(ni, v3_Extensions);
ni->owner_id = const_cpu_to_le32(0); ni->owner_id = const_cpu_to_le32(0);
ni->security_id = const_cpu_to_le32(0); ni->security_id = const_cpu_to_le32(0);
@ -221,8 +215,7 @@ static ntfs_inode *ntfs_inode_real_open( ntfs_volume *vol, const MFT_REF mref )
/* Set attribute list information. */ /* Set attribute list information. */
olderrno = errno; olderrno = errno;
if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0,
CASE_SENSITIVE, 0, NULL, 0, ctx ) ) CASE_SENSITIVE, 0, NULL, 0, ctx)) {
{
if (errno != ENOENT) if (errno != ENOENT)
goto put_err_out; goto put_err_out;
/* Attribute list attribute does not present. */ /* Attribute list attribute does not present. */
@ -234,8 +227,7 @@ static ntfs_inode *ntfs_inode_real_open( ntfs_volume *vol, const MFT_REF mref )
l = ntfs_get_attribute_value_length(ctx->attr); l = ntfs_get_attribute_value_length(ctx->attr);
if (!l) if (!l)
goto put_err_out; goto put_err_out;
if ( l > 0x40000 ) if (l > 0x40000) {
{
errno = EIO; errno = EIO;
ntfs_log_perror("Too large attrlist attribute (%lld), inode " ntfs_log_perror("Too large attrlist attribute (%lld), inode "
"%lld", (long long)l, (long long)MREF(mref)); "%lld", (long long)l, (long long)MREF(mref));
@ -248,8 +240,7 @@ static ntfs_inode *ntfs_inode_real_open( ntfs_volume *vol, const MFT_REF mref )
l = ntfs_get_attribute_value(vol, ctx->attr, ni->attr_list); l = ntfs_get_attribute_value(vol, ctx->attr, ni->attr_list);
if (!l) if (!l)
goto put_err_out; goto put_err_out;
if ( l != ni->attr_list_size ) if (l != ni->attr_list_size) {
{
errno = EIO; errno = EIO;
ntfs_log_perror("Unexpected attrlist size (%lld <> %u), inode " ntfs_log_perror("Unexpected attrlist size (%lld <> %u), inode "
"%lld", (long long)l, ni->attr_list_size, "%lld", (long long)l, ni->attr_list_size,
@ -258,19 +249,15 @@ static ntfs_inode *ntfs_inode_real_open( ntfs_volume *vol, const MFT_REF mref )
} }
get_size: get_size:
olderrno = errno; olderrno = errno;
if ( ntfs_attr_lookup( AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx ) ) if (ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
{
if (errno != ENOENT) if (errno != ENOENT)
goto put_err_out; goto put_err_out;
/* Directory or special file. */ /* Directory or special file. */
/* restore previous errno to avoid misinterpretation */ /* restore previous errno to avoid misinterpretation */
errno = olderrno; errno = olderrno;
ni->data_size = ni->allocated_size = 0; ni->data_size = ni->allocated_size = 0;
} } else {
else if (ctx->attr->non_resident) {
{
if ( ctx->attr->non_resident )
{
ni->data_size = sle64_to_cpu(ctx->attr->data_size); ni->data_size = sle64_to_cpu(ctx->attr->data_size);
if (ctx->attr->flags & if (ctx->attr->flags &
(ATTR_IS_COMPRESSED | ATTR_IS_SPARSE)) (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE))
@ -279,9 +266,7 @@ get_size:
else else
ni->allocated_size = sle64_to_cpu( ni->allocated_size = sle64_to_cpu(
ctx->attr->allocated_size); ctx->attr->allocated_size);
} } else {
else
{
ni->data_size = le32_to_cpu(ctx->attr->value_length); ni->data_size = le32_to_cpu(ctx->attr->value_length);
ni->allocated_size = (ni->data_size + 7) & ~7; ni->allocated_size = (ni->data_size + 7) & ~7;
} }
@ -335,30 +320,23 @@ int ntfs_inode_real_close( ntfs_inode *ni )
ntfs_log_enter("Entering for inode %lld\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 we have dirty metadata, write it out. */
if ( NInoDirty( ni ) || NInoAttrListDirty( ni ) ) if (NInoDirty(ni) || NInoAttrListDirty(ni)) {
{ if (ntfs_inode_sync(ni)) {
if ( ntfs_inode_sync( ni ) )
{
if (errno != EIO) if (errno != EIO)
errno = EBUSY; errno = EBUSY;
goto err; goto err;
} }
} }
/* Is this a base inode with mapped extent inodes? */ /* Is this a base inode with mapped extent inodes? */
if ( ni->nr_extents > 0 ) if (ni->nr_extents > 0) {
{ while (ni->nr_extents > 0) {
while ( ni->nr_extents > 0 ) if (ntfs_inode_real_close(ni->extent_nis[0])) {
{
if ( ntfs_inode_real_close( ni->extent_nis[0] ) )
{
if (errno != EIO) if (errno != EIO)
errno = EBUSY; errno = EBUSY;
goto err; goto err;
} }
} }
} } else if (ni->nr_extents == -1) {
else if ( ni->nr_extents == -1 )
{
ntfs_inode **tmp_nis; ntfs_inode **tmp_nis;
ntfs_inode *base_ni; ntfs_inode *base_ni;
s32 i; s32 i;
@ -368,8 +346,7 @@ int ntfs_inode_real_close( ntfs_inode *ni )
* base inode before destroying it. * base inode before destroying it.
*/ */
base_ni = ni->base_ni; base_ni = ni->base_ni;
for ( i = 0; i < base_ni->nr_extents; ++i ) for (i = 0; i < base_ni->nr_extents; ++i) {
{
tmp_nis = base_ni->extent_nis; tmp_nis = base_ni->extent_nis;
if (tmp_nis[i] != ni) if (tmp_nis[i] != ni)
continue; continue;
@ -378,8 +355,7 @@ int ntfs_inode_real_close( ntfs_inode *ni )
(base_ni->nr_extents - i - 1) * (base_ni->nr_extents - i - 1) *
sizeof(ntfs_inode *)); sizeof(ntfs_inode *));
/* Buffer should be for multiple of four extents. */ /* Buffer should be for multiple of four extents. */
if ( ( --base_ni->nr_extents ) & 3 ) if ((--base_ni->nr_extents) & 3) {
{
i = -1; i = -1;
break; break;
} }
@ -387,17 +363,14 @@ int ntfs_inode_real_close( ntfs_inode *ni )
* ElectricFence is unhappy with realloc(x,0) as free(x) * ElectricFence is unhappy with realloc(x,0) as free(x)
* thus we explicitly separate these two cases. * thus we explicitly separate these two cases.
*/ */
if ( base_ni->nr_extents ) if (base_ni->nr_extents) {
{
/* Resize the memory buffer. */ /* Resize the memory buffer. */
tmp_nis = realloc(tmp_nis, base_ni->nr_extents * tmp_nis = realloc(tmp_nis, base_ni->nr_extents *
sizeof(ntfs_inode *)); sizeof(ntfs_inode *));
/* Ignore errors, they don't really matter. */ /* Ignore errors, they don't really matter. */
if (tmp_nis) if (tmp_nis)
base_ni->extent_nis = tmp_nis; base_ni->extent_nis = tmp_nis;
} } else if (tmp_nis) {
else if ( tmp_nis )
{
free(tmp_nis); free(tmp_nis);
base_ni->extent_nis = (ntfs_inode**)NULL; base_ni->extent_nis = (ntfs_inode**)NULL;
} }
@ -500,15 +473,12 @@ ntfs_inode *ntfs_inode_open( ntfs_volume *vol, const MFT_REF mref )
item.varsize = 0; item.varsize = 0;
cached = (struct CACHED_NIDATA*)ntfs_fetch_cache(vol->nidata_cache, cached = (struct CACHED_NIDATA*)ntfs_fetch_cache(vol->nidata_cache,
GENERIC(&item),idata_cache_compare); GENERIC(&item),idata_cache_compare);
if ( cached ) if (cached) {
{
ni = cached->ni; ni = cached->ni;
/* do not keep open entries in cache */ /* do not keep open entries in cache */
ntfs_remove_cache(vol->nidata_cache, ntfs_remove_cache(vol->nidata_cache,
(struct CACHED_GENERIC*)cached,0); (struct CACHED_GENERIC*)cached,0);
} } else {
else
{
ni = ntfs_inode_real_open(vol, mref); ni = ntfs_inode_real_open(vol, mref);
} }
#else #else
@ -534,29 +504,24 @@ int ntfs_inode_close( ntfs_inode *ni )
BOOL dirty; BOOL dirty;
struct CACHED_NIDATA item; struct CACHED_NIDATA item;
if ( ni ) if (ni) {
{
debug_double_inode(ni->mft_no,0); debug_double_inode(ni->mft_no,0);
/* do not cache system files : could lead to double entries */ /* do not cache system files : could lead to double entries */
if (ni->vol && ni->vol->nidata_cache if (ni->vol && ni->vol->nidata_cache
&& ((ni->mft_no == FILE_root) && ((ni->mft_no == FILE_root)
|| ((ni->mft_no >= FILE_first_user) || ((ni->mft_no >= FILE_first_user)
&& !( ni->mrec->flags & MFT_RECORD_IS_4 ) ) ) ) && !(ni->mrec->flags & MFT_RECORD_IS_4)))) {
{
/* If we have dirty metadata, write it out. */ /* If we have dirty metadata, write it out. */
dirty = NInoDirty(ni) || NInoAttrListDirty(ni); dirty = NInoDirty(ni) || NInoAttrListDirty(ni);
if ( dirty ) if (dirty) {
{
res = ntfs_inode_sync(ni); res = ntfs_inode_sync(ni);
/* do a real close if sync failed */ /* do a real close if sync failed */
if (res) if (res)
ntfs_inode_real_close(ni); ntfs_inode_real_close(ni);
} } else
else
res = 0; res = 0;
if ( !res ) if (!res) {
{
/* feed idata into cache */ /* feed idata into cache */
item.inum = ni->mft_no; item.inum = ni->mft_no;
item.ni = ni; item.ni = ni;
@ -566,14 +531,11 @@ int ntfs_inode_close( ntfs_inode *ni )
ntfs_enter_cache(ni->vol->nidata_cache, ntfs_enter_cache(ni->vol->nidata_cache,
GENERIC(&item), idata_cache_compare); GENERIC(&item), idata_cache_compare);
} }
} } else {
else
{
/* cache not ready or system file, really close */ /* cache not ready or system file, really close */
res = ntfs_inode_real_close(ni); res = ntfs_inode_real_close(ni);
} }
} } else
else
res = 0; res = 0;
#else #else
res = ntfs_inode_real_close(ni); res = ntfs_inode_real_close(ni);
@ -613,8 +575,7 @@ ntfs_inode *ntfs_extent_inode_open( ntfs_inode *base_ni, const MFT_REF mref )
ntfs_inode **extent_nis; ntfs_inode **extent_nis;
int i; int i;
if ( !base_ni ) if (!base_ni) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s", __FUNCTION__); ntfs_log_perror("%s", __FUNCTION__);
return NULL; return NULL;
@ -625,11 +586,9 @@ ntfs_inode *ntfs_extent_inode_open( ntfs_inode *base_ni, const MFT_REF mref )
(unsigned long long)base_ni->mft_no); (unsigned long long)base_ni->mft_no);
/* Is the extent inode already open and attached to the base inode? */ /* Is the extent inode already open and attached to the base inode? */
if ( base_ni->nr_extents > 0 ) if (base_ni->nr_extents > 0) {
{
extent_nis = base_ni->extent_nis; extent_nis = base_ni->extent_nis;
for ( i = 0; i < base_ni->nr_extents; i++ ) for (i = 0; i < base_ni->nr_extents; i++) {
{
u16 seq_no; u16 seq_no;
ni = extent_nis[i]; ni = extent_nis[i];
@ -638,8 +597,7 @@ ntfs_inode *ntfs_extent_inode_open( ntfs_inode *base_ni, const MFT_REF mref )
/* Verify the sequence number if given. */ /* Verify the sequence number if given. */
seq_no = MSEQNO_LE(mref); seq_no = MSEQNO_LE(mref);
if (seq_no && seq_no != le16_to_cpu( if (seq_no && seq_no != le16_to_cpu(
ni->mrec->sequence_number ) ) ni->mrec->sequence_number)) {
{
errno = EIO; errno = EIO;
ntfs_log_perror("Found stale extent mft " ntfs_log_perror("Found stale extent mft "
"reference mft=%lld", "reference mft=%lld",
@ -659,15 +617,13 @@ ntfs_inode *ntfs_extent_inode_open( ntfs_inode *base_ni, const MFT_REF mref )
ni->nr_extents = -1; ni->nr_extents = -1;
ni->base_ni = base_ni; ni->base_ni = base_ni;
/* Attach extent inode to base inode, reallocating memory if needed. */ /* Attach extent inode to base inode, reallocating memory if needed. */
if ( !( base_ni->nr_extents & 3 ) ) if (!(base_ni->nr_extents & 3)) {
{
i = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *); i = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *);
extent_nis = ntfs_malloc(i); extent_nis = ntfs_malloc(i);
if (!extent_nis) if (!extent_nis)
goto err_out; goto err_out;
if ( base_ni->nr_extents ) if (base_ni->nr_extents) {
{
memcpy(extent_nis, base_ni->extent_nis, memcpy(extent_nis, base_ni->extent_nis,
i - 4 * sizeof(ntfs_inode *)); i - 4 * sizeof(ntfs_inode *));
free(base_ni->extent_nis); free(base_ni->extent_nis);
@ -695,8 +651,7 @@ int ntfs_inode_attach_all_extents( ntfs_inode *ni )
ATTR_LIST_ENTRY *ale; ATTR_LIST_ENTRY *ale;
u64 prev_attached = 0; u64 prev_attached = 0;
if ( !ni ) if (!ni) {
{
ntfs_log_trace("Invalid arguments.\n"); ntfs_log_trace("Invalid arguments.\n");
errno = EINVAL; errno = EINVAL;
return -1; return -1;
@ -711,8 +666,7 @@ int ntfs_inode_attach_all_extents( ntfs_inode *ni )
if (!NInoAttrList(ni)) if (!NInoAttrList(ni))
return 0; return 0;
if ( !ni->attr_list ) if (!ni->attr_list) {
{
ntfs_log_trace("Corrupt in-memory struct.\n"); ntfs_log_trace("Corrupt in-memory struct.\n");
errno = EINVAL; errno = EINVAL;
return -1; return -1;
@ -721,13 +675,10 @@ int ntfs_inode_attach_all_extents( ntfs_inode *ni )
/* Walk through attribute list and attach all extents. */ /* Walk through attribute list and attach all extents. */
errno = 0; errno = 0;
ale = (ATTR_LIST_ENTRY *)ni->attr_list; ale = (ATTR_LIST_ENTRY *)ni->attr_list;
while ( ( u8* )ale < ni->attr_list + ni->attr_list_size ) while ((u8*)ale < ni->attr_list + ni->attr_list_size) {
{
if (ni->mft_no != MREF_LE(ale->mft_reference) && if (ni->mft_no != MREF_LE(ale->mft_reference) &&
prev_attached != MREF_LE( ale->mft_reference ) ) prev_attached != MREF_LE(ale->mft_reference)) {
{ if (!ntfs_extent_inode_open(ni, ale->mft_reference)) {
if ( !ntfs_extent_inode_open( ni, ale->mft_reference ) )
{
ntfs_log_trace("Couldn't attach extent inode.\n"); ntfs_log_trace("Couldn't attach extent inode.\n");
return -1; return -1;
} }
@ -757,8 +708,7 @@ static int ntfs_inode_sync_standard_information( ntfs_inode *ni )
if (!ctx) if (!ctx)
return -1; return -1;
if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED,
0, CASE_SENSITIVE, 0, NULL, 0, ctx ) ) 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) {
{
ntfs_log_perror("Failed to sync standard info (inode %lld)", ntfs_log_perror("Failed to sync standard info (inode %lld)",
(long long)ni->mft_no); (long long)ni->mft_no);
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
@ -767,8 +717,7 @@ static int ntfs_inode_sync_standard_information( ntfs_inode *ni )
std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr + std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr +
le16_to_cpu(ctx->attr->value_offset)); le16_to_cpu(ctx->attr->value_offset));
std_info->file_attributes = ni->flags; std_info->file_attributes = ni->flags;
if ( !test_nino_flag( ni, TimesSet ) ) if (!test_nino_flag(ni, TimesSet)) {
{
std_info->creation_time = ni->creation_time; std_info->creation_time = ni->creation_time;
std_info->last_data_change_time = ni->last_data_change_time; std_info->last_data_change_time = ni->last_data_change_time;
std_info->last_mft_change_time = ni->last_mft_change_time; std_info->last_mft_change_time = ni->last_mft_change_time;
@ -783,8 +732,7 @@ static int ntfs_inode_sync_standard_information( ntfs_inode *ni )
&& (lth <= sizeof(STANDARD_INFORMATION))) && (lth <= sizeof(STANDARD_INFORMATION)))
ntfs_log_error("bad sync of standard information\n"); ntfs_log_error("bad sync of standard information\n");
if ( lth > sizeof( STANDARD_INFORMATION ) ) if (lth > sizeof(STANDARD_INFORMATION)) {
{
std_info->owner_id = ni->owner_id; std_info->owner_id = ni->owner_id;
std_info->security_id = ni->security_id; std_info->security_id = ni->security_id;
std_info->quota_charged = ni->quota_charged; std_info->quota_charged = ni->quota_charged;
@ -817,18 +765,15 @@ static int ntfs_inode_sync_file_name( ntfs_inode *ni, ntfs_inode *dir_ni )
ntfs_log_trace("Entering for inode %lld\n", (long long)ni->mft_no); ntfs_log_trace("Entering for inode %lld\n", (long long)ni->mft_no);
ctx = ntfs_attr_get_search_ctx(ni, NULL); ctx = ntfs_attr_get_search_ctx(ni, NULL);
if ( !ctx ) if (!ctx) {
{
err = errno; err = errno;
goto err_out; goto err_out;
} }
/* Collect the reparse tag, if any */ /* Collect the reparse tag, if any */
reparse_tag = cpu_to_le32(0); reparse_tag = cpu_to_le32(0);
if ( ni->flags & FILE_ATTR_REPARSE_POINT ) if (ni->flags & FILE_ATTR_REPARSE_POINT) {
{
if (!ntfs_attr_lookup(AT_REPARSE_POINT, NULL, if (!ntfs_attr_lookup(AT_REPARSE_POINT, NULL,
0, CASE_SENSITIVE, 0, NULL, 0, ctx ) ) 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) {
{
rpp = (REPARSE_POINT*)((u8 *)ctx->attr + rpp = (REPARSE_POINT*)((u8 *)ctx->attr +
le16_to_cpu(ctx->attr->value_offset)); le16_to_cpu(ctx->attr->value_offset));
reparse_tag = rpp->reparse_tag; reparse_tag = rpp->reparse_tag;
@ -836,12 +781,10 @@ static int ntfs_inode_sync_file_name( ntfs_inode *ni, ntfs_inode *dir_ni )
ntfs_attr_reinit_search_ctx(ctx); ntfs_attr_reinit_search_ctx(ctx);
} }
/* Walk through all FILE_NAME attributes and update them. */ /* Walk through all FILE_NAME attributes and update them. */
while ( !ntfs_attr_lookup( AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0, ctx ) ) while (!ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0, ctx)) {
{
fn = (FILE_NAME_ATTR *)((u8 *)ctx->attr + fn = (FILE_NAME_ATTR *)((u8 *)ctx->attr +
le16_to_cpu(ctx->attr->value_offset)); le16_to_cpu(ctx->attr->value_offset));
if ( MREF_LE( fn->parent_directory ) == ni->mft_no ) if (MREF_LE(fn->parent_directory) == ni->mft_no) {
{
/* /*
* WARNING: We cheat here and obtain 2 attribute * WARNING: We cheat here and obtain 2 attribute
* search contexts for one inode (first we obtained * search contexts for one inode (first we obtained
@ -850,14 +793,13 @@ static int ntfs_inode_sync_file_name( ntfs_inode *ni, ntfs_inode *dir_ni )
* but will deadlock in the kernel. * but will deadlock in the kernel.
*/ */
index_ni = ni; index_ni = ni;
} } else
else if ( dir_ni ) if (dir_ni)
index_ni = dir_ni; index_ni = dir_ni;
else else
index_ni = ntfs_inode_open(ni->vol, index_ni = ntfs_inode_open(ni->vol,
le64_to_cpu(fn->parent_directory)); le64_to_cpu(fn->parent_directory));
if ( !index_ni ) if (!index_ni) {
{
if (!err) if (!err)
err = errno; err = errno;
ntfs_log_perror("Failed to open inode %lld with index", ntfs_log_perror("Failed to open inode %lld with index",
@ -865,8 +807,7 @@ static int ntfs_inode_sync_file_name( ntfs_inode *ni, ntfs_inode *dir_ni )
continue; continue;
} }
ictx = ntfs_index_ctx_get(index_ni, NTFS_INDEX_I30, 4); ictx = ntfs_index_ctx_get(index_ni, NTFS_INDEX_I30, 4);
if ( !ictx ) if (!ictx) {
{
if (!err) if (!err)
err = errno; err = errno;
ntfs_log_perror("Failed to get index ctx, inode %lld", ntfs_log_perror("Failed to get index ctx, inode %lld",
@ -876,10 +817,8 @@ static int ntfs_inode_sync_file_name( ntfs_inode *ni, ntfs_inode *dir_ni )
err = errno; err = errno;
continue; continue;
} }
if ( ntfs_index_lookup( fn, sizeof( FILE_NAME_ATTR ), ictx ) ) if (ntfs_index_lookup(fn, sizeof(FILE_NAME_ATTR), ictx)) {
{ if (!err) {
if ( !err )
{
if (errno == ENOENT) if (errno == ENOENT)
err = EIO; err = EIO;
else else
@ -900,22 +839,18 @@ static int ntfs_inode_sync_file_name( ntfs_inode *ni, ntfs_inode *dir_ni )
if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
fnx->data_size = fnx->allocated_size fnx->data_size = fnx->allocated_size
= const_cpu_to_le64(0); = const_cpu_to_le64(0);
else else {
{
fnx->allocated_size = cpu_to_sle64(ni->allocated_size); fnx->allocated_size = cpu_to_sle64(ni->allocated_size);
fnx->data_size = cpu_to_sle64(ni->data_size); fnx->data_size = cpu_to_sle64(ni->data_size);
} }
/* update or clear the reparse tag in the index */ /* update or clear the reparse tag in the index */
fnx->reparse_point_tag = reparse_tag; fnx->reparse_point_tag = reparse_tag;
if ( !test_nino_flag( ni, TimesSet ) ) if (!test_nino_flag(ni, TimesSet)) {
{
fnx->creation_time = ni->creation_time; fnx->creation_time = ni->creation_time;
fnx->last_data_change_time = ni->last_data_change_time; fnx->last_data_change_time = ni->last_data_change_time;
fnx->last_mft_change_time = ni->last_mft_change_time; fnx->last_mft_change_time = ni->last_mft_change_time;
fnx->last_access_time = ni->last_access_time; fnx->last_access_time = ni->last_access_time;
} } else {
else
{
fnx->creation_time = fn->creation_time; fnx->creation_time = fn->creation_time;
fnx->last_data_change_time = fn->last_data_change_time; fnx->last_data_change_time = fn->last_data_change_time;
fnx->last_mft_change_time = fn->last_mft_change_time; fnx->last_mft_change_time = fn->last_mft_change_time;
@ -928,16 +863,14 @@ static int ntfs_inode_sync_file_name( ntfs_inode *ni, ntfs_inode *dir_ni )
err = errno; err = errno;
} }
/* Check for real error occurred. */ /* Check for real error occurred. */
if ( errno != ENOENT ) if (errno != ENOENT) {
{
err = errno; err = errno;
ntfs_log_perror("Attribute lookup failed, inode %lld", ntfs_log_perror("Attribute lookup failed, inode %lld",
(long long)ni->mft_no); (long long)ni->mft_no);
goto err_out; goto err_out;
} }
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
if ( err ) if (err) {
{
errno = err; errno = err;
return -1; return -1;
} }
@ -972,8 +905,7 @@ static int ntfs_inode_sync_in_dir( ntfs_inode *ni, ntfs_inode *dir_ni )
{ {
int ret = 0; int ret = 0;
int err = 0; int err = 0;
if ( !ni ) if (!ni) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_error("Failed to sync NULL inode\n"); ntfs_log_error("Failed to sync NULL inode\n");
return -1; return -1;
@ -983,10 +915,8 @@ static int ntfs_inode_sync_in_dir( ntfs_inode *ni, ntfs_inode *dir_ni )
/* Update STANDARD_INFORMATION. */ /* Update STANDARD_INFORMATION. */
if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 && if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 &&
ntfs_inode_sync_standard_information( ni ) ) ntfs_inode_sync_standard_information(ni)) {
{ if (!err || errno == EIO) {
if ( !err || errno == EIO )
{
err = errno; err = errno;
if (err != EIO) if (err != EIO)
err = EBUSY; err = EBUSY;
@ -996,10 +926,8 @@ static int ntfs_inode_sync_in_dir( ntfs_inode *ni, ntfs_inode *dir_ni )
/* Update FILE_NAME's in the index. */ /* Update FILE_NAME's in the index. */
if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 && if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 &&
NInoFileNameTestAndClearDirty(ni) && NInoFileNameTestAndClearDirty(ni) &&
ntfs_inode_sync_file_name( ni, dir_ni ) ) ntfs_inode_sync_file_name(ni, dir_ni)) {
{ if (!err || errno == EIO) {
if ( !err || errno == EIO )
{
err = errno; err = errno;
if (err != EIO) if (err != EIO)
err = EBUSY; err = EBUSY;
@ -1011,15 +939,12 @@ static int ntfs_inode_sync_in_dir( ntfs_inode *ni, ntfs_inode *dir_ni )
/* Write out attribute list from cache to disk. */ /* Write out attribute list from cache to disk. */
if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 && if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 &&
NInoAttrList( ni ) && NInoAttrListTestAndClearDirty( ni ) ) NInoAttrList(ni) && NInoAttrListTestAndClearDirty(ni)) {
{
ntfs_attr *na; ntfs_attr *na;
na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);
if ( !na ) if (!na) {
{ if (!err || errno == EIO) {
if ( !err || errno == EIO )
{
err = errno; err = errno;
if (err != EIO) if (err != EIO)
err = EBUSY; err = EBUSY;
@ -1031,13 +956,10 @@ static int ntfs_inode_sync_in_dir( ntfs_inode *ni, ntfs_inode *dir_ni )
goto sync_inode; goto sync_inode;
} }
if ( na->data_size == ni->attr_list_size ) if (na->data_size == ni->attr_list_size) {
{
if (ntfs_attr_pwrite(na, 0, ni->attr_list_size, if (ntfs_attr_pwrite(na, 0, ni->attr_list_size,
ni->attr_list ) != ni->attr_list_size ) ni->attr_list) != ni->attr_list_size) {
{ if (!err || errno == EIO) {
if ( !err || errno == EIO )
{
err = errno; err = errno;
if (err != EIO) if (err != EIO)
err = EBUSY; err = EBUSY;
@ -1047,9 +969,7 @@ static int ntfs_inode_sync_in_dir( ntfs_inode *ni, ntfs_inode *dir_ni )
} }
NInoAttrListSetDirty(ni); NInoAttrListSetDirty(ni);
} }
} } else {
else
{
err = EIO; err = EIO;
ntfs_log_error("Attribute list sync failed (bad size, " ntfs_log_error("Attribute list sync failed (bad size, "
"inode %lld)\n", (long long)ni->mft_no); "inode %lld)\n", (long long)ni->mft_no);
@ -1060,12 +980,9 @@ static int ntfs_inode_sync_in_dir( ntfs_inode *ni, ntfs_inode *dir_ni )
sync_inode: sync_inode:
/* Write this inode out to the $MFT (and $MFTMirr if applicable). */ /* Write this inode out to the $MFT (and $MFTMirr if applicable). */
if ( NInoTestAndClearDirty( ni ) ) if (NInoTestAndClearDirty(ni)) {
{ if (ntfs_mft_record_write(ni->vol, ni->mft_no, ni->mrec)) {
if ( ntfs_mft_record_write( ni->vol, ni->mft_no, ni->mrec ) ) if (!err || errno == EIO) {
{
if ( !err || errno == EIO )
{
err = errno; err = errno;
if (err != EIO) if (err != EIO)
err = EBUSY; err = EBUSY;
@ -1077,12 +994,10 @@ sync_inode:
} }
/* If this is a base inode with extents write all dirty extents, too. */ /* If this is a base inode with extents write all dirty extents, too. */
if ( ni->nr_extents > 0 ) if (ni->nr_extents > 0) {
{
s32 i; s32 i;
for ( i = 0; i < ni->nr_extents; ++i ) for (i = 0; i < ni->nr_extents; ++i) {
{
ntfs_inode *eni; ntfs_inode *eni;
eni = ni->extent_nis[i]; eni = ni->extent_nis[i];
@ -1090,10 +1005,8 @@ sync_inode:
continue; continue;
if (ntfs_mft_record_write(eni->vol, eni->mft_no, if (ntfs_mft_record_write(eni->vol, eni->mft_no,
eni->mrec ) ) eni->mrec)) {
{ if (!err || errno == EIO) {
if ( !err || errno == EIO )
{
err = errno; err = errno;
if (err != EIO) if (err != EIO)
err = EBUSY; err = EBUSY;
@ -1107,8 +1020,7 @@ sync_inode:
} }
} }
if ( err ) if (err) {
{
errno = err; errno = err;
ret = -1; ret = -1;
} }
@ -1131,12 +1043,10 @@ int ntfs_inode_close_in_dir( ntfs_inode *ni, ntfs_inode *dir_ni )
int res; int res;
res = ntfs_inode_sync_in_dir(ni, dir_ni); res = ntfs_inode_sync_in_dir(ni, dir_ni);
if ( res ) if (res) {
{
if (errno != EIO) if (errno != EIO)
errno = EBUSY; errno = EBUSY;
} } else
else
res = ntfs_inode_close(ni); res = ntfs_inode_close(ni);
return (res); return (res);
} }
@ -1161,8 +1071,7 @@ int ntfs_inode_add_attrlist( ntfs_inode *ni )
ATTR_LIST_ENTRY *ale = NULL; ATTR_LIST_ENTRY *ale = NULL;
ntfs_attr *na; ntfs_attr *na;
if ( !ni ) if (!ni) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s", __FUNCTION__); ntfs_log_perror("%s", __FUNCTION__);
return -1; return -1;
@ -1170,8 +1079,7 @@ int ntfs_inode_add_attrlist( ntfs_inode *ni )
ntfs_log_trace("inode %llu\n", (unsigned long long) ni->mft_no); ntfs_log_trace("inode %llu\n", (unsigned long long) ni->mft_no);
if ( NInoAttrList( ni ) || ni->nr_extents ) if (NInoAttrList(ni) || ni->nr_extents) {
{
errno = EEXIST; errno = EEXIST;
ntfs_log_perror("Inode already has attribute list"); ntfs_log_perror("Inode already has attribute list");
return -1; return -1;
@ -1179,19 +1087,16 @@ int ntfs_inode_add_attrlist( ntfs_inode *ni )
/* Form attribute list. */ /* Form attribute list. */
ctx = ntfs_attr_get_search_ctx(ni, NULL); ctx = ntfs_attr_get_search_ctx(ni, NULL);
if ( !ctx ) if (!ctx) {
{
err = errno; err = errno;
goto err_out; goto err_out;
} }
/* Walk through all attributes. */ /* Walk through all attributes. */
while ( !ntfs_attr_lookup( AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx ) ) while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) {
{
int ale_size; int ale_size;
if ( ctx->attr->type == AT_ATTRIBUTE_LIST ) if (ctx->attr->type == AT_ATTRIBUTE_LIST) {
{
err = EIO; err = EIO;
ntfs_log_perror("Attribute list already present"); ntfs_log_perror("Attribute list already present");
goto put_err_out; goto put_err_out;
@ -1202,8 +1107,7 @@ int ntfs_inode_add_attrlist( ntfs_inode *ni )
al_len += ale_size; al_len += ale_size;
aln = realloc(al, al_len); aln = realloc(al, al_len);
if ( !aln ) if (!aln) {
{
err = errno; err = errno;
ntfs_log_perror("Failed to realloc %d bytes", al_len); ntfs_log_perror("Failed to realloc %d bytes", al_len);
goto put_err_out; goto put_err_out;
@ -1232,8 +1136,7 @@ int ntfs_inode_add_attrlist( ntfs_inode *ni )
ale = (ATTR_LIST_ENTRY *)(al + al_len); ale = (ATTR_LIST_ENTRY *)(al + al_len);
} }
/* Check for real error occurred. */ /* Check for real error occurred. */
if ( errno != ENOENT ) if (errno != ENOENT) {
{
err = errno; err = errno;
ntfs_log_perror("%s: Attribute lookup failed, inode %lld", ntfs_log_perror("%s: Attribute lookup failed, inode %lld",
__FUNCTION__, (long long)ni->mft_no); __FUNCTION__, (long long)ni->mft_no);
@ -1249,11 +1152,9 @@ int ntfs_inode_add_attrlist( ntfs_inode *ni )
/* Free space if there is not enough it for $ATTRIBUTE_LIST. */ /* Free space if there is not enough it for $ATTRIBUTE_LIST. */
if (le32_to_cpu(ni->mrec->bytes_allocated) - if (le32_to_cpu(ni->mrec->bytes_allocated) -
le32_to_cpu(ni->mrec->bytes_in_use) < le32_to_cpu(ni->mrec->bytes_in_use) <
offsetof( ATTR_RECORD, resident_end ) ) offsetof(ATTR_RECORD, resident_end)) {
{
if (ntfs_inode_free_space(ni, if (ntfs_inode_free_space(ni,
offsetof( ATTR_RECORD, resident_end ) ) ) offsetof(ATTR_RECORD, resident_end))) {
{
/* Failed to free space. */ /* Failed to free space. */
err = errno; err = errno;
ntfs_log_perror("Failed to free space for attrlist"); ntfs_log_perror("Failed to free space for attrlist");
@ -1263,8 +1164,7 @@ int ntfs_inode_add_attrlist( ntfs_inode *ni )
/* Add $ATTRIBUTE_LIST to mft record. */ /* Add $ATTRIBUTE_LIST to mft record. */
if (ntfs_resident_attr_record_add(ni, if (ntfs_resident_attr_record_add(ni,
AT_ATTRIBUTE_LIST, NULL, 0, NULL, 0, 0 ) < 0 ) AT_ATTRIBUTE_LIST, NULL, 0, NULL, 0, 0) < 0) {
{
err = errno; err = errno;
ntfs_log_perror("Couldn't add $ATTRIBUTE_LIST to MFT"); ntfs_log_perror("Couldn't add $ATTRIBUTE_LIST to MFT");
goto rollback; goto rollback;
@ -1272,14 +1172,12 @@ int ntfs_inode_add_attrlist( ntfs_inode *ni )
/* Resize it. */ /* Resize it. */
na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);
if ( !na ) if (!na) {
{
err = errno; err = errno;
ntfs_log_perror("Failed to open just added $ATTRIBUTE_LIST"); ntfs_log_perror("Failed to open just added $ATTRIBUTE_LIST");
goto remove_attrlist_record; goto remove_attrlist_record;
} }
if ( ntfs_attr_truncate( na, al_len ) ) if (ntfs_attr_truncate(na, al_len)) {
{
err = errno; err = errno;
ntfs_log_perror("Failed to resize just added $ATTRIBUTE_LIST"); ntfs_log_perror("Failed to resize just added $ATTRIBUTE_LIST");
ntfs_attr_close(na); ntfs_attr_close(na);
@ -1297,12 +1195,10 @@ remove_attrlist_record:
/* Remove $ATTRIBUTE_LIST record. */ /* Remove $ATTRIBUTE_LIST record. */
ntfs_attr_reinit_search_ctx(ctx); ntfs_attr_reinit_search_ctx(ctx);
if (!ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, if (!ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0,
CASE_SENSITIVE, 0, NULL, 0, ctx ) ) CASE_SENSITIVE, 0, NULL, 0, ctx)) {
{
if (ntfs_attr_record_rm(ctx)) if (ntfs_attr_record_rm(ctx))
ntfs_log_perror("Rollback failed to remove attrlist"); ntfs_log_perror("Rollback failed to remove attrlist");
} } else
else
ntfs_log_perror("Rollback failed to find attrlist"); ntfs_log_perror("Rollback failed to find attrlist");
/* Setup back in-memory runlist. */ /* Setup back in-memory runlist. */
ni->attr_list = al; ni->attr_list = al;
@ -1315,21 +1211,17 @@ rollback:
*/ */
ntfs_attr_reinit_search_ctx(ctx); ntfs_attr_reinit_search_ctx(ctx);
ale = (ATTR_LIST_ENTRY*)al; ale = (ATTR_LIST_ENTRY*)al;
while ( ( u8* )ale < al + al_len ) while ((u8*)ale < al + al_len) {
{ if (MREF_LE(ale->mft_reference) != ni->mft_no) {
if ( MREF_LE( ale->mft_reference ) != ni->mft_no )
{
if (!ntfs_attr_lookup(ale->type, ale->name, if (!ntfs_attr_lookup(ale->type, ale->name,
ale->name_length, ale->name_length,
CASE_SENSITIVE, CASE_SENSITIVE,
sle64_to_cpu(ale->lowest_vcn), sle64_to_cpu(ale->lowest_vcn),
NULL, 0, ctx ) ) NULL, 0, ctx)) {
{
if (ntfs_attr_record_move_to(ctx, ni)) if (ntfs_attr_record_move_to(ctx, ni))
ntfs_log_perror("Rollback failed to " ntfs_log_perror("Rollback failed to "
"move attribute"); "move attribute");
} } else
else
ntfs_log_perror("Rollback failed to find attr"); ntfs_log_perror("Rollback failed to find attr");
ntfs_attr_reinit_search_ctx(ctx); ntfs_attr_reinit_search_ctx(ctx);
} }
@ -1360,8 +1252,7 @@ int ntfs_inode_free_space( ntfs_inode *ni, int size )
ntfs_attr_search_ctx *ctx; ntfs_attr_search_ctx *ctx;
int freed; int freed;
if ( !ni || size < 0 ) if (!ni || size < 0) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s: ni=%p size=%d", __FUNCTION__, ni, size); ntfs_log_perror("%s: ni=%p size=%d", __FUNCTION__, ni, size);
return -1; return -1;
@ -1386,15 +1277,13 @@ int ntfs_inode_free_space( ntfs_inode *ni, int size )
if (ntfs_attr_position(AT_FILE_NAME, ctx)) if (ntfs_attr_position(AT_FILE_NAME, ctx))
goto put_err_out; goto put_err_out;
while ( 1 ) while (1) {
{
int record_size; int record_size;
/* /*
* Check whether attribute is from different MFT record. If so, * Check whether attribute is from different MFT record. If so,
* find next, because we don't need such. * find next, because we don't need such.
*/ */
while ( ctx->ntfs_ino->mft_no != ni->mft_no ) while (ctx->ntfs_ino->mft_no != ni->mft_no) {
{
retry: retry:
if (ntfs_attr_position(AT_UNUSED, ctx)) if (ntfs_attr_position(AT_UNUSED, ctx))
goto put_err_out; goto put_err_out;
@ -1409,16 +1298,14 @@ retry:
record_size = le32_to_cpu(ctx->attr->length); record_size = le32_to_cpu(ctx->attr->length);
if ( ntfs_attr_record_move_away( ctx, 0 ) ) if (ntfs_attr_record_move_away(ctx, 0)) {
{
ntfs_log_perror("Failed to move out attribute #2"); ntfs_log_perror("Failed to move out attribute #2");
break; break;
} }
freed += record_size; freed += record_size;
/* Check whether we are done. */ /* Check whether we are done. */
if ( size <= freed ) if (size <= freed) {
{
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
return 0; return 0;
} }
@ -1452,8 +1339,7 @@ void ntfs_inode_update_times( ntfs_inode *ni, ntfs_time_update_flags mask )
{ {
ntfs_time now; ntfs_time now;
if ( !ni ) if (!ni) {
{
ntfs_log_error("%s(): Invalid arguments.\n", __FUNCTION__); ntfs_log_error("%s(): Invalid arguments.\n", __FUNCTION__);
return; return;
} }
@ -1491,8 +1377,7 @@ int ntfs_inode_badclus_bad( u64 mft_no, ATTR_RECORD *attr )
int len, ret = 0; int len, ret = 0;
ntfschar *ustr; ntfschar *ustr;
if ( !attr ) if (!attr) {
{
ntfs_log_error("Invalid argument.\n"); ntfs_log_error("Invalid argument.\n");
errno = EINVAL; errno = EINVAL;
return -1; return -1;
@ -1504,8 +1389,7 @@ int ntfs_inode_badclus_bad( u64 mft_no, ATTR_RECORD *attr )
if (attr->type != AT_DATA) if (attr->type != AT_DATA)
return 0; return 0;
if ( ( ustr = ntfs_str2ucs( "$Bad", &len ) ) == NULL ) if ((ustr = ntfs_str2ucs("$Bad", &len)) == NULL) {
{
ntfs_log_perror("Couldn't convert '$Bad' to Unicode"); ntfs_log_perror("Couldn't convert '$Bad' to Unicode");
return -1; return -1;
} }
@ -1541,40 +1425,32 @@ int ntfs_inode_get_times( ntfs_inode *ni, char *value, size_t size )
ret = 0; ret = 0;
ctx = ntfs_attr_get_search_ctx(ni, NULL); ctx = ntfs_attr_get_search_ctx(ni, NULL);
if ( ctx ) if (ctx) {
{
if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED,
0, CASE_SENSITIVE, 0, NULL, 0, ctx ) ) 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) {
{
ntfs_log_perror("Failed to get standard info (inode %lld)", ntfs_log_perror("Failed to get standard info (inode %lld)",
(long long)ni->mft_no); (long long)ni->mft_no);
} } else {
else
{
std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr + std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr +
le16_to_cpu(ctx->attr->value_offset)); le16_to_cpu(ctx->attr->value_offset));
if ( value && ( size >= 8 ) ) if (value && (size >= 8)) {
{
times = (u64*)value; times = (u64*)value;
times[0] = le64_to_cpu(std_info->creation_time); times[0] = le64_to_cpu(std_info->creation_time);
ret = 8; ret = 8;
if ( size >= 16 ) if (size >= 16) {
{
times[1] = le64_to_cpu(std_info->last_data_change_time); times[1] = le64_to_cpu(std_info->last_data_change_time);
ret = 16; ret = 16;
} }
if ( size >= 24 ) if (size >= 24) {
{
times[2] = le64_to_cpu(std_info->last_access_time); times[2] = le64_to_cpu(std_info->last_access_time);
ret = 24; ret = 24;
} }
if ( size >= 32 ) if (size >= 32) {
{
times[3] = le64_to_cpu(std_info->last_mft_change_time); times[3] = le64_to_cpu(std_info->last_mft_change_time);
ret = 32; ret = 32;
} }
} } else
else if ( !size ) if (!size)
ret = 32; ret = 32;
else else
ret = -ERANGE; ret = -ERANGE;
@ -1610,23 +1486,18 @@ int ntfs_inode_set_times( ntfs_inode *ni, const char *value, size_t size,
int ret; int ret;
ret = -1; ret = -1;
if ( ( size >= 8 ) && !( flags & XATTR_CREATE ) ) if ((size >= 8) && !(flags & XATTR_CREATE)) {
{
times = (const u64*)value; times = (const u64*)value;
now = ntfs_current_time(); now = ntfs_current_time();
/* update the standard information attribute */ /* update the standard information attribute */
ctx = ntfs_attr_get_search_ctx(ni, NULL); ctx = ntfs_attr_get_search_ctx(ni, NULL);
if ( ctx ) if (ctx) {
{
if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, if (ntfs_attr_lookup(AT_STANDARD_INFORMATION,
AT_UNNAMED, 0, CASE_SENSITIVE, AT_UNNAMED, 0, CASE_SENSITIVE,
0, NULL, 0, ctx ) ) 0, NULL, 0, ctx)) {
{
ntfs_log_perror("Failed to get standard info (inode %lld)", ntfs_log_perror("Failed to get standard info (inode %lld)",
(long long)ni->mft_no); (long long)ni->mft_no);
} } else {
else
{
std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr + std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr +
le16_to_cpu(ctx->attr->value_offset)); le16_to_cpu(ctx->attr->value_offset));
/* /*
@ -1641,14 +1512,12 @@ int ntfs_inode_set_times( ntfs_inode *ni, const char *value, size_t size,
std_info->creation_time = cpu_to_le64(times[0]); std_info->creation_time = cpu_to_le64(times[0]);
ni->creation_time ni->creation_time
= std_info->creation_time; = std_info->creation_time;
if ( size >= 16 ) if (size >= 16) {
{
std_info->last_data_change_time = cpu_to_le64(times[1]); std_info->last_data_change_time = cpu_to_le64(times[1]);
ni->last_data_change_time ni->last_data_change_time
= std_info->last_data_change_time; = std_info->last_data_change_time;
} }
if ( size >= 24 ) if (size >= 24) {
{
std_info->last_access_time = cpu_to_le64(times[2]); std_info->last_access_time = cpu_to_le64(times[2]);
ni->last_access_time ni->last_access_time
= std_info->last_access_time; = std_info->last_access_time;
@ -1663,8 +1532,7 @@ int ntfs_inode_set_times( ntfs_inode *ni, const char *value, size_t size,
cnt = 0; cnt = 0;
while (!ntfs_attr_lookup(AT_FILE_NAME, while (!ntfs_attr_lookup(AT_FILE_NAME,
AT_UNNAMED, 0, CASE_SENSITIVE, AT_UNNAMED, 0, CASE_SENSITIVE,
0, NULL, 0, ctx ) ) 0, NULL, 0, ctx)) {
{
fn = (FILE_NAME_ATTR*)((u8 *)ctx->attr + fn = (FILE_NAME_ATTR*)((u8 *)ctx->attr +
le16_to_cpu(ctx->attr->value_offset)); le16_to_cpu(ctx->attr->value_offset));
fn->creation_time fn->creation_time
@ -1680,16 +1548,15 @@ int ntfs_inode_set_times( ntfs_inode *ni, const char *value, size_t size,
} }
if (cnt) if (cnt)
ret = 0; ret = 0;
else else {
{
ntfs_log_perror("Failed to get file names (inode %lld)", ntfs_log_perror("Failed to get file names (inode %lld)",
(long long)ni->mft_no); (long long)ni->mft_no);
} }
} }
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
} }
} } else
else if ( size < 8 ) if (size < 8)
errno = ERANGE; errno = ERANGE;
else else
errno = EEXIST; errno = EEXIST;

View File

@ -40,8 +40,7 @@ typedef struct _ntfs_inode ntfs_inode;
* Defined bits for the state field in the ntfs_inode structure. * Defined bits for the state field in the ntfs_inode structure.
* (f) = files only, (d) = directories only * (f) = files only, (d) = directories only
*/ */
typedef enum typedef enum {
{
NI_Dirty, /* 1: Mft record needs to be written to disk. */ NI_Dirty, /* 1: Mft record needs to be written to disk. */
/* The NI_AttrList* tests only make sense for base inodes. */ /* The NI_AttrList* tests only make sense for base inodes. */
@ -104,8 +103,7 @@ typedef enum
* It is just used as an extension to the fields already provided in the VFS * It is just used as an extension to the fields already provided in the VFS
* inode. * inode.
*/ */
struct _ntfs_inode struct _ntfs_inode {
{
u64 mft_no; /* Inode / mft record number. */ u64 mft_no; /* Inode / mft record number. */
MFT_RECORD *mrec; /* The actual mft record of the inode. */ MFT_RECORD *mrec; /* The actual mft record of the inode. */
ntfs_volume *vol; /* Pointer to the ntfs volume of this inode. */ ntfs_volume *vol; /* Pointer to the ntfs volume of this inode. */
@ -124,8 +122,7 @@ struct _ntfs_inode
s32 nr_extents; /* For a base mft record, the number of s32 nr_extents; /* For a base mft record, the number of
attached extent inodes (0 if none), for attached extent inodes (0 if none), for
extent records this is -1. */ extent records this is -1. */
union /* This union is only used if nr_extents != 0. */ union { /* This union is only used if nr_extents != 0. */
{
ntfs_inode **extent_nis;/* For nr_extents > 0, array of the ntfs_inode **extent_nis;/* For nr_extents > 0, array of the
ntfs inodes of the extent mft ntfs inodes of the extent mft
records belonging to this base records belonging to this base
@ -169,8 +166,7 @@ struct _ntfs_inode
le64 usn; le64 usn;
}; };
typedef enum typedef enum {
{
NTFS_UPDATE_ATIME = 1 << 0, NTFS_UPDATE_ATIME = 1 << 0,
NTFS_UPDATE_MTIME = 1 << 1, NTFS_UPDATE_MTIME = 1 << 1,
NTFS_UPDATE_CTIME = 1 << 2, NTFS_UPDATE_CTIME = 1 << 2,

View File

@ -46,8 +46,7 @@
/** /**
* struct BIOS_PARAMETER_BLOCK - BIOS parameter block (bpb) structure. * struct BIOS_PARAMETER_BLOCK - BIOS parameter block (bpb) structure.
*/ */
typedef struct typedef struct {
{
u16 bytes_per_sector; /* Size of a sector in bytes. */ u16 bytes_per_sector; /* Size of a sector in bytes. */
u8 sectors_per_cluster; /* Size of a cluster in sectors. */ u8 sectors_per_cluster; /* Size of a cluster in sectors. */
u16 reserved_sectors; /* zero */ u16 reserved_sectors; /* zero */
@ -68,8 +67,7 @@ typedef struct
/** /**
* struct NTFS_BOOT_SECTOR - NTFS boot sector structure. * struct NTFS_BOOT_SECTOR - NTFS boot sector structure.
*/ */
typedef struct typedef struct {
{
u8 jump[3]; /* Irrelevant (jump to boot up code).*/ u8 jump[3]; /* Irrelevant (jump to boot up code).*/
u64 oem_id; /* Magic "NTFS ". */ u64 oem_id; /* Magic "NTFS ". */
/*0x0b*/BIOS_PARAMETER_BLOCK bpb; /* See BIOS_PARAMETER_BLOCK. */ /*0x0b*/BIOS_PARAMETER_BLOCK bpb; /* See BIOS_PARAMETER_BLOCK. */
@ -102,8 +100,7 @@ typedef struct
* Magic identifiers present at the beginning of all ntfs record containing * Magic identifiers present at the beginning of all ntfs record containing
* records (like mft records for example). * records (like mft records for example).
*/ */
typedef enum typedef enum {
{
/* Found in $MFT/$DATA. */ /* Found in $MFT/$DATA. */
magic_FILE = const_cpu_to_le32(0x454c4946), /* Mft entry. */ magic_FILE = const_cpu_to_le32(0x454c4946), /* Mft entry. */
magic_INDX = const_cpu_to_le32(0x58444e49), /* Index buffer. */ magic_INDX = const_cpu_to_le32(0x58444e49), /* Index buffer. */
@ -185,8 +182,7 @@ typedef enum
* This formula can be used as a consistency check in that usa_ofs + * This formula can be used as a consistency check in that usa_ofs +
* (usa_count * 2) has to be less than or equal to 510. * (usa_count * 2) has to be less than or equal to 510.
*/ */
typedef struct typedef struct {
{
NTFS_RECORD_TYPES magic;/* A four-byte magic identifying the NTFS_RECORD_TYPES magic;/* A four-byte magic identifying the
record type and/or status. */ record type and/or status. */
u16 usa_ofs; /* Offset to the Update Sequence Array (usa) u16 usa_ofs; /* Offset to the Update Sequence Array (usa)
@ -205,8 +201,7 @@ typedef struct
* mft records. Also, the sequence number for each of the system files is * mft records. Also, the sequence number for each of the system files is
* always equal to their mft record number and it is never modified. * always equal to their mft record number and it is never modified.
*/ */
typedef enum typedef enum {
{
FILE_MFT = 0, /* Master file table (mft). Data attribute FILE_MFT = 0, /* Master file table (mft). Data attribute
contains the entries and bitmap attribute contains the entries and bitmap attribute
records which ones are in use (bit==1). */ records which ones are in use (bit==1). */
@ -259,8 +254,7 @@ typedef enum
* index, that means an INDEX_ROOT and an INDEX_ALLOCATION with a name other * index, that means an INDEX_ROOT and an INDEX_ALLOCATION with a name other
* than "$I30". It is unknown if it is limited to metadata files only. * than "$I30". It is unknown if it is limited to metadata files only.
*/ */
typedef enum typedef enum {
{
MFT_RECORD_IN_USE = const_cpu_to_le16(0x0001), MFT_RECORD_IN_USE = const_cpu_to_le16(0x0001),
MFT_RECORD_IS_DIRECTORY = const_cpu_to_le16(0x0002), MFT_RECORD_IS_DIRECTORY = const_cpu_to_le16(0x0002),
MFT_RECORD_IS_4 = const_cpu_to_le16(0x0004), MFT_RECORD_IS_4 = const_cpu_to_le16(0x0004),
@ -341,8 +335,7 @@ typedef u64 MFT_REF;
* in that it only consists of the attribute type code AT_END and none of the * in that it only consists of the attribute type code AT_END and none of the
* other members of the attribute structure are present. * other members of the attribute structure are present.
*/ */
typedef struct typedef struct {
{
/*Ofs*/ /*Ofs*/
/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ /* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
NTFS_RECORD_TYPES magic;/* Usually the magic is "FILE". */ NTFS_RECORD_TYPES magic;/* Usually the magic is "FILE". */
@ -416,8 +409,7 @@ typedef struct
* *
* This is the version without the NTFS 3.1+ specific fields. * This is the version without the NTFS 3.1+ specific fields.
*/ */
typedef struct typedef struct {
{
/*Ofs*/ /*Ofs*/
/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ /* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
NTFS_RECORD_TYPES magic;/* Usually the magic is "FILE". */ NTFS_RECORD_TYPES magic;/* Usually the magic is "FILE". */
@ -494,8 +486,7 @@ typedef struct
* enum exchanging AT_ for the dollar sign ($). If that isn't a revealing * enum exchanging AT_ for the dollar sign ($). If that isn't a revealing
* choice of symbol... (-; * choice of symbol... (-;
*/ */
typedef enum typedef enum {
{
AT_UNUSED = const_cpu_to_le32( 0), AT_UNUSED = const_cpu_to_le32( 0),
AT_STANDARD_INFORMATION = const_cpu_to_le32( 0x10), AT_STANDARD_INFORMATION = const_cpu_to_le32( 0x10),
AT_ATTRIBUTE_LIST = const_cpu_to_le32( 0x20), AT_ATTRIBUTE_LIST = const_cpu_to_le32( 0x20),
@ -554,8 +545,7 @@ typedef enum
* the 2nd object_id. If the first u32 values of both object_ids were * the 2nd object_id. If the first u32 values of both object_ids were
* equal then the second u32 values would be compared, etc. * equal then the second u32 values would be compared, etc.
*/ */
typedef enum typedef enum {
{
COLLATION_BINARY = const_cpu_to_le32(0), /* Collate by binary COLLATION_BINARY = const_cpu_to_le32(0), /* Collate by binary
compare where the first byte is most compare where the first byte is most
significant. */ significant. */
@ -583,8 +573,7 @@ typedef enum
* name attribute has this flag set and this is the only attribute indexed in * name attribute has this flag set and this is the only attribute indexed in
* NT4. * NT4.
*/ */
typedef enum typedef enum {
{
ATTR_DEF_INDEXABLE = const_cpu_to_le32(0x02), /* Attribute can be ATTR_DEF_INDEXABLE = const_cpu_to_le32(0x02), /* Attribute can be
indexed. */ indexed. */
ATTR_DEF_MULTIPLE = const_cpu_to_le32(0x04), /* Attribute type ATTR_DEF_MULTIPLE = const_cpu_to_le32(0x04), /* Attribute type
@ -622,11 +611,9 @@ typedef enum
* attribute can be resident/non-resident and possibly other things, but the * attribute can be resident/non-resident and possibly other things, but the
* actual bits are unknown. * actual bits are unknown.
*/ */
typedef struct typedef struct {
{
/*hex ofs*/ /*hex ofs*/
/* 0*/ /* 0*/ ntfschar name[0x40]; /* Unicode name of the attribute. Zero
ntfschar name[0x40]; /* Unicode name of the attribute. Zero
terminated. */ terminated. */
/* 80*/ ATTR_TYPES type; /* Type of the attribute. */ /* 80*/ ATTR_TYPES type; /* Type of the attribute. */
/* 84*/ u32 display_rule; /* Default display rule. /* 84*/ u32 display_rule; /* Default display rule.
@ -641,8 +628,7 @@ typedef struct
/** /**
* enum ATTR_FLAGS - Attribute flags (16-bit). * enum ATTR_FLAGS - Attribute flags (16-bit).
*/ */
typedef enum typedef enum {
{
ATTR_IS_COMPRESSED = const_cpu_to_le16(0x0001), ATTR_IS_COMPRESSED = const_cpu_to_le16(0x0001),
ATTR_COMPRESSION_MASK = const_cpu_to_le16(0x00ff), /* Compression ATTR_COMPRESSION_MASK = const_cpu_to_le16(0x00ff), /* Compression
method mask. Also, first method mask. Also, first
@ -721,8 +707,7 @@ typedef enum
/** /**
* enum RESIDENT_ATTR_FLAGS - Flags of resident attributes (8-bit). * enum RESIDENT_ATTR_FLAGS - Flags of resident attributes (8-bit).
*/ */
typedef enum typedef enum {
{
RESIDENT_ATTR_IS_INDEXED = 0x01, /* Attribute is referenced in an index RESIDENT_ATTR_IS_INDEXED = 0x01, /* Attribute is referenced in an index
(has implications for deleting and (has implications for deleting and
modifying the attribute). */ modifying the attribute). */
@ -733,11 +718,9 @@ typedef enum
* *
* Always aligned to 8-byte boundary. * Always aligned to 8-byte boundary.
*/ */
typedef struct typedef struct {
{
/*Ofs*/ /*Ofs*/
/* 0*/ /* 0*/ ATTR_TYPES type; /* The (32-bit) type of the attribute. */
ATTR_TYPES type; /* The (32-bit) type of the attribute. */
/* 4*/ u32 length; /* Byte size of the resident part of the /* 4*/ u32 length; /* Byte size of the resident part of the
attribute (aligned to 8-byte boundary). attribute (aligned to 8-byte boundary).
Used to get to the next attribute. */ Used to get to the next attribute. */
@ -759,13 +742,10 @@ typedef struct
number is unique within this mft record (see number is unique within this mft record (see
MFT_RECORD/next_attribute_instance notes MFT_RECORD/next_attribute_instance notes
above for more details). */ above for more details). */
/* 16*/ union /* 16*/ union {
{
/* Resident attributes. */ /* Resident attributes. */
struct struct {
{ /* 16 */ u32 value_length; /* Byte size of attribute value. */
/* 16 */
u32 value_length; /* Byte size of attribute value. */
/* 20 */ u16 value_offset; /* Byte offset of the attribute /* 20 */ u16 value_offset; /* Byte offset of the attribute
value from the start of the value from the start of the
attribute record. When creating, attribute record. When creating,
@ -781,10 +761,8 @@ typedef struct
a resident attribute. */ a resident attribute. */
} __attribute__((__packed__)); } __attribute__((__packed__));
/* Non-resident attributes. */ /* Non-resident attributes. */
struct struct {
{ /* 16*/ VCN lowest_vcn; /* Lowest valid virtual cluster number
/* 16*/
VCN lowest_vcn; /* Lowest valid virtual cluster number
for this portion of the attribute value or for this portion of the attribute value or
0 if this is the only extent (usually the 0 if this is the only extent (usually the
case). - Only when an attribute list is used case). - Only when an attribute list is used
@ -847,8 +825,7 @@ typedef ATTR_RECORD ATTR_REC;
/** /**
* enum FILE_ATTR_FLAGS - File attribute flags (32-bit). * enum FILE_ATTR_FLAGS - File attribute flags (32-bit).
*/ */
typedef enum typedef enum {
{
/* /*
* These flags are only present in the STANDARD_INFORMATION attribute * These flags are only present in the STANDARD_INFORMATION attribute
* (in the field file_attributes). * (in the field file_attributes).
@ -928,11 +905,9 @@ typedef enum
* correct by practical experimentation on Windows NT4 SP6a and is hence * correct by practical experimentation on Windows NT4 SP6a and is hence
* assumed to be the one and only correct interpretation. * assumed to be the one and only correct interpretation.
*/ */
typedef struct typedef struct {
{
/*Ofs*/ /*Ofs*/
/* 0*/ /* 0*/ s64 creation_time; /* Time file was created. Updated when
s64 creation_time; /* Time file was created. Updated when
a filename is changed(?). */ a filename is changed(?). */
/* 8*/ s64 last_data_change_time; /* Time the data attribute was last /* 8*/ s64 last_data_change_time; /* Time the data attribute was last
modified. */ modified. */
@ -947,20 +922,16 @@ typedef struct
last access times updates can be last access times updates can be
disabled altogether for speed. */ disabled altogether for speed. */
/* 32*/ FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */ /* 32*/ FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */
/* 36*/ union /* 36*/ union {
{
/* NTFS 1.2 (and previous, presumably) */ /* NTFS 1.2 (and previous, presumably) */
struct struct {
{ /* 36 */ u8 reserved12[12]; /* Reserved/alignment to 8-byte
/* 36 */
u8 reserved12[12]; /* Reserved/alignment to 8-byte
boundary. */ boundary. */
/* 48 */ void *v1_end[0]; /* Marker for offsetof(). */ /* 48 */ void *v1_end[0]; /* Marker for offsetof(). */
} __attribute__((__packed__)); } __attribute__((__packed__));
/* sizeof() = 48 bytes */ /* sizeof() = 48 bytes */
/* NTFS 3.0 */ /* NTFS 3.0 */
struct struct {
{
/* /*
* If a volume has been upgraded from a previous NTFS version, then these * If a volume has been upgraded from a previous NTFS version, then these
* fields are present only if the file has been accessed since the upgrade. * fields are present only if the file has been accessed since the upgrade.
@ -980,8 +951,7 @@ typedef struct
* views that as a corruption, assuming that it behaves like this for all * views that as a corruption, assuming that it behaves like this for all
* attributes. * attributes.
*/ */
/* 36*/ /* 36*/ u32 maximum_versions; /* Maximum allowed versions for
u32 maximum_versions; /* Maximum allowed versions for
file. Zero if version numbering is disabled. */ file. Zero if version numbering is disabled. */
/* 40*/ u32 version_number; /* This file's version (if any). /* 40*/ u32 version_number; /* This file's version (if any).
Set to zero if maximum_versions is zero. */ Set to zero if maximum_versions is zero. */
@ -1046,11 +1016,9 @@ typedef struct
* NTFS 3.0 volumes). * NTFS 3.0 volumes).
* - There are many named streams. * - There are many named streams.
*/ */
typedef struct typedef struct {
{
/*Ofs*/ /*Ofs*/
/* 0*/ /* 0*/ ATTR_TYPES type; /* Type of referenced attribute. */
ATTR_TYPES type; /* Type of referenced attribute. */
/* 4*/ u16 length; /* Byte size of this entry. */ /* 4*/ u16 length; /* Byte size of this entry. */
/* 6*/ u8 name_length; /* Size in Unicode chars of the name of the /* 6*/ u8 name_length; /* Size in Unicode chars of the name of the
attribute or 0 if unnamed. */ attribute or 0 if unnamed. */
@ -1089,8 +1057,7 @@ typedef struct
* enum FILE_NAME_TYPE_FLAGS - Possible namespaces for filenames in ntfs. * enum FILE_NAME_TYPE_FLAGS - Possible namespaces for filenames in ntfs.
* (8-bit). * (8-bit).
*/ */
typedef enum typedef enum {
{
FILE_NAME_POSIX = 0x00, FILE_NAME_POSIX = 0x00,
/* This is the largest namespace. It is case sensitive and /* This is the largest namespace. It is case sensitive and
allows all Unicode characters except for: '\0' and '/'. allows all Unicode characters except for: '\0' and '/'.
@ -1126,11 +1093,9 @@ typedef enum
* correct by practical experimentation on Windows NT4 SP6a and is hence * correct by practical experimentation on Windows NT4 SP6a and is hence
* assumed to be the one and only correct interpretation. * assumed to be the one and only correct interpretation.
*/ */
typedef struct typedef struct {
{
/*hex ofs*/ /*hex ofs*/
/* 0*/ /* 0*/ MFT_REF parent_directory; /* Directory this filename is
MFT_REF parent_directory; /* Directory this filename is
referenced from. */ referenced from. */
/* 8*/ s64 creation_time; /* Time file was created. */ /* 8*/ s64 creation_time; /* Time file was created. */
/* 10*/ s64 last_data_change_time; /* Time the data attribute was last /* 10*/ s64 last_data_change_time; /* Time the data attribute was last
@ -1151,13 +1116,9 @@ typedef struct
/* 30*/ s64 data_size; /* Byte size of actual data in data /* 30*/ s64 data_size; /* Byte size of actual data in data
attribute. */ attribute. */
/* 38*/ FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */ /* 38*/ FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */
/* 3c*/ union /* 3c*/ union {
{ /* 3c*/ struct {
/* 3c*/ /* 3c*/ u16 packed_ea_size; /* Size of the buffer needed to
struct
{
/* 3c*/
u16 packed_ea_size; /* Size of the buffer needed to
pack the extended attributes pack the extended attributes
(EAs), if such are present.*/ (EAs), if such are present.*/
/* 3e*/ u16 reserved; /* Reserved for alignment. */ /* 3e*/ u16 reserved; /* Reserved for alignment. */
@ -1185,8 +1146,7 @@ typedef struct
* Example of a GUID: * Example of a GUID:
* 1F010768-5A73-BC91-0010-A52216A7227B * 1F010768-5A73-BC91-0010-A52216A7227B
*/ */
typedef struct typedef struct {
{
u32 data1; /* The first eight hexadecimal digits of the GUID. */ u32 data1; /* The first eight hexadecimal digits of the GUID. */
u16 data2; /* The first group of four hexadecimal digits. */ u16 data2; /* The first group of four hexadecimal digits. */
u16 data3; /* The second group of four hexadecimal digits. */ u16 data3; /* The second group of four hexadecimal digits. */
@ -1208,14 +1168,11 @@ typedef struct
* equals the object_id. Optional (i.e. can be zero). * equals the object_id. Optional (i.e. can be zero).
* domain_id - Reserved (always zero). * domain_id - Reserved (always zero).
*/ */
typedef struct typedef struct {
{
MFT_REF mft_reference; /* Mft record containing the object_id in MFT_REF mft_reference; /* Mft record containing the object_id in
the index entry key. */ the index entry key. */
union union {
{ struct {
struct
{
GUID birth_volume_id; GUID birth_volume_id;
GUID birth_object_id; GUID birth_object_id;
GUID domain_id; GUID domain_id;
@ -1229,8 +1186,7 @@ typedef struct
* *
* NOTE: Always resident. * NOTE: Always resident.
*/ */
typedef struct typedef struct {
{
GUID object_id; /* Unique id assigned to the GUID object_id; /* Unique id assigned to the
file.*/ file.*/
/* The following fields are optional. The attribute value size is 16 /* The following fields are optional. The attribute value size is 16
@ -1240,10 +1196,8 @@ typedef struct
when the fields are missing here, it is well possible that they are when the fields are missing here, it is well possible that they are
to be found within the $Extend/$ObjId system file indexed under the to be found within the $Extend/$ObjId system file indexed under the
above object_id. */ above object_id. */
union union {
{ struct {
struct
{
GUID birth_volume_id; /* Unique id of volume on which GUID birth_volume_id; /* Unique id of volume on which
the file was first created.*/ the file was first created.*/
GUID birth_object_id; /* Unique id of file when it was GUID birth_object_id; /* Unique id of file when it was
@ -1261,8 +1215,7 @@ typedef struct
* The pre-defined IDENTIFIER_AUTHORITIES used as SID_IDENTIFIER_AUTHORITY in * The pre-defined IDENTIFIER_AUTHORITIES used as SID_IDENTIFIER_AUTHORITY in
* the SID structure (see below). * the SID structure (see below).
*/ */
typedef enum /* SID string prefix. */ typedef enum { /* SID string prefix. */
{
SECURITY_NULL_SID_AUTHORITY = {0, 0, 0, 0, 0, 0}, /* S-1-0 */ SECURITY_NULL_SID_AUTHORITY = {0, 0, 0, 0, 0, 0}, /* S-1-0 */
SECURITY_WORLD_SID_AUTHORITY = {0, 0, 0, 0, 0, 1}, /* S-1-1 */ SECURITY_WORLD_SID_AUTHORITY = {0, 0, 0, 0, 0, 1}, /* S-1-1 */
SECURITY_LOCAL_SID_AUTHORITY = {0, 0, 0, 0, 0, 2}, /* S-1-2 */ SECURITY_LOCAL_SID_AUTHORITY = {0, 0, 0, 0, 0, 2}, /* S-1-2 */
@ -1284,8 +1237,7 @@ typedef enum /* SID string prefix. */
* made up of the identifier authority SECURITY_CREATOR_SID_AUTHORITY (3) and * made up of the identifier authority SECURITY_CREATOR_SID_AUTHORITY (3) and
* the relative identifier SECURITY_CREATOR_OWNER_RID (0). * the relative identifier SECURITY_CREATOR_OWNER_RID (0).
*/ */
typedef enum /* Identifier authority. */ typedef enum { /* Identifier authority. */
{
SECURITY_NULL_RID = 0, /* S-1-0 */ SECURITY_NULL_RID = 0, /* S-1-0 */
SECURITY_WORLD_RID = 0, /* S-1-1 */ SECURITY_WORLD_RID = 0, /* S-1-1 */
SECURITY_LOCAL_RID = 0, /* S-1-2 */ SECURITY_LOCAL_RID = 0, /* S-1-2 */
@ -1397,10 +1349,8 @@ typedef enum /* Identifier authority. */
* *
* NOTE: This is stored as a big endian number. * NOTE: This is stored as a big endian number.
*/ */
typedef union typedef union {
{ struct {
struct
{
u16 high_part; /* High 16-bits. */ u16 high_part; /* High 16-bits. */
u32 low_part; /* Low 32-bits. */ u32 low_part; /* Low 32-bits. */
} __attribute__((__packed__)); } __attribute__((__packed__));
@ -1435,8 +1385,7 @@ typedef union
* sub_authority[0] = 32, // SECURITY_BUILTIN_DOMAIN_RID * sub_authority[0] = 32, // SECURITY_BUILTIN_DOMAIN_RID
* sub_authority[1] = 544 // DOMAIN_ALIAS_RID_ADMINS * sub_authority[1] = 544 // DOMAIN_ALIAS_RID_ADMINS
*/ */
typedef struct typedef struct {
{
u8 revision; u8 revision;
u8 sub_authority_count; u8 sub_authority_count;
SID_IDENTIFIER_AUTHORITY identifier_authority; SID_IDENTIFIER_AUTHORITY identifier_authority;
@ -1446,8 +1395,7 @@ typedef struct
/** /**
* enum SID_CONSTANTS - Current constants for SIDs. * enum SID_CONSTANTS - Current constants for SIDs.
*/ */
typedef enum typedef enum {
{
SID_REVISION = 1, /* Current revision level. */ SID_REVISION = 1, /* Current revision level. */
SID_MAX_SUB_AUTHORITIES = 15, /* Maximum number of those. */ SID_MAX_SUB_AUTHORITIES = 15, /* Maximum number of those. */
SID_RECOMMENDED_SUB_AUTHORITIES = 1, /* Will change to around 6 in SID_RECOMMENDED_SUB_AUTHORITIES = 1, /* Will change to around 6 in
@ -1457,8 +1405,7 @@ typedef enum
/** /**
* enum ACE_TYPES - The predefined ACE types (8-bit, see below). * enum ACE_TYPES - The predefined ACE types (8-bit, see below).
*/ */
typedef enum typedef enum {
{
ACCESS_MIN_MS_ACE_TYPE = 0, ACCESS_MIN_MS_ACE_TYPE = 0,
ACCESS_ALLOWED_ACE_TYPE = 0, ACCESS_ALLOWED_ACE_TYPE = 0,
ACCESS_DENIED_ACE_TYPE = 1, ACCESS_DENIED_ACE_TYPE = 1,
@ -1493,8 +1440,7 @@ typedef enum
* FAILED_ACCESS_ACE_FLAG is only used with system audit and alarm ACE types * FAILED_ACCESS_ACE_FLAG is only used with system audit and alarm ACE types
* to indicate that a message is generated (in Windows!) for failed accesses. * to indicate that a message is generated (in Windows!) for failed accesses.
*/ */
typedef enum typedef enum {
{
/* The inheritance flags. */ /* The inheritance flags. */
OBJECT_INHERIT_ACE = 0x01, OBJECT_INHERIT_ACE = 0x01,
CONTAINER_INHERIT_ACE = 0x02, CONTAINER_INHERIT_ACE = 0x02,
@ -1521,8 +1467,7 @@ typedef enum
* which specifies the type and size of the ACE. The format of the subsequent * which specifies the type and size of the ACE. The format of the subsequent
* data depends on the ACE type. * data depends on the ACE type.
*/ */
typedef struct typedef struct {
{
ACE_TYPES type; /* Type of the ACE. */ ACE_TYPES type; /* Type of the ACE. */
ACE_FLAGS flags; /* Flags describing the ACE. */ ACE_FLAGS flags; /* Flags describing the ACE. */
u16 size; /* Size in bytes of the ACE. */ u16 size; /* Size in bytes of the ACE. */
@ -1533,8 +1478,7 @@ typedef struct
* *
* Defines the access rights. * Defines the access rights.
*/ */
typedef enum typedef enum {
{
/* /*
* The specific rights (bits 0 to 15). Depend on the type of the * The specific rights (bits 0 to 15). Depend on the type of the
* object being secured by the ACE. * object being secured by the ACE.
@ -1672,8 +1616,7 @@ typedef enum
* *
* FIXME: What exactly is this and what is it for? (AIA) * FIXME: What exactly is this and what is it for? (AIA)
*/ */
typedef struct typedef struct {
{
ACCESS_MASK generic_read; ACCESS_MASK generic_read;
ACCESS_MASK generic_write; ACCESS_MASK generic_write;
ACCESS_MASK generic_execute; ACCESS_MASK generic_execute;
@ -1689,8 +1632,7 @@ typedef struct
* *
* ACCESS_ALLOWED_ACE, ACCESS_DENIED_ACE, SYSTEM_AUDIT_ACE, SYSTEM_ALARM_ACE * ACCESS_ALLOWED_ACE, ACCESS_DENIED_ACE, SYSTEM_AUDIT_ACE, SYSTEM_ALARM_ACE
*/ */
typedef struct typedef struct {
{
/* 0 ACE_HEADER; -- Unfolded here as gcc doesn't like unnamed structs. */ /* 0 ACE_HEADER; -- Unfolded here as gcc doesn't like unnamed structs. */
ACE_TYPES type; /* Type of the ACE. */ ACE_TYPES type; /* Type of the ACE. */
ACE_FLAGS flags; /* Flags describing the ACE. */ ACE_FLAGS flags; /* Flags describing the ACE. */
@ -1704,8 +1646,7 @@ SYSTEM_AUDIT_ACE, SYSTEM_ALARM_ACE;
/** /**
* enum OBJECT_ACE_FLAGS - The object ACE flags (32-bit). * enum OBJECT_ACE_FLAGS - The object ACE flags (32-bit).
*/ */
typedef enum typedef enum {
{
ACE_OBJECT_TYPE_PRESENT = const_cpu_to_le32(1), ACE_OBJECT_TYPE_PRESENT = const_cpu_to_le32(1),
ACE_INHERITED_OBJECT_TYPE_PRESENT = const_cpu_to_le32(2), ACE_INHERITED_OBJECT_TYPE_PRESENT = const_cpu_to_le32(2),
} OBJECT_ACE_FLAGS; } OBJECT_ACE_FLAGS;
@ -1713,8 +1654,7 @@ typedef enum
/** /**
* struct ACCESS_ALLOWED_OBJECT_ACE - * struct ACCESS_ALLOWED_OBJECT_ACE -
*/ */
typedef struct typedef struct {
{
/* 0 ACE_HEADER; -- Unfolded here as gcc doesn't like unnamed structs. */ /* 0 ACE_HEADER; -- Unfolded here as gcc doesn't like unnamed structs. */
ACE_TYPES type; /* Type of the ACE. */ ACE_TYPES type; /* Type of the ACE. */
ACE_FLAGS flags; /* Flags describing the ACE. */ ACE_FLAGS flags; /* Flags describing the ACE. */
@ -1738,8 +1678,7 @@ SYSTEM_ALARM_OBJECT_ACE;
* zero or more access control entries (ACEs). The ACL as well as each ACE * zero or more access control entries (ACEs). The ACL as well as each ACE
* are aligned on 4-byte boundaries. * are aligned on 4-byte boundaries.
*/ */
typedef struct typedef struct {
{
u8 revision; /* Revision of this ACL. */ u8 revision; /* Revision of this ACL. */
u8 alignment1; u8 alignment1;
u16 size; /* Allocated space in bytes for ACL. Includes this u16 size; /* Allocated space in bytes for ACL. Includes this
@ -1752,8 +1691,7 @@ typedef struct
/** /**
* enum ACL_CONSTANTS - Current constants for ACLs. * enum ACL_CONSTANTS - Current constants for ACLs.
*/ */
typedef enum typedef enum {
{
/* Current revision. */ /* Current revision. */
ACL_REVISION = 2, ACL_REVISION = 2,
ACL_REVISION_DS = 4, ACL_REVISION_DS = 4,
@ -1816,8 +1754,7 @@ typedef enum
* and all pointer fields are expressed as offsets from the * and all pointer fields are expressed as offsets from the
* beginning of the security descriptor. * beginning of the security descriptor.
*/ */
typedef enum typedef enum {
{
SE_OWNER_DEFAULTED = const_cpu_to_le16(0x0001), SE_OWNER_DEFAULTED = const_cpu_to_le16(0x0001),
SE_GROUP_DEFAULTED = const_cpu_to_le16(0x0002), SE_GROUP_DEFAULTED = const_cpu_to_le16(0x0002),
SE_DACL_PRESENT = const_cpu_to_le16(0x0004), SE_DACL_PRESENT = const_cpu_to_le16(0x0004),
@ -1840,8 +1777,7 @@ typedef enum
* Self-relative security descriptor. Contains the owner and group SIDs as well * Self-relative security descriptor. Contains the owner and group SIDs as well
* as the sacl and dacl ACLs inside the security descriptor itself. * as the sacl and dacl ACLs inside the security descriptor itself.
*/ */
typedef struct typedef struct {
{
u8 revision; /* Revision level of the security descriptor. */ u8 revision; /* Revision level of the security descriptor. */
u8 alignment; u8 alignment;
SECURITY_DESCRIPTOR_CONTROL control; /* Flags qualifying the type of SECURITY_DESCRIPTOR_CONTROL control; /* Flags qualifying the type of
@ -1873,8 +1809,7 @@ typedef struct
* *
* On disk, a self-relative security descriptor is used. * On disk, a self-relative security descriptor is used.
*/ */
typedef struct typedef struct {
{
u8 revision; /* Revision level of the security descriptor. */ u8 revision; /* Revision level of the security descriptor. */
u8 alignment; u8 alignment;
SECURITY_DESCRIPTOR_CONTROL control; /* Flags qualifying the type of SECURITY_DESCRIPTOR_CONTROL control; /* Flags qualifying the type of
@ -1900,8 +1835,7 @@ typedef struct
* *
* Current constants for security descriptors. * Current constants for security descriptors.
*/ */
typedef enum typedef enum {
{
/* Current revision. */ /* Current revision. */
SECURITY_DESCRIPTOR_REVISION = 1, SECURITY_DESCRIPTOR_REVISION = 1,
SECURITY_DESCRIPTOR_REVISION1 = 1, SECURITY_DESCRIPTOR_REVISION1 = 1,
@ -1968,8 +1902,7 @@ typedef SECURITY_DESCRIPTOR_RELATIVE SECURITY_DESCRIPTOR_ATTR;
* This header precedes each security descriptor in the $SDS data stream. * This header precedes each security descriptor in the $SDS data stream.
* This is also the index entry data part of both the $SII and $SDH indexes. * This is also the index entry data part of both the $SII and $SDH indexes.
*/ */
typedef struct typedef struct {
{
u32 hash; /* Hash of the security descriptor. */ u32 hash; /* Hash of the security descriptor. */
u32 security_id; /* The security_id assigned to the descriptor. */ u32 security_id; /* The security_id assigned to the descriptor. */
u64 offset; /* Byte offset of this entry in the $SDS stream. */ u64 offset; /* Byte offset of this entry in the $SDS stream. */
@ -1979,8 +1912,7 @@ typedef struct
/** /**
* struct SDH_INDEX_DATA - * struct SDH_INDEX_DATA -
*/ */
typedef struct typedef struct {
{
u32 hash; /* Hash of the security descriptor. */ u32 hash; /* Hash of the security descriptor. */
u32 security_id; /* The security_id assigned to the descriptor. */ u32 security_id; /* The security_id assigned to the descriptor. */
u64 offset; /* Byte offset of this entry in the $SDS stream. */ u64 offset; /* Byte offset of this entry in the $SDS stream. */
@ -2007,8 +1939,7 @@ typedef SECURITY_DESCRIPTOR_HEADER SII_INDEX_DATA;
* the first copy of the security descriptor will be at offset 0x51d0 in the * the first copy of the security descriptor will be at offset 0x51d0 in the
* $SDS data stream and the second copy will be at offset 0x451d0. * $SDS data stream and the second copy will be at offset 0x451d0.
*/ */
typedef struct typedef struct {
{
/* 0 SECURITY_DESCRIPTOR_HEADER; -- Unfolded here as gcc doesn't like /* 0 SECURITY_DESCRIPTOR_HEADER; -- Unfolded here as gcc doesn't like
unnamed structs. */ unnamed structs. */
u32 hash; /* Hash of the security descriptor. */ u32 hash; /* Hash of the security descriptor. */
@ -2024,8 +1955,7 @@ typedef struct
* *
* The collation type is COLLATION_NTOFS_ULONG. * The collation type is COLLATION_NTOFS_ULONG.
*/ */
typedef struct typedef struct {
{
u32 security_id; /* The security_id assigned to the descriptor. */ u32 security_id; /* The security_id assigned to the descriptor. */
} __attribute__((__packed__)) SII_INDEX_KEY; } __attribute__((__packed__)) SII_INDEX_KEY;
@ -2035,8 +1965,7 @@ typedef struct
* The keys are sorted first by hash and then by security_id. * The keys are sorted first by hash and then by security_id.
* The collation rule is COLLATION_NTOFS_SECURITY_HASH. * The collation rule is COLLATION_NTOFS_SECURITY_HASH.
*/ */
typedef struct typedef struct {
{
u32 hash; /* Hash of the security descriptor. */ u32 hash; /* Hash of the security descriptor. */
u32 security_id; /* The security_id assigned to the descriptor. */ u32 security_id; /* The security_id assigned to the descriptor. */
} __attribute__((__packed__)) SDH_INDEX_KEY; } __attribute__((__packed__)) SDH_INDEX_KEY;
@ -2047,16 +1976,14 @@ typedef struct
* NOTE: Always resident. * NOTE: Always resident.
* NOTE: Present only in FILE_Volume. * NOTE: Present only in FILE_Volume.
*/ */
typedef struct typedef struct {
{
ntfschar name[0]; /* The name of the volume in Unicode. */ ntfschar name[0]; /* The name of the volume in Unicode. */
} __attribute__((__packed__)) VOLUME_NAME; } __attribute__((__packed__)) VOLUME_NAME;
/** /**
* enum VOLUME_FLAGS - Possible flags for the volume (16-bit). * enum VOLUME_FLAGS - Possible flags for the volume (16-bit).
*/ */
typedef enum typedef enum {
{
VOLUME_IS_DIRTY = const_cpu_to_le16(0x0001), VOLUME_IS_DIRTY = const_cpu_to_le16(0x0001),
VOLUME_RESIZE_LOG_FILE = const_cpu_to_le16(0x0002), VOLUME_RESIZE_LOG_FILE = const_cpu_to_le16(0x0002),
VOLUME_UPGRADE_ON_MOUNT = const_cpu_to_le16(0x0004), VOLUME_UPGRADE_ON_MOUNT = const_cpu_to_le16(0x0004),
@ -2076,8 +2003,7 @@ typedef enum
* NOTE: Windows 2000 uses NTFS 3.0 while Windows NT4 service pack 6a uses * NOTE: Windows 2000 uses NTFS 3.0 while Windows NT4 service pack 6a uses
* NTFS 1.2. I haven't personally seen other values yet. * NTFS 1.2. I haven't personally seen other values yet.
*/ */
typedef struct typedef struct {
{
u64 reserved; /* Not used (yet?). */ u64 reserved; /* Not used (yet?). */
u8 major_ver; /* Major version of the ntfs format. */ u8 major_ver; /* Major version of the ntfs format. */
u8 minor_ver; /* Minor version of the ntfs format. */ u8 minor_ver; /* Minor version of the ntfs format. */
@ -2091,16 +2017,14 @@ typedef struct
* *
* Data contents of a file (i.e. the unnamed stream) or of a named stream. * Data contents of a file (i.e. the unnamed stream) or of a named stream.
*/ */
typedef struct typedef struct {
{
u8 data[0]; /* The file's data contents. */ u8 data[0]; /* The file's data contents. */
} __attribute__((__packed__)) DATA_ATTR; } __attribute__((__packed__)) DATA_ATTR;
/** /**
* enum INDEX_HEADER_FLAGS - Index header flags (8-bit). * enum INDEX_HEADER_FLAGS - Index header flags (8-bit).
*/ */
typedef enum typedef enum {
{
/* When index header is in an index root attribute: */ /* When index header is in an index root attribute: */
SMALL_INDEX = 0, /* The index is small enough to fit inside the SMALL_INDEX = 0, /* The index is small enough to fit inside the
index root attribute and there is no index index root attribute and there is no index
@ -2130,10 +2054,8 @@ typedef enum
* relative to the start of the index header structure and not relative to the * relative to the start of the index header structure and not relative to the
* start of the index root or index allocation structures themselves. * start of the index root or index allocation structures themselves.
*/ */
typedef struct typedef struct {
{ /* 0*/ u32 entries_offset; /* Byte offset from the INDEX_HEADER to first
/* 0*/
u32 entries_offset; /* Byte offset from the INDEX_HEADER to first
INDEX_ENTRY, aligned to 8-byte boundary. */ INDEX_ENTRY, aligned to 8-byte boundary. */
/* 4*/ u32 index_length; /* Data size in byte of the INDEX_ENTRY's, /* 4*/ u32 index_length; /* Data size in byte of the INDEX_ENTRY's,
including the INDEX_HEADER, aligned to 8. */ including the INDEX_HEADER, aligned to 8. */
@ -2172,10 +2094,8 @@ typedef struct
* NOTE: The root directory (FILE_root) contains an entry for itself. Other * NOTE: The root directory (FILE_root) contains an entry for itself. Other
* directories do not contain entries for themselves, though. * directories do not contain entries for themselves, though.
*/ */
typedef struct typedef struct {
{ /* 0*/ ATTR_TYPES type; /* Type of the indexed attribute. Is
/* 0*/
ATTR_TYPES type; /* Type of the indexed attribute. Is
$FILE_NAME for directories, zero $FILE_NAME for directories, zero
for view indexes. No other values for view indexes. No other values
allowed. */ allowed. */
@ -2203,8 +2123,7 @@ typedef struct
* INDEX_BLOCK structure containing an index header, followed by a sequence of * INDEX_BLOCK structure containing an index header, followed by a sequence of
* index entries (INDEX_ENTRY structures), as described by the INDEX_HEADER. * index entries (INDEX_ENTRY structures), as described by the INDEX_HEADER.
*/ */
typedef struct typedef struct {
{
/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ /* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
NTFS_RECORD_TYPES magic;/* Magic is "INDX". */ NTFS_RECORD_TYPES magic;/* Magic is "INDX". */
u16 usa_ofs; /* See NTFS_RECORD definition. */ u16 usa_ofs; /* See NTFS_RECORD definition. */
@ -2239,8 +2158,7 @@ typedef INDEX_BLOCK INDEX_ALLOCATION;
* COLLATION_NTOFS_ULONGS. FIXME: Verify whether the reparse_tag is not the * COLLATION_NTOFS_ULONGS. FIXME: Verify whether the reparse_tag is not the
* primary key / is not a key at all. (AIA) * primary key / is not a key at all. (AIA)
*/ */
typedef struct typedef struct {
{
u32 reparse_tag; /* Reparse point type (inc. flags). */ u32 reparse_tag; /* Reparse point type (inc. flags). */
MFT_REF file_id; /* Mft record of the file containing the MFT_REF file_id; /* Mft record of the file containing the
reparse point attribute. */ reparse point attribute. */
@ -2249,8 +2167,7 @@ typedef struct
/** /**
* enum QUOTA_FLAGS - Quota flags (32-bit). * enum QUOTA_FLAGS - Quota flags (32-bit).
*/ */
typedef enum typedef enum {
{
/* The user quota flags. Names explain meaning. */ /* The user quota flags. Names explain meaning. */
QUOTA_FLAG_DEFAULT_LIMITS = const_cpu_to_le32(0x00000001), QUOTA_FLAG_DEFAULT_LIMITS = const_cpu_to_le32(0x00000001),
QUOTA_FLAG_LIMIT_REACHED = const_cpu_to_le32(0x00000002), QUOTA_FLAG_LIMIT_REACHED = const_cpu_to_le32(0x00000002),
@ -2294,8 +2211,7 @@ typedef enum
* *
* The $Q index entry data is the quota control entry and is defined below. * The $Q index entry data is the quota control entry and is defined below.
*/ */
typedef struct typedef struct {
{
u32 version; /* Currently equals 2. */ u32 version; /* Currently equals 2. */
QUOTA_FLAGS flags; /* Flags describing this quota entry. */ QUOTA_FLAGS flags; /* Flags describing this quota entry. */
u64 bytes_used; /* How many bytes of the quota are in use. */ u64 bytes_used; /* How many bytes of the quota are in use. */
@ -2317,8 +2233,7 @@ typedef struct
/** /**
* struct QUOTA_O_INDEX_DATA - * struct QUOTA_O_INDEX_DATA -
*/ */
typedef struct typedef struct {
{
u32 owner_id; u32 owner_id;
u32 unknown; /* Always 32. Seems to be padding and it's not u32 unknown; /* Always 32. Seems to be padding and it's not
counted in the INDEX_ENTRY's data_length. counted in the INDEX_ENTRY's data_length.
@ -2328,8 +2243,7 @@ typedef struct
/** /**
* enum PREDEFINED_OWNER_IDS - Predefined owner_id values (32-bit). * enum PREDEFINED_OWNER_IDS - Predefined owner_id values (32-bit).
*/ */
typedef enum typedef enum {
{
QUOTA_INVALID_ID = const_cpu_to_le32(0x00000000), QUOTA_INVALID_ID = const_cpu_to_le32(0x00000000),
QUOTA_DEFAULTS_ID = const_cpu_to_le32(0x00000001), QUOTA_DEFAULTS_ID = const_cpu_to_le32(0x00000001),
QUOTA_FIRST_USER_ID = const_cpu_to_le32(0x00000100), QUOTA_FIRST_USER_ID = const_cpu_to_le32(0x00000100),
@ -2338,8 +2252,7 @@ typedef enum
/** /**
* enum INDEX_ENTRY_FLAGS - Index entry flags (16-bit). * enum INDEX_ENTRY_FLAGS - Index entry flags (16-bit).
*/ */
typedef enum typedef enum {
{
INDEX_ENTRY_NODE = const_cpu_to_le16(1), /* This entry contains a INDEX_ENTRY_NODE = const_cpu_to_le16(1), /* This entry contains a
sub-node, i.e. a reference to an index sub-node, i.e. a reference to an index
block in form of a virtual cluster block in form of a virtual cluster
@ -2358,14 +2271,10 @@ typedef enum
* !!!!! SEE DESCRIPTION OF THE FIELDS AT INDEX_ENTRY !!!!! * !!!!! SEE DESCRIPTION OF THE FIELDS AT INDEX_ENTRY !!!!!
* ========================================================== * ==========================================================
*/ */
typedef struct typedef struct {
{ /* 0*/ union {
/* 0*/
union
{
MFT_REF indexed_file; MFT_REF indexed_file;
struct struct {
{
u16 data_offset; u16 data_offset;
u16 data_length; u16 data_length;
u32 reservedV; u32 reservedV;
@ -2387,17 +2296,14 @@ typedef struct
* *
* NOTE: Before NTFS 3.0 only filename attributes were indexed. * NOTE: Before NTFS 3.0 only filename attributes were indexed.
*/ */
typedef struct typedef struct {
{
/* 0 INDEX_ENTRY_HEADER; -- Unfolded here as gcc dislikes unnamed structs. */ /* 0 INDEX_ENTRY_HEADER; -- Unfolded here as gcc dislikes unnamed structs. */
union /* Only valid when INDEX_ENTRY_END is not set. */ union { /* Only valid when INDEX_ENTRY_END is not set. */
{
MFT_REF indexed_file; /* The mft reference of the file MFT_REF indexed_file; /* The mft reference of the file
described by this index described by this index
entry. Used for directory entry. Used for directory
indexes. */ indexes. */
struct /* Used for views/indexes to find the entry's data. */ struct { /* Used for views/indexes to find the entry's data. */
{
u16 data_offset; /* Data byte offset from this u16 data_offset; /* Data byte offset from this
INDEX_ENTRY. Follows the INDEX_ENTRY. Follows the
index key. */ index key. */
@ -2414,8 +2320,7 @@ typedef struct
/* 12*/ INDEX_ENTRY_FLAGS ie_flags; /* Bit field of INDEX_ENTRY_* flags. */ /* 12*/ INDEX_ENTRY_FLAGS ie_flags; /* Bit field of INDEX_ENTRY_* flags. */
/* 14*/ u16 reserved; /* Reserved/align to 8-byte boundary. */ /* 14*/ u16 reserved; /* Reserved/align to 8-byte boundary. */
/* End of INDEX_ENTRY_HEADER */ /* End of INDEX_ENTRY_HEADER */
/* 16*/ union /* 16*/ union { /* The key of the indexed attribute. NOTE: Only present
{ /* The key of the indexed attribute. NOTE: Only present
if INDEX_ENTRY_END bit in flags is not set. NOTE: On if INDEX_ENTRY_END bit in flags is not set. NOTE: On
NTFS versions before 3.0 the only valid key is the NTFS versions before 3.0 the only valid key is the
FILE_NAME_ATTR. On NTFS 3.0+ the following FILE_NAME_ATTR. On NTFS 3.0+ the following
@ -2459,8 +2364,7 @@ typedef struct
* the number of bits in the bitmap * index block size / cluster size is the * the number of bits in the bitmap * index block size / cluster size is the
* number of clusters in the index allocation attribute. * number of clusters in the index allocation attribute.
*/ */
typedef struct typedef struct {
{
u8 bitmap[0]; /* Array of bits. */ u8 bitmap[0]; /* Array of bits. */
} __attribute__((__packed__)) BITMAP_ATTR; } __attribute__((__packed__)) BITMAP_ATTR;
@ -2484,8 +2388,7 @@ typedef struct
* bit 31: Microsoft bit. If set, the tag is owned by Microsoft. User * bit 31: Microsoft bit. If set, the tag is owned by Microsoft. User
* defined tags have to use zero here. * defined tags have to use zero here.
*/ */
typedef enum typedef enum {
{
IO_REPARSE_TAG_IS_ALIAS = const_cpu_to_le32(0x20000000), IO_REPARSE_TAG_IS_ALIAS = const_cpu_to_le32(0x20000000),
IO_REPARSE_TAG_IS_HIGH_LATENCY = const_cpu_to_le32(0x40000000), IO_REPARSE_TAG_IS_HIGH_LATENCY = const_cpu_to_le32(0x40000000),
IO_REPARSE_TAG_IS_MICROSOFT = const_cpu_to_le32(0x80000000), IO_REPARSE_TAG_IS_MICROSOFT = const_cpu_to_le32(0x80000000),
@ -2513,8 +2416,7 @@ typedef enum
* *
* NOTE: Can be resident or non-resident. * NOTE: Can be resident or non-resident.
*/ */
typedef struct typedef struct {
{
u32 reparse_tag; /* Reparse point type (inc. flags). */ u32 reparse_tag; /* Reparse point type (inc. flags). */
u16 reparse_data_length; /* Byte size of reparse data. */ u16 reparse_data_length; /* Byte size of reparse data. */
u16 reserved; /* Align to 8-byte boundary. */ u16 reserved; /* Align to 8-byte boundary. */
@ -2526,8 +2428,7 @@ typedef struct
* *
* NOTE: Always resident. * NOTE: Always resident.
*/ */
typedef struct typedef struct {
{
u16 ea_length; /* Byte size of the packed extended u16 ea_length; /* Byte size of the packed extended
attributes. */ attributes. */
u16 need_ea_count; /* The number of extended attributes which have u16 need_ea_count; /* The number of extended attributes which have
@ -2542,8 +2443,7 @@ typedef struct
/** /**
* enum EA_FLAGS - Extended attribute flags (8-bit). * enum EA_FLAGS - Extended attribute flags (8-bit).
*/ */
typedef enum typedef enum {
{
NEED_EA = 0x80, /* Indicate that the file to which the EA NEED_EA = 0x80, /* Indicate that the file to which the EA
belongs cannot be interpreted without belongs cannot be interpreted without
understanding the associated extended understanding the associated extended
@ -2559,8 +2459,7 @@ typedef enum
* FIXME: It appears weird that the EA name is not Unicode. Is it true? * FIXME: It appears weird that the EA name is not Unicode. Is it true?
* FIXME: It seems that name is always uppercased. Is it true? * FIXME: It seems that name is always uppercased. Is it true?
*/ */
typedef struct typedef struct {
{
u32 next_entry_offset; /* Offset to the next EA_ATTR. */ u32 next_entry_offset; /* Offset to the next EA_ATTR. */
EA_FLAGS flags; /* Flags describing the EA. */ EA_FLAGS flags; /* Flags describing the EA. */
u8 name_length; /* Length of the name of the extended u8 name_length; /* Length of the name of the extended
@ -2577,8 +2476,7 @@ typedef struct
* Intended to support Native Structure Storage (NSS) - a feature removed from * Intended to support Native Structure Storage (NSS) - a feature removed from
* NTFS 3.0 during beta testing. * NTFS 3.0 during beta testing.
*/ */
typedef struct typedef struct {
{
/* Irrelevant as feature unused. */ /* Irrelevant as feature unused. */
} __attribute__((__packed__)) PROPERTY_SET; } __attribute__((__packed__)) PROPERTY_SET;
@ -2593,8 +2491,7 @@ typedef struct
* Used by the Encrypting File System (EFS). All encrypted files have this * Used by the Encrypting File System (EFS). All encrypted files have this
* attribute with the name $EFS. See below for the relevant structures. * attribute with the name $EFS. See below for the relevant structures.
*/ */
typedef struct typedef struct {
{
/* Can be anything the creator chooses. */ /* Can be anything the creator chooses. */
} __attribute__((__packed__)) LOGGED_UTILITY_STREAM; } __attribute__((__packed__)) LOGGED_UTILITY_STREAM;
@ -2630,10 +2527,8 @@ typedef struct
* *
* The header of the Logged utility stream (0x100) attribute named "$EFS". * The header of the Logged utility stream (0x100) attribute named "$EFS".
*/ */
typedef struct typedef struct {
{ /* 0*/ u32 length; /* Length of EFS attribute in bytes. */
/* 0*/
u32 length; /* Length of EFS attribute in bytes. */
u32 state; /* Always 0? */ u32 state; /* Always 0? */
u32 version; /* Efs version. Always 2? */ u32 version; /* Efs version. Always 2? */
u32 crypto_api_version; /* Always 0? */ u32 crypto_api_version; /* Always 0? */
@ -2656,8 +2551,7 @@ typedef struct
/** /**
* struct EFS_DF_ARRAY_HEADER - * struct EFS_DF_ARRAY_HEADER -
*/ */
typedef struct typedef struct {
{
u32 df_count; /* Number of data decryption/recovery fields in u32 df_count; /* Number of data decryption/recovery fields in
the array. */ the array. */
} __attribute__((__packed__)) EFS_DF_ARRAY_HEADER; } __attribute__((__packed__)) EFS_DF_ARRAY_HEADER;
@ -2665,10 +2559,8 @@ typedef struct
/** /**
* struct EFS_DF_HEADER - * struct EFS_DF_HEADER -
*/ */
typedef struct typedef struct {
{ /* 0*/ u32 df_length; /* Length of this data decryption/recovery
/* 0*/
u32 df_length; /* Length of this data decryption/recovery
field in bytes. */ field in bytes. */
u32 cred_header_offset; /* Offset in bytes to the credential header. */ u32 cred_header_offset; /* Offset in bytes to the credential header. */
u32 fek_size; /* Size in bytes of the encrypted file u32 fek_size; /* Size in bytes of the encrypted file
@ -2681,10 +2573,8 @@ typedef struct
/** /**
* struct EFS_DF_CREDENTIAL_HEADER - * struct EFS_DF_CREDENTIAL_HEADER -
*/ */
typedef struct typedef struct {
{ /* 0*/ u32 cred_length; /* Length of this credential in bytes. */
/* 0*/
u32 cred_length; /* Length of this credential in bytes. */
u32 sid_offset; /* Offset in bytes to the user's sid from start u32 sid_offset; /* Offset in bytes to the user's sid from start
of this structure. Zero if no sid is of this structure. Zero if no sid is
present. */ present. */
@ -2693,13 +2583,10 @@ typedef struct
2 = Unexpected type. 2 = Unexpected type.
3 = Certificate thumbprint. 3 = Certificate thumbprint.
other = Unknown type. */ other = Unknown type. */
union union {
{
/* CryptoAPI container. */ /* CryptoAPI container. */
struct struct {
{ /* 12*/ u32 container_name_offset; /* Offset in bytes to
/* 12*/
u32 container_name_offset; /* Offset in bytes to
the name of the container from start of this the name of the container from start of this
structure (may not be zero). */ structure (may not be zero). */
/* 16*/ u32 provider_name_offset; /* Offset in bytes to /* 16*/ u32 provider_name_offset; /* Offset in bytes to
@ -2712,10 +2599,8 @@ typedef struct
public key blob. */ public key blob. */
} __attribute__((__packed__)); } __attribute__((__packed__));
/* Certificate thumbprint. */ /* Certificate thumbprint. */
struct struct {
{ /* 12*/ u32 cert_thumbprint_header_size; /* Size in
/* 12*/
u32 cert_thumbprint_header_size; /* Size in
bytes of the header of the certificate bytes of the header of the certificate
thumbprint. */ thumbprint. */
/* 16*/ u32 cert_thumbprint_header_offset; /* Offset in /* 16*/ u32 cert_thumbprint_header_offset; /* Offset in
@ -2732,10 +2617,8 @@ typedef EFS_DF_CREDENTIAL_HEADER EFS_DF_CRED_HEADER;
/** /**
* struct EFS_DF_CERTIFICATE_THUMBPRINT_HEADER - * struct EFS_DF_CERTIFICATE_THUMBPRINT_HEADER -
*/ */
typedef struct typedef struct {
{ /* 0*/ u32 thumbprint_offset; /* Offset in bytes to the thumbprint. */
/* 0*/
u32 thumbprint_offset; /* Offset in bytes to the thumbprint. */
u32 thumbprint_size; /* Size of thumbprint in bytes. */ u32 thumbprint_size; /* Size of thumbprint in bytes. */
/* 8*/ u32 container_name_offset; /* Offset in bytes to the name of the /* 8*/ u32 container_name_offset; /* Offset in bytes to the name of the
container from start of this container from start of this
@ -2752,8 +2635,7 @@ typedef struct
typedef EFS_DF_CERTIFICATE_THUMBPRINT_HEADER EFS_DF_CERT_THUMBPRINT_HEADER; typedef EFS_DF_CERTIFICATE_THUMBPRINT_HEADER EFS_DF_CERT_THUMBPRINT_HEADER;
typedef enum typedef enum {
{
INTX_SYMBOLIC_LINK = INTX_SYMBOLIC_LINK =
const_cpu_to_le64(0x014B4E4C78746E49ULL), /* "IntxLNK\1" */ const_cpu_to_le64(0x014B4E4C78746E49ULL), /* "IntxLNK\1" */
INTX_CHARACTER_DEVICE = INTX_CHARACTER_DEVICE =
@ -2762,14 +2644,11 @@ typedef enum
const_cpu_to_le64(0x004B4C4278746E49ULL), /* "IntxBLK\0" */ const_cpu_to_le64(0x004B4C4278746E49ULL), /* "IntxBLK\0" */
} INTX_FILE_TYPES; } INTX_FILE_TYPES;
typedef struct typedef struct {
{
INTX_FILE_TYPES magic; /* Intx file magic. */ INTX_FILE_TYPES magic; /* Intx file magic. */
union union {
{
/* For character and block devices. */ /* For character and block devices. */
struct struct {
{
u64 major; /* Major device number. */ u64 major; /* Major device number. */
u64 minor; /* Minor device number. */ u64 minor; /* Minor device number. */
void *device_end[0]; /* Marker for offsetof(). */ void *device_end[0]; /* Marker for offsetof(). */

View File

@ -55,8 +55,7 @@
#define NTFS_LCNALLOC_BSIZE 4096 #define NTFS_LCNALLOC_BSIZE 4096
#define NTFS_LCNALLOC_SKIP NTFS_LCNALLOC_BSIZE #define NTFS_LCNALLOC_SKIP NTFS_LCNALLOC_BSIZE
enum enum {
{
ZONE_MFT = 1, ZONE_MFT = 1,
ZONE_DATA1 = 2, ZONE_DATA1 = 2,
ZONE_DATA2 = 4 ZONE_DATA2 = 4
@ -95,26 +94,19 @@ static void ntfs_cluster_update_zone_pos( ntfs_volume *vol, u8 zone, LCN tc )
static void update_full_status(ntfs_volume *vol, LCN lcn) static void update_full_status(ntfs_volume *vol, LCN lcn)
{ {
if ( lcn >= vol->mft_zone_end ) if (lcn >= vol->mft_zone_end) {
{ if (vol->full_zones & ZONE_DATA1) {
if ( vol->full_zones & ZONE_DATA1 )
{
ntfs_cluster_update_zone_pos(vol, ZONE_DATA1, lcn); ntfs_cluster_update_zone_pos(vol, ZONE_DATA1, lcn);
vol->full_zones &= ~ZONE_DATA1; vol->full_zones &= ~ZONE_DATA1;
} }
} } else
else if ( lcn < vol->mft_zone_start ) if (lcn < vol->mft_zone_start) {
{ if (vol->full_zones & ZONE_DATA2) {
if ( vol->full_zones & ZONE_DATA2 )
{
ntfs_cluster_update_zone_pos(vol, ZONE_DATA2, lcn); ntfs_cluster_update_zone_pos(vol, ZONE_DATA2, lcn);
vol->full_zones &= ~ZONE_DATA2; vol->full_zones &= ~ZONE_DATA2;
} }
} } else {
else if (vol->full_zones & ZONE_MFT) {
{
if ( vol->full_zones & ZONE_MFT )
{
ntfs_cluster_update_zone_pos(vol, ZONE_MFT, lcn); ntfs_cluster_update_zone_pos(vol, ZONE_MFT, lcn);
vol->full_zones &= ~ZONE_MFT; vol->full_zones &= ~ZONE_MFT;
} }
@ -130,49 +122,38 @@ static s64 max_empty_bit_range( unsigned char *buf, int size )
ntfs_log_trace("Entering\n"); ntfs_log_trace("Entering\n");
i = 0; i = 0;
while ( i < size ) while (i < size) {
{ switch (*buf) {
switch ( *buf )
{
case 0 : case 0 :
do do {
{
buf++; buf++;
run += 8; run += 8;
i++; i++;
} } while ((i < size) && !*buf);
while ( ( i < size ) && !*buf );
break; break;
case 255 : case 255 :
if ( run > max_range ) if (run > max_range) {
{
max_range = run; max_range = run;
start_pos = (s64)i * 8 - run; start_pos = (s64)i * 8 - run;
} }
run = 0; run = 0;
do do {
{
buf++; buf++;
i++; i++;
} } while ((i < size) && (*buf == 255));
while ( ( i < size ) && ( *buf == 255 ) );
break; break;
default : default :
for ( j = 0; j < 8; j++ ) for (j = 0; j < 8; j++) {
{
int bit = *buf & (1 << j); int bit = *buf & (1 << j);
if ( bit ) if (bit) {
{ if (run > max_range) {
if ( run > max_range )
{
max_range = run; max_range = run;
start_pos = (s64)i * 8 + (j - run); start_pos = (s64)i * 8 + (j - run);
} }
run = 0; run = 0;
} } else
else
run++; run++;
} }
i++; i++;
@ -200,8 +181,7 @@ static int bitmap_writeback( ntfs_volume *vol, s64 pos, s64 size, void *b,
*writeback = 0; *writeback = 0;
written = ntfs_attr_pwrite(vol->lcnbmp_na, pos, size, b); written = ntfs_attr_pwrite(vol->lcnbmp_na, pos, size, b);
if ( written != size ) if (written != size) {
{
if (!written) if (!written)
errno = EIO; errno = EIO;
ntfs_log_perror("Bitmap write error (%lld, %lld)", ntfs_log_perror("Bitmap write error (%lld, %lld)",
@ -273,8 +253,7 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
start_lcn, zone == MFT_ZONE ? "MFT" : "DATA"); start_lcn, zone == MFT_ZONE ? "MFT" : "DATA");
if (!vol || count < 0 || start_lcn < -1 || !vol->lcnbmp_na || if (!vol || count < 0 || start_lcn < -1 || !vol->lcnbmp_na ||
( s8 )zone < FIRST_ZONE || zone > LAST_ZONE ) (s8)zone < FIRST_ZONE || zone > LAST_ZONE) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s: vcn: %lld, count: %lld, lcn: %lld", ntfs_log_perror("%s: vcn: %lld, count: %lld, lcn: %lld",
__FUNCTION__, (long long)start_vcn, __FUNCTION__, (long long)start_vcn,
@ -283,11 +262,9 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
} }
/* Return empty runlist if @count == 0 */ /* Return empty runlist if @count == 0 */
if ( !count ) if (!count) {
{
rl = ntfs_malloc(0x1000); rl = ntfs_malloc(0x1000);
if ( rl ) if (rl) {
{
rl[0].vcn = start_vcn; rl[0].vcn = start_vcn;
rl[0].lcn = LCN_RL_NOT_MAPPED; rl[0].lcn = LCN_RL_NOT_MAPPED;
rl[0].length = 0; rl[0].length = 0;
@ -305,8 +282,7 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
has_guess = 1; has_guess = 1;
zone_start = start_lcn; zone_start = start_lcn;
if ( zone_start < 0 ) if (zone_start < 0) {
{
if (zone == DATA_ZONE) if (zone == DATA_ZONE)
zone_start = vol->data1_zone_pos; zone_start = vol->data1_zone_pos;
else else
@ -320,18 +296,13 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
zone_start == vol->mft_zone_end) zone_start == vol->mft_zone_end)
pass = 2; pass = 2;
if ( zone_start < vol->mft_zone_start ) if (zone_start < vol->mft_zone_start) {
{
zone_end = vol->mft_zone_start; zone_end = vol->mft_zone_start;
search_zone = ZONE_DATA2; search_zone = ZONE_DATA2;
} } else if (zone_start < vol->mft_zone_end) {
else if ( zone_start < vol->mft_zone_end )
{
zone_end = vol->mft_zone_end; zone_end = vol->mft_zone_end;
search_zone = ZONE_MFT; search_zone = ZONE_MFT;
} } else {
else
{
zone_end = vol->nr_clusters; zone_end = vol->nr_clusters;
search_zone = ZONE_DATA1; search_zone = ZONE_DATA1;
} }
@ -341,16 +312,14 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
/* Loop until all clusters are allocated. */ /* Loop until all clusters are allocated. */
clusters = count; clusters = count;
rlpos = rlsize = 0; rlpos = rlsize = 0;
while ( 1 ) while (1) {
{
/* check whether we have exhausted the current zone */ /* check whether we have exhausted the current zone */
if (search_zone & vol->full_zones) if (search_zone & vol->full_zones)
goto zone_pass_done; goto zone_pass_done;
last_read_pos = bmp_pos >> 3; last_read_pos = bmp_pos >> 3;
br = ntfs_attr_pread(vol->lcnbmp_na, last_read_pos, br = ntfs_attr_pread(vol->lcnbmp_na, last_read_pos,
NTFS_LCNALLOC_BSIZE, buf); NTFS_LCNALLOC_BSIZE, buf);
if ( br <= 0 ) if (br <= 0) {
{
if (!br) if (!br)
goto zone_pass_done; goto zone_pass_done;
err = errno; err = errno;
@ -366,20 +335,15 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
bmp_pos &= ~7; bmp_pos &= ~7;
writeback = 0; writeback = 0;
while ( lcn < buf_size ) while (lcn < buf_size) {
{
byte = buf + (lcn >> 3); byte = buf + (lcn >> 3);
bit = 1 << (lcn & 7); bit = 1 << (lcn & 7);
if ( has_guess ) if (has_guess) {
{ if (*byte & bit) {
if ( *byte & bit )
{
has_guess = 0; has_guess = 0;
break; break;
} }
} } else {
else
{
lcn = max_empty_bit_range(buf, br); lcn = max_empty_bit_range(buf, br);
if (lcn < 0) if (lcn < 0)
break; break;
@ -390,12 +354,10 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
/* First free bit is at lcn + bmp_pos. */ /* First free bit is at lcn + bmp_pos. */
/* Reallocate memory if necessary. */ /* Reallocate memory if necessary. */
if ( ( rlpos + 2 ) * ( int )sizeof( runlist ) >= rlsize ) if ((rlpos + 2) * (int)sizeof(runlist) >= rlsize) {
{
rlsize += 4096; rlsize += 4096;
trl = realloc(rl, rlsize); trl = realloc(rl, rlsize);
if ( !trl ) if (!trl) {
{
err = ENOMEM; err = ENOMEM;
ntfs_log_perror("realloc() failed"); ntfs_log_perror("realloc() failed");
goto wb_err_ret; goto wb_err_ret;
@ -417,8 +379,7 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
* Coalesce with previous run if adjacent LCNs. * Coalesce with previous run if adjacent LCNs.
* Otherwise, append a new run. * 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: " ntfs_log_debug("Cluster coalesce: prev_lcn: "
"%lld lcn: %lld bmp_pos: %lld " "%lld lcn: %lld bmp_pos: %lld "
"prev_run_len: %lld\n", "prev_run_len: %lld\n",
@ -426,14 +387,11 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
(long long)lcn, (long long)bmp_pos, (long long)lcn, (long long)bmp_pos,
(long long)prev_run_len); (long long)prev_run_len);
rl[rlpos - 1].length = ++prev_run_len; rl[rlpos - 1].length = ++prev_run_len;
} } else {
else
{
if (rlpos) if (rlpos)
rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos].vcn = rl[rlpos - 1].vcn +
prev_run_len; prev_run_len;
else else {
{
rl[rlpos].vcn = start_vcn; rl[rlpos].vcn = start_vcn;
ntfs_log_debug("Start_vcn: %lld\n", ntfs_log_debug("Start_vcn: %lld\n",
(long long)start_vcn); (long long)start_vcn);
@ -449,8 +407,7 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
(long long)rl[rlpos - 1].lcn, (long long)rl[rlpos - 1].lcn,
(long long)rl[rlpos - 1].length); (long long)rl[rlpos - 1].length);
/* Done? */ /* Done? */
if ( !--clusters ) if (!--clusters) {
{
if (used_zone_pos) if (used_zone_pos)
ntfs_cluster_update_zone_pos(vol, ntfs_cluster_update_zone_pos(vol,
search_zone, lcn + bmp_pos + 1 + search_zone, lcn + bmp_pos + 1 +
@ -461,14 +418,12 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
lcn++; lcn++;
} }
if ( bitmap_writeback( vol, last_read_pos, br, buf, &writeback ) ) if (bitmap_writeback(vol, last_read_pos, br, buf, &writeback)) {
{
err = errno; err = errno;
goto err_ret; goto err_ret;
} }
if ( !used_zone_pos ) if (!used_zone_pos) {
{
used_zone_pos = 1; used_zone_pos = 1;
@ -483,8 +438,7 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
zone_start == vol->mft_zone_end) zone_start == vol->mft_zone_end)
pass = 2; pass = 2;
bmp_pos = zone_start; bmp_pos = zone_start;
} } else
else
bmp_pos += buf_size; bmp_pos += buf_size;
if (bmp_pos < zone_end) if (bmp_pos < zone_end)
@ -492,8 +446,7 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
zone_pass_done: zone_pass_done:
ntfs_log_trace("Finished current zone pass(%i).\n", pass); ntfs_log_trace("Finished current zone pass(%i).\n", pass);
if ( pass == 1 ) if (pass == 1) {
{
pass = 2; pass = 2;
zone_end = zone_start; zone_end = zone_start;
@ -516,12 +469,10 @@ zone_pass_done:
done_zones_check: done_zones_check:
done_zones |= search_zone; done_zones |= search_zone;
vol->full_zones |= search_zone; vol->full_zones |= search_zone;
if ( done_zones < ( ZONE_MFT + ZONE_DATA1 + ZONE_DATA2 ) ) if (done_zones < (ZONE_MFT + ZONE_DATA1 + ZONE_DATA2)) {
{
ntfs_log_trace("Switching zone.\n"); ntfs_log_trace("Switching zone.\n");
pass = 1; pass = 1;
if ( rlpos ) if (rlpos) {
{
LCN tc = rl[rlpos - 1].lcn + LCN tc = rl[rlpos - 1].lcn +
rl[rlpos - 1].length + NTFS_LCNALLOC_SKIP; rl[rlpos - 1].length + NTFS_LCNALLOC_SKIP;
@ -530,8 +481,7 @@ done_zones_check:
search_zone, tc); search_zone, tc);
} }
switch ( search_zone ) switch (search_zone) {
{
case ZONE_MFT: case ZONE_MFT:
ntfs_log_trace("Zone switch: mft -> data1\n"); ntfs_log_trace("Zone switch: mft -> data1\n");
switch_to_data1_zone: search_zone = ZONE_DATA1; switch_to_data1_zone: search_zone = ZONE_DATA1;
@ -549,8 +499,7 @@ switch_to_data1_zone: search_zone = ZONE_DATA1;
pass = 2; pass = 2;
break; break;
case ZONE_DATA2: case ZONE_DATA2:
if ( !( done_zones & ZONE_DATA1 ) ) if (!(done_zones & ZONE_DATA1)) {
{
ntfs_log_trace("data2 -> data1\n"); ntfs_log_trace("data2 -> data1\n");
goto switch_to_data1_zone; goto switch_to_data1_zone;
} }
@ -565,8 +514,7 @@ switch_to_data1_zone: search_zone = ZONE_DATA1;
bmp_pos = zone_start; bmp_pos = zone_start;
if ( zone_start == zone_end ) if (zone_start == zone_end) {
{
ntfs_log_trace("Empty zone, skipped.\n"); ntfs_log_trace("Empty zone, skipped.\n");
goto done_zones_check; goto done_zones_check;
} }
@ -584,15 +532,13 @@ done_ret:
rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length; rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
rl[rlpos].lcn = LCN_RL_NOT_MAPPED; rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
rl[rlpos].length = 0; rl[rlpos].length = 0;
if ( bitmap_writeback( vol, last_read_pos, br, buf, &writeback ) ) if (bitmap_writeback(vol, last_read_pos, br, buf, &writeback)) {
{
err = errno; err = errno;
goto err_ret; goto err_ret;
} }
done_err_ret: done_err_ret:
free(buf); free(buf);
if ( err ) if (err) {
{
errno = err; errno = err;
ntfs_log_perror("Failed to allocate clusters"); ntfs_log_perror("Failed to allocate clusters");
rl = NULL; rl = NULL;
@ -607,8 +553,7 @@ wb_err_ret:
err = errno; err = errno;
err_ret: err_ret:
ntfs_log_trace("At err_ret.\n"); ntfs_log_trace("At err_ret.\n");
if ( rl ) if (rl) {
{
/* Add runlist terminator element. */ /* Add runlist terminator element. */
rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length; rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
rl[rlpos].lcn = LCN_RL_NOT_MAPPED; rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
@ -635,18 +580,15 @@ int ntfs_cluster_free_from_rl( ntfs_volume *vol, runlist *rl )
ntfs_log_trace("Entering.\n"); ntfs_log_trace("Entering.\n");
for ( ; rl->length; rl++ ) for (; rl->length; rl++) {
{
ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n", ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n",
(long long)rl->lcn, (long long)rl->length); (long long)rl->lcn, (long long)rl->length);
if ( rl->lcn >= 0 ) if (rl->lcn >= 0) {
{
update_full_status(vol,rl->lcn); update_full_status(vol,rl->lcn);
if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn, if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn,
rl->length ) ) rl->length)) {
{
ntfs_log_perror("Cluster deallocation failed " ntfs_log_perror("Cluster deallocation failed "
"(%lld, %lld)", "(%lld, %lld)",
(long long)rl->lcn, (long long)rl->lcn,
@ -681,12 +623,10 @@ int ntfs_cluster_free_basic( ntfs_volume *vol, s64 lcn, s64 count )
ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n", ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n",
(long long)lcn, (long long)count); (long long)lcn, (long long)count);
if ( lcn >= 0 ) if (lcn >= 0) {
{
update_full_status(vol,lcn); update_full_status(vol,lcn);
if (ntfs_bitmap_clear_run(vol->lcnbmp_na, lcn, if (ntfs_bitmap_clear_run(vol->lcnbmp_na, lcn,
count ) ) count)) {
{
ntfs_log_perror("Cluster deallocation failed " ntfs_log_perror("Cluster deallocation failed "
"(%lld, %lld)", "(%lld, %lld)",
(long long)lcn, (long long)lcn,
@ -728,8 +668,7 @@ int ntfs_cluster_free( ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count
int ret = -1; int ret = -1;
if (!vol || !vol->lcnbmp_na || !na || start_vcn < 0 || if (!vol || !vol->lcnbmp_na || !na || start_vcn < 0 ||
( count < 0 && count != -1 ) ) (count < 0 && count != -1)) {
{
ntfs_log_trace("Invalid arguments!\n"); ntfs_log_trace("Invalid arguments!\n");
errno = EINVAL; errno = EINVAL;
return -1; return -1;
@ -740,15 +679,13 @@ int ntfs_cluster_free( ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count
na->type, (long long)count, (long long)start_vcn); na->type, (long long)count, (long long)start_vcn);
rl = ntfs_attr_find_vcn(na, start_vcn); rl = ntfs_attr_find_vcn(na, start_vcn);
if ( !rl ) if (!rl) {
{
if (errno == ENOENT) if (errno == ENOENT)
ret = 0; ret = 0;
goto leave; goto leave;
} }
if ( rl->lcn < 0 && rl->lcn != LCN_HOLE ) if (rl->lcn < 0 && rl->lcn != LCN_HOLE) {
{
errno = EIO; errno = EIO;
ntfs_log_perror("%s: Unexpected lcn (%lld)", __FUNCTION__, ntfs_log_perror("%s: Unexpected lcn (%lld)", __FUNCTION__,
(long long)rl->lcn); (long long)rl->lcn);
@ -763,8 +700,7 @@ int ntfs_cluster_free( ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count
if (count >= 0 && to_free > count) if (count >= 0 && to_free > count)
to_free = count; to_free = count;
if ( rl->lcn != LCN_HOLE ) if (rl->lcn != LCN_HOLE) {
{
/* Do the actual freeing of the clusters in this run. */ /* Do the actual freeing of the clusters in this run. */
update_full_status(vol,rl->lcn + delta); update_full_status(vol,rl->lcn + delta);
if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn + delta, if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn + delta,
@ -782,12 +718,10 @@ int ntfs_cluster_free( ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count
* Loop over the remaining runs, using @count as a capping value, and * Loop over the remaining runs, using @count as a capping value, and
* free them. * free them.
*/ */
for ( ; rl->length && count != 0; ++rl ) for (; rl->length && count != 0; ++rl) {
{
// FIXME: Need to try ntfs_attr_map_runlist() for attribute // FIXME: Need to try ntfs_attr_map_runlist() for attribute
// list support! (AIA) // list support! (AIA)
if ( rl->lcn < 0 && rl->lcn != LCN_HOLE ) if (rl->lcn < 0 && rl->lcn != LCN_HOLE) {
{
// FIXME: Eeek! We need rollback! (AIA) // FIXME: Eeek! We need rollback! (AIA)
errno = EIO; errno = EIO;
ntfs_log_perror("%s: Invalid lcn (%lli)", ntfs_log_perror("%s: Invalid lcn (%lli)",
@ -800,12 +734,10 @@ int ntfs_cluster_free( ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count
if (count >= 0 && to_free > count) if (count >= 0 && to_free > count)
to_free = count; to_free = count;
if ( rl->lcn != LCN_HOLE ) if (rl->lcn != LCN_HOLE) {
{
update_full_status(vol,rl->lcn); update_full_status(vol,rl->lcn);
if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn, if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn,
to_free ) ) to_free)) {
{
// FIXME: Eeek! We need rollback! (AIA) // FIXME: Eeek! We need rollback! (AIA)
ntfs_log_perror("%s: Clearing bitmap run failed", ntfs_log_perror("%s: Clearing bitmap run failed",
__FUNCTION__); __FUNCTION__);
@ -818,8 +750,7 @@ int ntfs_cluster_free( ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count
count -= to_free; count -= to_free;
} }
if ( count != -1 && count != 0 ) if (count != -1 && count != 0) {
{
// FIXME: Eeek! BUG() // FIXME: Eeek! BUG()
errno = EIO; errno = EIO;
ntfs_log_perror("%s: count still not zero (%lld)", __FUNCTION__, ntfs_log_perror("%s: count still not zero (%lld)", __FUNCTION__,

View File

@ -31,8 +31,7 @@
/** /**
* enum NTFS_CLUSTER_ALLOCATION_ZONES - * enum NTFS_CLUSTER_ALLOCATION_ZONES -
*/ */
typedef enum typedef enum {
{
FIRST_ZONE = 0, /* For sanity checking. */ FIRST_ZONE = 0, /* For sanity checking. */
MFT_ZONE = 0, /* Allocate from $MFT zone. */ MFT_ZONE = 0, /* Allocate from $MFT zone. */
DATA_ZONE = 1, /* Allocate from $DATA zone. */ DATA_ZONE = 1, /* Allocate from $DATA zone. */

View File

@ -71,8 +71,7 @@ static BOOL ntfs_check_restart_page_header( RESTART_PAGE_HEADER *rp, s64 pos )
logfile_log_page_size < NTFS_BLOCK_SIZE || logfile_log_page_size < NTFS_BLOCK_SIZE ||
logfile_system_page_size & logfile_system_page_size &
(logfile_system_page_size - 1) || (logfile_system_page_size - 1) ||
logfile_log_page_size & ( logfile_log_page_size - 1 ) ) logfile_log_page_size & (logfile_log_page_size - 1)) {
{
ntfs_log_error("$LogFile uses unsupported page size.\n"); ntfs_log_error("$LogFile uses unsupported page size.\n");
return FALSE; return FALSE;
} }
@ -80,16 +79,14 @@ static BOOL ntfs_check_restart_page_header( RESTART_PAGE_HEADER *rp, s64 pos )
* We must be either at !pos (1st restart page) or at pos = system page * We must be either at !pos (1st restart page) or at pos = system page
* size (2nd restart page). * size (2nd restart page).
*/ */
if ( pos && pos != logfile_system_page_size ) if (pos && pos != logfile_system_page_size) {
{
ntfs_log_error("Found restart area in incorrect " ntfs_log_error("Found restart area in incorrect "
"position in $LogFile.\n"); "position in $LogFile.\n");
return FALSE; return FALSE;
} }
/* We only know how to handle version 1.1. */ /* We only know how to handle version 1.1. */
if (sle16_to_cpu(rp->major_ver) != 1 || if (sle16_to_cpu(rp->major_ver) != 1 ||
sle16_to_cpu( rp->minor_ver ) != 1 ) sle16_to_cpu(rp->minor_ver) != 1) {
{
ntfs_log_error("$LogFile version %i.%i is not " ntfs_log_error("$LogFile version %i.%i is not "
"supported. (This driver supports version " "supported. (This driver supports version "
"1.1 only.)\n", (int)sle16_to_cpu(rp->major_ver), "1.1 only.)\n", (int)sle16_to_cpu(rp->major_ver),
@ -100,15 +97,13 @@ static BOOL ntfs_check_restart_page_header( RESTART_PAGE_HEADER *rp, s64 pos )
* If chkdsk has been run the restart page may not be protected by an * If chkdsk has been run the restart page may not be protected by an
* update sequence array. * update sequence array.
*/ */
if ( ntfs_is_chkd_record( rp->magic ) && !le16_to_cpu( rp->usa_count ) ) if (ntfs_is_chkd_record(rp->magic) && !le16_to_cpu(rp->usa_count)) {
{
have_usa = FALSE; have_usa = FALSE;
goto skip_usa_checks; goto skip_usa_checks;
} }
/* Verify the size of the update sequence array. */ /* Verify the size of the update sequence array. */
usa_count = 1 + (logfile_system_page_size >> NTFS_BLOCK_SIZE_BITS); usa_count = 1 + (logfile_system_page_size >> NTFS_BLOCK_SIZE_BITS);
if ( usa_count != le16_to_cpu( rp->usa_count ) ) if (usa_count != le16_to_cpu(rp->usa_count)) {
{
ntfs_log_error("$LogFile restart page specifies " ntfs_log_error("$LogFile restart page specifies "
"inconsistent update sequence array count.\n"); "inconsistent update sequence array count.\n");
return FALSE; return FALSE;
@ -117,8 +112,7 @@ static BOOL ntfs_check_restart_page_header( RESTART_PAGE_HEADER *rp, s64 pos )
usa_ofs = le16_to_cpu(rp->usa_ofs); usa_ofs = le16_to_cpu(rp->usa_ofs);
usa_end = usa_ofs + usa_count * sizeof(u16); usa_end = usa_ofs + usa_count * sizeof(u16);
if (usa_ofs < sizeof(RESTART_PAGE_HEADER) || if (usa_ofs < sizeof(RESTART_PAGE_HEADER) ||
usa_end > NTFS_BLOCK_SIZE - sizeof( u16 ) ) usa_end > NTFS_BLOCK_SIZE - sizeof(u16)) {
{
ntfs_log_error("$LogFile restart page specifies " ntfs_log_error("$LogFile restart page specifies "
"inconsistent update sequence array offset.\n"); "inconsistent update sequence array offset.\n");
return FALSE; return FALSE;
@ -133,8 +127,7 @@ skip_usa_checks:
ra_ofs = le16_to_cpu(rp->restart_area_offset); ra_ofs = le16_to_cpu(rp->restart_area_offset);
if (ra_ofs & 7 || (have_usa ? ra_ofs < usa_end : if (ra_ofs & 7 || (have_usa ? ra_ofs < usa_end :
ra_ofs < sizeof(RESTART_PAGE_HEADER)) || ra_ofs < sizeof(RESTART_PAGE_HEADER)) ||
ra_ofs > logfile_system_page_size ) ra_ofs > logfile_system_page_size) {
{
ntfs_log_error("$LogFile restart page specifies " ntfs_log_error("$LogFile restart page specifies "
"inconsistent restart area offset.\n"); "inconsistent restart area offset.\n");
return FALSE; return FALSE;
@ -143,8 +136,7 @@ skip_usa_checks:
* Only restart pages modified by chkdsk are allowed to have chkdsk_lsn * Only restart pages modified by chkdsk are allowed to have chkdsk_lsn
* set. * set.
*/ */
if ( !ntfs_is_chkd_record( rp->magic ) && sle64_to_cpu( rp->chkdsk_lsn ) ) if (!ntfs_is_chkd_record(rp->magic) && sle64_to_cpu(rp->chkdsk_lsn)) {
{
ntfs_log_error("$LogFile restart page is not modified " ntfs_log_error("$LogFile restart page is not modified "
"by chkdsk but a chkdsk LSN is specified.\n"); "by chkdsk but a chkdsk LSN is specified.\n");
return FALSE; return FALSE;
@ -182,8 +174,7 @@ static BOOL ntfs_check_restart_area( RESTART_PAGE_HEADER *rp )
* safe to access ra->client_array_offset. * safe to access ra->client_array_offset.
*/ */
if (ra_ofs + offsetof(RESTART_AREA, file_size) > if (ra_ofs + offsetof(RESTART_AREA, file_size) >
NTFS_BLOCK_SIZE - sizeof( u16 ) ) NTFS_BLOCK_SIZE - sizeof(u16)) {
{
ntfs_log_error("$LogFile restart area specifies " ntfs_log_error("$LogFile restart area specifies "
"inconsistent file offset.\n"); "inconsistent file offset.\n");
return FALSE; return FALSE;
@ -198,8 +189,7 @@ static BOOL ntfs_check_restart_area( RESTART_PAGE_HEADER *rp )
ca_ofs = le16_to_cpu(ra->client_array_offset); ca_ofs = le16_to_cpu(ra->client_array_offset);
if (((ca_ofs + 7) & ~7) != ca_ofs || if (((ca_ofs + 7) & ~7) != ca_ofs ||
ra_ofs + ca_ofs > (u16)(NTFS_BLOCK_SIZE - ra_ofs + ca_ofs > (u16)(NTFS_BLOCK_SIZE -
sizeof( u16 ) ) ) sizeof(u16))) {
{
ntfs_log_error("$LogFile restart area specifies " ntfs_log_error("$LogFile restart area specifies "
"inconsistent client array offset.\n"); "inconsistent client array offset.\n");
return FALSE; return FALSE;
@ -214,8 +204,7 @@ static BOOL ntfs_check_restart_area( RESTART_PAGE_HEADER *rp )
if ((u32)(ra_ofs + ra_len) > le32_to_cpu(rp->system_page_size) || if ((u32)(ra_ofs + ra_len) > le32_to_cpu(rp->system_page_size) ||
(u32)(ra_ofs + le16_to_cpu(ra->restart_area_length)) > (u32)(ra_ofs + le16_to_cpu(ra->restart_area_length)) >
le32_to_cpu(rp->system_page_size) || le32_to_cpu(rp->system_page_size) ||
ra_len > le16_to_cpu( ra->restart_area_length ) ) ra_len > le16_to_cpu(ra->restart_area_length)) {
{
ntfs_log_error("$LogFile restart area is out of bounds " ntfs_log_error("$LogFile restart area is out of bounds "
"of the system page size specified by the " "of the system page size specified by the "
"restart page header and/or the specified " "restart page header and/or the specified "
@ -232,8 +221,7 @@ static BOOL ntfs_check_restart_area( RESTART_PAGE_HEADER *rp )
le16_to_cpu(ra->log_clients)) || le16_to_cpu(ra->log_clients)) ||
(ra->client_in_use_list != LOGFILE_NO_CLIENT && (ra->client_in_use_list != LOGFILE_NO_CLIENT &&
le16_to_cpu(ra->client_in_use_list) >= le16_to_cpu(ra->client_in_use_list) >=
le16_to_cpu( ra->log_clients ) ) ) le16_to_cpu(ra->log_clients))) {
{
ntfs_log_error("$LogFile restart area specifies " ntfs_log_error("$LogFile restart area specifies "
"overflowing client free and/or in use lists.\n"); "overflowing client free and/or in use lists.\n");
return FALSE; return FALSE;
@ -244,29 +232,25 @@ static BOOL ntfs_check_restart_area( RESTART_PAGE_HEADER *rp )
*/ */
file_size = (u64)sle64_to_cpu(ra->file_size); file_size = (u64)sle64_to_cpu(ra->file_size);
fs_bits = 0; fs_bits = 0;
while ( file_size ) while (file_size) {
{
file_size >>= 1; file_size >>= 1;
fs_bits++; fs_bits++;
} }
if ( le32_to_cpu( ra->seq_number_bits ) != ( u32 )( 67 - fs_bits ) ) if (le32_to_cpu(ra->seq_number_bits) != (u32)(67 - fs_bits)) {
{
ntfs_log_error("$LogFile restart area specifies " ntfs_log_error("$LogFile restart area specifies "
"inconsistent sequence number bits.\n"); "inconsistent sequence number bits.\n");
return FALSE; return FALSE;
} }
/* The log record header length must be a multiple of 8. */ /* The log record header length must be a multiple of 8. */
if (((le16_to_cpu(ra->log_record_header_length) + 7) & ~7) != if (((le16_to_cpu(ra->log_record_header_length) + 7) & ~7) !=
le16_to_cpu( ra->log_record_header_length ) ) le16_to_cpu(ra->log_record_header_length)) {
{
ntfs_log_error("$LogFile restart area specifies " ntfs_log_error("$LogFile restart area specifies "
"inconsistent log record header length.\n"); "inconsistent log record header length.\n");
return FALSE; return FALSE;
} }
/* Ditto for the log page data offset. */ /* Ditto for the log page data offset. */
if (((le16_to_cpu(ra->log_page_data_offset) + 7) & ~7) != if (((le16_to_cpu(ra->log_page_data_offset) + 7) & ~7) !=
le16_to_cpu( ra->log_page_data_offset ) ) le16_to_cpu(ra->log_page_data_offset)) {
{
ntfs_log_error("$LogFile restart area specifies " ntfs_log_error("$LogFile restart area specifies "
"inconsistent log page data offset.\n"); "inconsistent log page data offset.\n");
return FALSE; return FALSE;
@ -313,23 +297,20 @@ static BOOL ntfs_check_log_client_array( RESTART_PAGE_HEADER *rp )
in_free_list = TRUE; in_free_list = TRUE;
check_list: check_list:
for (idx_is_first = TRUE; idx != LOGFILE_NO_CLIENT_CPU; nr_clients--, for (idx_is_first = TRUE; idx != LOGFILE_NO_CLIENT_CPU; nr_clients--,
idx = le16_to_cpu( cr->next_client ) ) idx = le16_to_cpu(cr->next_client)) {
{
if (!nr_clients || idx >= le16_to_cpu(ra->log_clients)) if (!nr_clients || idx >= le16_to_cpu(ra->log_clients))
goto err_out; goto err_out;
/* Set @cr to the current log client record. */ /* Set @cr to the current log client record. */
cr = ca + idx; cr = ca + idx;
/* The first log client record must not have a prev_client. */ /* The first log client record must not have a prev_client. */
if ( idx_is_first ) if (idx_is_first) {
{
if (cr->prev_client != LOGFILE_NO_CLIENT) if (cr->prev_client != LOGFILE_NO_CLIENT)
goto err_out; goto err_out;
idx_is_first = FALSE; idx_is_first = FALSE;
} }
} }
/* Switch to and check the in use list if we just did the free list. */ /* Switch to and check the in use list if we just did the free list. */
if ( in_free_list ) if (in_free_list) {
{
in_free_list = FALSE; in_free_list = FALSE;
idx = le16_to_cpu(ra->client_in_use_list); idx = le16_to_cpu(ra->client_in_use_list);
goto check_list; goto check_list;
@ -378,14 +359,12 @@ static int ntfs_check_and_load_restart_page( ntfs_attr *log_na,
ntfs_log_trace("Entering.\n"); ntfs_log_trace("Entering.\n");
/* Check the restart page header for consistency. */ /* Check the restart page header for consistency. */
if ( !ntfs_check_restart_page_header( rp, pos ) ) if (!ntfs_check_restart_page_header(rp, pos)) {
{
/* Error output already done inside the function. */ /* Error output already done inside the function. */
return EINVAL; return EINVAL;
} }
/* Check the restart area for consistency. */ /* Check the restart area for consistency. */
if ( !ntfs_check_restart_area( rp ) ) if (!ntfs_check_restart_area(rp)) {
{
/* Error output already done inside the function. */ /* Error output already done inside the function. */
return EINVAL; return EINVAL;
} }
@ -406,8 +385,7 @@ static int ntfs_check_and_load_restart_page( ntfs_attr *log_na,
memcpy(trp, rp, le32_to_cpu(rp->system_page_size)); memcpy(trp, rp, le32_to_cpu(rp->system_page_size));
else if (ntfs_attr_pread(log_na, pos, else if (ntfs_attr_pread(log_na, pos,
le32_to_cpu(rp->system_page_size), trp) != le32_to_cpu(rp->system_page_size), trp) !=
le32_to_cpu( rp->system_page_size ) ) le32_to_cpu(rp->system_page_size)) {
{
err = errno; err = errno;
ntfs_log_error("Failed to read whole restart page into the " ntfs_log_error("Failed to read whole restart page into the "
"buffer.\n"); "buffer.\n");
@ -421,8 +399,7 @@ static int ntfs_check_and_load_restart_page( ntfs_attr *log_na,
*/ */
if ((!ntfs_is_chkd_record(trp->magic) || le16_to_cpu(trp->usa_count)) if ((!ntfs_is_chkd_record(trp->magic) || le16_to_cpu(trp->usa_count))
&& ntfs_mst_post_read_fixup((NTFS_RECORD*)trp, && ntfs_mst_post_read_fixup((NTFS_RECORD*)trp,
le32_to_cpu( rp->system_page_size ) ) ) le32_to_cpu(rp->system_page_size))) {
{
/* /*
* A multi sector tranfer error was detected. We only need to * A multi sector tranfer error was detected. We only need to
* abort if the restart page contents exceed the multi sector * abort if the restart page contents exceed the multi sector
@ -430,8 +407,7 @@ static int ntfs_check_and_load_restart_page( ntfs_attr *log_na,
*/ */
if (le16_to_cpu(rp->restart_area_offset) + if (le16_to_cpu(rp->restart_area_offset) +
le16_to_cpu(ra->restart_area_length) > le16_to_cpu(ra->restart_area_length) >
NTFS_BLOCK_SIZE - ( int )sizeof( u16 ) ) NTFS_BLOCK_SIZE - (int)sizeof(u16)) {
{
ntfs_log_error("Multi sector transfer error " ntfs_log_error("Multi sector transfer error "
"detected in $LogFile restart page.\n"); "detected in $LogFile restart page.\n");
err = EINVAL; err = EINVAL;
@ -445,16 +421,13 @@ static int ntfs_check_and_load_restart_page( ntfs_attr *log_na,
*/ */
err = 0; err = 0;
if (ntfs_is_rstr_record(rp->magic) && if (ntfs_is_rstr_record(rp->magic) &&
ra->client_in_use_list != LOGFILE_NO_CLIENT ) ra->client_in_use_list != LOGFILE_NO_CLIENT) {
{ if (!ntfs_check_log_client_array(trp)) {
if ( !ntfs_check_log_client_array( trp ) )
{
err = EINVAL; err = EINVAL;
goto err_out; goto err_out;
} }
} }
if ( lsn ) if (lsn) {
{
if (ntfs_is_rstr_record(rp->magic)) if (ntfs_is_rstr_record(rp->magic))
*lsn = sle64_to_cpu(ra->current_lsn); *lsn = sle64_to_cpu(ra->current_lsn);
else /* if (ntfs_is_chkd_record(rp->magic)) */ else /* if (ntfs_is_chkd_record(rp->magic)) */
@ -463,8 +436,7 @@ static int ntfs_check_and_load_restart_page( ntfs_attr *log_na,
ntfs_log_trace("Done.\n"); ntfs_log_trace("Done.\n");
if (wrp) if (wrp)
*wrp = trp; *wrp = trp;
else else {
{
err_out: err_out:
free(trp); free(trp);
} }
@ -522,8 +494,7 @@ BOOL ntfs_check_logfile( ntfs_attr *log_na, RESTART_PAGE_HEADER **rp )
* pages and the minimum number of log record pages. * pages and the minimum number of log record pages.
*/ */
if (size < log_page_size * 2 || (size - log_page_size * 2) >> if (size < log_page_size * 2 || (size - log_page_size * 2) >>
log_page_bits < MinLogRecordPages ) log_page_bits < MinLogRecordPages) {
{
ntfs_log_error("$LogFile is too small.\n"); ntfs_log_error("$LogFile is too small.\n");
return FALSE; return FALSE;
} }
@ -539,14 +510,12 @@ BOOL ntfs_check_logfile( ntfs_attr *log_na, RESTART_PAGE_HEADER **rp )
* contain empty and uninitialized records, the log file can be assumed * contain empty and uninitialized records, the log file can be assumed
* to be empty. * to be empty.
*/ */
for ( pos = 0; pos < size; pos <<= 1 ) for (pos = 0; pos < size; pos <<= 1) {
{
/* /*
* Read first NTFS_BLOCK_SIZE bytes of potential restart page. * Read first NTFS_BLOCK_SIZE bytes of potential restart page.
*/ */
if (ntfs_attr_pread(log_na, pos, NTFS_BLOCK_SIZE, kaddr) != if (ntfs_attr_pread(log_na, pos, NTFS_BLOCK_SIZE, kaddr) !=
NTFS_BLOCK_SIZE ) NTFS_BLOCK_SIZE) {
{
ntfs_log_error("Failed to read first NTFS_BLOCK_SIZE " ntfs_log_error("Failed to read first NTFS_BLOCK_SIZE "
"bytes of potential restart page.\n"); "bytes of potential restart page.\n");
goto err_out; goto err_out;
@ -569,8 +538,7 @@ BOOL ntfs_check_logfile( ntfs_attr *log_na, RESTART_PAGE_HEADER **rp )
break; break;
/* If not a (modified by chkdsk) restart page, continue. */ /* If not a (modified by chkdsk) restart page, continue. */
if (!ntfs_is_rstr_recordp((le32*)kaddr) && if (!ntfs_is_rstr_recordp((le32*)kaddr) &&
!ntfs_is_chkd_recordp( ( le32* )kaddr ) ) !ntfs_is_chkd_recordp((le32*)kaddr)) {
{
if (!pos) if (!pos)
pos = NTFS_BLOCK_SIZE >> 1; pos = NTFS_BLOCK_SIZE >> 1;
continue; continue;
@ -584,14 +552,12 @@ BOOL ntfs_check_logfile( ntfs_attr *log_na, RESTART_PAGE_HEADER **rp )
(RESTART_PAGE_HEADER*)kaddr, pos, (RESTART_PAGE_HEADER*)kaddr, pos,
!rstr1_ph ? &rstr1_ph : &rstr2_ph, !rstr1_ph ? &rstr1_ph : &rstr2_ph,
!rstr1_ph ? &rstr1_lsn : &rstr2_lsn); !rstr1_ph ? &rstr1_lsn : &rstr2_lsn);
if ( !err ) if (!err) {
{
/* /*
* If we have now found the first (modified by chkdsk) * If we have now found the first (modified by chkdsk)
* restart page, continue looking for the second one. * restart page, continue looking for the second one.
*/ */
if ( !pos ) if (!pos) {
{
pos = NTFS_BLOCK_SIZE >> 1; pos = NTFS_BLOCK_SIZE >> 1;
continue; continue;
} }
@ -612,20 +578,17 @@ BOOL ntfs_check_logfile( ntfs_attr *log_na, RESTART_PAGE_HEADER **rp )
if (!pos) if (!pos)
pos = NTFS_BLOCK_SIZE >> 1; pos = NTFS_BLOCK_SIZE >> 1;
} }
if ( kaddr ) if (kaddr) {
{
free(kaddr); free(kaddr);
kaddr = NULL; kaddr = NULL;
} }
if ( logfile_is_empty ) if (logfile_is_empty) {
{
NVolSetLogFileEmpty(vol); NVolSetLogFileEmpty(vol);
is_empty: is_empty:
ntfs_log_trace("Done. ($LogFile is empty.)\n"); ntfs_log_trace("Done. ($LogFile is empty.)\n");
return TRUE; return TRUE;
} }
if ( !rstr1_ph ) if (!rstr1_ph) {
{
if (rstr2_ph) if (rstr2_ph)
ntfs_log_error("BUG: rstr2_ph isn't NULL!\n"); ntfs_log_error("BUG: rstr2_ph isn't NULL!\n");
ntfs_log_error("Did not find any restart pages in " ntfs_log_error("Did not find any restart pages in "
@ -633,22 +596,18 @@ is_empty:
return FALSE; return FALSE;
} }
/* If both restart pages were found, use the more recent one. */ /* If both restart pages were found, use the more recent one. */
if ( rstr2_ph ) if (rstr2_ph) {
{
/* /*
* If the second restart area is more recent, switch to it. * If the second restart area is more recent, switch to it.
* Otherwise just throw it away. * Otherwise just throw it away.
*/ */
if ( rstr2_lsn > rstr1_lsn ) if (rstr2_lsn > rstr1_lsn) {
{
ntfs_log_debug("Using second restart page as it is more " ntfs_log_debug("Using second restart page as it is more "
"recent.\n"); "recent.\n");
free(rstr1_ph); free(rstr1_ph);
rstr1_ph = rstr2_ph; rstr1_ph = rstr2_ph;
/* rstr1_lsn = rstr2_lsn; */ /* rstr1_lsn = rstr2_lsn; */
} } else {
else
{
ntfs_log_debug("Using first restart page as it is more " ntfs_log_debug("Using first restart page as it is more "
"recent.\n"); "recent.\n");
free(rstr2_ph); free(rstr2_ph);
@ -695,19 +654,16 @@ BOOL ntfs_is_logfile_clean( ntfs_attr *log_na, RESTART_PAGE_HEADER *rp )
ntfs_log_trace("Entering.\n"); ntfs_log_trace("Entering.\n");
/* An empty $LogFile must have been clean before it got emptied. */ /* An empty $LogFile must have been clean before it got emptied. */
if ( NVolLogFileEmpty( log_na->ni->vol ) ) if (NVolLogFileEmpty(log_na->ni->vol)) {
{
ntfs_log_trace("$LogFile is empty\n"); ntfs_log_trace("$LogFile is empty\n");
return TRUE; return TRUE;
} }
if ( !rp ) if (!rp) {
{
ntfs_log_error("Restart page header is NULL\n"); ntfs_log_error("Restart page header is NULL\n");
return FALSE; return FALSE;
} }
if (!ntfs_is_rstr_record(rp->magic) && if (!ntfs_is_rstr_record(rp->magic) &&
!ntfs_is_chkd_record( rp->magic ) ) !ntfs_is_chkd_record(rp->magic)) {
{
ntfs_log_error("Restart page buffer is invalid\n"); ntfs_log_error("Restart page buffer is invalid\n");
return FALSE; return FALSE;
} }
@ -719,8 +675,7 @@ BOOL ntfs_is_logfile_clean( ntfs_attr *log_na, RESTART_PAGE_HEADER *rp )
* we assume there was an unclean shutdown. * we assume there was an unclean shutdown.
*/ */
if (ra->client_in_use_list != LOGFILE_NO_CLIENT && if (ra->client_in_use_list != LOGFILE_NO_CLIENT &&
!( ra->flags & RESTART_VOLUME_IS_CLEAN ) ) !(ra->flags & RESTART_VOLUME_IS_CLEAN)) {
{
ntfs_log_error("The disk contains an unclean file system (%d, " ntfs_log_error("The disk contains an unclean file system (%d, "
"%d).\n", le16_to_cpu(ra->client_in_use_list), "%d).\n", le16_to_cpu(ra->client_in_use_list),
le16_to_cpu(ra->flags)); le16_to_cpu(ra->flags));
@ -752,8 +707,7 @@ int ntfs_empty_logfile( ntfs_attr *na )
if (NVolLogFileEmpty(na->ni->vol)) if (NVolLogFileEmpty(na->ni->vol))
return 0; return 0;
if ( !NAttrNonResident( na ) ) if (!NAttrNonResident(na)) {
{
errno = EIO; errno = EIO;
ntfs_log_perror("Resident $LogFile $DATA attribute"); ntfs_log_perror("Resident $LogFile $DATA attribute");
return -1; return -1;
@ -762,15 +716,13 @@ int ntfs_empty_logfile( ntfs_attr *na )
memset(buf, -1, NTFS_BUF_SIZE); memset(buf, -1, NTFS_BUF_SIZE);
pos = 0; pos = 0;
while ( ( count = na->data_size - pos ) > 0 ) while ((count = na->data_size - pos) > 0) {
{
if (count > NTFS_BUF_SIZE) if (count > NTFS_BUF_SIZE)
count = NTFS_BUF_SIZE; count = NTFS_BUF_SIZE;
count = ntfs_attr_pwrite(na, pos, count, buf); count = ntfs_attr_pwrite(na, pos, count, buf);
if ( count <= 0 ) if (count <= 0) {
{
ntfs_log_perror("Failed to reset $LogFile"); ntfs_log_perror("Failed to reset $LogFile");
if (count != -1) if (count != -1)
errno = EIO; errno = EIO;

View File

@ -61,12 +61,10 @@
* *
* Begins the restart area. * Begins the restart area.
*/ */
typedef struct typedef struct {
{
/*Ofs*/ /*Ofs*/
/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ /* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
/* 0*/ /* 0*/ NTFS_RECORD_TYPES magic;/* The magic is "RSTR". */
NTFS_RECORD_TYPES magic;/* The magic is "RSTR". */
/* 4*/ le16 usa_ofs; /* See NTFS_RECORD definition in layout.h. /* 4*/ le16 usa_ofs; /* See NTFS_RECORD definition in layout.h.
When creating, set this to be immediately When creating, set this to be immediately
after this header structure (without any after this header structure (without any
@ -110,8 +108,7 @@ typedef struct
* These are the so far known RESTART_AREA_* flags (16-bit) which contain * These are the so far known RESTART_AREA_* flags (16-bit) which contain
* information about the log file in which they are present. * information about the log file in which they are present.
*/ */
enum enum {
{
RESTART_VOLUME_IS_CLEAN = const_cpu_to_le16(0x0002), RESTART_VOLUME_IS_CLEAN = const_cpu_to_le16(0x0002),
RESTART_SPACE_FILLER = 0xffff, /* gcc: Force enum bit width to 16. */ RESTART_SPACE_FILLER = 0xffff, /* gcc: Force enum bit width to 16. */
} __attribute__((__packed__)); } __attribute__((__packed__));
@ -125,11 +122,9 @@ typedef le16 RESTART_AREA_FLAGS;
* RESTART_PAGE_HEADER to the restart_area_offset value found in it. * RESTART_PAGE_HEADER to the restart_area_offset value found in it.
* See notes at restart_area_offset above. * See notes at restart_area_offset above.
*/ */
typedef struct typedef struct {
{
/*Ofs*/ /*Ofs*/
/* 0*/ /* 0*/ leLSN current_lsn; /* The current, i.e. last LSN inside the log
leLSN current_lsn; /* The current, i.e. last LSN inside the log
when the restart area was last written. when the restart area was last written.
This happens often but what is the interval? This happens often but what is the interval?
Is it just fixed time or is it every time a Is it just fixed time or is it every time a
@ -267,11 +262,9 @@ typedef struct
* The offset of this record is found by adding the offset of the * The offset of this record is found by adding the offset of the
* RESTART_AREA to the client_array_offset value found in it. * RESTART_AREA to the client_array_offset value found in it.
*/ */
typedef struct typedef struct {
{
/*Ofs*/ /*Ofs*/
/* 0*/ /* 0*/ leLSN oldest_lsn; /* Oldest LSN needed by this client. On create
leLSN oldest_lsn; /* Oldest LSN needed by this client. On create
set to 0. */ set to 0. */
/* 8*/ leLSN client_restart_lsn;/* LSN at which this client needs to restart /* 8*/ leLSN client_restart_lsn;/* LSN at which this client needs to restart
the volume, i.e. the current position within the volume, i.e. the current position within
@ -312,8 +305,7 @@ typedef struct
* following update sequence array and then aligned to 8 byte boundary, but is * following update sequence array and then aligned to 8 byte boundary, but is
* this specified anywhere?). * this specified anywhere?).
*/ */
typedef struct typedef struct {
{
/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ /* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
NTFS_RECORD_TYPES magic;/* Usually the magic is "RCRD". */ NTFS_RECORD_TYPES magic;/* Usually the magic is "RCRD". */
u16 usa_ofs; /* See NTFS_RECORD definition in layout.h. u16 usa_ofs; /* See NTFS_RECORD definition in layout.h.
@ -322,18 +314,15 @@ typedef struct
alignment). */ alignment). */
u16 usa_count; /* See NTFS_RECORD definition in layout.h. */ u16 usa_count; /* See NTFS_RECORD definition in layout.h. */
union union {
{
LSN last_lsn; LSN last_lsn;
s64 file_offset; s64 file_offset;
} __attribute__((__packed__)) copy; } __attribute__((__packed__)) copy;
u32 flags; u32 flags;
u16 page_count; u16 page_count;
u16 page_position; u16 page_position;
union union {
{ struct {
struct
{
u16 next_record_offset; u16 next_record_offset;
u8 reserved[6]; u8 reserved[6];
LSN last_end_lsn; LSN last_end_lsn;
@ -346,8 +335,7 @@ typedef struct
* *
* (Or is it log record pages?) * (Or is it log record pages?)
*/ */
typedef enum typedef enum {
{
LOG_RECORD_MULTI_PAGE = const_cpu_to_le16(0x0001), /* ??? */ LOG_RECORD_MULTI_PAGE = const_cpu_to_le16(0x0001), /* ??? */
LOG_RECORD_SIZE_PLACE_HOLDER = 0xffff, LOG_RECORD_SIZE_PLACE_HOLDER = 0xffff,
/* This has nothing to do with the log record. It is only so /* This has nothing to do with the log record. It is only so
@ -357,8 +345,7 @@ typedef enum
/** /**
* struct LOG_CLIENT_ID - The log client id structure identifying a log client. * struct LOG_CLIENT_ID - The log client id structure identifying a log client.
*/ */
typedef struct typedef struct {
{
u16 seq_number; u16 seq_number;
u16 client_index; u16 client_index;
} __attribute__((__packed__)) LOG_CLIENT_ID; } __attribute__((__packed__)) LOG_CLIENT_ID;
@ -368,8 +355,7 @@ typedef struct
* *
* Each log record seems to have a constant size of 0x70 bytes. * Each log record seems to have a constant size of 0x70 bytes.
*/ */
typedef struct typedef struct {
{
LSN this_lsn; LSN this_lsn;
LSN client_previous_lsn; LSN client_previous_lsn;
LSN client_undo_next_lsn; LSN client_undo_next_lsn;
@ -395,8 +381,7 @@ typedef struct
u32 alignment_or_reserved; u32 alignment_or_reserved;
VCN target_vcn; VCN target_vcn;
/* Now at ofs 0x50. */ /* Now at ofs 0x50. */
struct struct { /* Only present if lcns_to_follow
{ /* Only present if lcns_to_follow
is not 0. */ is not 0. */
LCN lcn; LCN lcn;
} __attribute__((__packed__)) lcn_list[0]; } __attribute__((__packed__)) lcn_list[0];

View File

@ -67,8 +67,7 @@ static int tab;
* @flags: Flags which affect the output style * @flags: Flags which affect the output style
* @handler: Function to perform the actual logging * @handler: Function to perform the actual logging
*/ */
struct ntfs_logging struct ntfs_logging {
{
u32 levels; u32 levels;
u32 flags; u32 flags;
ntfs_log_handler *handler BROKEN_GCC_FORMAT_ATTRIBUTE; ntfs_log_handler *handler BROKEN_GCC_FORMAT_ATTRIBUTE;
@ -78,8 +77,7 @@ struct ntfs_logging
* ntfs_log * ntfs_log
* This struct controls all the logging within the library and tools. * This struct controls all the logging within the library and tools.
*/ */
static struct ntfs_logging ntfs_log = static struct ntfs_logging ntfs_log = {
{
#ifdef DEBUG #ifdef DEBUG
NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE | NTFS_LOG_LEVEL_ENTER | NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE | NTFS_LOG_LEVEL_ENTER |
NTFS_LOG_LEVEL_LEAVE | NTFS_LOG_LEVEL_LEAVE |
@ -203,8 +201,7 @@ static FILE * ntfs_log_get_stream( u32 level )
{ {
FILE *stream; FILE *stream;
switch ( level ) switch (level) {
{
case NTFS_LOG_LEVEL_INFO: case NTFS_LOG_LEVEL_INFO:
case NTFS_LOG_LEVEL_QUIET: case NTFS_LOG_LEVEL_QUIET:
case NTFS_LOG_LEVEL_PROGRESS: case NTFS_LOG_LEVEL_PROGRESS:
@ -240,8 +237,7 @@ static const char * ntfs_log_get_prefix( u32 level )
{ {
const char *prefix; const char *prefix;
switch ( level ) switch (level) {
{
case NTFS_LOG_LEVEL_DEBUG: case NTFS_LOG_LEVEL_DEBUG:
prefix = "DEBUG: "; prefix = "DEBUG: ";
break; break;
@ -290,15 +286,13 @@ static const char * ntfs_log_get_prefix( u32 level )
*/ */
void ntfs_log_set_handler(ntfs_log_handler *handler) void ntfs_log_set_handler(ntfs_log_handler *handler)
{ {
if ( handler ) if (handler) {
{
ntfs_log.handler = handler; ntfs_log.handler = handler;
#ifdef HAVE_SYSLOG_H #ifdef HAVE_SYSLOG_H
if (handler == ntfs_log_handler_syslog) if (handler == ntfs_log_handler_syslog)
openlog("ntfs-3g", LOG_PID, LOG_USER); openlog("ntfs-3g", LOG_PID, LOG_USER);
#endif #endif
} } else
else
ntfs_log.handler = ntfs_log_handler_null; ntfs_log.handler = ntfs_log_handler_null;
} }
@ -375,15 +369,13 @@ int ntfs_log_handler_syslog( const char *function __attribute__( ( unused ) ),
return 1; return 1;
#endif #endif
ret = vsnprintf(logbuf, LOG_LINE_LEN, format, args); ret = vsnprintf(logbuf, LOG_LINE_LEN, format, args);
if ( ret < 0 ) if (ret < 0) {
{
vsyslog(LOG_NOTICE, format, args); vsyslog(LOG_NOTICE, format, args);
ret = 1; ret = 1;
goto out; goto out;
} }
if ( ( LOG_LINE_LEN > ret + 3 ) && ( level & NTFS_LOG_LEVEL_PERROR ) ) if ((LOG_LINE_LEN > ret + 3) && (level & NTFS_LOG_LEVEL_PERROR)) {
{
strncat(logbuf, ": ", LOG_LINE_LEN - ret - 1); strncat(logbuf, ": ", LOG_LINE_LEN - ret - 1);
strncat(logbuf, strerror(olderr), LOG_LINE_LEN - (ret + 3)); strncat(logbuf, strerror(olderr), LOG_LINE_LEN - (ret + 3));
ret = strlen(logbuf); ret = strlen(logbuf);
@ -432,8 +424,7 @@ int ntfs_log_handler_fprintf( const char *function, const char *file,
stream = (FILE*)data; stream = (FILE*)data;
#ifdef DEBUG #ifdef DEBUG
if ( level == NTFS_LOG_LEVEL_LEAVE ) if (level == NTFS_LOG_LEVEL_LEAVE) {
{
if (tab) if (tab)
tab--; tab--;
return 0; return 0;
@ -602,23 +593,16 @@ int ntfs_log_handler_stderr( const char *function, const char *file,
*/ */
BOOL ntfs_log_parse_option(const char *option) BOOL ntfs_log_parse_option(const char *option)
{ {
if ( strcmp( option, "--log-debug" ) == 0 ) if (strcmp(option, "--log-debug") == 0) {
{
ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG); ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG);
return TRUE; return TRUE;
} } else if (strcmp(option, "--log-verbose") == 0) {
else if ( strcmp( option, "--log-verbose" ) == 0 )
{
ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE); ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
return TRUE; return TRUE;
} } else if (strcmp(option, "--log-quiet") == 0) {
else if ( strcmp( option, "--log-quiet" ) == 0 )
{
ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET); ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
return TRUE; return TRUE;
} } else if (strcmp(option, "--log-trace") == 0) {
else if ( strcmp( option, "--log-trace" ) == 0 )
{
ntfs_log_set_levels(NTFS_LOG_LEVEL_TRACE); ntfs_log_set_levels(NTFS_LOG_LEVEL_TRACE);
return TRUE; return TRUE;
} }

View File

@ -24,13 +24,11 @@
#include <malloc.h> #include <malloc.h>
static inline void* ntfs_alloc ( size_t size ) static inline void* ntfs_alloc (size_t size) {
{
return malloc(size); return malloc(size);
} }
static inline void* ntfs_align ( size_t size ) static inline void* ntfs_align (size_t size) {
{
#ifdef __wii__ #ifdef __wii__
return memalign(32, size); return memalign(32, size);
#else #else
@ -38,8 +36,7 @@ static inline void* ntfs_align ( size_t size )
#endif #endif
} }
static inline void ntfs_free ( void* mem ) static inline void ntfs_free (void* mem) {
{
free(mem); free(mem);
} }

View File

@ -86,8 +86,7 @@ int ntfs_mft_records_read( const ntfs_volume *vol, const MFT_REF mref,
ntfs_log_trace("inode %llu\n", (unsigned long long)MREF(mref)); ntfs_log_trace("inode %llu\n", (unsigned long long)MREF(mref));
if ( !vol || !vol->mft_na || !b || count < 0 ) if (!vol || !vol->mft_na || !b || count < 0) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s: b=%p count=%lld mft=%llu", __FUNCTION__, ntfs_log_perror("%s: b=%p count=%lld mft=%llu", __FUNCTION__,
b, (long long)count, (unsigned long long)MREF(mref)); b, (long long)count, (unsigned long long)MREF(mref));
@ -96,8 +95,7 @@ int ntfs_mft_records_read( const ntfs_volume *vol, const MFT_REF mref,
m = MREF(mref); m = MREF(mref);
/* Refuse to read non-allocated mft records. */ /* Refuse to read non-allocated mft records. */
if (m + count > vol->mft_na->initialized_size >> if (m + count > vol->mft_na->initialized_size >>
vol->mft_record_size_bits ) vol->mft_record_size_bits) {
{
errno = ESPIPE; errno = ESPIPE;
ntfs_log_perror("Trying to read non-allocated mft records " ntfs_log_perror("Trying to read non-allocated mft records "
"(%lld > %lld)", (long long)m + count, "(%lld > %lld)", (long long)m + count,
@ -107,8 +105,7 @@ int ntfs_mft_records_read( const ntfs_volume *vol, const MFT_REF mref,
} }
br = ntfs_attr_mst_pread(vol->mft_na, m << vol->mft_record_size_bits, br = ntfs_attr_mst_pread(vol->mft_na, m << vol->mft_record_size_bits,
count, vol->mft_record_size, b); count, vol->mft_record_size, b);
if ( br != count ) if (br != count) {
{
if (br != -1) if (br != -1)
errno = EIO; errno = EIO;
ntfs_log_perror("Failed to read of MFT, mft=%llu count=%lld " ntfs_log_perror("Failed to read of MFT, mft=%llu count=%lld "
@ -151,16 +148,14 @@ int ntfs_mft_records_write( const ntfs_volume *vol, const MFT_REF mref,
void *bmirr = NULL; void *bmirr = NULL;
int cnt = 0, res = 0; int cnt = 0, res = 0;
if ( !vol || !vol->mft_na || vol->mftmirr_size <= 0 || !b || count < 0 ) if (!vol || !vol->mft_na || vol->mftmirr_size <= 0 || !b || count < 0) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
m = MREF(mref); m = MREF(mref);
/* Refuse to write non-allocated mft records. */ /* Refuse to write non-allocated mft records. */
if (m + count > vol->mft_na->initialized_size >> if (m + count > vol->mft_na->initialized_size >>
vol->mft_record_size_bits ) vol->mft_record_size_bits) {
{
errno = ESPIPE; errno = ESPIPE;
ntfs_log_perror("Trying to write non-allocated mft records " ntfs_log_perror("Trying to write non-allocated mft records "
"(%lld > %lld)", (long long)m + count, "(%lld > %lld)", (long long)m + count,
@ -168,10 +163,8 @@ int ntfs_mft_records_write( const ntfs_volume *vol, const MFT_REF mref,
vol->mft_record_size_bits); vol->mft_record_size_bits);
return -1; return -1;
} }
if ( m < vol->mftmirr_size ) if (m < vol->mftmirr_size) {
{ if (!vol->mftmirr_na) {
if ( !vol->mftmirr_na )
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@ -185,8 +178,7 @@ int ntfs_mft_records_write( const ntfs_volume *vol, const MFT_REF mref,
} }
bw = ntfs_attr_mst_pwrite(vol->mft_na, m << vol->mft_record_size_bits, bw = ntfs_attr_mst_pwrite(vol->mft_na, m << vol->mft_record_size_bits,
count, vol->mft_record_size, b); count, vol->mft_record_size, b);
if ( bw != count ) if (bw != count) {
{
if (bw != -1) if (bw != -1)
errno = EIO; errno = EIO;
if (bw >= 0) if (bw >= 0)
@ -196,15 +188,13 @@ int ntfs_mft_records_write( const ntfs_volume *vol, const MFT_REF mref,
ntfs_log_perror("Error writing $Mft record(s)"); ntfs_log_perror("Error writing $Mft record(s)");
res = errno; res = errno;
} }
if ( bmirr && bw > 0 ) if (bmirr && bw > 0) {
{
if (bw < cnt) if (bw < cnt)
cnt = bw; cnt = bw;
bw = ntfs_attr_mst_pwrite(vol->mftmirr_na, bw = ntfs_attr_mst_pwrite(vol->mftmirr_na,
m << vol->mft_record_size_bits, cnt, m << vol->mft_record_size_bits, cnt,
vol->mft_record_size, bmirr); vol->mft_record_size, bmirr);
if ( bw != cnt ) if (bw != cnt) {
{
if (bw != -1) if (bw != -1)
errno = EIO; errno = EIO;
ntfs_log_debug("Error: failed to sync $MFTMirr! Run " ntfs_log_debug("Error: failed to sync $MFTMirr! Run "
@ -225,15 +215,13 @@ int ntfs_mft_record_check( const ntfs_volume *vol, const MFT_REF mref,
ATTR_RECORD *a; ATTR_RECORD *a;
int ret = -1; int ret = -1;
if ( !ntfs_is_file_record( m->magic ) ) if (!ntfs_is_file_record(m->magic)) {
{
ntfs_log_error("Record %llu has no FILE magic (0x%x)\n", ntfs_log_error("Record %llu has no FILE magic (0x%x)\n",
(unsigned long long)MREF(mref), *(le32 *)m); (unsigned long long)MREF(mref), *(le32 *)m);
goto err_out; goto err_out;
} }
if ( le32_to_cpu( m->bytes_allocated ) != vol->mft_record_size ) if (le32_to_cpu(m->bytes_allocated) != vol->mft_record_size) {
{
ntfs_log_error("Record %llu has corrupt allocation size " ntfs_log_error("Record %llu has corrupt allocation size "
"(%u <> %u)\n", (unsigned long long)MREF(mref), "(%u <> %u)\n", (unsigned long long)MREF(mref),
vol->mft_record_size, vol->mft_record_size,
@ -242,8 +230,7 @@ int ntfs_mft_record_check( const ntfs_volume *vol, const MFT_REF mref,
} }
a = (ATTR_RECORD *)((char *)m + le16_to_cpu(m->attrs_offset)); a = (ATTR_RECORD *)((char *)m + le16_to_cpu(m->attrs_offset));
if ( p2n( a ) < p2n( m ) || ( char * )a > ( char * )m + vol->mft_record_size ) if (p2n(a) < p2n(m) || (char *)a > (char *)m + vol->mft_record_size) {
{
ntfs_log_error("Record %llu is corrupt\n", ntfs_log_error("Record %llu is corrupt\n",
(unsigned long long)MREF(mref)); (unsigned long long)MREF(mref));
goto err_out; goto err_out;
@ -292,16 +279,14 @@ int ntfs_file_record_read( const ntfs_volume *vol, const MFT_REF mref,
{ {
MFT_RECORD *m; MFT_RECORD *m;
if ( !vol || !mrec ) if (!vol || !mrec) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s: mrec=%p", __FUNCTION__, mrec); ntfs_log_perror("%s: mrec=%p", __FUNCTION__, mrec);
return -1; return -1;
} }
m = *mrec; m = *mrec;
if ( !m ) if (!m) {
{
m = ntfs_malloc(vol->mft_record_size); m = ntfs_malloc(vol->mft_record_size);
if (!m) if (!m)
return -1; return -1;
@ -312,8 +297,7 @@ int ntfs_file_record_read( const ntfs_volume *vol, const MFT_REF mref,
if (ntfs_mft_record_check(vol, mref, m)) if (ntfs_mft_record_check(vol, mref, m))
goto err_out; goto err_out;
if ( MSEQNO( mref ) && MSEQNO( mref ) != le16_to_cpu( m->sequence_number ) ) if (MSEQNO(mref) && MSEQNO(mref) != le16_to_cpu(m->sequence_number)) {
{
ntfs_log_error("Record %llu has wrong SeqNo (%d <> %d)\n", ntfs_log_error("Record %llu has wrong SeqNo (%d <> %d)\n",
(unsigned long long)MREF(mref), MSEQNO(mref), (unsigned long long)MREF(mref), MSEQNO(mref),
le16_to_cpu(m->sequence_number)); le16_to_cpu(m->sequence_number));
@ -348,8 +332,7 @@ int ntfs_mft_record_layout( const ntfs_volume *vol, const MFT_REF mref,
{ {
ATTR_RECORD *a; ATTR_RECORD *a;
if ( !vol || !mrec ) if (!vol || !mrec) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s: mrec=%p", __FUNCTION__, mrec); ntfs_log_perror("%s: mrec=%p", __FUNCTION__, mrec);
return -1; return -1;
@ -357,11 +340,9 @@ int ntfs_mft_record_layout( const ntfs_volume *vol, const MFT_REF mref,
/* Aligned to 2-byte boundary. */ /* Aligned to 2-byte boundary. */
if (vol->major_ver < 3 || (vol->major_ver == 3 && !vol->minor_ver)) if (vol->major_ver < 3 || (vol->major_ver == 3 && !vol->minor_ver))
mrec->usa_ofs = cpu_to_le16((sizeof(MFT_RECORD_OLD) + 1) & ~1); mrec->usa_ofs = cpu_to_le16((sizeof(MFT_RECORD_OLD) + 1) & ~1);
else else {
{
/* Abort if mref is > 32 bits. */ /* Abort if mref is > 32 bits. */
if ( MREF( mref ) & 0x0000ffff00000000ull ) if (MREF(mref) & 0x0000ffff00000000ull) {
{
errno = ERANGE; errno = ERANGE;
ntfs_log_perror("Mft reference exceeds 32 bits"); ntfs_log_perror("Mft reference exceeds 32 bits");
return -1; return -1;
@ -378,8 +359,7 @@ int ntfs_mft_record_layout( const ntfs_volume *vol, const MFT_REF mref,
if (vol->mft_record_size >= NTFS_BLOCK_SIZE) if (vol->mft_record_size >= NTFS_BLOCK_SIZE)
mrec->usa_count = cpu_to_le16(vol->mft_record_size / mrec->usa_count = cpu_to_le16(vol->mft_record_size /
NTFS_BLOCK_SIZE + 1); NTFS_BLOCK_SIZE + 1);
else else {
{
mrec->usa_count = cpu_to_le16(1); mrec->usa_count = cpu_to_le16(1);
ntfs_log_error("Sector size is bigger than MFT record size. " ntfs_log_error("Sector size is bigger than MFT record size. "
"Setting usa_count to 1. If Windows chkdsk " "Setting usa_count to 1. If Windows chkdsk "
@ -522,19 +502,16 @@ static int ntfs_mft_bitmap_find_free_rec( ntfs_volume *vol, ntfs_inode *base_ni
data_pos = base_ni->mft_no + 1; data_pos = base_ni->mft_no + 1;
if (data_pos < RESERVED_MFT_RECORDS) if (data_pos < RESERVED_MFT_RECORDS)
data_pos = RESERVED_MFT_RECORDS; data_pos = RESERVED_MFT_RECORDS;
if ( data_pos >= pass_end ) if (data_pos >= pass_end) {
{
data_pos = RESERVED_MFT_RECORDS; data_pos = RESERVED_MFT_RECORDS;
pass = 2; pass = 2;
/* This happens on a freshly formatted volume. */ /* This happens on a freshly formatted volume. */
if ( data_pos >= pass_end ) if (data_pos >= pass_end) {
{
errno = ENOSPC; errno = ENOSPC;
goto leave; goto leave;
} }
} }
if ( ntfs_is_mft( base_ni ) ) if (ntfs_is_mft(base_ni)) {
{
data_pos = 0; data_pos = 0;
pass = 2; pass = 2;
} }
@ -552,24 +529,21 @@ static int ntfs_mft_bitmap_find_free_rec( ntfs_volume *vol, ntfs_inode *base_ni
b = 0; b = 0;
#endif #endif
/* Loop until a free mft record is found. */ /* Loop until a free mft record is found. */
for ( ; pass <= 2; size = PAGE_SIZE ) for (; pass <= 2; size = PAGE_SIZE) {
{
/* Cap size to pass_end. */ /* Cap size to pass_end. */
ofs = data_pos >> 3; ofs = data_pos >> 3;
ll = ((pass_end + 7) >> 3) - ofs; ll = ((pass_end + 7) >> 3) - ofs;
if (size > ll) if (size > ll)
size = ll; size = ll;
ll = ntfs_attr_pread(mftbmp_na, ofs, size, buf); ll = ntfs_attr_pread(mftbmp_na, ofs, size, buf);
if ( ll < 0 ) if (ll < 0) {
{
ntfs_log_perror("Failed to read $MFT bitmap"); ntfs_log_perror("Failed to read $MFT bitmap");
free(buf); free(buf);
goto leave; goto leave;
} }
ntfs_log_debug("Read 0x%llx bytes.\n", (long long)ll); ntfs_log_debug("Read 0x%llx bytes.\n", (long long)ll);
/* If we read at least one byte, search @buf for a zero bit. */ /* If we read at least one byte, search @buf for a zero bit. */
if ( ll ) if (ll) {
{
size = ll << 3; size = ll << 3;
bit = data_pos & 7; bit = data_pos & 7;
data_pos &= ~7ull; data_pos &= ~7ull;
@ -579,8 +553,7 @@ static int ntfs_mft_bitmap_find_free_rec( ntfs_volume *vol, ntfs_inode *base_ni
(long long)data_pos, (long long)bit, (long long)data_pos, (long long)bit,
byte ? *byte : -1, b); byte ? *byte : -1, b);
for (; bit < size && data_pos + bit < pass_end; for (; bit < size && data_pos + bit < pass_end;
bit &= ~7ull, bit += 8 ) bit &= ~7ull, bit += 8) {
{
/* /*
* If we're extending $MFT and running out of the first * If we're extending $MFT and running out of the first
* mft record (base record) then give up searching since * mft record (base record) then give up searching since
@ -595,8 +568,7 @@ static int ntfs_mft_bitmap_find_free_rec( ntfs_volume *vol, ntfs_inode *base_ni
/* Note: ffz() result must be zero based. */ /* Note: ffz() result must be zero based. */
b = ntfs_ffz((unsigned long)*byte); b = ntfs_ffz((unsigned long)*byte);
if ( b < 8 && b >= ( bit & 7 ) ) if (b < 8 && b >= (bit & 7)) {
{
free(buf); free(buf);
ret = data_pos + (bit & ~7ull) + b; ret = data_pos + (bit & ~7ull) + b;
goto leave; goto leave;
@ -617,8 +589,7 @@ static int ntfs_mft_bitmap_find_free_rec( ntfs_volume *vol, ntfs_inode *base_ni
} }
/* Do the next pass. */ /* Do the next pass. */
pass++; pass++;
if ( pass == 2 ) if (pass == 2) {
{
/* /*
* Starting the second pass, in which we scan the first * Starting the second pass, in which we scan the first
* part of the zone which we omitted earlier. * part of the zone which we omitted earlier.
@ -646,10 +617,8 @@ static int ntfs_mft_attr_extend( ntfs_attr *na )
int ret = STATUS_ERROR; int ret = STATUS_ERROR;
ntfs_log_enter("Entering\n"); ntfs_log_enter("Entering\n");
if ( !NInoAttrList( na->ni ) ) if (!NInoAttrList(na->ni)) {
{ if (ntfs_inode_add_attrlist(na->ni)) {
if ( ntfs_inode_add_attrlist( na->ni ) )
{
ntfs_log_perror("%s: Can not add attrlist #3", __FUNCTION__); ntfs_log_perror("%s: Can not add attrlist #3", __FUNCTION__);
goto out; goto out;
} }
@ -658,8 +627,7 @@ static int ntfs_mft_attr_extend( ntfs_attr *na )
goto out; goto out;
} }
if ( ntfs_attr_update_mapping_pairs( na, 0 ) ) if (ntfs_attr_update_mapping_pairs(na, 0)) {
{
ntfs_log_perror("%s: MP update failed", __FUNCTION__); ntfs_log_perror("%s: MP update failed", __FUNCTION__);
goto out; goto out;
} }
@ -695,8 +663,7 @@ static int ntfs_mft_bitmap_extend_allocation_i( ntfs_volume *vol )
*/ */
rl = ntfs_attr_find_vcn(mftbmp_na, (mftbmp_na->allocated_size - 1) >> rl = ntfs_attr_find_vcn(mftbmp_na, (mftbmp_na->allocated_size - 1) >>
vol->cluster_size_bits); vol->cluster_size_bits);
if ( !rl || !rl->length || rl->lcn < 0 ) if (!rl || !rl->length || rl->lcn < 0) {
{
ntfs_log_error("Failed to determine last allocated " ntfs_log_error("Failed to determine last allocated "
"cluster of mft bitmap attribute.\n"); "cluster of mft bitmap attribute.\n");
if (rl) if (rl)
@ -706,15 +673,13 @@ static int ntfs_mft_bitmap_extend_allocation_i( ntfs_volume *vol )
lcn = rl->lcn + rl->length; lcn = rl->lcn + rl->length;
rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE); rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE);
if ( !rl2 ) if (!rl2) {
{
ntfs_log_error("Failed to allocate a cluster for " ntfs_log_error("Failed to allocate a cluster for "
"the mft bitmap.\n"); "the mft bitmap.\n");
return STATUS_ERROR; return STATUS_ERROR;
} }
rl = ntfs_runlists_merge(mftbmp_na->rl, rl2); rl = ntfs_runlists_merge(mftbmp_na->rl, rl2);
if ( !rl ) if (!rl) {
{
err = errno; err = errno;
ntfs_log_error("Failed to merge runlists for mft " ntfs_log_error("Failed to merge runlists for mft "
"bitmap.\n"); "bitmap.\n");
@ -739,8 +704,7 @@ static int ntfs_mft_bitmap_extend_allocation_i( ntfs_volume *vol )
goto undo_alloc; goto undo_alloc;
if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name, if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name,
mftbmp_na->name_len, 0, rl[1].vcn, NULL, 0, ctx ) ) mftbmp_na->name_len, 0, rl[1].vcn, NULL, 0, ctx)) {
{
ntfs_log_error("Failed to find last attribute extent of " ntfs_log_error("Failed to find last attribute extent of "
"mft bitmap attribute.\n"); "mft bitmap attribute.\n");
goto undo_alloc; goto undo_alloc;
@ -749,8 +713,7 @@ static int ntfs_mft_bitmap_extend_allocation_i( ntfs_volume *vol )
a = ctx->attr; a = ctx->attr;
ll = sle64_to_cpu(a->lowest_vcn); ll = sle64_to_cpu(a->lowest_vcn);
rl2 = ntfs_attr_find_vcn(mftbmp_na, ll); rl2 = ntfs_attr_find_vcn(mftbmp_na, ll);
if ( !rl2 || !rl2->length ) if (!rl2 || !rl2->length) {
{
ntfs_log_error("Failed to determine previous last " ntfs_log_error("Failed to determine previous last "
"allocated cluster of mft bitmap attribute.\n"); "allocated cluster of mft bitmap attribute.\n");
if (rl2) if (rl2)
@ -759,8 +722,7 @@ static int ntfs_mft_bitmap_extend_allocation_i( ntfs_volume *vol )
} }
/* Get the size for the new mapping pairs array for this extent. */ /* Get the size for the new mapping pairs array for this extent. */
mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, INT_MAX); mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, INT_MAX);
if ( mp_size <= 0 ) if (mp_size <= 0) {
{
ntfs_log_error("Get size for mapping pairs failed for " ntfs_log_error("Get size for mapping pairs failed for "
"mft bitmap attribute extent.\n"); "mft bitmap attribute extent.\n");
goto undo_alloc; goto undo_alloc;
@ -768,14 +730,12 @@ static int ntfs_mft_bitmap_extend_allocation_i( ntfs_volume *vol )
/* Expand the attribute record if necessary. */ /* Expand the attribute record if necessary. */
old_alen = le32_to_cpu(a->length); old_alen = le32_to_cpu(a->length);
if (ntfs_attr_record_resize(m, a, mp_size + if (ntfs_attr_record_resize(m, a, mp_size +
le16_to_cpu( a->mapping_pairs_offset ) ) ) le16_to_cpu(a->mapping_pairs_offset))) {
{
ntfs_log_info("extending $MFT bitmap\n"); ntfs_log_info("extending $MFT bitmap\n");
ret = ntfs_mft_attr_extend(vol->mftbmp_na); ret = ntfs_mft_attr_extend(vol->mftbmp_na);
if (ret == STATUS_OK) if (ret == STATUS_OK)
goto ok; goto ok;
if ( ret == STATUS_ERROR ) if (ret == STATUS_ERROR) {
{
ntfs_log_perror("%s: ntfs_mft_attr_extend failed", __FUNCTION__); ntfs_log_perror("%s: ntfs_mft_attr_extend failed", __FUNCTION__);
update_mp = TRUE; update_mp = TRUE;
} }
@ -785,8 +745,7 @@ static int ntfs_mft_bitmap_extend_allocation_i( ntfs_volume *vol )
/* Generate the mapping pairs array directly into the attr record. */ /* Generate the mapping pairs array directly into the attr record. */
if (ntfs_mapping_pairs_build(vol, (u8*)a + if (ntfs_mapping_pairs_build(vol, (u8*)a +
le16_to_cpu(a->mapping_pairs_offset), mp_size, rl2, ll, le16_to_cpu(a->mapping_pairs_offset), mp_size, rl2, ll,
NULL ) ) NULL)) {
{
ntfs_log_error("Failed to build mapping pairs array for " ntfs_log_error("Failed to build mapping pairs array for "
"mft bitmap attribute.\n"); "mft bitmap attribute.\n");
errno = EIO; errno = EIO;
@ -798,8 +757,7 @@ static int ntfs_mft_bitmap_extend_allocation_i( ntfs_volume *vol )
* We now have extended the mft bitmap allocated_size by one cluster. * We now have extended the mft bitmap allocated_size by one cluster.
* Reflect this in the ntfs_attr structure and the attribute record. * Reflect this in the ntfs_attr structure and the attribute record.
*/ */
if ( a->lowest_vcn ) if (a->lowest_vcn) {
{
/* /*
* We are not in the first attribute extent, switch to it, but * We are not in the first attribute extent, switch to it, but
* first ensure the changes will make it to disk later. * first ensure the changes will make it to disk later.
@ -807,8 +765,7 @@ static int ntfs_mft_bitmap_extend_allocation_i( ntfs_volume *vol )
ntfs_inode_mark_dirty(ctx->ntfs_ino); ntfs_inode_mark_dirty(ctx->ntfs_ino);
ntfs_attr_reinit_search_ctx(ctx); ntfs_attr_reinit_search_ctx(ctx);
if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name, if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name,
mftbmp_na->name_len, 0, 0, NULL, 0, ctx ) ) mftbmp_na->name_len, 0, 0, NULL, 0, ctx)) {
{
ntfs_log_error("Failed to find first attribute " ntfs_log_error("Failed to find first attribute "
"extent of mft bitmap attribute.\n"); "extent of mft bitmap attribute.\n");
goto restore_undo_alloc; goto restore_undo_alloc;
@ -827,8 +784,7 @@ restore_undo_alloc:
err = errno; err = errno;
ntfs_attr_reinit_search_ctx(ctx); ntfs_attr_reinit_search_ctx(ctx);
if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name, if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name,
mftbmp_na->name_len, 0, rl[1].vcn, NULL, 0, ctx ) ) mftbmp_na->name_len, 0, rl[1].vcn, NULL, 0, ctx)) {
{
ntfs_log_error("Failed to find last attribute extent of " ntfs_log_error("Failed to find last attribute extent of "
"mft bitmap attribute.%s\n", es); "mft bitmap attribute.%s\n", es);
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
@ -857,8 +813,7 @@ undo_alloc:
ntfs_log_error("Failed to free cluster.%s\n", es); ntfs_log_error("Failed to free cluster.%s\n", es);
else else
vol->free_clusters++; vol->free_clusters++;
if ( mp_rebuilt ) if (mp_rebuilt) {
{
if (ntfs_mapping_pairs_build(vol, (u8*)a + if (ntfs_mapping_pairs_build(vol, (u8*)a +
le16_to_cpu(a->mapping_pairs_offset), le16_to_cpu(a->mapping_pairs_offset),
old_alen - le16_to_cpu(a->mapping_pairs_offset), old_alen - le16_to_cpu(a->mapping_pairs_offset),
@ -870,8 +825,7 @@ undo_alloc:
"record.%s\n", es); "record.%s\n", es);
ntfs_inode_mark_dirty(ctx->ntfs_ino); ntfs_inode_mark_dirty(ctx->ntfs_ino);
} }
if ( update_mp ) if (update_mp) {
{
if (ntfs_attr_update_mapping_pairs(vol->mftbmp_na, 0)) if (ntfs_attr_update_mapping_pairs(vol->mftbmp_na, 0))
ntfs_log_perror("%s: MP update failed", __FUNCTION__); ntfs_log_perror("%s: MP update failed", __FUNCTION__);
} }
@ -930,8 +884,7 @@ static int ntfs_mft_bitmap_extend_initialized( ntfs_volume *vol )
goto out; goto out;
if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name, if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name,
mftbmp_na->name_len, 0, 0, NULL, 0, ctx ) ) mftbmp_na->name_len, 0, 0, NULL, 0, ctx)) {
{
ntfs_log_error("Failed to find first attribute extent of " ntfs_log_error("Failed to find first attribute extent of "
"mft bitmap attribute.\n"); "mft bitmap attribute.\n");
err = errno; err = errno;
@ -942,8 +895,7 @@ static int ntfs_mft_bitmap_extend_initialized( ntfs_volume *vol )
old_initialized_size = mftbmp_na->initialized_size; old_initialized_size = mftbmp_na->initialized_size;
mftbmp_na->initialized_size += 8; mftbmp_na->initialized_size += 8;
a->initialized_size = cpu_to_sle64(mftbmp_na->initialized_size); a->initialized_size = cpu_to_sle64(mftbmp_na->initialized_size);
if ( mftbmp_na->initialized_size > mftbmp_na->data_size ) if (mftbmp_na->initialized_size > mftbmp_na->data_size) {
{
mftbmp_na->data_size = mftbmp_na->initialized_size; mftbmp_na->data_size = mftbmp_na->initialized_size;
a->data_size = cpu_to_sle64(mftbmp_na->data_size); a->data_size = cpu_to_sle64(mftbmp_na->data_size);
} }
@ -953,8 +905,7 @@ static int ntfs_mft_bitmap_extend_initialized( ntfs_volume *vol )
/* Initialize the mft bitmap attribute value with zeroes. */ /* Initialize the mft bitmap attribute value with zeroes. */
ll = 0; ll = 0;
ll = ntfs_attr_pwrite(mftbmp_na, old_initialized_size, 8, &ll); ll = ntfs_attr_pwrite(mftbmp_na, old_initialized_size, 8, &ll);
if ( ll == 8 ) if (ll == 8) {
{
ntfs_log_debug("Wrote eight initialized bytes to mft bitmap.\n"); ntfs_log_debug("Wrote eight initialized bytes to mft bitmap.\n");
vol->free_mft_records += (8 * 8); vol->free_mft_records += (8 * 8);
ret = 0; ret = 0;
@ -970,8 +921,7 @@ static int ntfs_mft_bitmap_extend_initialized( ntfs_volume *vol )
goto err_out; goto err_out;
if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name, if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name,
mftbmp_na->name_len, 0, 0, NULL, 0, ctx ) ) mftbmp_na->name_len, 0, 0, NULL, 0, ctx)) {
{
ntfs_log_error("Failed to find first attribute extent of " ntfs_log_error("Failed to find first attribute extent of "
"mft bitmap attribute.%s\n", es); "mft bitmap attribute.%s\n", es);
put_err_out: put_err_out:
@ -981,8 +931,7 @@ put_err_out:
a = ctx->attr; a = ctx->attr;
mftbmp_na->initialized_size = old_initialized_size; mftbmp_na->initialized_size = old_initialized_size;
a->initialized_size = cpu_to_sle64(old_initialized_size); a->initialized_size = cpu_to_sle64(old_initialized_size);
if ( mftbmp_na->data_size != old_data_size ) if (mftbmp_na->data_size != old_data_size) {
{
mftbmp_na->data_size = old_data_size; mftbmp_na->data_size = old_data_size;
a->data_size = cpu_to_sle64(old_data_size); a->data_size = cpu_to_sle64(old_data_size);
} }
@ -1040,8 +989,7 @@ static int ntfs_mft_data_extend_allocation( ntfs_volume *vol )
rl = ntfs_attr_find_vcn(mft_na, rl = ntfs_attr_find_vcn(mft_na,
(mft_na->allocated_size - 1) >> vol->cluster_size_bits); (mft_na->allocated_size - 1) >> vol->cluster_size_bits);
if ( !rl || !rl->length || rl->lcn < 0 ) if (!rl || !rl->length || rl->lcn < 0) {
{
ntfs_log_error("Failed to determine last allocated " ntfs_log_error("Failed to determine last allocated "
"cluster of mft data attribute.\n"); "cluster of mft data attribute.\n");
if (rl) if (rl)
@ -1061,13 +1009,11 @@ static int ntfs_mft_data_extend_allocation( ntfs_volume *vol )
nr = min_nr; nr = min_nr;
old_last_vcn = rl[1].vcn; old_last_vcn = rl[1].vcn;
do do {
{
rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE); rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE);
if (rl2) if (rl2)
break; break;
if ( errno != ENOSPC || nr == min_nr ) if (errno != ENOSPC || nr == min_nr) {
{
ntfs_log_perror("Failed to allocate (%lld) clusters " ntfs_log_perror("Failed to allocate (%lld) clusters "
"for $MFT", (long long)nr); "for $MFT", (long long)nr);
goto out; goto out;
@ -1080,14 +1026,12 @@ static int ntfs_mft_data_extend_allocation( ntfs_volume *vol )
nr = min_nr; nr = min_nr;
ntfs_log_debug("Retrying mft data allocation with minimal cluster " ntfs_log_debug("Retrying mft data allocation with minimal cluster "
"count %lli.\n", (long long)nr); "count %lli.\n", (long long)nr);
} } while (1);
while ( 1 );
ntfs_log_debug("Allocated %lld clusters.\n", (long long)nr); ntfs_log_debug("Allocated %lld clusters.\n", (long long)nr);
rl = ntfs_runlists_merge(mft_na->rl, rl2); rl = ntfs_runlists_merge(mft_na->rl, rl2);
if ( !rl ) if (!rl) {
{
err = errno; err = errno;
ntfs_log_error("Failed to merge runlists for mft data " ntfs_log_error("Failed to merge runlists for mft data "
"attribute.\n"); "attribute.\n");
@ -1109,8 +1053,7 @@ static int ntfs_mft_data_extend_allocation( ntfs_volume *vol )
goto undo_alloc; goto undo_alloc;
if (ntfs_attr_lookup(mft_na->type, mft_na->name, mft_na->name_len, 0, if (ntfs_attr_lookup(mft_na->type, mft_na->name, mft_na->name_len, 0,
rl[1].vcn, NULL, 0, ctx ) ) rl[1].vcn, NULL, 0, ctx)) {
{
ntfs_log_error("Failed to find last attribute extent of " ntfs_log_error("Failed to find last attribute extent of "
"mft data attribute.\n"); "mft data attribute.\n");
goto undo_alloc; goto undo_alloc;
@ -1119,8 +1062,7 @@ static int ntfs_mft_data_extend_allocation( ntfs_volume *vol )
a = ctx->attr; a = ctx->attr;
ll = sle64_to_cpu(a->lowest_vcn); ll = sle64_to_cpu(a->lowest_vcn);
rl2 = ntfs_attr_find_vcn(mft_na, ll); rl2 = ntfs_attr_find_vcn(mft_na, ll);
if ( !rl2 || !rl2->length ) if (!rl2 || !rl2->length) {
{
ntfs_log_error("Failed to determine previous last " ntfs_log_error("Failed to determine previous last "
"allocated cluster of mft data attribute.\n"); "allocated cluster of mft data attribute.\n");
if (rl2) if (rl2)
@ -1129,8 +1071,7 @@ static int ntfs_mft_data_extend_allocation( ntfs_volume *vol )
} }
/* Get the size for the new mapping pairs array for this extent. */ /* Get the size for the new mapping pairs array for this extent. */
mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, INT_MAX); mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, INT_MAX);
if ( mp_size <= 0 ) if (mp_size <= 0) {
{
ntfs_log_error("Get size for mapping pairs failed for " ntfs_log_error("Get size for mapping pairs failed for "
"mft data attribute extent.\n"); "mft data attribute extent.\n");
goto undo_alloc; goto undo_alloc;
@ -1138,13 +1079,11 @@ static int ntfs_mft_data_extend_allocation( ntfs_volume *vol )
/* Expand the attribute record if necessary. */ /* Expand the attribute record if necessary. */
old_alen = le32_to_cpu(a->length); old_alen = le32_to_cpu(a->length);
if (ntfs_attr_record_resize(m, a, if (ntfs_attr_record_resize(m, a,
mp_size + le16_to_cpu( a->mapping_pairs_offset ) ) ) mp_size + le16_to_cpu(a->mapping_pairs_offset))) {
{
ret = ntfs_mft_attr_extend(vol->mft_na); ret = ntfs_mft_attr_extend(vol->mft_na);
if (ret == STATUS_OK) if (ret == STATUS_OK)
goto ok; goto ok;
if ( ret == STATUS_ERROR ) if (ret == STATUS_ERROR) {
{
ntfs_log_perror("%s: ntfs_mft_attr_extend failed", __FUNCTION__); ntfs_log_perror("%s: ntfs_mft_attr_extend failed", __FUNCTION__);
update_mp = TRUE; update_mp = TRUE;
} }
@ -1156,8 +1095,7 @@ static int ntfs_mft_data_extend_allocation( ntfs_volume *vol )
*/ */
if (ntfs_mapping_pairs_build(vol, if (ntfs_mapping_pairs_build(vol,
(u8*)a + le16_to_cpu(a->mapping_pairs_offset), mp_size, (u8*)a + le16_to_cpu(a->mapping_pairs_offset), mp_size,
rl2, ll, NULL ) ) rl2, ll, NULL)) {
{
ntfs_log_error("Failed to build mapping pairs array of " ntfs_log_error("Failed to build mapping pairs array of "
"mft data attribute.\n"); "mft data attribute.\n");
errno = EIO; errno = EIO;
@ -1171,8 +1109,7 @@ static int ntfs_mft_data_extend_allocation( ntfs_volume *vol )
* @rl is the last (non-terminator) runlist element of mft data * @rl is the last (non-terminator) runlist element of mft data
* attribute. * attribute.
*/ */
if ( a->lowest_vcn ) if (a->lowest_vcn) {
{
/* /*
* We are not in the first attribute extent, switch to it, but * We are not in the first attribute extent, switch to it, but
* first ensure the changes will make it to disk later. * first ensure the changes will make it to disk later.
@ -1180,8 +1117,7 @@ static int ntfs_mft_data_extend_allocation( ntfs_volume *vol )
ntfs_inode_mark_dirty(ctx->ntfs_ino); ntfs_inode_mark_dirty(ctx->ntfs_ino);
ntfs_attr_reinit_search_ctx(ctx); ntfs_attr_reinit_search_ctx(ctx);
if (ntfs_attr_lookup(mft_na->type, mft_na->name, if (ntfs_attr_lookup(mft_na->type, mft_na->name,
mft_na->name_len, 0, 0, NULL, 0, ctx ) ) mft_na->name_len, 0, 0, NULL, 0, ctx)) {
{
ntfs_log_error("Failed to find first attribute " ntfs_log_error("Failed to find first attribute "
"extent of mft data attribute.\n"); "extent of mft data attribute.\n");
goto restore_undo_alloc; goto restore_undo_alloc;
@ -1203,8 +1139,7 @@ restore_undo_alloc:
err = errno; err = errno;
ntfs_attr_reinit_search_ctx(ctx); ntfs_attr_reinit_search_ctx(ctx);
if (ntfs_attr_lookup(mft_na->type, mft_na->name, mft_na->name_len, 0, if (ntfs_attr_lookup(mft_na->type, mft_na->name, mft_na->name_len, 0,
rl[1].vcn, NULL, 0, ctx ) ) rl[1].vcn, NULL, 0, ctx)) {
{
ntfs_log_error("Failed to find last attribute extent of " ntfs_log_error("Failed to find last attribute extent of "
"mft data attribute.%s\n", es); "mft data attribute.%s\n", es);
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
@ -1229,8 +1164,7 @@ undo_alloc:
if (ntfs_rl_truncate(&mft_na->rl, old_last_vcn)) if (ntfs_rl_truncate(&mft_na->rl, old_last_vcn))
ntfs_log_error("Failed to truncate mft data attribute " ntfs_log_error("Failed to truncate mft data attribute "
"runlist.%s\n", es); "runlist.%s\n", es);
if ( mp_rebuilt ) if (mp_rebuilt) {
{
if (ntfs_mapping_pairs_build(vol, (u8*)a + if (ntfs_mapping_pairs_build(vol, (u8*)a +
le16_to_cpu(a->mapping_pairs_offset), le16_to_cpu(a->mapping_pairs_offset),
old_alen - le16_to_cpu(a->mapping_pairs_offset), old_alen - le16_to_cpu(a->mapping_pairs_offset),
@ -1242,8 +1176,7 @@ undo_alloc:
"record.%s\n", es); "record.%s\n", es);
ntfs_inode_mark_dirty(ctx->ntfs_ino); ntfs_inode_mark_dirty(ctx->ntfs_ino);
} }
if ( update_mp ) if (update_mp) {
{
if (ntfs_attr_update_mapping_pairs(vol->mft_na, 0)) if (ntfs_attr_update_mapping_pairs(vol->mft_na, 0))
ntfs_log_perror("%s: MP update failed", __FUNCTION__); ntfs_log_perror("%s: MP update failed", __FUNCTION__);
} }
@ -1280,8 +1213,7 @@ static int ntfs_mft_record_init( ntfs_volume *vol, s64 size )
(long long)mft_na->allocated_size, (long long)mft_na->allocated_size,
(long long)mft_na->data_size, (long long)mft_na->data_size,
(long long)mft_na->initialized_size); (long long)mft_na->initialized_size);
while ( size > mft_na->allocated_size ) while (size > mft_na->allocated_size) {
{
if (ntfs_mft_data_extend_allocation(vol) == STATUS_ERROR) if (ntfs_mft_data_extend_allocation(vol) == STATUS_ERROR)
goto out; goto out;
ntfs_log_debug("Status of mft data after allocation extension: " ntfs_log_debug("Status of mft data after allocation extension: "
@ -1302,15 +1234,13 @@ static int ntfs_mft_record_init( ntfs_volume *vol, s64 size )
* needed by ntfs_mft_record_format(). We will update the attribute * needed by ntfs_mft_record_format(). We will update the attribute
* record itself in one fell swoop later on. * record itself in one fell swoop later on.
*/ */
while ( size > mft_na->initialized_size ) while (size > mft_na->initialized_size) {
{
s64 ll2 = mft_na->initialized_size >> vol->mft_record_size_bits; s64 ll2 = mft_na->initialized_size >> vol->mft_record_size_bits;
mft_na->initialized_size += vol->mft_record_size; mft_na->initialized_size += vol->mft_record_size;
if (mft_na->initialized_size > mft_na->data_size) if (mft_na->initialized_size > mft_na->data_size)
mft_na->data_size = mft_na->initialized_size; mft_na->data_size = mft_na->initialized_size;
ntfs_log_debug("Initializing mft record 0x%llx.\n", (long long)ll2); ntfs_log_debug("Initializing mft record 0x%llx.\n", (long long)ll2);
if ( ntfs_mft_record_format( vol, ll2 ) < 0 ) if (ntfs_mft_record_format(vol, ll2) < 0) {
{
ntfs_log_perror("Failed to format mft record"); ntfs_log_perror("Failed to format mft record");
goto undo_data_init; goto undo_data_init;
} }
@ -1322,8 +1252,7 @@ static int ntfs_mft_record_init( ntfs_volume *vol, s64 size )
goto undo_data_init; goto undo_data_init;
if (ntfs_attr_lookup(mft_na->type, mft_na->name, mft_na->name_len, 0, if (ntfs_attr_lookup(mft_na->type, mft_na->name, mft_na->name_len, 0,
0, NULL, 0, ctx ) ) 0, NULL, 0, ctx)) {
{
ntfs_log_error("Failed to find first attribute extent of " ntfs_log_error("Failed to find first attribute extent of "
"mft data attribute.\n"); "mft data attribute.\n");
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
@ -1375,8 +1304,7 @@ static int ntfs_mft_rec_init( ntfs_volume *vol, s64 size )
mft_na = vol->mft_na; mft_na = vol->mft_na;
mftbmp_na = vol->mftbmp_na; mftbmp_na = vol->mftbmp_na;
if ( size > mft_na->allocated_size || size > mft_na->initialized_size ) if (size > mft_na->allocated_size || size > mft_na->initialized_size) {
{
errno = EIO; errno = EIO;
ntfs_log_perror("%s: unexpected $MFT sizes, see below", __FUNCTION__); ntfs_log_perror("%s: unexpected $MFT sizes, see below", __FUNCTION__);
ntfs_log_error("$MFT: size=%lld allocated_size=%lld " ntfs_log_error("$MFT: size=%lld allocated_size=%lld "
@ -1397,8 +1325,7 @@ static int ntfs_mft_rec_init( ntfs_volume *vol, s64 size )
goto undo_data_init; goto undo_data_init;
if (ntfs_attr_lookup(mft_na->type, mft_na->name, mft_na->name_len, 0, if (ntfs_attr_lookup(mft_na->type, mft_na->name, mft_na->name_len, 0,
0, NULL, 0, ctx ) ) 0, NULL, 0, ctx)) {
{
ntfs_log_error("Failed to find first attribute extent of " ntfs_log_error("Failed to find first attribute extent of "
"mft data attribute.\n"); "mft data attribute.\n");
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
@ -1457,8 +1384,7 @@ static ntfs_inode *ntfs_mft_rec_alloc( ntfs_volume *vol )
goto err_out; goto err_out;
found_free_rec: found_free_rec:
if ( ntfs_bitmap_set_bit( mftbmp_na, bit ) ) if (ntfs_bitmap_set_bit(mftbmp_na, bit)) {
{
ntfs_log_error("Failed to allocate bit in mft bitmap #2\n"); ntfs_log_error("Failed to allocate bit in mft bitmap #2\n");
goto err_out; goto err_out;
} }
@ -1477,14 +1403,12 @@ found_free_rec:
if (!m) if (!m)
goto undo_mftbmp_alloc; goto undo_mftbmp_alloc;
if ( ntfs_mft_record_read( vol, bit, m ) ) if (ntfs_mft_record_read(vol, bit, m)) {
{
free(m); free(m);
goto undo_mftbmp_alloc; goto undo_mftbmp_alloc;
} }
/* Sanity check that the mft record is really not in use. */ /* Sanity check that the mft record is really not in use. */
if ( ntfs_is_file_record( m->magic ) && ( m->flags & MFT_RECORD_IN_USE ) ) if (ntfs_is_file_record(m->magic) && (m->flags & MFT_RECORD_IN_USE)) {
{
ntfs_log_error("Inode %lld is used but it wasn't marked in " ntfs_log_error("Inode %lld is used but it wasn't marked in "
"$MFT bitmap. Fixed.\n", (long long)bit); "$MFT bitmap. Fixed.\n", (long long)bit);
free(m); free(m);
@ -1493,8 +1417,7 @@ found_free_rec:
seq_no = m->sequence_number; seq_no = m->sequence_number;
usn = *(le16*)((u8*)m + le16_to_cpu(m->usa_ofs)); usn = *(le16*)((u8*)m + le16_to_cpu(m->usa_ofs));
if ( ntfs_mft_record_layout( vol, bit, m ) ) if (ntfs_mft_record_layout(vol, bit, m)) {
{
ntfs_log_error("Failed to re-format mft record.\n"); ntfs_log_error("Failed to re-format mft record.\n");
free(m); free(m);
goto undo_mftbmp_alloc; goto undo_mftbmp_alloc;
@ -1508,8 +1431,7 @@ found_free_rec:
m->flags |= MFT_RECORD_IN_USE; m->flags |= MFT_RECORD_IN_USE;
/* Now need to open an ntfs inode for the mft record. */ /* Now need to open an ntfs inode for the mft record. */
ni = ntfs_inode_allocate(vol); ni = ntfs_inode_allocate(vol);
if ( !ni ) if (!ni) {
{
ntfs_log_error("Failed to allocate buffer for inode.\n"); ntfs_log_error("Failed to allocate buffer for inode.\n");
free(m); free(m);
goto undo_mftbmp_alloc; goto undo_mftbmp_alloc;
@ -1529,21 +1451,18 @@ found_free_rec:
* Attach the extent inode to the base inode, reallocating * Attach the extent inode to the base inode, reallocating
* memory if needed. * memory if needed.
*/ */
if ( !( base_ni->nr_extents & 3 ) ) if (!(base_ni->nr_extents & 3)) {
{
ntfs_inode **extent_nis; ntfs_inode **extent_nis;
int i; int i;
i = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *); i = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *);
extent_nis = ntfs_malloc(i); extent_nis = ntfs_malloc(i);
if ( !extent_nis ) if (!extent_nis) {
{
free(m); free(m);
free(ni); free(ni);
goto undo_mftbmp_alloc; goto undo_mftbmp_alloc;
} }
if ( base_ni->nr_extents ) if (base_ni->nr_extents) {
{
memcpy(extent_nis, base_ni->extent_nis, memcpy(extent_nis, base_ni->extent_nis,
i - 4 * sizeof(ntfs_inode *)); i - 4 * sizeof(ntfs_inode *));
free(base_ni->extent_nis); free(base_ni->extent_nis);
@ -1680,14 +1599,12 @@ ntfs_inode *ntfs_mft_record_alloc( ntfs_volume *vol, ntfs_inode *base_ni )
(long long)base_ni->mft_no); (long long)base_ni->mft_no);
else else
ntfs_log_enter("Entering (allocating a base mft record)\n"); ntfs_log_enter("Entering (allocating a base mft record)\n");
if ( !vol || !vol->mft_na || !vol->mftbmp_na ) if (!vol || !vol->mft_na || !vol->mftbmp_na) {
{
errno = EINVAL; errno = EINVAL;
goto out; goto out;
} }
if ( ntfs_is_mft( base_ni ) ) if (ntfs_is_mft(base_ni)) {
{
ni = ntfs_mft_rec_alloc(vol); ni = ntfs_mft_rec_alloc(vol);
goto out; goto out;
} }
@ -1696,8 +1613,7 @@ ntfs_inode *ntfs_mft_record_alloc( ntfs_volume *vol, ntfs_inode *base_ni )
mftbmp_na = vol->mftbmp_na; mftbmp_na = vol->mftbmp_na;
retry: retry:
bit = ntfs_mft_bitmap_find_free_rec(vol, base_ni); bit = ntfs_mft_bitmap_find_free_rec(vol, base_ni);
if ( bit >= 0 ) if (bit >= 0) {
{
ntfs_log_debug("found free record (#1) at %lld\n", ntfs_log_debug("found free record (#1) at %lld\n",
(long long)bit); (long long)bit);
goto found_free_rec; goto found_free_rec;
@ -1714,8 +1630,7 @@ retry:
*/ */
ll = mft_na->initialized_size >> vol->mft_record_size_bits; ll = mft_na->initialized_size >> vol->mft_record_size_bits;
if (mftbmp_na->initialized_size << 3 > ll && if (mftbmp_na->initialized_size << 3 > ll &&
mftbmp_na->initialized_size > RESERVED_MFT_RECORDS / 8 ) mftbmp_na->initialized_size > RESERVED_MFT_RECORDS / 8) {
{
bit = ll; bit = ll;
if (bit < RESERVED_MFT_RECORDS) if (bit < RESERVED_MFT_RECORDS)
bit = RESERVED_MFT_RECORDS; bit = RESERVED_MFT_RECORDS;
@ -1733,15 +1648,13 @@ retry:
(long long)mftbmp_na->allocated_size, (long long)mftbmp_na->allocated_size,
(long long)mftbmp_na->data_size, (long long)mftbmp_na->data_size,
(long long)mftbmp_na->initialized_size); (long long)mftbmp_na->initialized_size);
if ( mftbmp_na->initialized_size + 8 > mftbmp_na->allocated_size ) if (mftbmp_na->initialized_size + 8 > mftbmp_na->allocated_size) {
{
int ret = ntfs_mft_bitmap_extend_allocation(vol); int ret = ntfs_mft_bitmap_extend_allocation(vol);
if (ret == STATUS_ERROR) if (ret == STATUS_ERROR)
goto err_out; goto err_out;
if ( ret == STATUS_KEEP_SEARCHING ) if (ret == STATUS_KEEP_SEARCHING) {
{
ret = ntfs_mft_bitmap_extend_allocation(vol); ret = ntfs_mft_bitmap_extend_allocation(vol);
if (ret != STATUS_OK) if (ret != STATUS_OK)
goto err_out; goto err_out;
@ -1771,8 +1684,7 @@ retry:
ntfs_log_debug("found free record (#3) at %lld\n", (long long)bit); ntfs_log_debug("found free record (#3) at %lld\n", (long long)bit);
found_free_rec: found_free_rec:
/* @bit is the found free mft record, allocate it in the mft bitmap. */ /* @bit is the found free mft record, allocate it in the mft bitmap. */
if ( ntfs_bitmap_set_bit( mftbmp_na, bit ) ) if (ntfs_bitmap_set_bit(mftbmp_na, bit)) {
{
ntfs_log_error("Failed to allocate bit in mft bitmap.\n"); ntfs_log_error("Failed to allocate bit in mft bitmap.\n");
goto err_out; goto err_out;
} }
@ -1793,14 +1705,12 @@ found_free_rec:
if (!m) if (!m)
goto undo_mftbmp_alloc; goto undo_mftbmp_alloc;
if ( ntfs_mft_record_read( vol, bit, m ) ) if (ntfs_mft_record_read(vol, bit, m)) {
{
free(m); free(m);
goto undo_mftbmp_alloc; goto undo_mftbmp_alloc;
} }
/* Sanity check that the mft record is really not in use. */ /* Sanity check that the mft record is really not in use. */
if ( ntfs_is_file_record( m->magic ) && ( m->flags & MFT_RECORD_IN_USE ) ) if (ntfs_is_file_record(m->magic) && (m->flags & MFT_RECORD_IN_USE)) {
{
ntfs_log_error("Inode %lld is used but it wasn't marked in " ntfs_log_error("Inode %lld is used but it wasn't marked in "
"$MFT bitmap. Fixed.\n", (long long)bit); "$MFT bitmap. Fixed.\n", (long long)bit);
free(m); free(m);
@ -1808,8 +1718,7 @@ found_free_rec:
} }
seq_no = m->sequence_number; seq_no = m->sequence_number;
usn = *(le16*)((u8*)m + le16_to_cpu(m->usa_ofs)); usn = *(le16*)((u8*)m + le16_to_cpu(m->usa_ofs));
if ( ntfs_mft_record_layout( vol, bit, m ) ) if (ntfs_mft_record_layout(vol, bit, m)) {
{
ntfs_log_error("Failed to re-format mft record.\n"); ntfs_log_error("Failed to re-format mft record.\n");
free(m); free(m);
goto undo_mftbmp_alloc; goto undo_mftbmp_alloc;
@ -1823,8 +1732,7 @@ found_free_rec:
m->flags |= MFT_RECORD_IN_USE; m->flags |= MFT_RECORD_IN_USE;
/* Now need to open an ntfs inode for the mft record. */ /* Now need to open an ntfs inode for the mft record. */
ni = ntfs_inode_allocate(vol); ni = ntfs_inode_allocate(vol);
if ( !ni ) if (!ni) {
{
ntfs_log_error("Failed to allocate buffer for inode.\n"); ntfs_log_error("Failed to allocate buffer for inode.\n");
free(m); free(m);
goto undo_mftbmp_alloc; goto undo_mftbmp_alloc;
@ -1836,8 +1744,7 @@ found_free_rec:
* extent inode and attach it to the base inode. Also, set the base * extent inode and attach it to the base inode. Also, set the base
* mft record reference in the extent inode. * mft record reference in the extent inode.
*/ */
if ( base_ni ) if (base_ni) {
{
ni->nr_extents = -1; ni->nr_extents = -1;
ni->base_ni = base_ni; ni->base_ni = base_ni;
m->base_mft_record = MK_LE_MREF(base_ni->mft_no, m->base_mft_record = MK_LE_MREF(base_ni->mft_no,
@ -1846,21 +1753,18 @@ found_free_rec:
* Attach the extent inode to the base inode, reallocating * Attach the extent inode to the base inode, reallocating
* memory if needed. * memory if needed.
*/ */
if ( !( base_ni->nr_extents & 3 ) ) if (!(base_ni->nr_extents & 3)) {
{
ntfs_inode **extent_nis; ntfs_inode **extent_nis;
int i; int i;
i = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *); i = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *);
extent_nis = ntfs_malloc(i); extent_nis = ntfs_malloc(i);
if ( !extent_nis ) if (!extent_nis) {
{
free(m); free(m);
free(ni); free(ni);
goto undo_mftbmp_alloc; goto undo_mftbmp_alloc;
} }
if ( base_ni->nr_extents ) if (base_ni->nr_extents) {
{
memcpy(extent_nis, base_ni->extent_nis, memcpy(extent_nis, base_ni->extent_nis,
i - 4 * sizeof(ntfs_inode *)); i - 4 * sizeof(ntfs_inode *));
free(base_ni->extent_nis); free(base_ni->extent_nis);
@ -1920,8 +1824,7 @@ int ntfs_mft_record_free( ntfs_volume *vol, ntfs_inode *ni )
ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no);
if ( !vol || !vol->mftbmp_na || !ni ) if (!vol || !vol->mftbmp_na || !ni) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@ -1943,15 +1846,13 @@ int ntfs_mft_record_free( ntfs_volume *vol, ntfs_inode *ni )
/* Set the inode dirty and write it out. */ /* Set the inode dirty and write it out. */
ntfs_inode_mark_dirty(ni); ntfs_inode_mark_dirty(ni);
if ( ntfs_inode_sync( ni ) ) if (ntfs_inode_sync(ni)) {
{
err = errno; err = errno;
goto sync_rollback; goto sync_rollback;
} }
/* Clear the bit in the $MFT/$BITMAP corresponding to this record. */ /* Clear the bit in the $MFT/$BITMAP corresponding to this record. */
if ( ntfs_bitmap_clear_bit( vol->mftbmp_na, mft_no ) ) if (ntfs_bitmap_clear_bit(vol->mftbmp_na, mft_no)) {
{
err = errno; err = errno;
// FIXME: If ntfs_bitmap_clear_run() guarantees rollback on // FIXME: If ntfs_bitmap_clear_run() guarantees rollback on
// error, this could be changed to goto sync_rollback; // error, this could be changed to goto sync_rollback;
@ -1960,11 +1861,9 @@ int ntfs_mft_record_free( ntfs_volume *vol, ntfs_inode *ni )
/* Throw away the now freed inode. */ /* Throw away the now freed inode. */
#if CACHE_NIDATA_SIZE #if CACHE_NIDATA_SIZE
if ( !ntfs_inode_real_close( ni ) ) if (!ntfs_inode_real_close(ni)) {
{
#else #else
if ( !ntfs_inode_close( ni ) ) if (!ntfs_inode_close(ni)) {
{
#endif #endif
vol->free_mft_records++; vol->free_mft_records++;
return 0; return 0;
@ -1995,8 +1894,7 @@ int ntfs_mft_usn_dec( MFT_RECORD *mrec )
u16 usn; u16 usn;
le16 *usnp; le16 *usnp;
if ( !mrec ) if (!mrec) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }

View File

@ -61,8 +61,7 @@ int ntfs_mst_post_read_fixup( NTFS_RECORD *b, const u32 size )
/* Size and alignment checks. */ /* Size and alignment checks. */
if (size & (NTFS_BLOCK_SIZE - 1) || usa_ofs & 1 || if (size & (NTFS_BLOCK_SIZE - 1) || usa_ofs & 1 ||
(u32)(usa_ofs + (usa_count * 2)) > size || (u32)(usa_ofs + (usa_count * 2)) > size ||
( size >> NTFS_BLOCK_SIZE_BITS ) != usa_count ) (size >> NTFS_BLOCK_SIZE_BITS) != usa_count) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s: magic: 0x%08x size: %d usa_ofs: %d " ntfs_log_perror("%s: magic: 0x%08x size: %d usa_ofs: %d "
"usa_count: %d", __FUNCTION__, *(le32 *)b, "usa_count: %d", __FUNCTION__, *(le32 *)b,
@ -86,10 +85,8 @@ int ntfs_mst_post_read_fixup( NTFS_RECORD *b, const u32 size )
/* /*
* Check for incomplete multi sector transfer(s). * Check for incomplete multi sector transfer(s).
*/ */
while ( usa_count-- ) while (usa_count--) {
{ if (*data_pos != usn) {
if ( *data_pos != usn )
{
/* /*
* Incomplete multi sector transfer detected! )-: * Incomplete multi sector transfer detected! )-:
* Set the magic to "BAAD" and return failure. * Set the magic to "BAAD" and return failure.
@ -109,8 +106,7 @@ int ntfs_mst_post_read_fixup( NTFS_RECORD *b, const u32 size )
usa_count = le16_to_cpu(b->usa_count) - 1; usa_count = le16_to_cpu(b->usa_count) - 1;
data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1; data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
/* Fixup all sectors. */ /* Fixup all sectors. */
while ( usa_count-- ) while (usa_count--) {
{
/* /*
* Increment position in usa and restore original data from * Increment position in usa and restore original data from
* the usa into the data buffer. * the usa into the data buffer.
@ -151,8 +147,7 @@ int ntfs_mst_pre_write_fixup( NTFS_RECORD *b, const u32 size )
/* Sanity check + only fixup if it makes sense. */ /* Sanity check + only fixup if it makes sense. */
if (!b || ntfs_is_baad_record(b->magic) || if (!b || ntfs_is_baad_record(b->magic) ||
ntfs_is_hole_record( b->magic ) ) ntfs_is_hole_record(b->magic)) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s: bad argument", __FUNCTION__); ntfs_log_perror("%s: bad argument", __FUNCTION__);
return -1; return -1;
@ -164,8 +159,7 @@ int ntfs_mst_pre_write_fixup( NTFS_RECORD *b, const u32 size )
/* Size and alignment checks. */ /* Size and alignment checks. */
if (size & (NTFS_BLOCK_SIZE - 1) || usa_ofs & 1 || if (size & (NTFS_BLOCK_SIZE - 1) || usa_ofs & 1 ||
(u32)(usa_ofs + (usa_count * 2)) > size || (u32)(usa_ofs + (usa_count * 2)) > size ||
( size >> NTFS_BLOCK_SIZE_BITS ) != usa_count ) (size >> NTFS_BLOCK_SIZE_BITS) != usa_count) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s", __FUNCTION__); ntfs_log_perror("%s", __FUNCTION__);
return -1; return -1;
@ -184,8 +178,7 @@ int ntfs_mst_pre_write_fixup( NTFS_RECORD *b, const u32 size )
/* Position in data of first u16 that needs fixing up. */ /* Position in data of first u16 that needs fixing up. */
data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1; data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
/* Fixup all sectors. */ /* Fixup all sectors. */
while ( usa_count-- ) while (usa_count--) {
{
/* /*
* Increment the position in the usa and save the * Increment the position in the usa and save the
* original data from the data buffer into the usa. * original data from the data buffer into the usa.
@ -224,8 +217,7 @@ void ntfs_mst_post_write_fixup( NTFS_RECORD *b )
data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1; data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
/* Fixup all sectors. */ /* Fixup all sectors. */
while ( usa_count-- ) while (usa_count--) {
{
/* /*
* Increment position in usa and restore original data from * Increment position in usa and restore original data from
* the usa into the data buffer. * the usa into the data buffer.

View File

@ -41,8 +41,7 @@
#include "cache.h" #include "cache.h"
// NTFS device driver devoptab // NTFS device driver devoptab
static const devoptab_t devops_ntfs = static const devoptab_t devops_ntfs = {
{
NULL, /* Device name */ NULL, /* Device name */
sizeof (ntfs_file_state), sizeof (ntfs_file_state),
ntfs_open_r, ntfs_open_r,
@ -73,8 +72,7 @@ void ntfsInit ( void )
static bool isInit = false; static bool isInit = false;
// Initialise ntfs-3g (if not already done so) // Initialise ntfs-3g (if not already done so)
if ( !isInit ) if (!isInit) {
{
isInit = true; isInit = true;
// Set the log handler // Set the log handler
@ -100,8 +98,7 @@ int ntfsFindPartitions ( const DISC_INTERFACE *interface, sec_t **partitions )
sec_t part_lba = 0; sec_t part_lba = 0;
int i; int i;
union union {
{
u8 buffer[512]; u8 buffer[512];
MASTER_BOOT_RECORD mbr; MASTER_BOOT_RECORD mbr;
EXTENDED_BOOT_RECORD ebr; EXTENDED_BOOT_RECORD ebr;
@ -109,8 +106,7 @@ int ntfsFindPartitions ( const DISC_INTERFACE *interface, sec_t **partitions )
} sector; } sector;
// Sanity check // Sanity check
if ( !interface ) if (!interface) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@ -121,32 +117,27 @@ int ntfsFindPartitions ( const DISC_INTERFACE *interface, sec_t **partitions )
ntfsInit(); ntfsInit();
// Start the device and check that it is inserted // Start the device and check that it is inserted
if ( !interface->startup() ) if (!interface->startup()) {
{
errno = EIO; errno = EIO;
return -1; return -1;
} }
if ( !interface->isInserted() ) if (!interface->isInserted()) {
{
return 0; return 0;
} }
// Read the first sector on the device // Read the first sector on the device
if ( !interface->readSectors( 0, 1, &sector.buffer ) ) if (!interface->readSectors(0, 1, &sector.buffer)) {
{
errno = EIO; errno = EIO;
return -1; return -1;
} }
// If this is the devices master boot record // If this is the devices master boot record
if ( sector.mbr.signature == MBR_SIGNATURE ) if (sector.mbr.signature == MBR_SIGNATURE) {
{
memcpy(&mbr, &sector, sizeof(MASTER_BOOT_RECORD)); memcpy(&mbr, &sector, sizeof(MASTER_BOOT_RECORD));
ntfs_log_debug("Valid Master Boot Record found\n"); ntfs_log_debug("Valid Master Boot Record found\n");
// Search the partition table for all NTFS partitions (max. 4 primary partitions) // Search the partition table for all NTFS partitions (max. 4 primary partitions)
for ( i = 0; i < 4; i++ ) for (i = 0; i < 4; i++) {
{
partition = &mbr.partitions[i]; partition = &mbr.partitions[i];
part_lba = le32_to_cpu(mbr.partitions[i].lba_start); part_lba = le32_to_cpu(mbr.partitions[i].lba_start);
@ -155,32 +146,25 @@ int ntfsFindPartitions ( const DISC_INTERFACE *interface, sec_t **partitions )
part_lba, partition->type); part_lba, partition->type);
// Figure out what type of partition this is // Figure out what type of partition this is
switch ( partition->type ) switch (partition->type) {
{
// Ignore empty partitions // Ignore empty partitions
case PARTITION_TYPE_EMPTY: case PARTITION_TYPE_EMPTY:
continue; continue;
// NTFS partition // NTFS partition
case PARTITION_TYPE_NTFS: case PARTITION_TYPE_NTFS: {
{
ntfs_log_debug("Partition %i: Claims to be NTFS\n", i + 1); ntfs_log_debug("Partition %i: Claims to be NTFS\n", i + 1);
// Read and validate the NTFS partition // Read and validate the NTFS partition
if ( interface->readSectors( part_lba, 1, &sector ) ) if (interface->readSectors(part_lba, 1, &sector)) {
{ if (sector.boot.oem_id == NTFS_OEM_ID) {
if ( sector.boot.oem_id == NTFS_OEM_ID )
{
ntfs_log_debug("Partition %i: Valid NTFS boot sector found\n", i + 1); ntfs_log_debug("Partition %i: Valid NTFS boot sector found\n", i + 1);
if ( partition_count < NTFS_MAX_PARTITIONS ) if (partition_count < NTFS_MAX_PARTITIONS) {
{
partition_starts[partition_count] = part_lba; partition_starts[partition_count] = part_lba;
partition_count++; partition_count++;
} }
} } else {
else
{
ntfs_log_debug("Partition %i: Invalid NTFS boot sector, not actually NTFS\n", i + 1); ntfs_log_debug("Partition %i: Invalid NTFS boot sector, not actually NTFS\n", i + 1);
} }
} }
@ -191,21 +175,17 @@ int ntfsFindPartitions ( const DISC_INTERFACE *interface, sec_t **partitions )
// DOS 3.3+ or Windows 95 extended partition // DOS 3.3+ or Windows 95 extended partition
case PARTITION_TYPE_DOS33_EXTENDED: case PARTITION_TYPE_DOS33_EXTENDED:
case PARTITION_TYPE_WIN95_EXTENDED: case PARTITION_TYPE_WIN95_EXTENDED: {
{
ntfs_log_debug("Partition %i: Claims to be Extended\n", i + 1); ntfs_log_debug("Partition %i: Claims to be Extended\n", i + 1);
// Walk the extended partition chain, finding all NTFS partitions within it // Walk the extended partition chain, finding all NTFS partitions within it
sec_t ebr_lba = part_lba; sec_t ebr_lba = part_lba;
sec_t next_erb_lba = 0; sec_t next_erb_lba = 0;
do do {
{
// Read and validate the extended boot record // Read and validate the extended boot record
if ( interface->readSectors( ebr_lba + next_erb_lba, 1, &sector ) ) if (interface->readSectors(ebr_lba + next_erb_lba, 1, &sector)) {
{ if (sector.ebr.signature == EBR_SIGNATURE) {
if ( sector.ebr.signature == EBR_SIGNATURE )
{
ntfs_log_debug("Logical Partition @ %d: type 0x%x\n", ebr_lba + next_erb_lba, ntfs_log_debug("Logical Partition @ %d: type 0x%x\n", ebr_lba + next_erb_lba,
sector.ebr.partition.status == PARTITION_STATUS_BOOTABLE ? "bootable (active)" : "non-bootable", sector.ebr.partition.status == PARTITION_STATUS_BOOTABLE ? "bootable (active)" : "non-bootable",
sector.ebr.partition.type); sector.ebr.partition.type);
@ -216,54 +196,42 @@ int ntfsFindPartitions ( const DISC_INTERFACE *interface, sec_t **partitions )
next_erb_lba = le32_to_cpu(sector.ebr.next_ebr.lba_start); next_erb_lba = le32_to_cpu(sector.ebr.next_ebr.lba_start);
// Check if this partition has a valid NTFS boot record // Check if this partition has a valid NTFS boot record
if ( interface->readSectors( part_lba, 1, &sector ) ) if (interface->readSectors(part_lba, 1, &sector)) {
{ if (sector.boot.oem_id == NTFS_OEM_ID) {
if ( sector.boot.oem_id == NTFS_OEM_ID )
{
ntfs_log_debug("Logical Partition @ %d: Valid NTFS boot sector found\n", part_lba); ntfs_log_debug("Logical Partition @ %d: Valid NTFS boot sector found\n", part_lba);
if ( sector.ebr.partition.type != PARTITION_TYPE_NTFS ) if(sector.ebr.partition.type != PARTITION_TYPE_NTFS) {
{
ntfs_log_warning("Logical Partition @ %d: Is NTFS but type is 0x%x; 0x%x was expected\n", part_lba, sector.ebr.partition.type, PARTITION_TYPE_NTFS); ntfs_log_warning("Logical Partition @ %d: Is NTFS but type is 0x%x; 0x%x was expected\n", part_lba, sector.ebr.partition.type, PARTITION_TYPE_NTFS);
} }
if ( partition_count < NTFS_MAX_PARTITIONS ) if (partition_count < NTFS_MAX_PARTITIONS) {
{
partition_starts[partition_count] = part_lba; partition_starts[partition_count] = part_lba;
partition_count++; partition_count++;
} }
} }
} }
} } else {
else
{
next_erb_lba = 0; next_erb_lba = 0;
} }
} }
} } while (next_erb_lba);
while ( next_erb_lba );
break; break;
} }
// Unknown or unsupported partition type // Unknown or unsupported partition type
default: default: {
{
// Check if this partition has a valid NTFS boot record anyway, // Check if this partition has a valid NTFS boot record anyway,
// it might be misrepresented due to a lazy partition editor // it might be misrepresented due to a lazy partition editor
if ( interface->readSectors( part_lba, 1, &sector ) ) if (interface->readSectors(part_lba, 1, &sector)) {
{ if (sector.boot.oem_id == NTFS_OEM_ID) {
if ( sector.boot.oem_id == NTFS_OEM_ID )
{
ntfs_log_debug("Partition %i: Valid NTFS boot sector found\n", i + 1); ntfs_log_debug("Partition %i: Valid NTFS boot sector found\n", i + 1);
if ( partition->type != PARTITION_TYPE_NTFS ) if(partition->type != PARTITION_TYPE_NTFS) {
{
ntfs_log_warning("Partition %i: Is NTFS but type is 0x%x; 0x%x was expected\n", i + 1, partition->type, PARTITION_TYPE_NTFS); ntfs_log_warning("Partition %i: Is NTFS but type is 0x%x; 0x%x was expected\n", i + 1, partition->type, PARTITION_TYPE_NTFS);
} }
if ( partition_count < NTFS_MAX_PARTITIONS ) if (partition_count < NTFS_MAX_PARTITIONS) {
{
partition_starts[partition_count] = part_lba; partition_starts[partition_count] = part_lba;
partition_count++; partition_count++;
} }
@ -279,21 +247,15 @@ int ntfsFindPartitions ( const DISC_INTERFACE *interface, sec_t **partitions )
} }
// Else it is assumed this device has no master boot record // Else it is assumed this device has no master boot record
} } else {
else
{
ntfs_log_debug("No Master Boot Record was found!\n"); ntfs_log_debug("No Master Boot Record was found!\n");
// As a last-ditched effort, search the first 64 sectors of the device for stray NTFS partitions // As a last-ditched effort, search the first 64 sectors of the device for stray NTFS partitions
for ( i = 0; i < 64; i++ ) for (i = 0; i < 64; i++) {
{ if (interface->readSectors(i, 1, &sector)) {
if ( interface->readSectors( i, 1, &sector ) ) if (sector.boot.oem_id == NTFS_OEM_ID) {
{
if ( sector.boot.oem_id == NTFS_OEM_ID )
{
ntfs_log_debug("Valid NTFS boot sector found at sector %d!\n", i); ntfs_log_debug("Valid NTFS boot sector found at sector %d!\n", i);
if ( partition_count < NTFS_MAX_PARTITIONS ) if (partition_count < NTFS_MAX_PARTITIONS) {
{
partition_starts[partition_count] = i; partition_starts[partition_count] = i;
partition_count++; partition_count++;
} }
@ -307,11 +269,9 @@ int ntfsFindPartitions ( const DISC_INTERFACE *interface, sec_t **partitions )
/*interface->shutdown();*/ /*interface->shutdown();*/
// Return the found partitions (if any) // Return the found partitions (if any)
if ( partition_count > 0 ) if (partition_count > 0) {
{
*partitions = (sec_t*)ntfs_alloc(sizeof(sec_t) * partition_count); *partitions = (sec_t*)ntfs_alloc(sizeof(sec_t) * partition_count);
if ( *partitions ) if (*partitions) {
{
memcpy(*partitions, &partition_starts, sizeof(sec_t) * partition_count); memcpy(*partitions, &partition_starts, sizeof(sec_t) * partition_count);
return partition_count; return partition_count;
} }
@ -335,33 +295,25 @@ int ntfsMountAll ( ntfs_md **mounts, u32 flags )
ntfsInit(); ntfsInit();
// Find and mount all NTFS partitions on all known devices // Find and mount all NTFS partitions on all known devices
for ( i = 0; discs[i].name != NULL && discs[i].interface != NULL; i++ ) for (i = 0; discs[i].name != NULL && discs[i].interface != NULL; i++) {
{
disc = &discs[i]; disc = &discs[i];
partition_count = ntfsFindPartitions(disc->interface, &partitions); partition_count = ntfsFindPartitions(disc->interface, &partitions);
if ( partition_count > 0 && partitions ) if (partition_count > 0 && partitions) {
{ for (j = 0, k = 0; j < partition_count; j++) {
for ( j = 0, k = 0; j < partition_count; j++ )
{
// Find the next unused mount name // Find the next unused mount name
do do {
{
sprintf(name, "%s%i", NTFS_MOUNT_PREFIX, k++); sprintf(name, "%s%i", NTFS_MOUNT_PREFIX, k++);
if ( k >= NTFS_MAX_MOUNTS ) if (k >= NTFS_MAX_MOUNTS) {
{
ntfs_free(partitions); ntfs_free(partitions);
errno = EADDRNOTAVAIL; errno = EADDRNOTAVAIL;
return -1; return -1;
} }
} } while (ntfsGetDevice(name, false));
while ( ntfsGetDevice( name, false ) );
// Mount the partition // Mount the partition
if ( mount_count < NTFS_MAX_MOUNTS ) if (mount_count < NTFS_MAX_MOUNTS) {
{ if (ntfsMount(name, disc->interface, partitions[j], CACHE_DEFAULT_PAGE_SIZE, CACHE_DEFAULT_PAGE_COUNT, flags)) {
if ( ntfsMount( name, disc->interface, partitions[j], CACHE_DEFAULT_PAGE_SIZE, CACHE_DEFAULT_PAGE_COUNT, flags ) )
{
strcpy(mount_points[mount_count].name, name); strcpy(mount_points[mount_count].name, name);
mount_points[mount_count].interface = disc->interface; mount_points[mount_count].interface = disc->interface;
mount_points[mount_count].startSector = partitions[j]; mount_points[mount_count].startSector = partitions[j];
@ -375,11 +327,9 @@ int ntfsMountAll ( ntfs_md **mounts, u32 flags )
} }
// Return the mounts (if any) // Return the mounts (if any)
if ( mount_count > 0 && mounts ) if (mount_count > 0 && mounts) {
{
*mounts = (ntfs_md*)ntfs_alloc(sizeof(ntfs_md) * mount_count); *mounts = (ntfs_md*)ntfs_alloc(sizeof(ntfs_md) * mount_count);
if ( *mounts ) if (*mounts) {
{
memcpy(*mounts, &mount_points, sizeof(ntfs_md) * mount_count); memcpy(*mounts, &mount_points, sizeof(ntfs_md) * mount_count);
return mount_count; return mount_count;
} }
@ -400,8 +350,7 @@ int ntfsMountDevice ( const DISC_INTERFACE *interface, ntfs_md **mounts, u32 fla
int i, j, k; int i, j, k;
// Sanity check // Sanity check
if ( !interface ) if (!interface) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@ -410,35 +359,26 @@ int ntfsMountDevice ( const DISC_INTERFACE *interface, ntfs_md **mounts, u32 fla
ntfsInit(); ntfsInit();
// Find the specified device then find and mount all NTFS partitions on it // Find the specified device then find and mount all NTFS partitions on it
for ( i = 0; discs[i].name != NULL && discs[i].interface != NULL; i++ ) for (i = 0; discs[i].name != NULL && discs[i].interface != NULL; i++) {
{ if (discs[i].interface == interface) {
if ( discs[i].interface == interface )
{
disc = &discs[i]; disc = &discs[i];
partition_count = ntfsFindPartitions(disc->interface, &partitions); partition_count = ntfsFindPartitions(disc->interface, &partitions);
if ( partition_count > 0 && partitions ) if (partition_count > 0 && partitions) {
{ for (j = 0, k = 0; j < partition_count; j++) {
for ( j = 0, k = 0; j < partition_count; j++ )
{
// Find the next unused mount name // Find the next unused mount name
do do {
{
sprintf(name, "%s%i", NTFS_MOUNT_PREFIX, k++); sprintf(name, "%s%i", NTFS_MOUNT_PREFIX, k++);
if ( k >= NTFS_MAX_MOUNTS ) if (k >= NTFS_MAX_MOUNTS) {
{
ntfs_free(partitions); ntfs_free(partitions);
errno = EADDRNOTAVAIL; errno = EADDRNOTAVAIL;
return -1; return -1;
} }
} } while (ntfsGetDevice(name, false));
while ( ntfsGetDevice( name, false ) );
// Mount the partition // Mount the partition
if ( mount_count < NTFS_MAX_MOUNTS ) if (mount_count < NTFS_MAX_MOUNTS) {
{ if (ntfsMount(name, disc->interface, partitions[j], CACHE_DEFAULT_PAGE_SIZE, CACHE_DEFAULT_PAGE_COUNT, flags)) {
if ( ntfsMount( name, disc->interface, partitions[j], CACHE_DEFAULT_PAGE_SIZE, CACHE_DEFAULT_PAGE_COUNT, flags ) )
{
strcpy(mount_points[mount_count].name, name); strcpy(mount_points[mount_count].name, name);
mount_points[mount_count].interface = disc->interface; mount_points[mount_count].interface = disc->interface;
mount_points[mount_count].startSector = partitions[j]; mount_points[mount_count].startSector = partitions[j];
@ -454,18 +394,15 @@ int ntfsMountDevice ( const DISC_INTERFACE *interface, ntfs_md **mounts, u32 fla
} }
// If we couldn't find the device then return with error status // If we couldn't find the device then return with error status
if ( !disc ) if (!disc) {
{
errno = ENODEV; errno = ENODEV;
return -1; return -1;
} }
// Return the mounts (if any) // Return the mounts (if any)
if ( mount_count > 0 && mounts ) if (mount_count > 0 && mounts) {
{
*mounts = (ntfs_md*)ntfs_alloc(sizeof(ntfs_md) * mount_count); *mounts = (ntfs_md*)ntfs_alloc(sizeof(ntfs_md) * mount_count);
if ( *mounts ) if (*mounts) {
{
memcpy(*mounts, &mount_points, sizeof(ntfs_md) * mount_count); memcpy(*mounts, &mount_points, sizeof(ntfs_md) * mount_count);
return mount_count; return mount_count;
} }
@ -480,8 +417,7 @@ bool ntfsMount ( const char *name, const DISC_INTERFACE *interface, sec_t startS
gekko_fd *fd = NULL; gekko_fd *fd = NULL;
// Sanity check // Sanity check
if ( !name || !interface ) if (!name || !interface) {
{
errno = EINVAL; errno = EINVAL;
return false; return false;
} }
@ -490,23 +426,20 @@ bool ntfsMount ( const char *name, const DISC_INTERFACE *interface, sec_t startS
ntfsInit(); ntfsInit();
// Check that the requested mount name is free // Check that the requested mount name is free
if ( ntfsGetDevice( name, false ) ) if (ntfsGetDevice(name, false)) {
{
errno = EADDRINUSE; errno = EADDRINUSE;
return false; return false;
} }
// Check that we can at least read from this device // Check that we can at least read from this device
if ( !( interface->features & FEATURE_MEDIUM_CANREAD ) ) if (!(interface->features & FEATURE_MEDIUM_CANREAD)) {
{
errno = EPERM; errno = EPERM;
return false; return false;
} }
// Allocate the volume descriptor // Allocate the volume descriptor
vd = (ntfs_vd*)ntfs_alloc(sizeof(ntfs_vd)); vd = (ntfs_vd*)ntfs_alloc(sizeof(ntfs_vd));
if ( !vd ) if (!vd) {
{
errno = ENOMEM; errno = ENOMEM;
return false; return false;
} }
@ -524,8 +457,7 @@ bool ntfsMount ( const char *name, const DISC_INTERFACE *interface, sec_t startS
// Allocate the device driver descriptor // Allocate the device driver descriptor
fd = (gekko_fd*)ntfs_alloc(sizeof(gekko_fd)); fd = (gekko_fd*)ntfs_alloc(sizeof(gekko_fd));
if ( !fd ) if (!fd) {
{
ntfs_free(vd); ntfs_free(vd);
errno = ENOMEM; errno = ENOMEM;
return false; return false;
@ -541,8 +473,7 @@ bool ntfsMount ( const char *name, const DISC_INTERFACE *interface, sec_t startS
// Allocate the device driver // Allocate the device driver
vd->dev = ntfs_device_alloc(name, 0, &ntfs_device_gekko_io_ops, fd); vd->dev = ntfs_device_alloc(name, 0, &ntfs_device_gekko_io_ops, fd);
if ( !vd->dev ) if (!vd->dev) {
{
ntfs_free(fd); ntfs_free(fd);
ntfs_free(vd); ntfs_free(vd);
return false; return false;
@ -568,10 +499,8 @@ bool ntfsMount ( const char *name, const DISC_INTERFACE *interface, sec_t startS
// Mount the device // Mount the device
vd->vol = ntfs_device_mount(vd->dev, vd->flags); vd->vol = ntfs_device_mount(vd->dev, vd->flags);
if ( !vd->vol ) if (!vd->vol) {
{ switch(ntfs_volume_error(errno)) {
switch ( ntfs_volume_error( errno ) )
{
case NTFS_VOLUME_NOT_NTFS: errno = EINVALPART; break; case NTFS_VOLUME_NOT_NTFS: errno = EINVALPART; break;
case NTFS_VOLUME_CORRUPT: errno = EINVALPART; break; case NTFS_VOLUME_CORRUPT: errno = EINVALPART; break;
case NTFS_VOLUME_HIBERNATED: errno = EHIBERNATED; break; case NTFS_VOLUME_HIBERNATED: errno = EHIBERNATED; break;
@ -583,17 +512,18 @@ bool ntfsMount ( const char *name, const DISC_INTERFACE *interface, sec_t startS
return false; return false;
} }
if (flags & NTFS_IGNORE_CASE)
ntfs_set_ignore_case(vd->vol);
// Initialise the volume descriptor // Initialise the volume descriptor
if ( ntfsInitVolume( vd ) ) if (ntfsInitVolume(vd)) {
{
ntfs_umount(vd->vol, true); ntfs_umount(vd->vol, true);
ntfs_free(vd); ntfs_free(vd);
return false; return false;
} }
// Add the device to the devoptab table // Add the device to the devoptab table
if ( ntfsAddDevice( name, vd ) ) if (ntfsAddDevice(name, vd)) {
{
ntfsDeinitVolume(vd); ntfsDeinitVolume(vd);
ntfs_umount(vd->vol, true); ntfs_umount(vd->vol, true);
ntfs_free(vd); ntfs_free(vd);
@ -635,16 +565,14 @@ const char *ntfsGetVolumeName ( const char *name )
//char *volumeName = NULL; //char *volumeName = NULL;
// Sanity check // Sanity check
if ( !name ) if (!name) {
{
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} }
// Get the devices volume descriptor // Get the devices volume descriptor
vd = ntfsGetVolume(name); vd = ntfsGetVolume(name);
if ( !vd ) if (!vd) {
{
errno = ENODEV; errno = ENODEV;
return NULL; return NULL;
} }
@ -717,16 +645,14 @@ bool ntfsSetVolumeName ( const char *name, const char *volumeName )
int ulabel_len; int ulabel_len;
// Sanity check // Sanity check
if ( !name ) if (!name) {
{
errno = EINVAL; errno = EINVAL;
return false; return false;
} }
// Get the devices volume descriptor // Get the devices volume descriptor
vd = ntfsGetVolume(name); vd = ntfsGetVolume(name);
if ( !vd ) if (!vd) {
{
errno = ENODEV; errno = ENODEV;
return false; return false;
} }
@ -736,8 +662,7 @@ bool ntfsSetVolumeName ( const char *name, const char *volumeName )
// Convert the new volume name to unicode // Convert the new volume name to unicode
ulabel_len = ntfsLocalToUnicode(volumeName, &ulabel) * sizeof(ntfschar); ulabel_len = ntfsLocalToUnicode(volumeName, &ulabel) * sizeof(ntfschar);
if ( ulabel_len < 0 ) if (ulabel_len < 0) {
{
ntfsUnlock(vd); ntfsUnlock(vd);
errno = EINVAL; errno = EINVAL;
return false; return false;
@ -745,32 +670,26 @@ bool ntfsSetVolumeName ( const char *name, const char *volumeName )
// Check if the volume name attribute exists // Check if the volume name attribute exists
na = ntfs_attr_open(vd->vol->vol_ni, AT_VOLUME_NAME, NULL, 0); na = ntfs_attr_open(vd->vol->vol_ni, AT_VOLUME_NAME, NULL, 0);
if ( na ) if (na) {
{
// It does, resize it to match the length of the new volume name // It does, resize it to match the length of the new volume name
if ( ntfs_attr_truncate( na, ulabel_len ) ) if (ntfs_attr_truncate(na, ulabel_len)) {
{
ntfs_free(ulabel); ntfs_free(ulabel);
ntfsUnlock(vd); ntfsUnlock(vd);
return false; return false;
} }
// Write the new volume name // Write the new volume name
if ( ntfs_attr_pwrite( na, 0, ulabel_len, ulabel ) != ulabel_len ) if (ntfs_attr_pwrite(na, 0, ulabel_len, ulabel) != ulabel_len) {
{
ntfs_free(ulabel); ntfs_free(ulabel);
ntfsUnlock(vd); ntfsUnlock(vd);
return false; return false;
} }
} } else {
else
{
// It doesn't, create it now // It doesn't, create it now
if ( ntfs_attr_add( vd->vol->vol_ni, AT_VOLUME_NAME, NULL, 0, ( u8* )ulabel, ulabel_len ) ) if (ntfs_attr_add(vd->vol->vol_ni, AT_VOLUME_NAME, NULL, 0, (u8*)ulabel, ulabel_len)) {
{
ntfs_free(ulabel); ntfs_free(ulabel);
ntfsUnlock(vd); ntfsUnlock(vd);
return false; return false;
@ -786,8 +705,7 @@ bool ntfsSetVolumeName ( const char *name, const char *volumeName )
ntfs_attr_close(na); ntfs_attr_close(na);
// Sync the volume node // Sync the volume node
if ( ntfs_inode_sync( vd->vol->vol_ni ) ) if (ntfs_inode_sync(vd->vol->vol_ni)) {
{
ntfs_free(ulabel); ntfs_free(ulabel);
ntfsUnlock(vd); ntfsUnlock(vd);
return false; return false;

View File

@ -23,8 +23,7 @@
#define _LIBNTFS_H #define _LIBNTFS_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C" {
{
#endif #endif
#include <gctypes.h> #include <gctypes.h>
@ -49,14 +48,14 @@ extern "C"
#define NTFS_RECOVER 0x00000008 /* Reset $LogFile if dirty (i.e. from unclean disconnect) */ #define NTFS_RECOVER 0x00000008 /* Reset $LogFile if dirty (i.e. from unclean disconnect) */
#define NTFS_IGNORE_HIBERFILE 0x00000010 /* Mount even if volume is hibernated */ #define NTFS_IGNORE_HIBERFILE 0x00000010 /* Mount even if volume is hibernated */
#define NTFS_READ_ONLY 0x00000020 /* Mount in read only mode */ #define NTFS_READ_ONLY 0x00000020 /* Mount in read only mode */
#define NTFS_SU NTFS_SHOW_HIDDEN_FILES & NTFS_SHOW_SYSTEM_FILES #define NTFS_IGNORE_CASE 0x00000040 /* Ignore case sensitivity. Everything must be and will be provided in lowercase. */
#define NTFS_FORCE NTFS_RECOVER & NTFS_IGNORE_HIBERFILE #define NTFS_SU NTFS_SHOW_HIDDEN_FILES | NTFS_SHOW_SYSTEM_FILES
#define NTFS_FORCE NTFS_RECOVER | NTFS_IGNORE_HIBERFILE
/** /**
* ntfs_md - NTFS mount descriptor * ntfs_md - NTFS mount descriptor
*/ */
typedef struct _ntfs_md typedef struct _ntfs_md {
{
char name[32]; /* Mount name (can be accessed as "name:/") */ char name[32]; /* Mount name (can be accessed as "name:/") */
const DISC_INTERFACE *interface; /* Block device containing the mounted partition */ const DISC_INTERFACE *interface; /* Block device containing the mounted partition */
sec_t startSector; /* Local block address to first sector of partition */ sec_t startSector; /* Local block address to first sector of partition */
@ -141,9 +140,6 @@ extern "C"
*/ */
extern bool ntfsSetVolumeName (const char *name, const char *volumeName); extern bool ntfsSetVolumeName (const char *name, const char *volumeName);
typedef int ( *_ntfs_frag_append_t )( void *ff, u32 offset, u32 sector, u32 count );
int _NTFS_get_fragments ( const char *path, _ntfs_frag_append_t append_fragment, void *callback_data );
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -54,8 +54,7 @@ void ntfsCloseDir ( ntfs_dir_state *dir )
return; return;
// Free the directory entries (if any) // Free the directory entries (if any)
while ( dir->first ) while (dir->first) {
{
ntfs_dir_entry *next = dir->first->next; ntfs_dir_entry *next = dir->first->next;
ntfs_free(dir->first->name); ntfs_free(dir->first->name);
ntfs_free(dir->first); ntfs_free(dir->first);
@ -87,8 +86,7 @@ int ntfs_stat_r ( struct _reent *r, const char *path, struct stat *st )
// Get the volume descriptor for this path // Get the volume descriptor for this path
vd = ntfsGetVolume(path); vd = ntfsGetVolume(path);
if ( !vd ) if (!vd) {
{
r->_errno = ENODEV; r->_errno = ENODEV;
return -1; return -1;
} }
@ -105,8 +103,7 @@ int ntfs_stat_r ( struct _reent *r, const char *path, struct stat *st )
// Find the entry // Find the entry
ni = ntfsOpenEntry(vd, path); ni = ntfsOpenEntry(vd, path);
if ( !ni ) if (!ni) {
{
r->_errno = errno; r->_errno = errno;
ntfsUnlock(vd); ntfsUnlock(vd);
return -1; return -1;
@ -134,8 +131,7 @@ int ntfs_link_r ( struct _reent *r, const char *existing, const char *newLink )
// Get the volume descriptor for this path // Get the volume descriptor for this path
vd = ntfsGetVolume(existing); vd = ntfsGetVolume(existing);
if ( !vd ) if (!vd) {
{
r->_errno = ENODEV; r->_errno = ENODEV;
return -1; return -1;
} }
@ -145,8 +141,7 @@ int ntfs_link_r ( struct _reent *r, const char *existing, const char *newLink )
// Create a symbolic link between the two paths // Create a symbolic link between the two paths
ni = ntfsCreate(vd, existing, S_IFLNK, newLink); ni = ntfsCreate(vd, existing, S_IFLNK, newLink);
if ( !ni ) if (!ni) {
{
ntfsUnlock(vd); ntfsUnlock(vd);
r->_errno = errno; r->_errno = errno;
return -1; return -1;
@ -182,8 +177,7 @@ int ntfs_chdir_r ( struct _reent *r, const char *name )
// Get the volume descriptor for this path // Get the volume descriptor for this path
vd = ntfsGetVolume(name); vd = ntfsGetVolume(name);
if ( !vd ) if (!vd) {
{
r->_errno = ENODEV; r->_errno = ENODEV;
return -1; return -1;
} }
@ -193,16 +187,14 @@ int ntfs_chdir_r ( struct _reent *r, const char *name )
// Find the directory // Find the directory
ni = ntfsOpenEntry(vd, name); ni = ntfsOpenEntry(vd, name);
if ( !ni ) if (!ni) {
{
ntfsUnlock(vd); ntfsUnlock(vd);
r->_errno = ENOENT; r->_errno = ENOENT;
return -1; return -1;
} }
// Ensure that this directory is indeed a directory // Ensure that this directory is indeed a directory
if ( !( ni->mrec->flags && MFT_RECORD_IS_DIRECTORY ) ) if (!(ni->mrec->flags && MFT_RECORD_IS_DIRECTORY)) {
{
ntfsCloseEntry(vd, ni); ntfsCloseEntry(vd, ni);
ntfsUnlock(vd); ntfsUnlock(vd);
r->_errno = ENOTDIR; r->_errno = ENOTDIR;
@ -231,8 +223,7 @@ int ntfs_rename_r ( struct _reent *r, const char *oldName, const char *newName )
// Get the volume descriptor for this path // Get the volume descriptor for this path
vd = ntfsGetVolume(oldName); vd = ntfsGetVolume(oldName);
if ( !vd ) if (!vd) {
{
r->_errno = ENODEV; r->_errno = ENODEV;
return -1; return -1;
} }
@ -241,8 +232,7 @@ int ntfs_rename_r ( struct _reent *r, const char *oldName, const char *newName )
ntfsLock(vd); ntfsLock(vd);
// You cannot rename between devices // You cannot rename between devices
if ( vd != ntfsGetVolume( newName ) ) if(vd != ntfsGetVolume(newName)) {
{
ntfsUnlock(vd); ntfsUnlock(vd);
r->_errno = EXDEV; r->_errno = EXDEV;
return -1; return -1;
@ -250,8 +240,7 @@ int ntfs_rename_r ( struct _reent *r, const char *oldName, const char *newName )
// Check that there is no existing entry with the new name // Check that there is no existing entry with the new name
ni = ntfsOpenEntry(vd, newName); ni = ntfsOpenEntry(vd, newName);
if ( ni ) if (ni) {
{
ntfsCloseEntry(vd, ni); ntfsCloseEntry(vd, ni);
ntfsUnlock(vd); ntfsUnlock(vd);
r->_errno = EEXIST; r->_errno = EEXIST;
@ -259,17 +248,14 @@ int ntfs_rename_r ( struct _reent *r, const char *oldName, const char *newName )
} }
// Link the old entry with the new one // Link the old entry with the new one
if ( ntfsLink( vd, oldName, newName ) ) if (ntfsLink(vd, oldName, newName)) {
{
ntfsUnlock(vd); ntfsUnlock(vd);
return -1; return -1;
} }
// Unlink the old entry // Unlink the old entry
if ( ntfsUnlink( vd, oldName ) ) if (ntfsUnlink(vd, oldName)) {
{ if (ntfsUnlink(vd, newName)) {
if ( ntfsUnlink( vd, newName ) )
{
ntfsUnlock(vd); ntfsUnlock(vd);
return -1; return -1;
} }
@ -292,8 +278,7 @@ int ntfs_mkdir_r ( struct _reent *r, const char *path, int mode )
// Get the volume descriptor for this path // Get the volume descriptor for this path
vd = ntfsGetVolume(path); vd = ntfsGetVolume(path);
if ( !vd ) if (!vd) {
{
r->_errno = ENODEV; r->_errno = ENODEV;
return -1; return -1;
} }
@ -303,8 +288,7 @@ int ntfs_mkdir_r ( struct _reent *r, const char *path, int mode )
// Create the directory // Create the directory
ni = ntfsCreate(vd, path, S_IFDIR, NULL); ni = ntfsCreate(vd, path, S_IFDIR, NULL);
if ( !ni ) if (!ni) {
{
ntfsUnlock(vd); ntfsUnlock(vd);
r->_errno = errno; r->_errno = errno;
return -1; return -1;
@ -329,8 +313,7 @@ int ntfs_statvfs_r ( struct _reent *r, const char *path, struct statvfs *buf )
// Get the volume descriptor for this path // Get the volume descriptor for this path
vd = ntfsGetVolume(path); vd = ntfsGetVolume(path);
if ( !vd ) if (!vd) {
{
r->_errno = ENODEV; r->_errno = ENODEV;
return -1; return -1;
} }
@ -404,25 +387,21 @@ int ntfs_readdir_filler ( DIR_ITER *dirState, const ntfschar *name, const int na
char *entry_name = NULL; char *entry_name = NULL;
// Sanity check // Sanity check
if ( !dir || !dir->vd ) if (!dir || !dir->vd) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
// Ignore DOS file names // Ignore DOS file names
if ( name_type == FILE_NAME_DOS ) if (name_type == FILE_NAME_DOS) {
{
return 0; return 0;
} }
// Preliminary check that this entry can be enumerated (as described by the volume descriptor) // Preliminary check that this entry can be enumerated (as described by the volume descriptor)
if ( MREF( mref ) == FILE_root || MREF( mref ) >= FILE_first_user || dir->vd->showSystemFiles ) if (MREF(mref) == FILE_root || MREF(mref) >= FILE_first_user || dir->vd->showSystemFiles) {
{
// Convert the entry name to our current local // Convert the entry name to our current local
if ( ntfsUnicodeToLocal( name, name_len, &entry_name, 0 ) < 0 ) if (ntfsUnicodeToLocal(name, name_len, &entry_name, 0) < 0) {
{
return -1; return -1;
} }
@ -433,8 +412,7 @@ int ntfs_readdir_filler ( DIR_ITER *dirState, const ntfschar *name, const int na
} }
// If this is not the parent or self directory reference // If this is not the parent or self directory reference
if ( ( strcmp( entry_name, "." ) != 0 ) && ( strcmp( entry_name, ".." ) != 0 ) ) if ((strcmp(entry_name, ".") != 0) && (strcmp(entry_name, "..") != 0)) {
{
// Open the entry // Open the entry
ntfs_inode *ni = ntfs_pathname_to_inode(dir->vd->vol, dir->ni, entry_name); ntfs_inode *ni = ntfs_pathname_to_inode(dir->vd->vol, dir->ni, entry_name);
@ -443,8 +421,7 @@ int ntfs_readdir_filler ( DIR_ITER *dirState, const ntfschar *name, const int na
// Double check that this entry can be emuerated (as described by the volume descriptor) // Double check that this entry can be emuerated (as described by the volume descriptor)
if (((ni->flags & FILE_ATTR_HIDDEN) && !dir->vd->showHiddenFiles) || if (((ni->flags & FILE_ATTR_HIDDEN) && !dir->vd->showHiddenFiles) ||
( ( ni->flags & FILE_ATTR_SYSTEM ) && !dir->vd->showSystemFiles ) ) ((ni->flags & FILE_ATTR_SYSTEM) && !dir->vd->showSystemFiles)) {
{
ntfs_inode_close(ni); ntfs_inode_close(ni);
return 0; return 0;
} }
@ -465,12 +442,9 @@ int ntfs_readdir_filler ( DIR_ITER *dirState, const ntfschar *name, const int na
entry->mref = MREF(mref); entry->mref = MREF(mref);
// Link the entry to the directory // Link the entry to the directory
if ( !dir->first ) if (!dir->first) {
{
dir->first = entry; dir->first = entry;
} } else {
else
{
ntfs_dir_entry *last = dir->first; ntfs_dir_entry *last = dir->first;
while (last->next) last = last->next; while (last->next) last = last->next;
last->next = entry; last->next = entry;
@ -490,8 +464,7 @@ DIR_ITER *ntfs_diropen_r ( struct _reent *r, DIR_ITER *dirState, const char *pat
// Get the volume descriptor for this path // Get the volume descriptor for this path
dir->vd = ntfsGetVolume(path); dir->vd = ntfsGetVolume(path);
if ( !dir->vd ) if (!dir->vd) {
{
r->_errno = ENODEV; r->_errno = ENODEV;
return NULL; return NULL;
} }
@ -501,16 +474,14 @@ DIR_ITER *ntfs_diropen_r ( struct _reent *r, DIR_ITER *dirState, const char *pat
// Find the directory // Find the directory
dir->ni = ntfsOpenEntry(dir->vd, path); dir->ni = ntfsOpenEntry(dir->vd, path);
if ( !dir->ni ) if (!dir->ni) {
{
ntfsUnlock(dir->vd); ntfsUnlock(dir->vd);
r->_errno = ENOENT; r->_errno = ENOENT;
return NULL; return NULL;
} }
// Ensure that this directory is indeed a directory // Ensure that this directory is indeed a directory
if ( !( dir->ni->mrec->flags && MFT_RECORD_IS_DIRECTORY ) ) if (!(dir->ni->mrec->flags && MFT_RECORD_IS_DIRECTORY)) {
{
ntfsCloseEntry(dir->vd, dir->ni); ntfsCloseEntry(dir->vd, dir->ni);
ntfsUnlock(dir->vd); ntfsUnlock(dir->vd);
r->_errno = ENOTDIR; r->_errno = ENOTDIR;
@ -519,8 +490,7 @@ DIR_ITER *ntfs_diropen_r ( struct _reent *r, DIR_ITER *dirState, const char *pat
// Read the directory // Read the directory
dir->first = dir->current = NULL; dir->first = dir->current = NULL;
if ( ntfs_readdir( dir->ni, &position, dirState, ( ntfs_filldir_t )ntfs_readdir_filler ) ) if (ntfs_readdir(dir->ni, &position, dirState, (ntfs_filldir_t)ntfs_readdir_filler)) {
{
ntfsCloseDir(dir); ntfsCloseDir(dir);
ntfsUnlock(dir->vd); ntfsUnlock(dir->vd);
r->_errno = errno; r->_errno = errno;
@ -534,13 +504,10 @@ DIR_ITER *ntfs_diropen_r ( struct _reent *r, DIR_ITER *dirState, const char *pat
ntfsUpdateTimes(dir->vd, dir->ni, NTFS_UPDATE_ATIME); ntfsUpdateTimes(dir->vd, dir->ni, NTFS_UPDATE_ATIME);
// Insert the directory into the double-linked FILO list of open directories // Insert the directory into the double-linked FILO list of open directories
if ( dir->vd->firstOpenDir ) if (dir->vd->firstOpenDir) {
{
dir->nextOpenDir = dir->vd->firstOpenDir; dir->nextOpenDir = dir->vd->firstOpenDir;
dir->vd->firstOpenDir->prevOpenDir = dir; dir->vd->firstOpenDir->prevOpenDir = dir;
} } else {
else
{
dir->nextOpenDir = NULL; dir->nextOpenDir = NULL;
} }
dir->prevOpenDir = NULL; dir->prevOpenDir = NULL;
@ -561,8 +528,7 @@ int ntfs_dirreset_r ( struct _reent *r, DIR_ITER *dirState )
ntfs_dir_state* dir = STATE(dirState); ntfs_dir_state* dir = STATE(dirState);
// Sanity check // Sanity check
if ( !dir || !dir->vd || !dir->ni ) if (!dir || !dir->vd || !dir->ni) {
{
r->_errno = EBADF; r->_errno = EBADF;
return -1; return -1;
} }
@ -590,8 +556,7 @@ int ntfs_dirnext_r ( struct _reent *r, DIR_ITER *dirState, char *filename, struc
ntfs_inode *ni = NULL; ntfs_inode *ni = NULL;
// Sanity check // Sanity check
if ( !dir || !dir->vd || !dir->ni ) if (!dir || !dir->vd || !dir->ni) {
{
r->_errno = EBADF; r->_errno = EBADF;
return -1; return -1;
} }
@ -600,8 +565,7 @@ int ntfs_dirnext_r ( struct _reent *r, DIR_ITER *dirState, char *filename, struc
ntfsLock(dir->vd); ntfsLock(dir->vd);
// Check that there is a entry waiting to be fetched // Check that there is a entry waiting to be fetched
if ( !dir->current ) if (!dir->current) {
{
ntfsUnlock(dir->vd); ntfsUnlock(dir->vd);
r->_errno = ENOENT; r->_errno = ENOENT;
return -1; return -1;
@ -619,8 +583,7 @@ int ntfs_dirnext_r ( struct _reent *r, DIR_ITER *dirState, char *filename, struc
else else
{ {
ni = ntfsOpenEntry(dir->vd, dir->current->name); ni = ntfsOpenEntry(dir->vd, dir->current->name);
if ( ni ) if (ni) {
{
ntfsStat(dir->vd, ni, filestat); ntfsStat(dir->vd, ni, filestat);
ntfsCloseEntry(dir->vd, ni); ntfsCloseEntry(dir->vd, ni);
} }
@ -646,8 +609,7 @@ int ntfs_dirclose_r ( struct _reent *r, DIR_ITER *dirState )
ntfs_dir_state* dir = STATE(dirState); ntfs_dir_state* dir = STATE(dirState);
// Sanity check // Sanity check
if ( !dir || !dir->vd ) if (!dir || !dir->vd) {
{
r->_errno = EBADF; r->_errno = EBADF;
return -1; return -1;
} }

View File

@ -28,8 +28,7 @@
/** /**
* ntfs_dir_entry - Directory entry * ntfs_dir_entry - Directory entry
*/ */
typedef struct _ntfs_dir_entry typedef struct _ntfs_dir_entry {
{
char *name; char *name;
u64 mref; u64 mref;
struct _ntfs_dir_entry *next; struct _ntfs_dir_entry *next;
@ -38,8 +37,7 @@ typedef struct _ntfs_dir_entry
/** /**
* ntfs_dir_state - Directory state * ntfs_dir_state - Directory state
*/ */
typedef struct _ntfs_dir_state typedef struct _ntfs_dir_state {
{
ntfs_vd *vd; /* Volume this directory belongs to */ ntfs_vd *vd; /* Volume this directory belongs to */
ntfs_inode *ni; /* Directory descriptor */ ntfs_inode *ni; /* Directory descriptor */
ntfs_dir_entry *first; /* The first entry in the directory */ ntfs_dir_entry *first; /* The first entry in the directory */

View File

@ -97,8 +97,7 @@ int ntfs_open_r ( struct _reent *r, void *fileStruct, const char *path, int flag
// Get the volume descriptor for this path // Get the volume descriptor for this path
file->vd = ntfsGetVolume(path); file->vd = ntfsGetVolume(path);
if ( !file->vd ) if (!file->vd) {
{
r->_errno = ENODEV; r->_errno = ENODEV;
return -1; return -1;
} }
@ -108,26 +107,19 @@ int ntfs_open_r ( struct _reent *r, void *fileStruct, const char *path, int flag
// Determine which mode the file is opened for // Determine which mode the file is opened for
file->flags = flags; file->flags = flags;
if ( ( flags & 0x03 ) == O_RDONLY ) if ((flags & 0x03) == O_RDONLY) {
{
file->read = true; file->read = true;
file->write = false; file->write = false;
file->append = false; file->append = false;
} } else if ((flags & 0x03) == O_WRONLY) {
else if ( ( flags & 0x03 ) == O_WRONLY )
{
file->read = false; file->read = false;
file->write = true; file->write = true;
file->append = (flags & O_APPEND); file->append = (flags & O_APPEND);
} } else if ((flags & 0x03) == O_RDWR) {
else if ( ( flags & 0x03 ) == O_RDWR )
{
file->read = true; file->read = true;
file->write = true; file->write = true;
file->append = (flags & O_APPEND); file->append = (flags & O_APPEND);
} } else {
else
{
r->_errno = EACCES; r->_errno = EACCES;
ntfsUnlock(file->vd); ntfsUnlock(file->vd);
return -1; return -1;
@ -135,8 +127,7 @@ int ntfs_open_r ( struct _reent *r, void *fileStruct, const char *path, int flag
// Try and find the file and (if found) ensure that it is not a directory // Try and find the file and (if found) ensure that it is not a directory
file->ni = ntfsOpenEntry(file->vd, path); file->ni = ntfsOpenEntry(file->vd, path);
if ( file->ni && ( file->ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ) ) if (file->ni && (file->ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
{
ntfsCloseEntry(file->vd, file->ni); ntfsCloseEntry(file->vd, file->ni);
ntfsUnlock(file->vd); ntfsUnlock(file->vd);
r->_errno = EISDIR; r->_errno = EISDIR;
@ -144,22 +135,11 @@ int ntfs_open_r ( struct _reent *r, void *fileStruct, const char *path, int flag
} }
// Are we creating this file? // Are we creating this file?
if ( flags & O_CREAT ) if ((flags & O_CREAT) && !file->ni) {
{
// The file SHOULD NOT already exist
if ( file->ni )
{
ntfsCloseEntry( file->vd, file->ni );
ntfsUnlock( file->vd );
r->_errno = EEXIST;
return -1;
}
// Create the file // Create the file
file->ni = ntfsCreate(file->vd, path, S_IFREG, NULL); file->ni = ntfsCreate(file->vd, path, S_IFREG, NULL);
if ( !file->ni ) if (!file->ni) {
{
ntfsUnlock(file->vd); ntfsUnlock(file->vd);
return -1; return -1;
} }
@ -167,8 +147,7 @@ int ntfs_open_r ( struct _reent *r, void *fileStruct, const char *path, int flag
} }
// Sanity check, the file should be open by now // Sanity check, the file should be open by now
if ( !file->ni ) if (!file->ni) {
{
ntfsUnlock(file->vd); ntfsUnlock(file->vd);
r->_errno = ENOENT; r->_errno = ENOENT;
return -1; return -1;
@ -176,8 +155,7 @@ int ntfs_open_r ( struct _reent *r, void *fileStruct, const char *path, int flag
// Open the files data attribute // Open the files data attribute
file->data_na = ntfs_attr_open(file->ni, AT_DATA, AT_UNNAMED, 0); file->data_na = ntfs_attr_open(file->ni, AT_DATA, AT_UNNAMED, 0);
if ( !file->data_na ) if(!file->data_na) {
{
ntfsCloseEntry(file->vd, file->ni); ntfsCloseEntry(file->vd, file->ni);
ntfsUnlock(file->vd); ntfsUnlock(file->vd);
return -1; return -1;
@ -188,8 +166,7 @@ int ntfs_open_r ( struct _reent *r, void *fileStruct, const char *path, int flag
file->encrypted = NAttrEncrypted(file->data_na) || (file->ni->flags & FILE_ATTR_ENCRYPTED); file->encrypted = NAttrEncrypted(file->data_na) || (file->ni->flags & FILE_ATTR_ENCRYPTED);
// We cannot read/write encrypted files // We cannot read/write encrypted files
if ( file->encrypted ) if (file->encrypted) {
{
ntfs_attr_close(file->data_na); ntfs_attr_close(file->data_na);
ntfsCloseEntry(file->vd, file->ni); ntfsCloseEntry(file->vd, file->ni);
ntfsUnlock(file->vd); ntfsUnlock(file->vd);
@ -198,8 +175,7 @@ int ntfs_open_r ( struct _reent *r, void *fileStruct, const char *path, int flag
} }
// Make sure we aren't trying to write to a read-only file // Make sure we aren't trying to write to a read-only file
if ( ( file->ni->flags & FILE_ATTR_READONLY ) && file->write ) if ((file->ni->flags & FILE_ATTR_READONLY) && file->write) {
{
ntfs_attr_close(file->data_na); ntfs_attr_close(file->data_na);
ntfsCloseEntry(file->vd, file->ni); ntfsCloseEntry(file->vd, file->ni);
ntfsUnlock(file->vd); ntfsUnlock(file->vd);
@ -208,10 +184,8 @@ int ntfs_open_r ( struct _reent *r, void *fileStruct, const char *path, int flag
} }
// Truncate the file if requested // Truncate the file if requested
if ( ( flags & O_TRUNC ) && file->write ) if ((flags & O_TRUNC) && file->write) {
{ if (ntfs_attr_truncate(file->data_na, 0)) {
if ( ntfs_attr_truncate( file->data_na, 0 ) )
{
ntfs_attr_close(file->data_na); ntfs_attr_close(file->data_na);
ntfsCloseEntry(file->vd, file->ni); ntfsCloseEntry(file->vd, file->ni);
ntfsUnlock(file->vd); ntfsUnlock(file->vd);
@ -230,13 +204,10 @@ int ntfs_open_r ( struct _reent *r, void *fileStruct, const char *path, int flag
ntfsUpdateTimes(file->vd, file->ni, NTFS_UPDATE_ATIME); ntfsUpdateTimes(file->vd, file->ni, NTFS_UPDATE_ATIME);
// Insert the file into the double-linked FILO list of open files // Insert the file into the double-linked FILO list of open files
if ( file->vd->firstOpenFile ) if (file->vd->firstOpenFile) {
{
file->nextOpenFile = file->vd->firstOpenFile; file->nextOpenFile = file->vd->firstOpenFile;
file->vd->firstOpenFile->prevOpenFile = file; file->vd->firstOpenFile->prevOpenFile = file;
} } else {
else
{
file->nextOpenFile = NULL; file->nextOpenFile = NULL;
} }
file->prevOpenFile = NULL; file->prevOpenFile = NULL;
@ -256,8 +227,7 @@ int ntfs_close_r ( struct _reent *r, int fd )
ntfs_file_state* file = STATE(fd); ntfs_file_state* file = STATE(fd);
// Sanity check // Sanity check
if ( !file || !file->vd ) if (!file || !file->vd) {
{
r->_errno = EBADF; r->_errno = EBADF;
return -1; return -1;
} }
@ -292,15 +262,13 @@ ssize_t ntfs_write_r ( struct _reent *r, int fd, const char *ptr, size_t len )
off_t old_pos = 0; off_t old_pos = 0;
// Sanity check // Sanity check
if ( !file || !file->vd || !file->ni || !file->data_na ) if (!file || !file->vd || !file->ni || !file->data_na) {
{
r->_errno = EINVAL; r->_errno = EINVAL;
return -1; return -1;
} }
// Short circuit cases where we don't actually have to do anything // Short circuit cases where we don't actually have to do anything
if ( !ptr || len <= 0 ) if (!ptr || len <= 0) {
{
return 0; return 0;
} }
@ -308,26 +276,22 @@ ssize_t ntfs_write_r ( struct _reent *r, int fd, const char *ptr, size_t len )
ntfsLock(file->vd); ntfsLock(file->vd);
// Check that we are allowed to write to this file // Check that we are allowed to write to this file
if ( !file->write ) if (!file->write) {
{
ntfsUnlock(file->vd); ntfsUnlock(file->vd);
r->_errno = EACCES; r->_errno = EACCES;
return -1; return -1;
} }
// If we are in append mode, backup the current position and move to the end of the file // If we are in append mode, backup the current position and move to the end of the file
if ( file->append ) if (file->append) {
{
old_pos = file->pos; old_pos = file->pos;
file->pos = file->len; file->pos = file->len;
} }
// Write to the files data atrribute // Write to the files data atrribute
while ( len ) while (len) {
{
ssize_t ret = ntfs_attr_pwrite(file->data_na, file->pos, len, ptr); ssize_t ret = ntfs_attr_pwrite(file->data_na, file->pos, len, ptr);
if ( ret <= 0 ) if (ret <= 0) {
{
ntfsUnlock(file->vd); ntfsUnlock(file->vd);
r->_errno = errno; r->_errno = errno;
return -1; return -1;
@ -338,8 +302,7 @@ ssize_t ntfs_write_r ( struct _reent *r, int fd, const char *ptr, size_t len )
} }
// If we are in append mode, restore the current position to were it was prior to this write // If we are in append mode, restore the current position to were it was prior to this write
if ( file->append ) if (file->append) {
{
file->pos = old_pos; file->pos = old_pos;
} }
@ -364,15 +327,13 @@ ssize_t ntfs_read_r ( struct _reent *r, int fd, char *ptr, size_t len )
ssize_t read = 0; ssize_t read = 0;
// Sanity check // Sanity check
if ( !file || !file->vd || !file->ni || !file->data_na ) if (!file || !file->vd || !file->ni || !file->data_na) {
{
r->_errno = EINVAL; r->_errno = EINVAL;
return -1; return -1;
} }
// Short circuit cases where we don't actually have to do anything // Short circuit cases where we don't actually have to do anything
if ( !ptr || len <= 0 ) if (!ptr || len <= 0) {
{
return 0; return 0;
} }
@ -380,16 +341,14 @@ ssize_t ntfs_read_r ( struct _reent *r, int fd, char *ptr, size_t len )
ntfsLock(file->vd); ntfsLock(file->vd);
// Check that we are allowed to read from this file // Check that we are allowed to read from this file
if ( !file->read ) if (!file->read) {
{
ntfsUnlock(file->vd); ntfsUnlock(file->vd);
r->_errno = EACCES; r->_errno = EACCES;
return -1; return -1;
} }
// Don't read past the end of file // Don't read past the end of file
if ( file->pos + len > file->len ) if (file->pos + len > file->len) {
{
r->_errno = EOVERFLOW; r->_errno = EOVERFLOW;
len = file->len - file->pos; len = file->len - file->pos;
ntfs_log_trace("EOVERFLOW"); ntfs_log_trace("EOVERFLOW");
@ -398,11 +357,9 @@ ssize_t ntfs_read_r ( struct _reent *r, int fd, char *ptr, size_t len )
ntfs_log_trace("file->pos:%d, len:%d, file->len:%d \n", (u32)file->pos, (u32)len, (u32)file->len); ntfs_log_trace("file->pos:%d, len:%d, file->len:%d \n", (u32)file->pos, (u32)len, (u32)file->len);
// Read from the files data attribute // Read from the files data attribute
while ( len ) while (len) {
{
ssize_t ret = ntfs_attr_pread(file->data_na, file->pos, len, ptr); ssize_t ret = ntfs_attr_pread(file->data_na, file->pos, len, ptr);
if ( ret <= 0 || ret > len ) if (ret <= 0 || ret > len) {
{
ntfsUnlock(file->vd); ntfsUnlock(file->vd);
r->_errno = errno; r->_errno = errno;
return -1; return -1;
@ -429,8 +386,7 @@ off_t ntfs_seek_r ( struct _reent *r, int fd, off_t pos, int dir )
off_t position = 0; off_t position = 0;
// Sanity check // Sanity check
if ( !file || !file->vd || !file->ni || !file->data_na ) if (!file || !file->vd || !file->ni || !file->data_na) {
{
r->_errno = EINVAL; r->_errno = EINVAL;
return -1; return -1;
} }
@ -439,8 +395,7 @@ off_t ntfs_seek_r ( struct _reent *r, int fd, off_t pos, int dir )
ntfsLock(file->vd); ntfsLock(file->vd);
// Set the files current position // Set the files current position
switch ( dir ) switch(dir) {
{
case SEEK_SET: position = file->pos = MIN(MAX(pos, 0), file->len); break; case SEEK_SET: position = file->pos = MIN(MAX(pos, 0), file->len); break;
case SEEK_CUR: position = file->pos = MIN(MAX(file->pos + pos, 0), file->len); break; case SEEK_CUR: position = file->pos = MIN(MAX(file->pos + pos, 0), file->len); break;
case SEEK_END: position = file->pos = MIN(MAX(file->len + pos, 0), file->len); break; case SEEK_END: position = file->pos = MIN(MAX(file->len + pos, 0), file->len); break;
@ -459,8 +414,7 @@ int ntfs_fstat_r ( struct _reent *r, int fd, struct stat *st )
int ret = 0; int ret = 0;
// Sanity check // Sanity check
if ( !file || !file->vd || !file->ni || !file->data_na ) if (!file || !file->vd || !file->ni || !file->data_na) {
{
r->_errno = EINVAL; r->_errno = EINVAL;
return -1; return -1;
} }
@ -484,8 +438,7 @@ int ntfs_ftruncate_r ( struct _reent *r, int fd, off_t len )
ntfs_file_state* file = STATE(fd); ntfs_file_state* file = STATE(fd);
// Sanity check // Sanity check
if ( !file || !file->vd || !file->ni || !file->data_na ) if (!file || !file->vd || !file->ni || !file->data_na) {
{
r->_errno = EINVAL; r->_errno = EINVAL;
return -1; return -1;
} }
@ -494,8 +447,7 @@ int ntfs_ftruncate_r ( struct _reent *r, int fd, off_t len )
ntfsLock(file->vd); ntfsLock(file->vd);
// Check that we are allowed to write to this file // Check that we are allowed to write to this file
if ( !file->write ) if (!file->write) {
{
ntfsUnlock(file->vd); ntfsUnlock(file->vd);
r->_errno = EACCES; r->_errno = EACCES;
return -1; return -1;
@ -504,28 +456,22 @@ int ntfs_ftruncate_r ( struct _reent *r, int fd, off_t len )
// For compressed files, only deleting and expanding contents are implemented // For compressed files, only deleting and expanding contents are implemented
if (file->compressed && if (file->compressed &&
len > 0 && len > 0 &&
len < file->data_na->initialized_size ) len < file->data_na->initialized_size) {
{
ntfsUnlock(file->vd); ntfsUnlock(file->vd);
r->_errno = EOPNOTSUPP; r->_errno = EOPNOTSUPP;
return -1; return -1;
} }
// Resize the files data attribute, either by expanding or truncating // Resize the files data attribute, either by expanding or truncating
if ( file->compressed && len > file->data_na->initialized_size ) if (file->compressed && len > file->data_na->initialized_size) {
{
char zero = 0; char zero = 0;
if ( ntfs_attr_pwrite( file->data_na, len - 1, 1, &zero ) <= 0 ) if (ntfs_attr_pwrite(file->data_na, len - 1, 1, &zero) <= 0) {
{
ntfsUnlock(file->vd); ntfsUnlock(file->vd);
r->_errno = errno; r->_errno = errno;
return -1; return -1;
} }
} } else {
else if (ntfs_attr_truncate(file->data_na, len)) {
{
if ( ntfs_attr_truncate( file->data_na, len ) )
{
ntfsUnlock(file->vd); ntfsUnlock(file->vd);
r->_errno = errno; r->_errno = errno;
return -1; return -1;
@ -560,8 +506,7 @@ int ntfs_fsync_r ( struct _reent *r, int fd )
int ret = 0; int ret = 0;
// Sanity check // Sanity check
if ( !file || !file->vd || !file->ni || !file->data_na ) if (!file || !file->vd || !file->ni || !file->data_na) {
{
r->_errno = EINVAL; r->_errno = EINVAL;
return -1; return -1;
} }

View File

@ -32,8 +32,7 @@
/** /**
* ntfs_file_state - File state * ntfs_file_state - File state
*/ */
typedef struct _ntfs_file_state typedef struct _ntfs_file_state {
{
ntfs_vd *vd; /* Volume this file belongs to */ ntfs_vd *vd; /* Volume this file belongs to */
ntfs_inode *ni; /* File descriptor */ ntfs_inode *ni; /* File descriptor */
ntfs_attr *data_na; /* File data descriptor */ ntfs_attr *data_na; /* File data descriptor */

View File

@ -43,8 +43,7 @@
#include <sdcard/gcsd.h> #include <sdcard/gcsd.h>
#include <ogc/usbstorage.h> #include <ogc/usbstorage.h>
const INTERFACE_ID ntfs_disc_interfaces[] = const INTERFACE_ID ntfs_disc_interfaces[] = {
{
{ "sd", &__io_wiisd }, { "sd", &__io_wiisd },
{ "usb", &__io_usbstorage }, { "usb", &__io_usbstorage },
{ "carda", &__io_gcsda }, { "carda", &__io_gcsda },
@ -55,8 +54,7 @@ const INTERFACE_ID ntfs_disc_interfaces[] =
#elif defined(__gamecube__) #elif defined(__gamecube__)
#include <sdcard/gcsd.h> #include <sdcard/gcsd.h>
const INTERFACE_ID ntfs_disc_interfaces[] = const INTERFACE_ID ntfs_disc_interfaces[] = {
{
{ "carda", &__io_gcsda }, { "carda", &__io_gcsda },
{ "cardb", &__io_gcsdb }, { "cardb", &__io_gcsdb },
{ NULL, NULL } { NULL, NULL }
@ -72,16 +70,14 @@ int ntfsAddDevice ( const char *name, void *deviceData )
int i; int i;
// Sanity check // Sanity check
if ( !name || !deviceData || !devoptab_ntfs ) if (!name || !deviceData || !devoptab_ntfs) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
// Allocate a devoptab for this device // Allocate a devoptab for this device
dev = (devoptab_t *) ntfs_alloc(sizeof(devoptab_t) + strlen(name) + 1); dev = (devoptab_t *) ntfs_alloc(sizeof(devoptab_t) + strlen(name) + 1);
if ( !dev ) if (!dev) {
{
errno = ENOMEM; errno = ENOMEM;
return false; return false;
} }
@ -96,10 +92,8 @@ int ntfsAddDevice ( const char *name, void *deviceData )
dev->deviceData = deviceData; dev->deviceData = deviceData;
// Add the device to the devoptab table (if there is a free slot) // Add the device to the devoptab table (if there is a free slot)
for ( i = 0; i < STD_MAX; i++ ) for (i = 0; i < STD_MAX; i++) {
{ if (devoptab_list[i] == devoptab_list[0] && i != 0) {
if ( devoptab_list[i] == devoptab_list[0] && i != 0 )
{
devoptab_list[i] = dev; devoptab_list[i] = dev;
return 0; return 0;
} }
@ -124,13 +118,10 @@ void ntfsRemoveDevice ( const char *path )
// NOTE: We do this manually due to a 'bug' in RemoveDevice // NOTE: We do this manually due to a 'bug' in RemoveDevice
// which ignores names with suffixes and causes names // which ignores names with suffixes and causes names
// like "ntfs" and "ntfs1" to be seen as equals // like "ntfs" and "ntfs1" to be seen as equals
for ( i = 0; i < STD_MAX; i++ ) for (i = 0; i < STD_MAX; i++) {
{
devoptab = devoptab_list[i]; devoptab = devoptab_list[i];
if ( devoptab && devoptab->name ) if (devoptab && devoptab->name) {
{ if (strcmp(name, devoptab->name) == 0) {
if ( strcmp( name, devoptab->name ) == 0 )
{
devoptab_list[i] = devoptab_list[0]; devoptab_list[i] = devoptab_list[0];
ntfs_free((devoptab_t*)devoptab); ntfs_free((devoptab_t*)devoptab);
break; break;
@ -155,13 +146,10 @@ const devoptab_t *ntfsGetDevice ( const char *path, bool useDefaultDevice )
// NOTE: We do this manually due to a 'bug' in GetDeviceOpTab // NOTE: We do this manually due to a 'bug' in GetDeviceOpTab
// which ignores names with suffixes and causes names // which ignores names with suffixes and causes names
// like "ntfs" and "ntfs1" to be seen as equals // like "ntfs" and "ntfs1" to be seen as equals
for ( i = 0; i < STD_MAX; i++ ) for (i = 0; i < STD_MAX; i++) {
{
devoptab = devoptab_list[i]; devoptab = devoptab_list[i];
if ( devoptab && devoptab->name ) if (devoptab && devoptab->name) {
{ if (strcmp(name, devoptab->name) == 0) {
if ( strcmp( name, devoptab->name ) == 0 )
{
return devoptab; return devoptab;
} }
} }
@ -196,8 +184,7 @@ ntfs_vd *ntfsGetVolume ( const char *path )
int ntfsInitVolume (ntfs_vd *vd) int ntfsInitVolume (ntfs_vd *vd)
{ {
// Sanity check // Sanity check
if ( !vd ) if (!vd) {
{
errno = ENODEV; errno = ENODEV;
return -1; return -1;
} }
@ -223,8 +210,7 @@ int ntfsInitVolume ( ntfs_vd *vd )
void ntfsDeinitVolume (ntfs_vd *vd) void ntfsDeinitVolume (ntfs_vd *vd)
{ {
// Sanity check // Sanity check
if ( !vd ) if (!vd) {
{
errno = ENODEV; errno = ENODEV;
return; return;
} }
@ -234,8 +220,7 @@ void ntfsDeinitVolume ( ntfs_vd *vd )
// Close any directories which are still open (lazy programmers!) // Close any directories which are still open (lazy programmers!)
ntfs_dir_state *nextDir = vd->firstOpenDir; ntfs_dir_state *nextDir = vd->firstOpenDir;
while ( nextDir ) while (nextDir) {
{
ntfs_log_warning("Cleaning up orphaned directory @ %p\n", nextDir); ntfs_log_warning("Cleaning up orphaned directory @ %p\n", nextDir);
ntfsCloseDir(nextDir); ntfsCloseDir(nextDir);
nextDir = nextDir->nextOpenDir; nextDir = nextDir->nextOpenDir;
@ -243,8 +228,7 @@ void ntfsDeinitVolume ( ntfs_vd *vd )
// Close any files which are still open (lazy programmers!) // Close any files which are still open (lazy programmers!)
ntfs_file_state *nextFile = vd->firstOpenFile; ntfs_file_state *nextFile = vd->firstOpenFile;
while ( nextFile ) while (nextFile) {
{
ntfs_log_warning("Cleaning up orphaned file @ %p\n", nextFile); ntfs_log_warning("Cleaning up orphaned file @ %p\n", nextFile);
ntfsCloseFile(nextFile); ntfsCloseFile(nextFile);
nextFile = nextFile->nextOpenFile; nextFile = nextFile->nextOpenFile;
@ -286,21 +270,17 @@ ntfs_inode *ntfsParseEntry ( ntfs_vd *vd, const char *path, int reparseLevel )
int attr_size; int attr_size;
// Sanity check // Sanity check
if ( !vd ) if (!vd) {
{
errno = ENODEV; errno = ENODEV;
return NULL; return NULL;
} }
// Get the actual path of the entry // Get the actual path of the entry
path = ntfsRealPath(path); path = ntfsRealPath(path);
if ( !path ) if (!path) {
{
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} } else if (path[0] == '\0') {
else if ( path[0] == '\0' )
{
path = "."; path = ".";
} }
@ -312,14 +292,11 @@ ntfs_inode *ntfsParseEntry ( ntfs_vd *vd, const char *path, int reparseLevel )
// If the entry was found and it has reparse data then parse its true path; // If the entry was found and it has reparse data then parse its true path;
// this resolves the true location of symbolic links and directory junctions // this resolves the true location of symbolic links and directory junctions
if ( ni && ( ni->flags & FILE_ATTR_REPARSE_POINT ) ) if (ni && (ni->flags & FILE_ATTR_REPARSE_POINT)) {
{ if (ntfs_possible_symlink(ni)) {
if ( ntfs_possible_symlink( ni ) )
{
// Sanity check, give up if we are parsing to deep // Sanity check, give up if we are parsing to deep
if ( reparseLevel > NTFS_MAX_SYMLINK_DEPTH ) if (reparseLevel > NTFS_MAX_SYMLINK_DEPTH) {
{
ntfsCloseEntry(vd, ni); ntfsCloseEntry(vd, ni);
errno = ELOOP; errno = ELOOP;
return NULL; return NULL;
@ -327,8 +304,7 @@ ntfs_inode *ntfsParseEntry ( ntfs_vd *vd, const char *path, int reparseLevel )
// Get the target path of this entry // Get the target path of this entry
target = ntfs_make_symlink(ni, path, &attr_size); target = ntfs_make_symlink(ni, path, &attr_size);
if ( !target ) if (!target) {
{
ntfsCloseEntry(vd, ni); ntfsCloseEntry(vd, ni);
return NULL; return NULL;
} }
@ -351,8 +327,7 @@ ntfs_inode *ntfsParseEntry ( ntfs_vd *vd, const char *path, int reparseLevel )
void ntfsCloseEntry (ntfs_vd *vd, ntfs_inode *ni) void ntfsCloseEntry (ntfs_vd *vd, ntfs_inode *ni)
{ {
// Sanity check // Sanity check
if ( !vd ) if (!vd) {
{
errno = ENODEV; errno = ENODEV;
return; return;
} }
@ -383,17 +358,14 @@ ntfs_inode *ntfsCreate ( ntfs_vd *vd, const char *path, mode_t type, const char
int uname_len, utarget_len; int uname_len, utarget_len;
// Sanity check // Sanity check
if ( !vd ) if (!vd) {
{
errno = ENODEV; errno = ENODEV;
return NULL; return NULL;
} }
// You cannot link between devices // You cannot link between devices
if ( target ) if(target) {
{ if(vd != ntfsGetVolume(target)) {
if ( vd != ntfsGetVolume( target ) )
{
errno = EXDEV; errno = EXDEV;
return NULL; return NULL;
} }
@ -402,8 +374,7 @@ ntfs_inode *ntfsCreate ( ntfs_vd *vd, const char *path, mode_t type, const char
// Get the actual paths of the entry // Get the actual paths of the entry
path = ntfsRealPath(path); path = ntfsRealPath(path);
target = ntfsRealPath(target); target = ntfsRealPath(target);
if ( !path ) if (!path) {
{
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} }
@ -414,8 +385,7 @@ ntfs_inode *ntfsCreate ( ntfs_vd *vd, const char *path, mode_t type, const char
// Get the unicode name for the entry and find its parent directory // Get the unicode name for the entry and find its parent directory
// TODO: This looks horrible, clean it up // TODO: This looks horrible, clean it up
dir = strdup(path); dir = strdup(path);
if ( !dir ) if (!dir) {
{
errno = EINVAL; errno = EINVAL;
goto cleanup; goto cleanup;
} }
@ -425,8 +395,7 @@ ntfs_inode *ntfsCreate ( ntfs_vd *vd, const char *path, mode_t type, const char
else else
name = dir; name = dir;
uname_len = ntfsLocalToUnicode(name, &uname); uname_len = ntfsLocalToUnicode(name, &uname);
if ( uname_len < 0 ) if (uname_len < 0) {
{
errno = EINVAL; errno = EINVAL;
goto cleanup; goto cleanup;
} }
@ -439,25 +408,21 @@ ntfs_inode *ntfsCreate ( ntfs_vd *vd, const char *path, mode_t type, const char
// Open the entries parent directory // Open the entries parent directory
dir_ni = ntfsOpenEntry(vd, dir); dir_ni = ntfsOpenEntry(vd, dir);
if ( !dir_ni ) if (!dir_ni) {
{
goto cleanup; goto cleanup;
} }
// Create the entry // Create the entry
switch ( type ) switch (type) {
{
// Symbolic link // Symbolic link
case S_IFLNK: case S_IFLNK:
if ( !target ) if (!target) {
{
errno = EINVAL; errno = EINVAL;
goto cleanup; goto cleanup;
} }
utarget_len = ntfsLocalToUnicode(target, &utarget); utarget_len = ntfsLocalToUnicode(target, &utarget);
if ( utarget_len < 0 ) if (utarget_len < 0) {
{
errno = EINVAL; errno = EINVAL;
goto cleanup; goto cleanup;
} }
@ -473,8 +438,7 @@ ntfs_inode *ntfsCreate ( ntfs_vd *vd, const char *path, mode_t type, const char
} }
// If the entry was created // If the entry was created
if ( ni ) if (ni) {
{
// Mark the entry for archiving // Mark the entry for archiving
ni->flags |= FILE_ATTR_ARCHIVE; ni->flags |= FILE_ATTR_ARCHIVE;
@ -520,15 +484,13 @@ int ntfsLink ( ntfs_vd *vd, const char *old_path, const char *new_path )
int res = 0; int res = 0;
// Sanity check // Sanity check
if ( !vd ) if (!vd) {
{
errno = ENODEV; errno = ENODEV;
return -1; return -1;
} }
// You cannot link between devices // You cannot link between devices
if ( vd != ntfsGetVolume( new_path ) ) if(vd != ntfsGetVolume(new_path)) {
{
errno = EXDEV; errno = EXDEV;
return -1; return -1;
} }
@ -536,8 +498,7 @@ int ntfsLink ( ntfs_vd *vd, const char *old_path, const char *new_path )
// Get the actual paths of the entry // Get the actual paths of the entry
old_path = ntfsRealPath(old_path); old_path = ntfsRealPath(old_path);
new_path = ntfsRealPath(new_path); new_path = ntfsRealPath(new_path);
if ( !old_path || !new_path ) if (!old_path || !new_path) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@ -548,8 +509,7 @@ int ntfsLink ( ntfs_vd *vd, const char *old_path, const char *new_path )
// Get the unicode name for the entry and find its parent directory // Get the unicode name for the entry and find its parent directory
// TODO: This looks horrible, clean it up // TODO: This looks horrible, clean it up
dir = strdup(new_path); dir = strdup(new_path);
if ( !dir ) if (!dir) {
{
errno = EINVAL; errno = EINVAL;
goto cleanup; goto cleanup;
} }
@ -559,8 +519,7 @@ int ntfsLink ( ntfs_vd *vd, const char *old_path, const char *new_path )
else else
name = dir; name = dir;
uname_len = ntfsLocalToUnicode(name, &uname); uname_len = ntfsLocalToUnicode(name, &uname);
if ( uname_len < 0 ) if (uname_len < 0) {
{
errno = EINVAL; errno = EINVAL;
goto cleanup; goto cleanup;
} }
@ -568,8 +527,7 @@ int ntfsLink ( ntfs_vd *vd, const char *old_path, const char *new_path )
// Find the entry // Find the entry
ni = ntfsOpenEntry(vd, old_path); ni = ntfsOpenEntry(vd, old_path);
if ( !ni ) if (!ni) {
{
errno = ENOENT; errno = ENOENT;
res = -1; res = -1;
goto cleanup; goto cleanup;
@ -577,16 +535,14 @@ int ntfsLink ( ntfs_vd *vd, const char *old_path, const char *new_path )
// Open the entries new parent directory // Open the entries new parent directory
dir_ni = ntfsOpenEntry(vd, dir); dir_ni = ntfsOpenEntry(vd, dir);
if ( !dir_ni ) if (!dir_ni) {
{
errno = ENOENT; errno = ENOENT;
res = -1; res = -1;
goto cleanup; goto cleanup;
} }
// Link the entry to its new parent // Link the entry to its new parent
if ( ntfs_link( ni, dir_ni, uname, uname_len ) ) if (ntfs_link(ni, dir_ni, uname, uname_len)) {
{
res = -1; res = -1;
goto cleanup; goto cleanup;
} }
@ -627,16 +583,14 @@ int ntfsUnlink ( ntfs_vd *vd, const char *path )
int res = 0; int res = 0;
// Sanity check // Sanity check
if ( !vd ) if (!vd) {
{
errno = ENODEV; errno = ENODEV;
return -1; return -1;
} }
// Get the actual path of the entry // Get the actual path of the entry
path = ntfsRealPath(path); path = ntfsRealPath(path);
if ( !path ) if (!path) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@ -647,8 +601,7 @@ int ntfsUnlink ( ntfs_vd *vd, const char *path )
// Get the unicode name for the entry and find its parent directory // Get the unicode name for the entry and find its parent directory
// TODO: This looks horrible // TODO: This looks horrible
dir = strdup(path); dir = strdup(path);
if ( !dir ) if (!dir) {
{
errno = EINVAL; errno = EINVAL;
goto cleanup; goto cleanup;
} }
@ -658,8 +611,7 @@ int ntfsUnlink ( ntfs_vd *vd, const char *path )
else else
name = dir; name = dir;
uname_len = ntfsLocalToUnicode(name, &uname); uname_len = ntfsLocalToUnicode(name, &uname);
if ( uname_len < 0 ) if (uname_len < 0) {
{
errno = EINVAL; errno = EINVAL;
goto cleanup; goto cleanup;
} }
@ -672,8 +624,7 @@ int ntfsUnlink ( ntfs_vd *vd, const char *path )
// Find the entry // Find the entry
ni = ntfsOpenEntry(vd, path); ni = ntfsOpenEntry(vd, path);
if ( !ni ) if (!ni) {
{
errno = ENOENT; errno = ENOENT;
res = -1; res = -1;
goto cleanup; goto cleanup;
@ -681,16 +632,14 @@ int ntfsUnlink ( ntfs_vd *vd, const char *path )
// Open the entries parent directory // Open the entries parent directory
dir_ni = ntfsOpenEntry(vd, dir); dir_ni = ntfsOpenEntry(vd, dir);
if ( !dir_ni ) if (!dir_ni) {
{
errno = ENOENT; errno = ENOENT;
res = -1; res = -1;
goto cleanup; goto cleanup;
} }
// Unlink the entry from its parent // Unlink the entry from its parent
if ( ntfs_delete( vd->vol, path, ni, dir_ni, uname, uname_len ) ) if (ntfs_delete(vd->vol, path, ni, dir_ni, uname, uname_len)) {
{
res = -1; res = -1;
} }
@ -725,15 +674,13 @@ int ntfsSync ( ntfs_vd *vd, ntfs_inode *ni )
int res = 0; int res = 0;
// Sanity check // Sanity check
if ( !vd ) if (!vd) {
{
errno = ENODEV; errno = ENODEV;
return -1; return -1;
} }
// Sanity check // Sanity check
if ( !ni ) if (!ni) {
{
errno = ENOENT; errno = ENOENT;
return -1; return -1;
} }
@ -760,15 +707,13 @@ int ntfsStat ( ntfs_vd *vd, ntfs_inode *ni, struct stat *st )
int res = 0; int res = 0;
// Sanity check // Sanity check
if ( !vd ) if (!vd) {
{
errno = ENODEV; errno = ENODEV;
return -1; return -1;
} }
// Sanity check // Sanity check
if ( !ni ) if (!ni) {
{
errno = ENOENT; errno = ENOENT;
return -1; return -1;
} }
@ -784,24 +729,20 @@ int ntfsStat ( ntfs_vd *vd, ntfs_inode *ni, struct stat *st )
memset(st, 0, sizeof(struct stat)); memset(st, 0, sizeof(struct stat));
// Is this entry a directory // Is this entry a directory
if ( ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ) if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
{
st->st_mode = S_IFDIR | (0777 & ~vd->dmask); st->st_mode = S_IFDIR | (0777 & ~vd->dmask);
st->st_nlink = 1; st->st_nlink = 1;
// Open the directories index allocation table attribute // Open the directories index allocation table attribute
na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4); na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4);
if ( na ) if (na) {
{
st->st_size = na->data_size; st->st_size = na->data_size;
st->st_blocks = na->allocated_size >> 9; st->st_blocks = na->allocated_size >> 9;
ntfs_attr_close(na); ntfs_attr_close(na);
} }
// Else it must be a file // Else it must be a file
} } else {
else
{
st->st_mode = S_IFREG | (0777 & ~vd->fmask); st->st_mode = S_IFREG | (0777 & ~vd->fmask);
st->st_size = ni->data_size; st->st_size = ni->data_size;
st->st_blocks = (ni->allocated_size + 511) >> 9; st->st_blocks = (ni->allocated_size + 511) >> 9;
@ -846,12 +787,10 @@ const char *ntfsRealPath ( const char *path )
return NULL; return NULL;
// Move the path pointer to the start of the actual path // Move the path pointer to the start of the actual path
if ( strchr( path, ':' ) != NULL ) if (strchr(path, ':') != NULL) {
{
path = strchr(path, ':') + 1; path = strchr(path, ':') + 1;
} }
if ( strchr( path, ':' ) != NULL ) if (strchr(path, ':') != NULL) {
{
return NULL; return NULL;
} }
@ -869,24 +808,19 @@ int ntfsUnicodeToLocal ( const ntfschar *ins, const int ins_len, char **outs, in
// Convert the unicode string to our current local // Convert the unicode string to our current local
len = ntfs_ucstombs(ins, ins_len, outs, outs_len); len = ntfs_ucstombs(ins, ins_len, outs, outs_len);
if ( len == -1 && errno == EILSEQ ) if (len == -1 && errno == EILSEQ) {
{
// The string could not be converted to the current local, // The string could not be converted to the current local,
// do it manually by replacing non-ASCII characters with underscores // do it manually by replacing non-ASCII characters with underscores
if ( !*outs || outs_len >= ins_len ) if (!*outs || outs_len >= ins_len) {
{ if (!*outs) {
if ( !*outs )
{
*outs = (char *) ntfs_alloc(ins_len + 1); *outs = (char *) ntfs_alloc(ins_len + 1);
if ( !*outs ) if (!*outs) {
{
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
} }
} }
for ( i = 0; i < ins_len; i++ ) for (i = 0; i < ins_len; i++) {
{
ntfschar uc = le16_to_cpu(ins[i]); ntfschar uc = le16_to_cpu(ins[i]);
if (uc > 0xff) if (uc > 0xff)
uc = (ntfschar)'_'; uc = (ntfschar)'_';

View File

@ -69,8 +69,7 @@ struct _ntfs_dir_state;
/** /**
* PRIMARY_PARTITION - Block device partition record * PRIMARY_PARTITION - Block device partition record
*/ */
typedef struct _PARTITION_RECORD typedef struct _PARTITION_RECORD {
{
u8 status; /* Partition status; see above */ u8 status; /* Partition status; see above */
u8 chs_start[3]; /* Cylinder-head-sector address to first block of partition */ u8 chs_start[3]; /* Cylinder-head-sector address to first block of partition */
u8 type; /* Partition type; see above */ u8 type; /* Partition type; see above */
@ -82,8 +81,7 @@ typedef struct _PARTITION_RECORD
/** /**
* MASTER_BOOT_RECORD - Block device master boot record * MASTER_BOOT_RECORD - Block device master boot record
*/ */
typedef struct _MASTER_BOOT_RECORD typedef struct _MASTER_BOOT_RECORD {
{
u8 code_area[446]; /* Code area; normally empty */ u8 code_area[446]; /* Code area; normally empty */
PARTITION_RECORD partitions[4]; /* 4 primary partitions */ PARTITION_RECORD partitions[4]; /* 4 primary partitions */
u16 signature; /* MBR signature; 0xAA55 */ u16 signature; /* MBR signature; 0xAA55 */
@ -92,8 +90,7 @@ typedef struct _MASTER_BOOT_RECORD
/** /**
* EXTENDED_PARTITION - Block device extended boot record * EXTENDED_PARTITION - Block device extended boot record
*/ */
typedef struct _EXTENDED_BOOT_RECORD typedef struct _EXTENDED_BOOT_RECORD {
{
u8 code_area[446]; /* Code area; normally empty */ u8 code_area[446]; /* Code area; normally empty */
PARTITION_RECORD partition; /* Primary partition */ PARTITION_RECORD partition; /* Primary partition */
PARTITION_RECORD next_ebr; /* Next extended boot record in the chain */ PARTITION_RECORD next_ebr; /* Next extended boot record in the chain */
@ -104,8 +101,7 @@ typedef struct _EXTENDED_BOOT_RECORD
/** /**
* INTERFACE_ID - Disc interface identifier * INTERFACE_ID - Disc interface identifier
*/ */
typedef struct _INTERFACE_ID typedef struct _INTERFACE_ID {
{
const char *name; /* Interface name */ const char *name; /* Interface name */
const DISC_INTERFACE *interface; /* Disc interface */ const DISC_INTERFACE *interface; /* Disc interface */
} INTERFACE_ID; } INTERFACE_ID;
@ -113,8 +109,7 @@ typedef struct _INTERFACE_ID
/** /**
* ntfs_atime_t - File access time update strategies * ntfs_atime_t - File access time update strategies
*/ */
typedef enum typedef enum {
{
ATIME_ENABLED, /* Update access times */ ATIME_ENABLED, /* Update access times */
ATIME_DISABLED /* Don't update access times */ ATIME_DISABLED /* Don't update access times */
} ntfs_atime_t; } ntfs_atime_t;
@ -122,8 +117,7 @@ typedef enum
/** /**
* ntfs_vd - NTFS volume descriptor * ntfs_vd - NTFS volume descriptor
*/ */
typedef struct _ntfs_vd typedef struct _ntfs_vd {
{
struct ntfs_device *dev; /* NTFS device handle */ struct ntfs_device *dev; /* NTFS device handle */
ntfs_volume *vol; /* NTFS volume handle */ ntfs_volume *vol; /* NTFS volume handle */
mutex_t lock; /* Volume lock mutex */ mutex_t lock; /* Volume lock mutex */

View File

@ -106,29 +106,25 @@
* ---------------------- end from RFC 4122 ----------------------- * ---------------------- end from RFC 4122 -----------------------
*/ */
typedef struct typedef struct {
{
GUID object_id; GUID object_id;
} OBJECT_ID_INDEX_KEY; } OBJECT_ID_INDEX_KEY;
typedef struct typedef struct {
{
le64 file_id; le64 file_id;
GUID birth_volume_id; GUID birth_volume_id;
GUID birth_object_id; GUID birth_object_id;
GUID domain_id; GUID domain_id;
} OBJECT_ID_INDEX_DATA; // known as OBJ_ID_INDEX_DATA } OBJECT_ID_INDEX_DATA; // known as OBJ_ID_INDEX_DATA
struct OBJECT_ID_INDEX /* index entry in $Extend/$ObjId */ struct OBJECT_ID_INDEX { /* index entry in $Extend/$ObjId */
{
INDEX_ENTRY_HEADER header; INDEX_ENTRY_HEADER header;
OBJECT_ID_INDEX_KEY key; OBJECT_ID_INDEX_KEY key;
OBJECT_ID_INDEX_DATA data; OBJECT_ID_INDEX_DATA data;
} ; } ;
static ntfschar objid_index_name[] = { const_cpu_to_le16('$'), static ntfschar objid_index_name[] = { const_cpu_to_le16('$'),
const_cpu_to_le16( 'O' ) const_cpu_to_le16('O') };
};
#ifdef HAVE_SETXATTR /* extended attributes interface required */ #ifdef HAVE_SETXATTR /* extended attributes interface required */
/* /*
@ -196,22 +192,18 @@ static ntfs_index_context *open_object_id_index( ntfs_volume *vol )
/* do not use path_name_to inode - could reopen root */ /* do not use path_name_to inode - could reopen root */
dir_ni = ntfs_inode_open(vol, FILE_Extend); dir_ni = ntfs_inode_open(vol, FILE_Extend);
ni = (ntfs_inode*)NULL; ni = (ntfs_inode*)NULL;
if ( dir_ni ) if (dir_ni) {
{
inum = ntfs_inode_lookup_by_mbsname(dir_ni,"$ObjId"); inum = ntfs_inode_lookup_by_mbsname(dir_ni,"$ObjId");
if (inum != (u64)-1) if (inum != (u64)-1)
ni = ntfs_inode_open(vol, inum); ni = ntfs_inode_open(vol, inum);
ntfs_inode_close(dir_ni); ntfs_inode_close(dir_ni);
} }
if ( ni ) if (ni) {
{
xo = ntfs_index_ctx_get(ni, objid_index_name, 2); xo = ntfs_index_ctx_get(ni, objid_index_name, 2);
if ( !xo ) if (!xo) {
{
ntfs_inode_close(ni); ntfs_inode_close(ni);
} }
} } else
else
xo = (ntfs_index_context*)NULL; xo = (ntfs_index_context*)NULL;
return (xo); return (xo);
} }
@ -238,18 +230,15 @@ static int merge_index_data( ntfs_inode *ni,
res = -1; res = -1;
xo = open_object_id_index(ni->vol); xo = open_object_id_index(ni->vol);
if ( xo ) if (xo) {
{
memcpy(&key.object_id,objectid_attr,sizeof(GUID)); memcpy(&key.object_id,objectid_attr,sizeof(GUID));
if (!ntfs_index_lookup(&key, if (!ntfs_index_lookup(&key,
sizeof( OBJECT_ID_INDEX_KEY ), xo ) ) sizeof(OBJECT_ID_INDEX_KEY), xo)) {
{
entry = (struct OBJECT_ID_INDEX*)xo->entry; entry = (struct OBJECT_ID_INDEX*)xo->entry;
/* make sure inode numbers match */ /* make sure inode numbers match */
if (entry if (entry
&& (MREF(le64_to_cpu(entry->data.file_id)) && (MREF(le64_to_cpu(entry->data.file_id))
== ni->mft_no ) ) == ni->mft_no)) {
{
memcpy(&full_objectid->birth_volume_id, memcpy(&full_objectid->birth_volume_id,
&entry->data.birth_volume_id, &entry->data.birth_volume_id,
sizeof(GUID)); sizeof(GUID));
@ -288,18 +277,15 @@ static int remove_object_id_index( ntfs_attr *na, ntfs_index_context *xo,
int ret; int ret;
ret = na->data_size; ret = na->data_size;
if ( ret ) if (ret) {
{
/* read the existing object id attribute */ /* read the existing object id attribute */
size = ntfs_attr_pread(na, 0, sizeof(GUID), old_attr); size = ntfs_attr_pread(na, 0, sizeof(GUID), old_attr);
if ( size >= ( s64 )sizeof( GUID ) ) if (size >= (s64)sizeof(GUID)) {
{
memcpy(&key.object_id, memcpy(&key.object_id,
&old_attr->object_id,sizeof(GUID)); &old_attr->object_id,sizeof(GUID));
size = sizeof(GUID); size = sizeof(GUID);
if (!ntfs_index_lookup(&key, if (!ntfs_index_lookup(&key,
sizeof( OBJECT_ID_INDEX_KEY ), xo ) ) sizeof(OBJECT_ID_INDEX_KEY), xo)) {
{
entry = (struct OBJECT_ID_INDEX*)xo->entry; entry = (struct OBJECT_ID_INDEX*)xo->entry;
memcpy(&old_attr->birth_volume_id, memcpy(&old_attr->birth_volume_id,
&entry->data.birth_volume_id, &entry->data.birth_volume_id,
@ -314,9 +300,7 @@ static int remove_object_id_index( ntfs_attr *na, ntfs_index_context *xo,
if (ntfs_index_rm(xo)) if (ntfs_index_rm(xo))
ret = -1; ret = -1;
} }
} } else {
else
{
ret = -1; ret = -1;
errno = ENODATA; errno = ENODATA;
} }
@ -351,25 +335,21 @@ static int update_object_id( ntfs_inode *ni, ntfs_index_context *xo,
res = 0; res = 0;
na = ntfs_attr_open(ni, AT_OBJECT_ID, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_OBJECT_ID, AT_UNNAMED, 0);
if ( na ) if (na) {
{
/* remove the existing index entry */ /* remove the existing index entry */
oldsize = remove_object_id_index(na,xo,&old_attr); oldsize = remove_object_id_index(na,xo,&old_attr);
if (oldsize < 0) if (oldsize < 0)
res = -1; res = -1;
else else {
{
/* resize attribute */ /* resize attribute */
res = ntfs_attr_truncate(na, (s64)sizeof(GUID)); res = ntfs_attr_truncate(na, (s64)sizeof(GUID));
/* write the object_id in attribute */ /* write the object_id in attribute */
if ( !res && value ) if (!res && value) {
{
written = (int)ntfs_attr_pwrite(na, written = (int)ntfs_attr_pwrite(na,
(s64)0, (s64)sizeof(GUID), (s64)0, (s64)sizeof(GUID),
&value->object_id); &value->object_id);
if ( written != ( s64 )sizeof( GUID ) ) if (written != (s64)sizeof(GUID)) {
{
ntfs_log_error("Failed to update " ntfs_log_error("Failed to update "
"object id\n"); "object id\n");
errno = EIO; errno = EIO;
@ -379,8 +359,7 @@ static int update_object_id( ntfs_inode *ni, ntfs_index_context *xo,
/* write index part if provided */ /* write index part if provided */
if (!res if (!res
&& ((size < sizeof(OBJECT_ID_ATTR)) && ((size < sizeof(OBJECT_ID_ATTR))
|| set_object_id_index( ni, xo, value ) ) ) || set_object_id_index(ni,xo,value))) {
{
/* /*
* If cannot index, try to remove the object * If cannot index, try to remove the object
* id and log the error. There will be an * id and log the error. There will be an
@ -393,8 +372,7 @@ static int update_object_id( ntfs_inode *ni, ntfs_index_context *xo,
} }
ntfs_attr_close(na); ntfs_attr_close(na);
NInoSetDirty(ni); NInoSetDirty(ni);
} } else
else
res = -1; res = -1;
return (res); return (res);
} }
@ -412,29 +390,22 @@ static int add_object_id( ntfs_inode *ni, int flags )
u8 dummy; u8 dummy;
res = -1; /* default return */ res = -1; /* default return */
if ( !ntfs_attr_exist( ni, AT_OBJECT_ID, AT_UNNAMED, 0 ) ) if (!ntfs_attr_exist(ni,AT_OBJECT_ID, AT_UNNAMED,0)) {
{ if (!(flags & XATTR_REPLACE)) {
if ( !( flags & XATTR_REPLACE ) )
{
/* /*
* no object id attribute : add one, * no object id attribute : add one,
* apparently, this does not feed the new value in * apparently, this does not feed the new value in
* Note : NTFS version must be >= 3 * Note : NTFS version must be >= 3
*/ */
if ( ni->vol->major_ver >= 3 ) if (ni->vol->major_ver >= 3) {
{
res = ntfs_attr_add(ni, AT_OBJECT_ID, res = ntfs_attr_add(ni, AT_OBJECT_ID,
AT_UNNAMED, 0, &dummy, (s64)0); AT_UNNAMED, 0, &dummy, (s64)0);
NInoSetDirty(ni); NInoSetDirty(ni);
} } else
else
errno = EOPNOTSUPP; errno = EOPNOTSUPP;
} } else
else
errno = ENODATA; errno = ENODATA;
} } else {
else
{
if (flags & XATTR_CREATE) if (flags & XATTR_CREATE)
errno = EEXIST; errno = EEXIST;
else else
@ -462,15 +433,13 @@ int ntfs_delete_object_id_index( ntfs_inode *ni )
res = 0; res = 0;
na = ntfs_attr_open(ni, AT_OBJECT_ID, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_OBJECT_ID, AT_UNNAMED, 0);
if ( na ) if (na) {
{
/* /*
* read the existing object id * read the existing object id
* and un-index it * and un-index it
*/ */
xo = open_object_id_index(ni->vol); xo = open_object_id_index(ni->vol);
if ( xo ) if (xo) {
{
if (remove_object_id_index(na,xo,&old_attr) < 0) if (remove_object_id_index(na,xo,&old_attr) < 0)
res = -1; res = -1;
xoni = xo->ni; xoni = xo->ni;
@ -504,42 +473,34 @@ int ntfs_get_ntfs_object_id( ntfs_inode *ni, char *value, size_t size )
int full_size; int full_size;
full_size = 0; /* default to no data and some error to be defined */ full_size = 0; /* default to no data and some error to be defined */
if ( ni ) if (ni) {
{
objectid_attr = (OBJECT_ID_ATTR*)ntfs_attr_readall(ni, objectid_attr = (OBJECT_ID_ATTR*)ntfs_attr_readall(ni,
AT_OBJECT_ID,(ntfschar*)NULL, 0, &attr_size); AT_OBJECT_ID,(ntfschar*)NULL, 0, &attr_size);
if ( objectid_attr ) if (objectid_attr) {
{
/* restrict to only GUID present in attr */ /* restrict to only GUID present in attr */
if ( attr_size == sizeof( GUID ) ) if (attr_size == sizeof(GUID)) {
{
memcpy(&full_objectid.object_id, memcpy(&full_objectid.object_id,
objectid_attr,sizeof(GUID)); objectid_attr,sizeof(GUID));
full_size = sizeof(GUID); full_size = sizeof(GUID);
/* get data from index, if any */ /* get data from index, if any */
if (!merge_index_data(ni, objectid_attr, if (!merge_index_data(ni, objectid_attr,
&full_objectid ) ) &full_objectid)) {
{
full_size = sizeof(OBJECT_ID_ATTR); full_size = sizeof(OBJECT_ID_ATTR);
} }
if ( full_size <= ( s64 )size ) if (full_size <= (s64)size) {
{
if (value) if (value)
memcpy(value,&full_objectid, memcpy(value,&full_objectid,
full_size); full_size);
else else
errno = EINVAL; errno = EINVAL;
} }
} } else {
else
{
/* unexpected size, better return unsupported */ /* unexpected size, better return unsupported */
errno = EOPNOTSUPP; errno = EOPNOTSUPP;
full_size = 0; full_size = 0;
} }
free(objectid_attr); free(objectid_attr);
} } else
else
errno = ENODATA; errno = ENODATA;
} }
return (full_size ? (int)full_size : -errno); return (full_size ? (int)full_size : -errno);
@ -564,28 +525,22 @@ int ntfs_set_ntfs_object_id( ntfs_inode *ni,
int res; int res;
res = 0; res = 0;
if ( ni && value && ( size >= sizeof( GUID ) ) ) if (ni && value && (size >= sizeof(GUID))) {
{
xo = open_object_id_index(ni->vol); xo = open_object_id_index(ni->vol);
if ( xo ) if (xo) {
{
/* make sure the GUID was not used somewhere */ /* make sure the GUID was not used somewhere */
memcpy(&key.object_id, value, sizeof(GUID)); memcpy(&key.object_id, value, sizeof(GUID));
if (ntfs_index_lookup(&key, if (ntfs_index_lookup(&key,
sizeof( OBJECT_ID_INDEX_KEY ), xo ) ) sizeof(OBJECT_ID_INDEX_KEY), xo)) {
{
ntfs_index_ctx_reinit(xo); ntfs_index_ctx_reinit(xo);
res = add_object_id(ni, flags); res = add_object_id(ni, flags);
if ( !res ) if (!res) {
{
/* update value and index */ /* update value and index */
res = update_object_id(ni,xo, res = update_object_id(ni,xo,
(const OBJECT_ID_ATTR*)value, (const OBJECT_ID_ATTR*)value,
size); size);
} }
} } else {
else
{
/* GUID is present elsewhere */ /* GUID is present elsewhere */
res = -1; res = -1;
errno = EEXIST; errno = EEXIST;
@ -595,14 +550,10 @@ int ntfs_set_ntfs_object_id( ntfs_inode *ni,
NInoSetDirty(xoni); NInoSetDirty(xoni);
ntfs_index_ctx_put(xo); ntfs_index_ctx_put(xo);
ntfs_inode_close(xoni); ntfs_inode_close(xoni);
} } else {
else
{
res = -1; res = -1;
} }
} } else {
else
{
errno = EINVAL; errno = EINVAL;
res = -1; res = -1;
} }
@ -626,32 +577,25 @@ int ntfs_remove_ntfs_object_id( ntfs_inode *ni )
OBJECT_ID_ATTR old_attr; OBJECT_ID_ATTR old_attr;
res = 0; res = 0;
if ( ni ) if (ni) {
{
/* /*
* open and delete the object id * open and delete the object id
*/ */
na = ntfs_attr_open(ni, AT_OBJECT_ID, na = ntfs_attr_open(ni, AT_OBJECT_ID,
AT_UNNAMED,0); AT_UNNAMED,0);
if ( na ) if (na) {
{
/* first remove index (old object id needed) */ /* first remove index (old object id needed) */
xo = open_object_id_index(ni->vol); xo = open_object_id_index(ni->vol);
if ( xo ) if (xo) {
{
oldsize = remove_object_id_index(na,xo, oldsize = remove_object_id_index(na,xo,
&old_attr); &old_attr);
if ( oldsize < 0 ) if (oldsize < 0) {
{
res = -1; res = -1;
} } else {
else
{
/* now remove attribute */ /* now remove attribute */
res = ntfs_attr_rm(na); res = ntfs_attr_rm(na);
if (res if (res
&& ( oldsize > ( int )sizeof( GUID ) ) ) && (oldsize > (int)sizeof(GUID))) {
{
/* /*
* If we could not remove the * If we could not remove the
* attribute, try to restore the * attribute, try to restore the
@ -678,16 +622,12 @@ int ntfs_remove_ntfs_object_id( ntfs_inode *ni )
/* avoid errno pollution */ /* avoid errno pollution */
if (errno == ENOENT) if (errno == ENOENT)
errno = olderrno; errno = olderrno;
} } else {
else
{
errno = ENODATA; errno = ENODATA;
res = -1; res = -1;
} }
NInoSetDirty(ni); NInoSetDirty(ni);
} } else {
else
{
errno = EINVAL; errno = EINVAL;
res = -1; res = -1;
} }

View File

@ -32,8 +32,7 @@
#define OWNERFROMACL 1 /* Get the owner from ACL (not Windows owner) */ #define OWNERFROMACL 1 /* Get the owner from ACL (not Windows owner) */
/* default security sub-authorities */ /* default security sub-authorities */
enum enum {
{
DEFSECAUTH1 = -1153374643, /* 3141592653 */ DEFSECAUTH1 = -1153374643, /* 3141592653 */
DEFSECAUTH2 = 589793238, DEFSECAUTH2 = 589793238,
DEFSECAUTH3 = 462843383, DEFSECAUTH3 = 462843383,

View File

@ -71,8 +71,7 @@
#define IO_REPARSE_TAG_SIS const_cpu_to_le32(0x80000007) #define IO_REPARSE_TAG_SIS const_cpu_to_le32(0x80000007)
#define IO_REPARSE_TAG_SYMLINK const_cpu_to_le32(0xA000000C) #define IO_REPARSE_TAG_SYMLINK const_cpu_to_le32(0xA000000C)
struct MOUNT_POINT_REPARSE_DATA /* reparse data for junctions */ struct MOUNT_POINT_REPARSE_DATA { /* reparse data for junctions */
{
le16 subst_name_offset; le16 subst_name_offset;
le16 subst_name_length; le16 subst_name_length;
le16 print_name_offset; le16 print_name_offset;
@ -80,8 +79,7 @@ struct MOUNT_POINT_REPARSE_DATA /* reparse data for junctions */
char path_buffer[0]; /* above data assume this is char array */ char path_buffer[0]; /* above data assume this is char array */
} ; } ;
struct SYMLINK_REPARSE_DATA /* reparse data for symlinks */ struct SYMLINK_REPARSE_DATA { /* reparse data for symlinks */
{
le16 subst_name_offset; le16 subst_name_offset;
le16 subst_name_length; le16 subst_name_length;
le16 print_name_offset; le16 print_name_offset;
@ -90,23 +88,20 @@ struct SYMLINK_REPARSE_DATA /* reparse data for symlinks */
char path_buffer[0]; /* above data assume this is char array */ char path_buffer[0]; /* above data assume this is char array */
} ; } ;
struct REPARSE_INDEX /* index entry in $Extend/$Reparse */ struct REPARSE_INDEX { /* index entry in $Extend/$Reparse */
{
INDEX_ENTRY_HEADER header; INDEX_ENTRY_HEADER header;
REPARSE_INDEX_KEY key; REPARSE_INDEX_KEY key;
le32 filling; le32 filling;
} ; } ;
static const ntfschar dir_junction_head[] = static const ntfschar dir_junction_head[] = {
{
const_cpu_to_le16('\\'), const_cpu_to_le16('\\'),
const_cpu_to_le16('?'), const_cpu_to_le16('?'),
const_cpu_to_le16('?'), const_cpu_to_le16('?'),
const_cpu_to_le16('\\') const_cpu_to_le16('\\')
} ; } ;
static const ntfschar vol_junction_head[] = static const ntfschar vol_junction_head[] = {
{
const_cpu_to_le16('\\'), const_cpu_to_le16('\\'),
const_cpu_to_le16('?'), const_cpu_to_le16('?'),
const_cpu_to_le16('?'), const_cpu_to_le16('?'),
@ -121,8 +116,7 @@ static const ntfschar vol_junction_head[] =
} ; } ;
static ntfschar reparse_index_name[] = { const_cpu_to_le16('$'), static ntfschar reparse_index_name[] = { const_cpu_to_le16('$'),
const_cpu_to_le16( 'R' ) const_cpu_to_le16('R') };
};
static const char mappingdir[] = ".NTFS-3G/"; static const char mappingdir[] = ".NTFS-3G/";
@ -152,21 +146,18 @@ static u64 ntfs_fix_file_name( ntfs_inode *dir_ni, ntfschar *uname,
u32 cpuchar; u32 cpuchar;
INDEX_ENTRY *entry; INDEX_ENTRY *entry;
FILE_NAME_ATTR *found; FILE_NAME_ATTR *found;
struct struct {
{
FILE_NAME_ATTR attr; FILE_NAME_ATTR attr;
ntfschar file_name[NTFS_MAX_NAME_LEN + 1]; ntfschar file_name[NTFS_MAX_NAME_LEN + 1];
} find; } find;
mref = (u64)-1; /* default return (not found) */ mref = (u64)-1; /* default return (not found) */
icx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4); icx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4);
if ( icx ) if (icx) {
{
if (uname_len > NTFS_MAX_NAME_LEN) if (uname_len > NTFS_MAX_NAME_LEN)
uname_len = NTFS_MAX_NAME_LEN; uname_len = NTFS_MAX_NAME_LEN;
find.attr.file_name_length = uname_len; find.attr.file_name_length = uname_len;
for ( i = 0; i < uname_len; i++ ) for (i=0; i<uname_len; i++) {
{
cpuchar = le16_to_cpu(uname[i]); cpuchar = le16_to_cpu(uname[i]);
/* /*
* We need upper or lower value, whichever is smaller, * We need upper or lower value, whichever is smaller,
@ -193,8 +184,7 @@ static u64 ntfs_fix_file_name( ntfs_inode *dir_ni, ntfschar *uname,
entry = ntfs_index_next(icx->entry, icx); entry = ntfs_index_next(icx->entry, icx);
else else
entry = icx->entry; entry = icx->entry;
if ( entry ) if (entry) {
{
found = &entry->key.file_name; found = &entry->key.file_name;
if (lkup if (lkup
&& ntfs_names_are_equal(find.attr.file_name, && ntfs_names_are_equal(find.attr.file_name,
@ -203,8 +193,7 @@ static u64 ntfs_fix_file_name( ntfs_inode *dir_ni, ntfschar *uname,
IGNORE_CASE, IGNORE_CASE,
vol->upcase, vol->upcase_len)) vol->upcase, vol->upcase_len))
lkup = 0; lkup = 0;
if ( !lkup ) if (!lkup) {
{
/* /*
* name found : * name found :
* fix original name and return inode * fix original name and return inode
@ -239,11 +228,9 @@ static char *search_absolute( ntfs_volume *vol, ntfschar *path,
target = (char*)NULL; /* default return */ target = (char*)NULL; /* default return */
ni = ntfs_inode_open(vol, (MFT_REF)FILE_root); ni = ntfs_inode_open(vol, (MFT_REF)FILE_root);
if ( ni ) if (ni) {
{
start = 0; start = 0;
do do {
{
len = 0; len = 0;
while (((start + len) < count) while (((start + len) < count)
&& (path[start + len] != const_cpu_to_le16('\\'))) && (path[start + len] != const_cpu_to_le16('\\')))
@ -251,24 +238,20 @@ static char *search_absolute( ntfs_volume *vol, ntfschar *path,
inum = ntfs_fix_file_name(ni, &path[start], len); inum = ntfs_fix_file_name(ni, &path[start], len);
ntfs_inode_close(ni); ntfs_inode_close(ni);
ni = (ntfs_inode*)NULL; ni = (ntfs_inode*)NULL;
if ( inum != ( u64 ) - 1 ) if (inum != (u64)-1) {
{
inum = MREF(inum); inum = MREF(inum);
ni = ntfs_inode_open(vol, inum); ni = ntfs_inode_open(vol, inum);
start += len; start += len;
if (start < count) if (start < count)
path[start++] = const_cpu_to_le16('/'); path[start++] = const_cpu_to_le16('/');
} }
} } while (ni
while ( ni
&& (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
&& (start < count)); && (start < count));
if (ni if (ni
&& (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ? isdir : !isdir)) && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ? isdir : !isdir))
if ( ntfs_ucstombs( path, count, &target, 0 ) < 0 ) if (ntfs_ucstombs(path, count, &target, 0) < 0) {
{ if (target) {
if ( target )
{
free(target); free(target);
target = (char*)NULL; target = (char*)NULL;
} }
@ -305,22 +288,17 @@ static char *search_relative( ntfs_inode *ni, ntfschar *path, int count )
pos = 0; pos = 0;
ok = TRUE; ok = TRUE;
curni = ntfs_dir_parent_inode(ni); curni = ntfs_dir_parent_inode(ni);
while ( curni && ok && ( pos < ( count - 1 ) ) && --max ) while (curni && ok && (pos < (count - 1)) && --max) {
{
if ((count >= (pos + 2)) if ((count >= (pos + 2))
&& (path[pos] == const_cpu_to_le16('.')) && (path[pos] == const_cpu_to_le16('.'))
&& ( path[pos+1] == const_cpu_to_le16( '\\' ) ) ) && (path[pos+1] == const_cpu_to_le16('\\'))) {
{
path[1] = const_cpu_to_le16('/'); path[1] = const_cpu_to_le16('/');
pos += 2; pos += 2;
} } else {
else
{
if ((count >= (pos + 3)) if ((count >= (pos + 3))
&& (path[pos] == const_cpu_to_le16('.')) && (path[pos] == const_cpu_to_le16('.'))
&&(path[pos+1] == const_cpu_to_le16('.')) &&(path[pos+1] == const_cpu_to_le16('.'))
&& ( path[pos+2] == const_cpu_to_le16( '\\' ) ) ) && (path[pos+2] == const_cpu_to_le16('\\'))) {
{
path[2] = const_cpu_to_le16('/'); path[2] = const_cpu_to_le16('/');
pos += 3; pos += 3;
newni = ntfs_dir_parent_inode(curni); newni = ntfs_dir_parent_inode(curni);
@ -329,9 +307,7 @@ static char *search_relative( ntfs_inode *ni, ntfschar *path, int count )
curni = newni; curni = newni;
if (!curni) if (!curni)
ok = FALSE; ok = FALSE;
} } else {
else
{
lth = 0; lth = 0;
while (((pos + lth) < count) while (((pos + lth) < count)
&& (path[pos + lth] != const_cpu_to_le16('\\'))) && (path[pos + lth] != const_cpu_to_le16('\\')))
@ -345,20 +321,15 @@ static char *search_relative( ntfs_inode *ni, ntfschar *path, int count )
&& ntfs_inode_close(curni)) && ntfs_inode_close(curni))
|| (inum == (u64)-1)) || (inum == (u64)-1))
ok = FALSE; ok = FALSE;
else else {
{
curni = ntfs_inode_open(ni->vol, MREF(inum)); curni = ntfs_inode_open(ni->vol, MREF(inum));
if (!curni) if (!curni)
ok = FALSE; ok = FALSE;
else else {
{ if (ok && ((pos + lth) < count)) {
if ( ok && ( ( pos + lth ) < count ) )
{
path[pos + lth] = const_cpu_to_le16('/'); path[pos + lth] = const_cpu_to_le16('/');
pos += lth + 1; pos += lth + 1;
} } else {
else
{
pos += lth; pos += lth;
if ((ni->mrec->flags ^ curni->mrec->flags) if ((ni->mrec->flags ^ curni->mrec->flags)
& MFT_RECORD_IS_DIRECTORY) & MFT_RECORD_IS_DIRECTORY)
@ -372,8 +343,7 @@ static char *search_relative( ntfs_inode *ni, ntfschar *path, int count )
} }
} }
if ( ok && ( ntfs_ucstombs( path, count, &target, 0 ) < 0 ) ) if (ok && (ntfs_ucstombs(path, count, &target, 0) < 0)) {
{
free(target); // needed ? free(target); // needed ?
target = (char*)NULL; target = (char*)NULL;
} }
@ -400,8 +370,7 @@ static int ntfs_drive_letter( ntfs_volume *vol, ntfschar letter )
ret = -1; ret = -1;
drive = (char*)NULL; drive = (char*)NULL;
sz = ntfs_ucstombs(&letter, 1, &drive, 0); sz = ntfs_ucstombs(&letter, 1, &drive, 0);
if ( sz > 0 ) if (sz > 0) {
{
strcpy(defines,mappingdir); strcpy(defines,mappingdir);
if ((*drive >= 'a') && (*drive <= 'z')) if ((*drive >= 'a') && (*drive <= 'z'))
*drive += 'A' - 'a'; *drive += 'A' - 'a';
@ -411,8 +380,8 @@ static int ntfs_drive_letter( ntfs_volume *vol, ntfschar letter )
ni = ntfs_pathname_to_inode(vol, NULL, defines); ni = ntfs_pathname_to_inode(vol, NULL, defines);
if (ni && !ntfs_inode_close(ni)) if (ni && !ntfs_inode_close(ni))
ret = 1; ret = 1;
else if ( errno == ENOENT ) else
{ if (errno == ENOENT) {
ret = 0; ret = 0;
/* avoid errno pollution */ /* avoid errno pollution */
errno = olderrno; errno = olderrno;
@ -446,10 +415,8 @@ static BOOL valid_reparse_data( ntfs_inode *ni,
&& (size >= sizeof(REPARSE_POINT)) && (size >= sizeof(REPARSE_POINT))
&& (((size_t)le16_to_cpu(reparse_attr->reparse_data_length) && (((size_t)le16_to_cpu(reparse_attr->reparse_data_length)
+ sizeof(REPARSE_POINT)) == size); + sizeof(REPARSE_POINT)) == size);
if ( ok ) if (ok) {
{ switch (reparse_attr->reparse_tag) {
switch ( reparse_attr->reparse_tag )
{
case IO_REPARSE_TAG_MOUNT_POINT : case IO_REPARSE_TAG_MOUNT_POINT :
mount_point_data = (const struct MOUNT_POINT_REPARSE_DATA*) mount_point_data = (const struct MOUNT_POINT_REPARSE_DATA*)
reparse_attr->reparse_data; reparse_attr->reparse_data;
@ -536,15 +503,12 @@ static char *ntfs_get_fulllink( ntfs_volume *vol, ntfschar *junction,
if ((kind == DIR_JUNCTION) if ((kind == DIR_JUNCTION)
&& (count >= 7) && (count >= 7)
&& junction[7] && junction[7]
&& !ntfs_drive_letter( vol, junction[4] ) ) && !ntfs_drive_letter(vol, junction[4])) {
{
target = search_absolute(vol,&junction[7],count - 7, isdir); target = search_absolute(vol,&junction[7],count - 7, isdir);
if ( target ) if (target) {
{
fulltarget = (char*)ntfs_malloc(strlen(mnt_point) fulltarget = (char*)ntfs_malloc(strlen(mnt_point)
+ strlen(target) + 2); + strlen(target) + 2);
if ( fulltarget ) if (fulltarget) {
{
strcpy(fulltarget,mnt_point); strcpy(fulltarget,mnt_point);
strcat(fulltarget,"/"); strcat(fulltarget,"/");
strcat(fulltarget,target); strcat(fulltarget,target);
@ -559,13 +523,11 @@ static char *ntfs_get_fulllink( ntfs_volume *vol, ntfschar *junction,
* define as a symbolic link to the real target * define as a symbolic link to the real target
*/ */
if (((kind == DIR_JUNCTION) && !fulltarget) if (((kind == DIR_JUNCTION) && !fulltarget)
|| ( kind == VOL_JUNCTION ) ) || (kind == VOL_JUNCTION)) {
{
sz = ntfs_ucstombs(&junction[4], sz = ntfs_ucstombs(&junction[4],
(kind == VOL_JUNCTION ? count - 5 : count - 4), (kind == VOL_JUNCTION ? count - 5 : count - 4),
&target, 0); &target, 0);
if ( ( sz > 0 ) && target ) if ((sz > 0) && target) {
{
/* reverse slashes */ /* reverse slashes */
for (q=target; *q; q++) for (q=target; *q; q++)
if (*q == '\\') if (*q == '\\')
@ -577,8 +539,7 @@ static char *ntfs_get_fulllink( ntfs_volume *vol, ntfschar *junction,
target[0] += 'A' - 'a'; target[0] += 'A' - 'a';
fulltarget = (char*)ntfs_malloc(strlen(mnt_point) fulltarget = (char*)ntfs_malloc(strlen(mnt_point)
+ sizeof(mappingdir) + strlen(target) + 1); + sizeof(mappingdir) + strlen(target) + 1);
if ( fulltarget ) if (fulltarget) {
{
strcpy(fulltarget,mnt_point); strcpy(fulltarget,mnt_point);
strcat(fulltarget,"/"); strcat(fulltarget,"/");
strcat(fulltarget,mappingdir); strcat(fulltarget,mappingdir);
@ -644,20 +605,17 @@ static char *ntfs_get_abslink( ntfs_volume *vol, ntfschar *junction,
&& (count >= 3) && (count >= 3)
&& junction[3] && junction[3]
&& !ntfs_drive_letter(vol, junction[0])) && !ntfs_drive_letter(vol, junction[0]))
|| ( kind == ABS_PATH ) ) || (kind == ABS_PATH)) {
{
if (kind == ABS_PATH) if (kind == ABS_PATH)
target = search_absolute(vol, &junction[1], target = search_absolute(vol, &junction[1],
count - 1, isdir); count - 1, isdir);
else else
target = search_absolute(vol, &junction[3], target = search_absolute(vol, &junction[3],
count - 3, isdir); count - 3, isdir);
if ( target ) if (target) {
{
fulltarget = (char*)ntfs_malloc(strlen(mnt_point) fulltarget = (char*)ntfs_malloc(strlen(mnt_point)
+ strlen(target) + 2); + strlen(target) + 2);
if ( fulltarget ) if (fulltarget) {
{
strcpy(fulltarget,mnt_point); strcpy(fulltarget,mnt_point);
strcat(fulltarget,"/"); strcat(fulltarget,"/");
strcat(fulltarget,target); strcat(fulltarget,target);
@ -670,12 +628,10 @@ static char *ntfs_get_abslink( ntfs_volume *vol, ntfschar *junction,
* link to /.NTFS-3G/target which the user can * link to /.NTFS-3G/target which the user can
* define as a symbolic link to the real target * define as a symbolic link to the real target
*/ */
if ( ( kind == FULL_PATH ) && !fulltarget ) if ((kind == FULL_PATH) && !fulltarget) {
{
sz = ntfs_ucstombs(&junction[0], sz = ntfs_ucstombs(&junction[0],
count,&target, 0); count,&target, 0);
if ( ( sz > 0 ) && target ) if ((sz > 0) && target) {
{
/* reverse slashes */ /* reverse slashes */
for (q=target; *q; q++) for (q=target; *q; q++)
if (*q == '\\') if (*q == '\\')
@ -687,8 +643,7 @@ static char *ntfs_get_abslink( ntfs_volume *vol, ntfschar *junction,
target[0] += 'A' - 'a'; target[0] += 'A' - 'a';
fulltarget = (char*)ntfs_malloc(strlen(mnt_point) fulltarget = (char*)ntfs_malloc(strlen(mnt_point)
+ sizeof(mappingdir) + strlen(target) + 1); + sizeof(mappingdir) + strlen(target) + 1);
if ( fulltarget ) if (fulltarget) {
{
strcpy(fulltarget,mnt_point); strcpy(fulltarget,mnt_point);
strcat(fulltarget,"/"); strcat(fulltarget,"/");
strcat(fulltarget,mappingdir); strcat(fulltarget,mappingdir);
@ -755,10 +710,8 @@ char *ntfs_make_symlink( ntfs_inode *ni, const char *mnt_point,
reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni, reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni,
AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size); AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size);
if (reparse_attr && attr_size if (reparse_attr && attr_size
&& valid_reparse_data( ni, reparse_attr, attr_size ) ) && valid_reparse_data(ni, reparse_attr, attr_size)) {
{ switch (reparse_attr->reparse_tag) {
switch ( reparse_attr->reparse_tag )
{
case IO_REPARSE_TAG_MOUNT_POINT : case IO_REPARSE_TAG_MOUNT_POINT :
mount_point_data = (struct MOUNT_POINT_REPARSE_DATA*) mount_point_data = (struct MOUNT_POINT_REPARSE_DATA*)
reparse_attr->reparse_data; reparse_attr->reparse_data;
@ -781,26 +734,23 @@ char *ntfs_make_symlink( ntfs_inode *ni, const char *mnt_point,
* Predetermine the kind of target, * Predetermine the kind of target,
* the called function has to make a full check * the called function has to make a full check
*/ */
if ( *p++ == const_cpu_to_le16( '\\' ) ) if (*p++ == const_cpu_to_le16('\\')) {
{
if ((*p == const_cpu_to_le16('?')) if ((*p == const_cpu_to_le16('?'))
|| (*p == const_cpu_to_le16('\\'))) || (*p == const_cpu_to_le16('\\')))
kind = FULL_TARGET; kind = FULL_TARGET;
else else
kind = ABS_TARGET; kind = ABS_TARGET;
} } else
else if ( *p == const_cpu_to_le16( ':' ) ) if (*p == const_cpu_to_le16(':'))
kind = ABS_TARGET; kind = ABS_TARGET;
else else
kind = REL_TARGET; kind = REL_TARGET;
p--; p--;
/* reparse data consistency has been checked */ /* reparse data consistency has been checked */
switch ( kind ) switch (kind) {
{
case FULL_TARGET : case FULL_TARGET :
if (!(symlink_data->flags if (!(symlink_data->flags
& const_cpu_to_le32( 1 ) ) ) & const_cpu_to_le32(1))) {
{
target = ntfs_get_fulllink(vol, target = ntfs_get_fulllink(vol,
p, lth/2, p, lth/2,
mnt_point, isdir); mnt_point, isdir);
@ -810,8 +760,7 @@ char *ntfs_make_symlink( ntfs_inode *ni, const char *mnt_point,
break; break;
case ABS_TARGET : case ABS_TARGET :
if (symlink_data->flags if (symlink_data->flags
& const_cpu_to_le32( 1 ) ) & const_cpu_to_le32(1)) {
{
target = ntfs_get_abslink(vol, target = ntfs_get_abslink(vol,
p, lth/2, p, lth/2,
mnt_point, isdir); mnt_point, isdir);
@ -821,8 +770,7 @@ char *ntfs_make_symlink( ntfs_inode *ni, const char *mnt_point,
break; break;
case REL_TARGET : case REL_TARGET :
if (symlink_data->flags if (symlink_data->flags
& const_cpu_to_le32( 1 ) ) & const_cpu_to_le32(1)) {
{
target = ntfs_get_rellink(ni, target = ntfs_get_rellink(ni,
p, lth/2); p, lth/2);
if (target) if (target)
@ -857,10 +805,8 @@ BOOL ntfs_possible_symlink( ntfs_inode *ni )
possible = FALSE; possible = FALSE;
reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni, reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni,
AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size); AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size);
if ( reparse_attr && attr_size ) if (reparse_attr && attr_size) {
{ switch (reparse_attr->reparse_tag) {
switch ( reparse_attr->reparse_tag )
{
case IO_REPARSE_TAG_MOUNT_POINT : case IO_REPARSE_TAG_MOUNT_POINT :
case IO_REPARSE_TAG_SYMLINK : case IO_REPARSE_TAG_SYMLINK :
possible = TRUE; possible = TRUE;
@ -931,12 +877,10 @@ static int remove_reparse_index( ntfs_attr *na, ntfs_index_context *xr,
int ret; int ret;
ret = na->data_size; ret = na->data_size;
if ( ret ) if (ret) {
{
/* read the existing reparse_tag */ /* read the existing reparse_tag */
size = ntfs_attr_pread(na, 0, 4, preparse_tag); size = ntfs_attr_pread(na, 0, 4, preparse_tag);
if ( size == 4 ) if (size == 4) {
{
seqn = na->ni->mrec->sequence_number; seqn = na->ni->mrec->sequence_number;
file_id_cpu = MK_MREF(na->ni->mft_no,le16_to_cpu(seqn)); file_id_cpu = MK_MREF(na->ni->mft_no,le16_to_cpu(seqn));
file_id = cpu_to_le64(file_id_cpu); file_id = cpu_to_le64(file_id_cpu);
@ -946,9 +890,7 @@ static int remove_reparse_index( ntfs_attr *na, ntfs_index_context *xr,
if (!ntfs_index_lookup(&key, sizeof(REPARSE_INDEX_KEY), xr) if (!ntfs_index_lookup(&key, sizeof(REPARSE_INDEX_KEY), xr)
&& ntfs_index_rm(xr)) && ntfs_index_rm(xr))
ret = -1; ret = -1;
} } else {
else
{
ret = -1; ret = -1;
errno = ENODATA; errno = ENODATA;
} }
@ -975,22 +917,18 @@ static ntfs_index_context *open_reparse_index( ntfs_volume *vol )
/* do not use path_name_to inode - could reopen root */ /* do not use path_name_to inode - could reopen root */
dir_ni = ntfs_inode_open(vol, FILE_Extend); dir_ni = ntfs_inode_open(vol, FILE_Extend);
ni = (ntfs_inode*)NULL; ni = (ntfs_inode*)NULL;
if ( dir_ni ) if (dir_ni) {
{
inum = ntfs_inode_lookup_by_mbsname(dir_ni,"$Reparse"); inum = ntfs_inode_lookup_by_mbsname(dir_ni,"$Reparse");
if (inum != (u64)-1) if (inum != (u64)-1)
ni = ntfs_inode_open(vol, inum); ni = ntfs_inode_open(vol, inum);
ntfs_inode_close(dir_ni); ntfs_inode_close(dir_ni);
} }
if ( ni ) if (ni) {
{
xr = ntfs_index_ctx_get(ni, reparse_index_name, 2); xr = ntfs_index_ctx_get(ni, reparse_index_name, 2);
if ( !xr ) if (!xr) {
{
ntfs_inode_close(ni); ntfs_inode_close(ni);
} }
} } else
else
xr = (ntfs_index_context*)NULL; xr = (ntfs_index_context*)NULL;
return (xr); return (xr);
} }
@ -1021,23 +959,19 @@ static int update_reparse_data( ntfs_inode *ni, ntfs_index_context *xr,
res = 0; res = 0;
na = ntfs_attr_open(ni, AT_REPARSE_POINT, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_REPARSE_POINT, AT_UNNAMED, 0);
if ( na ) if (na) {
{
/* remove the existing reparse data */ /* remove the existing reparse data */
oldsize = remove_reparse_index(na,xr,&reparse_tag); oldsize = remove_reparse_index(na,xr,&reparse_tag);
if (oldsize < 0) if (oldsize < 0)
res = -1; res = -1;
else else {
{
/* resize attribute */ /* resize attribute */
res = ntfs_attr_truncate(na, (s64)size); res = ntfs_attr_truncate(na, (s64)size);
/* overwrite value if any */ /* overwrite value if any */
if ( !res && value ) if (!res && value) {
{
written = (int)ntfs_attr_pwrite(na, written = (int)ntfs_attr_pwrite(na,
(s64)0, (s64)size, value); (s64)0, (s64)size, value);
if ( written != ( s64 )size ) if (written != (s64)size) {
{
ntfs_log_error("Failed to update " ntfs_log_error("Failed to update "
"reparse data\n"); "reparse data\n");
errno = EIO; errno = EIO;
@ -1047,8 +981,7 @@ static int update_reparse_data( ntfs_inode *ni, ntfs_index_context *xr,
if (!res if (!res
&& set_reparse_index(ni,xr, && set_reparse_index(ni,xr,
((const REPARSE_POINT*)value)->reparse_tag) ((const REPARSE_POINT*)value)->reparse_tag)
&& ( oldsize > 0 ) ) && (oldsize > 0)) {
{
/* /*
* If cannot index, try to remove the reparse * If cannot index, try to remove the reparse
* data and log the error. There will be an * data and log the error. There will be an
@ -1061,8 +994,7 @@ static int update_reparse_data( ntfs_inode *ni, ntfs_index_context *xr,
} }
ntfs_attr_close(na); ntfs_attr_close(na);
NInoSetDirty(ni); NInoSetDirty(ni);
} } else
else
res = -1; res = -1;
return (res); return (res);
} }
@ -1086,15 +1018,13 @@ int ntfs_delete_reparse_index( ntfs_inode *ni )
res = 0; res = 0;
na = ntfs_attr_open(ni, AT_REPARSE_POINT, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_REPARSE_POINT, AT_UNNAMED, 0);
if ( na ) if (na) {
{
/* /*
* read the existing reparse data (the tag is enough) * read the existing reparse data (the tag is enough)
* and un-index it * and un-index it
*/ */
xr = open_reparse_index(ni->vol); xr = open_reparse_index(ni->vol);
if ( xr ) if (xr) {
{
if (remove_reparse_index(na,xr,&reparse_tag) < 0) if (remove_reparse_index(na,xr,&reparse_tag) < 0)
res = -1; res = -1;
xrni = xr->ni; xrni = xr->ni;
@ -1123,16 +1053,12 @@ int ntfs_get_ntfs_reparse_data( ntfs_inode *ni, char *value, size_t size )
s64 attr_size; s64 attr_size;
attr_size = 0; /* default to no data and no error */ attr_size = 0; /* default to no data and no error */
if ( ni ) if (ni) {
{ if (ni->flags & FILE_ATTR_REPARSE_POINT) {
if ( ni->flags & FILE_ATTR_REPARSE_POINT )
{
reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni, reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni,
AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size); AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size);
if ( reparse_attr ) if (reparse_attr) {
{ if (attr_size <= (s64)size) {
if ( attr_size <= ( s64 )size )
{
if (value) if (value)
memcpy(value,reparse_attr, memcpy(value,reparse_attr,
attr_size); attr_size);
@ -1141,8 +1067,7 @@ int ntfs_get_ntfs_reparse_data( ntfs_inode *ni, char *value, size_t size )
} }
free(reparse_attr); free(reparse_attr);
} }
} } else
else
errno = ENODATA; errno = ENODATA;
} }
return (attr_size ? (int)attr_size : -errno); return (attr_size ? (int)attr_size : -errno);
@ -1165,57 +1090,43 @@ int ntfs_set_ntfs_reparse_data( ntfs_inode *ni,
ntfs_index_context *xr; ntfs_index_context *xr;
res = 0; res = 0;
if ( ni && valid_reparse_data( ni, ( const REPARSE_POINT* )value, size ) ) if (ni && valid_reparse_data(ni, (const REPARSE_POINT*)value, size)) {
{
xr = open_reparse_index(ni->vol); xr = open_reparse_index(ni->vol);
if ( xr ) if (xr) {
{
if (!ntfs_attr_exist(ni,AT_REPARSE_POINT, if (!ntfs_attr_exist(ni,AT_REPARSE_POINT,
AT_UNNAMED, 0 ) ) AT_UNNAMED,0)) {
{ if (!(flags & XATTR_REPLACE)) {
if ( !( flags & XATTR_REPLACE ) )
{
/* /*
* no reparse data attribute : add one, * no reparse data attribute : add one,
* apparently, this does not feed the new value in * apparently, this does not feed the new value in
* Note : NTFS version must be >= 3 * Note : NTFS version must be >= 3
*/ */
if ( ni->vol->major_ver >= 3 ) if (ni->vol->major_ver >= 3) {
{
res = ntfs_attr_add(ni, res = ntfs_attr_add(ni,
AT_REPARSE_POINT, AT_REPARSE_POINT,
AT_UNNAMED,0,&dummy, AT_UNNAMED,0,&dummy,
(s64)0); (s64)0);
if ( !res ) if (!res) {
{
ni->flags |= ni->flags |=
FILE_ATTR_REPARSE_POINT; FILE_ATTR_REPARSE_POINT;
NInoFileNameSetDirty(ni); NInoFileNameSetDirty(ni);
} }
NInoSetDirty(ni); NInoSetDirty(ni);
} } else {
else
{
errno = EOPNOTSUPP; errno = EOPNOTSUPP;
res = -1; res = -1;
} }
} } else {
else
{
errno = ENODATA; errno = ENODATA;
res = -1; res = -1;
} }
} } else {
else if (flags & XATTR_CREATE) {
{
if ( flags & XATTR_CREATE )
{
errno = EEXIST; errno = EEXIST;
res = -1; res = -1;
} }
} }
if ( !res ) if (!res) {
{
/* update value and index */ /* update value and index */
res = update_reparse_data(ni,xr,value,size); res = update_reparse_data(ni,xr,value,size);
} }
@ -1224,14 +1135,10 @@ int ntfs_set_ntfs_reparse_data( ntfs_inode *ni,
NInoSetDirty(xrni); NInoSetDirty(xrni);
ntfs_index_ctx_put(xr); ntfs_index_ctx_put(xr);
ntfs_inode_close(xrni); ntfs_inode_close(xrni);
} } else {
else
{
res = -1; res = -1;
} }
} } else {
else
{
errno = EINVAL; errno = EINVAL;
res = -1; res = -1;
} }
@ -1254,36 +1161,27 @@ int ntfs_remove_ntfs_reparse_data( ntfs_inode *ni )
le32 reparse_tag; le32 reparse_tag;
res = 0; res = 0;
if ( ni ) if (ni) {
{
/* /*
* open and delete the reparse data * open and delete the reparse data
*/ */
na = ntfs_attr_open(ni, AT_REPARSE_POINT, na = ntfs_attr_open(ni, AT_REPARSE_POINT,
AT_UNNAMED,0); AT_UNNAMED,0);
if ( na ) if (na) {
{
/* first remove index (reparse data needed) */ /* first remove index (reparse data needed) */
xr = open_reparse_index(ni->vol); xr = open_reparse_index(ni->vol);
if ( xr ) if (xr) {
{
if (remove_reparse_index(na,xr, if (remove_reparse_index(na,xr,
&reparse_tag ) < 0 ) &reparse_tag) < 0) {
{
res = -1; res = -1;
} } else {
else
{
/* now remove attribute */ /* now remove attribute */
res = ntfs_attr_rm(na); res = ntfs_attr_rm(na);
if ( !res ) if (!res) {
{
ni->flags &= ni->flags &=
~FILE_ATTR_REPARSE_POINT; ~FILE_ATTR_REPARSE_POINT;
NInoFileNameSetDirty(ni); NInoFileNameSetDirty(ni);
} } else {
else
{
/* /*
* If we could not remove the * If we could not remove the
* attribute, try to restore the * attribute, try to restore the
@ -1309,16 +1207,12 @@ int ntfs_remove_ntfs_reparse_data( ntfs_inode *ni )
/* avoid errno pollution */ /* avoid errno pollution */
if (errno == ENOENT) if (errno == ENOENT)
errno = olderrno; errno = olderrno;
} } else {
else
{
errno = ENODATA; errno = ENODATA;
res = -1; res = -1;
} }
NInoSetDirty(ni); NInoSetDirty(ni);
} } else {
else
{
errno = EINVAL; errno = EINVAL;
res = -1; res = -1;
} }

View File

@ -127,24 +127,19 @@ runlist_element *ntfs_rl_extend( ntfs_attr *na, runlist_element *rl,
int last; int last;
int irl; int irl;
if ( na->rl && rl ) if (na->rl && rl) {
{
irl = (int)(rl - na->rl); irl = (int)(rl - na->rl);
last = irl; last = irl;
while (na->rl[last].length) while (na->rl[last].length)
last++; last++;
newrl = ntfs_rl_realloc(na->rl,last+1,last+more_entries+1); newrl = ntfs_rl_realloc(na->rl,last+1,last+more_entries+1);
if ( !newrl ) if (!newrl) {
{
errno = ENOMEM; errno = ENOMEM;
rl = (runlist_element*)NULL; rl = (runlist_element*)NULL;
} } else
else
na->rl = newrl; na->rl = newrl;
rl = &newrl[irl]; rl = &newrl[irl];
} } else {
else
{
ntfs_log_error("Cannot extend unmapped runlist"); ntfs_log_error("Cannot extend unmapped runlist");
errno = EIO; errno = EIO;
rl = (runlist_element*)NULL; rl = (runlist_element*)NULL;
@ -165,8 +160,7 @@ runlist_element *ntfs_rl_extend( ntfs_attr *na, runlist_element *rl,
*/ */
static BOOL ntfs_rl_are_mergeable(runlist_element *dst, runlist_element *src) static BOOL ntfs_rl_are_mergeable(runlist_element *dst, runlist_element *src)
{ {
if ( !dst || !src ) if (!dst || !src) {
{
ntfs_log_debug("Eeek. ntfs_rl_are_mergeable() invoked with NULL " ntfs_log_debug("Eeek. ntfs_rl_are_mergeable() invoked with NULL "
"pointer!\n"); "pointer!\n");
return FALSE; return FALSE;
@ -229,8 +223,7 @@ static runlist_element *ntfs_rl_append( runlist_element *dst, int dsize,
BOOL right = FALSE; /* Right end of @src needs merging */ BOOL right = FALSE; /* Right end of @src needs merging */
int marker; /* End of the inserted runs */ int marker; /* End of the inserted runs */
if ( !dst || !src ) if (!dst || !src) {
{
ntfs_log_debug("Eeek. ntfs_rl_append() invoked with NULL " ntfs_log_debug("Eeek. ntfs_rl_append() invoked with NULL "
"pointer!\n"); "pointer!\n");
errno = EINVAL; errno = EINVAL;
@ -298,8 +291,7 @@ static runlist_element *ntfs_rl_insert( runlist_element *dst, int dsize,
BOOL disc = FALSE; /* Discontinuity between @dst and @src */ BOOL disc = FALSE; /* Discontinuity between @dst and @src */
int marker; /* End of the inserted runs */ int marker; /* End of the inserted runs */
if ( !dst || !src ) if (!dst || !src) {
{
ntfs_log_debug("Eeek. ntfs_rl_insert() invoked with NULL " ntfs_log_debug("Eeek. ntfs_rl_insert() invoked with NULL "
"pointer!\n"); "pointer!\n");
errno = EINVAL; errno = EINVAL;
@ -311,8 +303,7 @@ static runlist_element *ntfs_rl_insert( runlist_element *dst, int dsize,
*/ */
if (loc == 0) if (loc == 0)
disc = (src[0].vcn > 0); disc = (src[0].vcn > 0);
else else {
{
s64 merged_length; s64 merged_length;
left = ntfs_rl_are_mergeable(dst + loc - 1, src); left = ntfs_rl_are_mergeable(dst + loc - 1, src);
@ -357,15 +348,11 @@ static runlist_element *ntfs_rl_insert( runlist_element *dst, int dsize,
dst[marker].length = dst[marker + 1].vcn - dst[marker].vcn; dst[marker].length = dst[marker + 1].vcn - dst[marker].vcn;
/* Writing beyond the end of the file and there's a discontinuity. */ /* Writing beyond the end of the file and there's a discontinuity. */
if ( disc ) if (disc) {
{ if (loc > 0) {
if ( loc > 0 )
{
dst[loc].vcn = dst[loc - 1].vcn + dst[loc - 1].length; dst[loc].vcn = dst[loc - 1].vcn + dst[loc - 1].length;
dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn; dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn;
} } else {
else
{
dst[loc].vcn = 0; dst[loc].vcn = 0;
dst[loc].length = dst[loc + 1].vcn; dst[loc].length = dst[loc + 1].vcn;
} }
@ -403,8 +390,7 @@ static runlist_element *ntfs_rl_replace( runlist_element *dst, int dsize,
int tail; /* Start of tail of @dst */ int tail; /* Start of tail of @dst */
int marker; /* End of the inserted runs */ int marker; /* End of the inserted runs */
if ( !dst || !src ) if (!dst || !src) {
{
ntfs_log_debug("Eeek. ntfs_rl_replace() invoked with NULL " ntfs_log_debug("Eeek. ntfs_rl_replace() invoked with NULL "
"pointer!\n"); "pointer!\n");
errno = EINVAL; errno = EINVAL;
@ -421,8 +407,7 @@ static runlist_element *ntfs_rl_replace( runlist_element *dst, int dsize,
* ends get merged. The -1 accounts for the run being replaced. * ends get merged. The -1 accounts for the run being replaced.
*/ */
delta = ssize - 1 - left - right; delta = ssize - 1 - left - right;
if ( delta > 0 ) if (delta > 0) {
{
dst = ntfs_rl_realloc(dst, dsize, dsize + delta); dst = ntfs_rl_realloc(dst, dsize, dsize + delta);
if (!dst) if (!dst)
return NULL; return NULL;
@ -486,8 +471,7 @@ static runlist_element *ntfs_rl_replace( runlist_element *dst, int dsize,
static runlist_element *ntfs_rl_split(runlist_element *dst, int dsize, static runlist_element *ntfs_rl_split(runlist_element *dst, int dsize,
runlist_element *src, int ssize, int loc) runlist_element *src, int ssize, int loc)
{ {
if ( !dst || !src ) if (!dst || !src) {
{
ntfs_log_debug("Eeek. ntfs_rl_split() invoked with NULL pointer!\n"); ntfs_log_debug("Eeek. ntfs_rl_split() invoked with NULL pointer!\n");
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
@ -540,12 +524,10 @@ static runlist_element *ntfs_runlists_merge_i( runlist_element *drl,
return drl; return drl;
/* Check for the case where the first mapping is being done now. */ /* Check for the case where the first mapping is being done now. */
if ( !drl ) if (!drl) {
{
drl = srl; drl = srl;
/* Complete the source runlist if necessary. */ /* Complete the source runlist if necessary. */
if ( drl[0].vcn ) if (drl[0].vcn) {
{
/* Scan to the end of the source runlist. */ /* Scan to the end of the source runlist. */
for (dend = 0; drl[dend].length; dend++) for (dend = 0; drl[dend].length; dend++)
; ;
@ -569,8 +551,7 @@ static runlist_element *ntfs_runlists_merge_i( runlist_element *drl,
si++; si++;
/* Can't have an entirely unmapped source runlist. */ /* Can't have an entirely unmapped source runlist. */
if ( !srl[si].length ) if (!srl[si].length) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s: unmapped source runlist", __FUNCTION__); ntfs_log_perror("%s: unmapped source runlist", __FUNCTION__);
return NULL; return NULL;
@ -584,8 +565,7 @@ static runlist_element *ntfs_runlists_merge_i( runlist_element *drl,
* be inserted. If we reach the end of @drl, @srl just needs to be * be inserted. If we reach the end of @drl, @srl just needs to be
* appended to @drl. * appended to @drl.
*/ */
for ( ; drl[di].length; di++ ) for (; drl[di].length; di++) {
{
if (drl[di].vcn + drl[di].length > srl[sstart].vcn) if (drl[di].vcn + drl[di].length > srl[sstart].vcn)
break; break;
} }
@ -593,8 +573,7 @@ static runlist_element *ntfs_runlists_merge_i( runlist_element *drl,
/* Sanity check for illegal overlaps. */ /* Sanity check for illegal overlaps. */
if ((drl[di].vcn == srl[si].vcn) && (drl[di].lcn >= 0) && if ((drl[di].vcn == srl[si].vcn) && (drl[di].lcn >= 0) &&
( srl[si].lcn >= 0 ) ) (srl[si].lcn >= 0)) {
{
errno = ERANGE; errno = ERANGE;
ntfs_log_perror("Run lists overlap. Cannot merge"); ntfs_log_perror("Run lists overlap. Cannot merge");
return NULL; return NULL;
@ -638,38 +617,31 @@ static runlist_element *ntfs_runlists_merge_i( runlist_element *drl,
ntfs_log_debug("start = %i, finish = %i\n", start, finish); ntfs_log_debug("start = %i, finish = %i\n", start, finish);
ntfs_log_debug("ds = %i, ss = %i, dins = %i\n", ds, ss, dins); ntfs_log_debug("ds = %i, ss = %i, dins = %i\n", ds, ss, dins);
if ( start ) if (start) {
{
if (finish) if (finish)
drl = ntfs_rl_replace(drl, ds, srl + sstart, ss, dins); drl = ntfs_rl_replace(drl, ds, srl + sstart, ss, dins);
else else
drl = ntfs_rl_insert(drl, ds, srl + sstart, ss, dins); drl = ntfs_rl_insert(drl, ds, srl + sstart, ss, dins);
} } else {
else
{
if (finish) if (finish)
drl = ntfs_rl_append(drl, ds, srl + sstart, ss, dins); drl = ntfs_rl_append(drl, ds, srl + sstart, ss, dins);
else else
drl = ntfs_rl_split(drl, ds, srl + sstart, ss, dins); drl = ntfs_rl_split(drl, ds, srl + sstart, ss, dins);
} }
if ( !drl ) if (!drl) {
{
ntfs_log_perror("Merge failed"); ntfs_log_perror("Merge failed");
return drl; return drl;
} }
free(srl); free(srl);
if ( marker ) if (marker) {
{
ntfs_log_debug("Triggering marker code.\n"); ntfs_log_debug("Triggering marker code.\n");
for (ds = dend; drl[ds].length; ds++) for (ds = dend; drl[ds].length; ds++)
; ;
/* We only need to care if @srl ended after @drl. */ /* We only need to care if @srl ended after @drl. */
if ( drl[ds].vcn <= marker_vcn ) if (drl[ds].vcn <= marker_vcn) {
{
int slots = 0; int slots = 0;
if ( drl[ds].vcn == marker_vcn ) if (drl[ds].vcn == marker_vcn) {
{
ntfs_log_debug("Old marker = %lli, replacing with " ntfs_log_debug("Old marker = %lli, replacing with "
"LCN_ENOENT.\n", "LCN_ENOENT.\n",
(long long)drl[ds].lcn); (long long)drl[ds].lcn);
@ -681,16 +653,13 @@ static runlist_element *ntfs_runlists_merge_i( runlist_element *drl,
* @drl or extend an existing one before adding the * @drl or extend an existing one before adding the
* ENOENT terminator. * ENOENT terminator.
*/ */
if ( drl[ds].lcn == ( LCN )LCN_ENOENT ) if (drl[ds].lcn == (LCN)LCN_ENOENT) {
{
ds--; ds--;
slots = 1; slots = 1;
} }
if ( drl[ds].lcn != ( LCN )LCN_RL_NOT_MAPPED ) if (drl[ds].lcn != (LCN)LCN_RL_NOT_MAPPED) {
{
/* Add an unmapped runlist element. */ /* Add an unmapped runlist element. */
if ( !slots ) if (!slots) {
{
/* FIXME/TODO: We need to have the /* FIXME/TODO: We need to have the
* extra memory already! (AIA) * extra memory already! (AIA)
*/ */
@ -711,8 +680,7 @@ static runlist_element *ntfs_runlists_merge_i( runlist_element *drl,
drl[ds].length = marker_vcn - drl[ds].vcn; drl[ds].length = marker_vcn - drl[ds].vcn;
/* Finally add the ENOENT terminator. */ /* Finally add the ENOENT terminator. */
ds++; ds++;
if ( !slots ) if (!slots) {
{
/* FIXME/TODO: We need to have the extra /* FIXME/TODO: We need to have the extra
* memory already! (AIA) * memory already! (AIA)
*/ */
@ -829,8 +797,7 @@ static runlist_element *ntfs_mapping_pairs_decompress_i( const ntfs_volume *vol,
(unsigned)le32_to_cpu(attr->type)); (unsigned)le32_to_cpu(attr->type));
/* Make sure attr exists and is non-resident. */ /* Make sure attr exists and is non-resident. */
if (!attr || !attr->non_resident || if (!attr || !attr->non_resident ||
sle64_to_cpu( attr->lowest_vcn ) < ( VCN )0 ) sle64_to_cpu(attr->lowest_vcn) < (VCN)0) {
{
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} }
@ -840,8 +807,7 @@ static runlist_element *ntfs_mapping_pairs_decompress_i( const ntfs_volume *vol,
/* Get start of the mapping pairs array. */ /* Get start of the mapping pairs array. */
buf = (const u8*)attr + le16_to_cpu(attr->mapping_pairs_offset); buf = (const u8*)attr + le16_to_cpu(attr->mapping_pairs_offset);
attr_end = (const u8*)attr + le32_to_cpu(attr->length); attr_end = (const u8*)attr + le32_to_cpu(attr->length);
if ( buf < ( const u8* )attr || buf > attr_end ) if (buf < (const u8*)attr || buf > attr_end) {
{
ntfs_log_debug("Corrupt attribute.\n"); ntfs_log_debug("Corrupt attribute.\n");
errno = EIO; errno = EIO;
return NULL; return NULL;
@ -854,27 +820,23 @@ static runlist_element *ntfs_mapping_pairs_decompress_i( const ntfs_volume *vol,
if (!rl) if (!rl)
return NULL; return NULL;
/* Insert unmapped starting element if necessary. */ /* Insert unmapped starting element if necessary. */
if ( vcn ) if (vcn) {
{
rl->vcn = (VCN)0; rl->vcn = (VCN)0;
rl->lcn = (LCN)LCN_RL_NOT_MAPPED; rl->lcn = (LCN)LCN_RL_NOT_MAPPED;
rl->length = vcn; rl->length = vcn;
rlpos++; rlpos++;
} }
while ( buf < attr_end && *buf ) while (buf < attr_end && *buf) {
{
/* /*
* Allocate more memory if needed, including space for the * Allocate more memory if needed, including space for the
* not-mapped and terminator elements. * not-mapped and terminator elements.
*/ */
if ( ( int )( ( rlpos + 3 ) * sizeof( *old_rl ) ) > rlsize ) if ((int)((rlpos + 3) * sizeof(*old_rl)) > rlsize) {
{
runlist_element *rl2; runlist_element *rl2;
rlsize += 0x1000; rlsize += 0x1000;
rl2 = realloc(rl, rlsize); rl2 = realloc(rl, rlsize);
if ( !rl2 ) if (!rl2) {
{
int eo = errno; int eo = errno;
free(rl); free(rl);
errno = eo; errno = eo;
@ -892,15 +854,12 @@ static runlist_element *ntfs_mapping_pairs_decompress_i( const ntfs_volume *vol,
* length as a signed value so that's how it is... * length as a signed value so that's how it is...
*/ */
b = *buf & 0xf; b = *buf & 0xf;
if ( b ) if (b) {
{
if (buf + b > attr_end) if (buf + b > attr_end)
goto io_error; goto io_error;
for (deltaxcn = (s8)buf[b--]; b; b--) for (deltaxcn = (s8)buf[b--]; b; b--)
deltaxcn = (deltaxcn << 8) + buf[b]; deltaxcn = (deltaxcn << 8) + buf[b];
} } else { /* The length entry is compulsory. */
else /* The length entry is compulsory. */
{
ntfs_log_debug("Missing length entry in mapping pairs " ntfs_log_debug("Missing length entry in mapping pairs "
"array.\n"); "array.\n");
deltaxcn = (s64)-1; deltaxcn = (s64)-1;
@ -909,8 +868,7 @@ static runlist_element *ntfs_mapping_pairs_decompress_i( const ntfs_volume *vol,
* Assume a negative length to indicate data corruption and * Assume a negative length to indicate data corruption and
* hence clean-up and return NULL. * hence clean-up and return NULL.
*/ */
if ( deltaxcn < 0 ) if (deltaxcn < 0) {
{
ntfs_log_debug("Invalid length in mapping pairs array.\n"); ntfs_log_debug("Invalid length in mapping pairs array.\n");
goto err_out; goto err_out;
} }
@ -928,8 +886,7 @@ static runlist_element *ntfs_mapping_pairs_decompress_i( const ntfs_volume *vol,
*/ */
if (!(*buf & 0xf0)) if (!(*buf & 0xf0))
rl[rlpos].lcn = (LCN)LCN_HOLE; rl[rlpos].lcn = (LCN)LCN_HOLE;
else else {
{
/* Get the lcn change which really can be negative. */ /* Get the lcn change which really can be negative. */
u8 b2 = *buf & 0xf; u8 b2 = *buf & 0xf;
b = b2 + ((*buf >> 4) & 0xf); b = b2 + ((*buf >> 4) & 0xf);
@ -947,8 +904,7 @@ static runlist_element *ntfs_mapping_pairs_decompress_i( const ntfs_volume *vol,
* -1. So if either is found give us a message so we * -1. So if either is found give us a message so we
* can investigate it further! * can investigate it further!
*/ */
if ( vol->major_ver < 3 ) if (vol->major_ver < 3) {
{
if (deltaxcn == (LCN)-1) if (deltaxcn == (LCN)-1)
ntfs_log_debug("lcn delta == -1\n"); ntfs_log_debug("lcn delta == -1\n");
if (lcn == (LCN)-1) if (lcn == (LCN)-1)
@ -956,8 +912,7 @@ static runlist_element *ntfs_mapping_pairs_decompress_i( const ntfs_volume *vol,
} }
#endif #endif
/* Check lcn is not below -1. */ /* Check lcn is not below -1. */
if ( lcn < ( LCN ) - 1 ) if (lcn < (LCN)-1) {
{
ntfs_log_debug("Invalid LCN < -1 in mapping pairs " ntfs_log_debug("Invalid LCN < -1 in mapping pairs "
"array.\n"); "array.\n");
goto err_out; goto err_out;
@ -977,16 +932,14 @@ static runlist_element *ntfs_mapping_pairs_decompress_i( const ntfs_volume *vol,
* vcn in the runlist - 1, or something has gone badly wrong. * vcn in the runlist - 1, or something has gone badly wrong.
*/ */
deltaxcn = sle64_to_cpu(attr->highest_vcn); deltaxcn = sle64_to_cpu(attr->highest_vcn);
if ( deltaxcn && vcn - 1 != deltaxcn ) if (deltaxcn && vcn - 1 != deltaxcn) {
{
mpa_err: mpa_err:
ntfs_log_debug("Corrupt mapping pairs array in non-resident " ntfs_log_debug("Corrupt mapping pairs array in non-resident "
"attribute.\n"); "attribute.\n");
goto err_out; goto err_out;
} }
/* Setup not mapped runlist element if this is the base extent. */ /* Setup not mapped runlist element if this is the base extent. */
if ( !attr->lowest_vcn ) if (!attr->lowest_vcn) {
{
VCN max_cluster; VCN max_cluster;
max_cluster = ((sle64_to_cpu(attr->allocated_size) + max_cluster = ((sle64_to_cpu(attr->allocated_size) +
@ -996,16 +949,14 @@ mpa_err:
* A highest_vcn of zero means this is a single extent * A highest_vcn of zero means this is a single extent
* attribute so simply terminate the runlist with LCN_ENOENT). * attribute so simply terminate the runlist with LCN_ENOENT).
*/ */
if ( deltaxcn ) if (deltaxcn) {
{
/* /*
* If there is a difference between the highest_vcn and * If there is a difference between the highest_vcn and
* the highest cluster, the runlist is either corrupt * the highest cluster, the runlist is either corrupt
* or, more likely, there are more extents following * or, more likely, there are more extents following
* this one. * this one.
*/ */
if ( deltaxcn < max_cluster ) if (deltaxcn < max_cluster) {
{
ntfs_log_debug("More extents to follow; deltaxcn = " ntfs_log_debug("More extents to follow; deltaxcn = "
"0x%llx, max_cluster = 0x%llx\n", "0x%llx, max_cluster = 0x%llx\n",
(long long)deltaxcn, (long long)deltaxcn,
@ -1014,9 +965,7 @@ mpa_err:
vcn += rl[rlpos].length = max_cluster - deltaxcn; vcn += rl[rlpos].length = max_cluster - deltaxcn;
rl[rlpos].lcn = (LCN)LCN_RL_NOT_MAPPED; rl[rlpos].lcn = (LCN)LCN_RL_NOT_MAPPED;
rlpos++; rlpos++;
} } else if (deltaxcn > max_cluster) {
else if ( deltaxcn > max_cluster )
{
ntfs_log_debug("Corrupt attribute. deltaxcn = " ntfs_log_debug("Corrupt attribute. deltaxcn = "
"0x%llx, max_cluster = 0x%llx\n", "0x%llx, max_cluster = 0x%llx\n",
(long long)deltaxcn, (long long)deltaxcn,
@ -1025,16 +974,14 @@ mpa_err:
} }
} }
rl[rlpos].lcn = (LCN)LCN_ENOENT; rl[rlpos].lcn = (LCN)LCN_ENOENT;
} } else /* Not the base extent. There may be more extents to follow. */
else /* Not the base extent. There may be more extents to follow. */
rl[rlpos].lcn = (LCN)LCN_RL_NOT_MAPPED; rl[rlpos].lcn = (LCN)LCN_RL_NOT_MAPPED;
/* Setup terminating runlist element. */ /* Setup terminating runlist element. */
rl[rlpos].vcn = vcn; rl[rlpos].vcn = vcn;
rl[rlpos].length = (s64)0; rl[rlpos].length = (s64)0;
/* If no existing runlist was specified, we are done. */ /* If no existing runlist was specified, we are done. */
if ( !old_rl ) if (!old_rl) {
{
ntfs_log_debug("Mapping pairs array successfully decompressed:\n"); ntfs_log_debug("Mapping pairs array successfully decompressed:\n");
ntfs_debug_runlist_dump(rl); ntfs_debug_runlist_dump(rl);
return rl; return rl;
@ -1104,10 +1051,8 @@ LCN ntfs_rl_vcn_to_lcn( const runlist_element *rl, const VCN vcn )
if (vcn < rl[0].vcn) if (vcn < rl[0].vcn)
return (LCN)LCN_ENOENT; return (LCN)LCN_ENOENT;
for ( i = 0; rl[i].length; i++ ) for (i = 0; rl[i].length; i++) {
{ if (vcn < rl[i+1].vcn) {
if ( vcn < rl[i+1].vcn )
{
if (rl[i].lcn >= (LCN)0) if (rl[i].lcn >= (LCN)0)
return rl[i].lcn + (vcn - rl[i].vcn); return rl[i].lcn + (vcn - rl[i].vcn);
return rl[i].lcn; return rl[i].lcn;
@ -1153,8 +1098,7 @@ s64 ntfs_rl_pread( const ntfs_volume *vol, const runlist_element *rl,
s64 bytes_read, to_read, ofs, total; s64 bytes_read, to_read, ofs, total;
int err = EIO; int err = EIO;
if ( !vol || !rl || pos < 0 || count < 0 ) if (!vol || !rl || pos < 0 || count < 0) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("Failed to read runlist [vol: %p rl: %p " ntfs_log_perror("Failed to read runlist [vol: %p rl: %p "
"pos: %lld count: %lld]", vol, rl, "pos: %lld count: %lld]", vol, rl,
@ -1169,12 +1113,10 @@ s64 ntfs_rl_pread( const ntfs_volume *vol, const runlist_element *rl,
ofs += (rl->length << vol->cluster_size_bits); ofs += (rl->length << vol->cluster_size_bits);
/* Offset in the run at which to begin reading. */ /* Offset in the run at which to begin reading. */
ofs = pos - ofs; ofs = pos - ofs;
for ( total = 0LL; count; rl++, ofs = 0 ) for (total = 0LL; count; rl++, ofs = 0) {
{
if (!rl->length) if (!rl->length)
goto rl_err_out; goto rl_err_out;
if ( rl->lcn < ( LCN )0 ) if (rl->lcn < (LCN)0) {
{
if (rl->lcn != (LCN)LCN_HOLE) if (rl->lcn != (LCN)LCN_HOLE)
goto rl_err_out; goto rl_err_out;
/* It is a hole. Just fill buffer @b with zeroes. */ /* It is a hole. Just fill buffer @b with zeroes. */
@ -1194,8 +1136,7 @@ retry:
bytes_read = ntfs_pread(vol->dev, (rl->lcn << bytes_read = ntfs_pread(vol->dev, (rl->lcn <<
vol->cluster_size_bits) + ofs, to_read, b); vol->cluster_size_bits) + ofs, to_read, b);
/* If everything ok, update progress counters and continue. */ /* If everything ok, update progress counters and continue. */
if ( bytes_read > 0 ) if (bytes_read > 0) {
{
total += bytes_read; total += bytes_read;
count -= bytes_read; count -= bytes_read;
b = (u8*)b + bytes_read; b = (u8*)b + bytes_read;
@ -1246,8 +1187,7 @@ s64 ntfs_rl_pwrite( const ntfs_volume *vol, const runlist_element *rl,
s64 written, to_write, total = 0; s64 written, to_write, total = 0;
int err = EIO; int err = EIO;
if ( !vol || !rl || pos < 0 || count < 0 ) if (!vol || !rl || pos < 0 || count < 0) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("Failed to write runlist [vol: %p rl: %p " ntfs_log_perror("Failed to write runlist [vol: %p rl: %p "
"pos: %lld count: %lld]", vol, rl, "pos: %lld count: %lld]", vol, rl,
@ -1258,19 +1198,16 @@ s64 ntfs_rl_pwrite( const ntfs_volume *vol, const runlist_element *rl,
goto out; goto out;
/* Seek in @rl to the run containing @pos. */ /* Seek in @rl to the run containing @pos. */
while (rl->length && (ofs + (rl->length << while (rl->length && (ofs + (rl->length <<
vol->cluster_size_bits ) <= pos ) ) vol->cluster_size_bits) <= pos)) {
{
ofs += (rl->length << vol->cluster_size_bits); ofs += (rl->length << vol->cluster_size_bits);
rl++; rl++;
} }
/* Offset in the run at which to begin writing. */ /* Offset in the run at which to begin writing. */
ofs = pos - ofs; ofs = pos - ofs;
for ( total = 0LL; count; rl++, ofs = 0 ) for (total = 0LL; count; rl++, ofs = 0) {
{
if (!rl->length) if (!rl->length)
goto rl_err_out; goto rl_err_out;
if ( rl->lcn < ( LCN )0 ) if (rl->lcn < (LCN)0) {
{
if (rl->lcn != (LCN)LCN_HOLE) if (rl->lcn != (LCN)LCN_HOLE)
goto rl_err_out; goto rl_err_out;
@ -1294,8 +1231,7 @@ retry:
else else
written = to_write; written = to_write;
/* If everything ok, update progress counters and continue. */ /* If everything ok, update progress counters and continue. */
if ( written > 0 ) if (written > 0) {
{
total += written; total += written;
count -= written; count -= written;
b = (u8*)b + written; b = (u8*)b + written;
@ -1339,15 +1275,12 @@ int ntfs_get_nr_significant_bytes( const s64 n )
l = (n < 0 ? ~n : n); l = (n < 0 ? ~n : n);
i = 1; i = 1;
if ( l >= 128 ) if (l >= 128) {
{
l >>= 7; l >>= 7;
do do {
{
i++; i++;
l >>= 8; l >>= 8;
} } while (l);
while ( l );
} }
return i; return i;
} }
@ -1378,17 +1311,14 @@ int ntfs_get_size_for_mapping_pairs( const ntfs_volume *vol,
LCN prev_lcn; LCN prev_lcn;
int rls; int rls;
if ( start_vcn < 0 ) if (start_vcn < 0) {
{
ntfs_log_trace("start_vcn %lld (should be >= 0)\n", ntfs_log_trace("start_vcn %lld (should be >= 0)\n",
(long long) start_vcn); (long long) start_vcn);
errno = EINVAL; errno = EINVAL;
goto errno_set; goto errno_set;
} }
if ( !rl ) if (!rl) {
{ if (start_vcn) {
if ( start_vcn )
{
ntfs_log_trace("rl NULL, start_vcn %lld (should be > 0)\n", ntfs_log_trace("rl NULL, start_vcn %lld (should be > 0)\n",
(long long) start_vcn); (long long) start_vcn);
errno = EINVAL; errno = EINVAL;
@ -1400,8 +1330,7 @@ int ntfs_get_size_for_mapping_pairs( const ntfs_volume *vol,
/* Skip to runlist element containing @start_vcn. */ /* Skip to runlist element containing @start_vcn. */
while (rl->length && start_vcn >= rl[1].vcn) while (rl->length && start_vcn >= rl[1].vcn)
rl++; rl++;
if ( ( !rl->length && start_vcn > rl->vcn ) || start_vcn < rl->vcn ) if ((!rl->length && start_vcn > rl->vcn) || start_vcn < rl->vcn) {
{
errno = EINVAL; errno = EINVAL;
goto errno_set; goto errno_set;
} }
@ -1409,8 +1338,7 @@ int ntfs_get_size_for_mapping_pairs( const ntfs_volume *vol,
/* Always need the terminating zero byte. */ /* Always need the terminating zero byte. */
rls = 1; rls = 1;
/* Do the first partial run if present. */ /* Do the first partial run if present. */
if ( start_vcn > rl->vcn ) if (start_vcn > rl->vcn) {
{
s64 delta; s64 delta;
/* We know rl->length != 0 already. */ /* We know rl->length != 0 already. */
@ -1426,8 +1354,7 @@ int ntfs_get_size_for_mapping_pairs( const ntfs_volume *vol,
* Note: this assumes that on NTFS 1.2-, holes are stored with * Note: this assumes that on NTFS 1.2-, holes are stored with
* an lcn of -1 and not a delta_lcn of -1 (unless both are -1). * an lcn of -1 and not a delta_lcn of -1 (unless both are -1).
*/ */
if ( rl->lcn >= 0 || vol->major_ver < 3 ) if (rl->lcn >= 0 || vol->major_ver < 3) {
{
prev_lcn = rl->lcn; prev_lcn = rl->lcn;
if (rl->lcn >= 0) if (rl->lcn >= 0)
prev_lcn += delta; prev_lcn += delta;
@ -1438,8 +1365,7 @@ int ntfs_get_size_for_mapping_pairs( const ntfs_volume *vol,
rl++; rl++;
} }
/* Do the full runs. */ /* Do the full runs. */
for ( ; rl->length && ( rls <= max_size ); rl++ ) for (; rl->length && (rls <= max_size); rl++) {
{
if (rl->length < 0 || rl->lcn < LCN_HOLE) if (rl->length < 0 || rl->lcn < LCN_HOLE)
goto err_out; goto err_out;
/* Header byte + length. */ /* Header byte + length. */
@ -1451,8 +1377,7 @@ int ntfs_get_size_for_mapping_pairs( const ntfs_volume *vol,
* Note: this assumes that on NTFS 1.2-, holes are stored with * Note: this assumes that on NTFS 1.2-, holes are stored with
* an lcn of -1 and not a delta_lcn of -1 (unless both are -1). * an lcn of -1 and not a delta_lcn of -1 (unless both are -1).
*/ */
if ( rl->lcn >= 0 || vol->major_ver < 3 ) if (rl->lcn >= 0 || vol->major_ver < 3) {
{
/* Change in lcn. */ /* Change in lcn. */
rls += ntfs_get_nr_significant_bytes(rl->lcn - rls += ntfs_get_nr_significant_bytes(rl->lcn -
prev_lcn); prev_lcn);
@ -1496,26 +1421,21 @@ int ntfs_write_significant_bytes( u8 *dst, const u8 *dst_max, const s64 n )
s8 j; s8 j;
i = 0; i = 0;
do do {
{
if (dst > dst_max) if (dst > dst_max)
goto err_out; goto err_out;
*dst++ = l & 0xffLL; *dst++ = l & 0xffLL;
l >>= 8; l >>= 8;
i++; i++;
} } while (l != 0LL && l != -1LL);
while ( l != 0LL && l != -1LL );
j = (n >> 8 * (i - 1)) & 0xff; j = (n >> 8 * (i - 1)) & 0xff;
/* If the sign bit is wrong, we need an extra byte. */ /* If the sign bit is wrong, we need an extra byte. */
if ( n < 0LL && j >= 0 ) if (n < 0LL && j >= 0) {
{
if (dst > dst_max) if (dst > dst_max)
goto err_out; goto err_out;
i++; i++;
*dst = (u8)-1; *dst = (u8)-1;
} } else if (n > 0LL && j < 0) {
else if ( n > 0LL && j < 0 )
{
if (dst > dst_max) if (dst > dst_max)
goto err_out; goto err_out;
i++; i++;
@ -1569,8 +1489,7 @@ int ntfs_mapping_pairs_build( const ntfs_volume *vol, u8 *dst,
if (start_vcn < 0) if (start_vcn < 0)
goto val_err; goto val_err;
if ( !rl ) if (!rl) {
{
if (start_vcn) if (start_vcn)
goto val_err; goto val_err;
if (stop_rl) if (stop_rl)
@ -1591,8 +1510,7 @@ int ntfs_mapping_pairs_build( const ntfs_volume *vol, u8 *dst,
dst_max = dst + dst_len - 1; dst_max = dst + dst_len - 1;
prev_lcn = 0; prev_lcn = 0;
/* Do the first partial run if present. */ /* Do the first partial run if present. */
if ( start_vcn > rl->vcn ) if (start_vcn > rl->vcn) {
{
s64 delta; s64 delta;
/* We know rl->length != 0 already. */ /* We know rl->length != 0 already. */
@ -1613,8 +1531,7 @@ int ntfs_mapping_pairs_build( const ntfs_volume *vol, u8 *dst,
* case on NT4. - We assume that we just need to write the lcn * case on NT4. - We assume that we just need to write the lcn
* change until someone tells us otherwise... (AIA) * change until someone tells us otherwise... (AIA)
*/ */
if ( rl->lcn >= 0 || vol->major_ver < 3 ) if (rl->lcn >= 0 || vol->major_ver < 3) {
{
prev_lcn = rl->lcn; prev_lcn = rl->lcn;
if (rl->lcn >= 0) if (rl->lcn >= 0)
prev_lcn += delta; prev_lcn += delta;
@ -1623,8 +1540,7 @@ int ntfs_mapping_pairs_build( const ntfs_volume *vol, u8 *dst,
len_len, dst_max, prev_lcn); len_len, dst_max, prev_lcn);
if (lcn_len < 0) if (lcn_len < 0)
goto size_err; goto size_err;
} } else
else
lcn_len = 0; lcn_len = 0;
dst_next = dst + len_len + lcn_len + 1; dst_next = dst + len_len + lcn_len + 1;
if (dst_next > dst_max) if (dst_next > dst_max)
@ -1637,8 +1553,7 @@ int ntfs_mapping_pairs_build( const ntfs_volume *vol, u8 *dst,
rl++; rl++;
} }
/* Do the full runs. */ /* Do the full runs. */
for ( ; rl->length; rl++ ) for (; rl->length; rl++) {
{
if (rl->length < 0 || rl->lcn < LCN_HOLE) if (rl->length < 0 || rl->lcn < LCN_HOLE)
goto err_out; goto err_out;
/* Write length. */ /* Write length. */
@ -1655,16 +1570,14 @@ int ntfs_mapping_pairs_build( const ntfs_volume *vol, u8 *dst,
* case on NT4. - We assume that we just need to write the lcn * case on NT4. - We assume that we just need to write the lcn
* change until someone tells us otherwise... (AIA) * change until someone tells us otherwise... (AIA)
*/ */
if ( rl->lcn >= 0 || vol->major_ver < 3 ) if (rl->lcn >= 0 || vol->major_ver < 3) {
{
/* Write change in lcn. */ /* Write change in lcn. */
lcn_len = ntfs_write_significant_bytes(dst + 1 + lcn_len = ntfs_write_significant_bytes(dst + 1 +
len_len, dst_max, rl->lcn - prev_lcn); len_len, dst_max, rl->lcn - prev_lcn);
if (lcn_len < 0) if (lcn_len < 0)
goto size_err; goto size_err;
prev_lcn = rl->lcn; prev_lcn = rl->lcn;
} } else
else
lcn_len = 0; lcn_len = 0;
dst_next = dst + len_len + lcn_len + 1; dst_next = dst + len_len + lcn_len + 1;
if (dst_next > dst_max) if (dst_next > dst_max)
@ -1722,8 +1635,7 @@ int ntfs_rl_truncate( runlist **arl, const VCN start_vcn )
runlist *rl; runlist *rl;
BOOL is_end = FALSE; BOOL is_end = FALSE;
if ( !arl || !*arl ) if (!arl || !*arl) {
{
errno = EINVAL; errno = EINVAL;
if (!arl) if (!arl)
ntfs_log_perror("rl_truncate error: arl: %p", arl); ntfs_log_perror("rl_truncate error: arl: %p", arl);
@ -1735,23 +1647,20 @@ int ntfs_rl_truncate( runlist **arl, const VCN start_vcn )
rl = *arl; rl = *arl;
if ( start_vcn < rl->vcn ) if (start_vcn < rl->vcn) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("Start_vcn lies outside front of runlist"); ntfs_log_perror("Start_vcn lies outside front of runlist");
return -1; return -1;
} }
/* Find the starting vcn in the run list. */ /* Find the starting vcn in the run list. */
while ( rl->length ) while (rl->length) {
{
if (start_vcn < rl[1].vcn) if (start_vcn < rl[1].vcn)
break; break;
rl++; rl++;
} }
if ( !rl->length ) if (!rl->length) {
{
errno = EIO; errno = EIO;
ntfs_log_trace("Truncating already truncated runlist?\n"); ntfs_log_trace("Truncating already truncated runlist?\n");
return -1; return -1;
@ -1765,8 +1674,7 @@ int ntfs_rl_truncate( runlist **arl, const VCN start_vcn )
* element a terminator instead of the truncated runlist * element a terminator instead of the truncated runlist
* element itself. * element itself.
*/ */
if ( rl->length ) if (rl->length) {
{
++rl; ++rl;
if (!rl->length) if (!rl->length)
is_end = TRUE; is_end = TRUE;
@ -1800,18 +1708,15 @@ int ntfs_rl_sparse( runlist *rl )
{ {
runlist *rlc; runlist *rlc;
if ( !rl ) if (!rl) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s: ", __FUNCTION__); ntfs_log_perror("%s: ", __FUNCTION__);
return -1; return -1;
} }
for (rlc = rl; rlc->length; rlc++) for (rlc = rl; rlc->length; rlc++)
if ( rlc->lcn < 0 ) if (rlc->lcn < 0) {
{ if (rlc->lcn != LCN_HOLE) {
if ( rlc->lcn != LCN_HOLE )
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s: bad runlist", __FUNCTION__); ntfs_log_perror("%s: bad runlist", __FUNCTION__);
return -1; return -1;
@ -1833,25 +1738,20 @@ s64 ntfs_rl_get_compressed_size( ntfs_volume *vol, runlist *rl )
runlist *rlc; runlist *rlc;
s64 ret = 0; s64 ret = 0;
if ( !rl ) if (!rl) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s: ", __FUNCTION__); ntfs_log_perror("%s: ", __FUNCTION__);
return -1; return -1;
} }
for ( rlc = rl; rlc->length; rlc++ ) for (rlc = rl; rlc->length; rlc++) {
{ if (rlc->lcn < 0) {
if ( rlc->lcn < 0 ) if (rlc->lcn != LCN_HOLE) {
{
if ( rlc->lcn != LCN_HOLE )
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s: bad runlist", __FUNCTION__); ntfs_log_perror("%s: bad runlist", __FUNCTION__);
return -1; return -1;
} }
} } else
else
ret += rlc->length; ret += rlc->length;
} }
return ret << vol->cluster_size_bits; return ret << vol->cluster_size_bits;
@ -1884,8 +1784,7 @@ static void test_rl_dump_runlist( const runlist_element *rl )
int i; int i;
const char *lcn_str[5] = { "HOLE", "NOTMAP", "ENOENT", "XXXX" }; const char *lcn_str[5] = { "HOLE", "NOTMAP", "ENOENT", "XXXX" };
if ( !rl ) if (!rl) {
{
printf(" Run list not present.\n"); printf(" Run list not present.\n");
return; return;
} }
@ -1894,28 +1793,24 @@ static void test_rl_dump_runlist( const runlist_element *rl )
for (len = 0; rl[len].length; len++) ; for (len = 0; rl[len].length; len++) ;
printf(" VCN LCN len\n"); printf(" VCN LCN len\n");
for ( i = 0; ; i++, rl++ ) for (i = 0; ; i++, rl++) {
{
LCN lcn = rl->lcn; LCN lcn = rl->lcn;
if ( ( abbr ) && ( len > 20 ) ) if ((abbr) && (len > 20)) {
{
if (i == 4) if (i == 4)
printf(" ...\n"); printf(" ...\n");
if ((i > 3) && (i < (len - 3))) if ((i > 3) && (i < (len - 3)))
continue; continue;
} }
if ( lcn < ( LCN )0 ) if (lcn < (LCN)0) {
{
int ind = -lcn - 1; int ind = -lcn - 1;
if (ind > -LCN_ENOENT - 1) if (ind > -LCN_ENOENT - 1)
ind = 3; ind = 3;
printf("%8lld %8s %8lld\n", printf("%8lld %8s %8lld\n",
rl->vcn, lcn_str[ind], rl->length); rl->vcn, lcn_str[ind], rl->length);
} } else
else
printf("%8lld %8lld %8lld\n", printf("%8lld %8lld %8lld\n",
rl->vcn, rl->lcn, rl->length); rl->vcn, rl->lcn, rl->length);
if (!rl->length) if (!rl->length)
@ -1967,14 +1862,12 @@ static int test_rl_read_buffer( const char *file, u8 *buf, int bufsize )
FILE *fptr; FILE *fptr;
fptr = fopen(file, "r"); fptr = fopen(file, "r");
if ( !fptr ) if (!fptr) {
{
printf("open %s\n", file); printf("open %s\n", file);
return 0; return 0;
} }
if ( fread( buf, bufsize, 1, fptr ) == 99 ) if (fread(buf, bufsize, 1, fptr) == 99) {
{
printf("read %s\n", file); printf("read %s\n", file);
return 0; return 0;
} }
@ -2008,16 +1901,13 @@ static runlist_element * test_rl_pure_src( BOOL contig, BOOL multi, int vcn, int
if (!result) if (!result)
return NULL; return NULL;
if ( multi ) if (multi) {
{
MKRL(result+0, vcn + (0*len/4), fudge + vcn + 1000 + (0*len/4), len / 4) MKRL(result+0, vcn + (0*len/4), fudge + vcn + 1000 + (0*len/4), len / 4)
MKRL(result+1, vcn + (1*len/4), fudge + vcn + 1000 + (1*len/4), len / 4) MKRL(result+1, vcn + (1*len/4), fudge + vcn + 1000 + (1*len/4), len / 4)
MKRL(result+2, vcn + (2*len/4), fudge + vcn + 1000 + (2*len/4), len / 4) MKRL(result+2, vcn + (2*len/4), fudge + vcn + 1000 + (2*len/4), len / 4)
MKRL(result+3, vcn + (3*len/4), fudge + vcn + 1000 + (3*len/4), len / 4) MKRL(result+3, vcn + (3*len/4), fudge + vcn + 1000 + (3*len/4), len / 4)
MKRL(result+4, vcn + (4*len/4), LCN_RL_NOT_MAPPED, 0) MKRL(result+4, vcn + (4*len/4), LCN_RL_NOT_MAPPED, 0)
} } else {
else
{
MKRL(result+0, vcn, fudge + vcn + 1000, len) MKRL(result+0, vcn, fudge + vcn + 1000, len)
MKRL(result+1, vcn + len, LCN_RL_NOT_MAPPED, 0) MKRL(result+1, vcn + len, LCN_RL_NOT_MAPPED, 0)
} }
@ -2046,8 +1936,7 @@ static void test_rl_pure_test( int test, BOOL contig, BOOL multi, int vcn, int l
src = test_rl_pure_src(contig, multi, vcn, len); src = test_rl_pure_src(contig, multi, vcn, len);
dst = ntfs_malloc(4096); dst = ntfs_malloc(4096);
if ( !src || !dst ) if (!src || !dst) {
{
printf("Test %2d ---------- FAILED! (no free memory?)\n", test); printf("Test %2d ---------- FAILED! (no free memory?)\n", test);
return; return;
} }
@ -2072,8 +1961,7 @@ static void test_rl_pure_test( int test, BOOL contig, BOOL multi, int vcn, int l
static void test_rl_pure(char *contig, char *multi) static void test_rl_pure(char *contig, char *multi)
{ {
/* VCN, LCN, len */ /* VCN, LCN, len */
static runlist_element file1[] = static runlist_element file1[] = {
{
{ 0, -1, 100 }, /* HOLE */ { 0, -1, 100 }, /* HOLE */
{ 100, 1100, 100 }, /* DATA */ { 100, 1100, 100 }, /* DATA */
{ 200, -1, 100 }, /* HOLE */ { 200, -1, 100 }, /* HOLE */
@ -2081,23 +1969,19 @@ static void test_rl_pure( char *contig, char *multi )
{ 400, -1, 100 }, /* HOLE */ { 400, -1, 100 }, /* HOLE */
{ 500, -3, 0 } /* NOENT */ { 500, -3, 0 } /* NOENT */
}; };
static runlist_element file2[] = static runlist_element file2[] = {
{
{ 0, 1000, 100 }, /* DATA */ { 0, 1000, 100 }, /* DATA */
{ 100, -1, 100 }, /* HOLE */ { 100, -1, 100 }, /* HOLE */
{ 200, -3, 0 } /* NOENT */ { 200, -3, 0 } /* NOENT */
}; };
static runlist_element file3[] = static runlist_element file3[] = {
{
{ 0, 1000, 100 }, /* DATA */ { 0, 1000, 100 }, /* DATA */
{ 100, -3, 0 } /* NOENT */ { 100, -3, 0 } /* NOENT */
}; };
static runlist_element file4[] = static runlist_element file4[] = {
{
{ 0, -3, 0 } /* NOENT */ { 0, -3, 0 } /* NOENT */
}; };
static runlist_element file5[] = static runlist_element file5[] = {
{
{ 0, -2, 100 }, /* NOTMAP */ { 0, -2, 100 }, /* NOTMAP */
{ 100, 1100, 100 }, /* DATA */ { 100, 1100, 100 }, /* DATA */
{ 200, -2, 100 }, /* NOTMAP */ { 200, -2, 100 }, /* NOTMAP */
@ -2105,8 +1989,7 @@ static void test_rl_pure( char *contig, char *multi )
{ 400, -2, 100 }, /* NOTMAP */ { 400, -2, 100 }, /* NOTMAP */
{ 500, -3, 0 } /* NOENT */ { 500, -3, 0 } /* NOENT */
}; };
static runlist_element file6[] = static runlist_element file6[] = {
{
{ 0, 1000, 100 }, /* DATA */ { 0, 1000, 100 }, /* DATA */
{ 100, -2, 100 }, /* NOTMAP */ { 100, -2, 100 }, /* NOTMAP */
{ 200, -3, 0 } /* NOENT */ { 200, -3, 0 } /* NOENT */
@ -2117,8 +2000,7 @@ static void test_rl_pure( char *contig, char *multi )
c = TRUE; c = TRUE;
else if (strcmp(contig, "noncontig") == 0) else if (strcmp(contig, "noncontig") == 0)
c = FALSE; c = FALSE;
else else {
{
printf("rl pure [contig|noncontig] [single|multi]\n"); printf("rl pure [contig|noncontig] [single|multi]\n");
return; return;
} }
@ -2126,8 +2008,7 @@ static void test_rl_pure( char *contig, char *multi )
m = TRUE; m = TRUE;
else if (strcmp(multi, "single") == 0) else if (strcmp(multi, "single") == 0)
m = FALSE; m = FALSE;
else else {
{
printf("rl pure [contig|noncontig] [single|multi]\n"); printf("rl pure [contig|noncontig] [single|multi]\n");
return; return;
} }

View File

@ -43,8 +43,7 @@ typedef runlist_element runlist;
* When lcn == -1 this means that the count vcns starting at vcn are not * When lcn == -1 this means that the count vcns starting at vcn are not
* physically allocated (i.e. this is a hole / data is sparse). * physically allocated (i.e. this is a hole / data is sparse).
*/ */
struct _runlist_element /* In memory vcn to lcn mapping structure element. */ struct _runlist_element {/* In memory vcn to lcn mapping structure element. */
{
VCN vcn; /* vcn = Starting virtual cluster number. */ VCN vcn; /* vcn = Starting virtual cluster number. */
LCN lcn; /* lcn = Starting logical cluster number. */ LCN lcn; /* lcn = Starting logical cluster number. */
s64 length; /* Run length in clusters. */ s64 length; /* Run length in clusters. */

File diff suppressed because it is too large Load Diff

View File

@ -50,8 +50,7 @@ typedef u32 be32;
* item in the mapping list * item in the mapping list
*/ */
struct MAPPING struct MAPPING {
{
struct MAPPING *next; struct MAPPING *next;
int xid; /* linux id : uid or gid */ int xid; /* linux id : uid or gid */
SID *sid; /* Windows id : usid or gsid */ SID *sid; /* Windows id : usid or gsid */
@ -64,8 +63,7 @@ struct MAPPING
* Note : this cache is not organized as a generic cache * Note : this cache is not organized as a generic cache
*/ */
struct CACHED_PERMISSIONS struct CACHED_PERMISSIONS {
{
uid_t uid; uid_t uid;
gid_t gid; gid_t gid;
le32 inh_fileid; le32 inh_fileid;
@ -82,8 +80,7 @@ struct CACHED_PERMISSIONS
* Entry in the permissions cache for directories with no security_id * Entry in the permissions cache for directories with no security_id
*/ */
struct CACHED_PERMISSIONS_LEGACY struct CACHED_PERMISSIONS_LEGACY {
{
struct CACHED_PERMISSIONS_LEGACY *next; struct CACHED_PERMISSIONS_LEGACY *next;
struct CACHED_PERMISSIONS_LEGACY *previous; struct CACHED_PERMISSIONS_LEGACY *previous;
void *variable; void *variable;
@ -97,8 +94,7 @@ struct CACHED_PERMISSIONS_LEGACY
* Entry in the securid cache * Entry in the securid cache
*/ */
struct CACHED_SECURID struct CACHED_SECURID {
{
struct CACHED_SECURID *next; struct CACHED_SECURID *next;
struct CACHED_SECURID *previous; struct CACHED_SECURID *previous;
void *variable; void *variable;
@ -115,8 +111,7 @@ struct CACHED_SECURID
* (has no cache structure by itself) * (has no cache structure by itself)
*/ */
struct CACHED_PERMISSIONS_HEADER struct CACHED_PERMISSIONS_HEADER {
{
unsigned int last; unsigned int last;
/* statistics for permissions */ /* statistics for permissions */
unsigned long p_writes; unsigned long p_writes;
@ -128,8 +123,7 @@ struct CACHED_PERMISSIONS_HEADER
* The whole permissions cache * The whole permissions cache
*/ */
struct PERMISSIONS_CACHE struct PERMISSIONS_CACHE {
{
struct CACHED_PERMISSIONS_HEADER head; struct CACHED_PERMISSIONS_HEADER head;
struct CACHED_PERMISSIONS *cachetable[1]; /* array of variable size */ struct CACHED_PERMISSIONS *cachetable[1]; /* array of variable size */
} ; } ;
@ -138,8 +132,7 @@ struct PERMISSIONS_CACHE
* Security flags values * Security flags values
*/ */
enum enum {
{
SECURITY_DEFAULT, /* rely on fuse for permissions checking */ SECURITY_DEFAULT, /* rely on fuse for permissions checking */
SECURITY_RAW, /* force same ownership/permissions on files */ SECURITY_RAW, /* force same ownership/permissions on files */
SECURITY_ADDSECURIDS, /* upgrade old security descriptors */ SECURITY_ADDSECURIDS, /* upgrade old security descriptors */
@ -153,8 +146,7 @@ enum
enum { MAPUSERS, MAPGROUPS, MAPCOUNT } ; enum { MAPUSERS, MAPGROUPS, MAPCOUNT } ;
struct SECURITY_CONTEXT struct SECURITY_CONTEXT {
{
ntfs_volume *vol; ntfs_volume *vol;
struct MAPPING *mapping[MAPCOUNT]; struct MAPPING *mapping[MAPCOUNT];
struct PERMISSIONS_CACHE **pseccache; struct PERMISSIONS_CACHE **pseccache;
@ -170,23 +162,20 @@ struct SECURITY_CONTEXT
* Posix ACL structures * Posix ACL structures
*/ */
struct POSIX_ACE struct POSIX_ACE {
{
u16 tag; u16 tag;
u16 perms; u16 perms;
s32 id; s32 id;
} ; } ;
struct POSIX_ACL struct POSIX_ACL {
{
u8 version; u8 version;
u8 flags; u8 flags;
u16 filler; u16 filler;
struct POSIX_ACE ace[0]; struct POSIX_ACE ace[0];
} ; } ;
struct POSIX_SECURITY struct POSIX_SECURITY {
{
mode_t mode; mode_t mode;
int acccnt; int acccnt;
int defcnt; int defcnt;
@ -199,8 +188,7 @@ struct POSIX_SECURITY
* Posix tags, cpu-endian 16 bits * Posix tags, cpu-endian 16 bits
*/ */
enum enum {
{
POSIX_ACL_USER_OBJ = 1, POSIX_ACL_USER_OBJ = 1,
POSIX_ACL_USER = 2, POSIX_ACL_USER = 2,
POSIX_ACL_GROUP_OBJ = 4, POSIX_ACL_GROUP_OBJ = 4,
@ -216,8 +204,7 @@ enum
* Posix permissions, cpu-endian 16 bits * Posix permissions, cpu-endian 16 bits
*/ */
enum enum {
{
POSIX_PERM_X = 1, POSIX_PERM_X = 1,
POSIX_PERM_W = 2, POSIX_PERM_W = 2,
POSIX_PERM_R = 4, POSIX_PERM_R = 4,
@ -323,8 +310,7 @@ int ntfs_set_ntfs_attrib( ntfs_inode *ni,
#define MAGIC_API 0x09042009 #define MAGIC_API 0x09042009
struct SECURITY_API struct SECURITY_API {
{
u32 magic; u32 magic;
struct SECURITY_CONTEXT security; struct SECURITY_CONTEXT security;
struct PERMISSIONS_CACHE *seccache; struct PERMISSIONS_CACHE *seccache;

View File

@ -92,8 +92,7 @@ typedef sle64 leLSN;
/** /**
* enum BOOL - These are just to make the code more readable... * enum BOOL - These are just to make the code more readable...
*/ */
typedef enum typedef enum {
{
#ifndef FALSE #ifndef FALSE
FALSE = 0, FALSE = 0,
#endif #endif
@ -119,8 +118,7 @@ typedef enum
/** /**
* enum IGNORE_CASE_BOOL - * enum IGNORE_CASE_BOOL -
*/ */
typedef enum typedef enum {
{
CASE_SENSITIVE = 0, CASE_SENSITIVE = 0,
IGNORE_CASE = 1, IGNORE_CASE = 1,
} IGNORE_CASE_BOOL; } IGNORE_CASE_BOOL;

View File

@ -88,8 +88,7 @@ static int nfconvert_utf8 = 1;
* characters are (in)valid. * characters are (in)valid.
*/ */
#if 0 #if 0
static const u8 legal_ansi_char_array[0x40] = static const u8 legal_ansi_char_array[0x40] = {
{
0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
@ -159,25 +158,20 @@ int ntfs_names_full_collate( const ntfschar *name1, const u32 name1_len,
u16 u1, u2; u16 u1, u2;
#ifdef DEBUG #ifdef DEBUG
if ( !name1 || !name2 || ( ic && ( !upcase || !upcase_len ) ) ) if (!name1 || !name2 || (ic && (!upcase || !upcase_len))) {
{
ntfs_log_debug("ntfs_names_collate received NULL pointer!\n"); ntfs_log_debug("ntfs_names_collate received NULL pointer!\n");
exit(1); exit(1);
} }
#endif #endif
cnt = min(name1_len, name2_len); cnt = min(name1_len, name2_len);
if ( cnt > 0 ) if (cnt > 0) {
{ if (ic == CASE_SENSITIVE) {
if ( ic == CASE_SENSITIVE ) do {
{
do
{
c1 = le16_to_cpu(*name1); c1 = le16_to_cpu(*name1);
name1++; name1++;
c2 = le16_to_cpu(*name2); c2 = le16_to_cpu(*name2);
name2++; name2++;
} } while (--cnt && (c1 == c2));
while ( --cnt && ( c1 == c2 ) );
u1 = c1; u1 = c1;
u2 = c2; u2 = c2;
if (u1 < upcase_len) if (u1 < upcase_len)
@ -185,8 +179,7 @@ int ntfs_names_full_collate( const ntfschar *name1, const u32 name1_len,
if (u2 < upcase_len) if (u2 < upcase_len)
u2 = le16_to_cpu(upcase[u2]); u2 = le16_to_cpu(upcase[u2]);
if ((u1 == u2) && cnt) if ((u1 == u2) && cnt)
do do {
{
u1 = le16_to_cpu(*name1); u1 = le16_to_cpu(*name1);
name1++; name1++;
u2 = le16_to_cpu(*name2); u2 = le16_to_cpu(*name2);
@ -195,8 +188,7 @@ int ntfs_names_full_collate( const ntfschar *name1, const u32 name1_len,
u1 = le16_to_cpu(upcase[u1]); u1 = le16_to_cpu(upcase[u1]);
if (u2 < upcase_len) if (u2 < upcase_len)
u2 = le16_to_cpu(upcase[u2]); u2 = le16_to_cpu(upcase[u2]);
} } while ((u1 == u2) && --cnt);
while ( ( u1 == u2 ) && --cnt );
if (u1 < u2) if (u1 < u2)
return -1; return -1;
if (u1 > u2) if (u1 > u2)
@ -209,11 +201,8 @@ int ntfs_names_full_collate( const ntfschar *name1, const u32 name1_len,
return -1; return -1;
if (c1 > c2) if (c1 > c2)
return 1; return 1;
} } else {
else do {
{
do
{
u1 = c1 = le16_to_cpu(*name1); u1 = c1 = le16_to_cpu(*name1);
name1++; name1++;
u2 = c2 = le16_to_cpu(*name2); u2 = c2 = le16_to_cpu(*name2);
@ -222,8 +211,7 @@ int ntfs_names_full_collate( const ntfschar *name1, const u32 name1_len,
u1 = le16_to_cpu(upcase[u1]); u1 = le16_to_cpu(upcase[u1]);
if (u2 < upcase_len) if (u2 < upcase_len)
u2 = le16_to_cpu(upcase[u2]); u2 = le16_to_cpu(upcase[u2]);
} } while ((u1 == u2) && --cnt);
while ( ( u1 == u2 ) && --cnt );
if (u1 < u2) if (u1 < u2)
return -1; return -1;
if (u1 > u2) if (u1 > u2)
@ -233,9 +221,7 @@ int ntfs_names_full_collate( const ntfschar *name1, const u32 name1_len,
if (name1_len > name2_len) if (name1_len > name2_len)
return 1; return 1;
} }
} } else {
else
{
if (name1_len < name2_len) if (name1_len < name2_len)
return -1; return -1;
if (name1_len > name2_len) if (name1_len > name2_len)
@ -264,14 +250,12 @@ int ntfs_ucsncmp( const ntfschar *s1, const ntfschar *s2, size_t n )
size_t i; size_t i;
#ifdef DEBUG #ifdef DEBUG
if ( !s1 || !s2 ) if (!s1 || !s2) {
{
ntfs_log_debug("ntfs_wcsncmp() received NULL pointer!\n"); ntfs_log_debug("ntfs_wcsncmp() received NULL pointer!\n");
exit(1); exit(1);
} }
#endif #endif
for ( i = 0; i < n; ++i ) for (i = 0; i < n; ++i) {
{
c1 = le16_to_cpu(s1[i]); c1 = le16_to_cpu(s1[i]);
c2 = le16_to_cpu(s2[i]); c2 = le16_to_cpu(s2[i]);
if (c1 < c2) if (c1 < c2)
@ -309,14 +293,12 @@ int ntfs_ucsncasecmp( const ntfschar *s1, const ntfschar *s2, size_t n,
size_t i; size_t i;
#ifdef DEBUG #ifdef DEBUG
if ( !s1 || !s2 || !upcase ) if (!s1 || !s2 || !upcase) {
{
ntfs_log_debug("ntfs_wcsncasecmp() received NULL pointer!\n"); ntfs_log_debug("ntfs_wcsncasecmp() received NULL pointer!\n");
exit(1); exit(1);
} }
#endif #endif
for ( i = 0; i < n; ++i ) for (i = 0; i < n; ++i) {
{
if ((c1 = le16_to_cpu(s1[i])) < upcase_size) if ((c1 = le16_to_cpu(s1[i])) < upcase_size)
c1 = le16_to_cpu(upcase[c1]); c1 = le16_to_cpu(upcase[c1]);
if ((c2 = le16_to_cpu(s2[i])) < upcase_size) if ((c2 = le16_to_cpu(s2[i])) < upcase_size)
@ -347,8 +329,7 @@ u32 ntfs_ucsnlen( const ntfschar *s, u32 maxlen )
{ {
u32 i; u32 i;
for ( i = 0; i < maxlen; i++ ) for (i = 0; i < maxlen; i++) {
{
if (!le16_to_cpu(s[i])) if (!le16_to_cpu(s[i]))
break; break;
} }
@ -379,8 +360,7 @@ ntfschar *ntfs_ucsndup( const ntfschar *s, u32 maxlen )
len = ntfs_ucsnlen(s, maxlen); len = ntfs_ucsnlen(s, maxlen);
dst = ntfs_malloc((len + 1) * sizeof(ntfschar)); dst = ntfs_malloc((len + 1) * sizeof(ntfschar));
if ( dst ) if (dst) {
{
memcpy(dst, s, len * sizeof(ntfschar)); memcpy(dst, s, len * sizeof(ntfschar));
dst[len] = cpu_to_le16(L'\0'); dst[len] = cpu_to_le16(L'\0');
} }
@ -478,20 +458,16 @@ static int utf16_to_utf8_size( const ntfschar *ins, const int ins_len, int outs_
BOOL surrog; BOOL surrog;
surrog = FALSE; surrog = FALSE;
for ( i = 0; i < ins_len && ins[i]; i++ ) for (i = 0; i < ins_len && ins[i]; i++) {
{
unsigned short c = le16_to_cpu(ins[i]); unsigned short c = le16_to_cpu(ins[i]);
if ( surrog ) if (surrog) {
{ if ((c >= 0xdc00) && (c < 0xe000)) {
if ( ( c >= 0xdc00 ) && ( c < 0xe000 ) )
{
surrog = FALSE; surrog = FALSE;
count += 4; count += 4;
} } else
else
goto fail; goto fail;
} } else
else if ( c < 0x80 ) if (c < 0x80)
count++; count++;
else if (c < 0x800) else if (c < 0x800)
count += 2; count += 2;
@ -507,8 +483,7 @@ static int utf16_to_utf8_size( const ntfschar *ins, const int ins_len, int outs_
count += 3; count += 3;
else else
goto fail; goto fail;
if ( count > outs_len ) if (count > outs_len) {
{
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
goto out; goto out;
} }
@ -556,8 +531,7 @@ static int ntfs_utf16_to_utf8( const ntfschar *ins, const int ins_len,
if (size < 0) if (size < 0)
goto out; goto out;
if ( !*outs ) if (!*outs) {
{
outs_len = size + 1; outs_len = size + 1;
*outs = ntfs_malloc(outs_len); *outs = ntfs_malloc(outs_len);
if (!*outs) if (!*outs)
@ -566,49 +540,35 @@ static int ntfs_utf16_to_utf8( const ntfschar *ins, const int ins_len,
t = *outs; t = *outs;
for ( i = 0; i < ins_len && ins[i]; i++ ) for (i = 0; i < ins_len && ins[i]; i++) {
{
unsigned short c = le16_to_cpu(ins[i]); unsigned short c = le16_to_cpu(ins[i]);
/* size not double-checked */ /* size not double-checked */
if ( halfpair ) if (halfpair) {
{ if ((c >= 0xdc00) && (c < 0xe000)) {
if ( ( c >= 0xdc00 ) && ( c < 0xe000 ) )
{
*t++ = 0xf0 + (((halfpair + 64) >> 8) & 7); *t++ = 0xf0 + (((halfpair + 64) >> 8) & 7);
*t++ = 0x80 + (((halfpair + 64) >> 2) & 63); *t++ = 0x80 + (((halfpair + 64) >> 2) & 63);
*t++ = 0x80 + ((c >> 6) & 15) + ((halfpair & 3) << 4); *t++ = 0x80 + ((c >> 6) & 15) + ((halfpair & 3) << 4);
*t++ = 0x80 + (c & 63); *t++ = 0x80 + (c & 63);
halfpair = 0; halfpair = 0;
} } else
else
goto fail; goto fail;
} } else if (c < 0x80) {
else if ( c < 0x80 )
{
*t++ = c; *t++ = c;
} } else {
else if (c < 0x800) {
{
if ( c < 0x800 )
{
*t++ = (0xc0 | ((c >> 6) & 0x3f)); *t++ = (0xc0 | ((c >> 6) & 0x3f));
*t++ = 0x80 | (c & 0x3f); *t++ = 0x80 | (c & 0x3f);
} } else if (c < 0xd800) {
else if ( c < 0xd800 )
{
*t++ = 0xe0 | (c >> 12); *t++ = 0xe0 | (c >> 12);
*t++ = 0x80 | ((c >> 6) & 0x3f); *t++ = 0x80 | ((c >> 6) & 0x3f);
*t++ = 0x80 | (c & 0x3f); *t++ = 0x80 | (c & 0x3f);
} } else if (c < 0xdc00)
else if ( c < 0xdc00 )
halfpair = c; halfpair = c;
else if ( c >= 0xe000 ) else if (c >= 0xe000) {
{
*t++ = 0xe0 | (c >> 12); *t++ = 0xe0 | (c >> 12);
*t++ = 0x80 | ((c >> 6) & 0x3f); *t++ = 0x80 | ((c >> 6) & 0x3f);
*t++ = 0x80 | (c & 0x3f); *t++ = 0x80 | (c & 0x3f);
} } else
else
goto fail; goto fail;
} }
} }
@ -616,21 +576,17 @@ static int ntfs_utf16_to_utf8( const ntfschar *ins, const int ins_len,
#if defined(__APPLE__) || defined(__DARWIN__) #if defined(__APPLE__) || defined(__DARWIN__)
#ifdef ENABLE_NFCONV #ifdef ENABLE_NFCONV
if ( nfconvert_utf8 && ( t - *outs ) > 0 ) if(nfconvert_utf8 && (t - *outs) > 0) {
{
char *new_outs = NULL; char *new_outs = NULL;
int new_outs_len = ntfs_macosx_normalize_utf8(*outs, &new_outs, 0); // Normalize to decomposed form int new_outs_len = ntfs_macosx_normalize_utf8(*outs, &new_outs, 0); // Normalize to decomposed form
if ( new_outs_len >= 0 && new_outs != NULL ) if(new_outs_len >= 0 && new_outs != NULL) {
{ if(original_outs_value != *outs) {
if ( original_outs_value != *outs )
{
// We have allocated outs ourselves. // We have allocated outs ourselves.
free(*outs); free(*outs);
*outs = new_outs; *outs = new_outs;
t = *outs + new_outs_len; t = *outs + new_outs_len;
} }
else else {
{
// We need to copy new_outs into the fixed outs buffer. // We need to copy new_outs into the fixed outs buffer.
memset(*outs, 0, original_outs_len); memset(*outs, 0, original_outs_len);
strncpy(*outs, new_outs, original_outs_len-1); strncpy(*outs, new_outs, original_outs_len-1);
@ -638,8 +594,7 @@ static int ntfs_utf16_to_utf8( const ntfschar *ins, const int ins_len,
free(new_outs); free(new_outs);
} }
} }
else else {
{
ntfs_log_error("Failed to normalize NTFS string to UTF-8 NFD: %s\n", *outs); ntfs_log_error("Failed to normalize NTFS string to UTF-8 NFD: %s\n", *outs);
ntfs_log_error(" new_outs=0x%p\n", new_outs); ntfs_log_error(" new_outs=0x%p\n", new_outs);
ntfs_log_error(" new_outs_len=%d\n", new_outs_len); ntfs_log_error(" new_outs_len=%d\n", new_outs_len);
@ -671,14 +626,11 @@ static int utf8_to_utf16_size( const char *s )
unsigned int byte; unsigned int byte;
size_t count = 0; size_t count = 0;
while ( ( byte = *( ( const unsigned char * )s++ ) ) ) while ((byte = *((const unsigned char *)s++))) {
{
if (++count >= PATH_MAX) if (++count >= PATH_MAX)
goto fail; goto fail;
if ( byte >= 0xc0 ) if (byte >= 0xc0) {
{ if (byte >= 0xF5) {
if ( byte >= 0xF5 )
{
errno = EILSEQ; errno = EILSEQ;
goto out; goto out;
} }
@ -692,8 +644,7 @@ static int utf8_to_utf16_size( const char *s )
s++; s++;
if (!*s) if (!*s)
break; break;
if ( byte >= 0xF0 ) if (byte >= 0xF0) {
{
s++; s++;
if (++count >= PATH_MAX) if (++count >= PATH_MAX)
goto fail; goto fail;
@ -719,37 +670,25 @@ static int utf8_to_unicode( u32 *wc, const char *s )
unsigned int byte = *((const unsigned char *)s); unsigned int byte = *((const unsigned char *)s);
/* single byte */ /* single byte */
if ( byte == 0 ) if (byte == 0) {
{
*wc = (u32) 0; *wc = (u32) 0;
return 0; return 0;
} } else if (byte < 0x80) {
else if ( byte < 0x80 )
{
*wc = (u32) byte; *wc = (u32) byte;
return 1; return 1;
/* double byte */ /* double byte */
} } else if (byte < 0xc2) {
else if ( byte < 0xc2 )
{
goto fail; goto fail;
} } else if (byte < 0xE0) {
else if ( byte < 0xE0 ) if ((s[1] & 0xC0) == 0x80) {
{
if ( ( s[1] & 0xC0 ) == 0x80 )
{
*wc = ((u32)(byte & 0x1F) << 6) *wc = ((u32)(byte & 0x1F) << 6)
| ((u32)(s[1] & 0x3F)); | ((u32)(s[1] & 0x3F));
return 2; return 2;
} } else
else
goto fail; goto fail;
/* three-byte */ /* three-byte */
} } else if (byte < 0xF0) {
else if ( byte < 0xF0 ) if (((s[1] & 0xC0) == 0x80) && ((s[2] & 0xC0) == 0x80)) {
{
if ( ( ( s[1] & 0xC0 ) == 0x80 ) && ( ( s[2] & 0xC0 ) == 0x80 ) )
{
*wc = ((u32)(byte & 0x0F) << 12) *wc = ((u32)(byte & 0x0F) << 12)
| ((u32)(s[1] & 0x3F) << 6) | ((u32)(s[1] & 0x3F) << 6)
| ((u32)(s[2] & 0x3F)); | ((u32)(s[2] & 0x3F));
@ -766,12 +705,9 @@ static int utf8_to_unicode( u32 *wc, const char *s )
} }
goto fail; goto fail;
/* four-byte */ /* four-byte */
} } else if (byte < 0xF5) {
else if ( byte < 0xF5 )
{
if (((s[1] & 0xC0) == 0x80) && ((s[2] & 0xC0) == 0x80) if (((s[1] & 0xC0) == 0x80) && ((s[2] & 0xC0) == 0x80)
&& ( ( s[3] & 0xC0 ) == 0x80 ) ) && ((s[3] & 0xC0) == 0x80)) {
{
*wc = ((u32)(byte & 0x07) << 18) *wc = ((u32)(byte & 0x07) << 18)
| ((u32)(s[1] & 0x3F) << 12) | ((u32)(s[1] & 0x3F) << 12)
| ((u32)(s[2] & 0x3F) << 6) | ((u32)(s[2] & 0x3F) << 6)
@ -800,8 +736,7 @@ static int ntfs_utf8_to_utf16( const char *ins, ntfschar **outs )
#if defined(__APPLE__) || defined(__DARWIN__) #if defined(__APPLE__) || defined(__DARWIN__)
#ifdef ENABLE_NFCONV #ifdef ENABLE_NFCONV
char *new_ins = NULL; char *new_ins = NULL;
if ( nfconvert_utf8 ) if(nfconvert_utf8) {
{
int new_ins_len; int new_ins_len;
new_ins_len = ntfs_macosx_normalize_utf8(ins, &new_ins, 1); // Normalize to composed form new_ins_len = ntfs_macosx_normalize_utf8(ins, &new_ins, 1); // Normalize to composed form
if(new_ins_len >= 0) if(new_ins_len >= 0)
@ -822,8 +757,7 @@ static int ntfs_utf8_to_utf16( const char *ins, ntfschar **outs )
goto fail; goto fail;
allocated = FALSE; allocated = FALSE;
if ( !*outs ) if (!*outs) {
{
*outs = ntfs_malloc((shorts + 1) * sizeof(ntfschar)); *outs = ntfs_malloc((shorts + 1) * sizeof(ntfschar));
if (!*outs) if (!*outs)
goto fail; goto fail;
@ -832,16 +766,12 @@ static int ntfs_utf8_to_utf16( const char *ins, ntfschar **outs )
outpos = *outs; outpos = *outs;
while ( 1 ) while(1) {
{
int m = utf8_to_unicode(&wc, t); int m = utf8_to_unicode(&wc, t);
if ( m <= 0 ) if (m <= 0) {
{ if (m < 0) {
if ( m < 0 )
{
/* do not leave space allocated if failed */ /* do not leave space allocated if failed */
if ( allocated ) if (allocated) {
{
free(*outs); free(*outs);
*outs = (ntfschar*)NULL; *outs = (ntfschar*)NULL;
} }
@ -852,8 +782,7 @@ static int ntfs_utf8_to_utf16( const char *ins, ntfschar **outs )
} }
if (wc < 0x10000) if (wc < 0x10000)
*outpos++ = cpu_to_le16(wc); *outpos++ = cpu_to_le16(wc);
else else {
{
wc -= 0x10000; wc -= 0x10000;
*outpos++ = cpu_to_le16((wc >> 10) + 0xd800); *outpos++ = cpu_to_le16((wc >> 10) + 0xd800);
*outpos++ = cpu_to_le16((wc & 0x3ff) + 0xdc00); *outpos++ = cpu_to_le16((wc & 0x3ff) + 0xdc00);
@ -908,22 +837,19 @@ int ntfs_ucstombs( const ntfschar *ins, const int ins_len, char **outs,
mbstate_t mbstate; mbstate_t mbstate;
#endif #endif
if ( !ins || !outs ) if (!ins || !outs) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
mbs = *outs; mbs = *outs;
mbs_len = outs_len; mbs_len = outs_len;
if ( mbs && !mbs_len ) if (mbs && !mbs_len) {
{
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
return -1; return -1;
} }
if (use_utf8) if (use_utf8)
return ntfs_utf16_to_utf8(ins, ins_len, outs, outs_len); return ntfs_utf16_to_utf8(ins, ins_len, outs, outs_len);
if ( !mbs ) if (!mbs) {
{
mbs_len = (ins_len + 1) * MB_CUR_MAX; mbs_len = (ins_len + 1) * MB_CUR_MAX;
mbs = ntfs_malloc(mbs_len); mbs = ntfs_malloc(mbs_len);
if (!mbs) if (!mbs)
@ -934,14 +860,11 @@ int ntfs_ucstombs( const ntfschar *ins, const int ins_len, char **outs,
#else #else
wctomb(NULL, 0); wctomb(NULL, 0);
#endif #endif
for ( i = o = 0; i < ins_len; i++ ) for (i = o = 0; i < ins_len; i++) {
{
/* Reallocate memory if necessary or abort. */ /* Reallocate memory if necessary or abort. */
if ( ( int )( o + MB_CUR_MAX ) > mbs_len ) if ((int)(o + MB_CUR_MAX) > mbs_len) {
{
char *tc; char *tc;
if ( mbs == *outs ) if (mbs == *outs) {
{
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
return -1; return -1;
} }
@ -965,8 +888,7 @@ int ntfs_ucstombs( const ntfschar *ins, const int ins_len, char **outs,
#endif #endif
if (cnt == -1) if (cnt == -1)
goto err_out; goto err_out;
if ( cnt <= 0 ) if (cnt <= 0) {
{
ntfs_log_debug("Eeek. cnt <= 0, cnt = %i\n", cnt); ntfs_log_debug("Eeek. cnt <= 0, cnt = %i\n", cnt);
errno = EINVAL; errno = EINVAL;
goto err_out; goto err_out;
@ -975,8 +897,7 @@ int ntfs_ucstombs( const ntfschar *ins, const int ins_len, char **outs,
} }
#ifdef HAVE_MBSINIT #ifdef HAVE_MBSINIT
/* Make sure we are back in the initial state. */ /* Make sure we are back in the initial state. */
if ( !mbsinit( &mbstate ) ) if (!mbsinit(&mbstate)) {
{
ntfs_log_debug("Eeek. mbstate not in initial state!\n"); ntfs_log_debug("Eeek. mbstate not in initial state!\n");
errno = EILSEQ; errno = EILSEQ;
goto err_out; goto err_out;
@ -988,8 +909,7 @@ int ntfs_ucstombs( const ntfschar *ins, const int ins_len, char **outs,
*outs = mbs; *outs = mbs;
return o; return o;
err_out: err_out:
if ( mbs != *outs ) if (mbs != *outs) {
{
int eo = errno; int eo = errno;
free(mbs); free(mbs);
errno = eo; errno = eo;
@ -1030,8 +950,7 @@ int ntfs_mbstoucs( const char *ins, ntfschar **outs )
mbstate_t mbstate; mbstate_t mbstate;
#endif #endif
if ( !ins || !outs ) if (!ins || !outs) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@ -1047,8 +966,7 @@ int ntfs_mbstoucs( const char *ins, ntfschar **outs )
memset(&mbstate, 0, sizeof(mbstate)); memset(&mbstate, 0, sizeof(mbstate));
ins_len = mbsrtowcs(NULL, (const char **)&s, 0, &mbstate); ins_len = mbsrtowcs(NULL, (const char **)&s, 0, &mbstate);
#ifdef __CYGWIN32__ #ifdef __CYGWIN32__
if ( !ins_len && *ins ) if (!ins_len && *ins) {
{
/* Older Cygwin had broken mbsrtowcs() implementation. */ /* Older Cygwin had broken mbsrtowcs() implementation. */
ins_len = strlen(ins); ins_len = strlen(ins);
} }
@ -1062,11 +980,9 @@ int ntfs_mbstoucs( const char *ins, ntfschar **outs )
if (ins_len == -1) if (ins_len == -1)
return ins_len; return ins_len;
#ifdef HAVE_MBSINIT #ifdef HAVE_MBSINIT
if ( ( s != ins ) || !mbsinit( &mbstate ) ) if ((s != ins) || !mbsinit(&mbstate)) {
{
#else #else
if ( s != ins ) if (s != ins) {
{
#endif #endif
errno = EILSEQ; errno = EILSEQ;
return -1; return -1;
@ -1082,11 +998,9 @@ int ntfs_mbstoucs( const char *ins, ntfschar **outs )
#else #else
mbtowc(NULL, NULL, 0); mbtowc(NULL, NULL, 0);
#endif #endif
for ( i = o = cnt = 0; i < ins_size; i += cnt, o++ ) for (i = o = cnt = 0; i < ins_size; i += cnt, o++) {
{
/* Reallocate memory if necessary. */ /* Reallocate memory if necessary. */
if ( o >= ucs_len ) if (o >= ucs_len) {
{
ntfschar *tc; ntfschar *tc;
ucs_len = (ucs_len * sizeof(ntfschar) + 64) & ~63; ucs_len = (ucs_len * sizeof(ntfschar) + 64) & ~63;
tc = realloc(ucs, ucs_len); tc = realloc(ucs, ucs_len);
@ -1105,16 +1019,14 @@ int ntfs_mbstoucs( const char *ins, ntfschar **outs )
break; break;
if (cnt == -1) if (cnt == -1)
goto err_out; goto err_out;
if ( cnt < -1 ) if (cnt < -1) {
{
ntfs_log_trace("Eeek. cnt = %i\n", cnt); ntfs_log_trace("Eeek. cnt = %i\n", cnt);
errno = EINVAL; errno = EINVAL;
goto err_out; goto err_out;
} }
/* Make sure we are not overflowing the NTFS Unicode set. */ /* Make sure we are not overflowing the NTFS Unicode set. */
if ((unsigned long)wc >= (unsigned long)(1 << if ((unsigned long)wc >= (unsigned long)(1 <<
( 8 * sizeof( ntfschar ) ) ) ) (8 * sizeof(ntfschar)))) {
{
errno = EILSEQ; errno = EILSEQ;
goto err_out; goto err_out;
} }
@ -1123,8 +1035,7 @@ int ntfs_mbstoucs( const char *ins, ntfschar **outs )
} }
#ifdef HAVE_MBSINIT #ifdef HAVE_MBSINIT
/* Make sure we are back in the initial state. */ /* Make sure we are back in the initial state. */
if ( !mbsinit( &mbstate ) ) if (!mbsinit(&mbstate)) {
{
ntfs_log_trace("Eeek. mbstate not in initial state!\n"); ntfs_log_trace("Eeek. mbstate not in initial state!\n");
errno = EILSEQ; errno = EILSEQ;
goto err_out; goto err_out;
@ -1158,32 +1069,24 @@ char *ntfs_uppercase_mbs( const char *low,
size = strlen(low); size = strlen(low);
upp = (char*)ntfs_malloc(3*size + 1); upp = (char*)ntfs_malloc(3*size + 1);
if ( upp ) if (upp) {
{
s = low; s = low;
t = upp; t = upp;
do do {
{
n = utf8_to_unicode(&wc, s); n = utf8_to_unicode(&wc, s);
if ( n > 0 ) if (n > 0) {
{
if (wc < upcase_size) if (wc < upcase_size)
wc = le16_to_cpu(upcase[wc]); wc = le16_to_cpu(upcase[wc]);
if (wc < 0x80) if (wc < 0x80)
*t++ = wc; *t++ = wc;
else if ( wc < 0x800 ) else if (wc < 0x800) {
{
*t++ = (0xc0 | ((wc >> 6) & 0x3f)); *t++ = (0xc0 | ((wc >> 6) & 0x3f));
*t++ = 0x80 | (wc & 0x3f); *t++ = 0x80 | (wc & 0x3f);
} } else if (wc < 0x10000) {
else if ( wc < 0x10000 )
{
*t++ = 0xe0 | (wc >> 12); *t++ = 0xe0 | (wc >> 12);
*t++ = 0x80 | ((wc >> 6) & 0x3f); *t++ = 0x80 | ((wc >> 6) & 0x3f);
*t++ = 0x80 | (wc & 0x3f); *t++ = 0x80 | (wc & 0x3f);
} } else {
else
{
*t++ = 0xf0 | ((wc >> 18) & 7); *t++ = 0xf0 | ((wc >> 18) & 7);
*t++ = 0x80 | ((wc >> 12) & 63); *t++ = 0x80 | ((wc >> 12) & 63);
*t++ = 0x80 | ((wc >> 6) & 0x3f); *t++ = 0x80 | ((wc >> 6) & 0x3f);
@ -1191,10 +1094,8 @@ char *ntfs_uppercase_mbs( const char *low,
} }
s += n; s += n;
} }
} } while (n > 0);
while ( n > 0 ); if (n < 0) {
if ( n < 0 )
{
free(upp); free(upp);
upp = (char*)NULL; upp = (char*)NULL;
errno = EILSEQ; errno = EILSEQ;
@ -1216,8 +1117,7 @@ char *ntfs_uppercase_mbs( const char *low,
*/ */
void ntfs_upcase_table_build(ntfschar *uc, u32 uc_len) void ntfs_upcase_table_build(ntfschar *uc, u32 uc_len)
{ {
static int uc_run_table[][3] = /* Start, End, Add */ static int uc_run_table[][3] = { /* Start, End, Add */
{
{0x0061, 0x007B, -32}, {0x0451, 0x045D, -80}, {0x1F70, 0x1F72, 74}, {0x0061, 0x007B, -32}, {0x0451, 0x045D, -80}, {0x1F70, 0x1F72, 74},
{0x00E0, 0x00F7, -32}, {0x045E, 0x0460, -80}, {0x1F72, 0x1F76, 86}, {0x00E0, 0x00F7, -32}, {0x045E, 0x0460, -80}, {0x1F72, 0x1F76, 86},
{0x00F8, 0x00FF, -32}, {0x0561, 0x0587, -48}, {0x1F76, 0x1F78, 100}, {0x00F8, 0x00FF, -32}, {0x0561, 0x0587, -48}, {0x1F76, 0x1F78, 100},
@ -1233,8 +1133,7 @@ void ntfs_upcase_table_build( ntfschar *uc, u32 uc_len )
{0x0430, 0x0450, -32}, {0x1F60, 0x1F68, 8}, {0xFF41, 0xFF5B, -32}, {0x0430, 0x0450, -32}, {0x1F60, 0x1F68, 8}, {0xFF41, 0xFF5B, -32},
{0} {0}
}; };
static int uc_dup_table[][2] = /* Start, End */ static int uc_dup_table[][2] = { /* Start, End */
{
{0x0100, 0x012F}, {0x01A0, 0x01A6}, {0x03E2, 0x03EF}, {0x04CB, 0x04CC}, {0x0100, 0x012F}, {0x01A0, 0x01A6}, {0x03E2, 0x03EF}, {0x04CB, 0x04CC},
{0x0132, 0x0137}, {0x01B3, 0x01B7}, {0x0460, 0x0481}, {0x04D0, 0x04EB}, {0x0132, 0x0137}, {0x01B3, 0x01B7}, {0x0460, 0x0481}, {0x04D0, 0x04EB},
{0x0139, 0x0149}, {0x01CD, 0x01DD}, {0x0490, 0x04BF}, {0x04EE, 0x04F5}, {0x0139, 0x0149}, {0x01CD, 0x01DD}, {0x0490, 0x04BF}, {0x04EE, 0x04F5},
@ -1243,8 +1142,7 @@ void ntfs_upcase_table_build( ntfschar *uc, u32 uc_len )
{0x018B, 0x018B}, {0x01FA, 0x0218}, {0x04C7, 0x04C8}, {0x1EA0, 0x1EF9}, {0x018B, 0x018B}, {0x01FA, 0x0218}, {0x04C7, 0x04C8}, {0x1EA0, 0x1EF9},
{0} {0}
}; };
static int uc_byte_table[][2] = /* Offset, Value */ static int uc_byte_table[][2] = { /* Offset, Value */
{
{0x00FF, 0x0178}, {0x01AD, 0x01AC}, {0x01F3, 0x01F1}, {0x0269, 0x0196}, {0x00FF, 0x0178}, {0x01AD, 0x01AC}, {0x01F3, 0x01F1}, {0x0269, 0x0196},
{0x0183, 0x0182}, {0x01B0, 0x01AF}, {0x0253, 0x0181}, {0x026F, 0x019C}, {0x0183, 0x0182}, {0x01B0, 0x01AF}, {0x0253, 0x0181}, {0x026F, 0x019C},
{0x0185, 0x0184}, {0x01B9, 0x01B8}, {0x0254, 0x0186}, {0x0272, 0x019D}, {0x0185, 0x0184}, {0x01B9, 0x01B8}, {0x0254, 0x0186}, {0x0272, 0x019D},
@ -1264,8 +1162,7 @@ void ntfs_upcase_table_build( ntfschar *uc, u32 uc_len )
uc_len = 65536; uc_len = 65536;
for (i = 0; (u32)i < uc_len; i++) for (i = 0; (u32)i < uc_len; i++)
uc[i] = cpu_to_le16(i); uc[i] = cpu_to_le16(i);
for ( r = 0; uc_run_table[r][0]; r++ ) for (r = 0; uc_run_table[r][0]; r++) {
{
off = uc_run_table[r][2]; off = uc_run_table[r][2];
for (i = uc_run_table[r][0]; i < uc_run_table[r][1]; i++) for (i = uc_run_table[r][0]; i < uc_run_table[r][1]; i++)
uc[i] = cpu_to_le16(i + off); uc[i] = cpu_to_le16(i + off);
@ -1273,8 +1170,7 @@ void ntfs_upcase_table_build( ntfschar *uc, u32 uc_len )
for (r = 0; uc_dup_table[r][0]; r++) for (r = 0; uc_dup_table[r][0]; r++)
for (i = uc_dup_table[r][0]; i < uc_dup_table[r][1]; i += 2) for (i = uc_dup_table[r][0]; i < uc_dup_table[r][1]; i += 2)
uc[i + 1] = cpu_to_le16(i); uc[i + 1] = cpu_to_le16(i);
for ( r = 0; uc_byte_table[r][0]; r++ ) for (r = 0; uc_byte_table[r][0]; r++) {
{
k = uc_byte_table[r][1]; k = uc_byte_table[r][1];
uc[uc_byte_table[r][0]] = cpu_to_le16(k); uc[uc_byte_table[r][0]] = cpu_to_le16(k);
} }
@ -1299,18 +1195,15 @@ ntfschar *ntfs_locase_table_build( const ntfschar *uc, u32 uc_cnt )
u32 i; u32 i;
lc = (ntfschar*)ntfs_malloc(uc_cnt*sizeof(ntfschar)); lc = (ntfschar*)ntfs_malloc(uc_cnt*sizeof(ntfschar));
if ( lc ) if (lc) {
{
for (i=0; i<uc_cnt; i++) for (i=0; i<uc_cnt; i++)
lc[i] = cpu_to_le16(i); lc[i] = cpu_to_le16(i);
for ( i = 0; i < uc_cnt; i++ ) for (i=0; i<uc_cnt; i++) {
{
upp = le16_to_cpu(uc[i]); upp = le16_to_cpu(uc[i]);
if ((upp != i) && (upp < uc_cnt)) if ((upp != i) && (upp < uc_cnt))
lc[upp] = cpu_to_le16(i); lc[upp] = cpu_to_le16(i);
} }
} } else
else
ntfs_log_error("Could not build the locase table\n"); ntfs_log_error("Could not build the locase table\n");
return (lc); return (lc);
} }
@ -1336,19 +1229,16 @@ ntfschar *ntfs_str2ucs( const char *s, int *len )
{ {
ntfschar *ucs = NULL; ntfschar *ucs = NULL;
if ( s && ( ( *len = ntfs_mbstoucs( s, &ucs ) ) == -1 ) ) if (s && ((*len = ntfs_mbstoucs(s, &ucs)) == -1)) {
{
ntfs_log_perror("Couldn't convert '%s' to Unicode", s); ntfs_log_perror("Couldn't convert '%s' to Unicode", s);
return NULL; return NULL;
} }
if ( *len > NTFS_MAX_NAME_LEN ) if (*len > NTFS_MAX_NAME_LEN) {
{
free(ucs); free(ucs);
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
return NULL; return NULL;
} }
if ( !ucs || !*len ) if (!ucs || !*len) {
{
ucs = AT_UNNAMED; ucs = AT_UNNAMED;
*len = 0; *len = 0;
} }
@ -1392,8 +1282,7 @@ BOOL ntfs_forbidden_chars( const ntfschar *name, int len )
forbidden = (len == 0) forbidden = (len == 0)
|| (le16_to_cpu(name[len-1]) == ' ') || (le16_to_cpu(name[len-1]) == ' ')
|| (le16_to_cpu(name[len-1]) == '.'); || (le16_to_cpu(name[len-1]) == '.');
for ( i = 0; i < len; i++ ) for (i=0; i<len; i++) {
{
ch = le16_to_cpu(name[i]); ch = le16_to_cpu(name[i]);
if ((ch < 0x20) if ((ch < 0x20)
|| ((ch < 0x40) || ((ch < 0x40)
@ -1425,8 +1314,7 @@ BOOL ntfs_collapsible_chars( ntfs_volume *vol,
collapsible = shortlen == longlen; collapsible = shortlen == longlen;
if (collapsible) if (collapsible)
for ( i = 0; i < shortlen; i++ ) for (i=0; i<shortlen; i++) {
{
ch = le16_to_cpu(longname[i]); ch = le16_to_cpu(longname[i]);
if ((ch >= vol->upcase_len) if ((ch >= vol->upcase_len)
|| ((shortname[i] != longname[i]) || ((shortname[i] != longname[i])
@ -1447,10 +1335,10 @@ int ntfs_set_char_encoding( const char *locale )
if (!locale || strstr(locale,"utf8") || strstr(locale,"UTF8") if (!locale || strstr(locale,"utf8") || strstr(locale,"UTF8")
|| strstr(locale,"utf-8") || strstr(locale,"UTF-8")) || strstr(locale,"utf-8") || strstr(locale,"UTF-8"))
use_utf8 = 1; use_utf8 = 1;
else if ( setlocale( LC_ALL, locale ) )
use_utf8 = 0;
else else
{ if (setlocale(LC_ALL, locale))
use_utf8 = 0;
else {
ntfs_log_error("Invalid locale, encoding to UTF-8\n"); ntfs_log_error("Invalid locale, encoding to UTF-8\n");
use_utf8 = 1; use_utf8 = 1;
} }
@ -1459,11 +1347,9 @@ int ntfs_set_char_encoding( const char *locale )
#if defined(__APPLE__) || defined(__DARWIN__) #if defined(__APPLE__) || defined(__DARWIN__)
int ntfs_macosx_normalize_filenames( int normalize ) int ntfs_macosx_normalize_filenames(int normalize) {
{
#ifdef ENABLE_NFCONV #ifdef ENABLE_NFCONV
if ( normalize == 0 || normalize == 1 ) if(normalize == 0 || normalize == 1) {
{
nfconvert_utf8 = normalize; nfconvert_utf8 = normalize;
return 0; return 0;
} }
@ -1475,8 +1361,7 @@ int ntfs_macosx_normalize_filenames( int normalize )
} }
int ntfs_macosx_normalize_utf8(const char *utf8_string, char **target, int ntfs_macosx_normalize_utf8(const char *utf8_string, char **target,
int composed ) int composed) {
{
#ifdef ENABLE_NFCONV #ifdef ENABLE_NFCONV
/* For this code to compile, the CoreFoundation framework must be fed to the linker. */ /* For this code to compile, the CoreFoundation framework must be fed to the linker. */
CFStringRef cfSourceString; CFStringRef cfSourceString;
@ -1488,8 +1373,7 @@ int ntfs_macosx_normalize_utf8( const char *utf8_string, char **target,
/* Convert the UTF-8 string to a CFString. */ /* Convert the UTF-8 string to a CFString. */
cfSourceString = CFStringCreateWithCString(kCFAllocatorDefault, utf8_string, kCFStringEncodingUTF8); cfSourceString = CFStringCreateWithCString(kCFAllocatorDefault, utf8_string, kCFStringEncodingUTF8);
if ( cfSourceString == NULL ) if(cfSourceString == NULL) {
{
ntfs_log_error("CFStringCreateWithCString failed!\n"); ntfs_log_error("CFStringCreateWithCString failed!\n");
return -2; return -2;
} }
@ -1497,8 +1381,7 @@ int ntfs_macosx_normalize_utf8( const char *utf8_string, char **target,
/* Create a mutable string from cfSourceString that we are free to modify. */ /* Create a mutable string from cfSourceString that we are free to modify. */
cfMutableString = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, cfSourceString); cfMutableString = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, cfSourceString);
CFRelease(cfSourceString); /* End-of-life. */ CFRelease(cfSourceString); /* End-of-life. */
if ( cfMutableString == NULL ) if(cfMutableString == NULL) {
{
ntfs_log_error("CFStringCreateMutableCopy failed!\n"); ntfs_log_error("CFStringCreateMutableCopy failed!\n");
return -3; return -3;
} }
@ -1508,16 +1391,13 @@ int ntfs_macosx_normalize_utf8( const char *utf8_string, char **target,
/* Store the resulting string in a '\0'-terminated UTF-8 encoded char* buffer. */ /* Store the resulting string in a '\0'-terminated UTF-8 encoded char* buffer. */
rangeToProcess = CFRangeMake(0, CFStringGetLength(cfMutableString)); rangeToProcess = CFRangeMake(0, CFStringGetLength(cfMutableString));
if ( CFStringGetBytes( cfMutableString, rangeToProcess, kCFStringEncodingUTF8, 0, false, NULL, 0, &requiredBufferLength ) > 0 ) if(CFStringGetBytes(cfMutableString, rangeToProcess, kCFStringEncodingUTF8, 0, false, NULL, 0, &requiredBufferLength) > 0) {
{
resultLength = sizeof(char)*(requiredBufferLength + 1); resultLength = sizeof(char)*(requiredBufferLength + 1);
result = ntfs_calloc(resultLength); result = ntfs_calloc(resultLength);
if ( result != NULL ) if(result != NULL) {
{
if(CFStringGetBytes(cfMutableString, rangeToProcess, kCFStringEncodingUTF8, if(CFStringGetBytes(cfMutableString, rangeToProcess, kCFStringEncodingUTF8,
0, false, ( UInt8* )result, resultLength - 1, &requiredBufferLength ) <= 0 ) 0, false, (UInt8*)result, resultLength-1, &requiredBufferLength) <= 0) {
{
ntfs_log_error("Could not perform UTF-8 conversion of normalized CFMutableString.\n"); ntfs_log_error("Could not perform UTF-8 conversion of normalized CFMutableString.\n");
free(result); free(result);
result = NULL; result = NULL;
@ -1532,8 +1412,7 @@ int ntfs_macosx_normalize_utf8( const char *utf8_string, char **target,
CFRelease(cfMutableString); CFRelease(cfMutableString);
if ( result != NULL ) if(result != NULL) {
{
*target = result; *target = result;
return resultLength - 1; return resultLength - 1;
} }

View File

@ -129,8 +129,7 @@ ntfs_volume *ntfs_volume_alloc( void )
static void ntfs_attr_free(ntfs_attr **na) static void ntfs_attr_free(ntfs_attr **na)
{ {
if ( na && *na ) if (na && *na) {
{
ntfs_attr_close(*na); ntfs_attr_close(*na);
*na = NULL; *na = NULL;
} }
@ -140,8 +139,7 @@ static int ntfs_inode_free( ntfs_inode **ni )
{ {
int ret = -1; int ret = -1;
if ( ni && *ni ) if (ni && *ni) {
{
ret = ntfs_inode_close(*ni); ret = ntfs_inode_close(*ni);
*ni = NULL; *ni = NULL;
} }
@ -192,8 +190,7 @@ static int __ntfs_volume_release( ntfs_volume *v )
if (ntfs_inode_free(&v->mftmirr_ni)) if (ntfs_inode_free(&v->mftmirr_ni))
ntfs_error_set(&err); ntfs_error_set(&err);
if ( v->dev ) if (v->dev) {
{
struct ntfs_device *dev = v->dev; struct ntfs_device *dev = v->dev;
if (dev->d_ops->sync(dev)) if (dev->d_ops->sync(dev))
@ -218,8 +215,7 @@ static void ntfs_attr_setup_flag( ntfs_inode *ni )
STANDARD_INFORMATION *si; STANDARD_INFORMATION *si;
si = ntfs_attr_readall(ni, AT_STANDARD_INFORMATION, AT_UNNAMED, 0, NULL); si = ntfs_attr_readall(ni, AT_STANDARD_INFORMATION, AT_UNNAMED, 0, NULL);
if ( si ) if (si) {
{
ni->flags = si->file_attributes; ni->flags = si->file_attributes;
free(si); free(si);
} }
@ -247,8 +243,7 @@ static int ntfs_mft_load( ntfs_volume *vol )
/* Manually setup an ntfs_inode. */ /* Manually setup an ntfs_inode. */
vol->mft_ni = ntfs_inode_allocate(vol); vol->mft_ni = ntfs_inode_allocate(vol);
mb = ntfs_malloc(vol->mft_record_size); mb = ntfs_malloc(vol->mft_record_size);
if ( !vol->mft_ni || !mb ) if (!vol->mft_ni || !mb) {
{
ntfs_log_perror("Error allocating memory for $MFT"); ntfs_log_perror("Error allocating memory for $MFT");
goto error_exit; goto error_exit;
} }
@ -257,8 +252,7 @@ static int ntfs_mft_load( ntfs_volume *vol )
/* Can't use any of the higher level functions yet! */ /* Can't use any of the higher level functions yet! */
l = ntfs_mst_pread(vol->dev, vol->mft_lcn << vol->cluster_size_bits, 1, l = ntfs_mst_pread(vol->dev, vol->mft_lcn << vol->cluster_size_bits, 1,
vol->mft_record_size, mb); vol->mft_record_size, mb);
if ( l != 1 ) if (l != 1) {
{
if (l != -1) if (l != -1)
errno = EIO; errno = EIO;
ntfs_log_perror("Error reading $MFT"); ntfs_log_perror("Error reading $MFT");
@ -274,10 +268,8 @@ static int ntfs_mft_load( ntfs_volume *vol )
/* Find the $ATTRIBUTE_LIST attribute in $MFT if present. */ /* Find the $ATTRIBUTE_LIST attribute in $MFT if present. */
if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0, if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0,
ctx ) ) ctx)) {
{ if (errno != ENOENT) {
if ( errno != ENOENT )
{
ntfs_log_error("$MFT has corrupt attribute list.\n"); ntfs_log_error("$MFT has corrupt attribute list.\n");
goto io_error_exit; goto io_error_exit;
} }
@ -285,8 +277,7 @@ static int ntfs_mft_load( ntfs_volume *vol )
} }
NInoSetAttrList(vol->mft_ni); NInoSetAttrList(vol->mft_ni);
l = ntfs_get_attribute_value_length(ctx->attr); l = ntfs_get_attribute_value_length(ctx->attr);
if ( l <= 0 || l > 0x40000 ) if (l <= 0 || l > 0x40000) {
{
ntfs_log_error("$MFT/$ATTR_LIST invalid length (%lld).\n", ntfs_log_error("$MFT/$ATTR_LIST invalid length (%lld).\n",
(long long)l); (long long)l);
goto io_error_exit; goto io_error_exit;
@ -297,13 +288,11 @@ static int ntfs_mft_load( ntfs_volume *vol )
goto error_exit; goto error_exit;
l = ntfs_get_attribute_value(vol, ctx->attr, vol->mft_ni->attr_list); l = ntfs_get_attribute_value(vol, ctx->attr, vol->mft_ni->attr_list);
if ( !l ) if (!l) {
{
ntfs_log_error("Failed to get value of $MFT/$ATTR_LIST.\n"); ntfs_log_error("Failed to get value of $MFT/$ATTR_LIST.\n");
goto io_error_exit; goto io_error_exit;
} }
if ( l != vol->mft_ni->attr_list_size ) if (l != vol->mft_ni->attr_list_size) {
{
ntfs_log_error("Partial read of $MFT/$ATTR_LIST (%lld != " ntfs_log_error("Partial read of $MFT/$ATTR_LIST (%lld != "
"%u).\n", (long long)l, "%u).\n", (long long)l,
vol->mft_ni->attr_list_size); vol->mft_ni->attr_list_size);
@ -318,8 +307,7 @@ mft_has_no_attr_list:
/* Get an ntfs attribute for $MFT/$DATA and set it up, too. */ /* Get an ntfs attribute for $MFT/$DATA and set it up, too. */
vol->mft_na = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0); vol->mft_na = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0);
if ( !vol->mft_na ) if (!vol->mft_na) {
{
ntfs_log_perror("Failed to open ntfs attribute"); ntfs_log_perror("Failed to open ntfs attribute");
goto error_exit; goto error_exit;
} }
@ -329,21 +317,18 @@ mft_has_no_attr_list:
highest_vcn = next_vcn = 0; highest_vcn = next_vcn = 0;
a = NULL; a = NULL;
while (!ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, next_vcn, NULL, 0, while (!ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, next_vcn, NULL, 0,
ctx ) ) ctx)) {
{
runlist_element *nrl; runlist_element *nrl;
a = ctx->attr; a = ctx->attr;
/* $MFT must be non-resident. */ /* $MFT must be non-resident. */
if ( !a->non_resident ) if (!a->non_resident) {
{
ntfs_log_error("$MFT must be non-resident.\n"); ntfs_log_error("$MFT must be non-resident.\n");
goto io_error_exit; goto io_error_exit;
} }
/* $MFT must be uncompressed and unencrypted. */ /* $MFT must be uncompressed and unencrypted. */
if (a->flags & ATTR_COMPRESSION_MASK || if (a->flags & ATTR_COMPRESSION_MASK ||
a->flags & ATTR_IS_ENCRYPTED ) a->flags & ATTR_IS_ENCRYPTED) {
{
ntfs_log_error("$MFT must be uncompressed and " ntfs_log_error("$MFT must be uncompressed and "
"unencrypted.\n"); "unencrypted.\n");
goto io_error_exit; goto io_error_exit;
@ -355,8 +340,7 @@ mft_has_no_attr_list:
* are a mount in progress task, too. * are a mount in progress task, too.
*/ */
nrl = ntfs_mapping_pairs_decompress(vol, a, vol->mft_na->rl); nrl = ntfs_mapping_pairs_decompress(vol, a, vol->mft_na->rl);
if ( !nrl ) if (!nrl) {
{
ntfs_log_perror("ntfs_mapping_pairs_decompress() failed"); ntfs_log_perror("ntfs_mapping_pairs_decompress() failed");
goto error_exit; goto error_exit;
} }
@ -371,19 +355,16 @@ mft_has_no_attr_list:
break; break;
/* Avoid endless loops due to corruption. */ /* Avoid endless loops due to corruption. */
if ( next_vcn < sle64_to_cpu( a->lowest_vcn ) ) if (next_vcn < sle64_to_cpu(a->lowest_vcn)) {
{
ntfs_log_error("$MFT has corrupt attribute list.\n"); ntfs_log_error("$MFT has corrupt attribute list.\n");
goto io_error_exit; goto io_error_exit;
} }
} }
if ( !a ) if (!a) {
{
ntfs_log_error("$MFT/$DATA attribute not found.\n"); ntfs_log_error("$MFT/$DATA attribute not found.\n");
goto io_error_exit; goto io_error_exit;
} }
if ( highest_vcn && highest_vcn != last_vcn - 1 ) if (highest_vcn && highest_vcn != last_vcn - 1) {
{
ntfs_log_error("Failed to load runlist for $MFT/$DATA.\n"); ntfs_log_error("Failed to load runlist for $MFT/$DATA.\n");
ntfs_log_error("highest_vcn = 0x%llx, last_vcn - 1 = 0x%llx\n", ntfs_log_error("highest_vcn = 0x%llx, last_vcn - 1 = 0x%llx\n",
(long long)highest_vcn, (long long)last_vcn - 1); (long long)highest_vcn, (long long)last_vcn - 1);
@ -396,8 +377,7 @@ mft_has_no_attr_list:
* The volume is now setup so we can use all read access functions. * The volume is now setup so we can use all read access functions.
*/ */
vol->mftbmp_na = ntfs_attr_open(vol->mft_ni, AT_BITMAP, AT_UNNAMED, 0); vol->mftbmp_na = ntfs_attr_open(vol->mft_ni, AT_BITMAP, AT_UNNAMED, 0);
if ( !vol->mftbmp_na ) if (!vol->mftbmp_na) {
{
ntfs_log_perror("Failed to open $MFT/$BITMAP"); ntfs_log_perror("Failed to open $MFT/$BITMAP");
goto error_exit; goto error_exit;
} }
@ -408,13 +388,11 @@ error_exit:
eo = errno; eo = errno;
if (ctx) if (ctx)
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
if ( vol->mft_na ) if (vol->mft_na) {
{
ntfs_attr_close(vol->mft_na); ntfs_attr_close(vol->mft_na);
vol->mft_na = NULL; vol->mft_na = NULL;
} }
if ( vol->mft_ni ) if (vol->mft_ni) {
{
ntfs_inode_close(vol->mft_ni); ntfs_inode_close(vol->mft_ni);
vol->mft_ni = NULL; vol->mft_ni = NULL;
} }
@ -438,21 +416,18 @@ static int ntfs_mftmirr_load( ntfs_volume *vol )
int err; int err;
vol->mftmirr_ni = ntfs_inode_open(vol, FILE_MFTMirr); vol->mftmirr_ni = ntfs_inode_open(vol, FILE_MFTMirr);
if ( !vol->mftmirr_ni ) if (!vol->mftmirr_ni) {
{
ntfs_log_perror("Failed to open inode $MFTMirr"); ntfs_log_perror("Failed to open inode $MFTMirr");
return -1; return -1;
} }
vol->mftmirr_na = ntfs_attr_open(vol->mftmirr_ni, AT_DATA, AT_UNNAMED, 0); vol->mftmirr_na = ntfs_attr_open(vol->mftmirr_ni, AT_DATA, AT_UNNAMED, 0);
if ( !vol->mftmirr_na ) if (!vol->mftmirr_na) {
{
ntfs_log_perror("Failed to open $MFTMirr/$DATA"); ntfs_log_perror("Failed to open $MFTMirr/$DATA");
goto error_exit; goto error_exit;
} }
if ( ntfs_attr_map_runlist( vol->mftmirr_na, 0 ) < 0 ) if (ntfs_attr_map_runlist(vol->mftmirr_na, 0) < 0) {
{
ntfs_log_perror("Failed to map runlist of $MFTMirr/$DATA"); ntfs_log_perror("Failed to map runlist of $MFTMirr/$DATA");
goto error_exit; goto error_exit;
} }
@ -461,8 +436,7 @@ static int ntfs_mftmirr_load( ntfs_volume *vol )
error_exit: error_exit:
err = errno; err = errno;
if ( vol->mftmirr_na ) if (vol->mftmirr_na) {
{
ntfs_attr_close(vol->mftmirr_na); ntfs_attr_close(vol->mftmirr_na);
vol->mftmirr_na = NULL; vol->mftmirr_na = NULL;
} }
@ -492,8 +466,7 @@ ntfs_volume *ntfs_volume_startup( struct ntfs_device *dev, unsigned long flags )
NTFS_BOOT_SECTOR *bs; NTFS_BOOT_SECTOR *bs;
int eo; int eo;
if ( !dev || !dev->d_ops || !dev->d_name ) if (!dev || !dev->d_ops || !dev->d_name) {
{
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s: dev = %p", __FUNCTION__, dev); ntfs_log_perror("%s: dev = %p", __FUNCTION__, dev);
return NULL; return NULL;
@ -528,8 +501,7 @@ ntfs_volume *ntfs_volume_startup( struct ntfs_device *dev, unsigned long flags )
NVolSetReadOnly(vol); NVolSetReadOnly(vol);
/* ...->open needs bracketing to compile with glibc 2.7 */ /* ...->open needs bracketing to compile with glibc 2.7 */
if ( ( dev->d_ops->open )( dev, NVolReadOnly( vol ) ? O_RDONLY : O_RDWR ) ) if ((dev->d_ops->open)(dev, NVolReadOnly(vol) ? O_RDONLY: O_RDWR)) {
{
ntfs_log_perror("Error opening '%s'", dev->d_name); ntfs_log_perror("Error opening '%s'", dev->d_name);
goto error_exit; goto error_exit;
} }
@ -538,8 +510,7 @@ ntfs_volume *ntfs_volume_startup( struct ntfs_device *dev, unsigned long flags )
/* Now read the bootsector. */ /* Now read the bootsector. */
br = ntfs_pread(dev, 0, sizeof(NTFS_BOOT_SECTOR), bs); br = ntfs_pread(dev, 0, sizeof(NTFS_BOOT_SECTOR), bs);
if ( br != sizeof( NTFS_BOOT_SECTOR ) ) if (br != sizeof(NTFS_BOOT_SECTOR)) {
{
if (br != -1) if (br != -1)
errno = EINVAL; errno = EINVAL;
if (!br) if (!br)
@ -548,8 +519,7 @@ ntfs_volume *ntfs_volume_startup( struct ntfs_device *dev, unsigned long flags )
ntfs_log_perror("Error reading bootsector"); ntfs_log_perror("Error reading bootsector");
goto error_exit; goto error_exit;
} }
if ( !ntfs_boot_sector_is_ntfs( bs ) ) if (!ntfs_boot_sector_is_ntfs(bs)) {
{
errno = EINVAL; errno = EINVAL;
goto error_exit; goto error_exit;
} }
@ -596,8 +566,7 @@ ntfs_volume *ntfs_volume_startup( struct ntfs_device *dev, unsigned long flags )
* halving the zone size until we are inside the volume. * halving the zone size until we are inside the volume.
*/ */
vol->mft_zone_end = vol->mft_lcn + mft_zone_size; vol->mft_zone_end = vol->mft_lcn + mft_zone_size;
while ( vol->mft_zone_end >= vol->nr_clusters ) while (vol->mft_zone_end >= vol->nr_clusters) {
{
mft_zone_size >>= 1; mft_zone_size >>= 1;
vol->mft_zone_end = vol->mft_lcn + mft_zone_size; vol->mft_zone_end = vol->mft_lcn + mft_zone_size;
} }
@ -620,15 +589,13 @@ ntfs_volume *ntfs_volume_startup( struct ntfs_device *dev, unsigned long flags )
*/ */
/* Need to setup $MFT so we can use the library read functions. */ /* Need to setup $MFT so we can use the library read functions. */
if ( ntfs_mft_load( vol ) < 0 ) if (ntfs_mft_load(vol) < 0) {
{
ntfs_log_perror("Failed to load $MFT"); ntfs_log_perror("Failed to load $MFT");
goto error_exit; goto error_exit;
} }
/* Need to setup $MFTMirr so we can use the write functions, too. */ /* Need to setup $MFTMirr so we can use the write functions, too. */
if ( ntfs_mftmirr_load( vol ) < 0 ) if (ntfs_mftmirr_load(vol) < 0) {
{
ntfs_log_perror("Failed to load $MFTMirr"); ntfs_log_perror("Failed to load $MFTMirr");
goto error_exit; goto error_exit;
} }
@ -656,16 +623,14 @@ static int ntfs_volume_check_logfile( ntfs_volume *vol )
int err = 0; int err = 0;
ni = ntfs_inode_open(vol, FILE_LogFile); ni = ntfs_inode_open(vol, FILE_LogFile);
if ( !ni ) if (!ni) {
{
ntfs_log_perror("Failed to open inode FILE_LogFile"); ntfs_log_perror("Failed to open inode FILE_LogFile");
errno = EIO; errno = EIO;
return -1; return -1;
} }
na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
if ( !na ) if (!na) {
{
ntfs_log_perror("Failed to open $FILE_LogFile/$DATA"); ntfs_log_perror("Failed to open $FILE_LogFile/$DATA");
err = EIO; err = EIO;
goto out; goto out;
@ -678,8 +643,7 @@ static int ntfs_volume_check_logfile( ntfs_volume *vol )
out: out:
if (ntfs_inode_close(ni)) if (ntfs_inode_close(ni))
ntfs_error_set(&err); ntfs_error_set(&err);
if ( err ) if (err) {
{
errno = err; errno = err;
return -1; return -1;
} }
@ -702,43 +666,37 @@ static ntfs_inode *ntfs_hiberfile_open( ntfs_volume *vol )
int unicode_len; int unicode_len;
const char *hiberfile = "hiberfil.sys"; const char *hiberfile = "hiberfil.sys";
if ( !vol ) if (!vol) {
{
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} }
ni_root = ntfs_inode_open(vol, FILE_root); ni_root = ntfs_inode_open(vol, FILE_root);
if ( !ni_root ) if (!ni_root) {
{
ntfs_log_debug("Couldn't open the root directory.\n"); ntfs_log_debug("Couldn't open the root directory.\n");
return NULL; return NULL;
} }
unicode_len = ntfs_mbstoucs(hiberfile, &unicode); unicode_len = ntfs_mbstoucs(hiberfile, &unicode);
if ( unicode_len < 0 ) if (unicode_len < 0) {
{
ntfs_log_perror("Couldn't convert 'hiberfil.sys' to Unicode"); ntfs_log_perror("Couldn't convert 'hiberfil.sys' to Unicode");
goto out; goto out;
} }
inode = ntfs_inode_lookup_by_name(ni_root, unicode, unicode_len); inode = ntfs_inode_lookup_by_name(ni_root, unicode, unicode_len);
if ( inode == ( u64 ) - 1 ) if (inode == (u64)-1) {
{
ntfs_log_debug("Couldn't find file '%s'.\n", hiberfile); ntfs_log_debug("Couldn't find file '%s'.\n", hiberfile);
goto out; goto out;
} }
inode = MREF(inode); inode = MREF(inode);
ni_hibr = ntfs_inode_open(vol, inode); ni_hibr = ntfs_inode_open(vol, inode);
if ( !ni_hibr ) if (!ni_hibr) {
{
ntfs_log_debug("Couldn't open inode %lld.\n", (long long)inode); ntfs_log_debug("Couldn't open inode %lld.\n", (long long)inode);
goto out; goto out;
} }
out: out:
if ( ntfs_inode_close( ni_root ) ) if (ntfs_inode_close(ni_root)) {
{
ntfs_inode_close(ni_hibr); ntfs_inode_close(ni_hibr);
ni_hibr = NULL; ni_hibr = NULL;
} }
@ -765,8 +723,7 @@ int ntfs_volume_check_hiberfile( ntfs_volume *vol, int verbose )
char *buf = NULL; char *buf = NULL;
ni = ntfs_hiberfile_open(vol); ni = ntfs_hiberfile_open(vol);
if ( !ni ) if (!ni) {
{
if (errno == ENOENT) if (errno == ENOENT)
return 0; return 0;
return -1; return -1;
@ -777,28 +734,24 @@ int ntfs_volume_check_hiberfile( ntfs_volume *vol, int verbose )
goto out; goto out;
na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
if ( !na ) if (!na) {
{
ntfs_log_perror("Failed to open hiberfil.sys data attribute"); ntfs_log_perror("Failed to open hiberfil.sys data attribute");
goto out; goto out;
} }
bytes_read = ntfs_attr_pread(na, 0, NTFS_HIBERFILE_HEADER_SIZE, buf); bytes_read = ntfs_attr_pread(na, 0, NTFS_HIBERFILE_HEADER_SIZE, buf);
if ( bytes_read == -1 ) if (bytes_read == -1) {
{
ntfs_log_perror("Failed to read hiberfil.sys"); ntfs_log_perror("Failed to read hiberfil.sys");
goto out; goto out;
} }
if ( bytes_read < NTFS_HIBERFILE_HEADER_SIZE ) if (bytes_read < NTFS_HIBERFILE_HEADER_SIZE) {
{
if (verbose) if (verbose)
ntfs_log_error("Hibernated non-system partition, " ntfs_log_error("Hibernated non-system partition, "
"refused to mount.\n"); "refused to mount.\n");
errno = EPERM; errno = EPERM;
goto out; goto out;
} }
if ( memcmp( buf, "hibr", 4 ) == 0 ) if (memcmp(buf, "hibr", 4) == 0) {
{
if (verbose) if (verbose)
ntfs_log_error("Windows is hibernated, refused to mount.\n"); ntfs_log_error("Windows is hibernated, refused to mount.\n");
errno = EPERM; errno = EPERM;
@ -842,19 +795,14 @@ static int fix_txf_data( ntfs_volume *vol )
res = 0; res = 0;
ntfs_log_debug("Loading root directory\n"); ntfs_log_debug("Loading root directory\n");
ni = ntfs_inode_open(vol, FILE_root); ni = ntfs_inode_open(vol, FILE_root);
if ( !ni ) if (!ni) {
{
ntfs_log_perror("Failed to open root directory"); ntfs_log_perror("Failed to open root directory");
res = -1; res = -1;
} } else {
else
{
/* Get the $TXF_DATA attribute */ /* Get the $TXF_DATA attribute */
na = ntfs_attr_open(ni, AT_LOGGED_UTILITY_STREAM, TXF_DATA, 9); na = ntfs_attr_open(ni, AT_LOGGED_UTILITY_STREAM, TXF_DATA, 9);
if ( na ) if (na) {
{ if (NAttrNonResident(na)) {
if ( NAttrNonResident( na ) )
{
/* /*
* Fix the attribute by truncating, then * Fix the attribute by truncating, then
* rewriting it. * rewriting it.
@ -863,8 +811,7 @@ static int fix_txf_data( ntfs_volume *vol )
txf_data = ntfs_attr_readall(ni, txf_data = ntfs_attr_readall(ni,
AT_LOGGED_UTILITY_STREAM, AT_LOGGED_UTILITY_STREAM,
TXF_DATA, 9, &txf_data_size); TXF_DATA, 9, &txf_data_size);
if ( txf_data ) if (txf_data) {
{
if (ntfs_attr_truncate(na, 0) if (ntfs_attr_truncate(na, 0)
|| (ntfs_attr_pwrite(na, 0, || (ntfs_attr_pwrite(na, 0,
txf_data_size, txf_data) txf_data_size, txf_data)
@ -879,8 +826,7 @@ static int fix_txf_data( ntfs_volume *vol )
} }
ntfs_attr_close(na); ntfs_attr_close(na);
} }
if ( ntfs_inode_close( ni ) ) if (ntfs_inode_close(ni)) {
{
ntfs_log_perror("Failed to close root"); ntfs_log_perror("Failed to close root");
res = -1; res = -1;
} }
@ -936,12 +882,10 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
l = ntfs_attr_mst_pread(vol->mft_na, 0, vol->mftmirr_size, l = ntfs_attr_mst_pread(vol->mft_na, 0, vol->mftmirr_size,
vol->mft_record_size, m); vol->mft_record_size, m);
if ( l != vol->mftmirr_size ) if (l != vol->mftmirr_size) {
{
if (l == -1) if (l == -1)
ntfs_log_perror("Failed to read $MFT"); ntfs_log_perror("Failed to read $MFT");
else else {
{
ntfs_log_error("Failed to read $MFT, unexpected length " ntfs_log_error("Failed to read $MFT, unexpected length "
"(%lld != %d).\n", (long long)l, "(%lld != %d).\n", (long long)l,
vol->mftmirr_size); vol->mftmirr_size);
@ -951,23 +895,19 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
} }
l = ntfs_attr_mst_pread(vol->mftmirr_na, 0, vol->mftmirr_size, l = ntfs_attr_mst_pread(vol->mftmirr_na, 0, vol->mftmirr_size,
vol->mft_record_size, m2); vol->mft_record_size, m2);
if ( l != vol->mftmirr_size ) if (l != vol->mftmirr_size) {
{ if (l == -1) {
if ( l == -1 )
{
ntfs_log_perror("Failed to read $MFTMirr"); ntfs_log_perror("Failed to read $MFTMirr");
goto error_exit; goto error_exit;
} }
vol->mftmirr_size = l; vol->mftmirr_size = l;
} }
ntfs_log_debug("Comparing $MFTMirr to $MFT...\n"); ntfs_log_debug("Comparing $MFTMirr to $MFT...\n");
for ( i = 0; i < vol->mftmirr_size; ++i ) for (i = 0; i < vol->mftmirr_size; ++i) {
{
MFT_RECORD *mrec, *mrec2; MFT_RECORD *mrec, *mrec2;
const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile", const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile",
"$Volume", "$AttrDef", "root directory", "$Bitmap", "$Volume", "$AttrDef", "root directory", "$Bitmap",
"$Boot", "$BadClus", "$Secure", "$UpCase", "$Extend" "$Boot", "$BadClus", "$Secure", "$UpCase", "$Extend" };
};
const char *s; const char *s;
if (i < 12) if (i < 12)
@ -978,41 +918,34 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
s = "mft record"; s = "mft record";
mrec = (MFT_RECORD*)(m + i * vol->mft_record_size); mrec = (MFT_RECORD*)(m + i * vol->mft_record_size);
if ( mrec->flags & MFT_RECORD_IN_USE ) if (mrec->flags & MFT_RECORD_IN_USE) {
{ if (ntfs_is_baad_recordp(mrec)) {
if ( ntfs_is_baad_recordp( mrec ) )
{
ntfs_log_error("$MFT error: Incomplete multi " ntfs_log_error("$MFT error: Incomplete multi "
"sector transfer detected in " "sector transfer detected in "
"'%s'.\n", s); "'%s'.\n", s);
goto io_error_exit; goto io_error_exit;
} }
if ( !ntfs_is_mft_recordp( mrec ) ) if (!ntfs_is_mft_recordp(mrec)) {
{
ntfs_log_error("$MFT error: Invalid mft " ntfs_log_error("$MFT error: Invalid mft "
"record for '%s'.\n", s); "record for '%s'.\n", s);
goto io_error_exit; goto io_error_exit;
} }
} }
mrec2 = (MFT_RECORD*)(m2 + i * vol->mft_record_size); mrec2 = (MFT_RECORD*)(m2 + i * vol->mft_record_size);
if ( mrec2->flags & MFT_RECORD_IN_USE ) if (mrec2->flags & MFT_RECORD_IN_USE) {
{ if (ntfs_is_baad_recordp(mrec2)) {
if ( ntfs_is_baad_recordp( mrec2 ) )
{
ntfs_log_error("$MFTMirr error: Incomplete " ntfs_log_error("$MFTMirr error: Incomplete "
"multi sector transfer " "multi sector transfer "
"detected in '%s'.\n", s); "detected in '%s'.\n", s);
goto io_error_exit; goto io_error_exit;
} }
if ( !ntfs_is_mft_recordp( mrec2 ) ) if (!ntfs_is_mft_recordp(mrec2)) {
{
ntfs_log_error("$MFTMirr error: Invalid mft " ntfs_log_error("$MFTMirr error: Invalid mft "
"record for '%s'.\n", s); "record for '%s'.\n", s);
goto io_error_exit; goto io_error_exit;
} }
} }
if ( memcmp( mrec, mrec2, ntfs_mft_record_get_data_size( mrec ) ) ) if (memcmp(mrec, mrec2, ntfs_mft_record_get_data_size(mrec))) {
{
ntfs_log_error("$MFTMirr does not match $MFT (record " ntfs_log_error("$MFTMirr does not match $MFT (record "
"%d).\n", i); "%d).\n", i);
goto io_error_exit; goto io_error_exit;
@ -1026,21 +959,18 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
/* Now load the bitmap from $Bitmap. */ /* Now load the bitmap from $Bitmap. */
ntfs_log_debug("Loading $Bitmap...\n"); ntfs_log_debug("Loading $Bitmap...\n");
vol->lcnbmp_ni = ntfs_inode_open(vol, FILE_Bitmap); vol->lcnbmp_ni = ntfs_inode_open(vol, FILE_Bitmap);
if ( !vol->lcnbmp_ni ) if (!vol->lcnbmp_ni) {
{
ntfs_log_perror("Failed to open inode FILE_Bitmap"); ntfs_log_perror("Failed to open inode FILE_Bitmap");
goto error_exit; goto error_exit;
} }
vol->lcnbmp_na = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0); vol->lcnbmp_na = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0);
if ( !vol->lcnbmp_na ) if (!vol->lcnbmp_na) {
{
ntfs_log_perror("Failed to open ntfs attribute"); ntfs_log_perror("Failed to open ntfs attribute");
goto error_exit; goto error_exit;
} }
if ( vol->lcnbmp_na->data_size > vol->lcnbmp_na->allocated_size ) if (vol->lcnbmp_na->data_size > vol->lcnbmp_na->allocated_size) {
{
ntfs_log_error("Corrupt cluster map size (%lld > %lld)\n", ntfs_log_error("Corrupt cluster map size (%lld > %lld)\n",
(long long)vol->lcnbmp_na->data_size, (long long)vol->lcnbmp_na->data_size,
(long long)vol->lcnbmp_na->allocated_size); (long long)vol->lcnbmp_na->allocated_size);
@ -1050,15 +980,13 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
/* Now load the upcase table from $UpCase. */ /* Now load the upcase table from $UpCase. */
ntfs_log_debug("Loading $UpCase...\n"); ntfs_log_debug("Loading $UpCase...\n");
ni = ntfs_inode_open(vol, FILE_UpCase); ni = ntfs_inode_open(vol, FILE_UpCase);
if ( !ni ) if (!ni) {
{
ntfs_log_perror("Failed to open inode FILE_UpCase"); ntfs_log_perror("Failed to open inode FILE_UpCase");
goto error_exit; goto error_exit;
} }
/* Get an ntfs attribute for $UpCase/$DATA. */ /* Get an ntfs attribute for $UpCase/$DATA. */
na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
if ( !na ) if (!na) {
{
ntfs_log_perror("Failed to open ntfs attribute"); ntfs_log_perror("Failed to open ntfs attribute");
goto error_exit; goto error_exit;
} }
@ -1068,15 +996,13 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
* checks done. Just check we don't overflow 32-bits worth of Unicode * checks done. Just check we don't overflow 32-bits worth of Unicode
* characters. * characters.
*/ */
if ( na->data_size & ~0x1ffffffffULL ) if (na->data_size & ~0x1ffffffffULL) {
{
ntfs_log_error("Error: Upcase table is too big (max 32-bit " ntfs_log_error("Error: Upcase table is too big (max 32-bit "
"allowed).\n"); "allowed).\n");
errno = EINVAL; errno = EINVAL;
goto error_exit; goto error_exit;
} }
if ( vol->upcase_len != na->data_size >> 1 ) if (vol->upcase_len != na->data_size >> 1) {
{
vol->upcase_len = na->data_size >> 1; vol->upcase_len = na->data_size >> 1;
/* Throw away default table. */ /* Throw away default table. */
free(vol->upcase); free(vol->upcase);
@ -1086,8 +1012,7 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
} }
/* Read in the $DATA attribute value into the buffer. */ /* Read in the $DATA attribute value into the buffer. */
l = ntfs_attr_pread(na, 0, na->data_size, vol->upcase); l = ntfs_attr_pread(na, 0, na->data_size, vol->upcase);
if ( l != na->data_size ) if (l != na->data_size) {
{
ntfs_log_error("Failed to read $UpCase, unexpected length " ntfs_log_error("Failed to read $UpCase, unexpected length "
"(%lld != %lld).\n", (long long)l, "(%lld != %lld).\n", (long long)l,
(long long)na->data_size); (long long)na->data_size);
@ -1096,8 +1021,7 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
} }
/* Done with the $UpCase mft record. */ /* Done with the $UpCase mft record. */
ntfs_attr_close(na); ntfs_attr_close(na);
if ( ntfs_inode_close( ni ) ) if (ntfs_inode_close(ni)) {
{
ntfs_log_perror("Failed to close $UpCase"); ntfs_log_perror("Failed to close $UpCase");
goto error_exit; goto error_exit;
} }
@ -1108,8 +1032,7 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
*/ */
ntfs_log_debug("Loading $Volume...\n"); ntfs_log_debug("Loading $Volume...\n");
vol->vol_ni = ntfs_inode_open(vol, FILE_Volume); vol->vol_ni = ntfs_inode_open(vol, FILE_Volume);
if ( !vol->vol_ni ) if (!vol->vol_ni) {
{
ntfs_log_perror("Failed to open inode FILE_Volume"); ntfs_log_perror("Failed to open inode FILE_Volume");
goto error_exit; goto error_exit;
} }
@ -1120,16 +1043,14 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
/* Find the $VOLUME_INFORMATION attribute. */ /* Find the $VOLUME_INFORMATION attribute. */
if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL, if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL,
0, ctx ) ) 0, ctx)) {
{
ntfs_log_perror("$VOLUME_INFORMATION attribute not found in " ntfs_log_perror("$VOLUME_INFORMATION attribute not found in "
"$Volume"); "$Volume");
goto error_exit; goto error_exit;
} }
a = ctx->attr; a = ctx->attr;
/* Has to be resident. */ /* Has to be resident. */
if ( a->non_resident ) if (a->non_resident) {
{
ntfs_log_error("Attribute $VOLUME_INFORMATION must be " ntfs_log_error("Attribute $VOLUME_INFORMATION must be "
"resident but it isn't.\n"); "resident but it isn't.\n");
errno = EIO; errno = EIO;
@ -1141,8 +1062,7 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
if ((char*)vinf + le32_to_cpu(a->value_length) > (char*)ctx->mrec + if ((char*)vinf + le32_to_cpu(a->value_length) > (char*)ctx->mrec +
le32_to_cpu(ctx->mrec->bytes_in_use) || le32_to_cpu(ctx->mrec->bytes_in_use) ||
le16_to_cpu(a->value_offset) + le32_to_cpu( le16_to_cpu(a->value_offset) + le32_to_cpu(
a->value_length ) > le32_to_cpu( a->length ) ) a->value_length) > le32_to_cpu(a->length)) {
{
ntfs_log_error("$VOLUME_INFORMATION in $Volume is corrupt.\n"); ntfs_log_error("$VOLUME_INFORMATION in $Volume is corrupt.\n");
errno = EIO; errno = EIO;
goto error_exit; goto error_exit;
@ -1158,10 +1078,8 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
*/ */
ntfs_attr_reinit_search_ctx(ctx); ntfs_attr_reinit_search_ctx(ctx);
if (ntfs_attr_lookup(AT_VOLUME_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, if (ntfs_attr_lookup(AT_VOLUME_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0,
ctx ) ) ctx)) {
{ if (errno != ENOENT) {
if ( errno != ENOENT )
{
ntfs_log_perror("Failed to lookup of $VOLUME_NAME in " ntfs_log_perror("Failed to lookup of $VOLUME_NAME in "
"$Volume failed"); "$Volume failed");
goto error_exit; goto error_exit;
@ -1175,13 +1093,10 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
if (!vol->vol_name) if (!vol->vol_name)
goto error_exit; goto error_exit;
vol->vol_name[0] = '\0'; vol->vol_name[0] = '\0';
} } else {
else
{
a = ctx->attr; a = ctx->attr;
/* Has to be resident. */ /* Has to be resident. */
if ( a->non_resident ) if (a->non_resident) {
{
ntfs_log_error("$VOLUME_NAME must be resident.\n"); ntfs_log_error("$VOLUME_NAME must be resident.\n");
errno = EIO; errno = EIO;
goto error_exit; goto error_exit;
@ -1194,8 +1109,7 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
* format. * format.
*/ */
vol->vol_name = NULL; vol->vol_name = NULL;
if ( ntfs_ucstombs( vname, u, &vol->vol_name, 0 ) == -1 ) if (ntfs_ucstombs(vname, u, &vol->vol_name, 0) == -1) {
{
ntfs_log_perror("Volume name could not be converted " ntfs_log_perror("Volume name could not be converted "
"to current locale"); "to current locale");
ntfs_log_debug("Forcing name into ASCII by replacing " ntfs_log_debug("Forcing name into ASCII by replacing "
@ -1204,8 +1118,7 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
if (!vol->vol_name) if (!vol->vol_name)
goto error_exit; goto error_exit;
for ( j = 0; j < ( s32 )u; j++ ) for (j = 0; j < (s32)u; j++) {
{
u16 uc = le16_to_cpu(vname[j]); u16 uc = le16_to_cpu(vname[j]);
if (uc > 0xff) if (uc > 0xff)
uc = (u16)'_'; uc = (u16)'_';
@ -1219,21 +1132,18 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
/* Now load the attribute definitions from $AttrDef. */ /* Now load the attribute definitions from $AttrDef. */
ntfs_log_debug("Loading $AttrDef...\n"); ntfs_log_debug("Loading $AttrDef...\n");
ni = ntfs_inode_open(vol, FILE_AttrDef); ni = ntfs_inode_open(vol, FILE_AttrDef);
if ( !ni ) if (!ni) {
{
ntfs_log_perror("Failed to open $AttrDef"); ntfs_log_perror("Failed to open $AttrDef");
goto error_exit; goto error_exit;
} }
/* Get an ntfs attribute for $AttrDef/$DATA. */ /* Get an ntfs attribute for $AttrDef/$DATA. */
na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
if ( !na ) if (!na) {
{
ntfs_log_perror("Failed to open ntfs attribute"); ntfs_log_perror("Failed to open ntfs attribute");
goto error_exit; goto error_exit;
} }
/* Check we don't overflow 32-bits. */ /* Check we don't overflow 32-bits. */
if ( na->data_size > 0xffffffffLL ) if (na->data_size > 0xffffffffLL) {
{
ntfs_log_error("Attribute definition table is too big (max " ntfs_log_error("Attribute definition table is too big (max "
"32-bit allowed).\n"); "32-bit allowed).\n");
errno = EINVAL; errno = EINVAL;
@ -1245,8 +1155,7 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
goto error_exit; goto error_exit;
/* Read in the $DATA attribute value into the buffer. */ /* Read in the $DATA attribute value into the buffer. */
l = ntfs_attr_pread(na, 0, na->data_size, vol->attrdef); l = ntfs_attr_pread(na, 0, na->data_size, vol->attrdef);
if ( l != na->data_size ) if (l != na->data_size) {
{
ntfs_log_error("Failed to read $AttrDef, unexpected length " ntfs_log_error("Failed to read $AttrDef, unexpected length "
"(%lld != %lld).\n", (long long)l, "(%lld != %lld).\n", (long long)l,
(long long)na->data_size); (long long)na->data_size);
@ -1255,8 +1164,7 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
} }
/* Done with the $AttrDef mft record. */ /* Done with the $AttrDef mft record. */
ntfs_attr_close(na); ntfs_attr_close(na);
if ( ntfs_inode_close( ni ) ) if (ntfs_inode_close(ni)) {
{
ntfs_log_perror("Failed to close $AttrDef"); ntfs_log_perror("Failed to close $AttrDef");
goto error_exit; goto error_exit;
} }
@ -1264,13 +1172,11 @@ ntfs_volume *ntfs_device_mount( struct ntfs_device *dev, unsigned long flags )
* Check for dirty logfile and hibernated Windows. * Check for dirty logfile and hibernated Windows.
* We care only about read-write mounts. * We care only about read-write mounts.
*/ */
if ( !( flags & MS_RDONLY ) ) if (!(flags & MS_RDONLY)) {
{
if (!(flags & MS_IGNORE_HIBERFILE) && if (!(flags & MS_IGNORE_HIBERFILE) &&
ntfs_volume_check_hiberfile(vol, 1) < 0) ntfs_volume_check_hiberfile(vol, 1) < 0)
goto error_exit; goto error_exit;
if ( ntfs_volume_check_logfile( vol ) < 0 ) if (ntfs_volume_check_logfile(vol) < 0) {
{
if (!(flags & MS_RECOVER)) if (!(flags & MS_RECOVER))
goto error_exit; goto error_exit;
ntfs_log_info("The file system wasn't safely " ntfs_log_info("The file system wasn't safely "
@ -1310,8 +1216,7 @@ int ntfs_set_shown_files( ntfs_volume *vol,
int res; int res;
res = -1; res = -1;
if ( vol ) if (vol) {
{
NVolClearShowSysFiles(vol); NVolClearShowSysFiles(vol);
NVolClearShowHidFiles(vol); NVolClearShowHidFiles(vol);
NVolClearHideDotFiles(vol); NVolClearHideDotFiles(vol);
@ -1337,12 +1242,10 @@ int ntfs_set_ignore_case( ntfs_volume *vol )
int res; int res;
res = -1; res = -1;
if ( vol && vol->upcase ) if (vol && vol->upcase) {
{
vol->locase = ntfs_locase_table_build(vol->upcase, vol->locase = ntfs_locase_table_build(vol->upcase,
vol->upcase_len); vol->upcase_len);
if ( vol->locase ) if (vol->locase) {
{
NVolClearCaseSensitive(vol); NVolClearCaseSensitive(vol);
res = 0; res = 0;
} }
@ -1390,13 +1293,11 @@ ntfs_volume *ntfs_mount( const char *name __attribute__( ( unused ) ),
return NULL; return NULL;
/* Call ntfs_device_mount() to do the actual mount. */ /* Call ntfs_device_mount() to do the actual mount. */
vol = ntfs_device_mount(dev, flags); vol = ntfs_device_mount(dev, flags);
if ( !vol ) if (!vol) {
{
int eo = errno; int eo = errno;
ntfs_device_free(dev); ntfs_device_free(dev);
errno = eo; errno = eo;
} } else
else
ntfs_create_lru_caches(vol); ntfs_create_lru_caches(vol);
return vol; return vol;
#else #else
@ -1437,8 +1338,7 @@ int ntfs_umount( ntfs_volume *vol, const BOOL force __attribute__( ( unused ) )
struct ntfs_device *dev; struct ntfs_device *dev;
int ret; int ret;
if ( !vol ) if (!vol) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@ -1481,23 +1381,19 @@ static int ntfs_mntent_check( const char *file, unsigned long *mnt_flags )
if (!real_file) if (!real_file)
return -1; return -1;
real_fsname = ntfs_malloc(PATH_MAX + 1); real_fsname = ntfs_malloc(PATH_MAX + 1);
if ( !real_fsname ) if (!real_fsname) {
{
err = errno; err = errno;
goto exit; goto exit;
} }
if ( !realpath( file, real_file ) ) if (!realpath(file, real_file)) {
{
err = errno; err = errno;
goto exit; goto exit;
} }
if ( !( f = setmntent( MOUNTED, "r" ) ) ) if (!(f = setmntent(MOUNTED, "r"))) {
{
err = errno; err = errno;
goto exit; goto exit;
} }
while ( ( mnt = getmntent( f ) ) ) while ((mnt = getmntent(f))) {
{
if (!realpath(mnt->mnt_fsname, real_fsname)) if (!realpath(mnt->mnt_fsname, real_fsname))
continue; continue;
if (!strcmp(real_file, real_fsname)) if (!strcmp(real_file, real_fsname))
@ -1516,8 +1412,7 @@ static int ntfs_mntent_check( const char *file, unsigned long *mnt_flags )
exit: exit:
free(real_file); free(real_file);
free(real_fsname); free(real_fsname);
if ( err ) if (err) {
{
errno = err; errno = err;
return -1; return -1;
} }
@ -1581,8 +1476,7 @@ int ntfs_version_is_supported( ntfs_volume *vol )
{ {
u8 major, minor; u8 major, minor;
if ( !vol ) if (!vol) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@ -1624,29 +1518,25 @@ int ntfs_logfile_reset( ntfs_volume *vol )
ntfs_attr *na; ntfs_attr *na;
int eo; int eo;
if ( !vol ) if (!vol) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
ni = ntfs_inode_open(vol, FILE_LogFile); ni = ntfs_inode_open(vol, FILE_LogFile);
if ( !ni ) if (!ni) {
{
ntfs_log_perror("Failed to open inode FILE_LogFile"); ntfs_log_perror("Failed to open inode FILE_LogFile");
return -1; return -1;
} }
na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
if ( !na ) if (!na) {
{
eo = errno; eo = errno;
ntfs_log_perror("Failed to open $FILE_LogFile/$DATA"); ntfs_log_perror("Failed to open $FILE_LogFile/$DATA");
goto error_exit; goto error_exit;
} }
if ( ntfs_empty_logfile( na ) ) if (ntfs_empty_logfile(na)) {
{
eo = errno; eo = errno;
ntfs_attr_close(na); ntfs_attr_close(na);
goto error_exit; goto error_exit;
@ -1678,8 +1568,7 @@ int ntfs_volume_write_flags( ntfs_volume *vol, const le16 flags )
ntfs_attr_search_ctx *ctx; ntfs_attr_search_ctx *ctx;
int ret = -1; /* failure */ int ret = -1; /* failure */
if ( !vol || !vol->vol_ni ) if (!vol || !vol->vol_ni) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@ -1689,16 +1578,14 @@ int ntfs_volume_write_flags( ntfs_volume *vol, const le16 flags )
return -1; return -1;
if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL, if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL,
0, ctx ) ) 0, ctx)) {
{
ntfs_log_error("Attribute $VOLUME_INFORMATION was not found " ntfs_log_error("Attribute $VOLUME_INFORMATION was not found "
"in $Volume!\n"); "in $Volume!\n");
goto err_out; goto err_out;
} }
a = ctx->attr; a = ctx->attr;
/* Sanity check. */ /* Sanity check. */
if ( a->non_resident ) if (a->non_resident) {
{
ntfs_log_error("Attribute $VOLUME_INFORMATION must be resident " ntfs_log_error("Attribute $VOLUME_INFORMATION must be resident "
"but it isn't.\n"); "but it isn't.\n");
errno = EIO; errno = EIO;
@ -1710,8 +1597,7 @@ int ntfs_volume_write_flags( ntfs_volume *vol, const le16 flags )
if ((char*)c + le32_to_cpu(a->value_length) > (char*)ctx->mrec + if ((char*)c + le32_to_cpu(a->value_length) > (char*)ctx->mrec +
le32_to_cpu(ctx->mrec->bytes_in_use) || le32_to_cpu(ctx->mrec->bytes_in_use) ||
le16_to_cpu(a->value_offset) + le16_to_cpu(a->value_offset) +
le32_to_cpu( a->value_length ) > le32_to_cpu( a->length ) ) le32_to_cpu(a->value_length) > le32_to_cpu(a->length)) {
{
ntfs_log_error("Attribute $VOLUME_INFORMATION in $Volume is " ntfs_log_error("Attribute $VOLUME_INFORMATION in $Volume is "
"corrupt!\n"); "corrupt!\n");
errno = EIO; errno = EIO;
@ -1734,8 +1620,7 @@ int ntfs_volume_error( int err )
{ {
int ret; int ret;
switch ( err ) switch (err) {
{
case 0: case 0:
ret = NTFS_VOLUME_OK; ret = NTFS_VOLUME_OK;
break; break;
@ -1770,8 +1655,7 @@ int ntfs_volume_error( int err )
void ntfs_mount_error(const char *volume, const char *mntpoint, int err) void ntfs_mount_error(const char *volume, const char *mntpoint, int err)
{ {
switch ( err ) switch (err) {
{
case NTFS_VOLUME_NOT_NTFS: case NTFS_VOLUME_NOT_NTFS:
ntfs_log_error(invalid_ntfs_msg, volume); ntfs_log_error(invalid_ntfs_msg, volume);
break; break;
@ -1801,8 +1685,7 @@ int ntfs_set_locale( void )
const char *locale; const char *locale;
locale = setlocale(LC_ALL, ""); locale = setlocale(LC_ALL, "");
if ( !locale ) if (!locale) {
{
locale = setlocale(LC_ALL, NULL); locale = setlocale(LC_ALL, NULL);
ntfs_log_error("Couldn't set local environment, using default " ntfs_log_error("Couldn't set local environment, using default "
"'%s'.\n", locale); "'%s'.\n", locale);
@ -1822,12 +1705,9 @@ int ntfs_volume_get_free_space( ntfs_volume *vol )
ret = -1; /* default return */ ret = -1; /* default return */
vol->free_clusters = ntfs_attr_get_free_bits(vol->lcnbmp_na); vol->free_clusters = ntfs_attr_get_free_bits(vol->lcnbmp_na);
if ( vol->free_clusters < 0 ) if (vol->free_clusters < 0) {
{
ntfs_log_perror("Failed to read NTFS $Bitmap"); ntfs_log_perror("Failed to read NTFS $Bitmap");
} } else {
else
{
na = vol->mftbmp_na; na = vol->mftbmp_na;
vol->free_mft_records = ntfs_attr_get_free_bits(na); vol->free_mft_records = ntfs_attr_get_free_bits(na);

View File

@ -74,8 +74,7 @@ typedef struct _ntfs_volume ntfs_volume;
* *
* Flags returned by the ntfs_check_if_mounted() function. * Flags returned by the ntfs_check_if_mounted() function.
*/ */
typedef enum typedef enum {
{
NTFS_MF_MOUNTED = 1, /* Device is mounted. */ NTFS_MF_MOUNTED = 1, /* Device is mounted. */
NTFS_MF_ISROOT = 2, /* Device is mounted as system root. */ NTFS_MF_ISROOT = 2, /* Device is mounted as system root. */
NTFS_MF_READONLY = 4, /* Device is mounted read-only. */ NTFS_MF_READONLY = 4, /* Device is mounted read-only. */
@ -83,8 +82,7 @@ typedef enum
extern int ntfs_check_if_mounted(const char *file, unsigned long *mnt_flags); extern int ntfs_check_if_mounted(const char *file, unsigned long *mnt_flags);
typedef enum typedef enum {
{
NTFS_VOLUME_OK = 0, NTFS_VOLUME_OK = 0,
NTFS_VOLUME_SYNTAX_ERROR = 11, NTFS_VOLUME_SYNTAX_ERROR = 11,
NTFS_VOLUME_NOT_NTFS = 12, NTFS_VOLUME_NOT_NTFS = 12,
@ -105,8 +103,7 @@ typedef enum
* *
* Defined bits for the state field in the ntfs_volume structure. * Defined bits for the state field in the ntfs_volume structure.
*/ */
typedef enum typedef enum {
{
NV_ReadOnly, /* 1: Volume is read-only. */ NV_ReadOnly, /* 1: Volume is read-only. */
NV_CaseSensitive, /* 1: Volume is mounted case-sensitive. */ NV_CaseSensitive, /* 1: Volume is mounted case-sensitive. */
NV_LogFileEmpty, /* 1: $logFile journal is empty. */ NV_LogFileEmpty, /* 1: $logFile journal is empty. */
@ -166,10 +163,8 @@ typedef enum
/** /**
* struct _ntfs_volume - structure describing an open volume in memory. * struct _ntfs_volume - structure describing an open volume in memory.
*/ */
struct _ntfs_volume struct _ntfs_volume {
{ union {
union
{
struct ntfs_device *dev; /* NTFS device associated with struct ntfs_device *dev; /* NTFS device associated with
the volume. */ the volume. */
void *sb; /* For kernel porting compatibility. */ void *sb; /* For kernel porting compatibility. */

View File

@ -56,7 +56,7 @@ bool TitleSelector( char output[] )
{ {
gprintf("TitleSelector()\n"); gprintf("TitleSelector()\n");
u32 num_titles; s32 num_titles;
s32 r = -1; s32 r = -1;
bool ret = false; bool ret = false;
u64 *titleList = NULL; u64 *titleList = NULL;
@ -93,7 +93,7 @@ bool TitleSelector( char output[] )
customOptionList options4( num_titles + 1 ); customOptionList options4( num_titles + 1 );
//write the titles on the option browser //write the titles on the option browser
u32 i = 0; s32 i = 0;
titles.SetType( 0x10001 ); titles.SetType( 0x10001 );
while ( i < num_titles ) while ( i < num_titles )
{ {

View File

@ -98,8 +98,11 @@ int GameList::ReadGameList()
static bool WCharSortCallback(const wchar_t char1, const wchar_t char2) static bool WCharSortCallback(const wchar_t char1, const wchar_t char2)
{ {
if( char2 == 0 )return true; if(char2 == 0)
if( char1 == 0 )return false; return true;
if(char1 == 0)
return false;
return char2 > char1; return char2 > char1;
} }
@ -276,7 +279,7 @@ bool GameList::FavoriteSortCallback( const struct discHdr *a, const struct discH
if (game_num2) if (game_num2)
fav2 = game_num2->favorite; fav2 = game_num2->favorite;
if ( fav1 == fav2 ); if (fav1 == fav2)
return NameSortCallback(a, b); return NameSortCallback(a, b);
return (fav1 > fav2); return (fav1 > fav2);