Changes by: antona
Update of /cvsroot/linux-ntfs/linux-ntfs/libntfs
In directory usw-pr-cvs1:/tmp/cvs-serv28833
Modified Files:
attrib.c bootsect.c disk_io.c mft.c ntfs_rec.c volume.c
Log Message:
Corresponding changes to the library.
Index: attrib.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/attrib.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -r1.3 -r1.4
*** attrib.c 2001/03/02 15:05:53 1.3
--- attrib.c 2001/03/05 03:04:40 1.4
***************
*** 20,24 ****
*/
- #include <wchar.h>
#include <stddef.h>
#include <stdio.h>
--- 20,23 ----
***************
*** 28,38 ****
#include <stdlib.h>
- /*
- * This would be defining wchar_t in the kernel, but stdio.h defines it for
- * userspace. FIXME: I have been a bit slack and defining __u16 instead of
- * wchar_t in most places. This will need fixing at some point. (AIA)
- */
- /* #include <linux/nls.h> */
-
#include "attrib.h"
#include "mft.h"
--- 27,30 ----
***************
*** 40,43 ****
--- 32,36 ----
#include "disk_io.h"
#include "volume.h"
+ #include "ntfs_unicode.h"
/*
***************
*** 46,59 ****
#define p2n(p) ((ptrdiff_t)((ptrdiff_t*)(p)))
! ATTRIBUTE_RECORD_HEADER *find_next_attr_in_attr_list(
const ntfs_volume *v,
! const MFT_RECORD_HEADER *m,
! const ATTRIBUTE_RECORD_HEADER *al,
! const ATTRIBUTE_TYPE t,
const wchar_t *n,
FIND_ATTR_CTX_FLAGS *ctx)
{
__u64 alen;
! ATTRIBUTE_LIST_ENTRY *ale, *aend;
int got_there = 0;
--- 39,52 ----
#define p2n(p) ((ptrdiff_t)((ptrdiff_t*)(p)))
! ATTR_RECORD *find_next_attr_in_attr_list(
const ntfs_volume *v,
! const MFT_RECORD *m,
! const ATTR_RECORD *al,
! const ATTR_TYPES t,
const wchar_t *n,
FIND_ATTR_CTX_FLAGS *ctx)
{
__u64 alen;
! ATTR_LIST_ENTRY *ale, *aend;
int got_there = 0;
***************
*** 73,92 ****
alen = get_attribute_value_length(al);
if (!al->non_resident) {
! #define RA(a) ((RESIDENT_ATTRIBUTE_RECORD_HEADER*)(a))
! astart = (ATTRIBUTE_LIST_ENTRY*)((char*)al +
! le16_to_cpu(RA(al)->value_offset));
! #undef RA
} else {
! #define NA(a) ((NONRESIDENT_ATTRIBUTE_RECORD_HEADER*)(a))
! if (!(astart = (ATTRIBUTE_LIST_ENTRY*)malloc(alen)))
goto ret_now;
if (get_attribute_value(v, al, astart) != alen)
goto error_ret;
- #undef NA
}
/* Set aend to first byte after the attribute list. */
! aend = (ATTRIBUTE_LIST_ENTRY*)((char*)astart + alen);
/* Iterate over all attribute list entries looking for the right one. */
! for (ale = astart; ale < aend; ale = (ATTRIBUTE_LIST_ENTRY*)
((char*)ale + le16_to_cpu(ale->length))) {
/* If we encounter lowest_vcn != 0 then instance is 0 and we
--- 66,81 ----
alen = get_attribute_value_length(al);
if (!al->non_resident) {
! astart = (ATTR_LIST_ENTRY*)((char*)al +
! le16_to_cpu(al->value_offset));
} else {
! if (!(astart = (ATTR_LIST_ENTRY*)malloc(alen)))
goto ret_now;
if (get_attribute_value(v, al, astart) != alen)
goto error_ret;
}
/* Set aend to first byte after the attribute list. */
! aend = (ATTR_LIST_ENTRY*)((char*)astart + alen);
/* Iterate over all attribute list entries looking for the right one. */
! for (ale = astart; ale < aend; ale = (ATTR_LIST_ENTRY*)
((char*)ale + le16_to_cpu(ale->length))) {
/* If we encounter lowest_vcn != 0 then instance is 0 and we
***************
*** 127,135 ****
}
! __inline__ ATTRIBUTE_RECORD_HEADER *find_first_attr_in_attr_list(
const ntfs_volume *v,
! const MFT_RECORD_HEADER *m,
! const ATTRIBUTE_RECORD_HEADER *al,
! const ATTRIBUTE_TYPE t,
const wchar_t *n,
FIND_ATTR_CTX_FLAGS *ctx)
--- 116,124 ----
}
! __inline__ ATTR_RECORD *find_first_attr_in_attr_list(
const ntfs_volume *v,
! const MFT_RECORD *m,
! const ATTR_RECORD *al,
! const ATTR_TYPES t,
const wchar_t *n,
FIND_ATTR_CTX_FLAGS *ctx)
***************
*** 142,153 ****
return find_next_attr_in_attr_list(v, m, al, t, n, ctx);
}
! ATTRIBUTE_RECORD_HEADER *find_next_attr(const ntfs_volume *v,
! const MFT_RECORD_HEADER *b,
! const ATTRIBUTE_TYPE t,
const wchar_t *n,
FIND_ATTR_CTX_FLAGS *ctx)
{
! ATTRIBUTE_RECORD_HEADER *a, *al = NULL;
int got_there = 0;
--- 131,279 ----
return find_next_attr_in_attr_list(v, m, al, t, n, ctx);
}
+
+ /**
+ * find_attr - find attribute in mft record
+ * @vol: volume on which @a resides (used to find the upcase table)
+ * @attr: last found attribute record inside mft record to search
+ * @type: attribute type to find
+ * @name: attribute name to find (optional)
+ * @ic: ignore case of @name (boolean)
+ * @val: attribute value to find (optional, resident attributes only)
+ * @len: attribute value length (only present if @val present)
+ *
+ * Decsription...
+ *
+ * find_attr() takes an attribute record header @a as a parameter, which must
+ * be the address of a pointer into an mft record. It specifies the attribute
+ * at which to begin the search, i.e. it is useful as a search context in
+ * attribute enumerations.
+ */
+ ATTR_RECORD *find_next_attr(const ntfs_volume *vol, const ATTR_RECORD **attr,
+ const ATTR_TYPES type, const wchar_t *name,
+ const __u8 ic, const __u8 *val, const __u32 len)
+ {
+ ATTR_RECORD a;
+ void *mft_rec;
+
+ if (!vol || !attr || !*attr) {
+ #ifdef DEBUG
+ puts("Sanity checks failed in find_attr()!");
+ #endif
+ return NULL;
+ }
+ a = *attr;
+ /*
+ * Calculate the beginning of the mft record, assuming that it is
+ * aligned on mft_record_size boundary. In the kernel, this is
+ * guaranteed as it is either on a page (cache page) boundary (and a
+ * page is larger than an mft record in any case) or it is inside a
+ * page (cache page) on an mft_record_size boundary (by definition).
+ */
+ mft_rec = (void*)(p2n(a) & (vol->mft_record_size - 1));
+ /*
+ * Iterate over attributes in mft record starting at @attr.
+ * Note: We do not use while/do/for loops so the comparison
+ * code does not get indented out of the screen... (AIA)
+ */
+ search_loop:
+ *attr = a;
+ /* We catch $END with this more general check, too... */
+ if (le32_to_cpu(a->type) > le32_to_cpu(type))
+ goto not_found;
+ if (!a->length)
+ goto file_corrupt;
+ if (a->type == type)
+ goto attr_type_matches;
+ do_next:
+ a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length));
+ if (a < mft_rec || a > (char*)mft_rec + vol->mft_record_size)
+ goto file_corrupt;
+ goto search_loop;
+ attr_type_matches:
+ /* If want an unnamed attribute, check if current one
+ is unnamed and if so we have found it! */
+ if (!n) {
+ if (!a->name_length) {
+ /* FIXME: Check the value first! */
+ return a;
+ }
+ /* If we want a named attribute, check that the string
+ length is equal and if so, compare the two strings
+ and if they match, we have found it! */
+ } else if (a->name_length && a->name_length == wcslen(n)) {
+ /* Sanity check. */
+ if (a->name_length * 2 + le16_to_cpu(a->name_offset)
+ > le32_to_cpu(a->length)) {
+ #ifdef DEBUG
+ puts("Warning: Encountered out of "
+ "bounds attribute name length in "
+ "find_attr()!");
+ #endif
+ /* Even though this one is illegal,
+ maybe it wasn't the right one, so
+ continue with the search (i.e. don't
+ return NULL).
+ FIXME: Shouldn't we doing a hotfix
+ here, i.e. truncate the name to the
+ indicated size or change the
+ indicated size, whichever makes more
+ sense? */
+ /* FIXME: Should we really be case sensitive?
+ If not, use ntfs_wcsncasecmp(). */
+ } else if (!ntfs_wcsncmp(n, (wchar_t*)((char*)a +
+ le16_to_cpu(a->name_offset))),
+ a->name_length) {
+ /* FIXME: Check the value. */
+ return a;
+ }
+ }
+ not_found:
+ #ifdef DEBUG
+ if (name)
+ printf("find_attr(): Named attribute 0x%x (\"%s\") not "
+ "found.\n", type, name);
+ else
+ printf("find_attr(): Unnamed attribute 0x%x not found.\n",
+ type);
+ #endif
+ return NULL;
+ file_corrupt:
+ #ifdef DEBUG
+ printf(stderr, "find_attr(): File is corrupt. Run ntfsck or chkdsk.\n");
+ #endif
+ return NULL;
+ }
!
!
!
! /*
! * The difference between lookup_attr and find_attr is that find_attr will only
! * look inside the mft record, ignoring attribute lists, while lookup_attr will
! * take the attribute list in consideration if present. If not, it just calls
! * find_attr. Also in kernel, lookup_attr takes and mft_reference as parameter,
! * while find_attr takes a pointer within a pinned/locked page cache page.
! *
! * v = volume
! * m = mft record to search, also consistency check the sequence number if not 0
! * (kernel), in user space @m is the buffer containing the mft record
! * type = attribute type to find (0 = find first attribute)
! * name = attribute name to find (NULL = unnamed)
! * ic = ignore case (true/false)
! * val = attribute value to find (resident attributes only, NULL = don't care)
! * len = length of attribute value to find (only valid if val != NULL)
! * lvcn = lowest_vcn to find (non-resident attributes only)
! *
! * return: memory location of attribute we are looking for. this will be
! * an offset into a (pinned/locked?) page cache page in the driver.
! * for userspace we just return a pointer into the mft record @m.
! */
! ATTR_RECORD *lookup_attr_in_mft_rec(const ntfs_volume *v,
! const MFT_RECORD *m,
! const ATTR_TYPES t,
const wchar_t *n,
FIND_ATTR_CTX_FLAGS *ctx)
{
! ATTR_RECORD *a, *al = NULL;
int got_there = 0;
***************
*** 166,170 ****
}
/* Position of the first attribute. */
! a = (ATTRIBUTE_RECORD_HEADER*)(le16_to_cpu(b->attributes_offset) +
(char*)b);
if (p2n(a) & 7) {
--- 292,296 ----
}
/* Position of the first attribute. */
! a = (ATTR_RECORD*)(le16_to_cpu(b->attributes_offset) +
(char*)b);
if (p2n(a) & 7) {
***************
*** 174,180 ****
return NULL;
}
! if (t == 0)
! goto found_it;
! /* Iterate over the attributes. */
while (a->type != $END) {
if (le32_to_cpu(a->length) + (char*)a >=
--- 300,306 ----
return NULL;
}
! /* Look for an attribute list and at the same time check for attributes
! * which collate before the attribute list (i.e. the standard
! * information attribute). */
while (a->type != $END) {
if (le32_to_cpu(a->length) + (char*)a >=
***************
*** 185,242 ****
#endif
return NULL;
- }
- if (a->type == t) {
- /* If this is not the first search, we need to find
- the attribute with instance *ctx & INSTANCE_MASK.
- We then need to return the first matching attribute
- following this one. */
- if (*ctx != FIRST_SEARCH && !got_there) {
- if (a->instance == *ctx & INSTANCE_MASK)
- got_there = 1;
- goto do_next_attr;
- }
- /* If want an unnamed attribute, check if current one
- is unnamed and if so we have found it! */
- if (!n) {
- if (!a->name_length) {
- found_it:
- *ctx = a->instance;
- return a;
- }
- /* If we want a named attribute, check that the string
- length is equal and if so, compare the two strings
- and if they match, we have found it! */
- } else if (a->name_length &&
- a->name_length == wcslen(n)) {
- /* Sanity check. */
- if (a->name_length * 2 +
- le16_to_cpu(a->name_offset)
- > le32_to_cpu(a->length)) {
- #ifdef DEBUG
- puts("Warning: Encountered out of "
- "bounds attribute name length in "
- "find_attribute()!");
- #endif
- /* Even though this one is illegal,
- maybe it wasn't the right one, so
- continue with the search (i.e. don't
- return NULL).
- FIXME: Shouldn't we be doing a hotfix
- here? */
- /* FIXME: Should we really be case sensitive?
- If not we should be using the $UpCase table,
- thus we need a custom function for
- comparisons. Can't just use strcasecmp(). */
- } else if (!wcscmp(n, (wchar_t*)((char*)a +
- le16_to_cpu(a->name_offset))))
- goto found_it;
- }
}
do_next_attr:
- /* If an attribute list is present, save it. */
- if (!al && a->type == $ATTRIBUTE_LIST)
- al = a;
/* Get next attribute. */
! a = (ATTRIBUTE_RECORD_HEADER*)((char *)a +
le32_to_cpu(a->length));
if (p2n(a) & 7) {
--- 311,326 ----
#endif
return NULL;
}
+ if (le32_to_cpu(a->type) > le32_to_cpu($ATTRIBUTE_LIST))
+ break;
+ if (a->type == t)
+ /* FIXME: This is wrong. */
+ return a;
+ /* If an attribute list is present, handle it first. */
+ if (a->type == $ATTRIBUTE_LIST)
+ goto attr_list_handling;
do_next_attr:
/* Get next attribute. */
! a = (ATTR_RECORD*)((char *)a +
le32_to_cpu(a->length));
if (p2n(a) & 7) {
***************
*** 247,256 ****
return NULL;
}
- /* Gone too far? - Make sure to at least go as far as the
- attribute list. */
- if (le32_to_cpu(a->type) > le32_to_cpu(t) &&
- le32_to_cpu(a->type) > le32_to_cpu($ATTRIBUTE_LIST))
- break;
}
/* We have not found the attribute in the mft record @b. If an
attribute_list was found, and we are not looking for it, search it
--- 331,345 ----
return NULL;
}
}
+ not_found:
+ /* The requested attribute is not present. */
+ return NULL;
+
+ attr_list_handling:
+ /* Looking for zero means we return the first attribute.
+ FIXME: The first attribute is in the attr list! (AIA)
+ Don't return the attr list itself but the attribute instead. */
+ if (t == 0)
+ goto found_it;
/* We have not found the attribute in the mft record @b. If an
attribute_list was found, and we are not looking for it, search it
***************
*** 258,271 ****
to search for a second attribute list, which, while braindamaged,
could screw us up badly. */
! if (al && t != $ATTRIBUTE_LIST)
! attr_list_handling:
! return find_next_attr_in_attr_list(v, b, al, t, n, ctx);
/* The requested attribute is not present. */
! return NULL;
}
! __inline__ ATTRIBUTE_RECORD_HEADER *find_first_attr(const ntfs_volume *v,
! const MFT_RECORD_HEADER *b,
! const ATTRIBUTE_TYPE t,
const wchar_t *n,
FIND_ATTR_CTX_FLAGS *ctx)
--- 347,359 ----
to search for a second attribute list, which, while braindamaged,
could screw us up badly. */
! //return find_next_attr_in_attr_list(v, b, al, t, n, ctx);
!
/* The requested attribute is not present. */
! goto not_found;
}
! __inline__ ATTR_RECORD *find_first_attr(const ntfs_volume *v,
! const MFT_RECORD *b,
! const ATTR_TYPES t,
const wchar_t *n,
FIND_ATTR_CTX_FLAGS *ctx)
***************
*** 280,287 ****
/* FIXME: Need to write the new flags to disk. */
! int set_ntfs_volume_flags(ntfs_volume *v, MFT_RECORD_HEADER *b,
const __u16 flags)
{
! RESIDENT_ATTRIBUTE_RECORD_HEADER *r;
VOLUME_INFORMATION *c;
--- 368,375 ----
/* FIXME: Need to write the new flags to disk. */
! int set_ntfs_volume_flags(ntfs_volume *v, MFT_RECORD *b,
const __u16 flags)
{
! ATTR_RECORD *r;
VOLUME_INFORMATION *c;
***************
*** 290,295 ****
return 0;
/* Get a pointer to the volume information attribute. */
! if (!(r = (RESIDENT_ATTRIBUTE_RECORD_HEADER*)find_first_attr(v, b,
! $VOLUME_INFORMATION, NULL))) {
fprintf(stderr, "Error: Attribute $VOLUME_INFORMATION was " \
"not found in $Volume!\n");
--- 378,382 ----
return 0;
/* Get a pointer to the volume information attribute. */
! if (!(r = find_first_attr(v, b, $VOLUME_INFORMATION, NULL))) {
fprintf(stderr, "Error: Attribute $VOLUME_INFORMATION was " \
"not found in $Volume!\n");
***************
*** 297,301 ****
}
/* Sanity check. */
! if (r->attribute.non_resident) {
fprintf(stderr, "Error: Attribute $VOLUME_INFORMATION must " \
"be resident (and it isn't)!\n");
--- 384,388 ----
}
/* Sanity check. */
! if (r->non_resident) {
fprintf(stderr, "Error: Attribute $VOLUME_INFORMATION must " \
"be resident (and it isn't)!\n");
***************
*** 308,312 ****
le16_to_cpu(b->bytes_in_use) + (char*)b ||
le16_to_cpu(r->value_offset) + le32_to_cpu(r->value_length) >
! le32_to_cpu(r->attribute.length)) {
fprintf(stderr, "Error: Attribute $VOLUME_INFORMATION in " \
"$Volume is corrupt!\n");
--- 395,399 ----
le16_to_cpu(b->bytes_in_use) + (char*)b ||
le16_to_cpu(r->value_offset) + le32_to_cpu(r->value_length) >
! le32_to_cpu(r->length)) {
fprintf(stderr, "Error: Attribute $VOLUME_INFORMATION in " \
"$Volume is corrupt!\n");
***************
*** 319,323 ****
}
! __s64 get_attribute_value_length(const ATTRIBUTE_RECORD_HEADER *a)
{
if (!a) {
--- 406,410 ----
}
! __s64 get_attribute_value_length(const ATTR_RECORD *a)
{
if (!a) {
***************
*** 327,341 ****
errno = 0;
if (a->non_resident)
! return sle64_to_cpu(((NONRESIDENT_ATTRIBUTE_RECORD_HEADER*)
! (a))->data_size);
else
! return (__s64)le32_to_cpu(((RESIDENT_ATTRIBUTE_RECORD_HEADER*)
! (a))->value_length);
errno = EINVAL;
return 0;
}
! __s64 get_attribute_value(const ntfs_volume *vol, const MFT_RECORD_HEADER *m,
! const ATTRIBUTE_RECORD_HEADER *a, __u8 *b)
{
/* Sanity checks. */
--- 414,426 ----
errno = 0;
if (a->non_resident)
! return sle64_to_cpu(a->data_size);
else
! return (__s64)le32_to_cpu(a->value_length);
errno = EINVAL;
return 0;
}
! __s64 get_attribute_value(const ntfs_volume *vol, const MFT_RECORD *m,
! const ATTR_RECORD *a, __u8 *b)
{
/* Sanity checks. */
***************
*** 352,368 ****
}
if (!a->non_resident) { /* Attribute is resident. */
- #define RA(a) ((RESIDENT_ATTRIBUTE_RECORD_HEADER*)(a))
/* Sanity check. */
! if (le32_to_cpu(RA(a)->value_length) +
! le16_to_cpu(RA(a)->value_offset) > le32_to_cpu(a->length)) {
return 0;
}
! memcpy(b, (char*)a + le16_to_cpu(RA(a)->value_offset),
! le32_to_cpu(RA(a)->value_length));
errno = 0;
! return (__s64)le32_to_cpu(RA(a)->value_length);
! #undef RA
} else { /* Attribute is not resident. */
- #define NA(a) ((NONRESIDENT_ATTRIBUTE_RECORD_HEADER*)(a))
run_list rl;
__s64 total;
--- 437,450 ----
}
if (!a->non_resident) { /* Attribute is resident. */
/* Sanity check. */
! if (le32_to_cpu(a->value_length) +
! le16_to_cpu(a->value_offset) > le32_to_cpu(a->length)) {
return 0;
}
! memcpy(b, (char*)a + le16_to_cpu(a->value_offset),
! le32_to_cpu(a->value_length));
errno = 0;
! return (__s64)le32_to_cpu(a->value_length);
} else { /* Attribute is not resident. */
run_list rl;
__s64 total;
***************
*** 370,374 ****
/* If no data, return 0. */
! if (!(NA(a)->data_size)) {
errno = 0;
return 0;
--- 452,456 ----
/* If no data, return 0. */
! if (!(a->data_size)) {
errno = 0;
return 0;
***************
*** 378,382 ****
*/
/* Decompress the mapping pairs array into a run list. */
! rl = decompress_run_list(NA(a));
if (!rl) {
errno = EINVAL;
--- 460,464 ----
*/
/* Decompress the mapping pairs array into a run list. */
! rl = decompress_run_list(a);
if (!rl) {
errno = EINVAL;
***************
*** 495,499 ****
}
! int set_attribute_value(ntfs_volume *vol, ATTRIBUTE_RECORD_HEADER *a,
const __u8 *b, __s64 l)
{
--- 577,581 ----
}
! int set_attribute_value(ntfs_volume *vol, ATTR_RECORD *a,
const __u8 *b, __s64 l)
{
***************
*** 517,533 ****
}
if (!a->non_resident) { /* Attribute is resident. */
- #define RA(a) ((RESIDENT_ATTRIBUTE_RECORD_HEADER*)(a))
/* Sanity check. */
! if (le32_to_cpu(RA(a)->value_length) +
! le16_to_cpu(RA(a)->value_offset) > le32_to_cpu(a->length)) {
errno = EINVAL;
return 0;
}
! memcpy((char*)a + le16_to_cpu(RA(a)->value_offset), b, l);
errno = 0;
return 1;
- #undef RA
} else { /* Attribute is not resident. */
- #define NA(a) ((NONRESIDENT_ATTRIBUTE_RECORD_HEADER*)(a))
run_list rl;
__s64 total;
--- 599,612 ----
}
if (!a->non_resident) { /* Attribute is resident. */
/* Sanity check. */
! if (le32_to_cpu(a->value_length) +
! le16_to_cpu(a->value_offset) > le32_to_cpu(a->length)) {
errno = EINVAL;
return 0;
}
! memcpy((char*)a + le16_to_cpu(a->value_offset), b, l);
errno = 0;
return 1;
} else { /* Attribute is not resident. */
run_list rl;
__s64 total;
***************
*** 536,545 ****
/* If no data return 1. FIXME: This needs to change when we can
cope with changes in length of the attribute. */
! if (!(NA(a)->data_size)) {
errno = 0;
return 1;
}
/* Decompress the mapping pairs array into a run list. */
! rl = decompress_run_list(NA(a));
/* Now write all clusters to disk from b. */
for (i = 0, total = 0; rl[i].length && (l > 0); i++) {
--- 615,624 ----
/* If no data return 1. FIXME: This needs to change when we can
cope with changes in length of the attribute. */
! if (!(a->data_size)) {
errno = 0;
return 1;
}
/* Decompress the mapping pairs array into a run list. */
! rl = decompress_run_list(a);
/* Now write all clusters to disk from b. */
for (i = 0, total = 0; rl[i].length && (l > 0); i++) {
***************
*** 587,591 ****
free(rl);
return 1;
- #undef NA
}
errno = EINVAL;
--- 666,669 ----
***************
*** 593,597 ****
}
! run_list decompress_run_list(const NONRESIDENT_ATTRIBUTE_RECORD_HEADER *attr)
{
__s64 vcn, lcn; /* Current vcn and lcn, respectively. */
--- 671,675 ----
}
! run_list decompress_run_list(const ATTR_RECORD *attr)
{
__s64 vcn, lcn; /* Current vcn and lcn, respectively. */
***************
*** 606,610 ****
/* Make sure attr exists and is non-resident. */
! if (!attr || !attr->attribute.non_resident)
return NULL;
/*
--- 684,688 ----
/* Make sure attr exists and is non-resident. */
! if (!attr || !attr->non_resident)
return NULL;
/*
Index: bootsect.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/bootsect.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -r1.2 -r1.3
*** bootsect.c 2001/01/30 12:29:03 1.2
--- bootsect.c 2001/03/05 03:04:40 1.3
***************
*** 84,87 ****
--- 84,96 ----
puts("OK");
+ /* Check the sector size is not above 65536 bytes. */
+ if (!silent)
+ printf("Checking cluster size... ");
+ if ((__u32)le16_to_cpu(b->bpb.bytes_per_sector) *
+ b->bpb.sectors_per_cluster > 0x10000)
+ goto not_ntfs;
+ if (!silent)
+ puts("OK");
+
/* Check reserved/unused fields are really zero. */
if (!silent)
Index: disk_io.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/disk_io.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -r1.2 -r1.3
*** disk_io.c 2001/03/02 15:05:53 1.2
--- disk_io.c 2001/03/05 03:04:40 1.3
***************
*** 94,98 ****
}
/* Prepare data for writing. */
! pre_write_mst_fixup((NTFS_RECORD_HEADER*)b, count);
/* Write the prepared data. */
total = retry = 0;
--- 94,98 ----
}
/* Prepare data for writing. */
! pre_write_mst_fixup((NTFS_RECORD*)b, count);
/* Write the prepared data. */
total = retry = 0;
***************
*** 118,122 ****
finished:
/* Quickly deprotect the data again. */
! __post_read_mft_fixup((NTFS_RECORD_HEADER*)b, count);
error_end:
return error;
--- 118,122 ----
finished:
/* Quickly deprotect the data again. */
! __post_read_mft_fixup((NTFS_RECORD*)b, count);
error_end:
return error;
***************
*** 199,203 ****
made use of). */
for (i = 0; i < count; ++i)
! post_read_mst_fixup((NTFS_RECORD_HEADER*)(b +
(i << bksize_bits)), bksize);
/* Finally, return the number of blocks read. */
--- 199,203 ----
made use of). */
for (i = 0; i < count; ++i)
! post_read_mst_fixup((NTFS_RECORD*)(b +
(i << bksize_bits)), bksize);
/* Finally, return the number of blocks read. */
Index: mft.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/mft.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** mft.c 2001/01/25 22:25:43 1.1
--- mft.c 2001/03/05 03:04:40 1.2
***************
*** 25,29 ****
#include "endians.h"
! inline __u32 get_mft_record_data_size(const MFT_RECORD_HEADER *b)
{
if (!b || !is_mft_recordp(b))
--- 25,29 ----
#include "endians.h"
! inline __u32 get_mft_record_data_size(const MFT_RECORD *b)
{
if (!b || !is_mft_recordp(b))
Index: ntfs_rec.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/ntfs_rec.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -r1.2 -r1.3
*** ntfs_rec.c 2001/03/02 15:05:54 1.2
--- ntfs_rec.c 2001/03/05 03:04:40 1.3
***************
*** 25,29 ****
#include "endians.h"
! __inline__ void __post_read_mst_fixup(NTFS_RECORD_HEADER *b, const __u32 size)
{
__u16 usa_ofs, usa_count;
--- 25,29 ----
#include "endians.h"
! __inline__ void __post_read_mst_fixup(NTFS_RECORD *b, const __u32 size)
{
__u16 usa_ofs, usa_count;
***************
*** 51,55 ****
}
! int post_read_mst_fixup(NTFS_RECORD_HEADER *b, const __u32 size)
{
__u16 usa_ofs, usa_count, usn;
--- 51,55 ----
}
! int post_read_mst_fixup(NTFS_RECORD *b, const __u32 size)
{
__u16 usa_ofs, usa_count, usn;
***************
*** 111,115 ****
}
! int pre_write_mst_fixup(NTFS_RECORD_HEADER *b, const __u32 size)
{
__u16 usa_ofs, usa_count, usn;
--- 111,115 ----
}
! int pre_write_mst_fixup(NTFS_RECORD *b, const __u32 size)
{
__u16 usa_ofs, usa_count, usn;
Index: volume.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/volume.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -r1.4 -r1.5
*** volume.c 2001/03/02 15:05:54 1.4
--- volume.c 2001/03/05 03:04:40 1.5
***************
*** 41,46 ****
ntfs_volume *vol = NULL;
NTFS_BOOT_SECTOR *bs = NULL;
! MFT_RECORD_HEADER *mb = NULL;
! ATTRIBUTE_RECORD_HEADER *a;
VOLUME_INFORMATION *vinf;
__u32 u;
--- 41,46 ----
ntfs_volume *vol = NULL;
NTFS_BOOT_SECTOR *bs = NULL;
! MFT_RECORD *mb = NULL;
! ATTR_RECORD *a;
VOLUME_INFORMATION *vinf;
__u32 u;
***************
*** 183,187 ****
/* Start with $Mft. */
printf("Loading $Mft... ");
! if (!(mb = (MFT_RECORD_HEADER *)malloc(vol->mft_record_size))) {
puts(FAILED);
perror("Error allocating memory for $Mft");
--- 183,187 ----
/* Start with $Mft. */
printf("Loading $Mft... ");
! if (!(mb = (MFT_RECORD *)malloc(vol->mft_record_size))) {
puts(FAILED);
perror("Error allocating memory for $Mft");
***************
*** 261,267 ****
}
/* Determine the number of mft records in $Mft. */
! vol->number_of_mft_records =
! ((NONRESIDENT_ATTRIBUTE_RECORD_HEADER*)a)->data_size >>
! vol->mft_record_size_bits;
/* The $DATA attribute of the $Mft has to be non-resident. */
if (!a->non_resident) {
--- 261,265 ----
}
/* Determine the number of mft records in $Mft. */
! vol->number_of_mft_records = a->data_size >> vol->mft_record_size_bits;
/* The $DATA attribute of the $Mft has to be non-resident. */
if (!a->non_resident) {
***************
*** 272,277 ****
}
/* Get the run list. */
! vol->mft_runlist = decompress_run_list(
! (NONRESIDENT_ATTRIBUTE_RECORD_HEADER*)a);
if (!vol->mft_runlist) {
puts(FAILED);
--- 270,274 ----
}
/* Get the run list. */
! vol->mft_runlist = decompress_run_list(a);
if (!vol->mft_runlist) {
puts(FAILED);
***************
*** 445,456 ****
}
/* Get a pointer to the value of the attribute. */
! #define RA(x) ((RESIDENT_ATTRIBUTE_RECORD_HEADER*)(x))
! vinf = (VOLUME_INFORMATION*)(le16_to_cpu(RA(a)->value_offset) +
! (char*)a);
/* Sanity checks. */
! if ((char*)vinf + le32_to_cpu(RA(a)->value_length) >
le16_to_cpu(mb->bytes_in_use) + (char*)mb ||
! le16_to_cpu(RA(a)->value_offset) +
! le32_to_cpu(RA(a)->value_length) >
le32_to_cpu(a->length)) {
fprintf(stderr, "Error: Attribute $VOLUME_INFORMATION in " \
--- 442,451 ----
}
/* Get a pointer to the value of the attribute. */
! vinf = (VOLUME_INFORMATION*)(le16_to_cpu(a->value_offset) + (char*)a);
/* Sanity checks. */
! if ((char*)vinf + le32_to_cpu(a->value_length) >
le16_to_cpu(mb->bytes_in_use) + (char*)mb ||
! le16_to_cpu(a->value_offset) +
! le32_to_cpu(a->value_length) >
le32_to_cpu(a->length)) {
fprintf(stderr, "Error: Attribute $VOLUME_INFORMATION in " \
***************
*** 459,463 ****
goto error_exit;
}
- #undef RA
/* Setup vol from the volume information attribute value. */
vol->major_ver = vinf->major_ver;
--- 454,457 ----
|