From 1984a714e57a5c0a0016d526ed4b34774a375d90 Mon Sep 17 00:00:00 2001 From: Erik Larsson Date: Thu, 28 Jan 2016 08:29:03 +0100 Subject: [PATCH] Enable strict checking of endian-specific types. Strict checking of endian-specific types mean that types that have a fixed endianness in the data representation of the value are now defined as complex types, enabling the compiler to catch mixed usage of these types with native-endian types. This allows us to catch most issues relating to usage on big-endian systems since we cannot anymore assign a fixed-endian value to a native-endian variable and vice-versa without a compiler error. The downside is that we aren't able to apply simple binary operators to the fixed-endian types anymore since they are complex... so all combining fixed-endian constants and values with |, &, etc. and comparison with ==, !=, <=, etc. must be replaced with a macro which unpacks the wrapped value and performs the operation. Lots of changes, lots of work but in the interest of good code quality it's justified. --- include/ntfs-3g/endians.h | 273 ++++++++++++++++++++++++++++++++++++++ include/ntfs-3g/layout.h | 164 ++++++++++++++++++++++- include/ntfs-3g/logfile.h | 18 +++ include/ntfs-3g/types.h | 70 ++++++++++ ntfsprogs/ntfsdecrypt.c | 10 ++ 5 files changed, 533 insertions(+), 2 deletions(-) diff --git a/include/ntfs-3g/endians.h b/include/ntfs-3g/endians.h index 91632f33..a15eaf34 100644 --- a/include/ntfs-3g/endians.h +++ b/include/ntfs-3g/endians.h @@ -52,6 +52,8 @@ #include #endif +#include "types.h" + #ifndef __BYTE_ORDER # if defined(_BYTE_ORDER) # define __BYTE_ORDER _BYTE_ORDER @@ -182,6 +184,8 @@ #endif +#if !ENABLE_STRICT_ENDIANNESS_CHECKING + /* Unsigned from LE to CPU conversion. */ #define le16_to_cpu(x) (u16)__le16_to_cpu((u16)(x)) @@ -348,4 +352,273 @@ #define le64_not(a) (~(a)) +#else + +/* Unsigned from LE to CPU conversion. */ + +static inline u16 le16_to_cpu(le16 x) { return (u16) __le16_to_cpu(x.value); } +static inline u32 le32_to_cpu(le32 x) { return (u32) __le32_to_cpu(x.value); } +static inline u64 le64_to_cpu(le64 x) { return (u64) __le64_to_cpu(x.value); } + +static inline u16 le16_to_cpup(const le16 *x) { + return (u16) __le16_to_cpu(x->value); +} +static inline u32 le32_to_cpup(const le32 *x) { + return (u32) __le32_to_cpu(x->value); +} +static inline u64 le64_to_cpup(const le64 *x) { + return (u64) __le64_to_cpu(x->value); +} + +/* Signed from LE to CPU conversion. */ + +static inline s16 sle16_to_cpu(sle16 x) { return (s16) __le16_to_cpu(x.value); } +static inline s32 sle32_to_cpu(sle32 x) { return (s32) __le32_to_cpu(x.value); } +static inline s64 sle64_to_cpu(sle64 x) { return (s64) __le64_to_cpu(x.value); } + +static inline s16 sle16_to_cpup(const sle16 *x) { + return (s16) __le16_to_cpu(x->value); +} +static inline s32 sle32_to_cpup(const sle32 *x) { + return (s32) __le32_to_cpu(x->value); +} +static inline s64 sle64_to_cpup(const sle64 *x) { + return (s64) __le64_to_cpu(x->value); +} + +/* Unsigned from CPU to LE conversion. */ + +static inline le16 cpu_to_le16(u16 x) { + le16 leval; leval.value = __cpu_to_le16(x); return leval; +} +static inline le32 cpu_to_le32(u32 x) { + le32 leval; leval.value = __cpu_to_le32(x); return leval; +} +static inline le64 cpu_to_le64(u64 x) { + le64 leval; leval.value = __cpu_to_le64(x); return leval; +} + +static inline le16 cpu_to_le16p(const u16 *x) { + le16 leval; leval.value = __cpu_to_le16(*x); return leval; +} +static inline le32 cpu_to_le32p(const u32 *x) { + le32 leval; leval.value = __cpu_to_le32(*x); return leval; +} +static inline le64 cpu_to_le64p(const u64 *x) { + le64 leval; leval.value = __cpu_to_le64(*x); return leval; +} + +/* Signed from CPU to LE conversion. */ + +static inline sle16 cpu_to_sle16(s16 x) { + sle16 leval; leval.value = __cpu_to_le16(x); return leval; +} +static inline sle32 cpu_to_sle32(s32 x) { + sle32 leval; leval.value = __cpu_to_le32(x); return leval; +} +static inline sle64 cpu_to_sle64(s64 x) { + sle64 leval; leval.value = __cpu_to_le64(x); return leval; +} + +static inline sle16 cpu_to_sle16p(const s16 *x) { + sle16 leval; leval.value = __cpu_to_le16(*x); return leval; +} +static inline sle32 cpu_to_sle32p(const s32 *x) { + sle32 leval; leval.value = __cpu_to_le32(*x); return leval; +} +static inline sle64 cpu_to_sle64p(const s64 *x) { + sle64 leval; leval.value = __cpu_to_le64(*x); return leval; +} + +/* Unsigned from BE to CPU conversion. */ + +static inline u16 be16_to_cpu(be16 x) { return (u16) __be16_to_cpu(x.value); } +static inline u32 be32_to_cpu(be32 x) { return (u32) __be32_to_cpu(x.value); } +static inline u64 be64_to_cpu(be64 x) { return (u64) __be64_to_cpu(x.value); } + +static inline u16 be16_to_cpup(const be16 *x) { + return (u16) __be16_to_cpu(x->value); +} +static inline u32 be32_to_cpup(const be32 *x) { + return (u32) __be32_to_cpu(x->value); +} +static inline u64 be64_to_cpup(const be64 *x) { + return (u64) __be64_to_cpu(x->value); +} + +/* Signed from BE to CPU conversion. */ + +static inline s16 sbe16_to_cpu(sbe16 x) { return (s16) __be16_to_cpu(x.value); } +static inline s32 sbe32_to_cpu(sbe32 x) { return (s32) __be32_to_cpu(x.value); } +static inline s64 sbe64_to_cpu(sbe64 x) { return (s64) __be64_to_cpu(x.value); } + +static inline s16 sbe16_to_cpup(const sbe16 *x) { + return (s16) __be16_to_cpu(x->value); +} +static inline s32 sbe32_to_cpup(const sbe32 *x) { + return (s32) __be32_to_cpu(x->value); +} +static inline s64 sbe64_to_cpup(const sbe64 *x) { + return (s64) __be64_to_cpu(x->value); +} + +/* Unsigned from CPU to BE conversion. */ + +static inline be16 cpu_to_be16(u16 x) { + be16 beval; beval.value = __cpu_to_be16(x); return beval; +} +static inline be32 cpu_to_be32(u32 x) { + be32 beval; beval.value = __cpu_to_be32(x); return beval; +} +static inline be64 cpu_to_be64(u64 x) { + be64 beval; beval.value = __cpu_to_be64(x); return beval; +} + +static inline be16 cpu_to_be16p(const u16 *x) { + be16 beval; beval.value = __cpu_to_be16(*x); return beval; +} +static inline be32 cpu_to_be32p(const u32 *x) { + be32 beval; beval.value = __cpu_to_be32(*x); return beval; +} +static inline be64 cpu_to_be64p(const u64 *x) { + be64 beval; beval.value = __cpu_to_be64(*x); return beval; +} + +/* Signed from CPU to BE conversion. */ + +static inline sbe16 cpu_to_sbe16(s16 x) { + sbe16 beval; beval.value = __cpu_to_be16(x); return beval; +} +static inline sbe32 cpu_to_sbe32(s32 x) { + sbe32 beval; beval.value = __cpu_to_be32(x); return beval; +} +static inline sbe64 cpu_to_sbe64(s64 x) { + sbe64 beval; beval.value = __cpu_to_be64(x); return beval; +} + +static inline sbe16 cpu_to_sbe16p(const s16 *x) { + sbe16 beval; beval.value = __cpu_to_be16(*x); return beval; +} +static inline sbe32 cpu_to_sbe32p(const s32 *x) { + sbe32 beval; beval.value = __cpu_to_be32(*x); return beval; +} +static inline sbe64 cpu_to_sbe64p(const s64 *x) { + sbe64 beval; beval.value = __cpu_to_be64(*x); return beval; +} + +/* Constant endianness conversion defines. */ + +#define const_le16_to_cpu(x) __constant_le16_to_cpu((u16)(x.value)) +#define const_le32_to_cpu(x) __constant_le32_to_cpu((u32)(x.value)) +#define const_le64_to_cpu(x) __constant_le64_to_cpu((u64)(x.value)) + +#define const_cpu_to_le16(x) ((le16)(u16) __constant_cpu_to_le16((u16)(x))) +#define const_cpu_to_le32(x) ((le32) __constant_cpu_to_le32((u32)(x))) +#define const_cpu_to_le64(x) ((le64) __constant_cpu_to_le64((u64)(x))) + +#define const_sle16_to_cpu(x) __constant_le16_to_cpu((u16)(x.value)) +#define const_sle32_to_cpu(x) __constant_le32_to_cpu((u32)(x.value)) +#define const_sle64_to_cpu(x) __constant_le64_to_cpu((u64)(x.value)) + +#define const_cpu_to_sle16(x) ((sle16)(u16) __constant_cpu_to_le16((u16)(x))) +#define const_cpu_to_sle32(x) ((sle32) __constant_cpu_to_le32((u32)(x))) +#define const_cpu_to_sle64(x) ((sle64) __constant_cpu_to_le64((u64)(x))) + +#define const_be16_to_cpu(x) __constant_be16_to_cpu((u16)(x.value)) +#define const_be32_to_cpu(x) __constant_be32_to_cpu((u32)(x.value)) +#define const_be64_to_cpu(x) __constant_be64_to_cpu((u64)(x.value)) + +#define const_cpu_to_be16(x) ((be16)(u16) __constant_cpu_to_be16((u16)(x))) +#define const_cpu_to_be32(x) ((be32) __constant_cpu_to_be32((u32)(x))) +#define const_cpu_to_be64(x) ((be64) __constant_cpu_to_be64((u64)(x))) + +#define const_sbe16_to_cpu(x) __constant_be16_to_cpu((u16)(x.value)) +#define const_sbe32_to_cpu(x) __constant_be32_to_cpu((u32)(x.value)) +#define const_sbe64_to_cpu(x) __constant_be64_to_cpu((u64)(x.value)) + +#define const_cpu_to_sbe16(x) ((sbe16)(u16) __constant_cpu_to_be16((u16)(x))) +#define const_cpu_to_sbe32(x) ((sbe32) __constant_cpu_to_be32((u32)(x))) +#define const_cpu_to_sbe64(x) ((sbe64) __constant_cpu_to_be64((u64)(x))) + +static inline int le16_eq(le16 a, le16 b) { return (a.value == b.value); } + +static inline int le32_eq(le32 a, le32 b) { return (a.value == b.value); } + +static inline int le64_eq(le64 a, le64 b) { return (a.value == b.value); } + +static inline int sle16_eq(sle16 a, sle16 b) { return (a.value == b.value); } + +static inline int sle64_eq(sle64 a, sle64 b) { return (a.value == b.value); } + +static inline int be16_eq(be16 a, be16 b) { return (a.value == b.value); } + +static inline int be32_eq(be32 a, be32 b) { return (a.value == b.value); } + +static inline int le16_cmpz(le16 a) { return !a.value; } + +static inline int le32_cmpz(le32 a) { return !a.value; } + +static inline int le64_cmpz(le64 a) { return !a.value; } + +static inline int sle64_cmpz(sle64 a) { return !a.value; } + +static inline int be16_cmpz(be16 a) { return !a.value; } + +static inline int le16_andz(le16 a, le16 b) { return !(a.value & b.value); } + +static inline int le32_andz(le32 a, le32 b) { return !(a.value & b.value); } + +static inline le16 le16_and(le16 a, le16 b) +{ + return (le16) ((u16) (a.value & b.value)); +} + +static inline le32 le32_and(le32 a, le32 b) +{ + return (le32) (a.value & b.value); +} + +static inline le64 le64_and(le64 a, le64 b) +{ + return (le64) (a.value & b.value); +} + +static inline le16 le16_or(le16 a, le16 b) +{ + return (le16) ((u16) (a.value | b.value)); +} + +static inline le32 le32_or(le32 a, le32 b) +{ + return (le32) (a.value | b.value); +} + +static inline le64 le64_or(le64 a, le64 b) +{ + return (le64) (a.value | b.value); +} + +static inline le16 le16_xor(le16 a, le16 b) +{ + return (le16) ((u16) (a.value ^ b.value)); +} + +static inline le32 le32_xor(le32 a, le32 b) +{ + return (le32) (a.value ^ b.value); +} + +static inline le64 le64_xor(le64 a, le64 b) +{ + return (le64) (a.value ^ b.value); +} + +static inline le16 le16_not(le16 a) { return (le16) ((u16) (~a.value)); } + +static inline le32 le32_not(le32 a) { return (le32) (~a.value); } + +static inline le64 le64_not(le64 a) { return (le64) (~a.value); } + +#endif /* !ENABLE_STRICT_ENDIANNESS_CHECKING ... */ + #endif /* defined _NTFS_ENDIANS_H */ diff --git a/include/ntfs-3g/layout.h b/include/ntfs-3g/layout.h index 9bee6e75..a96f9a1a 100644 --- a/include/ntfs-3g/layout.h +++ b/include/ntfs-3g/layout.h @@ -100,7 +100,13 @@ typedef struct { * Magic identifiers present at the beginning of all ntfs record containing * records (like mft records for example). */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le32 NTFS_RECORD_TYPES; + +static const le32 +#else typedef enum { +#endif /* Found in $MFT/$DATA. */ magic_FILE = const_cpu_to_le32(0x454c4946), /* Mft entry. */ magic_INDX = const_cpu_to_le32(0x58444e49), /* Index buffer. */ @@ -125,14 +131,18 @@ typedef enum { magic_empty = const_cpu_to_le32(0xffffffff),/* Record is empty and has to be initialized before it can be used. */ +#if !ENABLE_STRICT_ENDIANNESS_CHECKING } NTFS_RECORD_TYPES; +#else + __NTFS_RECORD_TYPES_end; +#endif /* * Generic magic comparison macros. Finally found a use for the ## preprocessor * operator! (-8 */ -#define ntfs_is_magic(x, m) ( (u32)(x) == (u32)magic_##m ) -#define ntfs_is_magicp(p, m) ( *(u32*)(p) == (u32)magic_##m ) +#define ntfs_is_magic(x, m) ( le32_eq(x, magic_##m) ) +#define ntfs_is_magicp(p, m) ( le32_eq(*p, magic_##m) ) /* * Specialised magic comparison macros for the NTFS_RECORD_TYPES defined above. @@ -254,14 +264,24 @@ typedef enum { * index, that means an INDEX_ROOT and an INDEX_ALLOCATION with a name other * than "$I30". It is unknown if it is limited to metadata files only. */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le16 MFT_RECORD_FLAGS; + +static const MFT_RECORD_FLAGS +#else typedef enum { +#endif MFT_RECORD_IN_USE = const_cpu_to_le16(0x0001), MFT_RECORD_IS_DIRECTORY = const_cpu_to_le16(0x0002), MFT_RECORD_IS_4 = const_cpu_to_le16(0x0004), MFT_RECORD_IS_VIEW_INDEX = const_cpu_to_le16(0x0008), +#if !ENABLE_STRICT_ENDIANNESS_CHECKING MFT_REC_SPACE_FILLER = 0xffff, /* Just to make flags 16-bit. */ } __attribute__((__packed__)) MFT_RECORD_FLAGS; +#else + __MFT_RECORD_FLAGS_end; +#endif /* * mft references (aka file references or file record segment references) are @@ -489,7 +509,13 @@ typedef struct { * enum exchanging AT_ for the dollar sign ($). If that isn't a revealing * choice of symbol... (-; */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le32 ATTR_TYPES; + +static const ATTR_TYPES +#else typedef enum { +#endif AT_UNUSED = const_cpu_to_le32( 0), AT_STANDARD_INFORMATION = const_cpu_to_le32( 0x10), AT_ATTRIBUTE_LIST = const_cpu_to_le32( 0x20), @@ -509,7 +535,11 @@ typedef enum { AT_LOGGED_UTILITY_STREAM = const_cpu_to_le32( 0x100), AT_FIRST_USER_DEFINED_ATTRIBUTE = const_cpu_to_le32( 0x1000), AT_END = const_cpu_to_le32(0xffffffff), +#if !ENABLE_STRICT_ENDIANNESS_CHECKING } ATTR_TYPES; +#else + __ATTR_TYPES_end; +#endif /** * enum COLLATION_RULES - The collation rules for sorting views/indexes/etc @@ -548,7 +578,13 @@ typedef enum { * the 2nd object_id. If the first le32 values of both object_ids were * equal then the second le32 values would be compared, etc. */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le32 COLLATION_RULES; + +static const COLLATION_RULES +#else typedef enum { +#endif COLLATION_BINARY = const_cpu_to_le32(0), /* Collate by binary compare where the first byte is most significant. */ @@ -564,7 +600,11 @@ typedef enum { COLLATION_NTOFS_SID = const_cpu_to_le32(17), COLLATION_NTOFS_SECURITY_HASH = const_cpu_to_le32(18), COLLATION_NTOFS_ULONGS = const_cpu_to_le32(19), +#if !ENABLE_STRICT_ENDIANNESS_CHECKING } COLLATION_RULES; +#else + __COLLATION_RULES_end; +#endif /** * enum ATTR_DEF_FLAGS - @@ -576,7 +616,13 @@ typedef enum { * name attribute has this flag set and this is the only attribute indexed in * NT4. */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le32 ATTR_DEF_FLAGS; + +static const ATTR_DEF_FLAGS +#else typedef enum { +#endif ATTR_DEF_INDEXABLE = const_cpu_to_le32(0x02), /* Attribute can be indexed. */ ATTR_DEF_MULTIPLE = const_cpu_to_le32(0x04), /* Attribute type @@ -601,7 +647,11 @@ typedef enum { non-resident. Without this, only log modifications if the attribute is resident. */ +#if !ENABLE_STRICT_ENDIANNESS_CHECKING } ATTR_DEF_FLAGS; +#else + __ATTR_DEF_FLAGS_end; +#endif /** * struct ATTR_DEF - @@ -631,14 +681,24 @@ typedef struct { /** * enum ATTR_FLAGS - Attribute flags (16-bit). */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le16 ATTR_FLAGS; + +static const ATTR_FLAGS +#else typedef enum { +#endif ATTR_IS_COMPRESSED = const_cpu_to_le16(0x0001), ATTR_COMPRESSION_MASK = const_cpu_to_le16(0x00ff), /* Compression method mask. Also, first illegal value. */ ATTR_IS_ENCRYPTED = const_cpu_to_le16(0x4000), ATTR_IS_SPARSE = const_cpu_to_le16(0x8000), +#if !ENABLE_STRICT_ENDIANNESS_CHECKING } __attribute__((__packed__)) ATTR_FLAGS; +#else + __ATTR_FLAGS_end; +#endif /* * Attribute compression. @@ -828,7 +888,13 @@ typedef ATTR_RECORD ATTR_REC; /** * enum FILE_ATTR_FLAGS - File attribute flags (32-bit). */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le32 FILE_ATTR_FLAGS; + +static const FILE_ATTR_FLAGS +#else typedef enum { +#endif /* * These flags are only present in the STANDARD_INFORMATION attribute * (in the field file_attributes). @@ -889,7 +955,11 @@ typedef enum { * $FILE_NAME attributes. */ FILE_ATTR_VIEW_INDEX_PRESENT = const_cpu_to_le32(0x20000000), +#if !ENABLE_STRICT_ENDIANNESS_CHECKING } __attribute__((__packed__)) FILE_ATTR_FLAGS; +#else + __FILE_ATTR_FLAGS_end; +#endif /* * NOTE on times in NTFS: All times are in MS standard time format, i.e. they @@ -1481,7 +1551,13 @@ typedef struct { * * Defines the access rights. */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le32 ACCESS_MASK; + +static const ACCESS_MASK +#else typedef enum { +#endif /* * The specific rights (bits 0 to 15). Depend on the type of the * object being secured by the ACE. @@ -1609,7 +1685,11 @@ typedef enum { * above for the descriptions of the rights granted. */ GENERIC_READ = const_cpu_to_le32(0x80000000), +#if !ENABLE_STRICT_ENDIANNESS_CHECKING } ACCESS_MASK; +#else + __ACCESS_MASK_end; +#endif /** * struct GENERIC_MAPPING - @@ -1649,10 +1729,20 @@ typedef struct { /** * enum OBJECT_ACE_FLAGS - The object ACE flags (32-bit). */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le32 OBJECT_ACE_FLAGS; + +static const OBJECT_ACE_FLAGS +#else typedef enum { +#endif ACE_OBJECT_TYPE_PRESENT = const_cpu_to_le32(1), ACE_INHERITED_OBJECT_TYPE_PRESENT = const_cpu_to_le32(2), +#if !ENABLE_STRICT_ENDIANNESS_CHECKING } OBJECT_ACE_FLAGS; +#else + __OBJECT_ACE_FLAGS_end; +#endif /** * struct ACCESS_ALLOWED_OBJECT_ACE - @@ -1757,7 +1847,13 @@ typedef enum { * and all pointer fields are expressed as offsets from the * beginning of the security descriptor. */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le16 SECURITY_DESCRIPTOR_CONTROL; + +static const SECURITY_DESCRIPTOR_CONTROL +#else typedef enum { +#endif SE_OWNER_DEFAULTED = const_cpu_to_le16(0x0001), SE_GROUP_DEFAULTED = const_cpu_to_le16(0x0002), SE_DACL_PRESENT = const_cpu_to_le16(0x0004), @@ -1772,7 +1868,11 @@ typedef enum { SE_SACL_PROTECTED = const_cpu_to_le16(0x2000), SE_RM_CONTROL_VALID = const_cpu_to_le16(0x4000), SE_SELF_RELATIVE = const_cpu_to_le16(0x8000), +#if !ENABLE_STRICT_ENDIANNESS_CHECKING } __attribute__((__packed__)) SECURITY_DESCRIPTOR_CONTROL; +#else + __SECURITY_DESCRIPTOR_CONTROL_end; +#endif /** * struct SECURITY_DESCRIPTOR_RELATIVE - @@ -1986,7 +2086,13 @@ typedef struct { /** * enum VOLUME_FLAGS - Possible flags for the volume (16-bit). */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le16 VOLUME_FLAGS; + +static const VOLUME_FLAGS +#else typedef enum { +#endif VOLUME_IS_DIRTY = const_cpu_to_le16(0x0001), VOLUME_RESIZE_LOG_FILE = const_cpu_to_le16(0x0002), VOLUME_UPGRADE_ON_MOUNT = const_cpu_to_le16(0x0004), @@ -1996,7 +2102,11 @@ typedef enum { VOLUME_CHKDSK_UNDERWAY = const_cpu_to_le16(0x4000), VOLUME_MODIFIED_BY_CHKDSK = const_cpu_to_le16(0x8000), VOLUME_FLAGS_MASK = const_cpu_to_le16(0xc03f), +#if !ENABLE_STRICT_ENDIANNESS_CHECKING } __attribute__((__packed__)) VOLUME_FLAGS; +#else + __VOLUME_FLAGS_end; +#endif /** * struct VOLUME_INFORMATION - Attribute: Volume information (0x70). @@ -2170,7 +2280,13 @@ typedef struct { /** * enum QUOTA_FLAGS - Quota flags (32-bit). */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le32 QUOTA_FLAGS; + +static const QUOTA_FLAGS +#else typedef enum { +#endif /* The user quota flags. Names explain meaning. */ QUOTA_FLAG_DEFAULT_LIMITS = const_cpu_to_le32(0x00000001), QUOTA_FLAG_LIMIT_REACHED = const_cpu_to_le32(0x00000002), @@ -2189,7 +2305,11 @@ typedef enum { QUOTA_FLAG_OUT_OF_DATE = const_cpu_to_le32(0x00000200), QUOTA_FLAG_CORRUPT = const_cpu_to_le32(0x00000400), QUOTA_FLAG_PENDING_DELETES = const_cpu_to_le32(0x00000800), +#if !ENABLE_STRICT_ENDIANNESS_CHECKING } QUOTA_FLAGS; +#else + __QUOTA_FLAGS_end; +#endif /** * struct QUOTA_CONTROL_ENTRY - @@ -2246,16 +2366,32 @@ typedef struct { /** * enum PREDEFINED_OWNER_IDS - Predefined owner_id values (32-bit). */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le32 PREDEFINED_OWNER_IDS; + +static const PREDEFINED_OWNER_IDS +#else typedef enum { +#endif QUOTA_INVALID_ID = const_cpu_to_le32(0x00000000), QUOTA_DEFAULTS_ID = const_cpu_to_le32(0x00000001), QUOTA_FIRST_USER_ID = const_cpu_to_le32(0x00000100), +#if !ENABLE_STRICT_ENDIANNESS_CHECKING } PREDEFINED_OWNER_IDS; +#else + __PREDEFINED_OWNER_IDS_end; +#endif /** * enum INDEX_ENTRY_FLAGS - Index entry flags (16-bit). */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le16 INDEX_ENTRY_FLAGS; + +static const INDEX_ENTRY_FLAGS +#else typedef enum { +#endif INDEX_ENTRY_NODE = const_cpu_to_le16(1), /* This entry contains a sub-node, i.e. a reference to an index block in form of a virtual cluster @@ -2264,8 +2400,12 @@ typedef enum { entry in an index block. The index entry does not represent a file but it can point to a sub-node. */ +#if !ENABLE_STRICT_ENDIANNESS_CHECKING INDEX_ENTRY_SPACE_FILLER = 0xffff, /* Just to force 16-bit width. */ } __attribute__((__packed__)) INDEX_ENTRY_FLAGS; +#else + __INDEX_ENTRY_FLAGS_end; +#endif /** * struct INDEX_ENTRY_HEADER - This the index entry header (see below). @@ -2391,7 +2531,13 @@ typedef struct { * bit 31: Microsoft bit. If set, the tag is owned by Microsoft. User * defined tags have to use zero here. */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le32 PREDEFINED_REPARSE_TAGS; + +static const PREDEFINED_REPARSE_TAGS +#else typedef enum { +#endif IO_REPARSE_TAG_IS_ALIAS = const_cpu_to_le32(0x20000000), IO_REPARSE_TAG_IS_HIGH_LATENCY = const_cpu_to_le32(0x40000000), IO_REPARSE_TAG_IS_MICROSOFT = const_cpu_to_le32(0x80000000), @@ -2413,7 +2559,11 @@ typedef enum { IO_REPARSE_TAG_WIM = const_cpu_to_le32(0x80000008), IO_REPARSE_TAG_VALID_VALUES = const_cpu_to_le32(0xf000ffff), +#if !ENABLE_STRICT_ENDIANNESS_CHECKING } PREDEFINED_REPARSE_TAGS; +#else + __PREDEFINED_REPARSE_TAGS_end; +#endif /** * struct REPARSE_POINT - Attribute: Reparse point (0xc0). @@ -2639,14 +2789,24 @@ typedef struct { typedef EFS_DF_CERTIFICATE_THUMBPRINT_HEADER EFS_DF_CERT_THUMBPRINT_HEADER; +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le64 INTX_FILE_TYPES; + +static const INTX_FILE_TYPES +#else typedef enum { +#endif INTX_SYMBOLIC_LINK = const_cpu_to_le64(0x014B4E4C78746E49ULL), /* "IntxLNK\1" */ INTX_CHARACTER_DEVICE = const_cpu_to_le64(0x0052484378746E49ULL), /* "IntxCHR\0" */ INTX_BLOCK_DEVICE = const_cpu_to_le64(0x004B4C4278746E49ULL), /* "IntxBLK\0" */ +#if !ENABLE_STRICT_ENDIANNESS_CHECKING } INTX_FILE_TYPES; +#else + __INTX_FILE_TYPES_end; +#endif typedef struct { INTX_FILE_TYPES magic; /* Intx file magic. */ diff --git a/include/ntfs-3g/logfile.h b/include/ntfs-3g/logfile.h index 6b2305b7..ad66bd87 100644 --- a/include/ntfs-3g/logfile.h +++ b/include/ntfs-3g/logfile.h @@ -108,10 +108,18 @@ 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. */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +static const le16 +#else enum { +#endif RESTART_VOLUME_IS_CLEAN = const_cpu_to_le16(0x0002), +#if !ENABLE_STRICT_ENDIANNESS_CHECKING RESTART_SPACE_FILLER = 0xffff, /* gcc: Force enum bit width to 16. */ } __attribute__((__packed__)); +#else + __RESTART_AREA_FLAGS_end; +#endif typedef le16 RESTART_AREA_FLAGS; @@ -335,12 +343,22 @@ typedef struct { * * (Or is it log record pages?) */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le16 LOG_RECORD_FLAGS; + +static const LOG_RECORD_FLAGS +#else typedef enum { +#endif LOG_RECORD_MULTI_PAGE = const_cpu_to_le16(0x0001), /* ??? */ +#if !ENABLE_STRICT_ENDIANNESS_CHECKING 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; +#else + __LOG_RECORD_FLAGS_end; +#endif /** * struct LOG_CLIENT_ID - The log client id structure identifying a log client. diff --git a/include/ntfs-3g/types.h b/include/ntfs-3g/types.h index 43d91b20..f1c3e5fc 100644 --- a/include/ntfs-3g/types.h +++ b/include/ntfs-3g/types.h @@ -27,6 +27,10 @@ #include "config.h" #endif +#if !defined(ENABLE_STRICT_ENDIANNESS_CHECKING) +#define ENABLE_STRICT_ENDIANNESS_CHECKING 1 +#endif /* !defined(ENABLE_STRICT_ENDIANNESS_CHECKING) */ + #if HAVE_STDINT_H || !HAVE_CONFIG_H #include #endif @@ -44,6 +48,7 @@ typedef int16_t s16; typedef int32_t s32; typedef int64_t s64; +#if !ENABLE_STRICT_ENDIANNESS_CHECKING typedef u16 le16; typedef u32 le32; typedef u64 le64; @@ -63,6 +68,71 @@ typedef u64 sle64; typedef u16 sbe16; typedef u32 sbe32; typedef u64 sbe64; +#else +typedef union { + u8 data[2]; + u16 value; +} le16; + +typedef union { + u8 data[4]; + u32 value; +} le32; + +typedef union { + u8 data[8]; + u64 value; +} le64; + +typedef union { + u8 data[2]; + u16 value; +} be16; + +typedef union { + u8 data[4]; + u32 value; +} be32; + +typedef union { + u8 data[8]; + u64 value; +} be64; + +/* + * Declare s{l,b}e{16,32,64} to be unsigned because we do not want sign + * extension on BE architectures. + */ +typedef union { + u8 data[2]; + u16 value; +} sle16; + +typedef union { + u8 data[4]; + u32 value; +} sle32; + +typedef union { + u8 data[8]; + u64 value; +} sle64; + +typedef union { + u8 data[2]; + u16 value; +} sbe16; + +typedef union { + u8 data[4]; + u32 value; +} sbe32; + +typedef union { + u8 data[8]; + u64 value; +} sbe64; +#endif /* !ENABLE_STRICT_ENDIANNESS_CHECKING ... */ typedef le16 ntfschar; /* 2-byte Unicode character type. */ #define UCHAR_T_SIZE_BITS 1 diff --git a/ntfsprogs/ntfsdecrypt.c b/ntfsprogs/ntfsdecrypt.c index 23a4059c..bdb13cc5 100644 --- a/ntfsprogs/ntfsdecrypt.c +++ b/ntfsprogs/ntfsdecrypt.c @@ -96,13 +96,23 @@ typedef enum { * this registry key. It would be interesting to check out encryption on one * of the "crippled" crypto Windows versions... */ +#if ENABLE_STRICT_ENDIANNESS_CHECKING +typedef le32 NTFS_CRYPTO_ALGORITHMS; + +static const le32 +#else typedef enum { +#endif CALG_DES = const_cpu_to_le32(0x6601), /* If not one of the below three, fall back to standard Des. */ CALG_3DES = const_cpu_to_le32(0x6603), CALG_DESX = const_cpu_to_le32(0x6604), CALG_AES_256 = const_cpu_to_le32(0x6610), +#if !ENABLE_STRICT_ENDIANNESS_CHECKING } NTFS_CRYPTO_ALGORITHMS; +#else + __NTFS_CRYPTO_ALGORITHMS_end; +#endif typedef struct { u64 in_whitening, out_whitening;