*Enabled NTFS writing

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

View File

@ -2,8 +2,8 @@
<app version="1">
<name> USB Loader GX</name>
<coder>USB Loader GX Team</coder>
<version>1.0 r953</version>
<release_date>201009190727</release_date>
<version>1.0 r957</version>
<release_date>201009191357</release_date>
<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.
The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller.

View File

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

View File

@ -9,8 +9,8 @@
#include "usbloader/usbstorage2.h"
#include "usbloader/sdhc.h"
#include "usbloader/wbfs.h"
#include "libfat/fat.h"
#include "libntfs/ntfs.h"
#include "libfat/fat.h"
#include "gecko.h"
//these are the only stable and speed is good
@ -215,7 +215,7 @@ s32 MountNTFS( u32 sector )
// }
/* Mount device */
// 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 )
{
return -2;
@ -226,11 +226,11 @@ s32 MountNTFS( u32 sector )
{
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
{
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 )
{

File diff suppressed because it is too large Load Diff

View File

@ -64,7 +64,7 @@
* when checking, check one is present
*/
/* flags which are set to mean exec, write or read */
/* flags which are set to mean exec, write or read */
#define FILE_READ (FILE_READ_DATA)
#define FILE_WRITE (FILE_WRITE_DATA | FILE_APPEND_DATA \
@ -75,8 +75,8 @@
| READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA)
#define DIR_EXEC (FILE_TRAVERSE)
/* flags tested for meaning exec, write or read */
/* tests for write allow for interpretation of a sticky bit */
/* flags tested for meaning exec, write or read */
/* tests for write allow for interpretation of a sticky bit */
#define FILE_GREAD (FILE_READ_DATA | GENERIC_READ)
#define FILE_GWRITE (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)
@ -85,19 +85,19 @@
#define DIR_GWRITE (FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | GENERIC_WRITE)
#define DIR_GEXEC (FILE_TRAVERSE | GENERIC_EXECUTE)
/* standard owner (and administrator) rights */
/* standard owner (and administrator) rights */
#define OWNER_RIGHTS (DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER \
| SYNCHRONIZE \
| FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES \
| FILE_READ_EA | FILE_WRITE_EA)
/* standard world rights */
/* standard world rights */
#define WORLD_RIGHTS (READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_EA \
| SYNCHRONIZE)
/* inheritance flags for files and directories */
/* inheritance flags for files and directories */
#define FILE_INHERITANCE NO_PROPAGATE_INHERIT_ACE
#define DIR_INHERITANCE (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE)
@ -122,8 +122,7 @@ typedef char BIGSID[40];
* (private to this module)
*/
struct MAPLIST
{
struct MAPLIST {
struct MAPLIST *next;
char *uidstr; /* uid text from the same record */
char *gidstr; /* gid text from the same record */
@ -131,7 +130,7 @@ struct MAPLIST
char maptext[LINESZ + 1];
};
typedef int ( *FILEREADER )( void *fileid, char *buf, size_t size, off_t pos );
typedef int (*FILEREADER)(void *fileid, char *buf, size_t size, off_t pos);
/*
* Constants defined in acls.c
@ -144,57 +143,57 @@ extern const SID *worldsid;
* Functions defined in acls.c
*/
BOOL ntfs_valid_descr( const char *securattr, unsigned int attrsz );
BOOL ntfs_valid_pattern( const SID *sid );
BOOL ntfs_valid_sid( const SID *sid );
BOOL ntfs_same_sid( const SID *first, const SID *second );
BOOL ntfs_valid_descr(const char *securattr, unsigned int attrsz);
BOOL ntfs_valid_pattern(const SID *sid);
BOOL ntfs_valid_sid(const SID *sid);
BOOL ntfs_same_sid(const SID *first, const SID *second);
BOOL ntfs_is_user_sid( const SID *usid );
BOOL ntfs_is_user_sid(const SID *usid);
int ntfs_sid_size( const SID * sid );
unsigned int ntfs_attr_size( const char *attr );
int ntfs_sid_size(const SID * sid);
unsigned int ntfs_attr_size(const char *attr);
const SID *ntfs_find_usid( const struct MAPPING *usermapping,
uid_t uid, SID *pdefsid );
const SID *ntfs_find_gsid( const struct MAPPING *groupmapping,
gid_t gid, SID *pdefsid );
uid_t ntfs_find_user( const struct MAPPING *usermapping, const SID *usid );
gid_t ntfs_find_group( const struct MAPPING *groupmapping, const SID * gsid );
const SID *ntfs_acl_owner( const char *secattr );
const SID *ntfs_find_usid(const struct MAPPING *usermapping,
uid_t uid, SID *pdefsid);
const SID *ntfs_find_gsid(const struct MAPPING *groupmapping,
gid_t gid, SID *pdefsid);
uid_t ntfs_find_user(const struct MAPPING *usermapping, const SID *usid);
gid_t ntfs_find_group(const struct MAPPING *groupmapping, const SID * gsid);
const SID *ntfs_acl_owner(const char *secattr);
#if POSIXACLS
BOOL ntfs_valid_posix( const struct POSIX_SECURITY *pxdesc );
void ntfs_sort_posix( struct POSIX_SECURITY *pxdesc );
int ntfs_merge_mode_posix( struct POSIX_SECURITY *pxdesc, mode_t mode );
BOOL ntfs_valid_posix(const struct POSIX_SECURITY *pxdesc);
void ntfs_sort_posix(struct POSIX_SECURITY *pxdesc);
int ntfs_merge_mode_posix(struct POSIX_SECURITY *pxdesc, mode_t mode);
struct POSIX_SECURITY *ntfs_build_inherited_posix(
const struct POSIX_SECURITY *pxdesc, mode_t mode,
mode_t umask, BOOL isdir );
struct POSIX_SECURITY *ntfs_replace_acl( const struct POSIX_SECURITY *oldpxdesc,
const struct POSIX_ACL *newacl, int count, BOOL deflt );
mode_t umask, BOOL isdir);
struct POSIX_SECURITY *ntfs_replace_acl(const struct POSIX_SECURITY *oldpxdesc,
const struct POSIX_ACL *newacl, int count, BOOL deflt);
struct POSIX_SECURITY *ntfs_build_permissions_posix(
struct MAPPING* const mapping[],
const char *securattr,
const SID *usid, const SID *gsid, BOOL isdir );
struct POSIX_SECURITY *ntfs_merge_descr_posix( const struct POSIX_SECURITY *first,
const struct POSIX_SECURITY *second );
char *ntfs_build_descr_posix( struct MAPPING* const mapping[],
const SID *usid, const SID *gsid, BOOL isdir);
struct POSIX_SECURITY *ntfs_merge_descr_posix(const struct POSIX_SECURITY *first,
const struct POSIX_SECURITY *second);
char *ntfs_build_descr_posix(struct MAPPING* const mapping[],
struct POSIX_SECURITY *pxdesc,
int isdir, const SID *usid, const SID *gsid );
int isdir, const SID *usid, const SID *gsid);
#endif /* POSIXACLS */
int ntfs_inherit_acl( const ACL *oldacl, ACL *newacl,
const SID *usid, const SID *gsid, BOOL fordir );
int ntfs_build_permissions( const char *securattr,
const SID *usid, const SID *gsid, BOOL isdir );
char *ntfs_build_descr( mode_t mode,
int isdir, const SID * usid, const SID * gsid );
struct MAPLIST *ntfs_read_mapping( FILEREADER reader, void *fileid );
struct MAPPING *ntfs_do_user_mapping( struct MAPLIST *firstitem );
struct MAPPING *ntfs_do_group_mapping( struct MAPLIST *firstitem );
void ntfs_free_mapping( struct MAPPING *mapping[] );
int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
const SID *usid, const SID *gsid, BOOL fordir);
int ntfs_build_permissions(const char *securattr,
const SID *usid, const SID *gsid, BOOL isdir);
char *ntfs_build_descr(mode_t mode,
int isdir, const SID * usid, const SID * gsid);
struct MAPLIST *ntfs_read_mapping(FILEREADER reader, void *fileid);
struct MAPPING *ntfs_do_user_mapping(struct MAPLIST *firstitem);
struct MAPPING *ntfs_do_group_mapping(struct MAPLIST *firstitem);
void ntfs_free_mapping(struct MAPPING *mapping[]);
#endif /* ACLS_H */

File diff suppressed because it is too large Load Diff

View File

@ -49,8 +49,7 @@ extern ntfschar TXF_DATA[10];
*
* TODO: Describe them.
*/
typedef enum
{
typedef enum {
LCN_HOLE = -1, /* Keep this as highest value or die! */
LCN_RL_NOT_MAPPED = -2,
LCN_ENOENT = -3,
@ -76,8 +75,7 @@ typedef enum
* any modification of the search context, to automagically get the next
* matching attribute.
*/
struct _ntfs_attr_search_ctx
{
struct _ntfs_attr_search_ctx {
MFT_RECORD *mrec;
ATTR_RECORD *attr;
BOOL is_first;
@ -88,20 +86,20 @@ struct _ntfs_attr_search_ctx
ATTR_RECORD *base_attr;
};
extern void ntfs_attr_reinit_search_ctx( ntfs_attr_search_ctx *ctx );
extern ntfs_attr_search_ctx *ntfs_attr_get_search_ctx( ntfs_inode *ni,
MFT_RECORD *mrec );
extern void ntfs_attr_put_search_ctx( ntfs_attr_search_ctx *ctx );
extern void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx);
extern ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni,
MFT_RECORD *mrec);
extern void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx);
extern int ntfs_attr_lookup( const ATTR_TYPES type, const ntfschar *name,
extern int ntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name,
const u32 name_len, const IGNORE_CASE_BOOL ic,
const VCN lowest_vcn, const u8 *val, const u32 val_len,
ntfs_attr_search_ctx *ctx );
ntfs_attr_search_ctx *ctx);
extern int ntfs_attr_position( const ATTR_TYPES type, ntfs_attr_search_ctx *ctx );
extern int ntfs_attr_position(const ATTR_TYPES type, ntfs_attr_search_ctx *ctx);
extern ATTR_DEF *ntfs_attr_find_in_attrdef( const ntfs_volume *vol,
const ATTR_TYPES type );
extern ATTR_DEF *ntfs_attr_find_in_attrdef(const ntfs_volume *vol,
const ATTR_TYPES type);
/**
* ntfs_attrs_walk - syntactic sugar for walking all attributes in an inode
@ -128,10 +126,10 @@ extern ATTR_DEF *ntfs_attr_find_in_attrdef( const ntfs_volume *vol,
* // Ooops. An error occurred! You should handle this case.
* // Now finished with all attributes in the inode.
*/
static __inline__ int ntfs_attrs_walk( ntfs_attr_search_ctx *ctx )
static __inline__ int ntfs_attrs_walk(ntfs_attr_search_ctx *ctx)
{
return ntfs_attr_lookup( AT_UNUSED, NULL, 0, CASE_SENSITIVE, 0,
NULL, 0, ctx );
return ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE, 0,
NULL, 0, ctx);
}
/**
@ -176,8 +174,7 @@ static __inline__ int ntfs_attrs_walk( ntfs_attr_search_ctx *ctx )
* @state contains NTFS attribute specific flags describing this attribute
* structure. See ntfs_attr_state_bits above.
*/
struct _ntfs_attr
{
struct _ntfs_attr {
runlist_element *rl;
ntfs_inode *ni;
ATTR_TYPES type;
@ -199,8 +196,7 @@ struct _ntfs_attr
* enum ntfs_attr_state_bits - bits for the state field in the ntfs_attr
* structure
*/
typedef enum
{
typedef enum {
NA_Initialized, /* 1: structure is initialized. */
NA_NonResident, /* 1: Attribute is not resident. */
NA_BeingNonResident, /* 1: Attribute is being made not resident. */
@ -237,9 +233,9 @@ extern int NAttr##func_name(ntfs_attr *na); \
extern void NAttrSet##func_name(ntfs_attr *na); \
extern void NAttrClear##func_name(ntfs_attr *na);
GenNAttrIno( Compressed, FILE_ATTR_COMPRESSED )
GenNAttrIno( Encrypted, FILE_ATTR_ENCRYPTED )
GenNAttrIno( Sparse, FILE_ATTR_SPARSE_FILE )
GenNAttrIno(Compressed, FILE_ATTR_COMPRESSED)
GenNAttrIno(Encrypted, FILE_ATTR_ENCRYPTED)
GenNAttrIno(Sparse, FILE_ATTR_SPARSE_FILE)
#undef GenNAttrIno
/**
@ -247,8 +243,7 @@ GenNAttrIno( Sparse, FILE_ATTR_SPARSE_FILE )
*
* For convenience. Used in the attr structure.
*/
typedef union
{
typedef union {
u8 _default; /* Unnamed u8 to serve as default when just using
a_val without specifying any of the below. */
STANDARD_INFORMATION std_inf;
@ -270,73 +265,73 @@ typedef union
EFS_ATTR_HEADER efs;
} attr_val;
extern void ntfs_attr_init( ntfs_attr *na, const BOOL non_resident,
extern void ntfs_attr_init(ntfs_attr *na, const BOOL non_resident,
const ATTR_FLAGS data_flags, const BOOL encrypted,
const BOOL sparse,
const s64 allocated_size, const s64 data_size,
const s64 initialized_size, const s64 compressed_size,
const u8 compression_unit );
const u8 compression_unit);
/* warning : in the following "name" has to be freeable */
/* or one of constants AT_UNNAMED, NTFS_INDEX_I30 or STREAM_SDS */
extern ntfs_attr *ntfs_attr_open( ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len );
extern void ntfs_attr_close( ntfs_attr *na );
/* warning : in the following "name" has to be freeable */
/* or one of constants AT_UNNAMED, NTFS_INDEX_I30 or STREAM_SDS */
extern ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len);
extern void ntfs_attr_close(ntfs_attr *na);
extern s64 ntfs_attr_pread( ntfs_attr *na, const s64 pos, s64 count,
void *b );
extern s64 ntfs_attr_pwrite( ntfs_attr *na, const s64 pos, s64 count,
const void *b );
extern int ntfs_attr_pclose( ntfs_attr *na );
extern s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count,
void *b);
extern s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count,
const void *b);
extern int ntfs_attr_pclose(ntfs_attr *na);
extern void *ntfs_attr_readall( ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len, s64 *data_size );
extern void *ntfs_attr_readall(ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len, s64 *data_size);
extern s64 ntfs_attr_mst_pread( ntfs_attr *na, const s64 pos,
const s64 bk_cnt, const u32 bk_size, void *dst );
extern s64 ntfs_attr_mst_pwrite( ntfs_attr *na, const s64 pos,
s64 bk_cnt, const u32 bk_size, void *src );
extern s64 ntfs_attr_mst_pread(ntfs_attr *na, const s64 pos,
const s64 bk_cnt, const u32 bk_size, void *dst);
extern s64 ntfs_attr_mst_pwrite(ntfs_attr *na, const s64 pos,
s64 bk_cnt, const u32 bk_size, void *src);
extern int ntfs_attr_map_runlist( ntfs_attr *na, VCN vcn );
extern int ntfs_attr_map_whole_runlist( ntfs_attr *na );
extern int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn);
extern int ntfs_attr_map_whole_runlist(ntfs_attr *na);
extern LCN ntfs_attr_vcn_to_lcn( ntfs_attr *na, const VCN vcn );
extern runlist_element *ntfs_attr_find_vcn( ntfs_attr *na, const VCN vcn );
extern LCN ntfs_attr_vcn_to_lcn(ntfs_attr *na, const VCN vcn);
extern runlist_element *ntfs_attr_find_vcn(ntfs_attr *na, const VCN vcn);
extern int ntfs_attr_size_bounds_check( const ntfs_volume *vol,
const ATTR_TYPES type, const s64 size );
extern int ntfs_attr_can_be_resident( const ntfs_volume *vol,
const ATTR_TYPES type );
int ntfs_attr_make_non_resident( ntfs_attr *na,
ntfs_attr_search_ctx *ctx );
int ntfs_attr_force_non_resident( ntfs_attr *na );
extern int ntfs_make_room_for_attr( MFT_RECORD *m, u8 *pos, u32 size );
extern int ntfs_attr_size_bounds_check(const ntfs_volume *vol,
const ATTR_TYPES type, const s64 size);
extern int ntfs_attr_can_be_resident(const ntfs_volume *vol,
const ATTR_TYPES type);
int ntfs_attr_make_non_resident(ntfs_attr *na,
ntfs_attr_search_ctx *ctx);
int ntfs_attr_force_non_resident(ntfs_attr *na);
extern int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size);
extern int ntfs_resident_attr_record_add( ntfs_inode *ni, ATTR_TYPES type,
extern int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
ntfschar *name, u8 name_len, u8 *val, u32 size,
ATTR_FLAGS flags );
extern int ntfs_non_resident_attr_record_add( ntfs_inode *ni, ATTR_TYPES type,
ATTR_FLAGS flags);
extern int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
ntfschar *name, u8 name_len, VCN lowest_vcn, int dataruns_size,
ATTR_FLAGS flags );
extern int ntfs_attr_record_rm( ntfs_attr_search_ctx *ctx );
ATTR_FLAGS flags);
extern int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx);
extern int ntfs_attr_add( ntfs_inode *ni, ATTR_TYPES type,
ntfschar *name, u8 name_len, u8 *val, s64 size );
extern int ntfs_attr_set_flags( ntfs_inode *ni, ATTR_TYPES type,
ntfschar *name, u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask );
extern int ntfs_attr_rm( ntfs_attr *na );
extern int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type,
ntfschar *name, u8 name_len, u8 *val, s64 size);
extern int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type,
ntfschar *name, u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask);
extern int ntfs_attr_rm(ntfs_attr *na);
extern int ntfs_attr_record_resize( MFT_RECORD *m, ATTR_RECORD *a, u32 new_size );
extern int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size);
extern int ntfs_resident_attr_value_resize( MFT_RECORD *m, ATTR_RECORD *a,
const u32 new_size );
extern int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a,
const u32 new_size);
extern int ntfs_attr_record_move_to( ntfs_attr_search_ctx *ctx, ntfs_inode *ni );
extern int ntfs_attr_record_move_away( ntfs_attr_search_ctx *ctx, int extra );
extern int ntfs_attr_record_move_to(ntfs_attr_search_ctx *ctx, ntfs_inode *ni);
extern int ntfs_attr_record_move_away(ntfs_attr_search_ctx *ctx, int extra);
extern int ntfs_attr_update_mapping_pairs( ntfs_attr *na, VCN from_vcn );
extern int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn);
extern int ntfs_attr_truncate( ntfs_attr *na, const s64 newsize );
extern int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize);
/**
* get_attribute_value_length - return the length of the value of an attribute
@ -349,7 +344,7 @@ extern int ntfs_attr_truncate( ntfs_attr *na, const s64 newsize );
*
* FIXME: Describe possible errnos.
*/
extern s64 ntfs_get_attribute_value_length( const ATTR_RECORD *a );
extern s64 ntfs_get_attribute_value_length(const ATTR_RECORD *a);
/**
* get_attribute_value - return the attribute value of an attribute
@ -365,16 +360,16 @@ extern s64 ntfs_get_attribute_value_length( const ATTR_RECORD *a );
* then nothing was read due to a zero-length attribute value, otherwise
* errno describes the error.
*/
extern s64 ntfs_get_attribute_value( const ntfs_volume *vol,
const ATTR_RECORD *a, u8 *b );
extern s64 ntfs_get_attribute_value(const ntfs_volume *vol,
const ATTR_RECORD *a, u8 *b);
extern void ntfs_attr_name_free( char **name );
extern char *ntfs_attr_name_get( const ntfschar *uname, const int uname_len );
extern int ntfs_attr_exist( ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len );
extern int ntfs_attr_remove( ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len );
extern s64 ntfs_attr_get_free_bits( ntfs_attr *na );
extern void ntfs_attr_name_free(char **name);
extern char *ntfs_attr_name_get(const ntfschar *uname, const int uname_len);
extern int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len);
extern int ntfs_attr_remove(ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len);
extern s64 ntfs_attr_get_free_bits(ntfs_attr *na);
#endif /* defined _NTFS_ATTRIB_H */

View File

@ -58,40 +58,36 @@
* EINVAL - Invalid arguments passed to function or attribute haven't got
* attribute list.
*/
int ntfs_attrlist_need( ntfs_inode *ni )
int ntfs_attrlist_need(ntfs_inode *ni)
{
ATTR_LIST_ENTRY *ale;
if ( !ni )
{
ntfs_log_trace( "Invalid arguments.\n" );
if (!ni) {
ntfs_log_trace("Invalid arguments.\n");
errno = EINVAL;
return -1;
}
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 ) )
{
ntfs_log_trace( "Inode haven't got attribute list.\n" );
if (!NInoAttrList(ni)) {
ntfs_log_trace("Inode haven't got attribute list.\n");
errno = EINVAL;
return -1;
}
if ( !ni->attr_list )
{
ntfs_log_trace( "Corrupt in-memory struct.\n" );
if (!ni->attr_list) {
ntfs_log_trace("Corrupt in-memory struct.\n");
errno = EINVAL;
return -1;
}
errno = 0;
ale = ( ATTR_LIST_ENTRY * )ni->attr_list;
while ( ( u8* )ale < ni->attr_list + ni->attr_list_size )
{
if ( MREF_LE( ale->mft_reference ) != ni->mft_no )
ale = (ATTR_LIST_ENTRY *)ni->attr_list;
while ((u8*)ale < ni->attr_list + ni->attr_list_size) {
if (MREF_LE(ale->mft_reference) != ni->mft_no)
return 1;
ale = ( ATTR_LIST_ENTRY * )( ( u8* )ale + le16_to_cpu( ale->length ) );
ale = (ATTR_LIST_ENTRY *)((u8*)ale + le16_to_cpu(ale->length));
}
return 0;
}
@ -108,7 +104,7 @@ int ntfs_attrlist_need( ntfs_inode *ni )
* EIO - I/O error occurred or damaged filesystem.
* EEXIST - Such attribute already present in attribute list.
*/
int ntfs_attrlist_entry_add( ntfs_inode *ni, ATTR_RECORD *attr )
int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr)
{
ATTR_LIST_ENTRY *ale;
MFT_REF mref;
@ -117,132 +113,122 @@ int ntfs_attrlist_entry_add( ntfs_inode *ni, ATTR_RECORD *attr )
u8 *new_al;
int entry_len, entry_offset, err;
ntfs_log_trace( "Entering for inode 0x%llx, attr 0x%x.\n",
( long long ) ni->mft_no,
( unsigned ) le32_to_cpu( attr->type ) );
ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n",
(long long) ni->mft_no,
(unsigned) le32_to_cpu(attr->type));
if ( !ni || !attr )
{
ntfs_log_trace( "Invalid arguments.\n" );
if (!ni || !attr) {
ntfs_log_trace("Invalid arguments.\n");
errno = EINVAL;
return -1;
}
mref = MK_LE_MREF( ni->mft_no, le16_to_cpu( ni->mrec->sequence_number ) );
mref = MK_LE_MREF(ni->mft_no, le16_to_cpu(ni->mrec->sequence_number));
if ( ni->nr_extents == -1 )
if (ni->nr_extents == -1)
ni = ni->base_ni;
if ( !NInoAttrList( ni ) )
{
ntfs_log_trace( "Attribute list isn't present.\n" );
if (!NInoAttrList(ni)) {
ntfs_log_trace("Attribute list isn't present.\n");
errno = ENOENT;
return -1;
}
/* Determine size and allocate memory for new attribute list. */
entry_len = ( sizeof( ATTR_LIST_ENTRY ) + sizeof( ntfschar ) *
attr->name_length + 7 ) & ~7;
new_al = ntfs_calloc( ni->attr_list_size + entry_len );
if ( !new_al )
entry_len = (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) *
attr->name_length + 7) & ~7;
new_al = ntfs_calloc(ni->attr_list_size + entry_len);
if (!new_al)
return -1;
/* Find place for the new entry. */
ctx = ntfs_attr_get_search_ctx( ni, NULL );
if ( !ctx )
{
ctx = ntfs_attr_get_search_ctx(ni, NULL);
if (!ctx) {
err = errno;
goto err_out;
}
if ( !ntfs_attr_lookup( attr->type, ( attr->name_length ) ? ( ntfschar* )
( ( u8* )attr + le16_to_cpu( attr->name_offset ) ) :
if (!ntfs_attr_lookup(attr->type, (attr->name_length) ? (ntfschar*)
((u8*)attr + le16_to_cpu(attr->name_offset)) :
AT_UNNAMED, attr->name_length, CASE_SENSITIVE,
( attr->non_resident ) ? le64_to_cpu( attr->lowest_vcn ) :
0, ( attr->non_resident ) ? NULL : ( ( u8* )attr +
le16_to_cpu( attr->value_offset ) ), ( attr->non_resident ) ?
0 : le32_to_cpu( attr->value_length ), ctx ) )
{
(attr->non_resident) ? le64_to_cpu(attr->lowest_vcn) :
0, (attr->non_resident) ? NULL : ((u8*)attr +
le16_to_cpu(attr->value_offset)), (attr->non_resident) ?
0 : le32_to_cpu(attr->value_length), ctx)) {
/* 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;
ntfs_log_trace( "Such attribute already present in the "
"attribute list.\n" );
ntfs_attr_put_search_ctx( ctx );
ntfs_log_trace("Such attribute already present in the "
"attribute list.\n");
ntfs_attr_put_search_ctx(ctx);
goto err_out;
}
/* Add new entry after this extent. */
ale = ( ATTR_LIST_ENTRY* )( ( u8* )ctx->al_entry +
le16_to_cpu( ctx->al_entry->length ) );
}
else
{
ale = (ATTR_LIST_ENTRY*)((u8*)ctx->al_entry +
le16_to_cpu(ctx->al_entry->length));
} else {
/* Check for real errors. */
if ( errno != ENOENT )
{
if (errno != ENOENT) {
err = errno;
ntfs_log_trace( "Attribute lookup failed.\n" );
ntfs_attr_put_search_ctx( ctx );
ntfs_log_trace("Attribute lookup failed.\n");
ntfs_attr_put_search_ctx(ctx);
goto err_out;
}
/* No previous extents found. */
ale = ctx->al_entry;
}
/* Don't need it anymore, @ctx->al_entry points to @ni->attr_list. */
ntfs_attr_put_search_ctx( ctx );
ntfs_attr_put_search_ctx(ctx);
/* Determine new entry offset. */
entry_offset = ( ( u8 * )ale - ni->attr_list );
entry_offset = ((u8 *)ale - ni->attr_list);
/* Set pointer to new entry. */
ale = ( ATTR_LIST_ENTRY * )( new_al + entry_offset );
ale = (ATTR_LIST_ENTRY *)(new_al + entry_offset);
/* Zero it to fix valgrind warning. */
memset( ale, 0, entry_len );
memset(ale, 0, entry_len);
/* Form new entry. */
ale->type = attr->type;
ale->length = cpu_to_le16( entry_len );
ale->length = cpu_to_le16(entry_len);
ale->name_length = attr->name_length;
ale->name_offset = offsetof( ATTR_LIST_ENTRY, name );
if ( attr->non_resident )
ale->name_offset = offsetof(ATTR_LIST_ENTRY, name);
if (attr->non_resident)
ale->lowest_vcn = attr->lowest_vcn;
else
ale->lowest_vcn = 0;
ale->mft_reference = mref;
ale->instance = attr->instance;
memcpy( ale->name, ( u8 * )attr + le16_to_cpu( attr->name_offset ),
attr->name_length * sizeof( ntfschar ) );
memcpy(ale->name, (u8 *)attr + le16_to_cpu(attr->name_offset),
attr->name_length * sizeof(ntfschar));
/* Resize $ATTRIBUTE_LIST to new length. */
na = ntfs_attr_open( ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0 );
if ( !na )
{
na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);
if (!na) {
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;
}
if ( ntfs_attr_truncate( na, ni->attr_list_size + entry_len ) )
{
if (ntfs_attr_truncate(na, ni->attr_list_size + entry_len)) {
err = errno;
ntfs_log_trace( "$ATTRIBUTE_LIST resize failed.\n" );
ntfs_log_trace("$ATTRIBUTE_LIST resize failed.\n");
goto err_out;
}
/* Copy entries from old attribute list to new. */
memcpy( new_al, ni->attr_list, entry_offset );
memcpy( new_al + entry_offset + entry_len, ni->attr_list +
entry_offset, ni->attr_list_size - entry_offset );
memcpy(new_al, ni->attr_list, entry_offset);
memcpy(new_al + entry_offset + entry_len, ni->attr_list +
entry_offset, ni->attr_list_size - entry_offset);
/* Set new runlist. */
free( ni->attr_list );
free(ni->attr_list);
ni->attr_list = new_al;
ni->attr_list_size = ni->attr_list_size + entry_len;
NInoAttrListSetDirty( ni );
NInoAttrListSetDirty(ni);
/* Done! */
ntfs_attr_close( na );
ntfs_attr_close(na);
return 0;
err_out:
if ( na )
ntfs_attr_close( na );
free( new_al );
if (na)
ntfs_attr_close(na);
free(new_al);
errno = err;
return -1;
}
@ -255,7 +241,7 @@ err_out:
*
* Return 0 on success and -1 on error with errno set to the error code.
*/
int ntfs_attrlist_entry_rm( ntfs_attr_search_ctx *ctx )
int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx)
{
u8 *new_al;
int new_al_len;
@ -264,69 +250,65 @@ int ntfs_attrlist_entry_rm( ntfs_attr_search_ctx *ctx )
ATTR_LIST_ENTRY *ale;
int err;
if ( !ctx || !ctx->ntfs_ino || !ctx->al_entry )
{
ntfs_log_trace( "Invalid arguments.\n" );
if (!ctx || !ctx->ntfs_ino || !ctx->al_entry) {
ntfs_log_trace("Invalid arguments.\n");
errno = EINVAL;
return -1;
}
if ( ctx->base_ntfs_ino )
if (ctx->base_ntfs_ino)
base_ni = ctx->base_ntfs_ino;
else
base_ni = ctx->ntfs_ino;
ale = ctx->al_entry;
ntfs_log_trace( "Entering for inode 0x%llx, attr 0x%x, lowest_vcn %lld.\n",
( long long ) ctx->ntfs_ino->mft_no,
( unsigned ) le32_to_cpu( ctx->al_entry->type ),
( long long ) le64_to_cpu( ctx->al_entry->lowest_vcn ) );
ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, lowest_vcn %lld.\n",
(long long) ctx->ntfs_ino->mft_no,
(unsigned) le32_to_cpu(ctx->al_entry->type),
(long long) le64_to_cpu(ctx->al_entry->lowest_vcn));
if ( !NInoAttrList( base_ni ) )
{
ntfs_log_trace( "Attribute list isn't present.\n" );
if (!NInoAttrList(base_ni)) {
ntfs_log_trace("Attribute list isn't present.\n");
errno = ENOENT;
return -1;
}
/* Allocate memory for new attribute list. */
new_al_len = base_ni->attr_list_size - le16_to_cpu( ale->length );
new_al = ntfs_calloc( new_al_len );
if ( !new_al )
new_al_len = base_ni->attr_list_size - le16_to_cpu(ale->length);
new_al = ntfs_calloc(new_al_len);
if (!new_al)
return -1;
/* Reisze $ATTRIBUTE_LIST to new length. */
na = ntfs_attr_open( base_ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0 );
if ( !na )
{
na = ntfs_attr_open(base_ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);
if (!na) {
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;
}
if ( ntfs_attr_truncate( na, new_al_len ) )
{
if (ntfs_attr_truncate(na, new_al_len)) {
err = errno;
ntfs_log_trace( "$ATTRIBUTE_LIST resize failed.\n" );
ntfs_log_trace("$ATTRIBUTE_LIST resize failed.\n");
goto err_out;
}
/* Copy entries from old attribute list to new. */
memcpy( new_al, base_ni->attr_list, ( u8* )ale - base_ni->attr_list );
memcpy( new_al + ( ( u8* )ale - base_ni->attr_list ), ( u8* )ale + le16_to_cpu(
ale->length ), new_al_len - ( ( u8* )ale - base_ni->attr_list ) );
memcpy(new_al, base_ni->attr_list, (u8*)ale - base_ni->attr_list);
memcpy(new_al + ((u8*)ale - base_ni->attr_list), (u8*)ale + le16_to_cpu(
ale->length), new_al_len - ((u8*)ale - base_ni->attr_list));
/* Set new runlist. */
free( base_ni->attr_list );
free(base_ni->attr_list);
base_ni->attr_list = new_al;
base_ni->attr_list_size = new_al_len;
NInoAttrListSetDirty( base_ni );
NInoAttrListSetDirty(base_ni);
/* Done! */
ntfs_attr_close( na );
ntfs_attr_close(na);
return 0;
err_out:
if ( na )
ntfs_attr_close( na );
free( new_al );
if (na)
ntfs_attr_close(na);
free(new_al);
errno = err;
return -1;
}

View File

@ -26,10 +26,10 @@
#include "attrib.h"
extern int ntfs_attrlist_need( ntfs_inode *ni );
extern int ntfs_attrlist_need(ntfs_inode *ni);
extern int ntfs_attrlist_entry_add( ntfs_inode *ni, ATTR_RECORD *attr );
extern int ntfs_attrlist_entry_rm( ntfs_attr_search_ctx *ctx );
extern int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr);
extern int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx);
/**
* ntfs_attrlist_mark_dirty - set the attribute list dirty
@ -40,12 +40,12 @@ extern int ntfs_attrlist_entry_rm( ntfs_attr_search_ctx *ctx );
*
* This function cannot fail.
*/
static __inline__ void ntfs_attrlist_mark_dirty( ntfs_inode *ni )
static __inline__ void ntfs_attrlist_mark_dirty(ntfs_inode *ni)
{
if ( ni->nr_extents == -1 )
NInoAttrListSetDirty( ni->base_ni );
if (ni->nr_extents == -1)
NInoAttrListSetDirty(ni->base_ni);
else
NInoAttrListSetDirty( ni );
NInoAttrListSetDirty(ni);
}
#endif /* defined _NTFS_ATTRLIST_H */

View File

@ -34,28 +34,24 @@
/*-----------------------------------------------------------------
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 )
{
return ( item[offset] | ( item[offset + 1] << 8 ) );
static inline uint16_t u8array_to_u16 (const uint8_t* item, int offset) {
return ( item[offset] | (item[offset + 1] << 8));
}
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 ) );
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));
}
static inline void u16_to_u8array ( uint8_t* item, int offset, uint16_t value )
{
item[offset] = ( uint8_t ) value;
item[offset + 1] = ( uint8_t )( value >> 8 );
static inline void u16_to_u8array (uint8_t* item, int offset, uint16_t value) {
item[offset] = (uint8_t) value;
item[offset + 1] = (uint8_t)(value >> 8);
}
static inline void u32_to_u8array ( uint8_t* item, int offset, uint32_t value )
{
item[offset] = ( uint8_t ) value;
item[offset + 1] = ( uint8_t )( value >> 8 );
item[offset + 2] = ( uint8_t )( value >> 16 );
item[offset + 3] = ( uint8_t )( value >> 24 );
static inline void u32_to_u8array (uint8_t* item, int offset, uint32_t value) {
item[offset] = (uint8_t) value;
item[offset + 1] = (uint8_t)(value >> 8);
item[offset + 2] = (uint8_t)(value >> 16);
item[offset + 3] = (uint8_t)(value >> 24);
}
#endif // _BIT_OPS_H

View File

@ -53,14 +53,14 @@
*
* Set the bit @bit in the @bitmap to @new_value. Ignore all errors.
*/
void ntfs_bit_set( u8 *bitmap, const u64 bit, const u8 new_value )
void ntfs_bit_set(u8 *bitmap, const u64 bit, const u8 new_value)
{
if ( !bitmap || new_value > 1 )
if (!bitmap || new_value > 1)
return;
if ( !new_value )
bitmap[bit >> 3] &= ~( 1 << ( bit & 7 ) );
if (!new_value)
bitmap[bit >> 3] &= ~(1 << (bit & 7));
else
bitmap[bit >> 3] |= ( 1 << ( bit & 7 ) );
bitmap[bit >> 3] |= (1 << (bit & 7));
}
/**
@ -71,11 +71,11 @@ void ntfs_bit_set( u8 *bitmap, const u64 bit, const u8 new_value )
* Get and return the value of the bit @bit in @bitmap (0 or 1).
* Return -1 on error.
*/
char ntfs_bit_get( const u8 *bitmap, const u64 bit )
char ntfs_bit_get(const u8 *bitmap, const u64 bit)
{
if ( !bitmap )
if (!bitmap)
return -1;
return ( bitmap[bit >> 3] >> ( bit & 7 ) ) & 1;
return (bitmap[bit >> 3] >> (bit & 7)) & 1;
}
/**
@ -87,15 +87,15 @@ char ntfs_bit_get( const u8 *bitmap, const u64 bit )
* Return the value of the bit @bit and set it to @new_value (0 or 1).
* Return -1 on error.
*/
char ntfs_bit_get_and_set( u8 *bitmap, const u64 bit, const u8 new_value )
char ntfs_bit_get_and_set(u8 *bitmap, const u64 bit, const u8 new_value)
{
register u8 old_bit, shift;
if ( !bitmap || new_value > 1 )
if (!bitmap || new_value > 1)
return -1;
shift = bit & 7;
old_bit = ( bitmap[bit >> 3] >> shift ) & 1;
if ( new_value != old_bit )
old_bit = (bitmap[bit >> 3] >> shift) & 1;
if (new_value != old_bit)
bitmap[bit >> 3] ^= 1 << shift;
return old_bit;
}
@ -112,105 +112,95 @@ char ntfs_bit_get_and_set( u8 *bitmap, const u64 bit, const u8 new_value )
*
* On success return 0 and on error return -1 with errno set to the error code.
*/
static int ntfs_bitmap_set_bits_in_run( ntfs_attr *na, s64 start_bit,
s64 count, int value )
static int ntfs_bitmap_set_bits_in_run(ntfs_attr *na, s64 start_bit,
s64 count, int value)
{
s64 bufsize, br;
u8 *buf, *lastbyte_buf;
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;
ntfs_log_perror( "%s: Invalid argument (%p, %lld, %lld)",
__FUNCTION__, na, ( long long )start_bit, ( long long )count );
ntfs_log_perror("%s: Invalid argument (%p, %lld, %lld)",
__FUNCTION__, na, (long long)start_bit, (long long)count);
return -1;
}
bit = start_bit & 7;
if ( bit )
if (bit)
firstbyte = 1;
else
firstbyte = 0;
/* Calculate the required buffer size in bytes, capping it at 8kiB. */
bufsize = ( ( count - ( bit ? 8 - bit : 0 ) + 7 ) >> 3 ) + firstbyte;
if ( bufsize > 8192 )
bufsize = ((count - (bit ? 8 - bit : 0) + 7) >> 3) + firstbyte;
if (bufsize > 8192)
bufsize = 8192;
buf = ntfs_malloc( bufsize );
if ( !buf )
buf = ntfs_malloc(bufsize);
if (!buf)
return -1;
/* Depending on @value, zero or set all bits in the allocated buffer. */
memset( buf, value ? 0xff : 0, bufsize );
memset(buf, value ? 0xff : 0, bufsize);
/* If there is a first partial byte... */
if ( bit )
{
if (bit) {
/* read it in... */
br = ntfs_attr_pread( na, start_bit >> 3, 1, buf );
if ( br != 1 )
{
if ( br >= 0 )
br = ntfs_attr_pread(na, start_bit >> 3, 1, buf);
if (br != 1) {
if (br >= 0)
errno = EIO;
goto free_err_out;
}
/* and set or clear the appropriate bits in it. */
while ( ( bit & 7 ) && count-- )
{
if ( value )
while ((bit & 7) && count--) {
if (value)
*buf |= 1 << bit++;
else
*buf &= ~( 1 << bit++ );
*buf &= ~(1 << bit++);
}
/* Update @start_bit to the new position. */
start_bit = ( start_bit + 7 ) & ~7;
start_bit = (start_bit + 7) & ~7;
}
/* Loop until @count reaches zero. */
lastbyte = 0;
lastbyte_buf = NULL;
bit = count & 7;
do
{
do {
/* If there is a last partial byte... */
if ( count > 0 && bit )
{
lastbyte_pos = ( ( count + 7 ) >> 3 ) + firstbyte;
if ( !lastbyte_pos )
{
if (count > 0 && bit) {
lastbyte_pos = ((count + 7) >> 3) + firstbyte;
if (!lastbyte_pos) {
// FIXME: Eeek! BUG!
ntfs_log_error( "Lastbyte is zero. Leaving "
"inconsistent metadata.\n" );
ntfs_log_error("Lastbyte is zero. Leaving "
"inconsistent metadata.\n");
errno = EIO;
goto free_err_out;
}
/* and it is in the currently loaded bitmap window... */
if ( lastbyte_pos <= bufsize )
{
if (lastbyte_pos <= bufsize) {
lastbyte_buf = buf + lastbyte_pos - 1;
/* read the byte in... */
br = ntfs_attr_pread( na, ( start_bit + count ) >>
3, 1, lastbyte_buf );
if ( br != 1 )
{
br = ntfs_attr_pread(na, (start_bit + count) >>
3, 1, lastbyte_buf);
if (br != 1) {
// FIXME: Eeek! We need rollback! (AIA)
if ( br >= 0 )
if (br >= 0)
errno = EIO;
ntfs_log_perror( "Reading of last byte "
ntfs_log_perror("Reading of last byte "
"failed (%lld). Leaving inconsistent "
"metadata", ( long long )br );
"metadata", (long long)br);
goto free_err_out;
}
/* and set/clear the appropriate bits in it. */
while ( bit && count-- )
{
if ( value )
while (bit && count--) {
if (value)
*lastbyte_buf |= 1 << --bit;
else
*lastbyte_buf &= ~( 1 << --bit );
*lastbyte_buf &= ~(1 << --bit);
}
/* We don't want to come back here... */
bit = 0;
@ -220,23 +210,21 @@ static int ntfs_bitmap_set_bits_in_run( ntfs_attr *na, s64 start_bit,
}
/* Write the prepared buffer to disk. */
tmp = ( start_bit >> 3 ) - firstbyte;
br = ntfs_attr_pwrite( na, tmp, bufsize, buf );
if ( br != bufsize )
{
tmp = (start_bit >> 3) - firstbyte;
br = ntfs_attr_pwrite(na, tmp, bufsize, buf);
if (br != bufsize) {
// FIXME: Eeek! We need rollback! (AIA)
if ( br >= 0 )
if (br >= 0)
errno = EIO;
ntfs_log_perror( "Failed to write buffer to bitmap "
ntfs_log_perror("Failed to write buffer to bitmap "
"(%lld != %lld). Leaving inconsistent metadata",
( long long )br, ( long long )bufsize );
(long long)br, (long long)bufsize);
goto free_err_out;
}
/* Update counters. */
tmp = ( bufsize - firstbyte - lastbyte ) << 3;
if ( firstbyte )
{
tmp = (bufsize - firstbyte - lastbyte) << 3;
if (firstbyte) {
firstbyte = 0;
/*
* Re-set the partial first byte so a subsequent write
@ -246,25 +234,23 @@ static int ntfs_bitmap_set_bits_in_run( ntfs_attr *na, s64 start_bit,
}
start_bit += tmp;
count -= tmp;
if ( bufsize > ( tmp = ( count + 7 ) >> 3 ) )
if (bufsize > (tmp = (count + 7) >> 3))
bufsize = tmp;
if ( lastbyte && count != 0 )
{
if (lastbyte && count != 0) {
// 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",
( long long )count );
(long long)count);
errno = EIO;
goto free_err_out;
}
}
while ( count > 0 );
} while (count > 0);
ret = 0;
free_err_out:
free( buf );
free(buf);
return ret;
}
@ -279,14 +265,14 @@ free_err_out:
*
* On success return 0 and on error return -1 with errno set to the error code.
*/
int ntfs_bitmap_set_run( ntfs_attr *na, s64 start_bit, s64 count )
int ntfs_bitmap_set_run(ntfs_attr *na, s64 start_bit, s64 count)
{
int ret;
ntfs_log_enter( "Set from bit %lld, count %lld\n",
( long long )start_bit, ( long long )count );
ret = ntfs_bitmap_set_bits_in_run( na, start_bit, count, 1 );
ntfs_log_leave( "\n" );
ntfs_log_enter("Set from bit %lld, count %lld\n",
(long long)start_bit, (long long)count);
ret = ntfs_bitmap_set_bits_in_run(na, start_bit, count, 1);
ntfs_log_leave("\n");
return ret;
}
@ -301,14 +287,14 @@ int ntfs_bitmap_set_run( ntfs_attr *na, s64 start_bit, s64 count )
*
* On success return 0 and on error return -1 with errno set to the error code.
*/
int ntfs_bitmap_clear_run( ntfs_attr *na, s64 start_bit, s64 count )
int ntfs_bitmap_clear_run(ntfs_attr *na, s64 start_bit, s64 count)
{
int ret;
ntfs_log_enter( "Clear from bit %lld, count %lld\n",
( long long )start_bit, ( long long )count );
ret = ntfs_bitmap_set_bits_in_run( na, start_bit, count, 0 );
ntfs_log_leave( "\n" );
ntfs_log_enter("Clear from bit %lld, count %lld\n",
(long long)start_bit, (long long)count);
ret = ntfs_bitmap_set_bits_in_run(na, start_bit, count, 0);
ntfs_log_leave("\n");
return ret;
}

View File

@ -36,11 +36,11 @@
* size of the bitmap.
*/
extern void ntfs_bit_set( u8 *bitmap, const u64 bit, const u8 new_value );
extern char ntfs_bit_get( const u8 *bitmap, const u64 bit );
extern char ntfs_bit_get_and_set( u8 *bitmap, const u64 bit, const u8 new_value );
extern int ntfs_bitmap_set_run( ntfs_attr *na, s64 start_bit, s64 count );
extern int ntfs_bitmap_clear_run( ntfs_attr *na, s64 start_bit, s64 count );
extern void ntfs_bit_set(u8 *bitmap, const u64 bit, const u8 new_value);
extern char ntfs_bit_get(const u8 *bitmap, const u64 bit);
extern char ntfs_bit_get_and_set(u8 *bitmap, const u64 bit, const u8 new_value);
extern int ntfs_bitmap_set_run(ntfs_attr *na, s64 start_bit, s64 count);
extern int ntfs_bitmap_clear_run(ntfs_attr *na, s64 start_bit, s64 count);
/**
* ntfs_bitmap_set_bit - set a bit in a bitmap
@ -51,9 +51,9 @@ extern int ntfs_bitmap_clear_run( ntfs_attr *na, s64 start_bit, s64 count );
*
* On success return 0 and on error return -1 with errno set to the error code.
*/
static __inline__ int ntfs_bitmap_set_bit( ntfs_attr *na, s64 bit )
static __inline__ int ntfs_bitmap_set_bit(ntfs_attr *na, s64 bit)
{
return ntfs_bitmap_set_run( na, bit, 1 );
return ntfs_bitmap_set_run(na, bit, 1);
}
/**
@ -65,9 +65,9 @@ static __inline__ int ntfs_bitmap_set_bit( ntfs_attr *na, s64 bit )
*
* On success return 0 and on error return -1 with errno set to the error code.
*/
static __inline__ int ntfs_bitmap_clear_bit( ntfs_attr *na, s64 bit )
static __inline__ int ntfs_bitmap_clear_bit(ntfs_attr *na, s64 bit)
{
return ntfs_bitmap_clear_run( na, bit, 1 );
return ntfs_bitmap_clear_run(na, bit, 1);
}
/*
@ -76,9 +76,9 @@ static __inline__ int ntfs_bitmap_clear_bit( ntfs_attr *na, s64 bit )
* @word: value to rotate
* @shift: bits to roll
*/
static __inline__ u32 ntfs_rol32( u32 word, unsigned int shift )
static __inline__ u32 ntfs_rol32(u32 word, unsigned int shift)
{
return ( word << shift ) | ( word >> ( 32 - shift ) );
return (word << shift) | (word >> (32 - shift));
}
/*
@ -87,9 +87,9 @@ static __inline__ u32 ntfs_rol32( u32 word, unsigned int shift )
* @word: value to rotate
* @shift: bits to roll
*/
static __inline__ u32 ntfs_ror32( u32 word, unsigned int shift )
static __inline__ u32 ntfs_ror32(u32 word, unsigned int shift)
{
return ( word >> shift ) | ( word << ( 32 - shift ) );
return (word >> shift) | (word << (32 - shift));
}
#endif /* defined _NTFS_BITMAP_H */

View File

@ -57,103 +57,94 @@
*
* Return TRUE if @b contains a valid ntfs boot sector and FALSE if not.
*/
BOOL ntfs_boot_sector_is_ntfs( NTFS_BOOT_SECTOR *b )
BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b)
{
u32 i;
BOOL ret = FALSE;
ntfs_log_debug( "Beginning bootsector check.\n" );
ntfs_log_debug("Beginning bootsector check.\n");
ntfs_log_debug( "Checking OEMid, NTFS signature.\n" );
if ( b->oem_id != cpu_to_le64( 0x202020205346544eULL ) ) /* "NTFS " */
{
ntfs_log_error( "NTFS signature is missing.\n" );
ntfs_log_debug("Checking OEMid, NTFS signature.\n");
if (b->oem_id != cpu_to_le64(0x202020205346544eULL)) { /* "NTFS " */
ntfs_log_error("NTFS signature is missing.\n");
goto not_ntfs;
}
ntfs_log_debug( "Checking bytes per sector.\n" );
if ( le16_to_cpu( b->bpb.bytes_per_sector ) < 256 ||
le16_to_cpu( b->bpb.bytes_per_sector ) > 4096 )
{
ntfs_log_error( "Unexpected bytes per sector value (%d).\n",
le16_to_cpu( b->bpb.bytes_per_sector ) );
ntfs_log_debug("Checking bytes per sector.\n");
if (le16_to_cpu(b->bpb.bytes_per_sector) < 256 ||
le16_to_cpu(b->bpb.bytes_per_sector) > 4096) {
ntfs_log_error("Unexpected bytes per sector value (%d).\n",
le16_to_cpu(b->bpb.bytes_per_sector));
goto not_ntfs;
}
ntfs_log_debug( "Checking sectors per cluster.\n" );
switch ( b->bpb.sectors_per_cluster )
{
ntfs_log_debug("Checking sectors per cluster.\n");
switch (b->bpb.sectors_per_cluster) {
case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128:
break;
default:
ntfs_log_error( "Unexpected sectors per cluster value (%d).\n",
b->bpb.sectors_per_cluster );
ntfs_log_error("Unexpected sectors per cluster value (%d).\n",
b->bpb.sectors_per_cluster);
goto not_ntfs;
}
ntfs_log_debug( "Checking cluster size.\n" );
i = ( u32 )le16_to_cpu( b->bpb.bytes_per_sector ) *
ntfs_log_debug("Checking cluster size.\n");
i = (u32)le16_to_cpu(b->bpb.bytes_per_sector) *
b->bpb.sectors_per_cluster;
if ( i > 65536 )
{
ntfs_log_error( "Unexpected cluster size (%d).\n", i );
if (i > 65536) {
ntfs_log_error("Unexpected cluster size (%d).\n", i);
goto not_ntfs;
}
ntfs_log_debug( "Checking reserved fields are zero.\n" );
if ( le16_to_cpu( b->bpb.reserved_sectors ) ||
le16_to_cpu( b->bpb.root_entries ) ||
le16_to_cpu( b->bpb.sectors ) ||
le16_to_cpu( b->bpb.sectors_per_fat ) ||
le32_to_cpu( b->bpb.large_sectors ) ||
b->bpb.fats )
{
ntfs_log_error( "Reserved fields aren't zero "
ntfs_log_debug("Checking reserved fields are zero.\n");
if (le16_to_cpu(b->bpb.reserved_sectors) ||
le16_to_cpu(b->bpb.root_entries) ||
le16_to_cpu(b->bpb.sectors) ||
le16_to_cpu(b->bpb.sectors_per_fat) ||
le32_to_cpu(b->bpb.large_sectors) ||
b->bpb.fats) {
ntfs_log_error("Reserved fields aren't zero "
"(%d, %d, %d, %d, %d, %d).\n",
le16_to_cpu( b->bpb.reserved_sectors ),
le16_to_cpu( b->bpb.root_entries ),
le16_to_cpu( b->bpb.sectors ),
le16_to_cpu( b->bpb.sectors_per_fat ),
le32_to_cpu( b->bpb.large_sectors ),
b->bpb.fats );
le16_to_cpu(b->bpb.reserved_sectors),
le16_to_cpu(b->bpb.root_entries),
le16_to_cpu(b->bpb.sectors),
le16_to_cpu(b->bpb.sectors_per_fat),
le32_to_cpu(b->bpb.large_sectors),
b->bpb.fats);
goto not_ntfs;
}
ntfs_log_debug( "Checking clusters per mft record.\n" );
if ( ( u8 )b->clusters_per_mft_record < 0xe1 ||
( u8 )b->clusters_per_mft_record > 0xf7 )
{
switch ( b->clusters_per_mft_record )
{
ntfs_log_debug("Checking clusters per mft record.\n");
if ((u8)b->clusters_per_mft_record < 0xe1 ||
(u8)b->clusters_per_mft_record > 0xf7) {
switch (b->clusters_per_mft_record) {
case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40:
break;
default:
ntfs_log_error( "Unexpected clusters per mft record "
"(%d).\n", b->clusters_per_mft_record );
ntfs_log_error("Unexpected clusters per mft record "
"(%d).\n", b->clusters_per_mft_record);
goto not_ntfs;
}
}
ntfs_log_debug( "Checking clusters per index block.\n" );
if ( ( u8 )b->clusters_per_index_record < 0xe1 ||
( u8 )b->clusters_per_index_record > 0xf7 )
{
switch ( b->clusters_per_index_record )
{
ntfs_log_debug("Checking clusters per index block.\n");
if ((u8)b->clusters_per_index_record < 0xe1 ||
(u8)b->clusters_per_index_record > 0xf7) {
switch (b->clusters_per_index_record) {
case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40:
break;
default:
ntfs_log_error( "Unexpected clusters per index record "
"(%d).\n", b->clusters_per_index_record );
ntfs_log_error("Unexpected clusters per index record "
"(%d).\n", b->clusters_per_index_record);
goto not_ntfs;
}
}
if ( b->end_of_sector_marker != cpu_to_le16( 0xaa55 ) )
ntfs_log_debug( "Warning: Bootsector has invalid end of sector "
"marker.\n" );
if (b->end_of_sector_marker != cpu_to_le16(0xaa55))
ntfs_log_debug("Warning: Bootsector has invalid end of sector "
"marker.\n");
ntfs_log_debug( "Bootsector check completed successfully.\n" );
ntfs_log_debug("Bootsector check completed successfully.\n");
ret = TRUE;
not_ntfs:
@ -161,11 +152,11 @@ not_ntfs:
}
static const char *last_sector_error =
"HINTS: Either the volume is a RAID/LDM but it wasn't setup yet,\n"
" or it was not setup correctly (e.g. by not using mdadm --build ...),\n"
" or a wrong device is tried to be mounted,\n"
" or the partition table is corrupt (partition is smaller than NTFS),\n"
" or the NTFS boot sector is corrupt (NTFS size is not valid).\n";
"HINTS: Either the volume is a RAID/LDM but it wasn't setup yet,\n"
" or it was not setup correctly (e.g. by not using mdadm --build ...),\n"
" or a wrong device is tried to be mounted,\n"
" or the partition table is corrupt (partition is smaller than NTFS),\n"
" or the NTFS boot sector is corrupt (NTFS size is not valid).\n";
/**
* ntfs_boot_sector_parse - setup an ntfs volume from an ntfs boot sector
@ -177,7 +168,7 @@ static const char *last_sector_error =
*
* Return 0 on success or -1 on error with errno set to the error code EINVAL.
*/
int ntfs_boot_sector_parse( ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs )
int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
{
s64 sectors;
u8 sectors_per_cluster;
@ -186,103 +177,97 @@ int ntfs_boot_sector_parse( ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs )
/* We return -1 with errno = EINVAL on error. */
errno = EINVAL;
vol->sector_size = le16_to_cpu( bs->bpb.bytes_per_sector );
vol->sector_size_bits = ffs( vol->sector_size ) - 1;
ntfs_log_debug( "SectorSize = 0x%x\n", vol->sector_size );
ntfs_log_debug( "SectorSizeBits = %u\n", vol->sector_size_bits );
vol->sector_size = le16_to_cpu(bs->bpb.bytes_per_sector);
vol->sector_size_bits = ffs(vol->sector_size) - 1;
ntfs_log_debug("SectorSize = 0x%x\n", vol->sector_size);
ntfs_log_debug("SectorSizeBits = %u\n", vol->sector_size_bits);
/*
* The bounds checks on mft_lcn and mft_mirr_lcn (i.e. them being
* below or equal the number_of_clusters) really belong in the
* ntfs_boot_sector_is_ntfs but in this way we can just do this once.
*/
sectors_per_cluster = bs->bpb.sectors_per_cluster;
ntfs_log_debug( "SectorsPerCluster = 0x%x\n", sectors_per_cluster );
if ( sectors_per_cluster & ( sectors_per_cluster - 1 ) )
{
ntfs_log_error( "sectors_per_cluster (%d) is not a power of 2."
"\n", sectors_per_cluster );
ntfs_log_debug("SectorsPerCluster = 0x%x\n", sectors_per_cluster);
if (sectors_per_cluster & (sectors_per_cluster - 1)) {
ntfs_log_error("sectors_per_cluster (%d) is not a power of 2."
"\n", sectors_per_cluster);
return -1;
}
sectors = sle64_to_cpu( bs->number_of_sectors );
ntfs_log_debug( "NumberOfSectors = %lld\n", ( long long )sectors );
if ( !sectors )
{
ntfs_log_error( "Volume size is set to zero.\n" );
sectors = sle64_to_cpu(bs->number_of_sectors);
ntfs_log_debug("NumberOfSectors = %lld\n", (long long)sectors);
if (!sectors) {
ntfs_log_error("Volume size is set to zero.\n");
return -1;
}
if ( vol->dev->d_ops->seek( vol->dev,
( sectors - 1 ) << vol->sector_size_bits,
SEEK_SET ) == -1 )
{
ntfs_log_perror( "Failed to read last sector (%lld)",
( long long )sectors );
ntfs_log_error( "%s", last_sector_error );
if (vol->dev->d_ops->seek(vol->dev,
(sectors - 1) << vol->sector_size_bits,
SEEK_SET) == -1) {
ntfs_log_perror("Failed to read last sector (%lld)",
(long long)sectors);
ntfs_log_error("%s", last_sector_error);
return -1;
}
vol->nr_clusters = sectors >> ( ffs( sectors_per_cluster ) - 1 );
vol->nr_clusters = sectors >> (ffs(sectors_per_cluster) - 1);
vol->mft_lcn = sle64_to_cpu( bs->mft_lcn );
vol->mftmirr_lcn = sle64_to_cpu( bs->mftmirr_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 );
if ( vol->mft_lcn > vol->nr_clusters ||
vol->mftmirr_lcn > vol->nr_clusters )
{
ntfs_log_error( "$MFT LCN (%lld) or $MFTMirr LCN (%lld) is "
vol->mft_lcn = sle64_to_cpu(bs->mft_lcn);
vol->mftmirr_lcn = sle64_to_cpu(bs->mftmirr_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);
if (vol->mft_lcn > vol->nr_clusters ||
vol->mftmirr_lcn > vol->nr_clusters) {
ntfs_log_error("$MFT LCN (%lld) or $MFTMirr LCN (%lld) is "
"greater than the number of clusters (%lld).\n",
( long long )vol->mft_lcn, ( long long )vol->mftmirr_lcn,
( long long )vol->nr_clusters );
(long long)vol->mft_lcn, (long long)vol->mftmirr_lcn,
(long long)vol->nr_clusters);
return -1;
}
vol->cluster_size = sectors_per_cluster * vol->sector_size;
if ( vol->cluster_size & ( vol->cluster_size - 1 ) )
{
ntfs_log_error( "cluster_size (%d) is not a power of 2.\n",
vol->cluster_size );
if (vol->cluster_size & (vol->cluster_size - 1)) {
ntfs_log_error("cluster_size (%d) is not a power of 2.\n",
vol->cluster_size);
return -1;
}
vol->cluster_size_bits = ffs( vol->cluster_size ) - 1;
vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
/*
* Need to get the clusters per mft record and handle it if it is
* negative. Then calculate the mft_record_size. A value of 0x80 is
* illegal, thus signed char is actually ok!
*/
c = bs->clusters_per_mft_record;
ntfs_log_debug( "ClusterSize = 0x%x\n", ( unsigned )vol->cluster_size );
ntfs_log_debug( "ClusterSizeBits = %u\n", vol->cluster_size_bits );
ntfs_log_debug( "ClustersPerMftRecord = 0x%x\n", c );
ntfs_log_debug("ClusterSize = 0x%x\n", (unsigned)vol->cluster_size);
ntfs_log_debug("ClusterSizeBits = %u\n", vol->cluster_size_bits);
ntfs_log_debug("ClustersPerMftRecord = 0x%x\n", c);
/*
* When clusters_per_mft_record is negative, it means that it is to
* be taken to be the negative base 2 logarithm of the mft_record_size
* min bytes. Then:
* mft_record_size = 2^(-clusters_per_mft_record) bytes.
*/
if ( c < 0 )
if (c < 0)
vol->mft_record_size = 1 << -c;
else
vol->mft_record_size = c << vol->cluster_size_bits;
if ( vol->mft_record_size & ( vol->mft_record_size - 1 ) )
{
ntfs_log_error( "mft_record_size (%d) is not a power of 2.\n",
vol->mft_record_size );
if (vol->mft_record_size & (vol->mft_record_size - 1)) {
ntfs_log_error("mft_record_size (%d) is not a power of 2.\n",
vol->mft_record_size);
return -1;
}
vol->mft_record_size_bits = ffs( vol->mft_record_size ) - 1;
ntfs_log_debug( "MftRecordSize = 0x%x\n", ( unsigned )vol->mft_record_size );
ntfs_log_debug( "MftRecordSizeBits = %u\n", vol->mft_record_size_bits );
vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1;
ntfs_log_debug("MftRecordSize = 0x%x\n", (unsigned)vol->mft_record_size);
ntfs_log_debug("MftRecordSizeBits = %u\n", vol->mft_record_size_bits);
/* Same as above for INDX record. */
c = bs->clusters_per_index_record;
ntfs_log_debug( "ClustersPerINDXRecord = 0x%x\n", c );
if ( c < 0 )
ntfs_log_debug("ClustersPerINDXRecord = 0x%x\n", c);
if (c < 0)
vol->indx_record_size = 1 << -c;
else
vol->indx_record_size = c << vol->cluster_size_bits;
vol->indx_record_size_bits = ffs( vol->indx_record_size ) - 1;
ntfs_log_debug( "INDXRecordSize = 0x%x\n", ( unsigned )vol->indx_record_size );
ntfs_log_debug( "INDXRecordSizeBits = %u\n", vol->indx_record_size_bits );
vol->indx_record_size_bits = ffs(vol->indx_record_size) - 1;
ntfs_log_debug("INDXRecordSize = 0x%x\n", (unsigned)vol->indx_record_size);
ntfs_log_debug("INDXRecordSizeBits = %u\n", vol->indx_record_size_bits);
/*
* Work out the size of the MFT mirror in number of mft records. If the
* cluster size is less than or equal to the size taken by four mft
@ -291,7 +276,7 @@ int ntfs_boot_sector_parse( ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs )
* mft mirror contains as many mft records as will fit into one
* cluster.
*/
if ( vol->cluster_size <= 4 * vol->mft_record_size )
if (vol->cluster_size <= 4 * vol->mft_record_size)
vol->mftmirr_size = 4;
else
vol->mftmirr_size = vol->cluster_size / vol->mft_record_size;

View File

@ -35,8 +35,8 @@
* This function checks the boot sector in @b for describing a valid ntfs
* volume. Return TRUE if @b is a valid NTFS boot sector or FALSE otherwise.
*/
extern BOOL ntfs_boot_sector_is_ntfs( NTFS_BOOT_SECTOR *b );
extern int ntfs_boot_sector_parse( ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs );
extern BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b);
extern int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs);
#endif /* defined _NTFS_BOOTSECT_H */

View File

@ -60,45 +60,38 @@
* Do not call when a record has been modified (with no key change)
*/
static void inserthashindex( struct CACHE_HEADER *cache,
struct CACHED_GENERIC *current )
static void inserthashindex(struct CACHE_HEADER *cache,
struct CACHED_GENERIC *current)
{
int h;
struct HASH_ENTRY *link;
struct HASH_ENTRY *first;
if ( cache->dohash )
{
h = cache->dohash( current );
if ( ( h >= 0 ) && ( h < cache->max_hash ) )
{
if (cache->dohash) {
h = cache->dohash(current);
if ((h >= 0) && (h < cache->max_hash)) {
/* get a free link and insert at top of hash list */
link = cache->free_hash;
if ( link )
{
if (link) {
cache->free_hash = link->next;
first = cache->first_hash[h];
if ( first )
if (first)
link->next = first;
else
link->next = NULL;
link->entry = current;
cache->first_hash[h] = link;
}
else
{
ntfs_log_error( "No more hash entries,"
} else {
ntfs_log_error("No more hash entries,"
" cache %s hashing dropped\n",
cache->name );
cache->dohash = ( cache_hash )NULL;
cache->name);
cache->dohash = (cache_hash)NULL;
}
}
else
{
ntfs_log_error( "Illegal hash value,"
} else {
ntfs_log_error("Illegal hash value,"
" cache %s hashing dropped\n",
cache->name );
cache->dohash = ( cache_hash )NULL;
cache->name);
cache->dohash = (cache_hash)NULL;
}
}
}
@ -107,47 +100,39 @@ static void inserthashindex( struct CACHE_HEADER *cache,
* Drop a hash index when a record is about to be deleted
*/
static void drophashindex( struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *current, int hash )
static void drophashindex(struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *current, int hash)
{
struct HASH_ENTRY *link;
struct HASH_ENTRY *previous;
if ( cache->dohash )
{
if ( ( hash >= 0 ) && ( hash < cache->max_hash ) )
{
if (cache->dohash) {
if ((hash >= 0) && (hash < cache->max_hash)) {
/* find the link and unlink */
link = cache->first_hash[hash];
previous = ( struct HASH_ENTRY* )NULL;
while ( link && ( link->entry != current ) )
{
previous = (struct HASH_ENTRY*)NULL;
while (link && (link->entry != current)) {
previous = link;
link = link->next;
}
if ( link )
{
if ( previous )
if (link) {
if (previous)
previous->next = link->next;
else
cache->first_hash[hash] = link->next;
link->next = cache->free_hash;
cache->free_hash = link;
}
else
{
ntfs_log_error( "Bad hash list,"
} else {
ntfs_log_error("Bad hash list,"
" cache %s hashing dropped\n",
cache->name );
cache->dohash = ( cache_hash )NULL;
cache->name);
cache->dohash = (cache_hash)NULL;
}
}
else
{
ntfs_log_error( "Illegal hash value,"
} else {
ntfs_log_error("Illegal hash value,"
" cache %s hashing dropped\n",
cache->name );
cache->dohash = ( cache_hash )NULL;
cache->name);
cache->dohash = (cache_hash)NULL;
}
}
}
@ -159,55 +144,49 @@ static void drophashindex( struct CACHE_HEADER *cache,
* The returned entry may be modified, but not freed
*/
struct CACHED_GENERIC *ntfs_fetch_cache( struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *wanted, cache_compare compare )
struct CACHED_GENERIC *ntfs_fetch_cache(struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *wanted, cache_compare compare)
{
struct CACHED_GENERIC *current;
struct CACHED_GENERIC *previous;
struct HASH_ENTRY *link;
int h;
current = ( struct CACHED_GENERIC* )NULL;
if ( cache )
{
if ( cache->dohash )
{
current = (struct CACHED_GENERIC*)NULL;
if (cache) {
if (cache->dohash) {
/*
* When possible, use the hash table to
* locate the entry if present
*/
h = cache->dohash( wanted );
h = cache->dohash(wanted);
link = cache->first_hash[h];
while ( link && compare( link->entry, wanted ) )
while (link && compare(link->entry, wanted))
link = link->next;
if ( link )
if (link)
current = link->entry;
}
if ( !cache->dohash )
{
if (!cache->dohash) {
/*
* Search sequentially in LRU list if no hash table
* or if hashing has just failed
*/
current = cache->most_recent_entry;
while ( current
&& compare( current, wanted ) )
{
while (current
&& compare(current, wanted)) {
current = current->next;
}
}
if ( current )
{
if (current) {
previous = current->previous;
cache->hits++;
if ( previous )
{
if (previous) {
/*
* found and not at head of list, unlink from current
* position and relink as head of list
*/
previous->next = current->next;
if ( current->next )
if (current->next)
current->next->previous
= current->previous;
else
@ -215,14 +194,14 @@ struct CACHED_GENERIC *ntfs_fetch_cache( struct CACHE_HEADER *cache,
= current->previous;
current->next = cache->most_recent_entry;
current->previous
= ( struct CACHED_GENERIC* )NULL;
= (struct CACHED_GENERIC*)NULL;
cache->most_recent_entry->previous = current;
cache->most_recent_entry = current;
}
}
cache->reads++;
}
return ( current );
return (current);
}
/*
@ -230,35 +209,31 @@ struct CACHED_GENERIC *ntfs_fetch_cache( struct CACHE_HEADER *cache,
* returns the cache entry or NULL if not possible
*/
struct CACHED_GENERIC *ntfs_enter_cache( struct CACHE_HEADER *cache,
struct CACHED_GENERIC *ntfs_enter_cache(struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *item,
cache_compare compare )
cache_compare compare)
{
struct CACHED_GENERIC *current;
struct CACHED_GENERIC *before;
struct HASH_ENTRY *link;
int h;
current = ( struct CACHED_GENERIC* )NULL;
if ( cache )
{
if ( cache->dohash )
{
current = (struct CACHED_GENERIC*)NULL;
if (cache) {
if (cache->dohash) {
/*
* When possible, use the hash table to
* find out whether the entry if present
*/
h = cache->dohash( item );
h = cache->dohash(item);
link = cache->first_hash[h];
while ( link && compare( link->entry, item ) )
while (link && compare(link->entry, item))
link = link->next;
if ( link )
{
if (link) {
current = link->entry;
}
}
if ( !cache->dohash )
{
if (!cache->dohash) {
/*
* Search sequentially in LRU list to locate the end,
* and find out whether the entry is already in list
@ -266,15 +241,13 @@ struct CACHED_GENERIC *ntfs_enter_cache( struct CACHE_HEADER *cache,
* kept.
*/
current = cache->most_recent_entry;
while ( current
&& compare( current, item ) )
{
while (current
&& compare(current, item)) {
current = current->next;
}
}
if ( !current )
{
if (!current) {
/*
* Not in list, get a free entry or reuse the
* last entry, and relink as head of list
@ -283,66 +256,54 @@ struct CACHED_GENERIC *ntfs_enter_cache( struct CACHE_HEADER *cache,
* an entry is reused.
*/
if ( cache->free_entry )
{
if (cache->free_entry) {
current = cache->free_entry;
cache->free_entry = cache->free_entry->next;
if ( item->varsize )
{
if (item->varsize) {
current->variable = ntfs_malloc(
item->varsize );
}
else
current->variable = ( void* )NULL;
item->varsize);
} else
current->variable = (void*)NULL;
current->varsize = item->varsize;
if ( !cache->oldest_entry )
if (!cache->oldest_entry)
cache->oldest_entry = current;
}
else
{
} else {
/* reusing the oldest entry */
current = cache->oldest_entry;
before = current->previous;
before->next = ( struct CACHED_GENERIC* )NULL;
if ( cache->dohash )
drophashindex( cache, current,
cache->dohash( current ) );
if ( cache->dofree )
cache->dofree( current );
before->next = (struct CACHED_GENERIC*)NULL;
if (cache->dohash)
drophashindex(cache,current,
cache->dohash(current));
if (cache->dofree)
cache->dofree(current);
cache->oldest_entry = current->previous;
if ( item->varsize )
{
if ( current->varsize )
if (item->varsize) {
if (current->varsize)
current->variable = realloc(
current->variable,
item->varsize );
item->varsize);
else
current->variable = ntfs_malloc(
item->varsize );
}
else
{
if ( current->varsize )
free( current->variable );
current->variable = ( void* )NULL;
item->varsize);
} else {
if (current->varsize)
free(current->variable);
current->variable = (void*)NULL;
}
current->varsize = item->varsize;
}
current->next = cache->most_recent_entry;
current->previous = ( struct CACHED_GENERIC* )NULL;
if ( cache->most_recent_entry )
current->previous = (struct CACHED_GENERIC*)NULL;
if (cache->most_recent_entry)
cache->most_recent_entry->previous = current;
cache->most_recent_entry = current;
memcpy( current->fixed, item->fixed, cache->fixed_size );
if ( item->varsize )
{
if ( current->variable )
{
memcpy( current->variable,
item->variable, item->varsize );
}
else
{
memcpy(current->fixed, item->fixed, cache->fixed_size);
if (item->varsize) {
if (current->variable) {
memcpy(current->variable,
item->variable, item->varsize);
} else {
/*
* no more memory for variable part
* recycle entry in free list
@ -351,20 +312,18 @@ struct CACHED_GENERIC *ntfs_enter_cache( struct CACHE_HEADER *cache,
cache->most_recent_entry = current->next;
current->next = cache->free_entry;
cache->free_entry = current;
current = ( struct CACHED_GENERIC* )NULL;
current = (struct CACHED_GENERIC*)NULL;
}
}
else
{
current->variable = ( void* )NULL;
} else {
current->variable = (void*)NULL;
current->varsize = 0;
}
if ( cache->dohash && current )
inserthashindex( cache, current );
if (cache->dohash && current)
inserthashindex(cache,current);
}
cache->writes++;
}
return ( current );
return (current);
}
/*
@ -373,31 +332,31 @@ struct CACHED_GENERIC *ntfs_enter_cache( struct CACHE_HEADER *cache,
* A specific function may be called for entry deletion
*/
static void do_invalidate( struct CACHE_HEADER *cache,
struct CACHED_GENERIC *current, int flags )
static void do_invalidate(struct CACHE_HEADER *cache,
struct CACHED_GENERIC *current, int flags)
{
struct CACHED_GENERIC *previous;
previous = current->previous;
if ( ( flags & CACHE_FREE ) && cache->dofree )
cache->dofree( current );
if ((flags & CACHE_FREE) && cache->dofree)
cache->dofree(current);
/*
* Relink into free list
*/
if ( current->next )
if (current->next)
current->next->previous = current->previous;
else
cache->oldest_entry = current->previous;
if ( previous )
if (previous)
previous->next = current->next;
else
cache->most_recent_entry = current->next;
current->next = cache->free_entry;
cache->free_entry = current;
if ( current->variable )
free( current->variable );
if (current->variable)
free(current->variable);
current->varsize = 0;
}
}
/*
@ -412,9 +371,9 @@ static void do_invalidate( struct CACHE_HEADER *cache,
* supposed to be found.
*/
int ntfs_invalidate_cache( struct CACHE_HEADER *cache,
int ntfs_invalidate_cache(struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *item, cache_compare compare,
int flags )
int flags)
{
struct CACHED_GENERIC *current;
struct CACHED_GENERIC *previous;
@ -423,100 +382,87 @@ int ntfs_invalidate_cache( struct CACHE_HEADER *cache,
int count;
int h;
current = ( struct CACHED_GENERIC* )NULL;
current = (struct CACHED_GENERIC*)NULL;
count = 0;
if ( cache )
{
if ( !( flags & CACHE_NOHASH ) && cache->dohash )
{
if (cache) {
if (!(flags & CACHE_NOHASH) && cache->dohash) {
/*
* When possible, use the hash table to
* find out whether the entry if present
*/
h = cache->dohash( item );
h = cache->dohash(item);
link = cache->first_hash[h];
while ( link )
{
if ( compare( link->entry, item ) )
while (link) {
if (compare(link->entry, item))
link = link->next;
else
{
else {
current = link->entry;
link = link->next;
if ( current )
{
drophashindex( cache, current, h );
do_invalidate( cache,
current, flags );
if (current) {
drophashindex(cache,current,h);
do_invalidate(cache,
current,flags);
count++;
}
}
}
}
if ( ( flags & CACHE_NOHASH ) || !cache->dohash )
{
if ((flags & CACHE_NOHASH) || !cache->dohash) {
/*
* Search sequentially in LRU list
*/
current = cache->most_recent_entry;
previous = ( struct CACHED_GENERIC* )NULL;
while ( current )
{
if ( !compare( current, item ) )
{
previous = (struct CACHED_GENERIC*)NULL;
while (current) {
if (!compare(current, item)) {
next = current->next;
if ( cache->dohash )
drophashindex( cache, current,
cache->dohash( current ) );
do_invalidate( cache, current, flags );
if (cache->dohash)
drophashindex(cache,current,
cache->dohash(current));
do_invalidate(cache,current,flags);
current = next;
count++;
}
else
{
} else {
previous = current;
current = current->next;
}
}
}
}
return ( count );
return (count);
}
int ntfs_remove_cache( struct CACHE_HEADER *cache,
struct CACHED_GENERIC *item, int flags )
int ntfs_remove_cache(struct CACHE_HEADER *cache,
struct CACHED_GENERIC *item, int flags)
{
int count;
count = 0;
if ( cache )
{
if ( cache->dohash )
drophashindex( cache, item, cache->dohash( item ) );
do_invalidate( cache, item, flags );
if (cache) {
if (cache->dohash)
drophashindex(cache,item,cache->dohash(item));
do_invalidate(cache,item,flags);
count++;
}
return ( count );
return (count);
}
/*
* Free memory allocated to a cache
*/
static void ntfs_free_cache( struct CACHE_HEADER *cache )
static void ntfs_free_cache(struct CACHE_HEADER *cache)
{
struct CACHED_GENERIC *entry;
if ( cache )
{
for ( entry = cache->most_recent_entry; entry; entry = entry->next )
{
if ( cache->dofree )
cache->dofree( entry );
if ( entry->variable )
free( entry->variable );
if (cache) {
for (entry=cache->most_recent_entry; entry; entry=entry->next) {
if (cache->dofree)
cache->dofree(entry);
if (entry->variable)
free(entry->variable);
}
free( cache );
free(cache);
}
}
@ -526,10 +472,10 @@ static void ntfs_free_cache( struct CACHE_HEADER *cache )
* Returns the cache header, or NULL if the cache could not be created
*/
static struct CACHE_HEADER *ntfs_create_cache( const char *name,
static struct CACHE_HEADER *ntfs_create_cache(const char *name,
cache_free dofree, cache_hash dohash,
int full_item_size,
int item_count, int max_hash )
int item_count, int max_hash)
{
struct CACHE_HEADER *cache;
struct CACHED_GENERIC *pc;
@ -540,78 +486,68 @@ static struct CACHE_HEADER *ntfs_create_cache( const char *name,
size_t size;
int i;
size = sizeof( struct CACHE_HEADER ) + item_count*full_item_size;
if ( max_hash )
size += item_count*sizeof( struct HASH_ENTRY )
+ max_hash*sizeof( struct HASH_ENTRY* );
cache = ( struct CACHE_HEADER* )ntfs_malloc( size );
if ( cache )
{
size = sizeof(struct CACHE_HEADER) + item_count*full_item_size;
if (max_hash)
size += item_count*sizeof(struct HASH_ENTRY)
+ max_hash*sizeof(struct HASH_ENTRY*);
cache = (struct CACHE_HEADER*)ntfs_malloc(size);
if (cache) {
/* header */
cache->name = name;
cache->dofree = dofree;
if ( dohash && max_hash )
{
if (dohash && max_hash) {
cache->dohash = dohash;
cache->max_hash = max_hash;
}
else
{
cache->dohash = ( cache_hash )NULL;
} else {
cache->dohash = (cache_hash)NULL;
cache->max_hash = 0;
}
cache->fixed_size = full_item_size - sizeof( struct CACHED_GENERIC );
cache->fixed_size = full_item_size - sizeof(struct CACHED_GENERIC);
cache->reads = 0;
cache->writes = 0;
cache->hits = 0;
/* chain the data entries, and mark an invalid entry */
cache->most_recent_entry = ( struct CACHED_GENERIC* )NULL;
cache->oldest_entry = ( struct CACHED_GENERIC* )NULL;
cache->most_recent_entry = (struct CACHED_GENERIC*)NULL;
cache->oldest_entry = (struct CACHED_GENERIC*)NULL;
cache->free_entry = &cache->entry[0];
pc = &cache->entry[0];
for ( i = 0; i < ( item_count - 1 ); i++ )
{
qc = ( struct CACHED_GENERIC* )( ( char* )pc
+ full_item_size );
for (i=0; i<(item_count - 1); i++) {
qc = (struct CACHED_GENERIC*)((char*)pc
+ full_item_size);
pc->next = qc;
pc->variable = ( void* )NULL;
pc->variable = (void*)NULL;
pc->varsize = 0;
pc = qc;
}
/* special for the last entry */
pc->next = ( struct CACHED_GENERIC* )NULL;
pc->variable = ( void* )NULL;
pc->next = (struct CACHED_GENERIC*)NULL;
pc->variable = (void*)NULL;
pc->varsize = 0;
if ( max_hash )
{
if (max_hash) {
/* 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;
for ( i = 0; i < ( item_count - 1 ); i++ )
{
for (i=0; i<(item_count - 1); i++) {
qh = &ph[1];
ph->next = qh;
ph = qh;
}
/* special for the last entry */
if ( item_count )
{
ph->next = ( struct HASH_ENTRY* )NULL;
if (item_count) {
ph->next = (struct HASH_ENTRY*)NULL;
}
/* create and initialize the hash indexes */
px = ( struct HASH_ENTRY** ) & ph[1];
px = (struct HASH_ENTRY**)&ph[1];
cache->first_hash = px;
for ( i = 0; i < max_hash; i++ )
px[i] = ( struct HASH_ENTRY* )NULL;
}
else
{
cache->free_hash = ( struct HASH_ENTRY* )NULL;
cache->first_hash = ( struct HASH_ENTRY** )NULL;
for (i=0; i<max_hash; i++)
px[i] = (struct HASH_ENTRY*)NULL;
} else {
cache->free_hash = (struct HASH_ENTRY*)NULL;
cache->first_hash = (struct HASH_ENTRY**)NULL;
}
}
return ( cache );
return (cache);
}
/*
@ -621,33 +557,33 @@ static struct CACHE_HEADER *ntfs_create_cache( const char *name,
* just be not available
*/
void ntfs_create_lru_caches( ntfs_volume *vol )
void ntfs_create_lru_caches(ntfs_volume *vol)
{
#if CACHE_INODE_SIZE
/* inode cache */
vol->xinode_cache = ntfs_create_cache( "inode", ( cache_free )NULL,
ntfs_dir_inode_hash, sizeof( struct CACHED_INODE ),
CACHE_INODE_SIZE, 2 * CACHE_INODE_SIZE );
vol->xinode_cache = ntfs_create_cache("inode",(cache_free)NULL,
ntfs_dir_inode_hash, sizeof(struct CACHED_INODE),
CACHE_INODE_SIZE, 2*CACHE_INODE_SIZE);
#endif
#if CACHE_NIDATA_SIZE
/* idata cache */
vol->nidata_cache = ntfs_create_cache( "nidata",
vol->nidata_cache = ntfs_create_cache("nidata",
ntfs_inode_nidata_free, ntfs_inode_nidata_hash,
sizeof( struct CACHED_NIDATA ),
CACHE_NIDATA_SIZE, 2 * CACHE_NIDATA_SIZE );
sizeof(struct CACHED_NIDATA),
CACHE_NIDATA_SIZE, 2*CACHE_NIDATA_SIZE);
#endif
#if CACHE_LOOKUP_SIZE
/* lookup cache */
vol->lookup_cache = ntfs_create_cache( "lookup",
( cache_free )NULL, ntfs_dir_lookup_hash,
sizeof( struct CACHED_LOOKUP ),
CACHE_LOOKUP_SIZE, 2 * CACHE_LOOKUP_SIZE );
vol->lookup_cache = ntfs_create_cache("lookup",
(cache_free)NULL, ntfs_dir_lookup_hash,
sizeof(struct CACHED_LOOKUP),
CACHE_LOOKUP_SIZE, 2*CACHE_LOOKUP_SIZE);
#endif
vol->securid_cache = ntfs_create_cache( "securid", ( cache_free )NULL,
( cache_hash )NULL, sizeof( struct CACHED_SECURID ), CACHE_SECURID_SIZE, 0 );
vol->securid_cache = ntfs_create_cache("securid",(cache_free)NULL,
(cache_hash)NULL,sizeof(struct CACHED_SECURID), CACHE_SECURID_SIZE, 0);
#if CACHE_LEGACY_SIZE
vol->legacy_cache = ntfs_create_cache( "legacy", ( cache_free )NULL,
( cache_hash )NULL, sizeof( struct CACHED_PERMISSIONS_LEGACY ), CACHE_LEGACY_SIZE, 0 );
vol->legacy_cache = ntfs_create_cache("legacy",(cache_free)NULL,
(cache_hash)NULL, sizeof(struct CACHED_PERMISSIONS_LEGACY), CACHE_LEGACY_SIZE, 0);
#endif
}
@ -655,19 +591,19 @@ void ntfs_create_lru_caches( ntfs_volume *vol )
* Free all LRU caches
*/
void ntfs_free_lru_caches( ntfs_volume *vol )
void ntfs_free_lru_caches(ntfs_volume *vol)
{
#if CACHE_INODE_SIZE
ntfs_free_cache( vol->xinode_cache );
ntfs_free_cache(vol->xinode_cache);
#endif
#if CACHE_NIDATA_SIZE
ntfs_free_cache( vol->nidata_cache );
ntfs_free_cache(vol->nidata_cache);
#endif
#if CACHE_LOOKUP_SIZE
ntfs_free_cache( vol->lookup_cache );
ntfs_free_cache(vol->lookup_cache);
#endif
ntfs_free_cache( vol->securid_cache );
ntfs_free_cache(vol->securid_cache);
#if CACHE_LEGACY_SIZE
ntfs_free_cache( vol->legacy_cache );
ntfs_free_cache(vol->legacy_cache);
#endif
}

View File

@ -24,22 +24,19 @@
#include "volume.h"
struct CACHED_GENERIC
{
struct CACHED_GENERIC {
struct CACHED_GENERIC *next;
struct CACHED_GENERIC *previous;
void *variable;
size_t varsize;
union
{
union {
/* force alignment for pointers and u64 */
u64 u64align;
void *ptralign;
} fixed[0];
} ;
struct CACHED_INODE
{
struct CACHED_INODE {
struct CACHED_INODE *next;
struct CACHED_INODE *previous;
const char *pathname;
@ -48,8 +45,7 @@ struct CACHED_INODE
u64 inum;
} ;
struct CACHED_NIDATA
{
struct CACHED_NIDATA {
struct CACHED_NIDATA *next;
struct CACHED_NIDATA *previous;
const char *pathname; /* not used */
@ -59,8 +55,7 @@ struct CACHED_NIDATA
ntfs_inode *ni;
} ;
struct CACHED_LOOKUP
{
struct CACHED_LOOKUP {
struct CACHED_LOOKUP *next;
struct CACHED_LOOKUP *previous;
const char *name;
@ -70,25 +65,22 @@ struct CACHED_LOOKUP
u64 inum;
} ;
enum
{
enum {
CACHE_FREE = 1,
CACHE_NOHASH = 2
} ;
typedef int ( *cache_compare )( const struct CACHED_GENERIC *cached,
const struct CACHED_GENERIC *item );
typedef void ( *cache_free )( const struct CACHED_GENERIC *cached );
typedef int ( *cache_hash )( const struct CACHED_GENERIC *cached );
typedef int (*cache_compare)(const struct CACHED_GENERIC *cached,
const struct CACHED_GENERIC *item);
typedef void (*cache_free)(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 CACHED_GENERIC *entry;
} ;
struct CACHE_HEADER
{
struct CACHE_HEADER {
const char *name;
struct CACHED_GENERIC *most_recent_entry;
struct CACHED_GENERIC *oldest_entry;
@ -105,23 +97,23 @@ struct CACHE_HEADER
struct CACHED_GENERIC entry[0];
} ;
/* cast to generic, avoiding gcc warnings */
/* cast to generic, avoiding gcc warnings */
#define GENERIC(pstr) ((const struct CACHED_GENERIC*)(const void*)(pstr))
struct CACHED_GENERIC *ntfs_fetch_cache( struct CACHE_HEADER *cache,
struct CACHED_GENERIC *ntfs_fetch_cache(struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *wanted,
cache_compare compare );
struct CACHED_GENERIC *ntfs_enter_cache( struct CACHE_HEADER *cache,
cache_compare compare);
struct CACHED_GENERIC *ntfs_enter_cache(struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *item,
cache_compare compare );
int ntfs_invalidate_cache( struct CACHE_HEADER *cache,
cache_compare compare);
int ntfs_invalidate_cache(struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *item,
cache_compare compare, int flags );
int ntfs_remove_cache( struct CACHE_HEADER *cache,
struct CACHED_GENERIC *item, int flags );
cache_compare compare, int flags);
int ntfs_remove_cache(struct CACHE_HEADER *cache,
struct CACHED_GENERIC *item, int flags);
void ntfs_create_lru_caches( ntfs_volume *vol );
void ntfs_free_lru_caches( ntfs_volume *vol );
void ntfs_create_lru_caches(ntfs_volume *vol);
void ntfs_free_lru_caches(ntfs_volume *vol);
#endif /* _NTFS_CACHE_H_ */

View File

@ -45,27 +45,23 @@
#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;
unsigned int i;
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;
}
if ( sectorsPerPage < 32 )
{
if (sectorsPerPage < 32) {
sectorsPerPage = 32;
}
cache = ( NTFS_CACHE* ) ntfs_alloc ( sizeof( NTFS_CACHE ) );
if ( cache == NULL )
{
cache = (NTFS_CACHE*) ntfs_alloc (sizeof(NTFS_CACHE));
if (cache == NULL) {
return NULL;
}
@ -76,20 +72,18 @@ NTFS_CACHE* _NTFS_cache_constructor ( unsigned int numberOfPages, unsigned int s
cache->sectorSize = sectorSize;
cacheEntries = ( NTFS_CACHE_ENTRY* ) ntfs_alloc ( sizeof( NTFS_CACHE_ENTRY ) * numberOfPages );
if ( cacheEntries == NULL )
{
ntfs_free ( cache );
cacheEntries = (NTFS_CACHE_ENTRY*) ntfs_alloc ( sizeof(NTFS_CACHE_ENTRY) * numberOfPages);
if (cacheEntries == NULL) {
ntfs_free (cache);
return NULL;
}
for ( i = 0; i < numberOfPages; i++ )
{
for (i = 0; i < numberOfPages; i++) {
cacheEntries[i].sector = CACHE_FREE;
cacheEntries[i].count = 0;
cacheEntries[i].last_access = 0;
cacheEntries[i].dirty = false;
cacheEntries[i].cache = ( uint8_t* ) ntfs_align ( sectorsPerPage * cache->sectorSize );
cacheEntries[i].cache = (uint8_t*) ntfs_align ( sectorsPerPage * cache->sectorSize );
}
cache->cacheEntries = cacheEntries;
@ -97,33 +91,30 @@ NTFS_CACHE* _NTFS_cache_constructor ( unsigned int numberOfPages, unsigned int s
return cache;
}
void _NTFS_cache_destructor ( NTFS_CACHE* cache )
{
void _NTFS_cache_destructor (NTFS_CACHE* cache) {
unsigned int i;
if ( cache == NULL ) return;
if(cache==NULL) return;
// Clear out cache before destroying it
_NTFS_cache_flush( cache );
_NTFS_cache_flush(cache);
// Free memory in reverse allocation order
for ( i = 0; i < cache->numberOfPages; i++ )
{
ntfs_free ( cache->cacheEntries[i].cache );
for (i = 0; i < cache->numberOfPages; i++) {
ntfs_free (cache->cacheEntries[i].cache);
}
ntfs_free ( cache->cacheEntries );
ntfs_free ( cache );
ntfs_free (cache->cacheEntries);
ntfs_free (cache);
}
static u32 accessCounter = 0;
static u32 accessTime()
{
static u32 accessTime(){
accessCounter++;
return accessCounter;
}
static NTFS_CACHE_ENTRY* _NTFS_cache_getPage( NTFS_CACHE *cache, sec_t sector )
static NTFS_CACHE_ENTRY* _NTFS_cache_getPage(NTFS_CACHE *cache,sec_t sector)
{
unsigned int i;
NTFS_CACHE_ENTRY* cacheEntries = cache->cacheEntries;
@ -134,42 +125,37 @@ static NTFS_CACHE_ENTRY* _NTFS_cache_getPage( NTFS_CACHE *cache, sec_t sector )
unsigned int oldUsed = 0;
unsigned int oldAccess = UINT_MAX;
for ( i = 0; i < numberOfPages; i++ )
{
if ( sector >= cacheEntries[i].sector && sector < ( cacheEntries[i].sector + cacheEntries[i].count ) )
{
for(i=0;i<numberOfPages;i++) {
if(sector>=cacheEntries[i].sector && sector<(cacheEntries[i].sector + cacheEntries[i].count)) {
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 ( cacheEntries[i].sector == CACHE_FREE ) foundFree = true;
if(foundFree==false && (cacheEntries[i].sector==CACHE_FREE || cacheEntries[i].last_access<oldAccess)) {
if(cacheEntries[i].sector==CACHE_FREE) foundFree = true;
oldUsed = i;
oldAccess = cacheEntries[i].last_access;
}
}
if ( foundFree == false && cacheEntries[oldUsed].dirty == true )
{
if ( !cache->disc->writeSectors( cacheEntries[oldUsed].sector, cacheEntries[oldUsed].count, cacheEntries[oldUsed].cache ) ) return NULL;
if(foundFree==false && cacheEntries[oldUsed].dirty==true) {
if(!cache->disc->writeSectors(cacheEntries[oldUsed].sector,cacheEntries[oldUsed].count,cacheEntries[oldUsed].cache)) return NULL;
cacheEntries[oldUsed].dirty = false;
}
sector = ( sector / sectorsPerPage ) * sectorsPerPage; // align base sector to page size
sector = (sector/sectorsPerPage)*sectorsPerPage; // align base sector to page size
sec_t next_page = sector + sectorsPerPage;
if ( next_page > cache->endOfPartition ) next_page = cache->endOfPartition;
if(next_page > cache->endOfPartition) next_page = cache->endOfPartition;
if ( !cache->disc->readSectors( sector, next_page - sector, cacheEntries[oldUsed].cache ) ) return NULL;
if(!cache->disc->readSectors(sector,next_page-sector,cacheEntries[oldUsed].cache)) return NULL;
cacheEntries[oldUsed].sector = sector;
cacheEntries[oldUsed].count = next_page - sector;
cacheEntries[oldUsed].count = next_page-sector;
cacheEntries[oldUsed].last_access = accessTime();
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;
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;
sec_t lowest = UINT_MAX;
for ( i = 0; i < numberOfPages; i++ )
{
if ( cacheEntries[i].sector != CACHE_FREE )
{
for(i=0;i<numberOfPages;i++) {
if (cacheEntries[i].sector != CACHE_FREE) {
bool intersect;
if ( sector > cacheEntries[i].sector )
{
if (sector > cacheEntries[i].sector) {
intersect = sector - cacheEntries[i].sector < cacheEntries[i].count;
}
else
{
} else {
intersect = cacheEntries[i].sector - sector < count;
}
if ( intersect && ( cacheEntries[i].sector < lowest ) )
{
if ( intersect && (cacheEntries[i].sector < lowest)) {
lowest = cacheEntries[i].sector;
entry = &cacheEntries[i];
}
@ -202,25 +182,24 @@ static NTFS_CACHE_ENTRY* _NTFS_cache_findPage( NTFS_CACHE *cache, sec_t sector,
return entry;
}
bool _NTFS_cache_readSectors( NTFS_CACHE *cache, sec_t sector, sec_t numSectors, void *buffer )
bool _NTFS_cache_readSectors(NTFS_CACHE *cache,sec_t sector,sec_t numSectors,void *buffer)
{
sec_t sec;
sec_t secs_to_read;
NTFS_CACHE_ENTRY *entry;
uint8_t *dest = buffer;
while ( numSectors > 0 )
{
entry = _NTFS_cache_getPage( cache, sector );
if ( entry == NULL ) return false;
while(numSectors>0) {
entry = _NTFS_cache_getPage(cache,sector);
if(entry==NULL) return false;
sec = sector - entry->sector;
secs_to_read = entry->count - sec;
if ( secs_to_read > numSectors ) secs_to_read = numSectors;
if(secs_to_read>numSectors) secs_to_read = numSectors;
memcpy( dest, entry->cache + ( sec*cache->sectorSize ), ( secs_to_read*cache->sectorSize ) );
memcpy(dest,entry->cache + (sec*cache->sectorSize),(secs_to_read*cache->sectorSize));
dest += ( secs_to_read * cache->sectorSize );
dest += (secs_to_read*cache->sectorSize);
sector += secs_to_read;
numSectors -= secs_to_read;
}
@ -232,32 +211,30 @@ bool _NTFS_cache_readSectors( NTFS_CACHE *cache, sec_t sector, sec_t numSectors,
Reads some data from a cache page, determined by the sector number
*/
bool _NTFS_cache_readPartialSector ( NTFS_CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size )
bool _NTFS_cache_readPartialSector (NTFS_CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size)
{
sec_t sec;
NTFS_CACHE_ENTRY *entry;
if ( offset + size > cache->sectorSize ) return false;
if (offset + size > cache->sectorSize) return false;
entry = _NTFS_cache_getPage( cache, sector );
if ( entry == NULL ) return false;
entry = _NTFS_cache_getPage(cache,sector);
if(entry==NULL) return false;
sec = sector - entry->sector;
memcpy( buffer, entry->cache + ( ( sec*cache->sectorSize ) + offset ), size );
memcpy(buffer,entry->cache + ((sec*cache->sectorSize) + offset),size);
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];
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 2: *value = u8array_to_u16( buf, 0 ); break;
case 4: *value = u8array_to_u32( buf, 0 ); break;
case 2: *value = u8array_to_u16(buf,0); break;
case 4: *value = u8array_to_u32(buf,0); break;
default: return false;
}
return true;
@ -267,81 +244,77 @@ bool _NTFS_cache_readLittleEndianValue ( NTFS_CACHE* cache, uint32_t *value, sec
Writes some data to a cache page, making sure it is loaded into memory first.
*/
bool _NTFS_cache_writePartialSector ( NTFS_CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size )
bool _NTFS_cache_writePartialSector (NTFS_CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size)
{
sec_t sec;
NTFS_CACHE_ENTRY *entry;
if ( offset + size > cache->sectorSize ) return false;
if (offset + size > cache->sectorSize) return false;
entry = _NTFS_cache_getPage( cache, sector );
if ( entry == NULL ) return false;
entry = _NTFS_cache_getPage(cache,sector);
if(entry==NULL) return false;
sec = sector - entry->sector;
memcpy( entry->cache + ( ( sec*cache->sectorSize ) + offset ), buffer, size );
memcpy(entry->cache + ((sec*cache->sectorSize) + offset),buffer,size);
entry->dirty = 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};
switch ( size )
{
switch(size) {
case 1: buf[0] = value; break;
case 2: u16_to_u8array( buf, 0, value ); break;
case 4: u32_to_u8array( buf, 0, value ); break;
case 2: u16_to_u8array(buf, 0, value); break;
case 4: u32_to_u8array(buf, 0, value); break;
default: return false;
}
return _NTFS_cache_writePartialSector( cache, buf, sector, offset, size );
return _NTFS_cache_writePartialSector(cache, buf, sector, offset, size);
}
/*
Writes some data to a cache page, zeroing out the page first
*/
bool _NTFS_cache_eraseWritePartialSector ( NTFS_CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size )
bool _NTFS_cache_eraseWritePartialSector (NTFS_CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size)
{
sec_t sec;
NTFS_CACHE_ENTRY *entry;
if ( offset + size > cache->sectorSize ) return false;
if (offset + size > cache->sectorSize) return false;
entry = _NTFS_cache_getPage( cache, sector );
if ( entry == NULL ) return false;
entry = _NTFS_cache_getPage(cache,sector);
if(entry==NULL) return false;
sec = sector - entry->sector;
memset( entry->cache + ( sec*cache->sectorSize ), 0, cache->sectorSize );
memcpy( entry->cache + ( ( sec*cache->sectorSize ) + offset ), buffer, size );
memset(entry->cache + (sec*cache->sectorSize),0,cache->sectorSize);
memcpy(entry->cache + ((sec*cache->sectorSize) + offset),buffer,size);
entry->dirty = true;
return true;
}
bool _NTFS_cache_writeSectors ( NTFS_CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer )
bool _NTFS_cache_writeSectors (NTFS_CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer)
{
sec_t sec;
sec_t secs_to_write;
NTFS_CACHE_ENTRY* entry;
const uint8_t *src = buffer;
while ( numSectors > 0 )
while(numSectors>0)
{
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;
cache->disc->writeSectors( sector, secs_to_write, src );
src += ( secs_to_write * cache->sectorSize );
cache->disc->writeSectors(sector,secs_to_write,src);
src += (secs_to_write*cache->sectorSize);
sector += secs_to_write;
numSectors -= secs_to_write;
}
@ -349,21 +322,19 @@ bool _NTFS_cache_writeSectors ( NTFS_CACHE* cache, sec_t sector, sec_t numSector
sec = sector - entry->sector;
secs_to_write = entry->count - sec;
if ( secs_to_write > numSectors ) secs_to_write = numSectors;
if(secs_to_write>numSectors) secs_to_write = numSectors;
memcpy( entry->cache + ( sec*cache->sectorSize ), src, ( secs_to_write*cache->sectorSize ) );
memcpy(entry->cache + (sec*cache->sectorSize),src,(secs_to_write*cache->sectorSize));
src += ( secs_to_write * cache->sectorSize );
src += (secs_to_write*cache->sectorSize);
sector += secs_to_write;
numSectors -= secs_to_write;
entry->dirty = true;
}
else
{
cache->disc->writeSectors( sector, numSectors, src );
numSectors = 0;
} else {
cache->disc->writeSectors(sector,numSectors,src);
numSectors=0;
}
}
return true;
@ -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.
*/
bool _NTFS_cache_flush ( NTFS_CACHE* cache )
{
bool _NTFS_cache_flush (NTFS_CACHE* cache) {
unsigned int i;
if ( cache == NULL ) return true;
if(cache==NULL) return true;
for ( i = 0; i < cache->numberOfPages; i++ )
{
if ( cache->cacheEntries[i].dirty )
{
if ( !cache->disc->writeSectors ( cache->cacheEntries[i].sector, cache->cacheEntries[i].count, cache->cacheEntries[i].cache ) )
{
for (i = 0; i < cache->numberOfPages; i++) {
if (cache->cacheEntries[i].dirty) {
if (!cache->disc->writeSectors (cache->cacheEntries[i].sector, cache->cacheEntries[i].count, cache->cacheEntries[i].cache)) {
return false;
}
}
@ -392,15 +359,13 @@ bool _NTFS_cache_flush ( NTFS_CACHE* cache )
return true;
}
void _NTFS_cache_invalidate ( NTFS_CACHE* cache )
{
void _NTFS_cache_invalidate (NTFS_CACHE* cache) {
unsigned int i;
if ( cache == NULL )
if(cache==NULL)
return;
_NTFS_cache_flush( cache );
for ( i = 0; i < cache->numberOfPages; i++ )
{
_NTFS_cache_flush(cache);
for (i = 0; i < cache->numberOfPages; i++) {
cache->cacheEntries[i].sector = CACHE_FREE;
cache->cacheEntries[i].last_access = 0;
cache->cacheEntries[i].count = 0;

View File

@ -46,8 +46,7 @@
#include <ogc/disc_io.h>
#include <gccore.h>
typedef struct
{
typedef struct {
sec_t sector;
unsigned int count;
u64 last_access;
@ -55,8 +54,7 @@ typedef struct
u8* cache;
} NTFS_CACHE_ENTRY;
typedef struct
{
typedef struct {
const DISC_INTERFACE* disc;
sec_t endOfPartition;
unsigned int numberOfPages;
@ -101,7 +99,7 @@ Precondition: offset + size <= BYTES_PER_READ
/*
Read several sectors from the NTFS_CACHE
*/
bool _NTFS_cache_readSectors ( NTFS_CACHE* NTFS_CACHE, sec_t sector, sec_t numSectors, void* buffer );
bool _NTFS_cache_readSectors (NTFS_CACHE* NTFS_CACHE, sec_t sector, sec_t numSectors, void* buffer);
/*
Read a full sector from the NTFS_CACHE
@ -117,21 +115,21 @@ Write a full sector to the NTFS_CACHE
// return _NTFS_cache_writePartialSector (NTFS_CACHE, buffer, sector, 0, BYTES_PER_READ);
//}
bool _NTFS_cache_writeSectors ( NTFS_CACHE* NTFS_CACHE, sec_t sector, sec_t numSectors, const void* buffer );
bool _NTFS_cache_writeSectors (NTFS_CACHE* NTFS_CACHE, sec_t sector, sec_t numSectors, const void* buffer);
/*
Write any dirty sectors back to disc and clear out the contents of the NTFS_CACHE
*/
bool _NTFS_cache_flush ( NTFS_CACHE* NTFS_CACHE );
bool _NTFS_cache_flush (NTFS_CACHE* NTFS_CACHE);
/*
Clear out the contents of the NTFS_CACHE without writing any dirty sectors first
*/
void _NTFS_cache_invalidate ( NTFS_CACHE* NTFS_CACHE );
void _NTFS_cache_invalidate (NTFS_CACHE* NTFS_CACHE);
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);
void _NTFS_cache_destructor ( NTFS_CACHE* NTFS_CACHE );
void _NTFS_cache_destructor (NTFS_CACHE* NTFS_CACHE);
#endif // _CACHE_H

View File

@ -52,22 +52,21 @@
*
* Returns:
*/
static int ntfs_collate_binary( ntfs_volume *vol __attribute__( ( unused ) ),
static int ntfs_collate_binary(ntfs_volume *vol __attribute__((unused)),
const void *data1, const int data1_len,
const void *data2, const int data2_len )
const void *data2, const int data2_len)
{
int rc;
ntfs_log_trace( "Entering.\n" );
rc = memcmp( data1, data2, min( data1_len, data2_len ) );
if ( !rc && ( data1_len != data2_len ) )
{
if ( data1_len < data2_len )
ntfs_log_trace("Entering.\n");
rc = memcmp(data1, data2, min(data1_len, data2_len));
if (!rc && (data1_len != data2_len)) {
if (data1_len < data2_len)
rc = -1;
else
rc = 1;
}
ntfs_log_trace( "Done, returning %i.\n", rc );
ntfs_log_trace("Done, returning %i.\n", rc);
return rc;
}
@ -83,31 +82,29 @@ static int ntfs_collate_binary( ntfs_volume *vol __attribute__( ( unused ) ),
*
* Returns:
*/
static int ntfs_collate_ntofs_ulong( ntfs_volume *vol __attribute__( ( unused ) ),
static int ntfs_collate_ntofs_ulong(ntfs_volume *vol __attribute__((unused)),
const void *data1, const int data1_len,
const void *data2, const int data2_len )
const void *data2, const int data2_len)
{
int rc;
u32 d1, d2;
ntfs_log_trace( "Entering.\n" );
if ( data1_len != data2_len || data1_len != 4 )
{
ntfs_log_error( "data1_len or/and data2_len not equal to 4.\n" );
ntfs_log_trace("Entering.\n");
if (data1_len != data2_len || data1_len != 4) {
ntfs_log_error("data1_len or/and data2_len not equal to 4.\n");
return NTFS_COLLATION_ERROR;
}
d1 = le32_to_cpup( data1 );
d2 = le32_to_cpup( data2 );
if ( d1 < d2 )
d1 = le32_to_cpup(data1);
d2 = le32_to_cpup(data2);
if (d1 < d2)
rc = -1;
else
{
if ( d1 == d2 )
else {
if (d1 == d2)
rc = 0;
else
rc = 1;
}
ntfs_log_trace( "Done, returning %i.\n", rc );
ntfs_log_trace("Done, returning %i.\n", rc);
return rc;
}
@ -117,42 +114,38 @@ static int ntfs_collate_ntofs_ulong( ntfs_volume *vol __attribute__( ( unused )
* Returns: -1, 0 or 1 depending of how the arrays compare
*/
static int ntfs_collate_ntofs_ulongs( ntfs_volume *vol __attribute__( ( unused ) ),
static int ntfs_collate_ntofs_ulongs(ntfs_volume *vol __attribute__((unused)),
const void *data1, const int data1_len,
const void *data2, const int data2_len )
const void *data2, const int data2_len)
{
int rc;
int len;
const le32 *p1, *p2;
u32 d1, d2;
ntfs_log_trace( "Entering.\n" );
if ( ( data1_len != data2_len ) || ( data1_len <= 0 ) || ( data1_len & 3 ) )
{
ntfs_log_error( "data1_len or data2_len not valid\n" );
ntfs_log_trace("Entering.\n");
if ((data1_len != data2_len) || (data1_len <= 0) || (data1_len & 3)) {
ntfs_log_error("data1_len or data2_len not valid\n");
return NTFS_COLLATION_ERROR;
}
p1 = ( const le32* )data1;
p2 = ( const le32* )data2;
p1 = (const le32*)data1;
p2 = (const le32*)data2;
len = data1_len;
do
{
d1 = le32_to_cpup( p1 );
do {
d1 = le32_to_cpup(p1);
p1++;
d2 = le32_to_cpup( p2 );
d2 = le32_to_cpup(p2);
p2++;
}
while ( ( d1 == d2 ) && ( ( len -= 4 ) > 0 ) );
if ( d1 < d2 )
} while ((d1 == d2) && ((len -= 4) > 0));
if (d1 < d2)
rc = -1;
else
{
if ( d1 == d2 )
else {
if (d1 == d2)
rc = 0;
else
rc = 1;
}
ntfs_log_trace( "Done, returning %i.\n", rc );
ntfs_log_trace("Done, returning %i.\n", rc);
return rc;
}
@ -169,48 +162,44 @@ static int ntfs_collate_ntofs_ulongs( ntfs_volume *vol __attribute__( ( unused )
*
* Returns: -1, 0 or 1 depending of how the keys compare
*/
static int ntfs_collate_ntofs_security_hash( ntfs_volume *vol __attribute__( ( unused ) ),
static int ntfs_collate_ntofs_security_hash(ntfs_volume *vol __attribute__((unused)),
const void *data1, const int data1_len,
const void *data2, const int data2_len )
const void *data2, const int data2_len)
{
int rc;
u32 d1, d2;
const le32 *p1, *p2;
ntfs_log_trace( "Entering.\n" );
if ( data1_len != data2_len || data1_len != 8 )
{
ntfs_log_error( "data1_len or/and data2_len not equal to 8.\n" );
ntfs_log_trace("Entering.\n");
if (data1_len != data2_len || data1_len != 8) {
ntfs_log_error("data1_len or/and data2_len not equal to 8.\n");
return NTFS_COLLATION_ERROR;
}
p1 = ( const le32* )data1;
p2 = ( const le32* )data2;
d1 = le32_to_cpup( p1 );
d2 = le32_to_cpup( p2 );
if ( d1 < d2 )
p1 = (const le32*)data1;
p2 = (const le32*)data2;
d1 = le32_to_cpup(p1);
d2 = le32_to_cpup(p2);
if (d1 < d2)
rc = -1;
else
{
if ( d1 > d2 )
else {
if (d1 > d2)
rc = 1;
else
{
else {
p1++;
p2++;
d1 = le32_to_cpup( p1 );
d2 = le32_to_cpup( p2 );
if ( d1 < d2 )
d1 = le32_to_cpup(p1);
d2 = le32_to_cpup(p2);
if (d1 < d2)
rc = -1;
else
{
if ( d1 > d2 )
else {
if (d1 > d2)
rc = 1;
else
rc = 0;
}
}
}
ntfs_log_trace( "Done, returning %i.\n", rc );
ntfs_log_trace("Done, returning %i.\n", rc);
return rc;
}
@ -226,24 +215,24 @@ static int ntfs_collate_ntofs_security_hash( ntfs_volume *vol __attribute__( ( u
*
* Returns:
*/
static int ntfs_collate_file_name( ntfs_volume *vol,
const void *data1, const int data1_len __attribute__( ( unused ) ),
const void *data2, const int data2_len __attribute__( ( unused ) ) )
static int ntfs_collate_file_name(ntfs_volume *vol,
const void *data1, const int data1_len __attribute__((unused)),
const void *data2, const int data2_len __attribute__((unused)))
{
const FILE_NAME_ATTR *file_name_attr1;
const FILE_NAME_ATTR *file_name_attr2;
int rc;
ntfs_log_trace( "Entering.\n" );
file_name_attr1 = ( const FILE_NAME_ATTR* )data1;
file_name_attr2 = ( const FILE_NAME_ATTR* )data2;
ntfs_log_trace("Entering.\n");
file_name_attr1 = (const FILE_NAME_ATTR*)data1;
file_name_attr2 = (const FILE_NAME_ATTR*)data2;
rc = ntfs_names_full_collate(
( ntfschar* ) & file_name_attr1->file_name,
(ntfschar*)&file_name_attr1->file_name,
file_name_attr1->file_name_length,
( ntfschar* ) & file_name_attr2->file_name,
(ntfschar*)&file_name_attr2->file_name,
file_name_attr2->file_name_length,
CASE_SENSITIVE, vol->upcase, vol->upcase_len );
ntfs_log_trace( "Done, returning %i.\n", rc );
CASE_SENSITIVE, vol->upcase, vol->upcase_len);
ntfs_log_trace("Done, returning %i.\n", rc);
return rc;
}
@ -253,12 +242,11 @@ static int ntfs_collate_file_name( ntfs_volume *vol,
* Returns NULL if the needed function is not implemented
*/
COLLATE ntfs_get_collate_function( COLLATION_RULES cr )
COLLATE ntfs_get_collate_function(COLLATION_RULES cr)
{
COLLATE collate;
switch ( cr )
{
switch (cr) {
case COLLATION_BINARY :
collate = ntfs_collate_binary;
break;
@ -276,8 +264,8 @@ COLLATE ntfs_get_collate_function( COLLATION_RULES cr )
break;
default :
errno = EOPNOTSUPP;
collate = ( COLLATE )NULL;
collate = (COLLATE)NULL;
break;
}
return ( collate );
return (collate);
}

View File

@ -29,6 +29,6 @@
#define NTFS_COLLATION_ERROR -2
extern COLLATE ntfs_get_collate_function( COLLATION_RULES );
extern COLLATE ntfs_get_collate_function(COLLATION_RULES);
#endif /* _NTFS_COLLATE_H */

View File

@ -35,34 +35,29 @@
*
* Returns:
*/
int ffs( int x )
int ffs(int x)
{
int r = 1;
if ( !x )
if (!x)
return 0;
if ( !( x & 0xffff ) )
{
if (!(x & 0xffff)) {
x >>= 16;
r += 16;
}
if ( !( x & 0xff ) )
{
if (!(x & 0xff)) {
x >>= 8;
r += 8;
}
if ( !( x & 0xf ) )
{
if (!(x & 0xf)) {
x >>= 4;
r += 4;
}
if ( !( x & 3 ) )
{
if (!(x & 3)) {
x >>= 2;
r += 2;
}
if ( !( x & 1 ) )
{
if (!(x & 1)) {
x >>= 1;
r += 1;
}
@ -125,35 +120,32 @@ static const char rcsid[] = "$Id: compat.c,v 1.1.1.1.2.1 2008-08-16 15:17:44 jpa
#include <unistd.h>
#endif
int daemon( int nochdir, int noclose )
{
int daemon(int nochdir, int noclose) {
int fd;
switch ( fork() )
{
switch (fork()) {
case -1:
return ( -1 );
return (-1);
case 0:
break;
default:
_exit( 0 );
_exit(0);
}
if ( setsid() == -1 )
return ( -1 );
if (setsid() == -1)
return (-1);
if ( !nochdir )
( void )chdir( "/" );
if (!nochdir)
(void)chdir("/");
if ( !noclose && ( fd = open( "/dev/null", O_RDWR, 0 ) ) != -1 )
{
( void )dup2( fd, 0 );
( void )dup2( fd, 1 );
( void )dup2( fd, 2 );
if ( fd > 2 )
( void )close ( fd );
if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
(void)dup2(fd, 0);
(void)dup2(fd, 1);
(void)dup2(fd, 2);
if (fd > 2)
(void)close (fd);
}
return ( 0 );
return (0);
}
/*
* End: src/lib/libresolv2/common/bsd/daemon.c
@ -226,32 +218,27 @@ 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.
*/
char *strsep( char **stringp, const char *delim )
{
char *strsep(char **stringp, const char *delim) {
char *s;
const char *spanp;
int c, sc;
char *tok;
if ( ( s = *stringp ) == NULL )
return ( NULL );
for ( tok = s;; )
{
if ((s = *stringp) == NULL)
return (NULL);
for (tok = s;;) {
c = *s++;
spanp = delim;
do
{
if ( ( sc = *spanp++ ) == c )
{
if ( c == 0 )
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = 0;
*stringp = s;
return ( tok );
return (tok);
}
}
while ( sc != 0 );
} while (sc != 0);
}
/* NOTREACHED */
}

View File

@ -36,15 +36,15 @@
#endif
#ifndef HAVE_FFS
extern int ffs( int i );
extern int ffs(int i);
#endif /* HAVE_FFS */
#ifndef HAVE_DAEMON
extern int daemon( int nochdir, int noclose );
extern int daemon(int nochdir, int noclose);
#endif /* HAVE_DAEMON */
#ifndef HAVE_STRSEP
extern char *strsep( char **stringp, const char *delim );
extern char *strsep(char **stringp, const char *delim);
#endif /* HAVE_STRSEP */
#ifdef WINDOWS

File diff suppressed because it is too large Load Diff

View File

@ -26,16 +26,16 @@
#include "types.h"
#include "attrib.h"
extern s64 ntfs_compressed_attr_pread( ntfs_attr *na, s64 pos, s64 count,
void *b );
extern s64 ntfs_compressed_attr_pread(ntfs_attr *na, s64 pos, s64 count,
void *b);
extern s64 ntfs_compressed_pwrite( ntfs_attr *na, runlist_element *brl, s64 wpos,
extern s64 ntfs_compressed_pwrite(ntfs_attr *na, runlist_element *brl, s64 wpos,
s64 offs, s64 to_write, s64 rounded,
const void *b, int compressed_part,
VCN *update_from );
VCN *update_from);
extern int ntfs_compressed_close( ntfs_attr *na, runlist_element *brl,
s64 offs, VCN *update_from );
extern int ntfs_compressed_close(ntfs_attr *na, runlist_element *brl,
s64 offs, VCN *update_from);
#endif /* defined _NTFS_COMPRESS_H */

View File

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

View File

@ -31,9 +31,9 @@
struct _runlist_element;
#ifdef DEBUG
extern void ntfs_debug_runlist_dump( const struct _runlist_element *rl );
extern void ntfs_debug_runlist_dump(const struct _runlist_element *rl);
#else
static __inline__ void ntfs_debug_runlist_dump( const struct _runlist_element *rl __attribute__( ( unused ) ) ) {}
static __inline__ void ntfs_debug_runlist_dump(const struct _runlist_element *rl __attribute__((unused))) {}
#endif
#define NTFS_BUG(msg) \

View File

@ -103,24 +103,21 @@
* On success return a pointer to the allocated ntfs device structure and on
* error return NULL with errno set to the error code returned by ntfs_malloc().
*/
struct ntfs_device *ntfs_device_alloc( const char *name, const long state,
struct ntfs_device_operations *dops, void *priv_data )
struct ntfs_device *ntfs_device_alloc(const char *name, const long state,
struct ntfs_device_operations *dops, void *priv_data)
{
struct ntfs_device *dev;
if ( !name )
{
if (!name) {
errno = EINVAL;
return NULL;
}
dev = ntfs_malloc( sizeof( struct ntfs_device ) );
if ( dev )
{
if ( !( dev->d_name = strdup( name ) ) )
{
dev = ntfs_malloc(sizeof(struct ntfs_device));
if (dev) {
if (!(dev->d_name = strdup(name))) {
int eo = errno;
free( dev );
free(dev);
errno = eo;
return NULL;
}
@ -142,20 +139,18 @@ struct ntfs_device *ntfs_device_alloc( const char *name, const long state,
* EINVAL Invalid pointer @dev.
* EBUSY Device is still open. Close it before freeing it!
*/
int ntfs_device_free( struct ntfs_device *dev )
int ntfs_device_free(struct ntfs_device *dev)
{
if ( !dev )
{
if (!dev) {
errno = EINVAL;
return -1;
}
if ( NDevOpen( dev ) )
{
if (NDevOpen(dev)) {
errno = EBUSY;
return -1;
}
free( dev->d_name );
free( dev );
free(dev->d_name);
free(dev);
return 0;
}
@ -178,31 +173,29 @@ int ntfs_device_free( struct ntfs_device *dev )
* to the return code of either seek, read, or set to EINVAL in case of
* invalid arguments.
*/
s64 ntfs_pread( struct ntfs_device *dev, const s64 pos, s64 count, void *b )
s64 ntfs_pread(struct ntfs_device *dev, const s64 pos, s64 count, void *b)
{
s64 br, total;
struct ntfs_device_operations *dops;
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;
return -1;
}
if ( !count )
if (!count)
return 0;
dops = dev->d_ops;
for ( total = 0; count; count -= br, total += br )
{
br = dops->pread( dev, ( char* )b + total, count, pos + total );
for (total = 0; count; count -= br, total += br) {
br = dops->pread(dev, (char*)b + total, count, pos + total);
/* If everything ok, continue. */
if ( br > 0 )
if (br > 0)
continue;
/* If EOF or error return number of bytes read. */
if ( !br || total )
if (!br || total)
return total;
/* Nothing read and error, return error status. */
return br;
@ -230,41 +223,38 @@ s64 ntfs_pread( struct ntfs_device *dev, const s64 pos, s64 count, void *b )
* appropriately to the return code of either seek, write, or set
* to EINVAL in case of invalid arguments.
*/
s64 ntfs_pwrite( struct ntfs_device *dev, const s64 pos, s64 count,
const void *b )
s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
const void *b)
{
s64 written, total, ret = -1;
struct ntfs_device_operations *dops;
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;
goto out;
}
if ( !count )
if (!count)
return 0;
if ( NDevReadOnly( dev ) )
{
if (NDevReadOnly(dev)) {
errno = EROFS;
goto out;
}
dops = dev->d_ops;
NDevSetDirty( dev );
for ( total = 0; count; count -= written, total += written )
{
written = dops->pwrite( dev, ( const char* )b + total, count,
pos + total );
NDevSetDirty(dev);
for (total = 0; count; count -= written, total += written) {
written = dops->pwrite(dev, (const char*)b + total, count,
pos + total);
/* If everything ok, continue. */
if ( written > 0 )
if (written > 0)
continue;
/*
* If nothing written or error return number of bytes written.
*/
if ( !written || total )
if (!written || total)
break;
/* Nothing written and error, return error status. */
total = written;
@ -304,19 +294,18 @@ out:
* sector transfer error. This should be detected by the caller by checking for
* the magic being "BAAD".
*/
s64 ntfs_mst_pread( struct ntfs_device *dev, const s64 pos, s64 count,
const u32 bksize, void *b )
s64 ntfs_mst_pread(struct ntfs_device *dev, const s64 pos, s64 count,
const u32 bksize, void *b)
{
s64 br, i;
if ( bksize & ( bksize - 1 ) || bksize % NTFS_BLOCK_SIZE )
{
if (bksize & (bksize - 1) || bksize % NTFS_BLOCK_SIZE) {
errno = EINVAL;
return -1;
}
/* Do the read. */
br = ntfs_pread( dev, pos, count * bksize, b );
if ( br < 0 )
br = ntfs_pread(dev, pos, count * bksize, b);
if (br < 0)
return br;
/*
* Apply fixups to successfully read data, disregarding any errors
@ -325,9 +314,9 @@ s64 ntfs_mst_pread( struct ntfs_device *dev, const s64 pos, s64 count,
* magic will be detected later on.
*/
count = br / bksize;
for ( i = 0; i < count; ++i )
ntfs_mst_post_read_fixup( ( NTFS_RECORD* )
( ( u8* )b + i * bksize ), bksize );
for (i = 0; i < count; ++i)
ntfs_mst_post_read_fixup((NTFS_RECORD*)
((u8*)b + i * bksize), bksize);
/* Finally, return the number of complete blocks read. */
return count;
}
@ -362,40 +351,37 @@ s64 ntfs_mst_pread( struct ntfs_device *dev, const s64 pos, s64 count,
* simulating an mst read on the written data. This way cache coherency is
* achieved.
*/
s64 ntfs_mst_pwrite( struct ntfs_device *dev, const s64 pos, s64 count,
const u32 bksize, void *b )
s64 ntfs_mst_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
const u32 bksize, void *b)
{
s64 written, i;
if ( count < 0 || bksize % NTFS_BLOCK_SIZE )
{
if (count < 0 || bksize % NTFS_BLOCK_SIZE) {
errno = EINVAL;
return -1;
}
if ( !count )
if (!count)
return 0;
/* Prepare data for writing. */
for ( i = 0; i < count; ++i )
{
for (i = 0; i < count; ++i) {
int err;
err = ntfs_mst_pre_write_fixup( ( NTFS_RECORD* )
( ( u8* )b + i * bksize ), bksize );
if ( err < 0 )
{
err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)
((u8*)b + i * bksize), bksize);
if (err < 0) {
/* Abort write at this position. */
if ( !i )
if (!i)
return err;
count = i;
break;
}
}
/* Write the prepared data. */
written = ntfs_pwrite( dev, pos, count * bksize, b );
written = ntfs_pwrite(dev, pos, count * bksize, b);
/* Quickly deprotect the data again. */
for ( i = 0; i < count; ++i )
ntfs_mst_post_write_fixup( ( NTFS_RECORD* )( ( u8* )b + i * bksize ) );
if ( written <= 0 )
for (i = 0; i < count; ++i)
ntfs_mst_post_write_fixup((NTFS_RECORD*)((u8*)b + i * bksize));
if (written <= 0)
return written;
/* Finally, return the number of complete blocks written. */
return written / bksize;
@ -412,29 +398,26 @@ s64 ntfs_mst_pwrite( struct ntfs_device *dev, const s64 pos, s64 count,
* volume @vol into buffer @b. Return number of clusters read or -1 on error,
* with errno set to the error code.
*/
s64 ntfs_cluster_read( const ntfs_volume *vol, const s64 lcn, const s64 count,
void *b )
s64 ntfs_cluster_read(const ntfs_volume *vol, const s64 lcn, const s64 count,
void *b)
{
s64 br;
if ( !vol || lcn < 0 || count < 0 )
{
if (!vol || lcn < 0 || count < 0) {
errno = EINVAL;
return -1;
}
if ( vol->nr_clusters < lcn + count )
{
if (vol->nr_clusters < lcn + count) {
errno = ESPIPE;
ntfs_log_perror( "Trying to read outside of volume "
"(%lld < %lld)", ( long long )vol->nr_clusters,
( long long )lcn + count );
ntfs_log_perror("Trying to read outside of volume "
"(%lld < %lld)", (long long)vol->nr_clusters,
(long long)lcn + count);
return -1;
}
br = ntfs_pread( vol->dev, lcn << vol->cluster_size_bits,
count << vol->cluster_size_bits, b );
if ( br < 0 )
{
ntfs_log_perror( "Error reading cluster(s)" );
br = ntfs_pread(vol->dev, lcn << vol->cluster_size_bits,
count << vol->cluster_size_bits, b);
if (br < 0) {
ntfs_log_perror("Error reading cluster(s)");
return br;
}
return br >> vol->cluster_size_bits;
@ -451,32 +434,29 @@ s64 ntfs_cluster_read( const ntfs_volume *vol, const s64 lcn, const s64 count,
* buffer @b to volume @vol. Return the number of clusters written or -1 on
* error, with errno set to the error code.
*/
s64 ntfs_cluster_write( const ntfs_volume *vol, const s64 lcn,
const s64 count, const void *b )
s64 ntfs_cluster_write(const ntfs_volume *vol, const s64 lcn,
const s64 count, const void *b)
{
s64 bw;
if ( !vol || lcn < 0 || count < 0 )
{
if (!vol || lcn < 0 || count < 0) {
errno = EINVAL;
return -1;
}
if ( vol->nr_clusters < lcn + count )
{
if (vol->nr_clusters < lcn + count) {
errno = ESPIPE;
ntfs_log_perror( "Trying to write outside of volume "
"(%lld < %lld)", ( long long )vol->nr_clusters,
( long long )lcn + count );
ntfs_log_perror("Trying to write outside of volume "
"(%lld < %lld)", (long long)vol->nr_clusters,
(long long)lcn + count);
return -1;
}
if ( !NVolReadOnly( vol ) )
bw = ntfs_pwrite( vol->dev, lcn << vol->cluster_size_bits,
count << vol->cluster_size_bits, b );
if (!NVolReadOnly(vol))
bw = ntfs_pwrite(vol->dev, lcn << vol->cluster_size_bits,
count << vol->cluster_size_bits, b);
else
bw = count << vol->cluster_size_bits;
if ( bw < 0 )
{
ntfs_log_perror( "Error writing cluster(s)" );
if (bw < 0) {
ntfs_log_perror("Error writing cluster(s)");
return bw;
}
return bw >> vol->cluster_size_bits;
@ -492,12 +472,12 @@ s64 ntfs_cluster_write( const ntfs_volume *vol, const s64 lcn,
*
* Return 0 if it is valid and -1 if it is not valid.
*/
static int ntfs_device_offset_valid( struct ntfs_device *dev, s64 ofs )
static int ntfs_device_offset_valid(struct ntfs_device *dev, s64 ofs)
{
char ch;
if ( dev->d_ops->seek( dev, ofs, SEEK_SET ) >= 0 &&
dev->d_ops->read( dev, &ch, 1 ) == 1 )
if (dev->d_ops->seek(dev, ofs, SEEK_SET) >= 0 &&
dev->d_ops->read(dev, &ch, 1) == 1)
return 0;
return -1;
}
@ -514,47 +494,43 @@ static int ntfs_device_offset_valid( struct ntfs_device *dev, s64 ofs )
*
* On error return -1 with errno set to the error code.
*/
s64 ntfs_device_size_get( struct ntfs_device *dev, int block_size )
s64 ntfs_device_size_get(struct ntfs_device *dev, int block_size)
{
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;
return -1;
}
#ifdef BLKGETSIZE64
{ u64 size;
if ( dev->d_ops->ioctl( dev, BLKGETSIZE64, &size ) >= 0 )
{
ntfs_log_debug( "BLKGETSIZE64 nr bytes = %llu (0x%llx)\n",
( unsigned long long )size,
( unsigned long long )size );
return ( s64 )size / block_size;
if (dev->d_ops->ioctl(dev, BLKGETSIZE64, &size) >= 0) {
ntfs_log_debug("BLKGETSIZE64 nr bytes = %llu (0x%llx)\n",
(unsigned long long)size,
(unsigned long long)size);
return (s64)size / block_size;
}
}
#endif
#ifdef BLKGETSIZE
{ unsigned long size;
if ( dev->d_ops->ioctl( dev, BLKGETSIZE, &size ) >= 0 )
{
ntfs_log_debug( "BLKGETSIZE nr 512 byte blocks = %lu (0x%lx)\n",
size, size );
return ( s64 )size * 512 / block_size;
if (dev->d_ops->ioctl(dev, BLKGETSIZE, &size) >= 0) {
ntfs_log_debug("BLKGETSIZE nr 512 byte blocks = %lu (0x%lx)\n",
size, size);
return (s64)size * 512 / block_size;
}
}
#endif
#ifdef FDGETPRM
{ struct floppy_struct this_floppy;
if ( dev->d_ops->ioctl( dev, FDGETPRM, &this_floppy ) >= 0 )
{
ntfs_log_debug( "FDGETPRM nr 512 byte blocks = %lu (0x%lx)\n",
( unsigned long )this_floppy.size,
( unsigned long )this_floppy.size );
return ( s64 )this_floppy.size * 512 / block_size;
if (dev->d_ops->ioctl(dev, FDGETPRM, &this_floppy) >= 0) {
ntfs_log_debug("FDGETPRM nr 512 byte blocks = %lu (0x%lx)\n",
(unsigned long)this_floppy.size,
(unsigned long)this_floppy.size);
return (s64)this_floppy.size * 512 / block_size;
}
}
#endif
@ -563,19 +539,18 @@ s64 ntfs_device_size_get( struct ntfs_device *dev, int block_size )
* so do binary search to find the size of the device.
*/
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;
while ( low < high - 1LL )
{
const s64 mid = ( low + high ) / 2;
while (low < high - 1LL) {
const s64 mid = (low + high) / 2;
if ( !ntfs_device_offset_valid( dev, mid ) )
if (!ntfs_device_offset_valid(dev, mid))
low = mid;
else
high = mid;
}
dev->d_ops->seek( dev, 0LL, SEEK_SET );
return ( low + 1LL ) / block_size;
dev->d_ops->seek(dev, 0LL, SEEK_SET);
return (low + 1LL) / block_size;
}
/**
@ -590,20 +565,18 @@ s64 ntfs_device_size_get( struct ntfs_device *dev, int block_size )
* EOPNOTSUPP System does not support HDIO_GETGEO ioctl
* ENOTTY @dev is a file or a device not supporting HDIO_GETGEO
*/
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;
return -1;
}
#ifdef HDIO_GETGEO
{ struct hd_geometry geo;
if ( !dev->d_ops->ioctl( dev, HDIO_GETGEO, &geo ) )
{
ntfs_log_debug( "HDIO_GETGEO start_sect = %lu (0x%lx)\n",
geo.start, geo.start );
if (!dev->d_ops->ioctl(dev, HDIO_GETGEO, &geo)) {
ntfs_log_debug("HDIO_GETGEO start_sect = %lu (0x%lx)\n",
geo.start, geo.start);
return geo.start;
}
}
@ -625,21 +598,19 @@ s64 ntfs_device_partition_start_sector_get( struct ntfs_device *dev )
* EOPNOTSUPP System does not support HDIO_GETGEO ioctl
* ENOTTY @dev is a file or a device not supporting HDIO_GETGEO
*/
int ntfs_device_heads_get( struct ntfs_device *dev )
int ntfs_device_heads_get(struct ntfs_device *dev)
{
if ( !dev )
{
if (!dev) {
errno = EINVAL;
return -1;
}
#ifdef HDIO_GETGEO
{ struct hd_geometry geo;
if ( !dev->d_ops->ioctl( dev, HDIO_GETGEO, &geo ) )
{
ntfs_log_debug( "HDIO_GETGEO heads = %u (0x%x)\n",
( unsigned )geo.heads,
( unsigned )geo.heads );
if (!dev->d_ops->ioctl(dev, HDIO_GETGEO, &geo)) {
ntfs_log_debug("HDIO_GETGEO heads = %u (0x%x)\n",
(unsigned)geo.heads,
(unsigned)geo.heads);
return geo.heads;
}
}
@ -661,21 +632,19 @@ int ntfs_device_heads_get( struct ntfs_device *dev )
* EOPNOTSUPP System does not support HDIO_GETGEO ioctl
* ENOTTY @dev is a file or a device not supporting HDIO_GETGEO
*/
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;
return -1;
}
#ifdef HDIO_GETGEO
{ struct hd_geometry geo;
if ( !dev->d_ops->ioctl( dev, HDIO_GETGEO, &geo ) )
{
ntfs_log_debug( "HDIO_GETGEO sectors_per_track = %u (0x%x)\n",
( unsigned )geo.sectors,
( unsigned )geo.sectors );
if (!dev->d_ops->ioctl(dev, HDIO_GETGEO, &geo)) {
ntfs_log_debug("HDIO_GETGEO sectors_per_track = %u (0x%x)\n",
(unsigned)geo.sectors,
(unsigned)geo.sectors);
return geo.sectors;
}
}
@ -697,10 +666,9 @@ int ntfs_device_sectors_per_track_get( struct ntfs_device *dev )
* EOPNOTSUPP System does not support BLKSSZGET ioctl
* ENOTTY @dev is a file or a device not supporting BLKSSZGET
*/
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;
return -1;
}
@ -708,10 +676,9 @@ int ntfs_device_sector_size_get( struct ntfs_device *dev )
{
int sect_size = 0;
if ( !dev->d_ops->ioctl( dev, BLKSSZGET, &sect_size ) )
{
ntfs_log_debug( "BLKSSZGET sector size = %d bytes\n",
sect_size );
if (!dev->d_ops->ioctl(dev, BLKSSZGET, &sect_size)) {
ntfs_log_debug("BLKSSZGET sector size = %d bytes\n",
sect_size);
return sect_size;
}
}
@ -734,30 +701,28 @@ int ntfs_device_sector_size_get( struct ntfs_device *dev )
* EOPNOTSUPP System does not support BLKBSZSET ioctl
* ENOTTY @dev is a file or a device not supporting BLKBSZSET
*/
int ntfs_device_block_size_set( struct ntfs_device *dev,
int block_size __attribute__( ( unused ) ) )
int ntfs_device_block_size_set(struct ntfs_device *dev,
int block_size __attribute__((unused)))
{
if ( !dev )
{
if (!dev) {
errno = EINVAL;
return -1;
}
#ifdef BLKBSZSET
{
size_t s_block_size = block_size;
if ( !dev->d_ops->ioctl( dev, BLKBSZSET, &s_block_size ) )
{
ntfs_log_debug( "Used BLKBSZSET to set block size to "
"%d bytes.\n", block_size );
if (!dev->d_ops->ioctl(dev, BLKBSZSET, &s_block_size)) {
ntfs_log_debug("Used BLKBSZSET to set block size to "
"%d bytes.\n", block_size);
return 0;
}
/* If not a block device, pretend it was successful. */
if ( !NDevBlock( dev ) )
if (!NDevBlock(dev))
return 0;
}
#else
/* If not a block device, pretend it was successful. */
if ( !NDevBlock( dev ) )
if (!NDevBlock(dev))
return 0;
errno = EOPNOTSUPP;
#endif

View File

@ -36,8 +36,7 @@
*
* Defined bits for the state field in the ntfs_device structure.
*/
typedef enum
{
typedef enum {
ND_Open, /* 1: Device is open. */
ND_ReadOnly, /* 1: Device is read-only. */
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
* level device underlying the ntfs volume.
*/
struct ntfs_device
{
struct ntfs_device {
struct ntfs_device_operations *d_ops; /* Device operations. */
unsigned long d_state; /* State of the device. */
char *d_name; /* Name of device. */
@ -87,45 +85,44 @@ struct stat;
* The ntfs device operations defining all operations that can be performed on
* the low level device described by an ntfs device structure.
*/
struct ntfs_device_operations
{
int ( *open )( struct ntfs_device *dev, int flags );
int ( *close )( struct ntfs_device *dev );
s64 ( *seek )( struct ntfs_device *dev, s64 offset, int whence );
s64 ( *read )( struct ntfs_device *dev, void *buf, s64 count );
s64 ( *write )( struct ntfs_device *dev, const void *buf, s64 count );
s64 ( *pread )( struct ntfs_device *dev, void *buf, s64 count, s64 offset );
s64 ( *pwrite )( struct ntfs_device *dev, const void *buf, s64 count,
s64 offset );
int ( *sync )( struct ntfs_device *dev );
int ( *stat )( struct ntfs_device *dev, struct stat *buf );
int ( *ioctl )( struct ntfs_device *dev, int request, void *argp );
struct ntfs_device_operations {
int (*open)(struct ntfs_device *dev, int flags);
int (*close)(struct ntfs_device *dev);
s64 (*seek)(struct ntfs_device *dev, s64 offset, int whence);
s64 (*read)(struct ntfs_device *dev, void *buf, s64 count);
s64 (*write)(struct ntfs_device *dev, const void *buf, s64 count);
s64 (*pread)(struct ntfs_device *dev, void *buf, s64 count, s64 offset);
s64 (*pwrite)(struct ntfs_device *dev, const void *buf, s64 count,
s64 offset);
int (*sync)(struct ntfs_device *dev);
int (*stat)(struct ntfs_device *dev, struct stat *buf);
int (*ioctl)(struct ntfs_device *dev, int request, void *argp);
};
extern struct ntfs_device *ntfs_device_alloc( const char *name, const long state,
struct ntfs_device_operations *dops, void *priv_data );
extern int ntfs_device_free( struct ntfs_device *dev );
extern struct ntfs_device *ntfs_device_alloc(const char *name, const long state,
struct ntfs_device_operations *dops, void *priv_data);
extern int ntfs_device_free(struct ntfs_device *dev);
extern s64 ntfs_pread( struct ntfs_device *dev, const s64 pos, s64 count,
void *b );
extern s64 ntfs_pwrite( struct ntfs_device *dev, const s64 pos, s64 count,
const void *b );
extern s64 ntfs_pread(struct ntfs_device *dev, const s64 pos, s64 count,
void *b);
extern s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
const void *b);
extern s64 ntfs_mst_pread( struct ntfs_device *dev, const s64 pos, s64 count,
const u32 bksize, void *b );
extern s64 ntfs_mst_pwrite( struct ntfs_device *dev, const s64 pos, s64 count,
const u32 bksize, void *b );
extern s64 ntfs_mst_pread(struct ntfs_device *dev, const s64 pos, s64 count,
const u32 bksize, void *b);
extern s64 ntfs_mst_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
const u32 bksize, void *b);
extern s64 ntfs_cluster_read( const ntfs_volume *vol, const s64 lcn,
const s64 count, void *b );
extern s64 ntfs_cluster_write( const ntfs_volume *vol, const s64 lcn,
const s64 count, const void *b );
extern s64 ntfs_cluster_read(const ntfs_volume *vol, const s64 lcn,
const s64 count, void *b);
extern s64 ntfs_cluster_write(const ntfs_volume *vol, const s64 lcn,
const s64 count, const void *b);
extern s64 ntfs_device_size_get( struct ntfs_device *dev, int block_size );
extern s64 ntfs_device_partition_start_sector_get( struct ntfs_device *dev );
extern int ntfs_device_heads_get( struct ntfs_device *dev );
extern int ntfs_device_sectors_per_track_get( struct ntfs_device *dev );
extern int ntfs_device_sector_size_get( struct ntfs_device *dev );
extern int ntfs_device_block_size_set( struct ntfs_device *dev, int block_size );
extern s64 ntfs_device_size_get(struct ntfs_device *dev, int block_size);
extern s64 ntfs_device_partition_start_sector_get(struct ntfs_device *dev);
extern int ntfs_device_heads_get(struct ntfs_device *dev);
extern int ntfs_device_sectors_per_track_get(struct ntfs_device *dev);
extern int ntfs_device_sector_size_get(struct ntfs_device *dev);
extern int ntfs_device_block_size_set(struct ntfs_device *dev, int block_size);
#endif /* defined _NTFS_DEVICE_H */

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -59,27 +59,27 @@ extern ntfschar NTFS_INDEX_O[3];
extern ntfschar NTFS_INDEX_Q[3];
extern ntfschar NTFS_INDEX_R[3];
extern u64 ntfs_inode_lookup_by_name( ntfs_inode *dir_ni,
const ntfschar *uname, const int uname_len );
extern u64 ntfs_inode_lookup_by_mbsname( ntfs_inode *dir_ni, const char *name );
extern void ntfs_inode_update_mbsname( ntfs_inode *dir_ni, const char *name,
u64 inum );
extern u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
const ntfschar *uname, const int uname_len);
extern u64 ntfs_inode_lookup_by_mbsname(ntfs_inode *dir_ni, const char *name);
extern void ntfs_inode_update_mbsname(ntfs_inode *dir_ni, const char *name,
u64 inum);
extern ntfs_inode *ntfs_pathname_to_inode( ntfs_volume *vol, ntfs_inode *parent,
const char *pathname );
extern ntfs_inode *ntfs_create( ntfs_inode *dir_ni, le32 securid,
ntfschar *name, u8 name_len, mode_t type );
extern ntfs_inode *ntfs_create_device( ntfs_inode *dir_ni, le32 securid,
ntfschar *name, u8 name_len, mode_t type, dev_t dev );
extern ntfs_inode *ntfs_create_symlink( ntfs_inode *dir_ni, le32 securid,
ntfschar *name, u8 name_len, ntfschar *target, int target_len );
extern int ntfs_check_empty_dir( ntfs_inode *ni );
extern int ntfs_delete( ntfs_volume *vol, const char *path,
extern ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent,
const char *pathname);
extern ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid,
ntfschar *name, u8 name_len, mode_t type);
extern ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid,
ntfschar *name, u8 name_len, mode_t type, dev_t dev);
extern ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, le32 securid,
ntfschar *name, u8 name_len, ntfschar *target, int target_len);
extern int ntfs_check_empty_dir(ntfs_inode *ni);
extern int ntfs_delete(ntfs_volume *vol, const char *path,
ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name,
u8 name_len );
u8 name_len);
extern int ntfs_link( ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name,
u8 name_len );
extern int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name,
u8 name_len);
/*
* File types (adapted from include <linux/fs.h>)
@ -100,27 +100,27 @@ extern int ntfs_link( ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name,
* This allows the caller to read directories into their application or
* to have different dirent layouts depending on the binary type.
*/
typedef int ( *ntfs_filldir_t )( void *dirent, const ntfschar *name,
typedef int (*ntfs_filldir_t)(void *dirent, const ntfschar *name,
const int name_len, const int name_type, const s64 pos,
const MFT_REF mref, const unsigned dt_type );
const MFT_REF mref, const unsigned dt_type);
extern int ntfs_readdir( ntfs_inode *dir_ni, s64 *pos,
void *dirent, ntfs_filldir_t filldir );
extern int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
void *dirent, ntfs_filldir_t filldir);
ntfs_inode *ntfs_dir_parent_inode( ntfs_inode *ni );
ntfs_inode *ntfs_dir_parent_inode(ntfs_inode *ni);
int ntfs_get_ntfs_dos_name( ntfs_inode *ni, ntfs_inode *dir_ni,
char *value, size_t size );
int ntfs_set_ntfs_dos_name( ntfs_inode *ni, ntfs_inode *dir_ni,
const char *value, size_t size, int flags );
int ntfs_remove_ntfs_dos_name( ntfs_inode *ni, ntfs_inode *dir_ni );
int ntfs_get_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
char *value, size_t size);
int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
const char *value, size_t size, int flags);
int ntfs_remove_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni);
#if CACHE_INODE_SIZE
struct CACHED_GENERIC;
extern int ntfs_dir_inode_hash( const struct CACHED_GENERIC *cached );
extern int ntfs_dir_lookup_hash( const struct CACHED_GENERIC *cached );
extern int ntfs_dir_inode_hash(const struct CACHED_GENERIC *cached);
extern int ntfs_dir_lookup_hash(const struct CACHED_GENERIC *cached);
#endif

View File

@ -60,13 +60,12 @@
#ifdef HAVE_SETXATTR /* extended attributes interface required */
static ntfschar logged_utility_stream_name[] =
{
const_cpu_to_le16( '$' ),
const_cpu_to_le16( 'E' ),
const_cpu_to_le16( 'F' ),
const_cpu_to_le16( 'S' ),
const_cpu_to_le16( 0 )
static ntfschar logged_utility_stream_name[] = {
const_cpu_to_le16('$'),
const_cpu_to_le16('E'),
const_cpu_to_le16('F'),
const_cpu_to_le16('S'),
const_cpu_to_le16(0)
} ;
@ -74,64 +73,51 @@ static ntfschar logged_utility_stream_name[] =
* Get the ntfs EFS info into an extended attribute
*/
int ntfs_get_efs_info( ntfs_inode *ni, char *value, size_t size )
int ntfs_get_efs_info(ntfs_inode *ni, char *value, size_t size)
{
EFS_ATTR_HEADER *efs_info;
s64 attr_size = 0;
if ( ni )
{
if ( ni->flags & FILE_ATTR_ENCRYPTED )
{
efs_info = ( EFS_ATTR_HEADER* )ntfs_attr_readall( ni,
AT_LOGGED_UTILITY_STREAM, ( ntfschar* )NULL, 0,
&attr_size );
if ( efs_info
&& ( le32_to_cpu( efs_info->length ) == attr_size ) )
{
if ( attr_size <= ( s64 )size )
{
if ( value )
memcpy( value, efs_info, attr_size );
else
{
if (ni) {
if (ni->flags & FILE_ATTR_ENCRYPTED) {
efs_info = (EFS_ATTR_HEADER*)ntfs_attr_readall(ni,
AT_LOGGED_UTILITY_STREAM,(ntfschar*)NULL, 0,
&attr_size);
if (efs_info
&& (le32_to_cpu(efs_info->length) == attr_size)) {
if (attr_size <= (s64)size) {
if (value)
memcpy(value,efs_info,attr_size);
else {
errno = EFAULT;
attr_size = 0;
}
}
else if ( size )
{
} else
if (size) {
errno = ERANGE;
attr_size = 0;
}
free ( efs_info );
}
else
{
if ( efs_info )
{
free( efs_info );
ntfs_log_error( "Bad efs_info for inode %lld\n",
( long long )ni->mft_no );
}
else
{
ntfs_log_error( "Could not get efsinfo"
free (efs_info);
} else {
if (efs_info) {
free(efs_info);
ntfs_log_error("Bad efs_info for inode %lld\n",
(long long)ni->mft_no);
} else {
ntfs_log_error("Could not get efsinfo"
" for inode %lld\n",
( long long )ni->mft_no );
(long long)ni->mft_no);
}
errno = EIO;
attr_size = 0;
}
}
else
{
} else {
errno = ENODATA;
ntfs_log_trace( "Inode %lld is not encrypted\n",
( long long )ni->mft_no );
ntfs_log_trace("Inode %lld is not encrypted\n",
(long long)ni->mft_no);
}
}
return ( attr_size ? ( int )attr_size : -errno );
return (attr_size ? (int)attr_size : -errno);
}
/*
@ -147,7 +133,7 @@ int ntfs_get_efs_info( ntfs_inode *ni, char *value, size_t size )
* -1 if there is a problem.
*/
static int fixup_loop( ntfs_inode *ni )
static int fixup_loop(ntfs_inode *ni)
{
ntfs_attr_search_ctx *ctx;
ntfs_attr *na;
@ -159,80 +145,66 @@ static int fixup_loop( ntfs_inode *ni )
int res = 0;
maxcnt = 0;
do
{
do {
restart = FALSE;
ctx = ntfs_attr_get_search_ctx( ni, NULL );
if ( !ctx )
{
ntfs_log_error( "Failed to get ctx for efs\n" );
ctx = ntfs_attr_get_search_ctx(ni, NULL);
if (!ctx) {
ntfs_log_error("Failed to get ctx for efs\n");
res = -1;
}
cnt = 0;
while ( !restart && !res
&& !ntfs_attr_lookup( AT_DATA, NULL, 0,
CASE_SENSITIVE, 0, NULL, 0, ctx ) )
{
while (!restart && !res
&& !ntfs_attr_lookup(AT_DATA, NULL, 0,
CASE_SENSITIVE, 0, NULL, 0, ctx)) {
cnt++;
a = ctx->attr;
na = ntfs_attr_open( ctx->ntfs_ino, AT_DATA,
( ntfschar* )( ( u8* )a + le16_to_cpu( a->name_offset ) ),
a->name_length );
if ( !na )
{
ntfs_log_error( "can't open DATA Attribute\n" );
na = ntfs_attr_open(ctx->ntfs_ino, AT_DATA,
(ntfschar*)((u8*)a + le16_to_cpu(a->name_offset)),
a->name_length);
if (!na) {
ntfs_log_error("can't open DATA Attribute\n");
res = -1;
}
if ( na && !( ctx->attr->flags & ATTR_IS_ENCRYPTED ) )
{
if ( !NAttrNonResident( na )
&& ntfs_attr_make_non_resident( na, ctx ) )
{
if (na && !(ctx->attr->flags & ATTR_IS_ENCRYPTED)) {
if (!NAttrNonResident(na)
&& ntfs_attr_make_non_resident(na, ctx)) {
/*
* ntfs_attr_make_non_resident fails if there
* is not enough space in the MFT record.
* When this happens, force making non-resident
* so that some other attribute is expelled.
*/
if ( ntfs_attr_force_non_resident( na ) )
{
if (ntfs_attr_force_non_resident(na)) {
res = -1;
}
else
{
} else {
/* make sure there is some progress */
if ( cnt <= maxcnt )
{
if (cnt <= maxcnt) {
errno = EIO;
ntfs_log_error( "Multiple failure"
" making non resident\n" );
ntfs_log_error("Multiple failure"
" making non resident\n");
res = -1;
}
else
{
ntfs_attr_put_search_ctx( ctx );
ctx = ( ntfs_attr_search_ctx* )NULL;
} else {
ntfs_attr_put_search_ctx(ctx);
ctx = (ntfs_attr_search_ctx*)NULL;
restart = TRUE;
maxcnt = cnt;
}
}
}
if ( !restart && !res
&& ntfs_efs_fixup_attribute( ctx, na ) )
{
ntfs_log_error( "Error in efs fixup of AT_DATA Attribute\n" );
if (!restart && !res
&& ntfs_efs_fixup_attribute(ctx, na)) {
ntfs_log_error("Error in efs fixup of AT_DATA Attribute\n");
res = -1;
}
}
if ( na )
ntfs_attr_close( na );
if (na)
ntfs_attr_close(na);
}
first = FALSE;
}
while ( restart && !res );
if ( ctx )
ntfs_attr_put_search_ctx( ctx );
return ( res );
} while (restart && !res);
if (ctx)
ntfs_attr_put_search_ctx(ctx);
return (res);
}
/*
@ -241,8 +213,8 @@ static int fixup_loop( ntfs_inode *ni )
* Returns 0, or -1 if there is a problem
*/
int ntfs_set_efs_info( ntfs_inode *ni, const char *value, size_t size,
int flags )
int ntfs_set_efs_info(ntfs_inode *ni, const char *value, size_t size,
int flags)
{
int res;
@ -251,112 +223,91 @@ int ntfs_set_efs_info( ntfs_inode *ni, const char *value, size_t size,
const EFS_ATTR_HEADER *info_header;
res = 0;
if ( ni && value && size )
{
if ( ni->flags & ( FILE_ATTR_ENCRYPTED | FILE_ATTR_COMPRESSED ) )
{
if ( ni->flags & FILE_ATTR_ENCRYPTED )
{
ntfs_log_trace( "Inode %lld already encrypted\n",
( long long )ni->mft_no );
if (ni && value && size) {
if (ni->flags & (FILE_ATTR_ENCRYPTED | FILE_ATTR_COMPRESSED)) {
if (ni->flags & FILE_ATTR_ENCRYPTED) {
ntfs_log_trace("Inode %lld already encrypted\n",
(long long)ni->mft_no);
errno = EEXIST;
}
else
{
} else {
/*
* Possible problem : if encrypted file was
* restored in a compressed directory, it was
* restored as compressed.
* TODO : decompress first.
*/
ntfs_log_error( "Inode %lld cannot be encrypted and compressed\n",
( long long )ni->mft_no );
ntfs_log_error("Inode %lld cannot be encrypted and compressed\n",
(long long)ni->mft_no);
errno = EIO;
}
return -1;
}
info_header = ( const EFS_ATTR_HEADER* )value;
info_header = (const EFS_ATTR_HEADER*)value;
/* 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;
return ( -1 );
return (-1);
}
if ( !ntfs_attr_exist( ni, AT_LOGGED_UTILITY_STREAM,
( ntfschar* )NULL, 0 ) )
{
if ( !( flags & XATTR_REPLACE ) )
{
if (!ntfs_attr_exist(ni,AT_LOGGED_UTILITY_STREAM,
(ntfschar*)NULL,0)) {
if (!(flags & XATTR_REPLACE)) {
/*
* no logged_utility_stream attribute : add one,
* apparently, this does not feed the new value in
*/
res = ntfs_attr_add( ni, AT_LOGGED_UTILITY_STREAM,
logged_utility_stream_name, 4,
( u8* )NULL, ( s64 )size );
}
else
{
res = ntfs_attr_add(ni,AT_LOGGED_UTILITY_STREAM,
logged_utility_stream_name,4,
(u8*)NULL,(s64)size);
} else {
errno = ENODATA;
res = -1;
}
}
else
{
} else {
errno = EEXIST;
res = -1;
}
if ( !res )
{
if (!res) {
/*
* open and update the existing efs data
*/
na = ntfs_attr_open( ni, AT_LOGGED_UTILITY_STREAM,
logged_utility_stream_name, 4 );
if ( na )
{
na = ntfs_attr_open(ni, AT_LOGGED_UTILITY_STREAM,
logged_utility_stream_name, 4);
if (na) {
/* resize attribute */
res = ntfs_attr_truncate( na, ( s64 )size );
res = ntfs_attr_truncate(na, (s64)size);
/* overwrite value if any */
if ( !res && value )
{
written = ( int )ntfs_attr_pwrite( na,
( s64 )0, ( s64 )size, value );
if ( written != ( s64 )size )
{
ntfs_log_error( "Failed to "
"update efs data\n" );
if (!res && value) {
written = (int)ntfs_attr_pwrite(na,
(s64)0, (s64)size, value);
if (written != (s64)size) {
ntfs_log_error("Failed to "
"update efs data\n");
errno = EIO;
res = -1;
}
}
ntfs_attr_close( na );
}
else
ntfs_attr_close(na);
} else
res = -1;
}
if ( !res )
{
if (!res) {
/* 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 */
/* set encrypted flag, truncate attribute to match padding bytes */
if ( fixup_loop( ni ) )
if (fixup_loop(ni))
return -1;
}
ni->flags |= FILE_ATTR_ENCRYPTED;
NInoSetDirty( ni );
NInoFileNameSetDirty( ni );
NInoSetDirty(ni);
NInoFileNameSetDirty(ni);
}
}
else
{
} else {
errno = EINVAL;
res = -1;
}
return ( res ? -1 : 0 );
return (res ? -1 : 0);
}
/*
@ -370,7 +321,7 @@ int ntfs_set_efs_info( ntfs_inode *ni, const char *value, size_t size,
* -1 if failed (errno tells why)
*/
int ntfs_efs_fixup_attribute( ntfs_attr_search_ctx *ctx, ntfs_attr *na )
int ntfs_efs_fixup_attribute(ntfs_attr_search_ctx *ctx, ntfs_attr *na)
{
u64 newsize;
u64 oldsize;
@ -379,59 +330,48 @@ int ntfs_efs_fixup_attribute( ntfs_attr_search_ctx *ctx, ntfs_attr *na )
ntfs_inode *ni;
BOOL close_ctx = FALSE;
if ( !na )
{
ntfs_log_error( "no na specified for efs_fixup_attribute\n" );
if (!na) {
ntfs_log_error("no na specified for efs_fixup_attribute\n");
goto err_out;
}
if ( !ctx )
{
ctx = ntfs_attr_get_search_ctx( na->ni, NULL );
if ( !ctx )
{
ntfs_log_error( "Failed to get ctx for efs\n" );
if (!ctx) {
ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
if (!ctx) {
ntfs_log_error("Failed to get ctx for efs\n");
goto err_out;
}
close_ctx = TRUE;
if ( ntfs_attr_lookup( AT_DATA, na->name, na->name_len,
CASE_SENSITIVE, 0, NULL, 0, ctx ) )
{
ntfs_log_error( "attr lookup for AT_DATA attribute failed in efs fixup\n" );
if (ntfs_attr_lookup(AT_DATA, na->name, na->name_len,
CASE_SENSITIVE, 0, NULL, 0, ctx)) {
ntfs_log_error("attr lookup for AT_DATA attribute failed in efs fixup\n");
goto err_out;
}
}
else
{
if ( !NAttrNonResident( na ) )
{
ntfs_log_error( "Cannot make non resident"
" when a context has been allocated\n" );
} else {
if (!NAttrNonResident(na)) {
ntfs_log_error("Cannot make non resident"
" when a context has been allocated\n");
goto err_out;
}
}
/* no extra bytes are added to void attributes */
oldsize = na->data_size;
if ( oldsize )
{
if (oldsize) {
/* make sure size is valid for a raw encrypted stream */
if ( ( oldsize & 511 ) != 2 )
{
ntfs_log_error( "Bad raw encrypted stream\n" );
if ((oldsize & 511) != 2) {
ntfs_log_error("Bad raw encrypted stream\n");
goto err_out;
}
/* read padding length from last two bytes of attribute */
if ( ntfs_attr_pread( na, oldsize - 2, 2, &appended_bytes ) != 2 )
{
ntfs_log_error( "Error reading padding length\n" );
if (ntfs_attr_pread(na, oldsize - 2, 2, &appended_bytes) != 2) {
ntfs_log_error("Error reading padding length\n");
goto err_out;
}
padding_length = le16_to_cpu( appended_bytes );
if ( padding_length > 511 || padding_length > na->data_size - 2 )
{
padding_length = le16_to_cpu(appended_bytes);
if (padding_length > 511 || padding_length > na->data_size-2) {
errno = EINVAL;
ntfs_log_error( "invalid padding length %d for data_size %lld\n",
padding_length, ( long long )oldsize );
ntfs_log_error("invalid padding length %d for data_size %lld\n",
padding_length, (long long)oldsize);
goto err_out;
}
newsize = oldsize - padding_length - 2;
@ -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
* to avoid losing useful data
*/
if ( ntfs_attr_truncate( na, oldsize - 2 ) )
{
ntfs_log_error( "Error truncating attribute\n" );
if (ntfs_attr_truncate(na, oldsize - 2)) {
ntfs_log_error("Error truncating attribute\n");
goto err_out;
}
}
else
} else
newsize = 0;
/*
@ -455,53 +393,47 @@ int ntfs_efs_fixup_attribute( ntfs_attr_search_ctx *ctx, ntfs_attr *na )
* resizing down to zero may cause the attribute to be made
* resident.
*/
if ( !NAttrNonResident( na )
&& ntfs_attr_make_non_resident( na, ctx ) )
{
if ( !close_ctx
|| ntfs_attr_force_non_resident( na ) )
{
ntfs_log_error( "Error making DATA attribute non-resident\n" );
if (!NAttrNonResident(na)
&& ntfs_attr_make_non_resident(na, ctx)) {
if (!close_ctx
|| ntfs_attr_force_non_resident(na)) {
ntfs_log_error("Error making DATA attribute non-resident\n");
goto err_out;
}
else
{
} else {
/*
* must reinitialize context after forcing
* non-resident. We need a context for updating
* the state, and at this point, we are sure
* the context is not used elsewhere.
*/
ntfs_attr_reinit_search_ctx( ctx );
if ( ntfs_attr_lookup( AT_DATA, na->name, na->name_len,
CASE_SENSITIVE, 0, NULL, 0, ctx ) )
{
ntfs_log_error( "attr lookup for AT_DATA attribute failed in efs fixup\n" );
ntfs_attr_reinit_search_ctx(ctx);
if (ntfs_attr_lookup(AT_DATA, na->name, na->name_len,
CASE_SENSITIVE, 0, NULL, 0, ctx)) {
ntfs_log_error("attr lookup for AT_DATA attribute failed in efs fixup\n");
goto err_out;
}
}
}
ni = na->ni;
if ( !na->name_len )
{
if (!na->name_len) {
ni->data_size = newsize;
ni->allocated_size = na->allocated_size;
}
NInoSetDirty( ni );
NInoFileNameSetDirty( ni );
NInoSetDirty(ni);
NInoFileNameSetDirty(ni);
ctx->attr->data_size = cpu_to_le64( newsize );
if ( le64_to_cpu( ctx->attr->initialized_size ) > newsize )
ctx->attr->data_size = cpu_to_le64(newsize);
if (le64_to_cpu(ctx->attr->initialized_size) > newsize)
ctx->attr->initialized_size = ctx->attr->data_size;
ctx->attr->flags |= ATTR_IS_ENCRYPTED;
if ( close_ctx )
ntfs_attr_put_search_ctx( ctx );
if (close_ctx)
ntfs_attr_put_search_ctx(ctx);
return ( 0 );
return (0);
err_out:
if ( close_ctx && ctx )
ntfs_attr_put_search_ctx( ctx );
return ( -1 );
if (close_ctx && ctx)
ntfs_attr_put_search_ctx(ctx);
return (-1);
}
#endif /* HAVE_SETXATTR */

View File

@ -21,10 +21,10 @@
#ifndef EFS_H
#define EFS_H
int ntfs_get_efs_info( ntfs_inode *ni, char *value, size_t size );
int ntfs_get_efs_info(ntfs_inode *ni, char *value, size_t size);
int ntfs_set_efs_info( ntfs_inode *ni,
const char *value, size_t size, int flags );
int ntfs_efs_fixup_attribute( ntfs_attr_search_ctx *ctx, ntfs_attr *na );
int ntfs_set_efs_info(ntfs_inode *ni,
const char *value, size_t size, int flags);
int ntfs_efs_fixup_attribute(ntfs_attr_search_ctx *ctx, ntfs_attr *na);
#endif /* EFS_H */

View File

@ -66,93 +66,83 @@
#define DEV_FD(dev) ((gekko_fd *)dev->d_private)
/* Prototypes */
static s64 ntfs_device_gekko_io_readbytes( struct ntfs_device *dev, s64 offset, s64 count, void *buf );
static bool ntfs_device_gekko_io_readsectors( struct ntfs_device *dev, sec_t sector, sec_t numSectors, void* buffer );
static s64 ntfs_device_gekko_io_writebytes( struct ntfs_device *dev, s64 offset, s64 count, const void *buf );
static bool ntfs_device_gekko_io_writesectors( struct ntfs_device *dev, sec_t sector, sec_t numSectors, const void* buffer );
static s64 ntfs_device_gekko_io_readbytes(struct ntfs_device *dev, s64 offset, s64 count, void *buf);
static bool ntfs_device_gekko_io_readsectors(struct ntfs_device *dev, sec_t sector, sec_t numSectors, void* buffer);
static s64 ntfs_device_gekko_io_writebytes(struct ntfs_device *dev, s64 offset, s64 count, const void *buf);
static bool ntfs_device_gekko_io_writesectors(struct ntfs_device *dev, sec_t sector, sec_t numSectors, const void* buffer);
/**
*
*/
static int ntfs_device_gekko_io_open( struct ntfs_device *dev, int flags )
static int ntfs_device_gekko_io_open(struct ntfs_device *dev, int flags)
{
ntfs_log_trace( "dev %p, flags %i\n", dev, flags );
ntfs_log_trace("dev %p, flags %i\n", dev, flags);
// Get the device driver descriptor
gekko_fd *fd = DEV_FD( dev );
if ( !fd )
{
gekko_fd *fd = DEV_FD(dev);
if (!fd) {
errno = EBADF;
return -1;
}
// Get the device interface
const DISC_INTERFACE* interface = fd->interface;
if ( !interface )
{
if (!interface) {
errno = ENODEV;
return -1;
}
// Start the device interface and ensure that it is inserted
if ( !interface->startup() )
{
ntfs_log_perror( "device failed to start\n" );
if (!interface->startup()) {
ntfs_log_perror("device failed to start\n");
errno = EIO;
return -1;
}
if ( !interface->isInserted() )
{
ntfs_log_perror( "device media is not inserted\n" );
if (!interface->isInserted()) {
ntfs_log_perror("device media is not inserted\n");
errno = EIO;
return -1;
}
// Check that the device isn't already open (used by another volume?)
if ( NDevOpen( dev ) )
{
ntfs_log_perror( "device is busy (already open)\n" );
if (NDevOpen(dev)) {
ntfs_log_perror("device is busy (already open)\n");
errno = EBUSY;
return -1;
}
// Check that there is a valid NTFS boot sector at the start of the device
NTFS_BOOT_SECTOR boot;
if ( interface->readSectors( fd->startSector, 1, &boot ) )
{
if ( !ntfs_boot_sector_is_ntfs( &boot ) )
{
if (interface->readSectors(fd->startSector, 1, &boot)) {
if (!ntfs_boot_sector_is_ntfs(&boot)) {
errno = EINVALPART;
return -1;
}
}
else
{
ntfs_log_perror( "read failure @ sector %d\n", fd->startSector );
} else {
ntfs_log_perror("read failure @ sector %d\n", fd->startSector);
errno = EIO;
return -1;
}
// Parse the boot sector
fd->hiddenSectors = le32_to_cpu( boot.bpb.hidden_sectors );
fd->sectorSize = le16_to_cpu( boot.bpb.bytes_per_sector );
fd->sectorCount = sle64_to_cpu( boot.number_of_sectors );
fd->hiddenSectors = le32_to_cpu(boot.bpb.hidden_sectors);
fd->sectorSize = le16_to_cpu(boot.bpb.bytes_per_sector);
fd->sectorCount = sle64_to_cpu(boot.number_of_sectors);
fd->pos = 0;
fd->len = ( fd->sectorCount * fd->sectorSize );
fd->ino = le64_to_cpu( boot.volume_serial_number );
fd->len = (fd->sectorCount * fd->sectorSize);
fd->ino = le64_to_cpu(boot.volume_serial_number);
// Mark the device as read-only (if required)
if ( flags & O_RDONLY )
{
NDevSetReadOnly( dev );
if (flags & O_RDONLY) {
NDevSetReadOnly(dev);
}
// Create the cache
fd->cache = _NTFS_cache_constructor( fd->cachePageCount, fd->cachePageSize, interface, fd->startSector + fd->sectorCount, fd->sectorSize );
fd->cache = _NTFS_cache_constructor(fd->cachePageCount, fd->cachePageSize, interface, fd->startSector + fd->sectorCount, fd->sectorSize);
// Mark the device as open
NDevSetBlock( dev );
NDevSetOpen( dev );
NDevSetBlock(dev);
NDevSetOpen(dev);
return 0;
}
@ -160,47 +150,43 @@ static int ntfs_device_gekko_io_open( struct ntfs_device *dev, int flags )
/**
*
*/
static int ntfs_device_gekko_io_close( struct ntfs_device *dev )
static int ntfs_device_gekko_io_close(struct ntfs_device *dev)
{
ntfs_log_trace( "dev %p\n", dev );
ntfs_log_trace("dev %p\n", dev);
// Get the device driver descriptor
gekko_fd *fd = DEV_FD( dev );
if ( !fd )
{
gekko_fd *fd = DEV_FD(dev);
if (!fd) {
errno = EBADF;
return -1;
}
// Check that the device is actually open
if ( !NDevOpen( dev ) )
{
ntfs_log_perror( "device is not open\n" );
if (!NDevOpen(dev)) {
ntfs_log_perror("device is not open\n");
errno = EIO;
return -1;
}
// Mark the device as closed
NDevClearOpen( dev );
NDevClearBlock( dev );
NDevClearOpen(dev);
NDevClearBlock(dev);
// Flush the device (if dirty and not read-only)
if ( NDevDirty( dev ) && !NDevReadOnly( dev ) )
{
ntfs_log_debug( "device is dirty, will now sync\n" );
if (NDevDirty(dev) && !NDevReadOnly(dev)) {
ntfs_log_debug("device is dirty, will now sync\n");
// ...?
// Mark the device as clean
NDevClearDirty( dev );
NDevClearDirty(dev);
}
// Flush and destroy the cache (if required)
if ( fd->cache )
{
_NTFS_cache_flush( fd->cache );
_NTFS_cache_destructor( fd->cache );
if (fd->cache) {
_NTFS_cache_flush(fd->cache);
_NTFS_cache_destructor(fd->cache);
}
// Shutdown the device interface
@ -210,7 +196,7 @@ static int ntfs_device_gekko_io_close( struct ntfs_device *dev )
}*/
// Free the device driver private data
ntfs_free( dev->d_private );
ntfs_free(dev->d_private);
dev->d_private = NULL;
return 0;
@ -219,24 +205,22 @@ static int ntfs_device_gekko_io_close( struct ntfs_device *dev )
/**
*
*/
static s64 ntfs_device_gekko_io_seek( struct ntfs_device *dev, s64 offset, int whence )
static s64 ntfs_device_gekko_io_seek(struct ntfs_device *dev, s64 offset, int whence)
{
ntfs_log_trace( "dev %p, offset %Li, whence %i\n", dev, offset, whence );
ntfs_log_trace("dev %p, offset %Li, whence %i\n", dev, offset, whence);
// Get the device driver descriptor
gekko_fd *fd = DEV_FD( dev );
if ( !fd )
{
gekko_fd *fd = DEV_FD(dev);
if (!fd) {
errno = EBADF;
return -1;
}
// Set the current position on the device (in bytes)
switch ( whence )
{
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_END: fd->pos = MIN( MAX( fd->len + offset, 0 ), fd->len ); break;
switch(whence) {
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_END: fd->pos = MIN(MAX(fd->len + offset, 0), fd->len); break;
}
return 0;
@ -245,92 +229,86 @@ static s64 ntfs_device_gekko_io_seek( struct ntfs_device *dev, s64 offset, int w
/**
*
*/
static s64 ntfs_device_gekko_io_read( struct ntfs_device *dev, void *buf, s64 count )
static s64 ntfs_device_gekko_io_read(struct ntfs_device *dev, void *buf, s64 count)
{
return ntfs_device_gekko_io_readbytes( dev, DEV_FD( dev )->pos, count, buf );
return ntfs_device_gekko_io_readbytes(dev, DEV_FD(dev)->pos, count, buf);
}
/**
*
*/
static s64 ntfs_device_gekko_io_write( struct ntfs_device *dev, const void *buf, s64 count )
static s64 ntfs_device_gekko_io_write(struct ntfs_device *dev, const void *buf, s64 count)
{
return ntfs_device_gekko_io_writebytes( dev, DEV_FD( dev )->pos, count, buf );
return ntfs_device_gekko_io_writebytes(dev, DEV_FD(dev)->pos, count, buf);
}
/**
*
*/
static s64 ntfs_device_gekko_io_pread( struct ntfs_device *dev, void *buf, s64 count, s64 offset )
static s64 ntfs_device_gekko_io_pread(struct ntfs_device *dev, void *buf, s64 count, s64 offset)
{
return ntfs_device_gekko_io_readbytes( dev, offset, count, buf );
return ntfs_device_gekko_io_readbytes(dev, offset, count, buf);
}
/**
*
*/
static s64 ntfs_device_gekko_io_pwrite( struct ntfs_device *dev, const void *buf, s64 count, s64 offset )
static s64 ntfs_device_gekko_io_pwrite(struct ntfs_device *dev, const void *buf, s64 count, s64 offset)
{
return ntfs_device_gekko_io_writebytes( dev, offset, count, buf );
return ntfs_device_gekko_io_writebytes(dev, offset, count, buf);
}
/**
*
*/
static s64 ntfs_device_gekko_io_readbytes( struct ntfs_device *dev, s64 offset, s64 count, void *buf )
static s64 ntfs_device_gekko_io_readbytes(struct ntfs_device *dev, s64 offset, s64 count, void *buf)
{
ntfs_log_trace( "dev %p, offset %Li, count %Li\n", dev, offset, count );
ntfs_log_trace("dev %p, offset %Li, count %Li\n", dev, offset, count);
// Get the device driver descriptor
gekko_fd *fd = DEV_FD( dev );
if ( !fd )
{
gekko_fd *fd = DEV_FD(dev);
if (!fd) {
errno = EBADF;
return -1;
}
// Get the device interface
const DISC_INTERFACE* interface = fd->interface;
if ( !interface )
{
if (!interface) {
errno = ENODEV;
return -1;
}
if ( offset < 0 )
if(offset < 0)
{
errno = EROFS;
return -1;
}
if ( !count )
if(!count)
return 0;
sec_t sec_start = ( sec_t ) fd->startSector;
sec_t sec_start = (sec_t) fd->startSector;
sec_t sec_count = 1;
u32 buffer_offset = ( u32 ) ( offset % fd->sectorSize );
u32 buffer_offset = (u32) (offset % fd->sectorSize);
u8 *buffer = NULL;
// Determine the range of sectors required for this read
if ( offset > 0 )
{
sec_start += ( sec_t ) floor( ( f64 ) offset / ( f64 ) fd->sectorSize );
if (offset > 0) {
sec_start += (sec_t) floor((f64) offset / (f64) fd->sectorSize);
}
if ( buffer_offset + count > fd->sectorSize )
{
sec_count = ( sec_t ) ceil( ( f64 ) ( buffer_offset + count ) / ( f64 ) fd->sectorSize );
if (buffer_offset+count > 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 ( ( buffer_offset == 0 ) && ( count % fd->sectorSize == 0 ) )
{
if((buffer_offset == 0) && (count % fd->sectorSize == 0)) {
// Read from the device
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 ) )
{
ntfs_log_perror( "direct read failure @ 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)) {
ntfs_log_perror("direct read failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count);
errno = EIO;
return -1;
}
@ -341,27 +319,25 @@ static s64 ntfs_device_gekko_io_readbytes( struct ntfs_device *dev, s64 offset,
{
// Allocate a buffer to hold the read data
buffer = ( u8* )ntfs_alloc( sec_count * fd->sectorSize );
if ( !buffer )
{
buffer = (u8*)ntfs_alloc(sec_count * fd->sectorSize);
if (!buffer) {
errno = ENOMEM;
return -1;
}
// Read from the device
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 );
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_free( buffer );
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);
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_free(buffer);
errno = EIO;
return -1;
}
// Copy what was requested to the destination buffer
memcpy( buf, buffer + buffer_offset, count );
ntfs_free( buffer );
memcpy(buf, buffer + buffer_offset, count);
ntfs_free(buffer);
}
@ -371,65 +347,58 @@ static s64 ntfs_device_gekko_io_readbytes( struct ntfs_device *dev, s64 offset,
/**
*
*/
static s64 ntfs_device_gekko_io_writebytes( struct ntfs_device *dev, s64 offset, s64 count, const void *buf )
static s64 ntfs_device_gekko_io_writebytes(struct ntfs_device *dev, s64 offset, s64 count, const void *buf)
{
ntfs_log_trace( "dev %p, offset %lli, count %lli\n", dev, offset, count );
ntfs_log_trace("dev %p, offset %lli, count %lli\n", dev, offset, count);
// Get the device driver descriptor
gekko_fd *fd = DEV_FD( dev );
if ( !fd )
{
gekko_fd *fd = DEV_FD(dev);
if (!fd) {
errno = EBADF;
return -1;
}
// Get the device interface
const DISC_INTERFACE* interface = fd->interface;
if ( !interface )
{
if (!interface) {
errno = ENODEV;
return -1;
}
// Check that the device can be written to
if ( NDevReadOnly( dev ) )
{
if (NDevReadOnly(dev)) {
errno = EROFS;
return -1;
}
if ( count < 0 || offset < 0 )
{
if(count < 0 || offset < 0) {
errno = EROFS;
return -1;
}
if ( count == 0 )
if(count == 0)
return 0;
sec_t sec_start = ( sec_t ) fd->startSector;
sec_t sec_start = (sec_t) fd->startSector;
sec_t sec_count = 1;
u32 buffer_offset = ( u32 ) ( offset % fd->sectorSize );
u32 buffer_offset = (u32) (offset % fd->sectorSize);
u8 *buffer = NULL;
// Determine the range of sectors required for this write
if ( offset > 0 )
{
sec_start += ( sec_t ) floor( ( f64 ) offset / ( f64 ) fd->sectorSize );
if (offset > 0) {
sec_start += (sec_t) floor((f64) offset / (f64) fd->sectorSize);
}
if ( ( buffer_offset + count ) > fd->sectorSize )
{
sec_count = ( sec_t ) ceil( ( f64 ) ( buffer_offset + count ) / ( f64 ) fd->sectorSize );
if ((buffer_offset+count) > fd->sectorSize) {
sec_count = (sec_t) ceil((f64) (buffer_offset+count) / (f64) fd->sectorSize);
}
// If this write happens to be on the sector boundaries then do the write straight to disc
if ( ( buffer_offset == 0 ) && ( count % fd->sectorSize == 0 ) )
if((buffer_offset == 0) && (count % fd->sectorSize == 0))
{
// Write to the device
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 ) )
{
ntfs_log_perror( "direct write failure @ 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)) {
ntfs_log_perror("direct write failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count);
errno = EIO;
return -1;
}
@ -438,92 +407,86 @@ static s64 ntfs_device_gekko_io_writebytes( struct ntfs_device *dev, s64 offset,
else
{
// Allocate a buffer to hold the write data
buffer = ( u8 * ) ntfs_alloc( sec_count * fd->sectorSize );
if ( !buffer )
{
buffer = (u8 *) ntfs_alloc(sec_count * fd->sectorSize);
if (!buffer) {
errno = ENOMEM;
return -1;
}
// Read the first and last sectors of the buffer from disc (if required)
// NOTE: This is done because the data does not line up with the sector boundaries,
// 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 ) )
{
ntfs_log_perror( "read failure @ sector %d\n", sec_start );
ntfs_free( buffer );
if (!ntfs_device_gekko_io_readsectors(dev, sec_start, 1, buffer)) {
ntfs_log_perror("read failure @ sector %d\n", sec_start);
ntfs_free(buffer);
errno = EIO;
return -1;
}
}
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 ) ) )
{
ntfs_log_perror( "read failure @ sector %d\n", sec_start + sec_count - 1 );
ntfs_free( buffer );
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_free(buffer);
errno = EIO;
return -1;
}
}
// Copy the data into the write buffer
memcpy( buffer + buffer_offset, buf, count );
memcpy(buffer + buffer_offset, buf, count);
// Write to the device
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 ) )
{
ntfs_log_perror( "buffered write failure @ sector %d\n", sec_start );
ntfs_free( buffer );
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)) {
ntfs_log_perror("buffered write failure @ sector %d\n", sec_start);
ntfs_free(buffer);
errno = EIO;
return -1;
}
// Free the buffer
ntfs_free( buffer );
ntfs_free(buffer);
}
// Mark the device as dirty (if we actually wrote anything)
NDevSetDirty( dev );
NDevSetDirty(dev);
return count;
}
static bool ntfs_device_gekko_io_readsectors( struct ntfs_device *dev, sec_t sector, sec_t numSectors, void* buffer )
static bool ntfs_device_gekko_io_readsectors(struct ntfs_device *dev, sec_t sector, sec_t numSectors, void* buffer)
{
// Get the device driver descriptor
gekko_fd *fd = DEV_FD( dev );
if ( !fd )
{
gekko_fd *fd = DEV_FD(dev);
if (!fd) {
errno = EBADF;
return false;
}
// Read the sectors from disc (or cache, if enabled)
if ( fd->cache )
return _NTFS_cache_readSectors( fd->cache, sector, numSectors, buffer );
if (fd->cache)
return _NTFS_cache_readSectors(fd->cache, sector, numSectors, buffer);
else
return fd->interface->readSectors( sector, numSectors, buffer );
return fd->interface->readSectors(sector, numSectors, buffer);
return false;
}
static bool ntfs_device_gekko_io_writesectors( struct ntfs_device *dev, sec_t sector, sec_t numSectors, const void* buffer )
static bool ntfs_device_gekko_io_writesectors(struct ntfs_device *dev, sec_t sector, sec_t numSectors, const void* buffer)
{
// Get the device driver descriptor
gekko_fd *fd = DEV_FD( dev );
if ( !fd )
{
gekko_fd *fd = DEV_FD(dev);
if (!fd) {
errno = EBADF;
return false;
}
// Write the sectors to disc (or cache, if enabled)
if ( fd->cache )
return _NTFS_cache_writeSectors( fd->cache, sector, numSectors, buffer );
if (fd->cache)
return _NTFS_cache_writeSectors(fd->cache, sector, numSectors, buffer);
else
return fd->interface->writeSectors( sector, numSectors, buffer );
return fd->interface->writeSectors(sector, numSectors, buffer);
return false;
}
@ -531,26 +494,23 @@ static bool ntfs_device_gekko_io_writesectors( struct ntfs_device *dev, sec_t se
/**
*
*/
static int ntfs_device_gekko_io_sync( struct ntfs_device *dev )
static int ntfs_device_gekko_io_sync(struct ntfs_device *dev)
{
gekko_fd *fd = DEV_FD( dev );
ntfs_log_trace( "dev %p\n", dev );
gekko_fd *fd = DEV_FD(dev);
ntfs_log_trace("dev %p\n", dev);
// Check that the device can be written to
if ( NDevReadOnly( dev ) )
{
if (NDevReadOnly(dev)) {
errno = EROFS;
return -1;
}
// Mark the device as clean
NDevClearDirty( dev );
NDevClearDirty(dev);
// Flush any sectors in the disc cache (if required)
if ( fd->cache )
{
if ( !_NTFS_cache_flush( fd->cache ) )
{
if (fd->cache) {
if (!_NTFS_cache_flush(fd->cache)) {
errno = EIO;
return -1;
}
@ -562,29 +522,28 @@ static int ntfs_device_gekko_io_sync( struct ntfs_device *dev )
/**
*
*/
static int ntfs_device_gekko_io_stat( struct ntfs_device *dev, struct stat *buf )
static int ntfs_device_gekko_io_stat(struct ntfs_device *dev, struct stat *buf)
{
ntfs_log_trace( "dev %p, buf %p\n", dev, buf );
ntfs_log_trace("dev %p, buf %p\n", dev, buf);
// Get the device driver descriptor
gekko_fd *fd = DEV_FD( dev );
if ( !fd )
{
gekko_fd *fd = DEV_FD(dev);
if (!fd) {
errno = EBADF;
return -1;
}
// Short circuit cases were we don't actually have to do anything
if ( !buf )
if (!buf)
return 0;
// Build the device mode
mode_t mode = ( S_IFBLK ) |
( S_IRUSR | S_IRGRP | S_IROTH ) |
( ( !NDevReadOnly( dev ) ) ? ( S_IWUSR | S_IWGRP | S_IWOTH ) : 0 );
mode_t mode = (S_IFBLK) |
(S_IRUSR | S_IRGRP | S_IROTH) |
((!NDevReadOnly(dev)) ? (S_IWUSR | S_IWGRP | S_IWOTH) : 0);
// Zero out the stat buffer
memset( buf, 0, sizeof( struct stat ) );
memset(buf, 0, sizeof(struct stat));
// Build the device stats
buf->st_dev = fd->interface->ioType;
@ -600,76 +559,68 @@ static int ntfs_device_gekko_io_stat( struct ntfs_device *dev, struct stat *buf
/**
*
*/
static int ntfs_device_gekko_io_ioctl( struct ntfs_device *dev, int request, void *argp )
static int ntfs_device_gekko_io_ioctl(struct ntfs_device *dev, int request, void *argp)
{
ntfs_log_trace( "dev %p, request %i, argp %p\n", dev, request, argp );
ntfs_log_trace("dev %p, request %i, argp %p\n", dev, request, argp);
// Get the device driver descriptor
gekko_fd *fd = DEV_FD( dev );
if ( !fd )
{
gekko_fd *fd = DEV_FD(dev);
if (!fd) {
errno = EBADF;
return -1;
}
// Figure out which i/o control was requested
switch ( request )
{
switch (request) {
// Get block device size (sectors)
#if defined(BLKGETSIZE)
case BLKGETSIZE:
{
*( u32* )argp = fd->sectorCount;
#if defined(BLKGETSIZE)
case BLKGETSIZE: {
*(u32*)argp = fd->sectorCount;
return 0;
}
#endif
#endif
// Get block device size (bytes)
#if defined(BLKGETSIZE64)
case BLKGETSIZE64:
{
*( u64* )argp = ( fd->sectorCount * fd->sectorSize );
#if defined(BLKGETSIZE64)
case BLKGETSIZE64: {
*(u64*)argp = (fd->sectorCount * fd->sectorSize);
return 0;
}
#endif
#endif
// Get hard drive geometry
#if defined(HDIO_GETGEO)
case HDIO_GETGEO:
{
struct hd_geometry *geo = ( struct hd_geometry* )argp;
#if defined(HDIO_GETGEO)
case HDIO_GETGEO: {
struct hd_geometry *geo = (struct hd_geometry*)argp;
geo->sectors = 0;
geo->heads = 0;
geo->cylinders = 0;
geo->start = fd->hiddenSectors;
return -1;
}
#endif
#endif
// Get block device sector size (bytes)
#if defined(BLKSSZGET)
case BLKSSZGET:
{
*( int* )argp = fd->sectorSize;
#if defined(BLKSSZGET)
case BLKSSZGET: {
*(int*)argp = fd->sectorSize;
return 0;
}
#endif
#endif
// Set block device block size (bytes)
#if defined(BLKBSZSET)
case BLKBSZSET:
{
int sectorSize = *( int* )argp;
#if defined(BLKBSZSET)
case BLKBSZSET: {
int sectorSize = *(int*)argp;
fd->sectorSize = sectorSize;
return 0;
}
#endif
#endif
// Unimplemented ioctrl
default:
{
ntfs_log_perror( "Unimplemented ioctrl %i\n", request );
default: {
ntfs_log_perror("Unimplemented ioctrl %i\n", request);
errno = EOPNOTSUPP;
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.
*/
struct ntfs_device_operations ntfs_device_gekko_io_ops =
{
struct ntfs_device_operations ntfs_device_gekko_io_ops = {
.open = ntfs_device_gekko_io_open,
.close = ntfs_device_gekko_io_close,
.seek = ntfs_device_gekko_io_seek,

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -63,8 +63,8 @@
#define MAX_PARENT_VCN 32
typedef int ( *COLLATE )( ntfs_volume *vol, const void *data1, int len1,
const void *data2, int len2 );
typedef int (*COLLATE)(ntfs_volume *vol, const void *data1, int len1,
const void *data2, int len2);
/**
* struct ntfs_index_context -
@ -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
* to disk.
*/
typedef struct
{
typedef struct {
ntfs_inode *ni;
ntfschar *name;
u32 name_len;
@ -134,35 +133,35 @@ typedef struct
u8 vcn_size_bits;
} ntfs_index_context;
extern ntfs_index_context *ntfs_index_ctx_get( ntfs_inode *ni,
ntfschar *name, u32 name_len );
extern void ntfs_index_ctx_put( ntfs_index_context *ictx );
extern void ntfs_index_ctx_reinit( ntfs_index_context *ictx );
extern ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *ni,
ntfschar *name, u32 name_len);
extern void ntfs_index_ctx_put(ntfs_index_context *ictx);
extern void ntfs_index_ctx_reinit(ntfs_index_context *ictx);
extern int ntfs_index_lookup( const void *key, const int key_len,
ntfs_index_context *ictx ) __attribute_warn_unused_result__;
extern int ntfs_index_lookup(const void *key, const int key_len,
ntfs_index_context *ictx) __attribute_warn_unused_result__;
extern INDEX_ENTRY *ntfs_index_next( INDEX_ENTRY *ie,
ntfs_index_context *ictx );
extern INDEX_ENTRY *ntfs_index_next(INDEX_ENTRY *ie,
ntfs_index_context *ictx);
extern int ntfs_index_add_filename( ntfs_inode *ni, FILE_NAME_ATTR *fn,
MFT_REF mref );
extern int ntfs_index_remove( ntfs_inode *dir_ni, ntfs_inode *ni,
const void *key, const int keylen );
extern int ntfs_index_add_filename(ntfs_inode *ni, FILE_NAME_ATTR *fn,
MFT_REF mref);
extern int ntfs_index_remove(ntfs_inode *dir_ni, ntfs_inode *ni,
const void *key, const int keylen);
extern INDEX_ROOT *ntfs_index_root_get( ntfs_inode *ni, ATTR_RECORD *attr );
extern INDEX_ROOT *ntfs_index_root_get(ntfs_inode *ni, ATTR_RECORD *attr);
extern VCN ntfs_ie_get_vcn( INDEX_ENTRY *ie );
extern VCN ntfs_ie_get_vcn(INDEX_ENTRY *ie);
extern void ntfs_index_entry_mark_dirty( ntfs_index_context *ictx );
extern void ntfs_index_entry_mark_dirty(ntfs_index_context *ictx);
extern char *ntfs_ie_filename_get( INDEX_ENTRY *ie );
extern void ntfs_ie_filename_dump( INDEX_ENTRY *ie );
extern void ntfs_ih_filename_dump( INDEX_HEADER *ih );
extern char *ntfs_ie_filename_get(INDEX_ENTRY *ie);
extern void ntfs_ie_filename_dump(INDEX_ENTRY *ie);
extern void ntfs_ih_filename_dump(INDEX_HEADER *ih);
/* the following was added by JPA for use in security.c */
extern int ntfs_ie_add( ntfs_index_context *icx, INDEX_ENTRY *ie );
extern int ntfs_index_rm( ntfs_index_context *icx );
extern int ntfs_ie_add(ntfs_index_context *icx, INDEX_ENTRY *ie);
extern int ntfs_index_rm(ntfs_index_context *icx);
#endif /* _NTFS_INDEX_H */

File diff suppressed because it is too large Load Diff

View File

@ -40,8 +40,7 @@ typedef struct _ntfs_inode ntfs_inode;
* Defined bits for the state field in the ntfs_inode structure.
* (f) = files only, (d) = directories only
*/
typedef enum
{
typedef enum {
NI_Dirty, /* 1: Mft record needs to be written to disk. */
/* 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
* inode.
*/
struct _ntfs_inode
{
struct _ntfs_inode {
u64 mft_no; /* Inode / mft record number. */
MFT_RECORD *mrec; /* The actual mft record of the 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
attached extent inodes (0 if none), for
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 inodes of the extent mft
records belonging to this base
@ -169,8 +166,7 @@ struct _ntfs_inode
le64 usn;
};
typedef enum
{
typedef enum {
NTFS_UPDATE_ATIME = 1 << 0,
NTFS_UPDATE_MTIME = 1 << 1,
NTFS_UPDATE_CTIME = 1 << 2,
@ -179,48 +175,48 @@ typedef enum
#define NTFS_UPDATE_MCTIME (NTFS_UPDATE_MTIME | NTFS_UPDATE_CTIME)
#define NTFS_UPDATE_AMCTIME (NTFS_UPDATE_ATIME | NTFS_UPDATE_MCTIME)
extern ntfs_inode *ntfs_inode_base( ntfs_inode *ni );
extern ntfs_inode *ntfs_inode_base(ntfs_inode *ni);
extern ntfs_inode *ntfs_inode_allocate( ntfs_volume *vol );
extern ntfs_inode *ntfs_inode_allocate(ntfs_volume *vol);
extern ntfs_inode *ntfs_inode_open( ntfs_volume *vol, const MFT_REF mref );
extern ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref);
extern int ntfs_inode_close( ntfs_inode *ni );
extern int ntfs_inode_close_in_dir( ntfs_inode *ni, ntfs_inode *dir_ni );
extern int ntfs_inode_close(ntfs_inode *ni);
extern int ntfs_inode_close_in_dir(ntfs_inode *ni, ntfs_inode *dir_ni);
#if CACHE_NIDATA_SIZE
struct CACHED_GENERIC;
extern int ntfs_inode_real_close( ntfs_inode *ni );
extern void ntfs_inode_invalidate( ntfs_volume *vol, const MFT_REF mref );
extern void ntfs_inode_nidata_free( const struct CACHED_GENERIC *cached );
extern int ntfs_inode_nidata_hash( const struct CACHED_GENERIC *item );
extern int ntfs_inode_real_close(ntfs_inode *ni);
extern void ntfs_inode_invalidate(ntfs_volume *vol, const MFT_REF mref);
extern void ntfs_inode_nidata_free(const struct CACHED_GENERIC *cached);
extern int ntfs_inode_nidata_hash(const struct CACHED_GENERIC *item);
#endif
extern ntfs_inode *ntfs_extent_inode_open( ntfs_inode *base_ni,
const MFT_REF mref );
extern ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni,
const MFT_REF mref);
extern int ntfs_inode_attach_all_extents( ntfs_inode *ni );
extern int ntfs_inode_attach_all_extents(ntfs_inode *ni);
extern void ntfs_inode_mark_dirty( ntfs_inode *ni );
extern void ntfs_inode_mark_dirty(ntfs_inode *ni);
extern void ntfs_inode_update_times( ntfs_inode *ni, ntfs_time_update_flags mask );
extern void ntfs_inode_update_times(ntfs_inode *ni, ntfs_time_update_flags mask);
extern int ntfs_inode_sync( ntfs_inode *ni );
extern int ntfs_inode_sync(ntfs_inode *ni);
extern int ntfs_inode_add_attrlist( ntfs_inode *ni );
extern int ntfs_inode_add_attrlist(ntfs_inode *ni);
extern int ntfs_inode_free_space( ntfs_inode *ni, int size );
extern int ntfs_inode_free_space(ntfs_inode *ni, int size);
extern int ntfs_inode_badclus_bad( u64 mft_no, ATTR_RECORD *a );
extern int ntfs_inode_badclus_bad(u64 mft_no, ATTR_RECORD *a);
extern int ntfs_inode_get_times( ntfs_inode *ni, char *value, size_t size );
extern int ntfs_inode_get_times(ntfs_inode *ni, char *value, size_t size);
extern int ntfs_inode_set_times( ntfs_inode *ni, const char *value,
size_t size, int flags );
extern int ntfs_inode_set_times(ntfs_inode *ni, const char *value,
size_t size, int flags);
/* debugging */
#define debug_double_inode(num, type)

File diff suppressed because it is too large Load Diff

View File

@ -55,36 +55,35 @@
#define NTFS_LCNALLOC_BSIZE 4096
#define NTFS_LCNALLOC_SKIP NTFS_LCNALLOC_BSIZE
enum
{
enum {
ZONE_MFT = 1,
ZONE_DATA1 = 2,
ZONE_DATA2 = 4
} ;
static void ntfs_cluster_set_zone_pos( LCN start, LCN end, LCN *pos, LCN tc )
static void ntfs_cluster_set_zone_pos(LCN start, LCN end, LCN *pos, LCN tc)
{
ntfs_log_trace( "pos: %lld tc: %lld\n", ( long long )*pos, ( long long )tc );
ntfs_log_trace("pos: %lld tc: %lld\n", (long long)*pos, (long long)tc);
if ( tc >= end )
if (tc >= end)
*pos = start;
else if ( tc >= start )
else if (tc >= start)
*pos = tc;
}
static void ntfs_cluster_update_zone_pos( ntfs_volume *vol, u8 zone, LCN tc )
static void ntfs_cluster_update_zone_pos(ntfs_volume *vol, u8 zone, LCN tc)
{
ntfs_log_trace( "tc = %lld, zone = %d\n", ( long long )tc, zone );
ntfs_log_trace("tc = %lld, zone = %d\n", (long long)tc, zone);
if ( zone == ZONE_MFT )
ntfs_cluster_set_zone_pos( vol->mft_lcn, vol->mft_zone_end,
&vol->mft_zone_pos, tc );
else if ( zone == ZONE_DATA1 )
ntfs_cluster_set_zone_pos( vol->mft_zone_end, vol->nr_clusters,
&vol->data1_zone_pos, tc );
if (zone == ZONE_MFT)
ntfs_cluster_set_zone_pos(vol->mft_lcn, vol->mft_zone_end,
&vol->mft_zone_pos, tc);
else if (zone == ZONE_DATA1)
ntfs_cluster_set_zone_pos(vol->mft_zone_end, vol->nr_clusters,
&vol->data1_zone_pos, tc);
else /* zone == ZONE_DATA2 */
ntfs_cluster_set_zone_pos( 0, vol->mft_zone_start,
&vol->data2_zone_pos, tc );
ntfs_cluster_set_zone_pos(0, vol->mft_zone_start,
&vol->data2_zone_pos, tc);
}
/*
@ -93,86 +92,68 @@ static void ntfs_cluster_update_zone_pos( ntfs_volume *vol, u8 zone, LCN tc )
* Next allocation will reuse the freed cluster
*/
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 ( vol->full_zones & ZONE_DATA1 )
{
ntfs_cluster_update_zone_pos( vol, ZONE_DATA1, lcn );
if (lcn >= vol->mft_zone_end) {
if (vol->full_zones & ZONE_DATA1) {
ntfs_cluster_update_zone_pos(vol, ZONE_DATA1, lcn);
vol->full_zones &= ~ZONE_DATA1;
}
}
else if ( lcn < vol->mft_zone_start )
{
if ( vol->full_zones & ZONE_DATA2 )
{
ntfs_cluster_update_zone_pos( vol, ZONE_DATA2, lcn );
} else
if (lcn < vol->mft_zone_start) {
if (vol->full_zones & ZONE_DATA2) {
ntfs_cluster_update_zone_pos(vol, ZONE_DATA2, lcn);
vol->full_zones &= ~ZONE_DATA2;
}
}
else
{
if ( vol->full_zones & ZONE_MFT )
{
ntfs_cluster_update_zone_pos( vol, ZONE_MFT, lcn );
} else {
if (vol->full_zones & ZONE_MFT) {
ntfs_cluster_update_zone_pos(vol, ZONE_MFT, lcn);
vol->full_zones &= ~ZONE_MFT;
}
}
}
static s64 max_empty_bit_range( unsigned char *buf, int size )
static s64 max_empty_bit_range(unsigned char *buf, int size)
{
int i, j, run = 0;
int max_range = 0;
s64 start_pos = -1;
ntfs_log_trace( "Entering\n" );
ntfs_log_trace("Entering\n");
i = 0;
while ( i < size )
{
switch ( *buf )
{
while (i < size) {
switch (*buf) {
case 0 :
do
{
do {
buf++;
run += 8;
i++;
}
while ( ( i < size ) && !*buf );
} while ((i < size) && !*buf);
break;
case 255 :
if ( run > max_range )
{
if (run > max_range) {
max_range = run;
start_pos = ( s64 )i * 8 - run;
start_pos = (s64)i * 8 - run;
}
run = 0;
do
{
do {
buf++;
i++;
}
while ( ( i < size ) && ( *buf == 255 ) );
} while ((i < size) && (*buf == 255));
break;
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 ( run > max_range )
{
if (bit) {
if (run > max_range) {
max_range = run;
start_pos = ( s64 )i * 8 + ( j - run );
start_pos = (s64)i * 8 + (j - run);
}
run = 0;
}
else
} else
run++;
}
i++;
@ -181,31 +162,30 @@ static s64 max_empty_bit_range( unsigned char *buf, int size )
}
}
if ( run > max_range )
start_pos = ( s64 )i * 8 - run;
if (run > max_range)
start_pos = (s64)i * 8 - run;
return start_pos;
}
static int bitmap_writeback( ntfs_volume *vol, s64 pos, s64 size, void *b,
u8 *writeback )
static int bitmap_writeback(ntfs_volume *vol, s64 pos, s64 size, void *b,
u8 *writeback)
{
s64 written;
ntfs_log_trace( "Entering\n" );
ntfs_log_trace("Entering\n");
if ( !*writeback )
if (!*writeback)
return 0;
*writeback = 0;
written = ntfs_attr_pwrite( vol->lcnbmp_na, pos, size, b );
if ( written != size )
{
if ( !written )
written = ntfs_attr_pwrite(vol->lcnbmp_na, pos, size, b);
if (written != size) {
if (!written)
errno = EIO;
ntfs_log_perror( "Bitmap write error (%lld, %lld)",
( long long )pos, ( long long )size );
ntfs_log_perror("Bitmap write error (%lld, %lld)",
(long long)pos, (long long)size);
return -1;
}
@ -252,8 +232,8 @@ static int bitmap_writeback( ntfs_volume *vol, s64 pos, s64 size, void *b,
* 2) causes reduction in fragmentation.
* The code is not optimized for speed.
*/
runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
LCN start_lcn, const NTFS_CLUSTER_ALLOCATION_ZONES zone )
runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
LCN start_lcn, const NTFS_CLUSTER_ALLOCATION_ZONES zone)
{
LCN zone_start, zone_end; /* current search range */
LCN last_read_pos, lcn;
@ -268,26 +248,23 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
u8 has_guess, used_zone_pos;
int err = 0, rlpos, rlsize, buf_size;
ntfs_log_enter( "Entering with count = 0x%llx, start_lcn = 0x%llx, "
"zone = %s_ZONE.\n", ( long long )count, ( long long )
start_lcn, zone == MFT_ZONE ? "MFT" : "DATA" );
ntfs_log_enter("Entering with count = 0x%llx, start_lcn = 0x%llx, "
"zone = %s_ZONE.\n", (long long)count, (long long)
start_lcn, zone == MFT_ZONE ? "MFT" : "DATA");
if ( !vol || count < 0 || start_lcn < -1 || !vol->lcnbmp_na ||
( s8 )zone < FIRST_ZONE || zone > LAST_ZONE )
{
if (!vol || count < 0 || start_lcn < -1 || !vol->lcnbmp_na ||
(s8)zone < FIRST_ZONE || zone > LAST_ZONE) {
errno = EINVAL;
ntfs_log_perror( "%s: vcn: %lld, count: %lld, lcn: %lld",
__FUNCTION__, ( long long )start_vcn,
( long long )count, ( long long )start_lcn );
ntfs_log_perror("%s: vcn: %lld, count: %lld, lcn: %lld",
__FUNCTION__, (long long)start_vcn,
(long long)count, (long long)start_lcn);
goto out;
}
/* Return empty runlist if @count == 0 */
if ( !count )
{
rl = ntfs_malloc( 0x1000 );
if ( rl )
{
if (!count) {
rl = ntfs_malloc(0x1000);
if (rl) {
rl[0].vcn = start_vcn;
rl[0].lcn = LCN_RL_NOT_MAPPED;
rl[0].length = 0;
@ -295,8 +272,8 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
goto out;
}
buf = ntfs_malloc( NTFS_LCNALLOC_BSIZE );
if ( !buf )
buf = ntfs_malloc(NTFS_LCNALLOC_BSIZE);
if (!buf)
goto out;
/*
* If no @start_lcn was requested, use the current zone
@ -305,9 +282,8 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
has_guess = 1;
zone_start = start_lcn;
if ( zone_start < 0 )
{
if ( zone == DATA_ZONE )
if (zone_start < 0) {
if (zone == DATA_ZONE)
zone_start = vol->data1_zone_pos;
else
zone_start = vol->mft_zone_pos;
@ -316,22 +292,17 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
used_zone_pos = has_guess ? 0 : 1;
if ( !zone_start || zone_start == vol->mft_zone_start ||
zone_start == vol->mft_zone_end )
if (!zone_start || zone_start == vol->mft_zone_start ||
zone_start == vol->mft_zone_end)
pass = 2;
if ( zone_start < vol->mft_zone_start )
{
if (zone_start < vol->mft_zone_start) {
zone_end = vol->mft_zone_start;
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;
search_zone = ZONE_MFT;
}
else
{
} else {
zone_end = vol->nr_clusters;
search_zone = ZONE_DATA1;
}
@ -341,47 +312,40 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
/* Loop until all clusters are allocated. */
clusters = count;
rlpos = rlsize = 0;
while ( 1 )
{
while (1) {
/* check whether we have exhausted the current zone */
if ( search_zone & vol->full_zones )
if (search_zone & vol->full_zones)
goto zone_pass_done;
last_read_pos = bmp_pos >> 3;
br = ntfs_attr_pread( vol->lcnbmp_na, last_read_pos,
NTFS_LCNALLOC_BSIZE, buf );
if ( br <= 0 )
{
if ( !br )
br = ntfs_attr_pread(vol->lcnbmp_na, last_read_pos,
NTFS_LCNALLOC_BSIZE, buf);
if (br <= 0) {
if (!br)
goto zone_pass_done;
err = errno;
ntfs_log_perror( "Reading $BITMAP failed" );
ntfs_log_perror("Reading $BITMAP failed");
goto err_ret;
}
/*
* We might have read less than NTFS_LCNALLOC_BSIZE bytes
* if we are close to the end of the attribute.
*/
buf_size = ( int )br << 3;
buf_size = (int)br << 3;
lcn = bmp_pos & 7;
bmp_pos &= ~7;
writeback = 0;
while ( lcn < buf_size )
{
byte = buf + ( lcn >> 3 );
bit = 1 << ( lcn & 7 );
if ( has_guess )
{
if ( *byte & bit )
{
while (lcn < buf_size) {
byte = buf + (lcn >> 3);
bit = 1 << (lcn & 7);
if (has_guess) {
if (*byte & bit) {
has_guess = 0;
break;
}
}
else
{
lcn = max_empty_bit_range( buf, br );
if ( lcn < 0 )
} else {
lcn = max_empty_bit_range(buf, br);
if (lcn < 0)
break;
has_guess = 1;
continue;
@ -390,14 +354,12 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
/* First free bit is at lcn + bmp_pos. */
/* Reallocate memory if necessary. */
if ( ( rlpos + 2 ) * ( int )sizeof( runlist ) >= rlsize )
{
if ((rlpos + 2) * (int)sizeof(runlist) >= rlsize) {
rlsize += 4096;
trl = realloc( rl, rlsize );
if ( !trl )
{
trl = realloc(rl, rlsize);
if (!trl) {
err = ENOMEM;
ntfs_log_perror( "realloc() failed" );
ntfs_log_perror("realloc() failed");
goto wb_err_ret;
}
rl = trl;
@ -406,10 +368,10 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
/* Allocate the bitmap bit. */
*byte |= bit;
writeback = 1;
if ( vol->free_clusters <= 0 )
ntfs_log_error( "Non-positive free clusters "
if (vol->free_clusters <= 0)
ntfs_log_error("Non-positive free clusters "
"(%lld)!\n",
( long long )vol->free_clusters );
(long long)vol->free_clusters);
else
vol->free_clusters--;
@ -417,26 +379,22 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
* Coalesce with previous run if adjacent LCNs.
* Otherwise, append a new run.
*/
if ( prev_lcn == lcn + bmp_pos - prev_run_len && rlpos )
{
ntfs_log_debug( "Cluster coalesce: prev_lcn: "
if (prev_lcn == lcn + bmp_pos - prev_run_len && rlpos) {
ntfs_log_debug("Cluster coalesce: prev_lcn: "
"%lld lcn: %lld bmp_pos: %lld "
"prev_run_len: %lld\n",
( long long )prev_lcn,
( long long )lcn, ( long long )bmp_pos,
( long long )prev_run_len );
(long long)prev_lcn,
(long long)lcn, (long long)bmp_pos,
(long long)prev_run_len);
rl[rlpos - 1].length = ++prev_run_len;
}
else
{
if ( rlpos )
} else {
if (rlpos)
rl[rlpos].vcn = rl[rlpos - 1].vcn +
prev_run_len;
else
{
else {
rl[rlpos].vcn = start_vcn;
ntfs_log_debug( "Start_vcn: %lld\n",
( long long )start_vcn );
ntfs_log_debug("Start_vcn: %lld\n",
(long long)start_vcn);
}
rl[rlpos].lcn = prev_lcn = lcn + bmp_pos;
@ -444,68 +402,63 @@ runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
rlpos++;
}
ntfs_log_debug( "RUN: %-16lld %-16lld %-16lld\n",
( long long )rl[rlpos - 1].vcn,
( long long )rl[rlpos - 1].lcn,
( long long )rl[rlpos - 1].length );
ntfs_log_debug("RUN: %-16lld %-16lld %-16lld\n",
(long long)rl[rlpos - 1].vcn,
(long long)rl[rlpos - 1].lcn,
(long long)rl[rlpos - 1].length);
/* Done? */
if ( !--clusters )
{
if ( used_zone_pos )
ntfs_cluster_update_zone_pos( vol,
if (!--clusters) {
if (used_zone_pos)
ntfs_cluster_update_zone_pos(vol,
search_zone, lcn + bmp_pos + 1 +
NTFS_LCNALLOC_SKIP );
NTFS_LCNALLOC_SKIP);
goto done_ret;
}
lcn++;
}
if ( bitmap_writeback( vol, last_read_pos, br, buf, &writeback ) )
{
if (bitmap_writeback(vol, last_read_pos, br, buf, &writeback)) {
err = errno;
goto err_ret;
}
if ( !used_zone_pos )
{
if (!used_zone_pos) {
used_zone_pos = 1;
if ( search_zone == ZONE_MFT )
if (search_zone == ZONE_MFT)
zone_start = vol->mft_zone_pos;
else if ( search_zone == ZONE_DATA1 )
else if (search_zone == ZONE_DATA1)
zone_start = vol->data1_zone_pos;
else
zone_start = vol->data2_zone_pos;
if ( !zone_start || zone_start == vol->mft_zone_start ||
zone_start == vol->mft_zone_end )
if (!zone_start || zone_start == vol->mft_zone_start ||
zone_start == vol->mft_zone_end)
pass = 2;
bmp_pos = zone_start;
}
else
} else
bmp_pos += buf_size;
if ( bmp_pos < zone_end )
if (bmp_pos < zone_end)
continue;
zone_pass_done:
ntfs_log_trace( "Finished current zone pass(%i).\n", pass );
if ( pass == 1 )
{
ntfs_log_trace("Finished current zone pass(%i).\n", pass);
if (pass == 1) {
pass = 2;
zone_end = zone_start;
if ( search_zone == ZONE_MFT )
if (search_zone == ZONE_MFT)
zone_start = vol->mft_zone_start;
else if ( search_zone == ZONE_DATA1 )
else if (search_zone == ZONE_DATA1)
zone_start = vol->mft_zone_end;
else
zone_start = 0;
/* Sanity check. */
if ( zone_end < zone_start )
if (zone_end < zone_start)
zone_end = zone_start;
bmp_pos = zone_start;
@ -516,106 +469,98 @@ zone_pass_done:
done_zones_check:
done_zones |= search_zone;
vol->full_zones |= search_zone;
if ( done_zones < ( ZONE_MFT + ZONE_DATA1 + ZONE_DATA2 ) )
{
ntfs_log_trace( "Switching zone.\n" );
if (done_zones < (ZONE_MFT + ZONE_DATA1 + ZONE_DATA2)) {
ntfs_log_trace("Switching zone.\n");
pass = 1;
if ( rlpos )
{
if (rlpos) {
LCN tc = rl[rlpos - 1].lcn +
rl[rlpos - 1].length + NTFS_LCNALLOC_SKIP;
if ( used_zone_pos )
ntfs_cluster_update_zone_pos( vol,
search_zone, tc );
if (used_zone_pos)
ntfs_cluster_update_zone_pos(vol,
search_zone, tc);
}
switch ( search_zone )
{
switch (search_zone) {
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;
zone_start = vol->data1_zone_pos;
zone_end = vol->nr_clusters;
if ( zone_start == vol->mft_zone_end )
if (zone_start == vol->mft_zone_end)
pass = 2;
break;
case ZONE_DATA1:
ntfs_log_trace( "Zone switch: data1 -> data2\n" );
ntfs_log_trace("Zone switch: data1 -> data2\n");
search_zone = ZONE_DATA2;
zone_start = vol->data2_zone_pos;
zone_end = vol->mft_zone_start;
if ( !zone_start )
if (!zone_start)
pass = 2;
break;
case ZONE_DATA2:
if ( !( done_zones & ZONE_DATA1 ) )
{
ntfs_log_trace( "data2 -> data1\n" );
if (!(done_zones & ZONE_DATA1)) {
ntfs_log_trace("data2 -> data1\n");
goto switch_to_data1_zone;
}
ntfs_log_trace( "Zone switch: data2 -> mft\n" );
ntfs_log_trace("Zone switch: data2 -> mft\n");
search_zone = ZONE_MFT;
zone_start = vol->mft_zone_pos;
zone_end = vol->mft_zone_end;
if ( zone_start == vol->mft_zone_start )
if (zone_start == vol->mft_zone_start)
pass = 2;
break;
}
bmp_pos = zone_start;
if ( zone_start == zone_end )
{
ntfs_log_trace( "Empty zone, skipped.\n" );
if (zone_start == zone_end) {
ntfs_log_trace("Empty zone, skipped.\n");
goto done_zones_check;
}
continue;
}
ntfs_log_trace( "All zones are finished, no space on device.\n" );
ntfs_log_trace("All zones are finished, no space on device.\n");
err = ENOSPC;
goto err_ret;
}
done_ret:
ntfs_log_debug( "At done_ret.\n" );
ntfs_log_debug("At done_ret.\n");
/* Add runlist terminator element. */
rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
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;
goto err_ret;
}
done_err_ret:
free( buf );
if ( err )
{
free(buf);
if (err) {
errno = err;
ntfs_log_perror( "Failed to allocate clusters" );
ntfs_log_perror("Failed to allocate clusters");
rl = NULL;
}
out:
ntfs_log_leave( "\n" );
ntfs_log_leave("\n");
return rl;
wb_err_ret:
ntfs_log_trace( "At wb_err_ret.\n" );
if ( bitmap_writeback( vol, last_read_pos, br, buf, &writeback ) )
ntfs_log_trace("At wb_err_ret.\n");
if (bitmap_writeback(vol, last_read_pos, br, buf, &writeback))
err = errno;
err_ret:
ntfs_log_trace( "At err_ret.\n" );
if ( rl )
{
ntfs_log_trace("At err_ret.\n");
if (rl) {
/* Add runlist terminator element. */
rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
rl[rlpos].length = 0;
ntfs_debug_runlist_dump( rl );
ntfs_cluster_free_from_rl( vol, rl );
free( rl );
ntfs_debug_runlist_dump(rl);
ntfs_cluster_free_from_rl(vol, rl);
free(rl);
rl = NULL;
}
goto done_err_ret;
@ -628,29 +573,26 @@ err_ret:
*
* On success return 0 and on error return -1 with errno set to the error code.
*/
int ntfs_cluster_free_from_rl( ntfs_volume *vol, runlist *rl )
int ntfs_cluster_free_from_rl(ntfs_volume *vol, runlist *rl)
{
s64 nr_freed = 0;
int ret = -1;
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",
( long long )rl->lcn, ( long long )rl->length );
ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n",
(long long)rl->lcn, (long long)rl->length);
if ( rl->lcn >= 0 )
{
update_full_status( vol, rl->lcn );
if ( ntfs_bitmap_clear_run( vol->lcnbmp_na, rl->lcn,
rl->length ) )
{
ntfs_log_perror( "Cluster deallocation failed "
if (rl->lcn >= 0) {
update_full_status(vol,rl->lcn);
if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn,
rl->length)) {
ntfs_log_perror("Cluster deallocation failed "
"(%lld, %lld)",
( long long )rl->lcn,
( long long )rl->length );
(long long)rl->lcn,
(long long)rl->length);
goto out;
}
nr_freed += rl->length ;
@ -660,10 +602,10 @@ int ntfs_cluster_free_from_rl( ntfs_volume *vol, runlist *rl )
ret = 0;
out:
vol->free_clusters += nr_freed;
if ( vol->free_clusters > vol->nr_clusters )
ntfs_log_error( "Too many free clusters (%lld > %lld)!",
( long long )vol->free_clusters,
( long long )vol->nr_clusters );
if (vol->free_clusters > vol->nr_clusters)
ntfs_log_error("Too many free clusters (%lld > %lld)!",
(long long)vol->free_clusters,
(long long)vol->nr_clusters);
return ret;
}
@ -672,25 +614,23 @@ out:
* Returns 0 if successful
*/
int ntfs_cluster_free_basic( ntfs_volume *vol, s64 lcn, s64 count )
int ntfs_cluster_free_basic(ntfs_volume *vol, s64 lcn, s64 count)
{
s64 nr_freed = 0;
int ret = -1;
ntfs_log_trace( "Entering.\n" );
ntfs_log_trace( "Dealloc lcn 0x%llx, len 0x%llx.\n",
( long long )lcn, ( long long )count );
ntfs_log_trace("Entering.\n");
ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n",
(long long)lcn, (long long)count);
if ( lcn >= 0 )
{
update_full_status( vol, lcn );
if ( ntfs_bitmap_clear_run( vol->lcnbmp_na, lcn,
count ) )
{
ntfs_log_perror( "Cluster deallocation failed "
if (lcn >= 0) {
update_full_status(vol,lcn);
if (ntfs_bitmap_clear_run(vol->lcnbmp_na, lcn,
count)) {
ntfs_log_perror("Cluster deallocation failed "
"(%lld, %lld)",
( long long )lcn,
( long long )count );
(long long)lcn,
(long long)count);
goto out;
}
nr_freed += count;
@ -698,10 +638,10 @@ int ntfs_cluster_free_basic( ntfs_volume *vol, s64 lcn, s64 count )
ret = 0;
out:
vol->free_clusters += nr_freed;
if ( vol->free_clusters > vol->nr_clusters )
ntfs_log_error( "Too many free clusters (%lld > %lld)!",
( long long )vol->free_clusters,
( long long )vol->nr_clusters );
if (vol->free_clusters > vol->nr_clusters)
ntfs_log_error("Too many free clusters (%lld > %lld)!",
(long long)vol->free_clusters,
(long long)vol->nr_clusters);
return ret;
}
@ -721,37 +661,34 @@ out:
* On success return the number of deallocated clusters (not counting sparse
* clusters) and on error return -1 with errno set to the error code.
*/
int ntfs_cluster_free( ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count )
int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count)
{
runlist *rl;
s64 delta, to_free, nr_freed = 0;
int ret = -1;
if ( !vol || !vol->lcnbmp_na || !na || start_vcn < 0 ||
( count < 0 && count != -1 ) )
{
ntfs_log_trace( "Invalid arguments!\n" );
if (!vol || !vol->lcnbmp_na || !na || start_vcn < 0 ||
(count < 0 && count != -1)) {
ntfs_log_trace("Invalid arguments!\n");
errno = EINVAL;
return -1;
}
ntfs_log_enter( "Entering for inode 0x%llx, attr 0x%x, count 0x%llx, "
"vcn 0x%llx.\n", ( unsigned long long )na->ni->mft_no,
na->type, ( long long )count, ( long long )start_vcn );
ntfs_log_enter("Entering for inode 0x%llx, attr 0x%x, count 0x%llx, "
"vcn 0x%llx.\n", (unsigned long long)na->ni->mft_no,
na->type, (long long)count, (long long)start_vcn);
rl = ntfs_attr_find_vcn( na, start_vcn );
if ( !rl )
{
if ( errno == ENOENT )
rl = ntfs_attr_find_vcn(na, start_vcn);
if (!rl) {
if (errno == ENOENT)
ret = 0;
goto leave;
}
if ( rl->lcn < 0 && rl->lcn != LCN_HOLE )
{
if (rl->lcn < 0 && rl->lcn != LCN_HOLE) {
errno = EIO;
ntfs_log_perror( "%s: Unexpected lcn (%lld)", __FUNCTION__,
( long long )rl->lcn );
ntfs_log_perror("%s: Unexpected lcn (%lld)", __FUNCTION__,
(long long)rl->lcn);
goto leave;
}
@ -760,81 +697,75 @@ int ntfs_cluster_free( ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count
/* The number of clusters in this run that need freeing. */
to_free = rl->length - delta;
if ( count >= 0 && to_free > count )
if (count >= 0 && 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. */
update_full_status( vol, rl->lcn + delta );
if ( ntfs_bitmap_clear_run( vol->lcnbmp_na, rl->lcn + delta,
to_free ) )
update_full_status(vol,rl->lcn + delta);
if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn + delta,
to_free))
goto leave;
nr_freed = to_free;
}
/* Go to the next run and adjust the number of clusters left to free. */
++rl;
if ( count >= 0 )
if (count >= 0)
count -= to_free;
/*
* Loop over the remaining runs, using @count as a capping value, and
* free them.
*/
for ( ; rl->length && count != 0; ++rl )
{
for (; rl->length && count != 0; ++rl) {
// FIXME: Need to try ntfs_attr_map_runlist() for attribute
// 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)
errno = EIO;
ntfs_log_perror( "%s: Invalid lcn (%lli)",
__FUNCTION__, ( long long )rl->lcn );
ntfs_log_perror("%s: Invalid lcn (%lli)",
__FUNCTION__, (long long)rl->lcn);
goto out;
}
/* The number of clusters in this run that need freeing. */
to_free = rl->length;
if ( count >= 0 && to_free > count )
if (count >= 0 && to_free > count)
to_free = count;
if ( rl->lcn != LCN_HOLE )
{
update_full_status( vol, rl->lcn );
if ( ntfs_bitmap_clear_run( vol->lcnbmp_na, rl->lcn,
to_free ) )
{
if (rl->lcn != LCN_HOLE) {
update_full_status(vol,rl->lcn);
if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn,
to_free)) {
// FIXME: Eeek! We need rollback! (AIA)
ntfs_log_perror( "%s: Clearing bitmap run failed",
__FUNCTION__ );
ntfs_log_perror("%s: Clearing bitmap run failed",
__FUNCTION__);
goto out;
}
nr_freed += to_free;
}
if ( count >= 0 )
if (count >= 0)
count -= to_free;
}
if ( count != -1 && count != 0 )
{
if (count != -1 && count != 0) {
// FIXME: Eeek! BUG()
errno = EIO;
ntfs_log_perror( "%s: count still not zero (%lld)", __FUNCTION__,
( long long )count );
ntfs_log_perror("%s: count still not zero (%lld)", __FUNCTION__,
(long long)count);
goto out;
}
ret = nr_freed;
out:
vol->free_clusters += nr_freed ;
if ( vol->free_clusters > vol->nr_clusters )
ntfs_log_error( "Too many free clusters (%lld > %lld)!",
( long long )vol->free_clusters,
( long long )vol->nr_clusters );
if (vol->free_clusters > vol->nr_clusters)
ntfs_log_error("Too many free clusters (%lld > %lld)!",
(long long)vol->free_clusters,
(long long)vol->nr_clusters);
leave:
ntfs_log_leave( "\n" );
ntfs_log_leave("\n");
return ret;
}

View File

@ -31,22 +31,21 @@
/**
* enum NTFS_CLUSTER_ALLOCATION_ZONES -
*/
typedef enum
{
typedef enum {
FIRST_ZONE = 0, /* For sanity checking. */
MFT_ZONE = 0, /* Allocate from $MFT zone. */
DATA_ZONE = 1, /* Allocate from $DATA zone. */
LAST_ZONE = 1, /* For sanity checking. */
} NTFS_CLUSTER_ALLOCATION_ZONES;
extern runlist *ntfs_cluster_alloc( ntfs_volume *vol, VCN start_vcn, s64 count,
LCN start_lcn, const NTFS_CLUSTER_ALLOCATION_ZONES zone );
extern runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
LCN start_lcn, const NTFS_CLUSTER_ALLOCATION_ZONES zone);
extern int ntfs_cluster_free_from_rl( ntfs_volume *vol, runlist *rl );
extern int ntfs_cluster_free_basic( ntfs_volume *vol, s64 lcn, s64 count );
extern int ntfs_cluster_free_from_rl(ntfs_volume *vol, runlist *rl);
extern int ntfs_cluster_free_basic(ntfs_volume *vol, s64 lcn, s64 count);
extern int ntfs_cluster_free( ntfs_volume *vol, ntfs_attr *na, VCN start_vcn,
s64 count );
extern int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn,
s64 count);
#endif /* defined _NTFS_LCNALLOC_H */

View File

@ -54,73 +54,67 @@
* This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not
* require the full restart page.
*/
static BOOL ntfs_check_restart_page_header( RESTART_PAGE_HEADER *rp, s64 pos )
static BOOL ntfs_check_restart_page_header(RESTART_PAGE_HEADER *rp, s64 pos)
{
u32 logfile_system_page_size, logfile_log_page_size;
u16 ra_ofs, usa_count, usa_ofs, usa_end = 0;
BOOL have_usa = TRUE;
ntfs_log_trace( "Entering.\n" );
ntfs_log_trace("Entering.\n");
/*
* If the system or log page sizes are smaller than the ntfs block size
* or either is not a power of 2 we cannot handle this log file.
*/
logfile_system_page_size = le32_to_cpu( rp->system_page_size );
logfile_log_page_size = le32_to_cpu( rp->log_page_size );
if ( logfile_system_page_size < NTFS_BLOCK_SIZE ||
logfile_system_page_size = le32_to_cpu(rp->system_page_size);
logfile_log_page_size = le32_to_cpu(rp->log_page_size);
if (logfile_system_page_size < NTFS_BLOCK_SIZE ||
logfile_log_page_size < NTFS_BLOCK_SIZE ||
logfile_system_page_size &
( logfile_system_page_size - 1 ) ||
logfile_log_page_size & ( logfile_log_page_size - 1 ) )
{
ntfs_log_error( "$LogFile uses unsupported page size.\n" );
(logfile_system_page_size - 1) ||
logfile_log_page_size & (logfile_log_page_size - 1)) {
ntfs_log_error("$LogFile uses unsupported page size.\n");
return FALSE;
}
/*
* We must be either at !pos (1st restart page) or at pos = system page
* size (2nd restart page).
*/
if ( pos && pos != logfile_system_page_size )
{
ntfs_log_error( "Found restart area in incorrect "
"position in $LogFile.\n" );
if (pos && pos != logfile_system_page_size) {
ntfs_log_error("Found restart area in incorrect "
"position in $LogFile.\n");
return FALSE;
}
/* We only know how to handle version 1.1. */
if ( sle16_to_cpu( rp->major_ver ) != 1 ||
sle16_to_cpu( rp->minor_ver ) != 1 )
{
ntfs_log_error( "$LogFile version %i.%i is not "
if (sle16_to_cpu(rp->major_ver) != 1 ||
sle16_to_cpu(rp->minor_ver) != 1) {
ntfs_log_error("$LogFile version %i.%i is not "
"supported. (This driver supports version "
"1.1 only.)\n", ( int )sle16_to_cpu( rp->major_ver ),
( int )sle16_to_cpu( rp->minor_ver ) );
"1.1 only.)\n", (int)sle16_to_cpu(rp->major_ver),
(int)sle16_to_cpu(rp->minor_ver));
return FALSE;
}
/*
* If chkdsk has been run the restart page may not be protected by an
* 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;
goto skip_usa_checks;
}
/* Verify the size of the update sequence array. */
usa_count = 1 + ( logfile_system_page_size >> NTFS_BLOCK_SIZE_BITS );
if ( usa_count != le16_to_cpu( rp->usa_count ) )
{
ntfs_log_error( "$LogFile restart page specifies "
"inconsistent update sequence array count.\n" );
usa_count = 1 + (logfile_system_page_size >> NTFS_BLOCK_SIZE_BITS);
if (usa_count != le16_to_cpu(rp->usa_count)) {
ntfs_log_error("$LogFile restart page specifies "
"inconsistent update sequence array count.\n");
return FALSE;
}
/* Verify the position of the update sequence array. */
usa_ofs = le16_to_cpu( rp->usa_ofs );
usa_end = usa_ofs + usa_count * sizeof( u16 );
if ( usa_ofs < sizeof( RESTART_PAGE_HEADER ) ||
usa_end > NTFS_BLOCK_SIZE - sizeof( u16 ) )
{
ntfs_log_error( "$LogFile restart page specifies "
"inconsistent update sequence array offset.\n" );
usa_ofs = le16_to_cpu(rp->usa_ofs);
usa_end = usa_ofs + usa_count * sizeof(u16);
if (usa_ofs < sizeof(RESTART_PAGE_HEADER) ||
usa_end > NTFS_BLOCK_SIZE - sizeof(u16)) {
ntfs_log_error("$LogFile restart page specifies "
"inconsistent update sequence array offset.\n");
return FALSE;
}
skip_usa_checks:
@ -130,26 +124,24 @@ skip_usa_checks:
* - after the update sequence array, and
* - within the system page size.
*/
ra_ofs = le16_to_cpu( rp->restart_area_offset );
if ( ra_ofs & 7 || ( have_usa ? ra_ofs < usa_end :
ra_ofs < sizeof( RESTART_PAGE_HEADER ) ) ||
ra_ofs > logfile_system_page_size )
{
ntfs_log_error( "$LogFile restart page specifies "
"inconsistent restart area offset.\n" );
ra_ofs = le16_to_cpu(rp->restart_area_offset);
if (ra_ofs & 7 || (have_usa ? ra_ofs < usa_end :
ra_ofs < sizeof(RESTART_PAGE_HEADER)) ||
ra_ofs > logfile_system_page_size) {
ntfs_log_error("$LogFile restart page specifies "
"inconsistent restart area offset.\n");
return FALSE;
}
/*
* Only restart pages modified by chkdsk are allowed to have chkdsk_lsn
* set.
*/
if ( !ntfs_is_chkd_record( rp->magic ) && sle64_to_cpu( rp->chkdsk_lsn ) )
{
ntfs_log_error( "$LogFile restart page is not modified "
"by chkdsk but a chkdsk LSN is specified.\n" );
if (!ntfs_is_chkd_record(rp->magic) && sle64_to_cpu(rp->chkdsk_lsn)) {
ntfs_log_error("$LogFile restart page is not modified "
"by chkdsk but a chkdsk LSN is specified.\n");
return FALSE;
}
ntfs_log_trace( "Done.\n" );
ntfs_log_trace("Done.\n");
return TRUE;
}
@ -166,26 +158,25 @@ skip_usa_checks:
* This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not
* require the full restart page.
*/
static BOOL ntfs_check_restart_area( RESTART_PAGE_HEADER *rp )
static BOOL ntfs_check_restart_area(RESTART_PAGE_HEADER *rp)
{
u64 file_size;
RESTART_AREA *ra;
u16 ra_ofs, ra_len, ca_ofs;
u8 fs_bits;
ntfs_log_trace( "Entering.\n" );
ra_ofs = le16_to_cpu( rp->restart_area_offset );
ra = ( RESTART_AREA* )( ( u8* )rp + ra_ofs );
ntfs_log_trace("Entering.\n");
ra_ofs = le16_to_cpu(rp->restart_area_offset);
ra = (RESTART_AREA*)((u8*)rp + ra_ofs);
/*
* Everything before ra->file_size must be before the first word
* protected by an update sequence number. This ensures that it is
* safe to access ra->client_array_offset.
*/
if ( ra_ofs + offsetof( RESTART_AREA, file_size ) >
NTFS_BLOCK_SIZE - sizeof( u16 ) )
{
ntfs_log_error( "$LogFile restart area specifies "
"inconsistent file offset.\n" );
if (ra_ofs + offsetof(RESTART_AREA, file_size) >
NTFS_BLOCK_SIZE - sizeof(u16)) {
ntfs_log_error("$LogFile restart area specifies "
"inconsistent file offset.\n");
return FALSE;
}
/*
@ -195,13 +186,12 @@ static BOOL ntfs_check_restart_area( RESTART_PAGE_HEADER *rp )
* restart area elements safely. Also, the client array offset must be
* aligned to an 8-byte boundary.
*/
ca_ofs = le16_to_cpu( ra->client_array_offset );
if ( ( ( ca_ofs + 7 ) & ~7 ) != ca_ofs ||
ra_ofs + ca_ofs > ( u16 )( NTFS_BLOCK_SIZE -
sizeof( u16 ) ) )
{
ntfs_log_error( "$LogFile restart area specifies "
"inconsistent client array offset.\n" );
ca_ofs = le16_to_cpu(ra->client_array_offset);
if (((ca_ofs + 7) & ~7) != ca_ofs ||
ra_ofs + ca_ofs > (u16)(NTFS_BLOCK_SIZE -
sizeof(u16))) {
ntfs_log_error("$LogFile restart area specifies "
"inconsistent client array offset.\n");
return FALSE;
}
/*
@ -209,17 +199,16 @@ static BOOL ntfs_check_restart_area( RESTART_PAGE_HEADER *rp )
* calculated manually and as specified by ra->restart_area_length.
* Also, the calculated length must not exceed the specified length.
*/
ra_len = ca_ofs + le16_to_cpu( ra->log_clients ) *
sizeof( LOG_CLIENT_RECORD );
if ( ( u32 )( ra_ofs + ra_len ) > le32_to_cpu( rp->system_page_size ) ||
( u32 )( ra_ofs + le16_to_cpu( ra->restart_area_length ) ) >
le32_to_cpu( rp->system_page_size ) ||
ra_len > le16_to_cpu( ra->restart_area_length ) )
{
ntfs_log_error( "$LogFile restart area is out of bounds "
ra_len = ca_ofs + le16_to_cpu(ra->log_clients) *
sizeof(LOG_CLIENT_RECORD);
if ((u32)(ra_ofs + ra_len) > le32_to_cpu(rp->system_page_size) ||
(u32)(ra_ofs + le16_to_cpu(ra->restart_area_length)) >
le32_to_cpu(rp->system_page_size) ||
ra_len > le16_to_cpu(ra->restart_area_length)) {
ntfs_log_error("$LogFile restart area is out of bounds "
"of the system page size specified by the "
"restart page header and/or the specified "
"restart area length is inconsistent.\n" );
"restart area length is inconsistent.\n");
return FALSE;
}
/*
@ -227,51 +216,46 @@ static BOOL ntfs_check_restart_area( RESTART_PAGE_HEADER *rp )
* LOGFILE_NO_CLIENT or less than ra->log_clients or they are
* overflowing the client array.
*/
if ( ( ra->client_free_list != LOGFILE_NO_CLIENT &&
le16_to_cpu( ra->client_free_list ) >=
le16_to_cpu( ra->log_clients ) ) ||
( ra->client_in_use_list != LOGFILE_NO_CLIENT &&
le16_to_cpu( ra->client_in_use_list ) >=
le16_to_cpu( ra->log_clients ) ) )
{
ntfs_log_error( "$LogFile restart area specifies "
"overflowing client free and/or in use lists.\n" );
if ((ra->client_free_list != LOGFILE_NO_CLIENT &&
le16_to_cpu(ra->client_free_list) >=
le16_to_cpu(ra->log_clients)) ||
(ra->client_in_use_list != LOGFILE_NO_CLIENT &&
le16_to_cpu(ra->client_in_use_list) >=
le16_to_cpu(ra->log_clients))) {
ntfs_log_error("$LogFile restart area specifies "
"overflowing client free and/or in use lists.\n");
return FALSE;
}
/*
* Check ra->seq_number_bits against ra->file_size for consistency.
* We cannot just use ffs() because the file size is not a power of 2.
*/
file_size = ( u64 )sle64_to_cpu( ra->file_size );
file_size = (u64)sle64_to_cpu(ra->file_size);
fs_bits = 0;
while ( file_size )
{
while (file_size) {
file_size >>= 1;
fs_bits++;
}
if ( le32_to_cpu( ra->seq_number_bits ) != ( u32 )( 67 - fs_bits ) )
{
ntfs_log_error( "$LogFile restart area specifies "
"inconsistent sequence number bits.\n" );
if (le32_to_cpu(ra->seq_number_bits) != (u32)(67 - fs_bits)) {
ntfs_log_error("$LogFile restart area specifies "
"inconsistent sequence number bits.\n");
return FALSE;
}
/* The log record header length must be a multiple of 8. */
if ( ( ( le16_to_cpu( ra->log_record_header_length ) + 7 ) & ~7 ) !=
le16_to_cpu( ra->log_record_header_length ) )
{
ntfs_log_error( "$LogFile restart area specifies "
"inconsistent log record header length.\n" );
if (((le16_to_cpu(ra->log_record_header_length) + 7) & ~7) !=
le16_to_cpu(ra->log_record_header_length)) {
ntfs_log_error("$LogFile restart area specifies "
"inconsistent log record header length.\n");
return FALSE;
}
/* Ditto for the log page data offset. */
if ( ( ( le16_to_cpu( ra->log_page_data_offset ) + 7 ) & ~7 ) !=
le16_to_cpu( ra->log_page_data_offset ) )
{
ntfs_log_error( "$LogFile restart area specifies "
"inconsistent log page data offset.\n" );
if (((le16_to_cpu(ra->log_page_data_offset) + 7) & ~7) !=
le16_to_cpu(ra->log_page_data_offset)) {
ntfs_log_error("$LogFile restart area specifies "
"inconsistent log page data offset.\n");
return FALSE;
}
ntfs_log_trace( "Done.\n" );
ntfs_log_trace("Done.\n");
return TRUE;
}
@ -289,17 +273,17 @@ static BOOL ntfs_check_restart_area( RESTART_PAGE_HEADER *rp )
* function needs @rp->system_page_size bytes in @rp, i.e. it requires the full
* restart page and the page must be multi sector transfer deprotected.
*/
static BOOL ntfs_check_log_client_array( RESTART_PAGE_HEADER *rp )
static BOOL ntfs_check_log_client_array(RESTART_PAGE_HEADER *rp)
{
RESTART_AREA *ra;
LOG_CLIENT_RECORD *ca, *cr;
u16 nr_clients, idx;
BOOL in_free_list, idx_is_first;
ntfs_log_trace( "Entering.\n" );
ra = ( RESTART_AREA* )( ( u8* )rp + le16_to_cpu( rp->restart_area_offset ) );
ca = ( LOG_CLIENT_RECORD* )( ( u8* )ra +
le16_to_cpu( ra->client_array_offset ) );
ntfs_log_trace("Entering.\n");
ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset));
ca = (LOG_CLIENT_RECORD*)((u8*)ra +
le16_to_cpu(ra->client_array_offset));
/*
* Check the ra->client_free_list first and then check the
* ra->client_in_use_list. Check each of the log client records in
@ -308,36 +292,33 @@ static BOOL ntfs_check_log_client_array( RESTART_PAGE_HEADER *rp )
* visited as there cannot be more than ra->log_clients records and
* that way we detect eventual loops in within a list.
*/
nr_clients = le16_to_cpu( ra->log_clients );
idx = le16_to_cpu( ra->client_free_list );
nr_clients = le16_to_cpu(ra->log_clients);
idx = le16_to_cpu(ra->client_free_list);
in_free_list = TRUE;
check_list:
for ( idx_is_first = TRUE; idx != LOGFILE_NO_CLIENT_CPU; nr_clients--,
idx = le16_to_cpu( cr->next_client ) )
{
if ( !nr_clients || idx >= le16_to_cpu( ra->log_clients ) )
for (idx_is_first = TRUE; idx != LOGFILE_NO_CLIENT_CPU; nr_clients--,
idx = le16_to_cpu(cr->next_client)) {
if (!nr_clients || idx >= le16_to_cpu(ra->log_clients))
goto err_out;
/* Set @cr to the current log client record. */
cr = ca + idx;
/* The first log client record must not have a prev_client. */
if ( idx_is_first )
{
if ( cr->prev_client != LOGFILE_NO_CLIENT )
if (idx_is_first) {
if (cr->prev_client != LOGFILE_NO_CLIENT)
goto err_out;
idx_is_first = FALSE;
}
}
/* 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;
idx = le16_to_cpu( ra->client_in_use_list );
idx = le16_to_cpu(ra->client_in_use_list);
goto check_list;
}
ntfs_log_trace( "Done.\n" );
ntfs_log_trace("Done.\n");
return TRUE;
err_out:
ntfs_log_error( "$LogFile log client array is corrupt.\n" );
ntfs_log_error("$LogFile log client array is corrupt.\n");
return FALSE;
}
@ -368,50 +349,47 @@ err_out:
* ENOMEM - Not enough memory to load the restart page.
* EIO - Failed to reading from $LogFile.
*/
static int ntfs_check_and_load_restart_page( ntfs_attr *log_na,
static int ntfs_check_and_load_restart_page(ntfs_attr *log_na,
RESTART_PAGE_HEADER *rp, s64 pos, RESTART_PAGE_HEADER **wrp,
LSN *lsn )
LSN *lsn)
{
RESTART_AREA *ra;
RESTART_PAGE_HEADER *trp;
int err;
ntfs_log_trace( "Entering.\n" );
ntfs_log_trace("Entering.\n");
/* 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. */
return EINVAL;
}
/* 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. */
return EINVAL;
}
ra = ( RESTART_AREA* )( ( u8* )rp + le16_to_cpu( rp->restart_area_offset ) );
ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset));
/*
* Allocate a buffer to store the whole restart page so we can multi
* sector transfer deprotect it.
*/
trp = ntfs_malloc( le32_to_cpu( rp->system_page_size ) );
if ( !trp )
trp = ntfs_malloc(le32_to_cpu(rp->system_page_size));
if (!trp)
return errno;
/*
* Read the whole of the restart page into the buffer. If it fits
* completely inside @rp, just copy it from there. Otherwise read it
* from disk.
*/
if ( le32_to_cpu( rp->system_page_size ) <= NTFS_BLOCK_SIZE )
memcpy( trp, rp, le32_to_cpu( rp->system_page_size ) );
else if ( ntfs_attr_pread( log_na, pos,
le32_to_cpu( rp->system_page_size ), trp ) !=
le32_to_cpu( rp->system_page_size ) )
{
if (le32_to_cpu(rp->system_page_size) <= NTFS_BLOCK_SIZE)
memcpy(trp, rp, le32_to_cpu(rp->system_page_size));
else if (ntfs_attr_pread(log_na, pos,
le32_to_cpu(rp->system_page_size), trp) !=
le32_to_cpu(rp->system_page_size)) {
err = errno;
ntfs_log_error( "Failed to read whole restart page into the "
"buffer.\n" );
if ( err != ENOMEM )
ntfs_log_error("Failed to read whole restart page into the "
"buffer.\n");
if (err != ENOMEM)
err = EIO;
goto err_out;
}
@ -419,21 +397,19 @@ static int ntfs_check_and_load_restart_page( ntfs_attr *log_na,
* Perform the multi sector transfer deprotection on the buffer if the
* restart page is protected.
*/
if ( ( !ntfs_is_chkd_record( trp->magic ) || le16_to_cpu( trp->usa_count ) )
&& ntfs_mst_post_read_fixup( ( NTFS_RECORD* )trp,
le32_to_cpu( rp->system_page_size ) ) )
{
if ((!ntfs_is_chkd_record(trp->magic) || le16_to_cpu(trp->usa_count))
&& ntfs_mst_post_read_fixup((NTFS_RECORD*)trp,
le32_to_cpu(rp->system_page_size))) {
/*
* A multi sector tranfer error was detected. We only need to
* abort if the restart page contents exceed the multi sector
* transfer fixup of the first sector.
*/
if ( le16_to_cpu( rp->restart_area_offset ) +
le16_to_cpu( ra->restart_area_length ) >
NTFS_BLOCK_SIZE - ( int )sizeof( u16 ) )
{
ntfs_log_error( "Multi sector transfer error "
"detected in $LogFile restart page.\n" );
if (le16_to_cpu(rp->restart_area_offset) +
le16_to_cpu(ra->restart_area_length) >
NTFS_BLOCK_SIZE - (int)sizeof(u16)) {
ntfs_log_error("Multi sector transfer error "
"detected in $LogFile restart page.\n");
err = EINVAL;
goto err_out;
}
@ -444,29 +420,25 @@ static int ntfs_check_and_load_restart_page( ntfs_attr *log_na,
* check the log client records for consistency, too.
*/
err = 0;
if ( ntfs_is_rstr_record( rp->magic ) &&
ra->client_in_use_list != LOGFILE_NO_CLIENT )
{
if ( !ntfs_check_log_client_array( trp ) )
{
if (ntfs_is_rstr_record(rp->magic) &&
ra->client_in_use_list != LOGFILE_NO_CLIENT) {
if (!ntfs_check_log_client_array(trp)) {
err = EINVAL;
goto err_out;
}
}
if ( lsn )
{
if ( ntfs_is_rstr_record( rp->magic ) )
*lsn = sle64_to_cpu( ra->current_lsn );
if (lsn) {
if (ntfs_is_rstr_record(rp->magic))
*lsn = sle64_to_cpu(ra->current_lsn);
else /* if (ntfs_is_chkd_record(rp->magic)) */
*lsn = sle64_to_cpu( rp->chkdsk_lsn );
*lsn = sle64_to_cpu(rp->chkdsk_lsn);
}
ntfs_log_trace( "Done.\n" );
if ( wrp )
ntfs_log_trace("Done.\n");
if (wrp)
*wrp = trp;
else
{
else {
err_out:
free( trp );
free(trp);
}
return err;
}
@ -488,7 +460,7 @@ err_out:
* if the $LogFile was created on a system with a different page size to ours
* yet and mst deprotection would fail if our page size is smaller.
*/
BOOL ntfs_check_logfile( ntfs_attr *log_na, RESTART_PAGE_HEADER **rp )
BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp)
{
s64 size, pos;
LSN rstr1_lsn, rstr2_lsn;
@ -500,13 +472,13 @@ BOOL ntfs_check_logfile( ntfs_attr *log_na, RESTART_PAGE_HEADER **rp )
BOOL logfile_is_empty = TRUE;
u8 log_page_bits;
ntfs_log_trace( "Entering.\n" );
ntfs_log_trace("Entering.\n");
/* An empty $LogFile must have been clean before it got emptied. */
if ( NVolLogFileEmpty( vol ) )
if (NVolLogFileEmpty(vol))
goto is_empty;
size = log_na->data_size;
/* Make sure the file doesn't exceed the maximum allowed size. */
if ( size > ( s64 )MaxLogFileSize )
if (size > (s64)MaxLogFileSize)
size = MaxLogFileSize;
log_page_size = DefaultLogPageSize;
log_page_mask = log_page_size - 1;
@ -514,22 +486,21 @@ BOOL ntfs_check_logfile( ntfs_attr *log_na, RESTART_PAGE_HEADER **rp )
* Use generic_ffs() instead of ffs() to enable the compiler to
* optimize log_page_size and log_page_bits into constants.
*/
log_page_bits = ffs( log_page_size ) - 1;
size &= ~( log_page_size - 1 );
log_page_bits = ffs(log_page_size) - 1;
size &= ~(log_page_size - 1);
/*
* Ensure the log file is big enough to store at least the two restart
* pages and the minimum number of log record pages.
*/
if ( size < log_page_size * 2 || ( size - log_page_size * 2 ) >>
log_page_bits < MinLogRecordPages )
{
ntfs_log_error( "$LogFile is too small.\n" );
if (size < log_page_size * 2 || (size - log_page_size * 2) >>
log_page_bits < MinLogRecordPages) {
ntfs_log_error("$LogFile is too small.\n");
return FALSE;
}
/* Allocate memory for restart page. */
kaddr = ntfs_malloc( NTFS_BLOCK_SIZE );
if ( !kaddr )
kaddr = ntfs_malloc(NTFS_BLOCK_SIZE);
if (!kaddr)
return FALSE;
/*
* Read through the file looking for a restart page. Since the restart
@ -539,16 +510,14 @@ BOOL ntfs_check_logfile( ntfs_attr *log_na, RESTART_PAGE_HEADER **rp )
* contain empty and uninitialized records, the log file can be assumed
* 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.
*/
if ( ntfs_attr_pread( log_na, pos, NTFS_BLOCK_SIZE, kaddr ) !=
NTFS_BLOCK_SIZE )
{
ntfs_log_error( "Failed to read first NTFS_BLOCK_SIZE "
"bytes of potential restart page.\n" );
if (ntfs_attr_pread(log_na, pos, NTFS_BLOCK_SIZE, kaddr) !=
NTFS_BLOCK_SIZE) {
ntfs_log_error("Failed to read first NTFS_BLOCK_SIZE "
"bytes of potential restart page.\n");
goto err_out;
}
@ -557,21 +526,20 @@ BOOL ntfs_check_logfile( ntfs_attr *log_na, RESTART_PAGE_HEADER **rp )
* empty block after a non-empty block has been encountered
* means we are done.
*/
if ( !ntfs_is_empty_recordp( ( le32* )kaddr ) )
if (!ntfs_is_empty_recordp((le32*)kaddr))
logfile_is_empty = FALSE;
else if ( !logfile_is_empty )
else if (!logfile_is_empty)
break;
/*
* A log record page means there cannot be a restart page after
* this so no need to continue searching.
*/
if ( ntfs_is_rcrd_recordp( ( le32* )kaddr ) )
if (ntfs_is_rcrd_recordp((le32*)kaddr))
break;
/* If not a (modified by chkdsk) restart page, continue. */
if ( !ntfs_is_rstr_recordp( ( le32* )kaddr ) &&
!ntfs_is_chkd_recordp( ( le32* )kaddr ) )
{
if ( !pos )
if (!ntfs_is_rstr_recordp((le32*)kaddr) &&
!ntfs_is_chkd_recordp((le32*)kaddr)) {
if (!pos)
pos = NTFS_BLOCK_SIZE >> 1;
continue;
}
@ -580,18 +548,16 @@ BOOL ntfs_check_logfile( ntfs_attr *log_na, RESTART_PAGE_HEADER **rp )
* and get a copy of the complete multi sector transfer
* deprotected restart page.
*/
err = ntfs_check_and_load_restart_page( log_na,
( RESTART_PAGE_HEADER* )kaddr, pos,
err = ntfs_check_and_load_restart_page(log_na,
(RESTART_PAGE_HEADER*)kaddr, pos,
!rstr1_ph ? &rstr1_ph : &rstr2_ph,
!rstr1_ph ? &rstr1_lsn : &rstr2_lsn );
if ( !err )
{
!rstr1_ph ? &rstr1_lsn : &rstr2_lsn);
if (!err) {
/*
* If we have now found the first (modified by chkdsk)
* restart page, continue looking for the second one.
*/
if ( !pos )
{
if (!pos) {
pos = NTFS_BLOCK_SIZE >> 1;
continue;
}
@ -606,66 +572,59 @@ BOOL ntfs_check_logfile( ntfs_attr *log_na, RESTART_PAGE_HEADER **rp )
* not abort if the restart page was invalid as we might still
* find a valid one further in the file.
*/
if ( err != EINVAL )
if (err != EINVAL)
goto err_out;
/* Continue looking. */
if ( !pos )
if (!pos)
pos = NTFS_BLOCK_SIZE >> 1;
}
if ( kaddr )
{
free( kaddr );
if (kaddr) {
free(kaddr);
kaddr = NULL;
}
if ( logfile_is_empty )
{
NVolSetLogFileEmpty( vol );
if (logfile_is_empty) {
NVolSetLogFileEmpty(vol);
is_empty:
ntfs_log_trace( "Done. ($LogFile is empty.)\n" );
ntfs_log_trace("Done. ($LogFile is empty.)\n");
return TRUE;
}
if ( !rstr1_ph )
{
if ( rstr2_ph )
ntfs_log_error( "BUG: rstr2_ph isn't NULL!\n" );
ntfs_log_error( "Did not find any restart pages in "
"$LogFile and it was not empty.\n" );
if (!rstr1_ph) {
if (rstr2_ph)
ntfs_log_error("BUG: rstr2_ph isn't NULL!\n");
ntfs_log_error("Did not find any restart pages in "
"$LogFile and it was not empty.\n");
return FALSE;
}
/* 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.
* Otherwise just throw it away.
*/
if ( rstr2_lsn > rstr1_lsn )
{
ntfs_log_debug( "Using second restart page as it is more "
"recent.\n" );
free( rstr1_ph );
if (rstr2_lsn > rstr1_lsn) {
ntfs_log_debug("Using second restart page as it is more "
"recent.\n");
free(rstr1_ph);
rstr1_ph = rstr2_ph;
/* rstr1_lsn = rstr2_lsn; */
}
else
{
ntfs_log_debug( "Using first restart page as it is more "
"recent.\n" );
free( rstr2_ph );
} else {
ntfs_log_debug("Using first restart page as it is more "
"recent.\n");
free(rstr2_ph);
}
rstr2_ph = NULL;
}
/* All consistency checks passed. */
if ( rp )
if (rp)
*rp = rstr1_ph;
else
free( rstr1_ph );
ntfs_log_trace( "Done.\n" );
free(rstr1_ph);
ntfs_log_trace("Done.\n");
return TRUE;
err_out:
free( kaddr );
free( rstr1_ph );
free( rstr2_ph );
free(kaddr);
free(rstr1_ph);
free(rstr2_ph);
return FALSE;
}
@ -689,45 +648,41 @@ err_out:
* is empty this function requires that NVolLogFileEmpty() is true otherwise an
* empty volume will be reported as dirty.
*/
BOOL ntfs_is_logfile_clean( ntfs_attr *log_na, RESTART_PAGE_HEADER *rp )
BOOL ntfs_is_logfile_clean(ntfs_attr *log_na, RESTART_PAGE_HEADER *rp)
{
RESTART_AREA *ra;
ntfs_log_trace( "Entering.\n" );
ntfs_log_trace("Entering.\n");
/* An empty $LogFile must have been clean before it got emptied. */
if ( NVolLogFileEmpty( log_na->ni->vol ) )
{
ntfs_log_trace( "$LogFile is empty\n" );
if (NVolLogFileEmpty(log_na->ni->vol)) {
ntfs_log_trace("$LogFile is empty\n");
return TRUE;
}
if ( !rp )
{
ntfs_log_error( "Restart page header is NULL\n" );
if (!rp) {
ntfs_log_error("Restart page header is NULL\n");
return FALSE;
}
if ( !ntfs_is_rstr_record( rp->magic ) &&
!ntfs_is_chkd_record( rp->magic ) )
{
ntfs_log_error( "Restart page buffer is invalid\n" );
if (!ntfs_is_rstr_record(rp->magic) &&
!ntfs_is_chkd_record(rp->magic)) {
ntfs_log_error("Restart page buffer is invalid\n");
return FALSE;
}
ra = ( RESTART_AREA* )( ( u8* )rp + le16_to_cpu( rp->restart_area_offset ) );
ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset));
/*
* If the $LogFile has active clients, i.e. it is open, and we do not
* have the RESTART_VOLUME_IS_CLEAN bit set in the restart area flags,
* we assume there was an unclean shutdown.
*/
if ( ra->client_in_use_list != LOGFILE_NO_CLIENT &&
!( ra->flags & RESTART_VOLUME_IS_CLEAN ) )
{
ntfs_log_error( "The disk contains an unclean file system (%d, "
"%d).\n", le16_to_cpu( ra->client_in_use_list ),
le16_to_cpu( ra->flags ) );
if (ra->client_in_use_list != LOGFILE_NO_CLIENT &&
!(ra->flags & RESTART_VOLUME_IS_CLEAN)) {
ntfs_log_error("The disk contains an unclean file system (%d, "
"%d).\n", le16_to_cpu(ra->client_in_use_list),
le16_to_cpu(ra->flags));
return FALSE;
}
/* $LogFile indicates a clean shutdown. */
ntfs_log_trace( "$LogFile indicates a clean shutdown\n" );
ntfs_log_trace("$LogFile indicates a clean shutdown\n");
return TRUE;
}
@ -742,44 +697,41 @@ BOOL ntfs_is_logfile_clean( ntfs_attr *log_na, RESTART_PAGE_HEADER *rp )
* checked by a call to ntfs_check_logfile() and that ntfs_is_logfile_clean()
* has been used to ensure that the $LogFile is clean.
*/
int ntfs_empty_logfile( ntfs_attr *na )
int ntfs_empty_logfile(ntfs_attr *na)
{
s64 pos, count;
char buf[NTFS_BUF_SIZE];
ntfs_log_trace( "Entering.\n" );
ntfs_log_trace("Entering.\n");
if ( NVolLogFileEmpty( na->ni->vol ) )
if (NVolLogFileEmpty(na->ni->vol))
return 0;
if ( !NAttrNonResident( na ) )
{
if (!NAttrNonResident(na)) {
errno = EIO;
ntfs_log_perror( "Resident $LogFile $DATA attribute" );
ntfs_log_perror("Resident $LogFile $DATA attribute");
return -1;
}
memset( buf, -1, NTFS_BUF_SIZE );
memset(buf, -1, NTFS_BUF_SIZE);
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_attr_pwrite( na, pos, count, buf );
if ( count <= 0 )
{
ntfs_log_perror( "Failed to reset $LogFile" );
if ( count != -1 )
count = ntfs_attr_pwrite(na, pos, count, buf);
if (count <= 0) {
ntfs_log_perror("Failed to reset $LogFile");
if (count != -1)
errno = EIO;
return -1;
}
pos += count;
}
NVolSetLogFileEmpty( na->ni->vol );
NVolSetLogFileEmpty(na->ni->vol);
return 0;
}

View File

@ -61,42 +61,40 @@
*
* Begins the restart area.
*/
typedef struct
{
/*Ofs*/
/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
/* 0*/
NTFS_RECORD_TYPES magic;/* The magic is "RSTR". */
/* 4*/ le16 usa_ofs; /* See NTFS_RECORD definition in layout.h.
typedef struct {
/*Ofs*/
/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
/* 0*/ NTFS_RECORD_TYPES magic;/* The magic is "RSTR". */
/* 4*/ le16 usa_ofs; /* See NTFS_RECORD definition in layout.h.
When creating, set this to be immediately
after this header structure (without any
alignment). */
/* 6*/ le16 usa_count; /* See NTFS_RECORD definition in layout.h. */
/* 6*/ le16 usa_count; /* See NTFS_RECORD definition in layout.h. */
/* 8*/ leLSN chkdsk_lsn; /* The last log file sequence number found by
/* 8*/ leLSN chkdsk_lsn; /* The last log file sequence number found by
chkdsk. Only used when the magic is changed
to "CHKD". Otherwise this is zero. */
/* 16*/ le32 system_page_size; /* Byte size of system pages when the log file
/* 16*/ le32 system_page_size; /* Byte size of system pages when the log file
was created, has to be >= 512 and a power of
2. Use this to calculate the required size
of the usa (usa_count) and add it to usa_ofs.
Then verify that the result is less than the
value of the restart_area_offset. */
/* 20*/ le32 log_page_size; /* Byte size of log file pages, has to be >=
/* 20*/ le32 log_page_size; /* Byte size of log file pages, has to be >=
512 and a power of 2. The default is 4096
and is used when the system page size is
between 4096 and 8192. Otherwise this is
set to the system page size instead. */
/* 24*/ le16 restart_area_offset;/* Byte offset from the start of this header to
/* 24*/ le16 restart_area_offset;/* Byte offset from the start of this header to
the RESTART_AREA. Value has to be aligned
to 8-byte boundary. When creating, set this
to be after the usa. */
/* 26*/ sle16 minor_ver; /* Log file minor version. Only check if major
/* 26*/ sle16 minor_ver; /* Log file minor version. Only check if major
version is 1. */
/* 28*/ sle16 major_ver; /* Log file major version. We only support
/* 28*/ sle16 major_ver; /* Log file major version. We only support
version 1.1. */
/* sizeof() = 30 (0x1e) bytes */
} __attribute__( ( __packed__ ) ) RESTART_PAGE_HEADER;
/* sizeof() = 30 (0x1e) bytes */
} __attribute__((__packed__)) RESTART_PAGE_HEADER;
/*
* Constant for the log client indices meaning that there are no client records
@ -110,11 +108,10 @@ typedef struct
* These are the so far known RESTART_AREA_* flags (16-bit) which contain
* information about the log file in which they are present.
*/
enum
{
RESTART_VOLUME_IS_CLEAN = const_cpu_to_le16( 0x0002 ),
enum {
RESTART_VOLUME_IS_CLEAN = const_cpu_to_le16(0x0002),
RESTART_SPACE_FILLER = 0xffff, /* gcc: Force enum bit width to 16. */
} __attribute__( ( __packed__ ) );
} __attribute__((__packed__));
typedef le16 RESTART_AREA_FLAGS;
@ -125,20 +122,18 @@ typedef le16 RESTART_AREA_FLAGS;
* RESTART_PAGE_HEADER to the restart_area_offset value found in it.
* See notes at restart_area_offset above.
*/
typedef struct
{
/*Ofs*/
/* 0*/
leLSN current_lsn; /* The current, i.e. last LSN inside the log
typedef struct {
/*Ofs*/
/* 0*/ leLSN current_lsn; /* The current, i.e. last LSN inside the log
when the restart area was last written.
This happens often but what is the interval?
Is it just fixed time or is it every time a
check point is written or something else?
On create set to 0. */
/* 8*/ le16 log_clients; /* Number of log client records in the array of
/* 8*/ le16 log_clients; /* Number of log client records in the array of
log client records which follows this
restart area. Must be 1. */
/* 10*/ le16 client_free_list; /* The index of the first free log client record
/* 10*/ le16 client_free_list; /* The index of the first free log client record
in the array of log client records.
LOGFILE_NO_CLIENT means that there are no
free log client records in the array.
@ -154,7 +149,7 @@ typedef struct
and presumably later, the logfile is always
open, even on clean shutdown so this should
always be LOGFILE_NO_CLIENT. */
/* 12*/ le16 client_in_use_list;/* The index of the first in-use log client
/* 12*/ le16 client_in_use_list;/* The index of the first in-use log client
record in the array of log client records.
LOGFILE_NO_CLIENT means that there are no
in-use log client records in the array. If
@ -171,7 +166,7 @@ typedef struct
presumably later, the logfile is always
open, even on clean shutdown so this should
always be 0. */
/* 14*/ RESTART_AREA_FLAGS flags;/* Flags modifying LFS behaviour. On Win2k
/* 14*/ RESTART_AREA_FLAGS flags;/* Flags modifying LFS behaviour. On Win2k
and presumably earlier this is always 0. On
WinXP and presumably later, if the logfile
was shutdown cleanly, the second bit,
@ -187,13 +182,13 @@ typedef struct
clean. If on the other hand the logfile is
open and this bit is clear, we can be almost
certain that the logfile is dirty. */
/* 16*/ le32 seq_number_bits; /* How many bits to use for the sequence
/* 16*/ le32 seq_number_bits; /* How many bits to use for the sequence
number. This is calculated as 67 - the
number of bits required to store the logfile
size in bytes and this can be used in with
the specified file_size as a consistency
check. */
/* 20*/ le16 restart_area_length;/* Length of the restart area including the
/* 20*/ le16 restart_area_length;/* Length of the restart area including the
client array. Following checks required if
version matches. Otherwise, skip them.
restart_area_offset + restart_area_length
@ -201,7 +196,7 @@ typedef struct
restart_area_length has to be >=
client_array_offset + (log_clients *
sizeof(log client record)). */
/* 22*/ le16 client_array_offset;/* Offset from the start of this record to
/* 22*/ le16 client_array_offset;/* Offset from the start of this record to
the first log client record if versions are
matched. When creating, set this to be
after this restart area structure, aligned
@ -223,7 +218,7 @@ typedef struct
the client array. This probably means that
the RESTART_AREA record is actually bigger
in WinXP and later. */
/* 24*/ sle64 file_size; /* Usable byte size of the log file. If the
/* 24*/ sle64 file_size; /* Usable byte size of the log file. If the
restart_area_offset + the offset of the
file_size are > 510 then corruption has
occurred. This is the very first check when
@ -236,10 +231,10 @@ typedef struct
then it has to be at least big enough to
store the two restart pages and 48 (0x30)
log record pages. */
/* 32*/ le32 last_lsn_data_length;/* Length of data of last LSN, not including
/* 32*/ le32 last_lsn_data_length;/* Length of data of last LSN, not including
the log record header. On create set to
0. */
/* 36*/ le16 log_record_header_length;/* Byte size of the log record header.
/* 36*/ le16 log_record_header_length;/* Byte size of the log record header.
If the version matches then check that the
value of log_record_header_length is a
multiple of 8, i.e.
@ -247,19 +242,19 @@ typedef struct
log_record_header_length. When creating set
it to sizeof(LOG_RECORD_HEADER), aligned to
8 bytes. */
/* 38*/ le16 log_page_data_offset;/* Offset to the start of data in a log record
/* 38*/ le16 log_page_data_offset;/* Offset to the start of data in a log record
page. Must be a multiple of 8. On create
set it to immediately after the update
sequence array of the log record page. */
/* 40*/ le32 restart_log_open_count;/* A counter that gets incremented every
/* 40*/ le32 restart_log_open_count;/* A counter that gets incremented every
time the logfile is restarted which happens
at mount time when the logfile is opened.
When creating set to a random value. Win2k
sets it to the low 32 bits of the current
system time in NTFS format (see time.h). */
/* 44*/ le32 reserved; /* Reserved/alignment to 8-byte boundary. */
/* sizeof() = 48 (0x30) bytes */
} __attribute__( ( __packed__ ) ) RESTART_AREA;
/* 44*/ le32 reserved; /* Reserved/alignment to 8-byte boundary. */
/* sizeof() = 48 (0x30) bytes */
} __attribute__((__packed__)) RESTART_AREA;
/**
* struct LOG_CLIENT_RECORD - Log client record.
@ -267,42 +262,40 @@ typedef struct
* The offset of this record is found by adding the offset of the
* RESTART_AREA to the client_array_offset value found in it.
*/
typedef struct
{
/*Ofs*/
/* 0*/
leLSN oldest_lsn; /* Oldest LSN needed by this client. On create
typedef struct {
/*Ofs*/
/* 0*/ leLSN oldest_lsn; /* Oldest LSN needed by this client. On create
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 log file. At present, if clean this
should = current_lsn in restart area but it
probably also = current_lsn when dirty most
of the time. At create set to 0. */
/* 16*/ le16 prev_client; /* The offset to the previous log client record
/* 16*/ le16 prev_client; /* The offset to the previous log client record
in the array of log client records.
LOGFILE_NO_CLIENT means there is no previous
client record, i.e. this is the first one.
This is always LOGFILE_NO_CLIENT. */
/* 18*/ le16 next_client; /* The offset to the next log client record in
/* 18*/ le16 next_client; /* The offset to the next log client record in
the array of log client records.
LOGFILE_NO_CLIENT means there are no next
client records, i.e. this is the last one.
This is always LOGFILE_NO_CLIENT. */
/* 20*/ le16 seq_number; /* On Win2k and presumably earlier, this is set
/* 20*/ le16 seq_number; /* On Win2k and presumably earlier, this is set
to zero every time the logfile is restarted
and it is incremented when the logfile is
closed at dismount time. Thus it is 0 when
dirty and 1 when clean. On WinXP and
presumably later, this is always 0. */
/* 22*/ u8 reserved[6]; /* Reserved/alignment. */
/* 28*/ le32 client_name_length;/* Length of client name in bytes. Should
/* 22*/ u8 reserved[6]; /* Reserved/alignment. */
/* 28*/ le32 client_name_length;/* Length of client name in bytes. Should
always be 8. */
/* 32*/ ntfschar client_name[64];/* Name of the client in Unicode. Should
/* 32*/ ntfschar client_name[64];/* Name of the client in Unicode. Should
always be "NTFS" with the remaining bytes
set to 0. */
/* sizeof() = 160 (0xa0) bytes */
} __attribute__( ( __packed__ ) ) LOG_CLIENT_RECORD;
/* sizeof() = 160 (0xa0) bytes */
} __attribute__((__packed__)) LOG_CLIENT_RECORD;
/**
* struct RECORD_PAGE_HEADER - Log page record page header.
@ -312,9 +305,8 @@ typedef struct
* following update sequence array and then aligned to 8 byte boundary, but is
* this specified anywhere?).
*/
typedef struct
{
/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
typedef struct {
/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
NTFS_RECORD_TYPES magic;/* Usually the magic is "RCRD". */
u16 usa_ofs; /* See NTFS_RECORD definition in layout.h.
When creating, set this to be immediately
@ -322,54 +314,48 @@ typedef struct
alignment). */
u16 usa_count; /* See NTFS_RECORD definition in layout.h. */
union
{
union {
LSN last_lsn;
s64 file_offset;
} __attribute__( ( __packed__ ) ) copy;
} __attribute__((__packed__)) copy;
u32 flags;
u16 page_count;
u16 page_position;
union
{
struct
{
union {
struct {
u16 next_record_offset;
u8 reserved[6];
LSN last_end_lsn;
} __attribute__( ( __packed__ ) ) packed;
} __attribute__( ( __packed__ ) ) header;
} __attribute__( ( __packed__ ) ) RECORD_PAGE_HEADER;
} __attribute__((__packed__)) packed;
} __attribute__((__packed__)) header;
} __attribute__((__packed__)) RECORD_PAGE_HEADER;
/**
* enum LOG_RECORD_FLAGS - Possible 16-bit flags for log records.
*
* (Or is it log record pages?)
*/
typedef enum
{
LOG_RECORD_MULTI_PAGE = const_cpu_to_le16( 0x0001 ), /* ??? */
typedef enum {
LOG_RECORD_MULTI_PAGE = const_cpu_to_le16(0x0001), /* ??? */
LOG_RECORD_SIZE_PLACE_HOLDER = 0xffff,
/* This has nothing to do with the log record. It is only so
gcc knows to make the flags 16-bit. */
} __attribute__( ( __packed__ ) ) LOG_RECORD_FLAGS;
} __attribute__((__packed__)) LOG_RECORD_FLAGS;
/**
* struct LOG_CLIENT_ID - The log client id structure identifying a log client.
*/
typedef struct
{
typedef struct {
u16 seq_number;
u16 client_index;
} __attribute__( ( __packed__ ) ) LOG_CLIENT_ID;
} __attribute__((__packed__)) LOG_CLIENT_ID;
/**
* struct LOG_RECORD - Log record header.
*
* Each log record seems to have a constant size of 0x70 bytes.
*/
typedef struct
{
typedef struct {
LSN this_lsn;
LSN client_previous_lsn;
LSN client_undo_next_lsn;
@ -379,7 +365,7 @@ typedef struct
u32 transaction_id;
u16 flags;
u16 reserved_or_alignment[3];
/* Now are at ofs 0x30 into struct. */
/* Now are at ofs 0x30 into struct. */
u16 redo_operation;
u16 undo_operation;
u16 redo_offset;
@ -389,21 +375,20 @@ typedef struct
u16 target_attribute;
u16 lcns_to_follow; /* Number of lcn_list entries
following this entry. */
/* Now at ofs 0x40. */
/* Now at ofs 0x40. */
u16 record_offset;
u16 attribute_offset;
u32 alignment_or_reserved;
VCN target_vcn;
/* Now at ofs 0x50. */
struct
{ /* Only present if lcns_to_follow
/* Now at ofs 0x50. */
struct { /* Only present if lcns_to_follow
is not 0. */
LCN lcn;
} __attribute__( ( __packed__ ) ) lcn_list[0];
} __attribute__( ( __packed__ ) ) LOG_RECORD;
} __attribute__((__packed__)) lcn_list[0];
} __attribute__((__packed__)) LOG_RECORD;
extern BOOL ntfs_check_logfile( ntfs_attr *log_na, RESTART_PAGE_HEADER **rp );
extern BOOL ntfs_is_logfile_clean( ntfs_attr *log_na, RESTART_PAGE_HEADER *rp );
extern int ntfs_empty_logfile( ntfs_attr *na );
extern BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp);
extern BOOL ntfs_is_logfile_clean(ntfs_attr *log_na, RESTART_PAGE_HEADER *rp);
extern int ntfs_empty_logfile(ntfs_attr *na);
#endif /* defined _NTFS_LOGFILE_H */

View File

@ -67,8 +67,7 @@ static int tab;
* @flags: Flags which affect the output style
* @handler: Function to perform the actual logging
*/
struct ntfs_logging
{
struct ntfs_logging {
u32 levels;
u32 flags;
ntfs_log_handler *handler BROKEN_GCC_FORMAT_ATTRIBUTE;
@ -78,8 +77,7 @@ struct ntfs_logging
* ntfs_log
* 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
NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE | NTFS_LOG_LEVEL_ENTER |
NTFS_LOG_LEVEL_LEAVE |
@ -103,7 +101,7 @@ static struct ntfs_logging ntfs_log =
*
* Returns: Log levels in a 32-bit field
*/
u32 ntfs_log_get_levels( void )
u32 ntfs_log_get_levels(void)
{
return ntfs_log.levels;
}
@ -117,7 +115,7 @@ u32 ntfs_log_get_levels( void )
*
* Returns: Log levels that were enabled before the call
*/
u32 ntfs_log_set_levels( u32 levels )
u32 ntfs_log_set_levels(u32 levels)
{
u32 old;
old = ntfs_log.levels;
@ -134,11 +132,11 @@ u32 ntfs_log_set_levels( u32 levels )
*
* Returns: Log levels that were enabled before the call
*/
u32 ntfs_log_clear_levels( u32 levels )
u32 ntfs_log_clear_levels(u32 levels)
{
u32 old;
old = ntfs_log.levels;
ntfs_log.levels &= ( ~levels );
ntfs_log.levels &= (~levels);
return old;
}
@ -150,7 +148,7 @@ u32 ntfs_log_clear_levels( u32 levels )
*
* Returns: Logging flags in a 32-bit field
*/
u32 ntfs_log_get_flags( void )
u32 ntfs_log_get_flags(void)
{
return ntfs_log.flags;
}
@ -164,7 +162,7 @@ u32 ntfs_log_get_flags( void )
*
* Returns: Logging flags that were enabled before the call
*/
u32 ntfs_log_set_flags( u32 flags )
u32 ntfs_log_set_flags(u32 flags)
{
u32 old;
old = ntfs_log.flags;
@ -181,11 +179,11 @@ u32 ntfs_log_set_flags( u32 flags )
*
* Returns: Logging flags that were enabled before the call
*/
u32 ntfs_log_clear_flags( u32 flags )
u32 ntfs_log_clear_flags(u32 flags)
{
u32 old;
old = ntfs_log.flags;
ntfs_log.flags &= ( ~flags );
ntfs_log.flags &= (~flags);
return old;
}
@ -199,12 +197,11 @@ u32 ntfs_log_clear_flags( u32 flags )
*
* Returns: "string" Prefix to be used
*/
static FILE * ntfs_log_get_stream( u32 level )
static FILE * ntfs_log_get_stream(u32 level)
{
FILE *stream;
switch ( level )
{
switch (level) {
case NTFS_LOG_LEVEL_INFO:
case NTFS_LOG_LEVEL_QUIET:
case NTFS_LOG_LEVEL_PROGRESS:
@ -236,12 +233,11 @@ static FILE * ntfs_log_get_stream( u32 level )
*
* Returns: "string" Prefix to be used
*/
static const char * ntfs_log_get_prefix( u32 level )
static const char * ntfs_log_get_prefix(u32 level)
{
const char *prefix;
switch ( level )
{
switch (level) {
case NTFS_LOG_LEVEL_DEBUG:
prefix = "DEBUG: ";
break;
@ -288,17 +284,15 @@ static const char * ntfs_log_get_prefix( u32 level )
* This alternate handler will be called for all future logging requests.
* If no @handler is specified, logging will revert to the default handler.
*/
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;
#ifdef HAVE_SYSLOG_H
if ( handler == ntfs_log_handler_syslog )
openlog( "ntfs-3g", LOG_PID, LOG_USER );
if (handler == ntfs_log_handler_syslog)
openlog("ntfs-3g", LOG_PID, LOG_USER);
#endif
}
else
} else
ntfs_log.handler = ntfs_log_handler_null;
}
@ -319,20 +313,20 @@ void ntfs_log_set_handler( ntfs_log_handler *handler )
* 0 Message wasn't logged
* num Number of output characters
*/
int ntfs_log_redirect( const char *function, const char *file,
int line, u32 level, void *data, const char *format, ... )
int ntfs_log_redirect(const char *function, const char *file,
int line, u32 level, void *data, const char *format, ...)
{
int olderr = errno;
int ret;
va_list args;
if ( !( ntfs_log.levels & level ) ) /* Don't log this message */
if (!(ntfs_log.levels & level)) /* Don't log this message */
return 0;
va_start( args, format );
va_start(args, format);
errno = olderr;
ret = ntfs_log.handler( function, file, line, level, data, format, args );
va_end( args );
ret = ntfs_log.handler(function, file, line, level, data, format, args);
va_end(args);
errno = olderr;
return ret;
@ -361,35 +355,33 @@ int ntfs_log_redirect( const char *function, const char *file,
#define LOG_LINE_LEN 512
int ntfs_log_handler_syslog( const char *function __attribute__( ( unused ) ),
const char *file __attribute__( ( unused ) ),
int line __attribute__( ( unused ) ), u32 level,
void *data __attribute__( ( unused ) ),
const char *format, va_list args )
int ntfs_log_handler_syslog(const char *function __attribute__((unused)),
const char *file __attribute__((unused)),
int line __attribute__((unused)), u32 level,
void *data __attribute__((unused)),
const char *format, va_list args)
{
char logbuf[LOG_LINE_LEN];
int ret, olderr = errno;
#ifndef DEBUG
if ( ( level & NTFS_LOG_LEVEL_PERROR ) && errno == ENOSPC )
if ((level & NTFS_LOG_LEVEL_PERROR) && errno == ENOSPC)
return 1;
#endif
ret = vsnprintf( logbuf, LOG_LINE_LEN, format, args );
if ( ret < 0 )
{
vsyslog( LOG_NOTICE, format, args );
ret = vsnprintf(logbuf, LOG_LINE_LEN, format, args);
if (ret < 0) {
vsyslog(LOG_NOTICE, format, args);
ret = 1;
goto out;
}
if ( ( LOG_LINE_LEN > ret + 3 ) && ( level & NTFS_LOG_LEVEL_PERROR ) )
{
strncat( logbuf, ": ", LOG_LINE_LEN - ret - 1 );
strncat( logbuf, strerror( olderr ), LOG_LINE_LEN - ( ret + 3 ) );
ret = strlen( logbuf );
if ((LOG_LINE_LEN > ret + 3) && (level & NTFS_LOG_LEVEL_PERROR)) {
strncat(logbuf, ": ", LOG_LINE_LEN - ret - 1);
strncat(logbuf, strerror(olderr), LOG_LINE_LEN - (ret + 3));
ret = strlen(logbuf);
}
syslog( LOG_NOTICE, "%s", logbuf );
syslog(LOG_NOTICE, "%s", logbuf);
out:
errno = olderr;
return ret;
@ -417,8 +409,8 @@ out:
* 0 Message wasn't logged
* num Number of output characters
*/
int ntfs_log_handler_fprintf( const char *function, const char *file,
int line, u32 level, void *data, const char *format, va_list args )
int ntfs_log_handler_fprintf(const char *function, const char *file,
int line, u32 level, void *data, const char *format, va_list args)
{
#ifdef DEBUG
int i;
@ -427,48 +419,47 @@ int ntfs_log_handler_fprintf( const char *function, const char *file,
int olderr = errno;
FILE *stream;
if ( !data ) /* Interpret data as a FILE stream. */
if (!data) /* Interpret data as a FILE stream. */
return 0; /* If it's NULL, we can't do anything. */
stream = ( FILE* )data;
stream = (FILE*)data;
#ifdef DEBUG
if ( level == NTFS_LOG_LEVEL_LEAVE )
{
if ( tab )
if (level == NTFS_LOG_LEVEL_LEAVE) {
if (tab)
tab--;
return 0;
}
for ( i = 0; i < tab; i++ )
ret += fprintf( stream, " " );
for (i = 0; i < tab; i++)
ret += fprintf(stream, " ");
#endif
if ( ( ntfs_log.flags & NTFS_LOG_FLAG_ONLYNAME ) &&
( strchr( file, PATH_SEP ) ) ) /* Abbreviate the filename */
file = strrchr( file, PATH_SEP ) + 1;
if ((ntfs_log.flags & NTFS_LOG_FLAG_ONLYNAME) &&
(strchr(file, PATH_SEP))) /* Abbreviate the filename */
file = strrchr(file, PATH_SEP) + 1;
if ( ntfs_log.flags & NTFS_LOG_FLAG_PREFIX ) /* Prefix the output */
ret += fprintf( stream, "%s", ntfs_log_get_prefix( level ) );
if (ntfs_log.flags & NTFS_LOG_FLAG_PREFIX) /* Prefix the output */
ret += fprintf(stream, "%s", ntfs_log_get_prefix(level));
if ( ntfs_log.flags & NTFS_LOG_FLAG_FILENAME ) /* Source filename */
ret += fprintf( stream, "%s ", file );
if (ntfs_log.flags & NTFS_LOG_FLAG_FILENAME) /* Source filename */
ret += fprintf(stream, "%s ", file);
if ( ntfs_log.flags & NTFS_LOG_FLAG_LINE ) /* Source line number */
ret += fprintf( stream, "(%d) ", line );
if (ntfs_log.flags & NTFS_LOG_FLAG_LINE) /* Source line number */
ret += fprintf(stream, "(%d) ", line);
if ( ( ntfs_log.flags & NTFS_LOG_FLAG_FUNCTION ) || /* Source function */
( level & NTFS_LOG_LEVEL_TRACE ) || ( level & NTFS_LOG_LEVEL_ENTER ) )
ret += fprintf( stream, "%s(): ", function );
if ((ntfs_log.flags & NTFS_LOG_FLAG_FUNCTION) || /* Source function */
(level & NTFS_LOG_LEVEL_TRACE) || (level & NTFS_LOG_LEVEL_ENTER))
ret += fprintf(stream, "%s(): ", function);
ret += vfprintf( stream, format, args );
ret += vfprintf(stream, format, args);
if ( level & NTFS_LOG_LEVEL_PERROR )
ret += fprintf( stream, ": %s\n", strerror( olderr ) );
if (level & NTFS_LOG_LEVEL_PERROR)
ret += fprintf(stream, ": %s\n", strerror(olderr));
#ifdef DEBUG
if ( level == NTFS_LOG_LEVEL_ENTER )
if (level == NTFS_LOG_LEVEL_ENTER)
tab++;
#endif
fflush( stream );
fflush(stream);
errno = olderr;
return ret;
}
@ -488,9 +479,9 @@ int ntfs_log_handler_fprintf( const char *function, const char *file,
*
* Returns: 0 Message wasn't logged
*/
int ntfs_log_handler_null( const char *function __attribute__( ( unused ) ), const char *file __attribute__( ( unused ) ),
int line __attribute__( ( unused ) ), u32 level __attribute__( ( unused ) ), void *data __attribute__( ( unused ) ),
const char *format __attribute__( ( unused ) ), va_list args __attribute__( ( unused ) ) )
int ntfs_log_handler_null(const char *function __attribute__((unused)), const char *file __attribute__((unused)),
int line __attribute__((unused)), u32 level __attribute__((unused)), void *data __attribute__((unused)),
const char *format __attribute__((unused)), va_list args __attribute__((unused)))
{
return 0;
}
@ -516,13 +507,13 @@ int ntfs_log_handler_null( const char *function __attribute__( ( unused ) ), con
* 0 Message wasn't logged
* num Number of output characters
*/
int ntfs_log_handler_stdout( const char *function, const char *file,
int line, u32 level, void *data, const char *format, va_list args )
int ntfs_log_handler_stdout(const char *function, const char *file,
int line, u32 level, void *data, const char *format, va_list args)
{
if ( !data )
if (!data)
data = stdout;
return ntfs_log_handler_fprintf( function, file, line, level, data, format, args );
return ntfs_log_handler_fprintf(function, file, line, level, data, format, args);
}
/**
@ -547,13 +538,13 @@ int ntfs_log_handler_stdout( const char *function, const char *file,
* 0 Message wasn't logged
* num Number of output characters
*/
int ntfs_log_handler_outerr( const char *function, const char *file,
int line, u32 level, void *data, const char *format, va_list args )
int ntfs_log_handler_outerr(const char *function, const char *file,
int line, u32 level, void *data, const char *format, va_list args)
{
if ( !data )
data = ntfs_log_get_stream( level );
if (!data)
data = ntfs_log_get_stream(level);
return ntfs_log_handler_fprintf( function, file, line, level, data, format, args );
return ntfs_log_handler_fprintf(function, file, line, level, data, format, args);
}
/**
@ -577,13 +568,13 @@ int ntfs_log_handler_outerr( const char *function, const char *file,
* 0 Message wasn't logged
* num Number of output characters
*/
int ntfs_log_handler_stderr( const char *function, const char *file,
int line, u32 level, void *data, const char *format, va_list args )
int ntfs_log_handler_stderr(const char *function, const char *file,
int line, u32 level, void *data, const char *format, va_list args)
{
if ( !data )
if (!data)
data = stderr;
return ntfs_log_handler_fprintf( function, file, line, level, data, format, args );
return ntfs_log_handler_fprintf(function, file, line, level, data, format, args);
}
@ -600,30 +591,23 @@ int ntfs_log_handler_stderr( const char *function, const char *file,
* Returns: TRUE Option understood
* FALSE Invalid log option
*/
BOOL ntfs_log_parse_option( const char *option )
BOOL ntfs_log_parse_option(const char *option)
{
if ( strcmp( option, "--log-debug" ) == 0 )
{
ntfs_log_set_levels( NTFS_LOG_LEVEL_DEBUG );
if (strcmp(option, "--log-debug") == 0) {
ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG);
return TRUE;
}
else if ( strcmp( option, "--log-verbose" ) == 0 )
{
ntfs_log_set_levels( NTFS_LOG_LEVEL_VERBOSE );
} else if (strcmp(option, "--log-verbose") == 0) {
ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
return TRUE;
}
else if ( strcmp( option, "--log-quiet" ) == 0 )
{
ntfs_log_clear_levels( NTFS_LOG_LEVEL_QUIET );
} else if (strcmp(option, "--log-quiet") == 0) {
ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
return TRUE;
}
else if ( strcmp( option, "--log-trace" ) == 0 )
{
ntfs_log_set_levels( NTFS_LOG_LEVEL_TRACE );
} else if (strcmp(option, "--log-trace") == 0) {
ntfs_log_set_levels(NTFS_LOG_LEVEL_TRACE);
return TRUE;
}
ntfs_log_debug( "Unknown logging option '%s'\n", option );
ntfs_log_debug("Unknown logging option '%s'\n", option);
return FALSE;
}

View File

@ -34,37 +34,37 @@
#include "types.h"
/* Function prototype for the logging handlers */
typedef int ( ntfs_log_handler )( const char *function, const char *file, int line,
u32 level, void *data, const char *format, va_list args );
typedef int (ntfs_log_handler)(const char *function, const char *file, int line,
u32 level, void *data, const char *format, va_list args);
/* Set the logging handler from one of the functions, below. */
void ntfs_log_set_handler( ntfs_log_handler *handler
__attribute__( ( format( printf, 6, 0 ) ) ) );
void ntfs_log_set_handler(ntfs_log_handler *handler
__attribute__((format(printf, 6, 0))));
/* Logging handlers */
ntfs_log_handler ntfs_log_handler_syslog __attribute__( ( format( printf, 6, 0 ) ) );
ntfs_log_handler ntfs_log_handler_fprintf __attribute__( ( format( printf, 6, 0 ) ) );
ntfs_log_handler ntfs_log_handler_null __attribute__( ( format( printf, 6, 0 ) ) );
ntfs_log_handler ntfs_log_handler_stdout __attribute__( ( format( printf, 6, 0 ) ) );
ntfs_log_handler ntfs_log_handler_outerr __attribute__( ( format( printf, 6, 0 ) ) );
ntfs_log_handler ntfs_log_handler_stderr __attribute__( ( format( printf, 6, 0 ) ) );
ntfs_log_handler ntfs_log_handler_syslog __attribute__((format(printf, 6, 0)));
ntfs_log_handler ntfs_log_handler_fprintf __attribute__((format(printf, 6, 0)));
ntfs_log_handler ntfs_log_handler_null __attribute__((format(printf, 6, 0)));
ntfs_log_handler ntfs_log_handler_stdout __attribute__((format(printf, 6, 0)));
ntfs_log_handler ntfs_log_handler_outerr __attribute__((format(printf, 6, 0)));
ntfs_log_handler ntfs_log_handler_stderr __attribute__((format(printf, 6, 0)));
/* Enable/disable certain log levels */
u32 ntfs_log_set_levels( u32 levels );
u32 ntfs_log_clear_levels( u32 levels );
u32 ntfs_log_get_levels( void );
u32 ntfs_log_set_levels(u32 levels);
u32 ntfs_log_clear_levels(u32 levels);
u32 ntfs_log_get_levels(void);
/* Enable/disable certain log flags */
u32 ntfs_log_set_flags( u32 flags );
u32 ntfs_log_clear_flags( u32 flags );
u32 ntfs_log_get_flags( void );
u32 ntfs_log_set_flags(u32 flags);
u32 ntfs_log_clear_flags(u32 flags);
u32 ntfs_log_get_flags(void);
/* Turn command-line options into logging flags */
BOOL ntfs_log_parse_option( const char *option );
BOOL ntfs_log_parse_option(const char *option);
int ntfs_log_redirect( const char *function, const char *file, int line,
u32 level, void *data, const char *format, ... )
__attribute__( ( format( printf, 6, 7 ) ) );
int ntfs_log_redirect(const char *function, const char *file, int line,
u32 level, void *data, const char *format, ...)
__attribute__((format(printf, 6, 7)));
/* Logging levels - Determine what gets logged */
#define NTFS_LOG_LEVEL_DEBUG (1 << 0) /* x = 42 */

View File

@ -24,23 +24,20 @@
#include <malloc.h>
static inline void* ntfs_alloc ( size_t size )
{
return malloc( size );
static inline void* ntfs_alloc (size_t size) {
return malloc(size);
}
static inline void* ntfs_align ( size_t size )
{
#ifdef __wii__
return memalign( 32, size );
#else
return malloc( size );
#endif
static inline void* ntfs_align (size_t size) {
#ifdef __wii__
return memalign(32, size);
#else
return malloc(size);
#endif
}
static inline void ntfs_free ( void* mem )
{
free( mem );
static inline void ntfs_free (void* mem) {
free(mem);
}
#endif /* _MEM_ALLOCATE_H */

File diff suppressed because it is too large Load Diff

View File

@ -29,8 +29,8 @@
#include "layout.h"
#include "logging.h"
extern int ntfs_mft_records_read( const ntfs_volume *vol, const MFT_REF mref,
const s64 count, MFT_RECORD *b );
extern int ntfs_mft_records_read(const ntfs_volume *vol, const MFT_REF mref,
const s64 count, MFT_RECORD *b);
/**
* ntfs_mft_record_read - read a record from the mft
@ -47,25 +47,25 @@ extern int ntfs_mft_records_read( const ntfs_volume *vol, const MFT_REF mref,
*
* NOTE: @b has to be at least of size vol->mft_record_size.
*/
static __inline__ int ntfs_mft_record_read( const ntfs_volume *vol,
const MFT_REF mref, MFT_RECORD *b )
static __inline__ int ntfs_mft_record_read(const ntfs_volume *vol,
const MFT_REF mref, MFT_RECORD *b)
{
int ret;
ntfs_log_enter( "Entering for inode %lld\n", ( long long )MREF( mref ) );
ret = ntfs_mft_records_read( vol, mref, 1, b );
ntfs_log_leave( "\n" );
ntfs_log_enter("Entering for inode %lld\n", (long long)MREF(mref));
ret = ntfs_mft_records_read(vol, mref, 1, b);
ntfs_log_leave("\n");
return ret;
}
extern int ntfs_mft_record_check( const ntfs_volume *vol, const MFT_REF mref,
MFT_RECORD *m );
extern int ntfs_mft_record_check(const ntfs_volume *vol, const MFT_REF mref,
MFT_RECORD *m);
extern int ntfs_file_record_read( const ntfs_volume *vol, const MFT_REF mref,
MFT_RECORD **mrec, ATTR_RECORD **attr );
extern int ntfs_file_record_read(const ntfs_volume *vol, const MFT_REF mref,
MFT_RECORD **mrec, ATTR_RECORD **attr);
extern int ntfs_mft_records_write( const ntfs_volume *vol, const MFT_REF mref,
const s64 count, MFT_RECORD *b );
extern int ntfs_mft_records_write(const ntfs_volume *vol, const MFT_REF mref,
const s64 count, MFT_RECORD *b);
/**
* ntfs_mft_record_write - write an mft record to disk
@ -82,14 +82,14 @@ extern int ntfs_mft_records_write( const ntfs_volume *vol, const MFT_REF mref,
*
* NOTE: @b has to be at least of size vol->mft_record_size.
*/
static __inline__ int ntfs_mft_record_write( const ntfs_volume *vol,
const MFT_REF mref, MFT_RECORD *b )
static __inline__ int ntfs_mft_record_write(const ntfs_volume *vol,
const MFT_REF mref, MFT_RECORD *b)
{
int ret;
ntfs_log_enter( "Entering for inode %lld\n", ( long long )MREF( mref ) );
ret = ntfs_mft_records_write( vol, mref, 1, b );
ntfs_log_leave( "\n" );
ntfs_log_enter("Entering for inode %lld\n", (long long)MREF(mref));
ret = ntfs_mft_records_write(vol, mref, 1, b);
ntfs_log_leave("\n");
return ret;
}
@ -109,24 +109,24 @@ static __inline__ int ntfs_mft_record_write( const ntfs_volume *vol,
* non-existent (don't know if Windows' NTFS driver/chkdsk wouldn't view this
* as corruption in itself though).
*/
static __inline__ u32 ntfs_mft_record_get_data_size( const MFT_RECORD *m )
static __inline__ u32 ntfs_mft_record_get_data_size(const MFT_RECORD *m)
{
if ( !m || !ntfs_is_mft_record( m->magic ) )
if (!m || !ntfs_is_mft_record(m->magic))
return 0;
/* Get the number of used bytes and return it. */
return le32_to_cpu( m->bytes_in_use );
return le32_to_cpu(m->bytes_in_use);
}
extern int ntfs_mft_record_layout( const ntfs_volume *vol, const MFT_REF mref,
MFT_RECORD *mrec );
extern int ntfs_mft_record_layout(const ntfs_volume *vol, const MFT_REF mref,
MFT_RECORD *mrec);
extern int ntfs_mft_record_format( const ntfs_volume *vol, const MFT_REF mref );
extern int ntfs_mft_record_format(const ntfs_volume *vol, const MFT_REF mref);
extern ntfs_inode *ntfs_mft_record_alloc( ntfs_volume *vol, ntfs_inode *base_ni );
extern ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, ntfs_inode *base_ni);
extern int ntfs_mft_record_free( ntfs_volume *vol, ntfs_inode *ni );
extern int ntfs_mft_record_free(ntfs_volume *vol, ntfs_inode *ni);
extern int ntfs_mft_usn_dec( MFT_RECORD *mrec );
extern int ntfs_mft_usn_dec(MFT_RECORD *mrec);
#endif /* defined _NTFS_MFT_H */

View File

@ -40,22 +40,22 @@
*
* Return a pointer to the allocated memory or NULL if the request fails.
*/
void *ntfs_calloc( size_t size )
void *ntfs_calloc(size_t size)
{
void *p;
p = calloc( 1, size );
if ( !p )
ntfs_log_perror( "Failed to calloc %lld bytes", ( long long )size );
p = calloc(1, size);
if (!p)
ntfs_log_perror("Failed to calloc %lld bytes", (long long)size);
return p;
}
void *ntfs_malloc( size_t size )
void *ntfs_malloc(size_t size)
{
void *p;
p = malloc( size );
if ( !p )
ntfs_log_perror( "Failed to malloc %lld bytes", ( long long )size );
p = malloc(size);
if (!p)
ntfs_log_perror("Failed to malloc %lld bytes", (long long)size);
return p;
}

View File

@ -23,8 +23,8 @@
#ifndef _NTFS_MISC_H_
#define _NTFS_MISC_H_
void *ntfs_calloc( size_t size );
void *ntfs_malloc( size_t size );
void *ntfs_calloc(size_t size);
void *ntfs_malloc(size_t size);
#endif /* _NTFS_MISC_H_ */

View File

@ -47,30 +47,29 @@
* EIO Multi sector transfer error was detected. Magic of the NTFS
* record in @b will have been set to "BAAD".
*/
int ntfs_mst_post_read_fixup( NTFS_RECORD *b, const u32 size )
int ntfs_mst_post_read_fixup(NTFS_RECORD *b, const u32 size)
{
u16 usa_ofs, usa_count, usn;
u16 *usa_pos, *data_pos;
ntfs_log_trace( "Entering\n" );
ntfs_log_trace("Entering\n");
/* Setup the variables. */
usa_ofs = le16_to_cpu( b->usa_ofs );
usa_ofs = le16_to_cpu(b->usa_ofs);
/* Decrement usa_count to get number of fixups. */
usa_count = le16_to_cpu( b->usa_count ) - 1;
usa_count = le16_to_cpu(b->usa_count) - 1;
/* Size and alignment checks. */
if ( size & ( NTFS_BLOCK_SIZE - 1 ) || usa_ofs & 1 ||
( u32 )( usa_ofs + ( usa_count * 2 ) ) > size ||
( size >> NTFS_BLOCK_SIZE_BITS ) != usa_count )
{
if (size & (NTFS_BLOCK_SIZE - 1) || usa_ofs & 1 ||
(u32)(usa_ofs + (usa_count * 2)) > size ||
(size >> NTFS_BLOCK_SIZE_BITS) != usa_count) {
errno = EINVAL;
ntfs_log_perror( "%s: magic: 0x%08x size: %d usa_ofs: %d "
"usa_count: %d", __FUNCTION__, *( le32 * )b,
size, usa_ofs, usa_count );
ntfs_log_perror("%s: magic: 0x%08x size: %d usa_ofs: %d "
"usa_count: %d", __FUNCTION__, *(le32 *)b,
size, usa_ofs, usa_count);
return -1;
}
/* Position of usn in update sequence array. */
usa_pos = ( u16* )b + usa_ofs / sizeof( u16 );
usa_pos = (u16*)b + usa_ofs/sizeof(u16);
/*
* The update sequence number which has to be equal to each of the
* u16 values before they are fixed up. Note no need to care for
@ -82,42 +81,39 @@ int ntfs_mst_post_read_fixup( NTFS_RECORD *b, const u32 size )
/*
* Position in protected 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;
/*
* Check for incomplete multi sector transfer(s).
*/
while ( usa_count-- )
{
if ( *data_pos != usn )
{
while (usa_count--) {
if (*data_pos != usn) {
/*
* Incomplete multi sector transfer detected! )-:
* Set the magic to "BAAD" and return failure.
* Note that magic_BAAD is already converted to le32.
*/
errno = EIO;
ntfs_log_perror( "Incomplete multi-sector transfer: "
ntfs_log_perror("Incomplete multi-sector transfer: "
"magic: 0x%08x size: %d usa_ofs: %d usa_count:"
" %d data: %d usn: %d", *( le32 * )b, size,
usa_ofs, usa_count, *data_pos, usn );
" %d data: %d usn: %d", *(le32 *)b, size,
usa_ofs, usa_count, *data_pos, usn);
b->magic = magic_BAAD;
return -1;
}
data_pos += NTFS_BLOCK_SIZE / sizeof( u16 );
data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
}
/* Re-setup the variables. */
usa_count = le16_to_cpu( b->usa_count ) - 1;
data_pos = ( u16* )b + NTFS_BLOCK_SIZE / sizeof( u16 ) - 1;
usa_count = le16_to_cpu(b->usa_count) - 1;
data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
/* Fixup all sectors. */
while ( usa_count-- )
{
while (usa_count--) {
/*
* Increment position in usa and restore original data from
* the usa into the data buffer.
*/
*data_pos = *( ++usa_pos );
*data_pos = *(++usa_pos);
/* Increment position in data as well. */
data_pos += NTFS_BLOCK_SIZE / sizeof( u16 );
data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
}
return 0;
}
@ -142,59 +138,56 @@ int ntfs_mst_post_read_fixup( NTFS_RECORD *b, const u32 size )
* otherwise a random word will be used (whatever was in the record at that
* position at that time).
*/
int ntfs_mst_pre_write_fixup( NTFS_RECORD *b, const u32 size )
int ntfs_mst_pre_write_fixup(NTFS_RECORD *b, const u32 size)
{
u16 usa_ofs, usa_count, usn;
u16 *usa_pos, *data_pos;
ntfs_log_trace( "Entering\n" );
ntfs_log_trace("Entering\n");
/* Sanity check + only fixup if it makes sense. */
if ( !b || ntfs_is_baad_record( b->magic ) ||
ntfs_is_hole_record( b->magic ) )
{
if (!b || ntfs_is_baad_record(b->magic) ||
ntfs_is_hole_record(b->magic)) {
errno = EINVAL;
ntfs_log_perror( "%s: bad argument", __FUNCTION__ );
ntfs_log_perror("%s: bad argument", __FUNCTION__);
return -1;
}
/* Setup the variables. */
usa_ofs = le16_to_cpu( b->usa_ofs );
usa_ofs = le16_to_cpu(b->usa_ofs);
/* Decrement usa_count to get number of fixups. */
usa_count = le16_to_cpu( b->usa_count ) - 1;
usa_count = le16_to_cpu(b->usa_count) - 1;
/* Size and alignment checks. */
if ( size & ( NTFS_BLOCK_SIZE - 1 ) || usa_ofs & 1 ||
( u32 )( usa_ofs + ( usa_count * 2 ) ) > size ||
( size >> NTFS_BLOCK_SIZE_BITS ) != usa_count )
{
if (size & (NTFS_BLOCK_SIZE - 1) || usa_ofs & 1 ||
(u32)(usa_ofs + (usa_count * 2)) > size ||
(size >> NTFS_BLOCK_SIZE_BITS) != usa_count) {
errno = EINVAL;
ntfs_log_perror( "%s", __FUNCTION__ );
ntfs_log_perror("%s", __FUNCTION__);
return -1;
}
/* Position of usn in update sequence array. */
usa_pos = ( u16* )( ( u8* )b + usa_ofs );
usa_pos = (u16*)((u8*)b + usa_ofs);
/*
* Cyclically increment the update sequence number
* (skipping 0 and -1, i.e. 0xffff).
*/
usn = le16_to_cpup( usa_pos ) + 1;
if ( usn == 0xffff || !usn )
usn = le16_to_cpup(usa_pos) + 1;
if (usn == 0xffff || !usn)
usn = 1;
usn = cpu_to_le16( usn );
usn = cpu_to_le16(usn);
*usa_pos = usn;
/* 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. */
while ( usa_count-- )
{
while (usa_count--) {
/*
* Increment the position in the usa and save the
* original data from the data buffer into the usa.
*/
*( ++usa_pos ) = *data_pos;
*(++usa_pos) = *data_pos;
/* Apply fixup to data. */
*data_pos = usn;
/* Increment position in data as well. */
data_pos += NTFS_BLOCK_SIZE / sizeof( u16 );
data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
}
return 0;
}
@ -208,32 +201,31 @@ int ntfs_mst_pre_write_fixup( NTFS_RECORD *b, const u32 size )
* ntfs_mst_pre_write_fixup(), thus the data will be fine or we would never
* have gotten here.
*/
void ntfs_mst_post_write_fixup( NTFS_RECORD *b )
void ntfs_mst_post_write_fixup(NTFS_RECORD *b)
{
u16 *usa_pos, *data_pos;
u16 usa_ofs = le16_to_cpu( b->usa_ofs );
u16 usa_count = le16_to_cpu( b->usa_count ) - 1;
u16 usa_ofs = le16_to_cpu(b->usa_ofs);
u16 usa_count = le16_to_cpu(b->usa_count) - 1;
ntfs_log_trace( "Entering\n" );
ntfs_log_trace("Entering\n");
/* Position of usn in update sequence array. */
usa_pos = ( u16* )b + usa_ofs / sizeof( u16 );
usa_pos = (u16*)b + usa_ofs/sizeof(u16);
/* Position in protected 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. */
while ( usa_count-- )
{
while (usa_count--) {
/*
* Increment position in usa and restore original data from
* the usa into the data buffer.
*/
*data_pos = *( ++usa_pos );
*data_pos = *(++usa_pos);
/* Increment position in data as well. */
data_pos += NTFS_BLOCK_SIZE / sizeof( u16 );
data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
}
}

View File

@ -26,9 +26,9 @@
#include "types.h"
#include "layout.h"
extern int ntfs_mst_post_read_fixup( NTFS_RECORD *b, const u32 size );
extern int ntfs_mst_pre_write_fixup( NTFS_RECORD *b, const u32 size );
extern void ntfs_mst_post_write_fixup( NTFS_RECORD *b );
extern int ntfs_mst_post_read_fixup(NTFS_RECORD *b, const u32 size);
extern int ntfs_mst_pre_write_fixup(NTFS_RECORD *b, const u32 size);
extern void ntfs_mst_post_write_fixup(NTFS_RECORD *b);
#endif /* defined _NTFS_MST_H */

View File

@ -41,10 +41,9 @@
#include "cache.h"
// NTFS device driver devoptab
static const devoptab_t devops_ntfs =
{
static const devoptab_t devops_ntfs = {
NULL, /* Device name */
sizeof ( ntfs_file_state ),
sizeof (ntfs_file_state),
ntfs_open_r,
ntfs_close_r,
ntfs_write_r,
@ -57,7 +56,7 @@ static const devoptab_t devops_ntfs =
ntfs_chdir_r,
ntfs_rename_r,
ntfs_mkdir_r,
sizeof ( ntfs_dir_state ),
sizeof (ntfs_dir_state),
ntfs_diropen_r,
ntfs_dirreset_r,
ntfs_dirnext_r,
@ -68,21 +67,20 @@ static const devoptab_t devops_ntfs =
NULL /* Device data */
};
void ntfsInit ( void )
void ntfsInit (void)
{
static bool isInit = false;
// Initialise ntfs-3g (if not already done so)
if ( !isInit )
{
if (!isInit) {
isInit = true;
// Set the log handler
#ifdef NTFS_ENABLE_LOG
ntfs_log_set_handler( ntfs_log_handler_stderr );
#else
ntfs_log_set_handler( ntfs_log_handler_null );
#endif
#ifdef NTFS_ENABLE_LOG
ntfs_log_set_handler(ntfs_log_handler_stderr);
#else
ntfs_log_set_handler(ntfs_log_handler_null);
#endif
// Set our current local
ntfs_set_locale();
@ -91,7 +89,7 @@ void ntfsInit ( void )
return;
}
int ntfsFindPartitions ( const DISC_INTERFACE *interface, sec_t **partitions )
int ntfsFindPartitions (const DISC_INTERFACE *interface, sec_t **partitions)
{
MASTER_BOOT_RECORD mbr;
PARTITION_RECORD *partition = NULL;
@ -100,8 +98,7 @@ int ntfsFindPartitions ( const DISC_INTERFACE *interface, sec_t **partitions )
sec_t part_lba = 0;
int i;
union
{
union {
u8 buffer[512];
MASTER_BOOT_RECORD mbr;
EXTENDED_BOOT_RECORD ebr;
@ -109,79 +106,66 @@ int ntfsFindPartitions ( const DISC_INTERFACE *interface, sec_t **partitions )
} sector;
// Sanity check
if ( !interface )
{
if (!interface) {
errno = EINVAL;
return -1;
}
if ( !partitions )
if (!partitions)
return 0;
// Initialise ntfs-3g
ntfsInit();
// Start the device and check that it is inserted
if ( !interface->startup() )
{
if (!interface->startup()) {
errno = EIO;
return -1;
}
if ( !interface->isInserted() )
{
if (!interface->isInserted()) {
return 0;
}
// Read the first sector on the device
if ( !interface->readSectors( 0, 1, &sector.buffer ) )
{
if (!interface->readSectors(0, 1, &sector.buffer)) {
errno = EIO;
return -1;
}
// If this is the devices master boot record
if ( sector.mbr.signature == MBR_SIGNATURE )
{
memcpy( &mbr, &sector, sizeof( MASTER_BOOT_RECORD ) );
ntfs_log_debug( "Valid Master Boot Record found\n" );
if (sector.mbr.signature == MBR_SIGNATURE) {
memcpy(&mbr, &sector, sizeof(MASTER_BOOT_RECORD));
ntfs_log_debug("Valid Master Boot Record found\n");
// 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];
part_lba = le32_to_cpu( mbr.partitions[i].lba_start );
part_lba = le32_to_cpu(mbr.partitions[i].lba_start);
ntfs_log_debug( "Partition %i: %s, sector %d, type 0x%x\n", i + 1,
ntfs_log_debug("Partition %i: %s, sector %d, type 0x%x\n", i + 1,
partition->status == PARTITION_STATUS_BOOTABLE ? "bootable (active)" : "non-bootable",
part_lba, partition->type );
part_lba, partition->type);
// Figure out what type of partition this is
switch ( partition->type )
{
switch (partition->type) {
// Ignore empty partitions
case PARTITION_TYPE_EMPTY:
continue;
// NTFS partition
case PARTITION_TYPE_NTFS:
{
ntfs_log_debug( "Partition %i: Claims to be NTFS\n", i + 1 );
case PARTITION_TYPE_NTFS: {
ntfs_log_debug("Partition %i: Claims to be NTFS\n", i + 1);
// Read and validate the NTFS partition
if ( interface->readSectors( part_lba, 1, &sector ) )
{
if ( sector.boot.oem_id == NTFS_OEM_ID )
{
ntfs_log_debug( "Partition %i: Valid NTFS boot sector found\n", i + 1 );
if ( partition_count < NTFS_MAX_PARTITIONS )
{
if (interface->readSectors(part_lba, 1, &sector)) {
if (sector.boot.oem_id == NTFS_OEM_ID) {
ntfs_log_debug("Partition %i: Valid NTFS boot sector found\n", i + 1);
if (partition_count < NTFS_MAX_PARTITIONS) {
partition_starts[partition_count] = part_lba;
partition_count++;
}
}
else
{
ntfs_log_debug( "Partition %i: Invalid NTFS boot sector, not actually NTFS\n", i + 1 );
} else {
ntfs_log_debug("Partition %i: Invalid NTFS boot sector, not actually NTFS\n", i + 1);
}
}
@ -191,79 +175,63 @@ int ntfsFindPartitions ( const DISC_INTERFACE *interface, sec_t **partitions )
// DOS 3.3+ or Windows 95 extended partition
case PARTITION_TYPE_DOS33_EXTENDED:
case PARTITION_TYPE_WIN95_EXTENDED:
{
ntfs_log_debug( "Partition %i: Claims to be Extended\n", i + 1 );
case PARTITION_TYPE_WIN95_EXTENDED: {
ntfs_log_debug("Partition %i: Claims to be Extended\n", i + 1);
// Walk the extended partition chain, finding all NTFS partitions within it
sec_t ebr_lba = part_lba;
sec_t next_erb_lba = 0;
do
{
do {
// Read and validate the extended boot record
if ( interface->readSectors( ebr_lba + next_erb_lba, 1, &sector ) )
{
if ( sector.ebr.signature == EBR_SIGNATURE )
{
ntfs_log_debug( "Logical Partition @ %d: type 0x%x\n", ebr_lba + next_erb_lba,
if (interface->readSectors(ebr_lba + next_erb_lba, 1, &sector)) {
if (sector.ebr.signature == EBR_SIGNATURE) {
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.type );
sector.ebr.partition.type);
// Get the start sector of the current partition
// and the next extended boot record in the chain
part_lba = ebr_lba + next_erb_lba + le32_to_cpu( sector.ebr.partition.lba_start );
next_erb_lba = le32_to_cpu( sector.ebr.next_ebr.lba_start );
part_lba = ebr_lba + next_erb_lba + le32_to_cpu(sector.ebr.partition.lba_start);
next_erb_lba = le32_to_cpu(sector.ebr.next_ebr.lba_start);
// Check if this partition has a valid NTFS boot record
if ( interface->readSectors( part_lba, 1, &sector ) )
{
if ( sector.boot.oem_id == NTFS_OEM_ID )
{
ntfs_log_debug( "Logical Partition @ %d: Valid NTFS boot sector found\n", part_lba );
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 );
if (interface->readSectors(part_lba, 1, &sector)) {
if (sector.boot.oem_id == NTFS_OEM_ID) {
ntfs_log_debug("Logical Partition @ %d: Valid NTFS boot sector found\n", part_lba);
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);
}
if ( partition_count < NTFS_MAX_PARTITIONS )
{
if (partition_count < NTFS_MAX_PARTITIONS) {
partition_starts[partition_count] = part_lba;
partition_count++;
}
}
}
}
else
{
} else {
next_erb_lba = 0;
}
}
}
while ( next_erb_lba );
} while (next_erb_lba);
break;
}
// Unknown or unsupported partition type
default:
{
default: {
// Check if this partition has a valid NTFS boot record anyway,
// it might be misrepresented due to a lazy partition editor
if ( interface->readSectors( part_lba, 1, &sector ) )
{
if ( sector.boot.oem_id == NTFS_OEM_ID )
{
ntfs_log_debug( "Partition %i: Valid NTFS boot sector found\n", i + 1 );
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 );
if (interface->readSectors(part_lba, 1, &sector)) {
if (sector.boot.oem_id == NTFS_OEM_ID) {
ntfs_log_debug("Partition %i: Valid NTFS boot sector found\n", i + 1);
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);
}
if ( partition_count < NTFS_MAX_PARTITIONS )
{
if (partition_count < NTFS_MAX_PARTITIONS) {
partition_starts[partition_count] = part_lba;
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
{
ntfs_log_debug( "No Master Boot Record was found!\n" );
} else {
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
for ( i = 0; i < 64; i++ )
{
if ( interface->readSectors( i, 1, &sector ) )
{
if ( sector.boot.oem_id == NTFS_OEM_ID )
{
ntfs_log_debug( "Valid NTFS boot sector found at sector %d!\n", i );
if ( partition_count < NTFS_MAX_PARTITIONS )
{
for (i = 0; i < 64; i++) {
if (interface->readSectors(i, 1, &sector)) {
if (sector.boot.oem_id == NTFS_OEM_ID) {
ntfs_log_debug("Valid NTFS boot sector found at sector %d!\n", i);
if (partition_count < NTFS_MAX_PARTITIONS) {
partition_starts[partition_count] = i;
partition_count++;
}
@ -307,12 +269,10 @@ int ntfsFindPartitions ( const DISC_INTERFACE *interface, sec_t **partitions )
/*interface->shutdown();*/
// Return the found partitions (if any)
if ( partition_count > 0 )
{
*partitions = ( sec_t* )ntfs_alloc( sizeof( sec_t ) * partition_count );
if ( *partitions )
{
memcpy( *partitions, &partition_starts, sizeof( sec_t ) * partition_count );
if (partition_count > 0) {
*partitions = (sec_t*)ntfs_alloc(sizeof(sec_t) * partition_count);
if (*partitions) {
memcpy(*partitions, &partition_starts, sizeof(sec_t) * partition_count);
return partition_count;
}
}
@ -320,7 +280,7 @@ int ntfsFindPartitions ( const DISC_INTERFACE *interface, sec_t **partitions )
return 0;
}
int ntfsMountAll ( ntfs_md **mounts, u32 flags )
int ntfsMountAll (ntfs_md **mounts, u32 flags)
{
const INTERFACE_ID *discs = ntfsGetDiscInterfaces();
const INTERFACE_ID *disc = NULL;
@ -335,34 +295,26 @@ int ntfsMountAll ( ntfs_md **mounts, u32 flags )
ntfsInit();
// 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];
partition_count = ntfsFindPartitions( disc->interface, &partitions );
if ( partition_count > 0 && partitions )
{
for ( j = 0, k = 0; j < partition_count; j++ )
{
partition_count = ntfsFindPartitions(disc->interface, &partitions);
if (partition_count > 0 && partitions) {
for (j = 0, k = 0; j < partition_count; j++) {
// Find the next unused mount name
do
{
sprintf( name, "%s%i", NTFS_MOUNT_PREFIX, k++ );
if ( k >= NTFS_MAX_MOUNTS )
{
ntfs_free( partitions );
do {
sprintf(name, "%s%i", NTFS_MOUNT_PREFIX, k++);
if (k >= NTFS_MAX_MOUNTS) {
ntfs_free(partitions);
errno = EADDRNOTAVAIL;
return -1;
}
}
while ( ntfsGetDevice( name, false ) );
} while (ntfsGetDevice(name, false));
// Mount the partition
if ( mount_count < NTFS_MAX_MOUNTS )
{
if ( ntfsMount( name, disc->interface, partitions[j], CACHE_DEFAULT_PAGE_SIZE, CACHE_DEFAULT_PAGE_COUNT, flags ) )
{
strcpy( mount_points[mount_count].name, name );
if (mount_count < NTFS_MAX_MOUNTS) {
if (ntfsMount(name, disc->interface, partitions[j], CACHE_DEFAULT_PAGE_SIZE, CACHE_DEFAULT_PAGE_COUNT, flags)) {
strcpy(mount_points[mount_count].name, name);
mount_points[mount_count].interface = disc->interface;
mount_points[mount_count].startSector = partitions[j];
mount_count++;
@ -370,17 +322,15 @@ int ntfsMountAll ( ntfs_md **mounts, u32 flags )
}
}
ntfs_free( partitions );
ntfs_free(partitions);
}
}
// Return the mounts (if any)
if ( mount_count > 0 && mounts )
{
*mounts = ( ntfs_md* )ntfs_alloc( sizeof( ntfs_md ) * mount_count );
if ( *mounts )
{
memcpy( *mounts, &mount_points, sizeof( ntfs_md ) * mount_count );
if (mount_count > 0 && mounts) {
*mounts = (ntfs_md*)ntfs_alloc(sizeof(ntfs_md) * mount_count);
if (*mounts) {
memcpy(*mounts, &mount_points, sizeof(ntfs_md) * mount_count);
return mount_count;
}
}
@ -388,7 +338,7 @@ int ntfsMountAll ( ntfs_md **mounts, u32 flags )
return 0;
}
int ntfsMountDevice ( const DISC_INTERFACE *interface, ntfs_md **mounts, u32 flags )
int ntfsMountDevice (const DISC_INTERFACE *interface, ntfs_md **mounts, u32 flags)
{
const INTERFACE_ID *discs = ntfsGetDiscInterfaces();
const INTERFACE_ID *disc = NULL;
@ -400,8 +350,7 @@ int ntfsMountDevice ( const DISC_INTERFACE *interface, ntfs_md **mounts, u32 fla
int i, j, k;
// Sanity check
if ( !interface )
{
if (!interface) {
errno = EINVAL;
return -1;
}
@ -410,36 +359,27 @@ int ntfsMountDevice ( const DISC_INTERFACE *interface, ntfs_md **mounts, u32 fla
ntfsInit();
// 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++ )
{
if ( discs[i].interface == interface )
{
for (i = 0; discs[i].name != NULL && discs[i].interface != NULL; i++) {
if (discs[i].interface == interface) {
disc = &discs[i];
partition_count = ntfsFindPartitions( disc->interface, &partitions );
if ( partition_count > 0 && partitions )
{
for ( j = 0, k = 0; j < partition_count; j++ )
{
partition_count = ntfsFindPartitions(disc->interface, &partitions);
if (partition_count > 0 && partitions) {
for (j = 0, k = 0; j < partition_count; j++) {
// Find the next unused mount name
do
{
sprintf( name, "%s%i", NTFS_MOUNT_PREFIX, k++ );
if ( k >= NTFS_MAX_MOUNTS )
{
ntfs_free( partitions );
do {
sprintf(name, "%s%i", NTFS_MOUNT_PREFIX, k++);
if (k >= NTFS_MAX_MOUNTS) {
ntfs_free(partitions);
errno = EADDRNOTAVAIL;
return -1;
}
}
while ( ntfsGetDevice( name, false ) );
} while (ntfsGetDevice(name, false));
// Mount the partition
if ( mount_count < NTFS_MAX_MOUNTS )
{
if ( ntfsMount( name, disc->interface, partitions[j], CACHE_DEFAULT_PAGE_SIZE, CACHE_DEFAULT_PAGE_COUNT, flags ) )
{
strcpy( mount_points[mount_count].name, name );
if (mount_count < NTFS_MAX_MOUNTS) {
if (ntfsMount(name, disc->interface, partitions[j], CACHE_DEFAULT_PAGE_SIZE, CACHE_DEFAULT_PAGE_COUNT, flags)) {
strcpy(mount_points[mount_count].name, name);
mount_points[mount_count].interface = disc->interface;
mount_points[mount_count].startSector = partitions[j];
mount_count++;
@ -447,26 +387,23 @@ int ntfsMountDevice ( const DISC_INTERFACE *interface, ntfs_md **mounts, u32 fla
}
}
ntfs_free( partitions );
ntfs_free(partitions);
}
break;
}
}
// If we couldn't find the device then return with error status
if ( !disc )
{
if (!disc) {
errno = ENODEV;
return -1;
}
// Return the mounts (if any)
if ( mount_count > 0 && mounts )
{
*mounts = ( ntfs_md* )ntfs_alloc( sizeof( ntfs_md ) * mount_count );
if ( *mounts )
{
memcpy( *mounts, &mount_points, sizeof( ntfs_md ) * mount_count );
if (mount_count > 0 && mounts) {
*mounts = (ntfs_md*)ntfs_alloc(sizeof(ntfs_md) * mount_count);
if (*mounts) {
memcpy(*mounts, &mount_points, sizeof(ntfs_md) * mount_count);
return mount_count;
}
}
@ -474,14 +411,13 @@ int ntfsMountDevice ( const DISC_INTERFACE *interface, ntfs_md **mounts, u32 fla
return 0;
}
bool ntfsMount ( const char *name, const DISC_INTERFACE *interface, sec_t startSector, u32 cachePageCount, u32 cachePageSize, u32 flags )
bool ntfsMount (const char *name, const DISC_INTERFACE *interface, sec_t startSector, u32 cachePageCount, u32 cachePageSize, u32 flags)
{
ntfs_vd *vd = NULL;
gekko_fd *fd = NULL;
// Sanity check
if ( !name || !interface )
{
if (!name || !interface) {
errno = EINVAL;
return false;
}
@ -490,23 +426,20 @@ bool ntfsMount ( const char *name, const DISC_INTERFACE *interface, sec_t startS
ntfsInit();
// Check that the requested mount name is free
if ( ntfsGetDevice( name, false ) )
{
if (ntfsGetDevice(name, false)) {
errno = EADDRINUSE;
return false;
}
// Check that we can at least read from this device
if ( !( interface->features & FEATURE_MEDIUM_CANREAD ) )
{
if (!(interface->features & FEATURE_MEDIUM_CANREAD)) {
errno = EPERM;
return false;
}
// Allocate the volume descriptor
vd = ( ntfs_vd* )ntfs_alloc( sizeof( ntfs_vd ) );
if ( !vd )
{
vd = (ntfs_vd*)ntfs_alloc(sizeof(ntfs_vd));
if (!vd) {
errno = ENOMEM;
return false;
}
@ -518,15 +451,14 @@ bool ntfsMount ( const char *name, const DISC_INTERFACE *interface, sec_t startS
vd->gid = 0;
vd->fmask = 0;
vd->dmask = 0;
vd->atime = ( ( flags & NTFS_UPDATE_ACCESS_TIMES ) ? ATIME_ENABLED : ATIME_DISABLED );
vd->showHiddenFiles = ( flags & NTFS_SHOW_HIDDEN_FILES );
vd->showSystemFiles = ( flags & NTFS_SHOW_SYSTEM_FILES );
vd->atime = ((flags & NTFS_UPDATE_ACCESS_TIMES) ? ATIME_ENABLED : ATIME_DISABLED);
vd->showHiddenFiles = (flags & NTFS_SHOW_HIDDEN_FILES);
vd->showSystemFiles = (flags & NTFS_SHOW_SYSTEM_FILES);
// Allocate the device driver descriptor
fd = ( gekko_fd* )ntfs_alloc( sizeof( gekko_fd ) );
if ( !fd )
{
ntfs_free( vd );
fd = (gekko_fd*)ntfs_alloc(sizeof(gekko_fd));
if (!fd) {
ntfs_free(vd);
errno = ENOMEM;
return false;
}
@ -540,94 +472,92 @@ bool ntfsMount ( const char *name, const DISC_INTERFACE *interface, sec_t startS
fd->cachePageSize = cachePageSize;
// Allocate the device driver
vd->dev = ntfs_device_alloc( name, 0, &ntfs_device_gekko_io_ops, fd );
if ( !vd->dev )
{
ntfs_free( fd );
ntfs_free( vd );
vd->dev = ntfs_device_alloc(name, 0, &ntfs_device_gekko_io_ops, fd);
if (!vd->dev) {
ntfs_free(fd);
ntfs_free(vd);
return false;
}
// Build the mount flags
if ( flags & NTFS_READ_ONLY )
if (flags & NTFS_READ_ONLY)
vd->flags |= MS_RDONLY;
else
{
if ( !( interface->features & FEATURE_MEDIUM_CANWRITE ) )
if (!(interface->features & FEATURE_MEDIUM_CANWRITE))
vd->flags |= MS_RDONLY;
if ( ( interface->features & FEATURE_MEDIUM_CANREAD ) && ( interface->features & FEATURE_MEDIUM_CANWRITE ) )
if ((interface->features & FEATURE_MEDIUM_CANREAD) && (interface->features & FEATURE_MEDIUM_CANWRITE))
vd->flags |= MS_EXCLUSIVE;
}
if ( flags & NTFS_RECOVER )
if (flags & NTFS_RECOVER)
vd->flags |= MS_RECOVER;
if ( flags & NTFS_IGNORE_HIBERFILE )
if (flags & NTFS_IGNORE_HIBERFILE)
vd->flags |= MS_IGNORE_HIBERFILE;
if ( vd->flags & MS_RDONLY )
ntfs_log_debug( "Mounting \"%s\" as read-only\n", name );
if (vd->flags & MS_RDONLY)
ntfs_log_debug("Mounting \"%s\" as read-only\n", name);
// Mount the device
vd->vol = ntfs_device_mount( vd->dev, vd->flags );
if ( !vd->vol )
{
switch ( ntfs_volume_error( errno ) )
{
vd->vol = ntfs_device_mount(vd->dev, vd->flags);
if (!vd->vol) {
switch(ntfs_volume_error(errno)) {
case NTFS_VOLUME_NOT_NTFS: errno = EINVALPART; break;
case NTFS_VOLUME_CORRUPT: errno = EINVALPART; break;
case NTFS_VOLUME_HIBERNATED: errno = EHIBERNATED; break;
case NTFS_VOLUME_UNCLEAN_UNMOUNT: errno = EDIRTY; break;
default: errno = EINVAL; break;
}
ntfs_device_free( vd->dev );
ntfs_free( vd );
ntfs_device_free(vd->dev);
ntfs_free(vd);
return false;
}
if (flags & NTFS_IGNORE_CASE)
ntfs_set_ignore_case(vd->vol);
// Initialise the volume descriptor
if ( ntfsInitVolume( vd ) )
{
ntfs_umount( vd->vol, true );
ntfs_free( vd );
if (ntfsInitVolume(vd)) {
ntfs_umount(vd->vol, true);
ntfs_free(vd);
return false;
}
// Add the device to the devoptab table
if ( ntfsAddDevice( name, vd ) )
{
ntfsDeinitVolume( vd );
ntfs_umount( vd->vol, true );
ntfs_free( vd );
if (ntfsAddDevice(name, vd)) {
ntfsDeinitVolume(vd);
ntfs_umount(vd->vol, true);
ntfs_free(vd);
return false;
}
return true;
}
void ntfsUnmount ( const char *name, bool force )
void ntfsUnmount (const char *name, bool force)
{
ntfs_vd *vd = NULL;
// Get the devices volume descriptor
vd = ntfsGetVolume( name );
if ( !vd )
vd = ntfsGetVolume(name);
if (!vd)
return;
// Remove the device from the devoptab table
ntfsRemoveDevice( name );
ntfsRemoveDevice(name);
// Deinitialise the volume descriptor
ntfsDeinitVolume( vd );
ntfsDeinitVolume(vd);
// Unmount the volume
ntfs_umount( vd->vol, force );
ntfs_umount(vd->vol, force);
// Free the volume descriptor
ntfs_free( vd );
ntfs_free(vd);
return;
}
const char *ntfsGetVolumeName ( const char *name )
const char *ntfsGetVolumeName (const char *name)
{
ntfs_vd *vd = NULL;
//ntfs_attr *na = NULL;
@ -635,21 +565,19 @@ const char *ntfsGetVolumeName ( const char *name )
//char *volumeName = NULL;
// Sanity check
if ( !name )
{
if (!name) {
errno = EINVAL;
return NULL;
}
// Get the devices volume descriptor
vd = ntfsGetVolume( name );
if ( !vd )
{
vd = ntfsGetVolume(name);
if (!vd) {
errno = ENODEV;
return NULL;
}
return vd->vol->vol_name;
/*
/*
// If the volume name has already been cached then just use that
if (vd->name[0])
@ -706,10 +634,10 @@ const char *ntfsGetVolumeName ( const char *name )
ntfsUnlock(vd);
return vd->name;
*/
*/
}
bool ntfsSetVolumeName ( const char *name, const char *volumeName )
bool ntfsSetVolumeName (const char *name, const char *volumeName)
{
ntfs_vd *vd = NULL;
ntfs_attr *na = NULL;
@ -717,62 +645,53 @@ bool ntfsSetVolumeName ( const char *name, const char *volumeName )
int ulabel_len;
// Sanity check
if ( !name )
{
if (!name) {
errno = EINVAL;
return false;
}
// Get the devices volume descriptor
vd = ntfsGetVolume( name );
if ( !vd )
{
vd = ntfsGetVolume(name);
if (!vd) {
errno = ENODEV;
return false;
}
// Lock
ntfsLock( vd );
ntfsLock(vd);
// Convert the new volume name to unicode
ulabel_len = ntfsLocalToUnicode( volumeName, &ulabel ) * sizeof( ntfschar );
if ( ulabel_len < 0 )
{
ntfsUnlock( vd );
ulabel_len = ntfsLocalToUnicode(volumeName, &ulabel) * sizeof(ntfschar);
if (ulabel_len < 0) {
ntfsUnlock(vd);
errno = EINVAL;
return false;
}
// Check if the volume name attribute exists
na = ntfs_attr_open( vd->vol->vol_ni, AT_VOLUME_NAME, NULL, 0 );
if ( na )
{
na = ntfs_attr_open(vd->vol->vol_ni, AT_VOLUME_NAME, NULL, 0);
if (na) {
// It does, resize it to match the length of the new volume name
if ( ntfs_attr_truncate( na, ulabel_len ) )
{
ntfs_free( ulabel );
ntfsUnlock( vd );
if (ntfs_attr_truncate(na, ulabel_len)) {
ntfs_free(ulabel);
ntfsUnlock(vd);
return false;
}
// Write the new volume name
if ( ntfs_attr_pwrite( na, 0, ulabel_len, ulabel ) != ulabel_len )
{
ntfs_free( ulabel );
ntfsUnlock( vd );
if (ntfs_attr_pwrite(na, 0, ulabel_len, ulabel) != ulabel_len) {
ntfs_free(ulabel);
ntfsUnlock(vd);
return false;
}
}
else
{
} else {
// It doesn't, create it now
if ( ntfs_attr_add( vd->vol->vol_ni, AT_VOLUME_NAME, NULL, 0, ( u8* )ulabel, ulabel_len ) )
{
ntfs_free( ulabel );
ntfsUnlock( vd );
if (ntfs_attr_add(vd->vol->vol_ni, AT_VOLUME_NAME, NULL, 0, (u8*)ulabel, ulabel_len)) {
ntfs_free(ulabel);
ntfsUnlock(vd);
return false;
}
@ -782,27 +701,26 @@ bool ntfsSetVolumeName ( const char *name, const char *volumeName )
vd->name[0] = '\0';
// Close the volume name attribute
if ( na )
ntfs_attr_close( na );
if (na)
ntfs_attr_close(na);
// Sync the volume node
if ( ntfs_inode_sync( vd->vol->vol_ni ) )
{
ntfs_free( ulabel );
ntfsUnlock( vd );
if (ntfs_inode_sync(vd->vol->vol_ni)) {
ntfs_free(ulabel);
ntfsUnlock(vd);
return false;
}
// Clean up
ntfs_free( ulabel );
ntfs_free(ulabel);
// Unlock
ntfsUnlock( vd );
ntfsUnlock(vd);
return true;
}
const devoptab_t *ntfsGetDevOpTab ( void )
const devoptab_t *ntfsGetDevOpTab (void)
{
return &devops_ntfs;
}

View File

@ -23,25 +23,24 @@
#define _LIBNTFS_H
#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif
#include <gctypes.h>
#include <gccore.h>
#include <ogc/disc_io.h>
/* NTFS errno values */
/* NTFS errno values */
#define ENOPART 3000 /* No partition was found */
#define EINVALPART 3001 /* Specified partition is invalid or not supported */
#define EDIRTY 3002 /* Volume is dirty and NTFS_RECOVER was not specified during mount */
#define EHIBERNATED 3003 /* Volume is hibernated and NTFS_IGNORE_HIBERFILE was not specified during mount */
/* NTFS cache options */
/* NTFS cache options */
#define CACHE_DEFAULT_PAGE_COUNT 8 /* The default number of pages in the cache */
#define CACHE_DEFAULT_PAGE_SIZE 128 /* The default number of sectors per cache page */
/* NTFS mount flags */
/* NTFS mount flags */
#define NTFS_DEFAULT 0x00000000 /* Standard mount, expects a clean, non-hibernated volume */
#define NTFS_SHOW_HIDDEN_FILES 0x00000001 /* Display hidden files when enumerating directories */
#define NTFS_SHOW_SYSTEM_FILES 0x00000002 /* Display system files when enumerating directories */
@ -49,20 +48,20 @@ extern "C"
#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_READ_ONLY 0x00000020 /* Mount in read only mode */
#define NTFS_SU NTFS_SHOW_HIDDEN_FILES & NTFS_SHOW_SYSTEM_FILES
#define NTFS_FORCE NTFS_RECOVER & NTFS_IGNORE_HIBERFILE
#define NTFS_IGNORE_CASE 0x00000040 /* Ignore case sensitivity. Everything must be and will be provided in lowercase. */
#define NTFS_SU NTFS_SHOW_HIDDEN_FILES | NTFS_SHOW_SYSTEM_FILES
#define NTFS_FORCE NTFS_RECOVER | NTFS_IGNORE_HIBERFILE
/**
/**
* ntfs_md - NTFS mount descriptor
*/
typedef struct _ntfs_md
{
typedef struct _ntfs_md {
char name[32]; /* Mount name (can be accessed as "name:/") */
const DISC_INTERFACE *interface; /* Block device containing the mounted partition */
sec_t startSector; /* Local block address to first sector of partition */
} ntfs_md;
} ntfs_md;
/**
/**
* Find all NTFS partitions on a block device.
*
* @param INTERFACE The block device to search
@ -71,9 +70,9 @@ extern "C"
* @return The number of entries in PARTITIONS or -1 if an error occurred (see errno)
* @note The caller is responsible for freeing PARTITIONS when finished with it
*/
extern int ntfsFindPartitions ( const DISC_INTERFACE *interface, sec_t **partitions );
extern int ntfsFindPartitions (const DISC_INTERFACE *interface, sec_t **partitions);
/**
/**
* Mount all NTFS partitions on all inserted block devices.
*
* @param MOUNTS (out) A pointer to receive the array of mount descriptors
@ -83,9 +82,9 @@ extern "C"
* @note The caller is responsible for freeing MOUNTS when finished with it
* @note All device caches are setup using default values (see above)
*/
extern int ntfsMountAll ( ntfs_md **mounts, u32 flags );
extern int ntfsMountAll (ntfs_md **mounts, u32 flags);
/**
/**
* Mount all NTFS partitions on a block devices.
*
* @param INTERFACE The block device to mount.
@ -96,9 +95,9 @@ extern "C"
* @note The caller is responsible for freeing MOUNTS when finished with it
* @note The device cache is setup using default values (see above)
*/
extern int ntfsMountDevice ( const DISC_INTERFACE* interface, ntfs_md **mounts, u32 flags );
extern int ntfsMountDevice (const DISC_INTERFACE* interface, ntfs_md **mounts, u32 flags);
/**
/**
* Mount a NTFS partition from a specific sector on a block device.
*
* @param NAME The name to mount the device under (can then be accessed as "NAME:/")
@ -111,26 +110,26 @@ extern "C"
* @return True if mount was successful, false if no partition was found or an error occurred (see errno)
* @note ntfsFindPartitions should be used first to locate the partitions start sector
*/
extern bool ntfsMount ( const char *name, const DISC_INTERFACE *interface, sec_t startSector, u32 cachePageCount, u32 cachePageSize, u32 flags );
extern bool ntfsMount (const char *name, const DISC_INTERFACE *interface, sec_t startSector, u32 cachePageCount, u32 cachePageSize, u32 flags);
/**
/**
* Unmount a NTFS partition.
*
* @param NAME The name of mount used in ntfsMountSimple() and ntfsMount()
* @param FORCE If true unmount even if the device is busy (may lead to data lose)
*/
extern void ntfsUnmount ( const char *name, bool force );
extern void ntfsUnmount (const char *name, bool force);
/**
/**
* Get the volume name of a mounted NTFS partition.
*
* @param NAME The name of mount (see @ntfsMountAll, @ntfsMountDevice, and @ntfsMount)
*
* @return The volumes name if successful or NULL if an error occurred (see errno)
*/
extern const char *ntfsGetVolumeName ( const char *name );
extern const char *ntfsGetVolumeName (const char *name);
/**
/**
* Set the volume name of a mounted NTFS partition.
*
* @param NAME The name of mount (see @ntfsMountAll, @ntfsMountDevice, and @ntfsMount)
@ -139,10 +138,7 @@ extern "C"
* @return True if mount was successful, false if an error occurred (see errno)
* @note The mount must be write-enabled else this will fail
*/
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 );
extern bool ntfsSetVolumeName (const char *name, const char *volumeName);
#ifdef __cplusplus
}

View File

@ -47,24 +47,23 @@
#define STATE(x) ((ntfs_dir_state*)(x)->dirStruct)
void ntfsCloseDir ( ntfs_dir_state *dir )
void ntfsCloseDir (ntfs_dir_state *dir)
{
// Sanity check
if ( !dir || !dir->vd )
if (!dir || !dir->vd)
return;
// Free the directory entries (if any)
while ( dir->first )
{
while (dir->first) {
ntfs_dir_entry *next = dir->first->next;
ntfs_free( dir->first->name );
ntfs_free( dir->first );
ntfs_free(dir->first->name);
ntfs_free(dir->first);
dir->first = next;
}
// Close the directory (if open)
if ( dir->ni )
ntfsCloseEntry( dir->vd, dir->ni );
if (dir->ni)
ntfsCloseEntry(dir->vd, dir->ni);
// Reset the directory state
dir->ni = NULL;
@ -74,280 +73,264 @@ void ntfsCloseDir ( ntfs_dir_state *dir )
return;
}
int ntfs_stat_r ( struct _reent *r, const char *path, struct stat *st )
int ntfs_stat_r (struct _reent *r, const char *path, struct stat *st)
{
// Short circuit cases were we don't actually have to do anything
if ( !st || !path )
if (!st || !path)
return 0;
ntfs_log_trace( "path %s, st %p\n", path, st );
ntfs_log_trace("path %s, st %p\n", path, st);
ntfs_vd *vd = NULL;
ntfs_inode *ni = NULL;
// Get the volume descriptor for this path
vd = ntfsGetVolume( path );
if ( !vd )
{
vd = ntfsGetVolume(path);
if (!vd) {
r->_errno = ENODEV;
return -1;
}
if ( strcmp( path, "." ) == 0 || strcmp( path, ".." ) == 0 )
if(strcmp(path, ".") == 0 || strcmp(path, "..") == 0)
{
memset( st, 0, sizeof( struct stat ) );
memset(st, 0, sizeof(struct stat));
st->st_mode = S_IFDIR;
return 0;
}
// Lock
ntfsLock( vd );
ntfsLock(vd);
// Find the entry
ni = ntfsOpenEntry( vd, path );
if ( !ni )
{
ni = ntfsOpenEntry(vd, path);
if (!ni) {
r->_errno = errno;
ntfsUnlock( vd );
ntfsUnlock(vd);
return -1;
}
// Get the entry stats
int ret = ntfsStat( vd, ni, st );
if ( ret )
int ret = ntfsStat(vd, ni, st);
if (ret)
r->_errno = errno;
// Close the entry
ntfsCloseEntry( vd, ni );
ntfsCloseEntry(vd, ni);
ntfsUnlock( vd );
ntfsUnlock(vd);
return 0;
}
int ntfs_link_r ( struct _reent *r, const char *existing, const char *newLink )
int ntfs_link_r (struct _reent *r, const char *existing, const char *newLink)
{
ntfs_log_trace( "existing %s, newLink %s\n", existing, newLink );
ntfs_log_trace("existing %s, newLink %s\n", existing, newLink);
ntfs_vd *vd = NULL;
ntfs_inode *ni = NULL;
// Get the volume descriptor for this path
vd = ntfsGetVolume( existing );
if ( !vd )
{
vd = ntfsGetVolume(existing);
if (!vd) {
r->_errno = ENODEV;
return -1;
}
// Lock
ntfsLock( vd );
ntfsLock(vd);
// Create a symbolic link between the two paths
ni = ntfsCreate( vd, existing, S_IFLNK, newLink );
if ( !ni )
{
ntfsUnlock( vd );
ni = ntfsCreate(vd, existing, S_IFLNK, newLink);
if (!ni) {
ntfsUnlock(vd);
r->_errno = errno;
return -1;
}
// Close the symbolic link
ntfsCloseEntry( vd, ni );
ntfsCloseEntry(vd, ni);
// Unlock
ntfsUnlock( vd );
ntfsUnlock(vd);
return 0;
}
int ntfs_unlink_r ( struct _reent *r, const char *name )
int ntfs_unlink_r (struct _reent *r, const char *name)
{
ntfs_log_trace( "name %s\n", name );
ntfs_log_trace("name %s\n", name);
// Unlink the entry
int ret = ntfsUnlink( ntfsGetVolume( name ), name );
if ( ret )
int ret = ntfsUnlink(ntfsGetVolume(name), name);
if (ret)
r->_errno = errno;
return ret;
}
int ntfs_chdir_r ( struct _reent *r, const char *name )
int ntfs_chdir_r (struct _reent *r, const char *name)
{
ntfs_log_trace( "name %s\n", name );
ntfs_log_trace("name %s\n", name);
ntfs_vd *vd = NULL;
ntfs_inode *ni = NULL;
// Get the volume descriptor for this path
vd = ntfsGetVolume( name );
if ( !vd )
{
vd = ntfsGetVolume(name);
if (!vd) {
r->_errno = ENODEV;
return -1;
}
// Lock
ntfsLock( vd );
ntfsLock(vd);
// Find the directory
ni = ntfsOpenEntry( vd, name );
if ( !ni )
{
ntfsUnlock( vd );
ni = ntfsOpenEntry(vd, name);
if (!ni) {
ntfsUnlock(vd);
r->_errno = ENOENT;
return -1;
}
// Ensure that this directory is indeed a directory
if ( !( ni->mrec->flags && MFT_RECORD_IS_DIRECTORY ) )
{
ntfsCloseEntry( vd, ni );
ntfsUnlock( vd );
if (!(ni->mrec->flags && MFT_RECORD_IS_DIRECTORY)) {
ntfsCloseEntry(vd, ni);
ntfsUnlock(vd);
r->_errno = ENOTDIR;
return -1;
}
// Close the old current directory (if any)
if ( vd->cwd_ni )
ntfsCloseEntry( vd, vd->cwd_ni );
if (vd->cwd_ni)
ntfsCloseEntry(vd, vd->cwd_ni);
// Set the new current directory
vd->cwd_ni = ni;
// Unlock
ntfsUnlock( vd );
ntfsUnlock(vd);
return 0;
}
int ntfs_rename_r ( struct _reent *r, const char *oldName, const char *newName )
int ntfs_rename_r (struct _reent *r, const char *oldName, const char *newName)
{
ntfs_log_trace( "oldName %s, newName %s\n", oldName, newName );
ntfs_log_trace("oldName %s, newName %s\n", oldName, newName);
ntfs_vd *vd = NULL;
ntfs_inode *ni = NULL;
// Get the volume descriptor for this path
vd = ntfsGetVolume( oldName );
if ( !vd )
{
vd = ntfsGetVolume(oldName);
if (!vd) {
r->_errno = ENODEV;
return -1;
}
// Lock
ntfsLock( vd );
ntfsLock(vd);
// You cannot rename between devices
if ( vd != ntfsGetVolume( newName ) )
{
ntfsUnlock( vd );
if(vd != ntfsGetVolume(newName)) {
ntfsUnlock(vd);
r->_errno = EXDEV;
return -1;
}
// Check that there is no existing entry with the new name
ni = ntfsOpenEntry( vd, newName );
if ( ni )
{
ntfsCloseEntry( vd, ni );
ntfsUnlock( vd );
ni = ntfsOpenEntry(vd, newName);
if (ni) {
ntfsCloseEntry(vd, ni);
ntfsUnlock(vd);
r->_errno = EEXIST;
return -1;
}
// Link the old entry with the new one
if ( ntfsLink( vd, oldName, newName ) )
{
ntfsUnlock( vd );
if (ntfsLink(vd, oldName, newName)) {
ntfsUnlock(vd);
return -1;
}
// Unlink the old entry
if ( ntfsUnlink( vd, oldName ) )
{
if ( ntfsUnlink( vd, newName ) )
{
ntfsUnlock( vd );
if (ntfsUnlink(vd, oldName)) {
if (ntfsUnlink(vd, newName)) {
ntfsUnlock(vd);
return -1;
}
ntfsUnlock( vd );
ntfsUnlock(vd);
return -1;
}
// Unlock
ntfsUnlock( vd );
ntfsUnlock(vd);
return 0;
}
int ntfs_mkdir_r ( struct _reent *r, const char *path, int mode )
int ntfs_mkdir_r (struct _reent *r, const char *path, int mode)
{
ntfs_log_trace( "path %s, mode %i\n", path, mode );
ntfs_log_trace("path %s, mode %i\n", path, mode);
ntfs_vd *vd = NULL;
ntfs_inode *ni = NULL;
// Get the volume descriptor for this path
vd = ntfsGetVolume( path );
if ( !vd )
{
vd = ntfsGetVolume(path);
if (!vd) {
r->_errno = ENODEV;
return -1;
}
// Lock
ntfsLock( vd );
ntfsLock(vd);
// Create the directory
ni = ntfsCreate( vd, path, S_IFDIR, NULL );
if ( !ni )
{
ntfsUnlock( vd );
ni = ntfsCreate(vd, path, S_IFDIR, NULL);
if (!ni) {
ntfsUnlock(vd);
r->_errno = errno;
return -1;
}
// Close the directory
ntfsCloseEntry( vd, ni );
ntfsCloseEntry(vd, ni);
// Unlock
ntfsUnlock( vd );
ntfsUnlock(vd);
return 0;
}
int ntfs_statvfs_r ( struct _reent *r, const char *path, struct statvfs *buf )
int ntfs_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf)
{
ntfs_log_trace( "path %s, buf %p\n", path, buf );
ntfs_log_trace("path %s, buf %p\n", path, buf);
ntfs_vd *vd = NULL;
s64 size;
int delta_bits;
// Get the volume descriptor for this path
vd = ntfsGetVolume( path );
if ( !vd )
{
vd = ntfsGetVolume(path);
if (!vd) {
r->_errno = ENODEV;
return -1;
}
// Short circuit cases were we don't actually have to do anything
if ( !buf )
if (!buf)
return 0;
// Lock
ntfsLock( vd );
ntfsLock(vd);
// Zero out the stat buffer
memset( buf, 0, sizeof( struct statvfs ) );
memset(buf, 0, sizeof(struct statvfs));
if ( ntfs_volume_get_free_space( vd->vol ) < 0 )
if(ntfs_volume_get_free_space(vd->vol) < 0)
{
ntfsUnlock( vd );
ntfsUnlock(vd);
return -1;
}
@ -361,34 +344,34 @@ int ntfs_statvfs_r ( struct _reent *r, const char *path, struct statvfs *buf )
buf->f_blocks = vd->vol->nr_clusters;
// Free blocks available for all and for non-privileged processes
size = MAX( vd->vol->free_clusters, 0 );
size = MAX(vd->vol->free_clusters, 0);
buf->f_bfree = buf->f_bavail = size;
// Free inodes on the free space
delta_bits = vd->vol->cluster_size_bits - vd->vol->mft_record_size_bits;
if ( delta_bits >= 0 )
if (delta_bits >= 0)
size <<= delta_bits;
else
size >>= -delta_bits;
// Number of inodes at this point in time
buf->f_files = ( vd->vol->mftbmp_na->allocated_size << 3 ) + size;
buf->f_files = (vd->vol->mftbmp_na->allocated_size << 3) + size;
// Free inodes available for all and for non-privileged processes
size += vd->vol->free_mft_records;
buf->f_ffree = buf->f_favail = MAX( size, 0 );
buf->f_ffree = buf->f_favail = MAX(size, 0);
// File system id
buf->f_fsid = vd->id;
// Bit mask of f_flag values.
buf->f_flag = ( NVolReadOnly( vd->vol ) ? ST_RDONLY : 0 );
buf->f_flag = (NVolReadOnly(vd->vol) ? ST_RDONLY : 0);
// Maximum length of filenames
buf->f_namemax = NTFS_MAX_NAME_LEN;
// Unlock
ntfsUnlock( vd );
ntfsUnlock(vd);
return 0;
}
@ -396,83 +379,74 @@ int ntfs_statvfs_r ( struct _reent *r, const char *path, struct statvfs *buf )
/**
* PRIVATE: Callback for directory walking
*/
int ntfs_readdir_filler ( DIR_ITER *dirState, const ntfschar *name, const int name_len, const int name_type,
const s64 pos, const MFT_REF mref, const unsigned dt_type )
int ntfs_readdir_filler (DIR_ITER *dirState, const ntfschar *name, const int name_len, const int name_type,
const s64 pos, const MFT_REF mref, const unsigned dt_type)
{
ntfs_dir_state *dir = STATE( dirState );
ntfs_dir_state *dir = STATE(dirState);
ntfs_dir_entry *entry = NULL;
char *entry_name = NULL;
// Sanity check
if ( !dir || !dir->vd )
{
if (!dir || !dir->vd) {
errno = EINVAL;
return -1;
}
// Ignore DOS file names
if ( name_type == FILE_NAME_DOS )
{
if (name_type == FILE_NAME_DOS) {
return 0;
}
// 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
if ( ntfsUnicodeToLocal( name, name_len, &entry_name, 0 ) < 0 )
{
if (ntfsUnicodeToLocal(name, name_len, &entry_name, 0) < 0) {
return -1;
}
if ( dir->first && dir->first->mref == FILE_root &&
MREF( mref ) == FILE_root && strcmp( entry_name, ".." ) == 0 )
if(dir->first && dir->first->mref == FILE_root &&
MREF(mref) == FILE_root && strcmp(entry_name, "..") == 0)
{
return 0;
}
// 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
ntfs_inode *ni = ntfs_pathname_to_inode( dir->vd->vol, dir->ni, entry_name );
if ( !ni )
ntfs_inode *ni = ntfs_pathname_to_inode(dir->vd->vol, dir->ni, entry_name);
if (!ni)
return -1;
// Double check that this entry can be emuerated (as described by the volume descriptor)
if ( ( ( ni->flags & FILE_ATTR_HIDDEN ) && !dir->vd->showHiddenFiles ) ||
( ( ni->flags & FILE_ATTR_SYSTEM ) && !dir->vd->showSystemFiles ) )
{
ntfs_inode_close( ni );
if (((ni->flags & FILE_ATTR_HIDDEN) && !dir->vd->showHiddenFiles) ||
((ni->flags & FILE_ATTR_SYSTEM) && !dir->vd->showSystemFiles)) {
ntfs_inode_close(ni);
return 0;
}
// Close the entry
ntfs_inode_close( ni );
ntfs_inode_close(ni);
}
// Allocate a new directory entry
entry = ( ntfs_dir_entry * ) ntfs_alloc( sizeof( ntfs_dir_entry ) );
if ( !entry )
entry = (ntfs_dir_entry *) ntfs_alloc(sizeof(ntfs_dir_entry));
if (!entry)
return -1;
// Setup the entry
entry->name = entry_name;
entry->next = NULL;
entry->mref = MREF( mref );
entry->mref = MREF(mref);
// Link the entry to the directory
if ( !dir->first )
{
if (!dir->first) {
dir->first = entry;
}
else
{
} else {
ntfs_dir_entry *last = dir->first;
while ( last->next ) last = last->next;
while (last->next) last = last->next;
last->next = entry;
}
@ -481,48 +455,44 @@ int ntfs_readdir_filler ( DIR_ITER *dirState, const ntfschar *name, const int na
return 0;
}
DIR_ITER *ntfs_diropen_r ( struct _reent *r, DIR_ITER *dirState, const char *path )
DIR_ITER *ntfs_diropen_r (struct _reent *r, DIR_ITER *dirState, const char *path)
{
ntfs_log_trace( "dirState %p, path %s\n", dirState, path );
ntfs_log_trace("dirState %p, path %s\n", dirState, path);
ntfs_dir_state* dir = STATE( dirState );
ntfs_dir_state* dir = STATE(dirState);
s64 position = 0;
// Get the volume descriptor for this path
dir->vd = ntfsGetVolume( path );
if ( !dir->vd )
{
dir->vd = ntfsGetVolume(path);
if (!dir->vd) {
r->_errno = ENODEV;
return NULL;
}
// Lock
ntfsLock( dir->vd );
ntfsLock(dir->vd);
// Find the directory
dir->ni = ntfsOpenEntry( dir->vd, path );
if ( !dir->ni )
{
ntfsUnlock( dir->vd );
dir->ni = ntfsOpenEntry(dir->vd, path);
if (!dir->ni) {
ntfsUnlock(dir->vd);
r->_errno = ENOENT;
return NULL;
}
// Ensure that this directory is indeed a directory
if ( !( dir->ni->mrec->flags && MFT_RECORD_IS_DIRECTORY ) )
{
ntfsCloseEntry( dir->vd, dir->ni );
ntfsUnlock( dir->vd );
if (!(dir->ni->mrec->flags && MFT_RECORD_IS_DIRECTORY)) {
ntfsCloseEntry(dir->vd, dir->ni);
ntfsUnlock(dir->vd);
r->_errno = ENOTDIR;
return NULL;
}
// Read the directory
dir->first = dir->current = NULL;
if ( ntfs_readdir( dir->ni, &position, dirState, ( ntfs_filldir_t )ntfs_readdir_filler ) )
{
ntfsCloseDir( dir );
ntfsUnlock( dir->vd );
if (ntfs_readdir(dir->ni, &position, dirState, (ntfs_filldir_t)ntfs_readdir_filler)) {
ntfsCloseDir(dir);
ntfsUnlock(dir->vd);
r->_errno = errno;
return NULL;
}
@ -531,16 +501,13 @@ DIR_ITER *ntfs_diropen_r ( struct _reent *r, DIR_ITER *dirState, const char *pat
dir->current = dir->first;
// Update directory times
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
if ( dir->vd->firstOpenDir )
{
if (dir->vd->firstOpenDir) {
dir->nextOpenDir = dir->vd->firstOpenDir;
dir->vd->firstOpenDir->prevOpenDir = dir;
}
else
{
} else {
dir->nextOpenDir = NULL;
}
dir->prevOpenDir = NULL;
@ -549,80 +516,76 @@ DIR_ITER *ntfs_diropen_r ( struct _reent *r, DIR_ITER *dirState, const char *pat
dir->vd->openDirCount++;
// Unlock
ntfsUnlock( dir->vd );
ntfsUnlock(dir->vd);
return dirState;
}
int ntfs_dirreset_r ( struct _reent *r, DIR_ITER *dirState )
int ntfs_dirreset_r (struct _reent *r, DIR_ITER *dirState)
{
ntfs_log_trace( "dirState %p\n", dirState );
ntfs_log_trace("dirState %p\n", dirState);
ntfs_dir_state* dir = STATE( dirState );
ntfs_dir_state* dir = STATE(dirState);
// Sanity check
if ( !dir || !dir->vd || !dir->ni )
{
if (!dir || !dir->vd || !dir->ni) {
r->_errno = EBADF;
return -1;
}
// Lock
ntfsLock( dir->vd );
ntfsLock(dir->vd);
// Move to the first entry in the directory
dir->current = dir->first;
// Update directory times
ntfsUpdateTimes( dir->vd, dir->ni, NTFS_UPDATE_ATIME );
ntfsUpdateTimes(dir->vd, dir->ni, NTFS_UPDATE_ATIME);
// Unlock
ntfsUnlock( dir->vd );
ntfsUnlock(dir->vd);
return 0;
}
int ntfs_dirnext_r ( struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat )
int ntfs_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat)
{
ntfs_log_trace( "dirState %p, filename %p, filestat %p\n", dirState, filename, filestat );
ntfs_log_trace("dirState %p, filename %p, filestat %p\n", dirState, filename, filestat);
ntfs_dir_state* dir = STATE( dirState );
ntfs_dir_state* dir = STATE(dirState);
ntfs_inode *ni = NULL;
// Sanity check
if ( !dir || !dir->vd || !dir->ni )
{
if (!dir || !dir->vd || !dir->ni) {
r->_errno = EBADF;
return -1;
}
// Lock
ntfsLock( dir->vd );
ntfsLock(dir->vd);
// Check that there is a entry waiting to be fetched
if ( !dir->current )
{
ntfsUnlock( dir->vd );
if (!dir->current) {
ntfsUnlock(dir->vd);
r->_errno = ENOENT;
return -1;
}
// Fetch the current entry
strcpy( filename, dir->current->name );
if ( filestat != NULL )
strcpy(filename, dir->current->name);
if(filestat != NULL)
{
if ( strcmp( dir->current->name, "." ) == 0 || strcmp( dir->current->name, ".." ) == 0 )
if(strcmp(dir->current->name, ".") == 0 || strcmp(dir->current->name, "..") == 0)
{
memset( filestat, 0, sizeof( struct stat ) );
memset(filestat, 0, sizeof(struct stat));
filestat->st_mode = S_IFDIR;
}
else
{
ni = ntfsOpenEntry( dir->vd, dir->current->name );
if ( ni )
{
ntfsStat( dir->vd, ni, filestat );
ntfsCloseEntry( dir->vd, ni );
ni = ntfsOpenEntry(dir->vd, dir->current->name);
if (ni) {
ntfsStat(dir->vd, ni, filestat);
ntfsCloseEntry(dir->vd, ni);
}
}
}
@ -631,44 +594,43 @@ int ntfs_dirnext_r ( struct _reent *r, DIR_ITER *dirState, char *filename, struc
dir->current = dir->current->next;
// Update directory times
ntfsUpdateTimes( dir->vd, dir->ni, NTFS_UPDATE_ATIME );
ntfsUpdateTimes(dir->vd, dir->ni, NTFS_UPDATE_ATIME);
// Unlock
ntfsUnlock( dir->vd );
ntfsUnlock(dir->vd);
return 0;
}
int ntfs_dirclose_r ( struct _reent *r, DIR_ITER *dirState )
int ntfs_dirclose_r (struct _reent *r, DIR_ITER *dirState)
{
ntfs_log_trace( "dirState %p\n", dirState );
ntfs_log_trace("dirState %p\n", dirState);
ntfs_dir_state* dir = STATE( dirState );
ntfs_dir_state* dir = STATE(dirState);
// Sanity check
if ( !dir || !dir->vd )
{
if (!dir || !dir->vd) {
r->_errno = EBADF;
return -1;
}
// Lock
ntfsLock( dir->vd );
ntfsLock(dir->vd);
// Close the directory
ntfsCloseDir( dir );
ntfsCloseDir(dir);
// Remove the directory from the double-linked FILO list of open directories
dir->vd->openDirCount--;
if ( dir->nextOpenDir )
if (dir->nextOpenDir)
dir->nextOpenDir->prevOpenDir = dir->prevOpenDir;
if ( dir->prevOpenDir )
if (dir->prevOpenDir)
dir->prevOpenDir->nextOpenDir = dir->nextOpenDir;
else
dir->vd->firstOpenDir = dir->nextOpenDir;
// Unlock
ntfsUnlock( dir->vd );
ntfsUnlock(dir->vd);
return 0;
}

View File

@ -28,8 +28,7 @@
/**
* ntfs_dir_entry - Directory entry
*/
typedef struct _ntfs_dir_entry
{
typedef struct _ntfs_dir_entry {
char *name;
u64 mref;
struct _ntfs_dir_entry *next;
@ -38,8 +37,7 @@ typedef struct _ntfs_dir_entry
/**
* ntfs_dir_state - Directory state
*/
typedef struct _ntfs_dir_state
{
typedef struct _ntfs_dir_state {
ntfs_vd *vd; /* Volume this directory belongs to */
ntfs_inode *ni; /* Directory descriptor */
ntfs_dir_entry *first; /* The first entry in the directory */
@ -49,22 +47,22 @@ typedef struct _ntfs_dir_state
} ntfs_dir_state;
/* Directory state routines */
void ntfsCloseDir ( ntfs_dir_state *file );
void ntfsCloseDir (ntfs_dir_state *file);
/* Gekko devoptab directory routines for NTFS-based devices */
extern int ntfs_stat_r ( struct _reent *r, const char *path, struct stat *st );
extern int ntfs_link_r ( struct _reent *r, const char *existing, const char *newLink );
extern int ntfs_unlink_r ( struct _reent *r, const char *name );
extern int ntfs_chdir_r ( struct _reent *r, const char *name );
extern int ntfs_rename_r ( struct _reent *r, const char *oldName, const char *newName );
extern int ntfs_mkdir_r ( struct _reent *r, const char *path, int mode );
extern int ntfs_statvfs_r ( struct _reent *r, const char *path, struct statvfs *buf );
extern int ntfs_stat_r (struct _reent *r, const char *path, struct stat *st);
extern int ntfs_link_r (struct _reent *r, const char *existing, const char *newLink);
extern int ntfs_unlink_r (struct _reent *r, const char *name);
extern int ntfs_chdir_r (struct _reent *r, const char *name);
extern int ntfs_rename_r (struct _reent *r, const char *oldName, const char *newName);
extern int ntfs_mkdir_r (struct _reent *r, const char *path, int mode);
extern int ntfs_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf);
/* Gekko devoptab directory walking routines for NTFS-based devices */
extern DIR_ITER *ntfs_diropen_r ( struct _reent *r, DIR_ITER *dirState, const char *path );
extern int ntfs_dirreset_r ( struct _reent *r, DIR_ITER *dirState );
extern int ntfs_dirnext_r ( struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat );
extern int ntfs_dirclose_r ( struct _reent *r, DIR_ITER *dirState );
extern DIR_ITER *ntfs_diropen_r (struct _reent *r, DIR_ITER *dirState, const char *path);
extern int ntfs_dirreset_r (struct _reent *r, DIR_ITER *dirState);
extern int ntfs_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat);
extern int ntfs_dirclose_r (struct _reent *r, DIR_ITER *dirState);
#endif /* _NTFSDIR_H */

View File

@ -45,36 +45,36 @@
#define STATE(x) ((ntfs_file_state*)x)
void ntfsCloseFile ( ntfs_file_state *file )
void ntfsCloseFile (ntfs_file_state *file)
{
// Sanity check
if ( !file || !file->vd )
if (!file || !file->vd)
return;
// Special case fix ups for compressed and/or encrypted files
if ( file->compressed )
ntfs_attr_pclose( file->data_na );
if (file->compressed)
ntfs_attr_pclose(file->data_na);
#ifdef HAVE_SETXATTR
if ( file->encrypted )
ntfs_efs_fixup_attribute( NULL, file->data_na );
if (file->encrypted)
ntfs_efs_fixup_attribute(NULL, file->data_na);
#endif
// Close the file data attribute (if open)
if ( file->data_na )
ntfs_attr_close( file->data_na );
if (file->data_na)
ntfs_attr_close(file->data_na);
// Sync the file (and its attributes) to disc
if ( file->write )
if(file->write)
{
ntfsUpdateTimes( file->vd, file->ni, NTFS_UPDATE_ATIME | NTFS_UPDATE_CTIME );
ntfsSync( file->vd, file->ni );
ntfsUpdateTimes(file->vd, file->ni, NTFS_UPDATE_ATIME | NTFS_UPDATE_CTIME);
ntfsSync(file->vd, file->ni);
}
if ( file->read )
ntfsUpdateTimes( file->vd, file->ni, NTFS_UPDATE_ATIME );
if (file->read)
ntfsUpdateTimes(file->vd, file->ni, NTFS_UPDATE_ATIME);
// Close the file (if open)
if ( file->ni )
ntfsCloseEntry( file->vd, file->ni );
if (file->ni)
ntfsCloseEntry(file->vd, file->ni);
// Reset the file state
file->ni = NULL;
@ -89,132 +89,106 @@ void ntfsCloseFile ( ntfs_file_state *file )
return;
}
int ntfs_open_r ( struct _reent *r, void *fileStruct, const char *path, int flags, int mode )
int ntfs_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode)
{
ntfs_log_trace( "fileStruct %p, path %s, flags %i, mode %i\n", fileStruct, path, flags, mode );
ntfs_log_trace("fileStruct %p, path %s, flags %i, mode %i\n", fileStruct, path, flags, mode);
ntfs_file_state* file = STATE( fileStruct );
ntfs_file_state* file = STATE(fileStruct);
// Get the volume descriptor for this path
file->vd = ntfsGetVolume( path );
if ( !file->vd )
{
file->vd = ntfsGetVolume(path);
if (!file->vd) {
r->_errno = ENODEV;
return -1;
}
// Lock
ntfsLock( file->vd );
ntfsLock(file->vd);
// Determine which mode the file is opened for
file->flags = flags;
if ( ( flags & 0x03 ) == O_RDONLY )
{
if ((flags & 0x03) == O_RDONLY) {
file->read = true;
file->write = false;
file->append = false;
}
else if ( ( flags & 0x03 ) == O_WRONLY )
{
} else if ((flags & 0x03) == O_WRONLY) {
file->read = false;
file->write = true;
file->append = ( flags & O_APPEND );
}
else if ( ( flags & 0x03 ) == O_RDWR )
{
file->append = (flags & O_APPEND);
} else if ((flags & 0x03) == O_RDWR) {
file->read = true;
file->write = true;
file->append = ( flags & O_APPEND );
}
else
{
file->append = (flags & O_APPEND);
} else {
r->_errno = EACCES;
ntfsUnlock( file->vd );
ntfsUnlock(file->vd);
return -1;
}
// Try and find the file and (if found) ensure that it is not a directory
file->ni = ntfsOpenEntry( file->vd, path );
if ( file->ni && ( file->ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ) )
{
ntfsCloseEntry( file->vd, file->ni );
ntfsUnlock( file->vd );
file->ni = ntfsOpenEntry(file->vd, path);
if (file->ni && (file->ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
ntfsCloseEntry(file->vd, file->ni);
ntfsUnlock(file->vd);
r->_errno = EISDIR;
return -1;
}
// Are we creating this file?
if ( flags & O_CREAT )
{
// The file SHOULD NOT already exist
if ( file->ni )
{
ntfsCloseEntry( file->vd, file->ni );
ntfsUnlock( file->vd );
r->_errno = EEXIST;
return -1;
}
if ((flags & O_CREAT) && !file->ni) {
// Create the file
file->ni = ntfsCreate( file->vd, path, S_IFREG, NULL );
if ( !file->ni )
{
ntfsUnlock( file->vd );
file->ni = ntfsCreate(file->vd, path, S_IFREG, NULL);
if (!file->ni) {
ntfsUnlock(file->vd);
return -1;
}
}
// Sanity check, the file should be open by now
if ( !file->ni )
{
ntfsUnlock( file->vd );
if (!file->ni) {
ntfsUnlock(file->vd);
r->_errno = ENOENT;
return -1;
}
// Open the files data attribute
file->data_na = ntfs_attr_open( file->ni, AT_DATA, AT_UNNAMED, 0 );
if ( !file->data_na )
{
ntfsCloseEntry( file->vd, file->ni );
ntfsUnlock( file->vd );
file->data_na = ntfs_attr_open(file->ni, AT_DATA, AT_UNNAMED, 0);
if(!file->data_na) {
ntfsCloseEntry(file->vd, file->ni);
ntfsUnlock(file->vd);
return -1;
}
// Determine if this files data is compressed and/or encrypted
file->compressed = NAttrCompressed( file->data_na ) || ( file->ni->flags & FILE_ATTR_COMPRESSED );
file->encrypted = NAttrEncrypted( file->data_na ) || ( file->ni->flags & FILE_ATTR_ENCRYPTED );
file->compressed = NAttrCompressed(file->data_na) || (file->ni->flags & FILE_ATTR_COMPRESSED);
file->encrypted = NAttrEncrypted(file->data_na) || (file->ni->flags & FILE_ATTR_ENCRYPTED);
// We cannot read/write encrypted files
if ( file->encrypted )
{
ntfs_attr_close( file->data_na );
ntfsCloseEntry( file->vd, file->ni );
ntfsUnlock( file->vd );
if (file->encrypted) {
ntfs_attr_close(file->data_na);
ntfsCloseEntry(file->vd, file->ni);
ntfsUnlock(file->vd);
r->_errno = EACCES;
return -1;
}
// Make sure we aren't trying to write to a read-only file
if ( ( file->ni->flags & FILE_ATTR_READONLY ) && file->write )
{
ntfs_attr_close( file->data_na );
ntfsCloseEntry( file->vd, file->ni );
ntfsUnlock( file->vd );
if ((file->ni->flags & FILE_ATTR_READONLY) && file->write) {
ntfs_attr_close(file->data_na);
ntfsCloseEntry(file->vd, file->ni);
ntfsUnlock(file->vd);
r->_errno = EROFS;
return -1;
}
// Truncate the file if requested
if ( ( flags & O_TRUNC ) && file->write )
{
if ( ntfs_attr_truncate( file->data_na, 0 ) )
{
ntfs_attr_close( file->data_na );
ntfsCloseEntry( file->vd, file->ni );
ntfsUnlock( file->vd );
if ((flags & O_TRUNC) && file->write) {
if (ntfs_attr_truncate(file->data_na, 0)) {
ntfs_attr_close(file->data_na);
ntfsCloseEntry(file->vd, file->ni);
ntfsUnlock(file->vd);
r->_errno = errno;
return -1;
}
@ -224,19 +198,16 @@ int ntfs_open_r ( struct _reent *r, void *fileStruct, const char *path, int flag
file->pos = 0;
file->len = file->data_na->data_size;
ntfs_log_trace( "file->len %d\n", file->len );
ntfs_log_trace("file->len %d\n", file->len);
// Update file times
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
if ( file->vd->firstOpenFile )
{
if (file->vd->firstOpenFile) {
file->nextOpenFile = file->vd->firstOpenFile;
file->vd->firstOpenFile->prevOpenFile = file;
}
else
{
} else {
file->nextOpenFile = NULL;
}
file->prevOpenFile = NULL;
@ -244,91 +215,84 @@ int ntfs_open_r ( struct _reent *r, void *fileStruct, const char *path, int flag
file->vd->openFileCount++;
// Unlock
ntfsUnlock( file->vd );
ntfsUnlock(file->vd);
return ( int )fileStruct;
return (int)fileStruct;
}
int ntfs_close_r ( struct _reent *r, int fd )
int ntfs_close_r (struct _reent *r, int fd)
{
ntfs_log_trace( "fd %p\n", fd );
ntfs_log_trace("fd %p\n", fd);
ntfs_file_state* file = STATE( fd );
ntfs_file_state* file = STATE(fd);
// Sanity check
if ( !file || !file->vd )
{
if (!file || !file->vd) {
r->_errno = EBADF;
return -1;
}
// Lock
ntfsLock( file->vd );
ntfsLock(file->vd);
// Close the file
ntfsCloseFile( file );
ntfsCloseFile(file);
// Remove the file from the double-linked FILO list of open files
file->vd->openFileCount--;
if ( file->nextOpenFile )
if (file->nextOpenFile)
file->nextOpenFile->prevOpenFile = file->prevOpenFile;
if ( file->prevOpenFile )
if (file->prevOpenFile)
file->prevOpenFile->nextOpenFile = file->nextOpenFile;
else
file->vd->firstOpenFile = file->nextOpenFile;
// Unlock
ntfsUnlock( file->vd );
ntfsUnlock(file->vd);
return 0;
}
ssize_t ntfs_write_r ( struct _reent *r, int fd, const char *ptr, size_t len )
ssize_t ntfs_write_r (struct _reent *r, int fd, const char *ptr, size_t len)
{
ntfs_log_trace( "fd %p, ptr %p, len %Li\n", fd, ptr, len );
ntfs_log_trace("fd %p, ptr %p, len %Li\n", fd, ptr, len);
ntfs_file_state* file = STATE( fd );
ntfs_file_state* file = STATE(fd);
ssize_t written = 0;
off_t old_pos = 0;
// Sanity check
if ( !file || !file->vd || !file->ni || !file->data_na )
{
if (!file || !file->vd || !file->ni || !file->data_na) {
r->_errno = EINVAL;
return -1;
}
// Short circuit cases where we don't actually have to do anything
if ( !ptr || len <= 0 )
{
if (!ptr || len <= 0) {
return 0;
}
// Lock
ntfsLock( file->vd );
ntfsLock(file->vd);
// Check that we are allowed to write to this file
if ( !file->write )
{
ntfsUnlock( file->vd );
if (!file->write) {
ntfsUnlock(file->vd);
r->_errno = EACCES;
return -1;
}
// 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;
file->pos = file->len;
}
// Write to the files data atrribute
while ( len )
{
ssize_t ret = ntfs_attr_pwrite( file->data_na, file->pos, len, ptr );
if ( ret <= 0 )
{
ntfsUnlock( file->vd );
while (len) {
ssize_t ret = ntfs_attr_pwrite(file->data_na, file->pos, len, ptr);
if (ret <= 0) {
ntfsUnlock(file->vd);
r->_errno = errno;
return -1;
}
@ -338,72 +302,65 @@ 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 ( file->append )
{
if (file->append) {
file->pos = old_pos;
}
// Mark the file for archiving (if we actually wrote something)
if ( written )
if (written)
file->ni->flags |= FILE_ATTR_ARCHIVE;
// Update the files data length
file->len = file->data_na->data_size;
// Unlock
ntfsUnlock( file->vd );
ntfsUnlock(file->vd);
return written;
}
ssize_t ntfs_read_r ( struct _reent *r, int fd, char *ptr, size_t len )
ssize_t ntfs_read_r (struct _reent *r, int fd, char *ptr, size_t len)
{
ntfs_log_trace( "fd %p, ptr %p, len %Li\n", fd, ptr, len );
ntfs_log_trace("fd %p, ptr %p, len %Li\n", fd, ptr, len);
ntfs_file_state* file = STATE( fd );
ntfs_file_state* file = STATE(fd);
ssize_t read = 0;
// Sanity check
if ( !file || !file->vd || !file->ni || !file->data_na )
{
if (!file || !file->vd || !file->ni || !file->data_na) {
r->_errno = EINVAL;
return -1;
}
// Short circuit cases where we don't actually have to do anything
if ( !ptr || len <= 0 )
{
if (!ptr || len <= 0) {
return 0;
}
// Lock
ntfsLock( file->vd );
ntfsLock(file->vd);
// Check that we are allowed to read from this file
if ( !file->read )
{
ntfsUnlock( file->vd );
if (!file->read) {
ntfsUnlock(file->vd);
r->_errno = EACCES;
return -1;
}
// Don't read past the end of file
if ( file->pos + len > file->len )
{
if (file->pos + len > file->len) {
r->_errno = EOVERFLOW;
len = file->len - file->pos;
ntfs_log_trace( "EOVERFLOW" );
ntfs_log_trace("EOVERFLOW");
}
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
while ( len )
{
ssize_t ret = ntfs_attr_pread( file->data_na, file->pos, len, ptr );
if ( ret <= 0 || ret > len )
{
ntfsUnlock( file->vd );
while (len) {
ssize_t ret = ntfs_attr_pread(file->data_na, file->pos, len, ptr);
if (ret <= 0 || ret > len) {
ntfsUnlock(file->vd);
r->_errno = errno;
return -1;
}
@ -416,166 +373,154 @@ ssize_t ntfs_read_r ( struct _reent *r, int fd, char *ptr, size_t len )
// Update file times (if we actually read something)
// Unlock
ntfsUnlock( file->vd );
ntfsUnlock(file->vd);
return read;
}
off_t ntfs_seek_r ( struct _reent *r, int fd, off_t pos, int dir )
off_t ntfs_seek_r (struct _reent *r, int fd, off_t pos, int dir)
{
ntfs_log_trace( "fd %p, pos %Li, dir %i\n", fd, pos, dir );
ntfs_log_trace("fd %p, pos %Li, dir %i\n", fd, pos, dir);
ntfs_file_state* file = STATE( fd );
ntfs_file_state* file = STATE(fd);
off_t position = 0;
// Sanity check
if ( !file || !file->vd || !file->ni || !file->data_na )
{
if (!file || !file->vd || !file->ni || !file->data_na) {
r->_errno = EINVAL;
return -1;
}
// Lock
ntfsLock( file->vd );
ntfsLock(file->vd);
// Set the files current position
switch ( dir )
{
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_END: position = file->pos = MIN( MAX( file->len + pos, 0 ), file->len ); break;
switch(dir) {
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_END: position = file->pos = MIN(MAX(file->len + pos, 0), file->len); break;
}
// Unlock
ntfsUnlock( file->vd );
ntfsUnlock(file->vd);
return position;
}
int ntfs_fstat_r ( struct _reent *r, int fd, struct stat *st )
int ntfs_fstat_r (struct _reent *r, int fd, struct stat *st)
{
ntfs_log_trace( "fd %p\n", fd );
ntfs_log_trace("fd %p\n", fd);
ntfs_file_state* file = STATE( fd );
ntfs_file_state* file = STATE(fd);
int ret = 0;
// Sanity check
if ( !file || !file->vd || !file->ni || !file->data_na )
{
if (!file || !file->vd || !file->ni || !file->data_na) {
r->_errno = EINVAL;
return -1;
}
// Short circuit cases were we don't actually have to do anything
if ( !st )
if (!st)
return 0;
// Get the file stats
ret = ntfsStat( file->vd, file->ni, st );
if ( ret )
ret = ntfsStat(file->vd, file->ni, st);
if (ret)
r->_errno = errno;
return ret;
}
int ntfs_ftruncate_r ( struct _reent *r, int fd, off_t len )
int ntfs_ftruncate_r (struct _reent *r, int fd, off_t len)
{
ntfs_log_trace( "fd %p, len %Li\n", fd, len );
ntfs_log_trace("fd %p, len %Li\n", fd, len);
ntfs_file_state* file = STATE( fd );
ntfs_file_state* file = STATE(fd);
// Sanity check
if ( !file || !file->vd || !file->ni || !file->data_na )
{
if (!file || !file->vd || !file->ni || !file->data_na) {
r->_errno = EINVAL;
return -1;
}
// Lock
ntfsLock( file->vd );
ntfsLock(file->vd);
// Check that we are allowed to write to this file
if ( !file->write )
{
ntfsUnlock( file->vd );
if (!file->write) {
ntfsUnlock(file->vd);
r->_errno = EACCES;
return -1;
}
// For compressed files, only deleting and expanding contents are implemented
if ( file->compressed &&
if (file->compressed &&
len > 0 &&
len < file->data_na->initialized_size )
{
ntfsUnlock( file->vd );
len < file->data_na->initialized_size) {
ntfsUnlock(file->vd);
r->_errno = EOPNOTSUPP;
return -1;
}
// 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;
if ( ntfs_attr_pwrite( file->data_na, len - 1, 1, &zero ) <= 0 )
{
ntfsUnlock( file->vd );
if (ntfs_attr_pwrite(file->data_na, len - 1, 1, &zero) <= 0) {
ntfsUnlock(file->vd);
r->_errno = errno;
return -1;
}
}
else
{
if ( ntfs_attr_truncate( file->data_na, len ) )
{
ntfsUnlock( file->vd );
} else {
if (ntfs_attr_truncate(file->data_na, len)) {
ntfsUnlock(file->vd);
r->_errno = errno;
return -1;
}
}
// Mark the file for archiving (if we actually changed something)
if ( file->len != file->data_na->data_size )
if (file->len != file->data_na->data_size)
file->ni->flags |= FILE_ATTR_ARCHIVE;
// Update file times (if we actually changed something)
if ( file->len != file->data_na->data_size )
ntfsUpdateTimes( file->vd, file->ni, NTFS_UPDATE_AMCTIME );
if (file->len != file->data_na->data_size)
ntfsUpdateTimes(file->vd, file->ni, NTFS_UPDATE_AMCTIME);
// Update the files data length
file->len = file->data_na->data_size;
// Sync the file (and its attributes) to disc
ntfsSync( file->vd, file->ni );
ntfsSync(file->vd, file->ni);
// Unlock
ntfsUnlock( file->vd );
ntfsUnlock(file->vd);
return 0;
}
int ntfs_fsync_r ( struct _reent *r, int fd )
int ntfs_fsync_r (struct _reent *r, int fd)
{
ntfs_log_trace( "fd %p\n", fd );
ntfs_log_trace("fd %p\n", fd);
ntfs_file_state* file = STATE( fd );
ntfs_file_state* file = STATE(fd);
int ret = 0;
// Sanity check
if ( !file || !file->vd || !file->ni || !file->data_na )
{
if (!file || !file->vd || !file->ni || !file->data_na) {
r->_errno = EINVAL;
return -1;
}
// Lock
ntfsLock( file->vd );
ntfsLock(file->vd);
// Sync the file (and its attributes) to disc
ret = ntfsSync( file->vd, file->ni );
if ( ret )
ret = ntfsSync(file->vd, file->ni);
if (ret)
r->_errno = errno;
// Unlock
ntfsUnlock( file->vd );
ntfsUnlock(file->vd);
return ret;
}

View File

@ -32,8 +32,7 @@
/**
* ntfs_file_state - File state
*/
typedef struct _ntfs_file_state
{
typedef struct _ntfs_file_state {
ntfs_vd *vd; /* Volume this file belongs to */
ntfs_inode *ni; /* File descriptor */
ntfs_attr *data_na; /* File data descriptor */
@ -50,17 +49,17 @@ typedef struct _ntfs_file_state
} ntfs_file_state;
/* File state routines */
void ntfsCloseFile ( ntfs_file_state *file );
void ntfsCloseFile (ntfs_file_state *file);
/* Gekko devoptab file routines for NTFS-based devices */
extern int ntfs_open_r ( struct _reent *r, void *fileStruct, const char *path, int flags, int mode );
extern int ntfs_close_r ( struct _reent *r, int fd );
extern ssize_t ntfs_write_r ( struct _reent *r, int fd, const char *ptr, size_t len );
extern ssize_t ntfs_read_r ( struct _reent *r, int fd, char *ptr, size_t len );
extern off_t ntfs_seek_r ( struct _reent *r, int fd, off_t pos, int dir );
extern int ntfs_fstat_r ( struct _reent *r, int fd, struct stat *st );
extern int ntfs_ftruncate_r ( struct _reent *r, int fd, off_t len );
extern int ntfs_fsync_r ( struct _reent *r, int fd );
extern int ntfs_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode);
extern int ntfs_close_r (struct _reent *r, int fd);
extern ssize_t ntfs_write_r (struct _reent *r, int fd, const char *ptr, size_t len);
extern ssize_t ntfs_read_r (struct _reent *r, int fd, char *ptr, size_t len);
extern off_t ntfs_seek_r (struct _reent *r, int fd, off_t pos, int dir);
extern int ntfs_fstat_r (struct _reent *r, int fd, struct stat *st);
extern int ntfs_ftruncate_r (struct _reent *r, int fd, off_t len);
extern int ntfs_fsync_r (struct _reent *r, int fd);
#endif /* _NTFSFILE_H */

File diff suppressed because it is too large Load Diff

View File

@ -69,43 +69,39 @@ struct _ntfs_dir_state;
/**
* PRIMARY_PARTITION - Block device partition record
*/
typedef struct _PARTITION_RECORD
{
typedef struct _PARTITION_RECORD {
u8 status; /* Partition status; see above */
u8 chs_start[3]; /* Cylinder-head-sector address to first block of partition */
u8 type; /* Partition type; see above */
u8 chs_end[3]; /* Cylinder-head-sector address to last block of partition */
u32 lba_start; /* Local block address to first sector of partition */
u32 block_count; /* Number of blocks in partition */
} __attribute__( ( __packed__ ) ) PARTITION_RECORD;
} __attribute__((__packed__)) PARTITION_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 */
PARTITION_RECORD partitions[4]; /* 4 primary partitions */
u16 signature; /* MBR signature; 0xAA55 */
} __attribute__( ( __packed__ ) ) MASTER_BOOT_RECORD;
} __attribute__((__packed__)) MASTER_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 */
PARTITION_RECORD partition; /* Primary partition */
PARTITION_RECORD next_ebr; /* Next extended boot record in the chain */
u8 reserved[32]; /* Normally empty */
u16 signature; /* EBR signature; 0xAA55 */
} __attribute__( ( __packed__ ) ) EXTENDED_BOOT_RECORD;
} __attribute__((__packed__)) EXTENDED_BOOT_RECORD;
/**
* INTERFACE_ID - Disc interface identifier
*/
typedef struct _INTERFACE_ID
{
typedef struct _INTERFACE_ID {
const char *name; /* Interface name */
const DISC_INTERFACE *interface; /* Disc interface */
} INTERFACE_ID;
@ -113,8 +109,7 @@ typedef struct _INTERFACE_ID
/**
* ntfs_atime_t - File access time update strategies
*/
typedef enum
{
typedef enum {
ATIME_ENABLED, /* Update access times */
ATIME_DISABLED /* Don't update access times */
} ntfs_atime_t;
@ -122,8 +117,7 @@ typedef enum
/**
* ntfs_vd - NTFS volume descriptor
*/
typedef struct _ntfs_vd
{
typedef struct _ntfs_vd {
struct ntfs_device *dev; /* NTFS device handle */
ntfs_volume *vol; /* NTFS volume handle */
mutex_t lock; /* Volume lock mutex */
@ -145,40 +139,40 @@ typedef struct _ntfs_vd
} ntfs_vd;
/* Lock volume */
static inline void ntfsLock ( ntfs_vd *vd )
static inline void ntfsLock (ntfs_vd *vd)
{
LWP_MutexLock( vd->lock );
LWP_MutexLock(vd->lock);
}
/* Unlock volume */
static inline void ntfsUnlock ( ntfs_vd *vd )
static inline void ntfsUnlock (ntfs_vd *vd)
{
LWP_MutexUnlock( vd->lock );
LWP_MutexUnlock(vd->lock);
}
/* Gekko device related routines */
int ntfsAddDevice ( const char *name, void *deviceData );
void ntfsRemoveDevice ( const char *path );
const devoptab_t *ntfsGetDevice ( const char *path, bool useDefaultDevice );
const devoptab_t *ntfsGetDevOpTab ( void );
const INTERFACE_ID* ntfsGetDiscInterfaces ( void );
int ntfsAddDevice (const char *name, void *deviceData);
void ntfsRemoveDevice (const char *path);
const devoptab_t *ntfsGetDevice (const char *path, bool useDefaultDevice);
const devoptab_t *ntfsGetDevOpTab (void);
const INTERFACE_ID* ntfsGetDiscInterfaces (void);
/* Miscellaneous helper/support routines */
int ntfsInitVolume ( ntfs_vd *vd );
void ntfsDeinitVolume ( ntfs_vd *vd );
ntfs_vd *ntfsGetVolume ( const char *path );
ntfs_inode *ntfsOpenEntry ( ntfs_vd *vd, const char *path );
ntfs_inode *ntfsParseEntry ( ntfs_vd *vd, const char *path, int reparseLevel );
void ntfsCloseEntry ( ntfs_vd *vd, ntfs_inode *ni );
ntfs_inode *ntfsCreate ( ntfs_vd *vd, const char *path, mode_t type, const char *target );
int ntfsLink ( ntfs_vd *vd, const char *old_path, const char *new_path );
int ntfsUnlink ( ntfs_vd *vd, const char *path );
int ntfsSync ( ntfs_vd *vd, ntfs_inode *ni );
int ntfsStat ( ntfs_vd *vd, ntfs_inode *ni, struct stat *st );
void ntfsUpdateTimes ( ntfs_vd *vd, ntfs_inode *ni, ntfs_time_update_flags mask );
int ntfsInitVolume (ntfs_vd *vd);
void ntfsDeinitVolume (ntfs_vd *vd);
ntfs_vd *ntfsGetVolume (const char *path);
ntfs_inode *ntfsOpenEntry (ntfs_vd *vd, const char *path);
ntfs_inode *ntfsParseEntry (ntfs_vd *vd, const char *path, int reparseLevel);
void ntfsCloseEntry (ntfs_vd *vd, ntfs_inode *ni);
ntfs_inode *ntfsCreate (ntfs_vd *vd, const char *path, mode_t type, const char *target);
int ntfsLink (ntfs_vd *vd, const char *old_path, const char *new_path);
int ntfsUnlink (ntfs_vd *vd, const char *path);
int ntfsSync (ntfs_vd *vd, ntfs_inode *ni);
int ntfsStat (ntfs_vd *vd, ntfs_inode *ni, struct stat *st);
void ntfsUpdateTimes (ntfs_vd *vd, ntfs_inode *ni, ntfs_time_update_flags mask);
const char *ntfsRealPath ( const char *path );
int ntfsUnicodeToLocal ( const ntfschar *ins, const int ins_len, char **outs, int outs_len );
int ntfsLocalToUnicode ( const char *ins, ntfschar **outs );
const char *ntfsRealPath (const char *path);
int ntfsUnicodeToLocal (const ntfschar *ins, const int ins_len, char **outs, int outs_len);
int ntfsLocalToUnicode (const char *ins, ntfschar **outs);
#endif /* _NTFSINTERNAL_H */

View File

@ -55,19 +55,19 @@ typedef sle64 ntfs_time;
*
* Return: A Unix time (number of seconds since 1970, and nanoseconds)
*/
static __inline__ struct timespec ntfs2timespec( ntfs_time ntfstime )
static __inline__ struct timespec ntfs2timespec(ntfs_time ntfstime)
{
struct timespec spec;
s64 cputime;
cputime = sle64_to_cpu( ntfstime );
spec.tv_sec = ( cputime - ( NTFS_TIME_OFFSET ) ) / 10000000;
spec.tv_nsec = ( cputime - ( NTFS_TIME_OFFSET )
- ( s64 )spec.tv_sec*10000000 )*100;
cputime = sle64_to_cpu(ntfstime);
spec.tv_sec = (cputime - (NTFS_TIME_OFFSET)) / 10000000;
spec.tv_nsec = (cputime - (NTFS_TIME_OFFSET)
- (s64)spec.tv_sec*10000000)*100;
/* force zero nsec for overflowing dates */
if ( ( spec.tv_nsec < 0 ) || ( spec.tv_nsec > 999999999 ) )
if ((spec.tv_nsec < 0) || (spec.tv_nsec > 999999999))
spec.tv_nsec = 0;
return ( spec );
return (spec);
}
/**
@ -86,36 +86,36 @@ static __inline__ struct timespec ntfs2timespec( ntfs_time ntfstime )
*
* Return: An NTFS time (100ns units since Jan 1601)
*/
static __inline__ ntfs_time timespec2ntfs( struct timespec spec )
static __inline__ ntfs_time timespec2ntfs(struct timespec spec)
{
s64 units;
units = ( s64 )spec.tv_sec * 10000000
+ NTFS_TIME_OFFSET + spec.tv_nsec / 100;
return ( cpu_to_le64( units ) );
units = (s64)spec.tv_sec * 10000000
+ NTFS_TIME_OFFSET + spec.tv_nsec/100;
return (cpu_to_le64(units));
}
/*
* Return the current time in ntfs format
*/
static __inline__ ntfs_time ntfs_current_time( void )
static __inline__ ntfs_time ntfs_current_time(void)
{
struct timespec now;
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_SYS_CLOCK_GETTIME)
clock_gettime( CLOCK_REALTIME, &now );
clock_gettime(CLOCK_REALTIME, &now);
#elif defined(HAVE_GETTIMEOFDAY)
struct timeval microseconds;
gettimeofday( &microseconds, ( struct timezone* )NULL );
gettimeofday(&microseconds, (struct timezone*)NULL);
now.tv_sec = microseconds.tv_sec;
now.tv_nsec = microseconds.tv_usec * 1000;
now.tv_nsec = microseconds.tv_usec*1000;
#else
now.tv_sec = time( ( time_t* )NULL );
now.tv_sec = time((time_t*)NULL);
now.tv_nsec = 0;
#endif
return ( timespec2ntfs( now ) );
return (timespec2ntfs(now));
}
#endif /* _NTFS_NTFSTIME_H */

View File

@ -106,29 +106,25 @@
* ---------------------- end from RFC 4122 -----------------------
*/
typedef struct
{
typedef struct {
GUID object_id;
} OBJECT_ID_INDEX_KEY;
typedef struct
{
typedef struct {
le64 file_id;
GUID birth_volume_id;
GUID birth_object_id;
GUID domain_id;
} 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;
OBJECT_ID_INDEX_KEY key;
OBJECT_ID_INDEX_DATA data;
} ;
static ntfschar objid_index_name[] = { const_cpu_to_le16( '$' ),
const_cpu_to_le16( 'O' )
};
static ntfschar objid_index_name[] = { const_cpu_to_le16('$'),
const_cpu_to_le16('O') };
#ifdef HAVE_SETXATTR /* extended attributes interface required */
/*
@ -138,8 +134,8 @@ static ntfschar objid_index_name[] = { const_cpu_to_le16( '$' ),
* -1 if failure, explained by errno
*/
static int set_object_id_index( ntfs_inode *ni, ntfs_index_context *xo,
const OBJECT_ID_ATTR *object_id )
static int set_object_id_index(ntfs_inode *ni, ntfs_index_context *xo,
const OBJECT_ID_ATTR *object_id)
{
struct OBJECT_ID_INDEX indx;
u64 file_id_cpu;
@ -147,32 +143,32 @@ static int set_object_id_index( ntfs_inode *ni, ntfs_index_context *xo,
le16 seqn;
seqn = ni->mrec->sequence_number;
file_id_cpu = MK_MREF( ni->mft_no, le16_to_cpu( seqn ) );
file_id = cpu_to_le64( file_id_cpu );
file_id_cpu = MK_MREF(ni->mft_no,le16_to_cpu(seqn));
file_id = cpu_to_le64(file_id_cpu);
indx.header.data_offset = const_cpu_to_le16(
sizeof( INDEX_ENTRY_HEADER )
+ sizeof( OBJECT_ID_INDEX_KEY ) );
sizeof(INDEX_ENTRY_HEADER)
+ sizeof(OBJECT_ID_INDEX_KEY));
indx.header.data_length = const_cpu_to_le16(
sizeof( OBJECT_ID_INDEX_DATA ) );
indx.header.reservedV = const_cpu_to_le32( 0 );
sizeof(OBJECT_ID_INDEX_DATA));
indx.header.reservedV = const_cpu_to_le32(0);
indx.header.length = const_cpu_to_le16(
sizeof( struct OBJECT_ID_INDEX ) );
sizeof(struct OBJECT_ID_INDEX));
indx.header.key_length = const_cpu_to_le16(
sizeof( OBJECT_ID_INDEX_KEY ) );
indx.header.flags = const_cpu_to_le16( 0 );
indx.header.reserved = const_cpu_to_le16( 0 );
sizeof(OBJECT_ID_INDEX_KEY));
indx.header.flags = const_cpu_to_le16(0);
indx.header.reserved = const_cpu_to_le16(0);
memcpy( &indx.key.object_id, object_id, sizeof( GUID ) );
memcpy(&indx.key.object_id,object_id,sizeof(GUID));
indx.data.file_id = file_id;
memcpy( &indx.data.birth_volume_id,
&object_id->birth_volume_id, sizeof( GUID ) );
memcpy( &indx.data.birth_object_id,
&object_id->birth_object_id, sizeof( GUID ) );
memcpy( &indx.data.domain_id,
&object_id->domain_id, sizeof( GUID ) );
ntfs_index_ctx_reinit( xo );
return ( ntfs_ie_add( xo, ( INDEX_ENTRY* )&indx ) );
memcpy(&indx.data.birth_volume_id,
&object_id->birth_volume_id,sizeof(GUID));
memcpy(&indx.data.birth_object_id,
&object_id->birth_object_id,sizeof(GUID));
memcpy(&indx.data.domain_id,
&object_id->domain_id,sizeof(GUID));
ntfs_index_ctx_reinit(xo);
return (ntfs_ie_add(xo,(INDEX_ENTRY*)&indx));
}
#endif /* HAVE_SETXATTR */
@ -186,7 +182,7 @@ static int set_object_id_index( ntfs_inode *ni, ntfs_index_context *xo,
* The index has to be freed and inode closed when not needed any more.
*/
static ntfs_index_context *open_object_id_index( ntfs_volume *vol )
static ntfs_index_context *open_object_id_index(ntfs_volume *vol)
{
u64 inum;
ntfs_inode *ni;
@ -194,26 +190,22 @@ static ntfs_index_context *open_object_id_index( ntfs_volume *vol )
ntfs_index_context *xo;
/* do not use path_name_to inode - could reopen root */
dir_ni = ntfs_inode_open( vol, FILE_Extend );
ni = ( ntfs_inode* )NULL;
if ( dir_ni )
{
inum = ntfs_inode_lookup_by_mbsname( dir_ni, "$ObjId" );
if ( inum != ( u64 ) - 1 )
ni = ntfs_inode_open( vol, inum );
ntfs_inode_close( dir_ni );
dir_ni = ntfs_inode_open(vol, FILE_Extend);
ni = (ntfs_inode*)NULL;
if (dir_ni) {
inum = ntfs_inode_lookup_by_mbsname(dir_ni,"$ObjId");
if (inum != (u64)-1)
ni = ntfs_inode_open(vol, inum);
ntfs_inode_close(dir_ni);
}
if ( ni )
{
xo = ntfs_index_ctx_get( ni, objid_index_name, 2 );
if ( !xo )
{
ntfs_inode_close( ni );
if (ni) {
xo = ntfs_index_ctx_get(ni, objid_index_name, 2);
if (!xo) {
ntfs_inode_close(ni);
}
}
else
xo = ( ntfs_index_context* )NULL;
return ( xo );
} else
xo = (ntfs_index_context*)NULL;
return (xo);
}
#ifdef HAVE_SETXATTR /* extended attributes interface required */
@ -226,9 +218,9 @@ static ntfs_index_context *open_object_id_index( ntfs_volume *vol )
* -1 if no data could be merged. This is generally not an error
*/
static int merge_index_data( ntfs_inode *ni,
static int merge_index_data(ntfs_inode *ni,
const OBJECT_ID_ATTR *objectid_attr,
OBJECT_ID_ATTR *full_objectid )
OBJECT_ID_ATTR *full_objectid)
{
OBJECT_ID_INDEX_KEY key;
struct OBJECT_ID_INDEX *entry;
@ -237,36 +229,33 @@ static int merge_index_data( ntfs_inode *ni,
int res;
res = -1;
xo = open_object_id_index( ni->vol );
if ( xo )
{
memcpy( &key.object_id, objectid_attr, sizeof( GUID ) );
if ( !ntfs_index_lookup( &key,
sizeof( OBJECT_ID_INDEX_KEY ), xo ) )
{
entry = ( struct OBJECT_ID_INDEX* )xo->entry;
xo = open_object_id_index(ni->vol);
if (xo) {
memcpy(&key.object_id,objectid_attr,sizeof(GUID));
if (!ntfs_index_lookup(&key,
sizeof(OBJECT_ID_INDEX_KEY), xo)) {
entry = (struct OBJECT_ID_INDEX*)xo->entry;
/* make sure inode numbers match */
if ( entry
&& ( MREF( le64_to_cpu( entry->data.file_id ) )
== ni->mft_no ) )
{
memcpy( &full_objectid->birth_volume_id,
if (entry
&& (MREF(le64_to_cpu(entry->data.file_id))
== ni->mft_no)) {
memcpy(&full_objectid->birth_volume_id,
&entry->data.birth_volume_id,
sizeof( GUID ) );
memcpy( &full_objectid->birth_object_id,
sizeof(GUID));
memcpy(&full_objectid->birth_object_id,
&entry->data.birth_object_id,
sizeof( GUID ) );
memcpy( &full_objectid->domain_id,
sizeof(GUID));
memcpy(&full_objectid->domain_id,
&entry->data.domain_id,
sizeof( GUID ) );
sizeof(GUID));
res = 0;
}
}
xoni = xo->ni;
ntfs_index_ctx_put( xo );
ntfs_inode_close( xoni );
ntfs_index_ctx_put(xo);
ntfs_inode_close(xoni);
}
return ( res );
return (res);
}
#endif /* HAVE_SETXATTR */
@ -279,8 +268,8 @@ static int merge_index_data( ntfs_inode *ni,
* -1 if failure, explained by errno
*/
static int remove_object_id_index( ntfs_attr *na, ntfs_index_context *xo,
OBJECT_ID_ATTR *old_attr )
static int remove_object_id_index(ntfs_attr *na, ntfs_index_context *xo,
OBJECT_ID_ATTR *old_attr)
{
OBJECT_ID_INDEX_KEY key;
struct OBJECT_ID_INDEX *entry;
@ -288,40 +277,35 @@ static int remove_object_id_index( ntfs_attr *na, ntfs_index_context *xo,
int ret;
ret = na->data_size;
if ( ret )
{
if (ret) {
/* read the existing object id attribute */
size = ntfs_attr_pread( na, 0, sizeof( GUID ), old_attr );
if ( size >= ( s64 )sizeof( GUID ) )
{
memcpy( &key.object_id,
&old_attr->object_id, sizeof( GUID ) );
size = sizeof( GUID );
if ( !ntfs_index_lookup( &key,
sizeof( OBJECT_ID_INDEX_KEY ), xo ) )
{
entry = ( struct OBJECT_ID_INDEX* )xo->entry;
memcpy( &old_attr->birth_volume_id,
size = ntfs_attr_pread(na, 0, sizeof(GUID), old_attr);
if (size >= (s64)sizeof(GUID)) {
memcpy(&key.object_id,
&old_attr->object_id,sizeof(GUID));
size = sizeof(GUID);
if (!ntfs_index_lookup(&key,
sizeof(OBJECT_ID_INDEX_KEY), xo)) {
entry = (struct OBJECT_ID_INDEX*)xo->entry;
memcpy(&old_attr->birth_volume_id,
&entry->data.birth_volume_id,
sizeof( GUID ) );
memcpy( &old_attr->birth_object_id,
sizeof(GUID));
memcpy(&old_attr->birth_object_id,
&entry->data.birth_object_id,
sizeof( GUID ) );
memcpy( &old_attr->domain_id,
sizeof(GUID));
memcpy(&old_attr->domain_id,
&entry->data.domain_id,
sizeof( GUID ) );
size = sizeof( OBJECT_ID_ATTR );
if ( ntfs_index_rm( xo ) )
sizeof(GUID));
size = sizeof(OBJECT_ID_ATTR);
if (ntfs_index_rm(xo))
ret = -1;
}
}
else
{
} else {
ret = -1;
errno = ENODATA;
}
}
return ( ret );
return (ret);
}
#ifdef HAVE_SETXATTR /* extended attributes interface required */
@ -339,8 +323,8 @@ static int remove_object_id_index( ntfs_attr *na, ntfs_index_context *xo,
* If failed to insert the index, data is removed
*/
static int update_object_id( ntfs_inode *ni, ntfs_index_context *xo,
const OBJECT_ID_ATTR *value, size_t size )
static int update_object_id(ntfs_inode *ni, ntfs_index_context *xo,
const OBJECT_ID_ATTR *value, size_t size)
{
OBJECT_ID_ATTR old_attr;
ntfs_attr *na;
@ -350,53 +334,47 @@ static int update_object_id( ntfs_inode *ni, ntfs_index_context *xo,
res = 0;
na = ntfs_attr_open( ni, AT_OBJECT_ID, AT_UNNAMED, 0 );
if ( na )
{
na = ntfs_attr_open(ni, AT_OBJECT_ID, AT_UNNAMED, 0);
if (na) {
/* remove the existing index entry */
oldsize = remove_object_id_index( na, xo, &old_attr );
if ( oldsize < 0 )
oldsize = remove_object_id_index(na,xo,&old_attr);
if (oldsize < 0)
res = -1;
else
{
else {
/* resize attribute */
res = ntfs_attr_truncate( na, ( s64 )sizeof( GUID ) );
res = ntfs_attr_truncate(na, (s64)sizeof(GUID));
/* write the object_id in attribute */
if ( !res && value )
{
written = ( int )ntfs_attr_pwrite( na,
( s64 )0, ( s64 )sizeof( GUID ),
&value->object_id );
if ( written != ( s64 )sizeof( GUID ) )
{
ntfs_log_error( "Failed to update "
"object id\n" );
if (!res && value) {
written = (int)ntfs_attr_pwrite(na,
(s64)0, (s64)sizeof(GUID),
&value->object_id);
if (written != (s64)sizeof(GUID)) {
ntfs_log_error("Failed to update "
"object id\n");
errno = EIO;
res = -1;
}
}
/* write index part if provided */
if ( !res
&& ( ( size < sizeof( OBJECT_ID_ATTR ) )
|| set_object_id_index( ni, xo, value ) ) )
{
if (!res
&& ((size < sizeof(OBJECT_ID_ATTR))
|| set_object_id_index(ni,xo,value))) {
/*
* If cannot index, try to remove the object
* id and log the error. There will be an
* inconsistency if removal fails.
*/
ntfs_attr_rm( na );
ntfs_log_error( "Failed to index object id."
" Possible corruption.\n" );
ntfs_attr_rm(na);
ntfs_log_error("Failed to index object id."
" Possible corruption.\n");
}
}
ntfs_attr_close( na );
NInoSetDirty( ni );
}
else
ntfs_attr_close(na);
NInoSetDirty(ni);
} else
res = -1;
return ( res );
return (res);
}
/*
@ -406,41 +384,34 @@ static int update_object_id( ntfs_inode *ni, ntfs_index_context *xo,
* -1 if adding failed (explained by errno)
*/
static int add_object_id( ntfs_inode *ni, int flags )
static int add_object_id(ntfs_inode *ni, int flags)
{
int res;
u8 dummy;
res = -1; /* default return */
if ( !ntfs_attr_exist( ni, AT_OBJECT_ID, AT_UNNAMED, 0 ) )
{
if ( !( flags & XATTR_REPLACE ) )
{
if (!ntfs_attr_exist(ni,AT_OBJECT_ID, AT_UNNAMED,0)) {
if (!(flags & XATTR_REPLACE)) {
/*
* no object id attribute : add one,
* apparently, this does not feed the new value in
* Note : NTFS version must be >= 3
*/
if ( ni->vol->major_ver >= 3 )
{
res = ntfs_attr_add( ni, AT_OBJECT_ID,
AT_UNNAMED, 0, &dummy, ( s64 )0 );
NInoSetDirty( ni );
}
else
if (ni->vol->major_ver >= 3) {
res = ntfs_attr_add(ni, AT_OBJECT_ID,
AT_UNNAMED, 0, &dummy, (s64)0);
NInoSetDirty(ni);
} else
errno = EOPNOTSUPP;
}
else
} else
errno = ENODATA;
}
else
{
if ( flags & XATTR_CREATE )
} else {
if (flags & XATTR_CREATE)
errno = EEXIST;
else
res = 0;
}
return ( res );
return (res);
}
#endif /* HAVE_SETXATTR */
@ -452,7 +423,7 @@ static int add_object_id( ntfs_inode *ni, int flags )
* -1 if failure, explained by errno
*/
int ntfs_delete_object_id_index( ntfs_inode *ni )
int ntfs_delete_object_id_index(ntfs_inode *ni)
{
ntfs_index_context *xo;
ntfs_inode *xoni;
@ -461,27 +432,25 @@ int ntfs_delete_object_id_index( ntfs_inode *ni )
int res;
res = 0;
na = ntfs_attr_open( ni, AT_OBJECT_ID, AT_UNNAMED, 0 );
if ( na )
{
na = ntfs_attr_open(ni, AT_OBJECT_ID, AT_UNNAMED, 0);
if (na) {
/*
* read the existing object id
* and un-index it
*/
xo = open_object_id_index( ni->vol );
if ( xo )
{
if ( remove_object_id_index( na, xo, &old_attr ) < 0 )
xo = open_object_id_index(ni->vol);
if (xo) {
if (remove_object_id_index(na,xo,&old_attr) < 0)
res = -1;
xoni = xo->ni;
ntfs_index_entry_mark_dirty( xo );
NInoSetDirty( xoni );
ntfs_index_ctx_put( xo );
ntfs_inode_close( xoni );
ntfs_index_entry_mark_dirty(xo);
NInoSetDirty(xoni);
ntfs_index_ctx_put(xo);
ntfs_inode_close(xoni);
}
ntfs_attr_close( na );
ntfs_attr_close(na);
}
return ( res );
return (res);
}
#ifdef HAVE_SETXATTR /* extended attributes interface required */
@ -496,7 +465,7 @@ int ntfs_delete_object_id_index( ntfs_inode *ni )
* and the buffer is updated if it is long enough
*/
int ntfs_get_ntfs_object_id( ntfs_inode *ni, char *value, size_t size )
int ntfs_get_ntfs_object_id(ntfs_inode *ni, char *value, size_t size)
{
OBJECT_ID_ATTR full_objectid;
OBJECT_ID_ATTR *objectid_attr;
@ -504,45 +473,37 @@ int ntfs_get_ntfs_object_id( ntfs_inode *ni, char *value, size_t size )
int full_size;
full_size = 0; /* default to no data and some error to be defined */
if ( ni )
{
objectid_attr = ( OBJECT_ID_ATTR* )ntfs_attr_readall( ni,
AT_OBJECT_ID, ( ntfschar* )NULL, 0, &attr_size );
if ( objectid_attr )
{
if (ni) {
objectid_attr = (OBJECT_ID_ATTR*)ntfs_attr_readall(ni,
AT_OBJECT_ID,(ntfschar*)NULL, 0, &attr_size);
if (objectid_attr) {
/* restrict to only GUID present in attr */
if ( attr_size == sizeof( GUID ) )
{
memcpy( &full_objectid.object_id,
objectid_attr, sizeof( GUID ) );
full_size = sizeof( GUID );
if (attr_size == sizeof(GUID)) {
memcpy(&full_objectid.object_id,
objectid_attr,sizeof(GUID));
full_size = sizeof(GUID);
/* get data from index, if any */
if ( !merge_index_data( ni, objectid_attr,
&full_objectid ) )
{
full_size = sizeof( OBJECT_ID_ATTR );
if (!merge_index_data(ni, objectid_attr,
&full_objectid)) {
full_size = sizeof(OBJECT_ID_ATTR);
}
if ( full_size <= ( s64 )size )
{
if ( value )
memcpy( value, &full_objectid,
full_size );
if (full_size <= (s64)size) {
if (value)
memcpy(value,&full_objectid,
full_size);
else
errno = EINVAL;
}
}
else
{
} else {
/* unexpected size, better return unsupported */
errno = EOPNOTSUPP;
full_size = 0;
}
free( objectid_attr );
}
else
free(objectid_attr);
} else
errno = ENODATA;
}
return ( full_size ? ( int )full_size : -errno );
return (full_size ? (int)full_size : -errno);
}
/*
@ -555,8 +516,8 @@ int ntfs_get_ntfs_object_id( ntfs_inode *ni, char *value, size_t size )
* Returns 0, or -1 if there is a problem
*/
int ntfs_set_ntfs_object_id( ntfs_inode *ni,
const char *value, size_t size, int flags )
int ntfs_set_ntfs_object_id(ntfs_inode *ni,
const char *value, size_t size, int flags)
{
OBJECT_ID_INDEX_KEY key;
ntfs_inode *xoni;
@ -564,49 +525,39 @@ int ntfs_set_ntfs_object_id( ntfs_inode *ni,
int res;
res = 0;
if ( ni && value && ( size >= sizeof( GUID ) ) )
{
xo = open_object_id_index( ni->vol );
if ( xo )
{
if (ni && value && (size >= sizeof(GUID))) {
xo = open_object_id_index(ni->vol);
if (xo) {
/* make sure the GUID was not used somewhere */
memcpy( &key.object_id, value, sizeof( GUID ) );
if ( ntfs_index_lookup( &key,
sizeof( OBJECT_ID_INDEX_KEY ), xo ) )
{
ntfs_index_ctx_reinit( xo );
res = add_object_id( ni, flags );
if ( !res )
{
memcpy(&key.object_id, value, sizeof(GUID));
if (ntfs_index_lookup(&key,
sizeof(OBJECT_ID_INDEX_KEY), xo)) {
ntfs_index_ctx_reinit(xo);
res = add_object_id(ni, flags);
if (!res) {
/* update value and index */
res = update_object_id( ni, xo,
( const OBJECT_ID_ATTR* )value,
size );
res = update_object_id(ni,xo,
(const OBJECT_ID_ATTR*)value,
size);
}
}
else
{
} else {
/* GUID is present elsewhere */
res = -1;
errno = EEXIST;
}
xoni = xo->ni;
ntfs_index_entry_mark_dirty( xo );
NInoSetDirty( xoni );
ntfs_index_ctx_put( xo );
ntfs_inode_close( xoni );
}
else
{
ntfs_index_entry_mark_dirty(xo);
NInoSetDirty(xoni);
ntfs_index_ctx_put(xo);
ntfs_inode_close(xoni);
} else {
res = -1;
}
}
else
{
} else {
errno = EINVAL;
res = -1;
}
return ( res ? -1 : 0 );
return (res ? -1 : 0);
}
/*
@ -615,7 +566,7 @@ int ntfs_set_ntfs_object_id( ntfs_inode *ni,
* Returns 0, or -1 if there is a problem
*/
int ntfs_remove_ntfs_object_id( ntfs_inode *ni )
int ntfs_remove_ntfs_object_id(ntfs_inode *ni)
{
int res;
int olderrno;
@ -626,32 +577,25 @@ int ntfs_remove_ntfs_object_id( ntfs_inode *ni )
OBJECT_ID_ATTR old_attr;
res = 0;
if ( ni )
{
if (ni) {
/*
* open and delete the object id
*/
na = ntfs_attr_open( ni, AT_OBJECT_ID,
AT_UNNAMED, 0 );
if ( na )
{
na = ntfs_attr_open(ni, AT_OBJECT_ID,
AT_UNNAMED,0);
if (na) {
/* first remove index (old object id needed) */
xo = open_object_id_index( ni->vol );
if ( xo )
{
oldsize = remove_object_id_index( na, xo,
&old_attr );
if ( oldsize < 0 )
{
xo = open_object_id_index(ni->vol);
if (xo) {
oldsize = remove_object_id_index(na,xo,
&old_attr);
if (oldsize < 0) {
res = -1;
}
else
{
} else {
/* now remove attribute */
res = ntfs_attr_rm( na );
if ( res
&& ( oldsize > ( int )sizeof( GUID ) ) )
{
res = ntfs_attr_rm(na);
if (res
&& (oldsize > (int)sizeof(GUID))) {
/*
* If we could not remove the
* attribute, try to restore the
@ -659,39 +603,35 @@ int ntfs_remove_ntfs_object_id( ntfs_inode *ni )
* will be an inconsistency if
* the reindexing fails.
*/
set_object_id_index( ni, xo,
&old_attr );
set_object_id_index(ni, xo,
&old_attr);
ntfs_log_error(
"Failed to remove object id."
" Possible corruption.\n" );
" Possible corruption.\n");
}
}
xoni = xo->ni;
ntfs_index_entry_mark_dirty( xo );
NInoSetDirty( xoni );
ntfs_index_ctx_put( xo );
ntfs_inode_close( xoni );
ntfs_index_entry_mark_dirty(xo);
NInoSetDirty(xoni);
ntfs_index_ctx_put(xo);
ntfs_inode_close(xoni);
}
olderrno = errno;
ntfs_attr_close( na );
ntfs_attr_close(na);
/* avoid errno pollution */
if ( errno == ENOENT )
if (errno == ENOENT)
errno = olderrno;
}
else
{
} else {
errno = ENODATA;
res = -1;
}
NInoSetDirty( ni );
}
else
{
NInoSetDirty(ni);
} else {
errno = EINVAL;
res = -1;
}
return ( res ? -1 : 0 );
return (res ? -1 : 0);
}
#endif /* HAVE_SETXATTR */

View File

@ -24,12 +24,12 @@
#ifndef OBJECT_ID_H
#define OBJECT_ID_H
int ntfs_get_ntfs_object_id( ntfs_inode *ni, char *value, size_t size );
int ntfs_get_ntfs_object_id(ntfs_inode *ni, char *value, size_t size);
int ntfs_set_ntfs_object_id( ntfs_inode *ni, const char *value,
size_t size, int flags );
int ntfs_remove_ntfs_object_id( ntfs_inode *ni );
int ntfs_set_ntfs_object_id(ntfs_inode *ni, const char *value,
size_t size, int flags);
int ntfs_remove_ntfs_object_id(ntfs_inode *ni);
int ntfs_delete_object_id_index( ntfs_inode *ni );
int ntfs_delete_object_id_index(ntfs_inode *ni);
#endif /* OBJECT_ID_H */

View File

@ -31,9 +31,8 @@
#define FORCE_FORMAT_v1x 0 /* Insert security data as in NTFS v1.x */
#define OWNERFROMACL 1 /* Get the owner from ACL (not Windows owner) */
/* default security sub-authorities */
enum
{
/* default security sub-authorities */
enum {
DEFSECAUTH1 = -1153374643, /* 3141592653 */
DEFSECAUTH2 = 589793238,
DEFSECAUTH3 = 462843383,
@ -44,11 +43,11 @@ enum
* Parameters for compression
*/
/* default option for compression */
/* default option for compression */
#define DEFAULT_COMPRESSION FALSE
/* (log2 of) number of clusters in a compression block for new files */
/* (log2 of) number of clusters in a compression block for new files */
#define STANDARD_COMPRESSION_UNIT 4
/* maximum cluster size for allowing compression for new files */
/* maximum cluster size for allowing compression for new files */
#define MAX_COMPRESSION_CLUSTER_SIZE 4096
/*

File diff suppressed because it is too large Load Diff

View File

@ -24,16 +24,16 @@
#ifndef REPARSE_H
#define REPARSE_H
char *ntfs_make_symlink( ntfs_inode *ni, const char *mnt_point,
int *pattr_size );
BOOL ntfs_possible_symlink( ntfs_inode *ni );
char *ntfs_make_symlink(ntfs_inode *ni, const char *mnt_point,
int *pattr_size);
BOOL ntfs_possible_symlink(ntfs_inode *ni);
int ntfs_get_ntfs_reparse_data( ntfs_inode *ni, char *value, size_t size );
int ntfs_get_ntfs_reparse_data(ntfs_inode *ni, char *value, size_t size);
int ntfs_set_ntfs_reparse_data( ntfs_inode *ni, const char *value,
size_t size, int flags );
int ntfs_remove_ntfs_reparse_data( ntfs_inode *ni );
int ntfs_set_ntfs_reparse_data(ntfs_inode *ni, const char *value,
size_t size, int flags);
int ntfs_remove_ntfs_reparse_data(ntfs_inode *ni);
int ntfs_delete_reparse_index( ntfs_inode *ni );
int ntfs_delete_reparse_index(ntfs_inode *ni);
#endif /* REPARSE_H */

File diff suppressed because it is too large Load Diff

View File

@ -43,48 +43,47 @@ typedef runlist_element runlist;
* 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).
*/
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. */
LCN lcn; /* lcn = Starting logical cluster number. */
s64 length; /* Run length in clusters. */
};
extern runlist_element *ntfs_rl_extend( ntfs_attr *na, runlist_element *rl,
int more_entries );
extern runlist_element *ntfs_rl_extend(ntfs_attr *na, runlist_element *rl,
int more_entries);
extern LCN ntfs_rl_vcn_to_lcn( const runlist_element *rl, const VCN vcn );
extern LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn);
extern s64 ntfs_rl_pread( const ntfs_volume *vol, const runlist_element *rl,
const s64 pos, s64 count, void *b );
extern s64 ntfs_rl_pwrite( const ntfs_volume *vol, const runlist_element *rl,
s64 ofs, const s64 pos, s64 count, void *b );
extern s64 ntfs_rl_pread(const ntfs_volume *vol, const runlist_element *rl,
const s64 pos, s64 count, void *b);
extern s64 ntfs_rl_pwrite(const ntfs_volume *vol, const runlist_element *rl,
s64 ofs, const s64 pos, s64 count, void *b);
extern runlist_element *ntfs_runlists_merge( runlist_element *drl,
runlist_element *srl );
extern runlist_element *ntfs_runlists_merge(runlist_element *drl,
runlist_element *srl);
extern runlist_element *ntfs_mapping_pairs_decompress( const ntfs_volume *vol,
const ATTR_RECORD *attr, runlist_element *old_rl );
extern runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol,
const ATTR_RECORD *attr, runlist_element *old_rl);
extern int ntfs_get_nr_significant_bytes( const s64 n );
extern int ntfs_get_nr_significant_bytes(const s64 n);
extern int ntfs_get_size_for_mapping_pairs( const ntfs_volume *vol,
const runlist_element *rl, const VCN start_vcn, int max_size );
extern int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
const runlist_element *rl, const VCN start_vcn, int max_size);
extern int ntfs_write_significant_bytes( u8 *dst, const u8 *dst_max,
const s64 n );
extern int ntfs_write_significant_bytes(u8 *dst, const u8 *dst_max,
const s64 n);
extern int ntfs_mapping_pairs_build( const ntfs_volume *vol, u8 *dst,
extern int ntfs_mapping_pairs_build(const ntfs_volume *vol, u8 *dst,
const int dst_len, const runlist_element *rl,
const VCN start_vcn, runlist_element const **stop_rl );
const VCN start_vcn, runlist_element const **stop_rl);
extern int ntfs_rl_truncate( runlist **arl, const VCN start_vcn );
extern int ntfs_rl_truncate(runlist **arl, const VCN start_vcn);
extern int ntfs_rl_sparse( runlist *rl );
extern s64 ntfs_rl_get_compressed_size( ntfs_volume *vol, runlist *rl );
extern int ntfs_rl_sparse(runlist *rl);
extern s64 ntfs_rl_get_compressed_size(ntfs_volume *vol, runlist *rl);
#ifdef NTFS_TEST
int test_rl_main( int argc, char *argv[] );
int test_rl_main(int argc, char *argv[]);
#endif
#endif /* defined _NTFS_RUNLIST_H */

File diff suppressed because it is too large Load Diff

View File

@ -50,8 +50,7 @@ typedef u32 be32;
* item in the mapping list
*/
struct MAPPING
{
struct MAPPING {
struct MAPPING *next;
int xid; /* linux id : uid or gid */
SID *sid; /* Windows id : usid or gsid */
@ -64,26 +63,24 @@ struct MAPPING
* Note : this cache is not organized as a generic cache
*/
struct CACHED_PERMISSIONS
{
struct CACHED_PERMISSIONS {
uid_t uid;
gid_t gid;
le32 inh_fileid;
le32 inh_dirid;
#if POSIXACLS
struct POSIX_SECURITY *pxdesc;
unsigned int pxdescsize: 16;
unsigned int pxdescsize:16;
#endif
unsigned int mode: 12;
unsigned int valid: 1;
unsigned int mode:12;
unsigned int valid:1;
} ;
/*
* 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 *previous;
void *variable;
@ -97,8 +94,7 @@ struct CACHED_PERMISSIONS_LEGACY
* Entry in the securid cache
*/
struct CACHED_SECURID
{
struct CACHED_SECURID {
struct CACHED_SECURID *next;
struct CACHED_SECURID *previous;
void *variable;
@ -115,8 +111,7 @@ struct CACHED_SECURID
* (has no cache structure by itself)
*/
struct CACHED_PERMISSIONS_HEADER
{
struct CACHED_PERMISSIONS_HEADER {
unsigned int last;
/* statistics for permissions */
unsigned long p_writes;
@ -128,8 +123,7 @@ struct CACHED_PERMISSIONS_HEADER
* The whole permissions cache
*/
struct PERMISSIONS_CACHE
{
struct PERMISSIONS_CACHE {
struct CACHED_PERMISSIONS_HEADER head;
struct CACHED_PERMISSIONS *cachetable[1]; /* array of variable size */
} ;
@ -138,8 +132,7 @@ struct PERMISSIONS_CACHE
* Security flags values
*/
enum
{
enum {
SECURITY_DEFAULT, /* rely on fuse for permissions checking */
SECURITY_RAW, /* force same ownership/permissions on files */
SECURITY_ADDSECURIDS, /* upgrade old security descriptors */
@ -153,8 +146,7 @@ enum
enum { MAPUSERS, MAPGROUPS, MAPCOUNT } ;
struct SECURITY_CONTEXT
{
struct SECURITY_CONTEXT {
ntfs_volume *vol;
struct MAPPING *mapping[MAPCOUNT];
struct PERMISSIONS_CACHE **pseccache;
@ -162,7 +154,7 @@ struct SECURITY_CONTEXT
gid_t gid; /* gid of user requesting (not the mounter) */
pid_t tid; /* thread id of thread requesting */
mode_t umask; /* umask of requesting thread */
} ;
} ;
#if POSIXACLS
@ -170,23 +162,20 @@ struct SECURITY_CONTEXT
* Posix ACL structures
*/
struct POSIX_ACE
{
struct POSIX_ACE {
u16 tag;
u16 perms;
s32 id;
} ;
struct POSIX_ACL
{
struct POSIX_ACL {
u8 version;
u8 flags;
u16 filler;
struct POSIX_ACE ace[0];
} ;
struct POSIX_SECURITY
{
struct POSIX_SECURITY {
mode_t mode;
int acccnt;
int defcnt;
@ -199,8 +188,7 @@ struct POSIX_SECURITY
* Posix tags, cpu-endian 16 bits
*/
enum
{
enum {
POSIX_ACL_USER_OBJ = 1,
POSIX_ACL_USER = 2,
POSIX_ACL_GROUP_OBJ = 4,
@ -216,8 +204,7 @@ enum
* Posix permissions, cpu-endian 16 bits
*/
enum
{
enum {
POSIX_PERM_X = 1,
POSIX_PERM_W = 2,
POSIX_PERM_R = 4,
@ -228,8 +215,8 @@ enum
#endif
extern BOOL ntfs_guid_is_zero( const GUID *guid );
extern char *ntfs_guid_to_mbs( const GUID *guid, char *guid_str );
extern BOOL ntfs_guid_is_zero(const GUID *guid);
extern char *ntfs_guid_to_mbs(const GUID *guid, char *guid_str);
/**
* ntfs_sid_is_valid - determine if a SID is valid
@ -239,81 +226,81 @@ extern char *ntfs_guid_to_mbs( const GUID *guid, char *guid_str );
*
* Return TRUE if it is valid and FALSE otherwise.
*/
static __inline__ BOOL ntfs_sid_is_valid( const SID *sid )
static __inline__ BOOL ntfs_sid_is_valid(const SID *sid)
{
if ( !sid || sid->revision != SID_REVISION ||
sid->sub_authority_count > SID_MAX_SUB_AUTHORITIES )
if (!sid || sid->revision != SID_REVISION ||
sid->sub_authority_count > SID_MAX_SUB_AUTHORITIES)
return FALSE;
return TRUE;
}
extern int ntfs_sid_to_mbs_size( const SID *sid );
extern char *ntfs_sid_to_mbs( const SID *sid, char *sid_str,
size_t sid_str_size );
extern void ntfs_generate_guid( GUID *guid );
extern int ntfs_sd_add_everyone( ntfs_inode *ni );
extern int ntfs_sid_to_mbs_size(const SID *sid);
extern char *ntfs_sid_to_mbs(const SID *sid, char *sid_str,
size_t sid_str_size);
extern void ntfs_generate_guid(GUID *guid);
extern int ntfs_sd_add_everyone(ntfs_inode *ni);
extern le32 ntfs_security_hash( const SECURITY_DESCRIPTOR_RELATIVE *sd,
const u32 len );
extern le32 ntfs_security_hash(const SECURITY_DESCRIPTOR_RELATIVE *sd,
const u32 len);
int ntfs_build_mapping( struct SECURITY_CONTEXT *scx, const char *usermap_path,
BOOL allowdef );
int ntfs_get_owner_mode( struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, struct stat* );
int ntfs_set_mode( struct SECURITY_CONTEXT *scx, ntfs_inode *ni, mode_t mode );
BOOL ntfs_allowed_as_owner( struct SECURITY_CONTEXT *scx, ntfs_inode *ni );
int ntfs_allowed_access( struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, int accesstype );
BOOL old_ntfs_allowed_dir_access( struct SECURITY_CONTEXT *scx,
const char *path, int accesstype );
int ntfs_build_mapping(struct SECURITY_CONTEXT *scx, const char *usermap_path,
BOOL allowdef);
int ntfs_get_owner_mode(struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, struct stat*);
int ntfs_set_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, mode_t mode);
BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni);
int ntfs_allowed_access(struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, int accesstype);
BOOL old_ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx,
const char *path, int accesstype);
#if POSIXACLS
le32 ntfs_alloc_securid( struct SECURITY_CONTEXT *scx,
le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx,
uid_t uid, gid_t gid, ntfs_inode *dir_ni,
mode_t mode, BOOL isdir );
mode_t mode, BOOL isdir);
#else
le32 ntfs_alloc_securid( struct SECURITY_CONTEXT *scx,
uid_t uid, gid_t gid, mode_t mode, BOOL isdir );
le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx,
uid_t uid, gid_t gid, mode_t mode, BOOL isdir);
#endif
int ntfs_set_owner( struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
uid_t uid, gid_t gid );
int ntfs_set_ownmod( struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, uid_t uid, gid_t gid, mode_t mode );
int ntfs_set_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
uid_t uid, gid_t gid);
int ntfs_set_ownmod(struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, uid_t uid, gid_t gid, mode_t mode);
#if POSIXACLS
int ntfs_set_owner_mode( struct SECURITY_CONTEXT *scx,
int ntfs_set_owner_mode(struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, uid_t uid, gid_t gid,
mode_t mode, struct POSIX_SECURITY *pxdesc );
mode_t mode, struct POSIX_SECURITY *pxdesc);
#else
int ntfs_set_owner_mode( struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, uid_t uid, gid_t gid, mode_t mode );
int ntfs_set_owner_mode(struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, uid_t uid, gid_t gid, mode_t mode);
#endif
le32 ntfs_inherited_id( struct SECURITY_CONTEXT *scx,
ntfs_inode *dir_ni, BOOL fordir );
int ntfs_open_secure( ntfs_volume *vol );
void ntfs_close_secure( struct SECURITY_CONTEXT *scx );
le32 ntfs_inherited_id(struct SECURITY_CONTEXT *scx,
ntfs_inode *dir_ni, BOOL fordir);
int ntfs_open_secure(ntfs_volume *vol);
void ntfs_close_secure(struct SECURITY_CONTEXT *scx);
#if POSIXACLS
int ntfs_set_inherited_posix( struct SECURITY_CONTEXT *scx,
int ntfs_set_inherited_posix(struct SECURITY_CONTEXT *scx,
ntfs_inode *ni, uid_t uid, gid_t gid,
ntfs_inode *dir_ni, mode_t mode );
int ntfs_get_posix_acl( struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
const char *name, char *value, size_t size );
int ntfs_set_posix_acl( struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
ntfs_inode *dir_ni, mode_t mode);
int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
const char *name, char *value, size_t size);
int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
const char *name, const char *value, size_t size,
int flags );
int ntfs_remove_posix_acl( struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
const char *name );
int flags);
int ntfs_remove_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
const char *name);
#endif
int ntfs_get_ntfs_acl( struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
char *value, size_t size );
int ntfs_set_ntfs_acl( struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
const char *value, size_t size, int flags );
int ntfs_get_ntfs_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
char *value, size_t size);
int ntfs_set_ntfs_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
const char *value, size_t size, int flags);
int ntfs_get_ntfs_attrib( ntfs_inode *ni, char *value, size_t size );
int ntfs_set_ntfs_attrib( ntfs_inode *ni,
const char *value, size_t size, int flags );
int ntfs_get_ntfs_attrib(ntfs_inode *ni, char *value, size_t size);
int ntfs_set_ntfs_attrib(ntfs_inode *ni,
const char *value, size_t size, int flags);
/*
@ -323,8 +310,7 @@ int ntfs_set_ntfs_attrib( ntfs_inode *ni,
#define MAGIC_API 0x09042009
struct SECURITY_API
{
struct SECURITY_API {
u32 magic;
struct SECURITY_CONTEXT security;
struct PERMISSIONS_CACHE *seccache;
@ -340,32 +326,32 @@ enum { OWNER_SECURITY_INFORMATION = 1,
GROUP_SECURITY_INFORMATION = 2,
DACL_SECURITY_INFORMATION = 4,
SACL_SECURITY_INFORMATION = 8
} ;
} ;
int ntfs_get_file_security( struct SECURITY_API *scapi,
int ntfs_get_file_security(struct SECURITY_API *scapi,
const char *path, u32 selection,
char *buf, u32 buflen, u32 *psize );
int ntfs_set_file_security( struct SECURITY_API *scapi,
const char *path, u32 selection, const char *attr );
int ntfs_get_file_attributes( struct SECURITY_API *scapi,
const char *path );
BOOL ntfs_set_file_attributes( struct SECURITY_API *scapi,
const char *path, s32 attrib );
BOOL ntfs_read_directory( struct SECURITY_API *scapi,
const char *path, ntfs_filldir_t callback, void *context );
int ntfs_read_sds( struct SECURITY_API *scapi,
char *buf, u32 size, u32 offset );
INDEX_ENTRY *ntfs_read_sii( struct SECURITY_API *scapi,
INDEX_ENTRY *entry );
INDEX_ENTRY *ntfs_read_sdh( struct SECURITY_API *scapi,
INDEX_ENTRY *entry );
struct SECURITY_API *ntfs_initialize_file_security( const char *device,
int flags );
BOOL ntfs_leave_file_security( struct SECURITY_API *scx );
char *buf, u32 buflen, u32 *psize);
int ntfs_set_file_security(struct SECURITY_API *scapi,
const char *path, u32 selection, const char *attr);
int ntfs_get_file_attributes(struct SECURITY_API *scapi,
const char *path);
BOOL ntfs_set_file_attributes(struct SECURITY_API *scapi,
const char *path, s32 attrib);
BOOL ntfs_read_directory(struct SECURITY_API *scapi,
const char *path, ntfs_filldir_t callback, void *context);
int ntfs_read_sds(struct SECURITY_API *scapi,
char *buf, u32 size, u32 offset);
INDEX_ENTRY *ntfs_read_sii(struct SECURITY_API *scapi,
INDEX_ENTRY *entry);
INDEX_ENTRY *ntfs_read_sdh(struct SECURITY_API *scapi,
INDEX_ENTRY *entry);
struct SECURITY_API *ntfs_initialize_file_security(const char *device,
int flags);
BOOL ntfs_leave_file_security(struct SECURITY_API *scx);
int ntfs_get_usid( struct SECURITY_API *scapi, uid_t uid, char *buf );
int ntfs_get_gsid( struct SECURITY_API *scapi, gid_t gid, char *buf );
int ntfs_get_user( struct SECURITY_API *scapi, const SID *usid );
int ntfs_get_group( struct SECURITY_API *scapi, const SID *gsid );
int ntfs_get_usid(struct SECURITY_API *scapi, uid_t uid, char *buf);
int ntfs_get_gsid(struct SECURITY_API *scapi, gid_t gid, char *buf);
int ntfs_get_user(struct SECURITY_API *scapi, const SID *usid);
int ntfs_get_group(struct SECURITY_API *scapi, const SID *gsid);
#endif /* defined _NTFS_SECURITY_H */

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -26,53 +26,53 @@
#include "types.h"
#include "layout.h"
extern BOOL ntfs_names_are_equal( const ntfschar *s1, size_t s1_len,
extern BOOL ntfs_names_are_equal(const ntfschar *s1, size_t s1_len,
const ntfschar *s2, size_t s2_len, const IGNORE_CASE_BOOL ic,
const ntfschar *upcase, const u32 upcase_size );
const ntfschar *upcase, const u32 upcase_size);
extern int ntfs_names_full_collate( const ntfschar *name1, const u32 name1_len,
extern int ntfs_names_full_collate(const ntfschar *name1, const u32 name1_len,
const ntfschar *name2, const u32 name2_len,
const IGNORE_CASE_BOOL ic,
const ntfschar *upcase, const u32 upcase_len );
const ntfschar *upcase, const u32 upcase_len);
extern int ntfs_ucsncmp( const ntfschar *s1, const ntfschar *s2, size_t n );
extern int ntfs_ucsncmp(const ntfschar *s1, const ntfschar *s2, size_t n);
extern int ntfs_ucsncasecmp( const ntfschar *s1, const ntfschar *s2, size_t n,
const ntfschar *upcase, const u32 upcase_size );
extern int ntfs_ucsncasecmp(const ntfschar *s1, const ntfschar *s2, size_t n,
const ntfschar *upcase, const u32 upcase_size);
extern u32 ntfs_ucsnlen( const ntfschar *s, u32 maxlen );
extern u32 ntfs_ucsnlen(const ntfschar *s, u32 maxlen);
extern ntfschar *ntfs_ucsndup( const ntfschar *s, u32 maxlen );
extern ntfschar *ntfs_ucsndup(const ntfschar *s, u32 maxlen);
extern void ntfs_name_upcase( ntfschar *name, u32 name_len,
const ntfschar *upcase, const u32 upcase_len );
extern void ntfs_name_upcase(ntfschar *name, u32 name_len,
const ntfschar *upcase, const u32 upcase_len);
extern void ntfs_name_locase( ntfschar *name, u32 name_len,
const ntfschar *locase, const u32 locase_len );
extern void ntfs_name_locase(ntfschar *name, u32 name_len,
const ntfschar *locase, const u32 locase_len);
extern void ntfs_file_value_upcase( FILE_NAME_ATTR *file_name_attr,
const ntfschar *upcase, const u32 upcase_len );
extern void ntfs_file_value_upcase(FILE_NAME_ATTR *file_name_attr,
const ntfschar *upcase, const u32 upcase_len);
extern int ntfs_ucstombs( const ntfschar *ins, const int ins_len, char **outs,
int outs_len );
extern int ntfs_mbstoucs( const char *ins, ntfschar **outs );
extern int ntfs_ucstombs(const ntfschar *ins, const int ins_len, char **outs,
int outs_len);
extern int ntfs_mbstoucs(const char *ins, ntfschar **outs);
extern char *ntfs_uppercase_mbs( const char *low,
const ntfschar *upcase, u32 upcase_len );
extern char *ntfs_uppercase_mbs(const char *low,
const ntfschar *upcase, u32 upcase_len);
extern void ntfs_upcase_table_build( ntfschar *uc, u32 uc_len );
extern ntfschar *ntfs_locase_table_build( const ntfschar *uc, u32 uc_cnt );
extern void ntfs_upcase_table_build(ntfschar *uc, u32 uc_len);
extern ntfschar *ntfs_locase_table_build(const ntfschar *uc, u32 uc_cnt);
extern ntfschar *ntfs_str2ucs( const char *s, int *len );
extern ntfschar *ntfs_str2ucs(const char *s, int *len);
extern void ntfs_ucsfree( ntfschar *ucs );
extern void ntfs_ucsfree(ntfschar *ucs);
extern BOOL ntfs_forbidden_chars( const ntfschar *name, int len );
extern BOOL ntfs_collapsible_chars( ntfs_volume *vol,
extern BOOL ntfs_forbidden_chars(const ntfschar *name, int len);
extern BOOL ntfs_collapsible_chars(ntfs_volume *vol,
const ntfschar *shortname, int shortlen,
const ntfschar *longname, int longlen );
const ntfschar *longname, int longlen);
extern int ntfs_set_char_encoding( const char *locale );
extern int ntfs_set_char_encoding(const char *locale);
#if defined(__APPLE__) || defined(__DARWIN__)
/**
@ -92,7 +92,7 @@ extern int ntfs_set_char_encoding( const char *locale );
* 1 means it is enabled.
* @return -1 if the argument was invalid or an error occurred, 0 if all went well.
*/
extern int ntfs_macosx_normalize_filenames( int normalize );
extern int ntfs_macosx_normalize_filenames(int normalize);
/**
* Mac OS X only.
@ -111,7 +111,7 @@ extern int ntfs_macosx_normalize_filenames( int normalize );
* @return -1 if the normalization failed for some reason, otherwise the length of the
* normalized string stored in target.
*/
extern int ntfs_macosx_normalize_utf8( const char *utf8_string, char **target, int composed );
extern int ntfs_macosx_normalize_utf8(const char *utf8_string, char **target, int composed);
#endif /* defined(__APPLE__) || defined(__DARWIN__) */
#endif /* defined _NTFS_UNISTR_H */

File diff suppressed because it is too large Load Diff

View File

@ -74,17 +74,15 @@ typedef struct _ntfs_volume ntfs_volume;
*
* Flags returned by the ntfs_check_if_mounted() function.
*/
typedef enum
{
typedef enum {
NTFS_MF_MOUNTED = 1, /* Device is mounted. */
NTFS_MF_ISROOT = 2, /* Device is mounted as system root. */
NTFS_MF_READONLY = 4, /* Device is mounted read-only. */
} ntfs_mount_flags;
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_SYNTAX_ERROR = 11,
NTFS_VOLUME_NOT_NTFS = 12,
@ -105,8 +103,7 @@ typedef enum
*
* Defined bits for the state field in the ntfs_volume structure.
*/
typedef enum
{
typedef enum {
NV_ReadOnly, /* 1: Volume is read-only. */
NV_CaseSensitive, /* 1: Volume is mounted case-sensitive. */
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
{
union
{
struct _ntfs_volume {
union {
struct ntfs_device *dev; /* NTFS device associated with
the volume. */
void *sb; /* For kernel porting compatibility. */
@ -277,32 +272,32 @@ struct _ntfs_volume
extern const char *ntfs_home;
extern ntfs_volume *ntfs_volume_alloc( void );
extern ntfs_volume *ntfs_volume_alloc(void);
extern ntfs_volume *ntfs_volume_startup( struct ntfs_device *dev,
unsigned long flags );
extern ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
unsigned long flags);
extern ntfs_volume *ntfs_device_mount( struct ntfs_device *dev,
unsigned long flags );
extern ntfs_volume *ntfs_device_mount(struct ntfs_device *dev,
unsigned long flags);
extern ntfs_volume *ntfs_mount( const char *name, unsigned long flags );
extern int ntfs_umount( ntfs_volume *vol, const BOOL force );
extern ntfs_volume *ntfs_mount(const char *name, unsigned long flags);
extern int ntfs_umount(ntfs_volume *vol, const BOOL force);
extern int ntfs_version_is_supported( ntfs_volume *vol );
extern int ntfs_volume_check_hiberfile( ntfs_volume *vol, int verbose );
extern int ntfs_logfile_reset( ntfs_volume *vol );
extern int ntfs_version_is_supported(ntfs_volume *vol);
extern int ntfs_volume_check_hiberfile(ntfs_volume *vol, int verbose);
extern int ntfs_logfile_reset(ntfs_volume *vol);
extern int ntfs_volume_write_flags( ntfs_volume *vol, const le16 flags );
extern int ntfs_volume_write_flags(ntfs_volume *vol, const le16 flags);
extern int ntfs_volume_error( int err );
extern void ntfs_mount_error( const char *vol, const char *mntpoint, int err );
extern int ntfs_volume_error(int err);
extern void ntfs_mount_error(const char *vol, const char *mntpoint, int err);
extern int ntfs_volume_get_free_space( ntfs_volume *vol );
extern int ntfs_volume_get_free_space(ntfs_volume *vol);
extern int ntfs_set_shown_files( ntfs_volume *vol,
BOOL show_sys_files, BOOL show_hid_files, BOOL hide_dot_files );
extern int ntfs_set_locale( void );
extern int ntfs_set_ignore_case( ntfs_volume *vol );
extern int ntfs_set_shown_files(ntfs_volume *vol,
BOOL show_sys_files, BOOL show_hid_files, BOOL hide_dot_files);
extern int ntfs_set_locale(void);
extern int ntfs_set_ignore_case(ntfs_volume *vol);
#endif /* defined _NTFS_VOLUME_H */

View File

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

View File

@ -96,10 +96,13 @@ int GameList::ReadGameList()
return LoadUnfiltered();
}
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( char1 == 0 )return false;
if(char2 == 0)
return true;
if(char1 == 0)
return false;
return char2 > char1;
}
@ -243,41 +246,41 @@ void GameList::SortList()
}
bool GameList::NameSortCallback( const struct discHdr *a, const struct discHdr *b )
bool GameList::NameSortCallback(const struct discHdr *a, const struct discHdr *b)
{
return ( strcasecmp( get_title( ( struct discHdr * ) a ), get_title( ( struct discHdr * ) b ) ) < 0 );
return (strcasecmp(get_title((struct discHdr *) a), get_title((struct discHdr *) b)) < 0);
}
bool GameList::PlaycountSortCallback( const struct discHdr *a, const struct discHdr *b )
bool GameList::PlaycountSortCallback(const struct discHdr *a, const struct discHdr *b)
{
struct Game_NUM* game_num1 = CFG_get_game_num( a->id );
struct Game_NUM* game_num2 = CFG_get_game_num( b->id );
int count1 = 0, count2 = 0;
if ( game_num1 )
if (game_num1)
count1 = game_num1->count;
if ( game_num2 )
if (game_num2)
count2 = game_num2->count;
if ( count1 == count2 )
return NameSortCallback( a, b );
if (count1 == count2)
return NameSortCallback(a, b);
return ( count1 > count2 );
return (count1 > count2);
}
bool GameList::FavoriteSortCallback( const struct discHdr *a, const struct discHdr *b )
bool GameList::FavoriteSortCallback(const struct discHdr *a, const struct discHdr *b)
{
struct Game_NUM* game_num1 = CFG_get_game_num( a->id );
struct Game_NUM* game_num2 = CFG_get_game_num( b->id );
int fav1 = 0, fav2 = 0;
if ( game_num1 )
if (game_num1)
fav1 = game_num1->favorite;
if ( game_num2 )
if (game_num2)
fav2 = game_num2->favorite;
if ( fav1 == fav2 );
return NameSortCallback( a, b );
if (fav1 == fav2)
return NameSortCallback(a, b);
return ( fav1 > fav2 );
return (fav1 > fav2);
}