mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-16 00:15:08 +01:00
*Enabled NTFS writing
*Fixed favorite sorting
This commit is contained in:
parent
6012536f67
commit
9594155a8d
@ -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.
|
||||||
|
8
Makefile
8
Makefile
@ -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
|
||||||
|
@ -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
@ -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
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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
@ -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
|
||||||
|
@ -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, §_size ) )
|
if (!dev->d_ops->ioctl(dev, BLKSSZGET, §_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;
|
||||||
|
@ -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);
|
||||||
|
@ -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
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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) */
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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(). */
|
||||||
|
@ -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__,
|
||||||
|
@ -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. */
|
||||||
|
@ -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;
|
||||||
|
@ -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];
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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, §or.buffer ) )
|
if (!interface->readSectors(0, 1, §or.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, §or, sizeof(MASTER_BOOT_RECORD));
|
memcpy(&mbr, §or, 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, §or ) )
|
if (interface->readSectors(part_lba, 1, §or)) {
|
||||||
{
|
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, §or ) )
|
if (interface->readSectors(ebr_lba + next_erb_lba, 1, §or)) {
|
||||||
{
|
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, §or ) )
|
if (interface->readSectors(part_lba, 1, §or)) {
|
||||||
{
|
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, §or ) )
|
if (interface->readSectors(part_lba, 1, §or)) {
|
||||||
{
|
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, §or)) {
|
||||||
if ( interface->readSectors( i, 1, §or ) )
|
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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
||||||
|
@ -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)'_';
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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. */
|
||||||
|
@ -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 )
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user