Changes by: antona
Update of /cvsroot/linux-ntfs/linux-ntfs/libntfs
In directory usw-pr-cvs1:/tmp/cvs-serv5330
Modified Files:
attrib.c disk_io.c ntfs_rec.c volume.c
Log Message:
Commit latest library state. !!!NOTE!!! This breaks everything!!! I'm in the
middle of rewritting the find_attribute stuff in attrib.c at the moment.
Index: attrib.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/attrib.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -r1.2 -r1.3
*** attrib.c 2001/01/30 12:55:21 1.2
--- attrib.c 2001/03/02 15:05:53 1.3
***************
*** 31,35 ****
* 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.
*/
/* #include <linux/nls.h> */
--- 31,35 ----
* 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> */
***************
*** 46,61 ****
#define p2n(p) ((ptrdiff_t)((ptrdiff_t*)(p)))
! ATTRIBUTE_RECORD_HEADER *find_attribute(const MFT_RECORD_HEADER *b,
const ATTRIBUTE_TYPE t,
! const wchar_t *n)
{
! ATTRIBUTE_RECORD_HEADER *a;
/* Sanity/size/alignment checks. */
! if (!b || !is_mft_recordp(b) ||
! !(b->flags & MFT_RECORD_IN_USE) ||
! b->base_mft_record ||
! p2n((char*)b + b->attributes_offset) & 7 ||
! p2n((char*)b + b->bytes_in_use) & 7 ||
le16_to_cpu(b->attributes_offset) >= le32_to_cpu(b->bytes_in_use)) {
#ifdef DEBUG
--- 46,161 ----
#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;
!
! if (!al || !ctx || al->type != $ATTRIBUTE_LIST) {
! errno = EINVAL;
! goto ret_now;
! }
! if (al->flags) {
! #ifdef DEBUG
! puts("Error! Compressed/sparse/encrypted attribute lists not "
! "supported.");
! #endif
! errno = ENOTSUP;
! goto ret_now;
! }
! /* Get the actual attribute list and it's length. */
! 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
! are currently in a list of extents. */
! if (*ctx == FIRST_SEARCH) {
! /* The attribute was not found in the base mft record
! at all. Thus take the first matching entry and
! return that. */
! *ctx = IN_ATTR_LIST | ...;
! } else {
! /* The attribute has been found before. */
! if (!(*ctx & IN_ATTR_LIST)) {
! /* We were not in the attribute list before,
! yet we had found the attribute at least once
! already. The entry we had found will be
! duplicated in the attribute list. Thus, skip
! the first matching entry (which will be the
! duplicate one). */
! /* FIXME: This won't work as we get into nested
! extents / attributes problem! Argh! We _have_
! to search the attribute list if it is present
! and ignore the base mft record otherwise.
! We search the base mft record for other
! attributes only if the attribute list entry
! points us to it. */
! *ctx |= IN_ATTR_LIST;
! } else {
! /* We were in the attribute list already, */
! }
! }
! }
! errno = ENOENT;
! error_ret:
! if (al->non_resident)
! free(astart);
! ret_now:
! return NULL;
! }
!
! __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)
! {
! FIND_ATTR_CTX_FLAGS c;
!
! if (!ctx)
! ctx = &c;
! *ctx = FIRST_SEARCH;
! 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;
+
/* Sanity/size/alignment checks. */
! if (!b || !ctx || !is_mft_recordp(b) ||
! !(b->flags & MFT_RECORD_IN_USE) ||
! b->base_mft_record ||
! p2n((char*)b + b->attributes_offset) & 7 ||
! p2n((char*)b + b->bytes_in_use) & 7 ||
le16_to_cpu(b->attributes_offset) >= le32_to_cpu(b->bytes_in_use)) {
#ifdef DEBUG
***************
*** 67,73 ****
/* Position of the first attribute. */
a = (ATTRIBUTE_RECORD_HEADER*)(le16_to_cpu(b->attributes_offset) +
! (char*)b);
! /* Alignment check. Note: Can't move this inside while loop, since if
! this fails a->type will fail too but it will cause an exception! */
if (p2n(a) & 7) {
#ifdef DEBUG
--- 167,171 ----
/* Position of the first attribute. */
a = (ATTRIBUTE_RECORD_HEADER*)(le16_to_cpu(b->attributes_offset) +
! (char*)b);
if (p2n(a) & 7) {
#ifdef DEBUG
***************
*** 76,80 ****
return NULL;
}
! /* Iterate over all atributes. */
while (a->type != $END) {
if (le32_to_cpu(a->length) + (char*)a >=
--- 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 >=
***************
*** 87,95 ****
}
if (a->type == t) {
/* If want an unnamed attribute, check if current one
is unnamed and if so we have found it! */
if (!n) {
! if (!a->name_length)
return a;
/* If we want a named attribute, check that the string
length is equal and if so, compare the two strings
--- 187,207 ----
}
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
***************
*** 110,158 ****
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 we should be using the $UpCase table,
thus we need a custom function for
! comparisons. */
} else if (!wcscmp(n, (wchar_t*)((char*)a +
le16_to_cpu(a->name_offset))))
! return a;
}
- }
- /* FIXME: If we find an attribute list then the attribute we
- are looking for might be in there, but we don't handle those
- yet, so just skip it for now and emitt a warning. */
- if (a->type == $ATTRIBUTE_LIST) {
- puts("Warning: Encountered attribute list attribute"
- "which we can't handle yet.");
}
/* Get next attribute. */
a = (ATTRIBUTE_RECORD_HEADER*)((char *)a +
le32_to_cpu(a->length));
- /* Alignment check. */
if (p2n(a) & 7) {
#ifdef DEBUG
! puts("Allignment check (3) failed in " \
"find_attribute()!");
#endif
return NULL;
}
! }
! #ifdef DEBUG
! if (n)
! printf("Named attribute 0x%x not found in " \
! "find_attribute()!", t);
! else
! printf("Unnamed attribute 0x%x not found in " \
! "find_attribute()!", t);
! #endif
return NULL;
}
! int set_ntfs_volume_flags(MFT_RECORD_HEADER *b, const __u16 flags)
{
RESIDENT_ATTRIBUTE_RECORD_HEADER *r;
--- 222,285 ----
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) {
#ifdef DEBUG
! puts("Allignment check (4) failed in " \
"find_attribute()!");
#endif
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
! now, otherwise return NULL. Second check needed if someone decides
! 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)
+ {
+ FIND_ATTR_CTX_FLAGS c;
+
+ if (!ctx)
+ ctx = &c;
+ *ctx = FIRST_SEARCH;
+ return find_next_attr(v, b, t, n, ctx);
+ }
! /* 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;
***************
*** 163,167 ****
return 0;
/* Get a pointer to the volume information attribute. */
! if (!(r = (RESIDENT_ATTRIBUTE_RECORD_HEADER*)find_attribute(b,
$VOLUME_INFORMATION, NULL))) {
fprintf(stderr, "Error: Attribute $VOLUME_INFORMATION was " \
--- 290,294 ----
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 " \
***************
*** 192,196 ****
}
! __u64 get_attribute_value_length(const ATTRIBUTE_RECORD_HEADER *a)
{
if (!a) {
--- 319,323 ----
}
! __s64 get_attribute_value_length(const ATTRIBUTE_RECORD_HEADER *a)
{
if (!a) {
***************
*** 200,207 ****
errno = 0;
if (a->non_resident)
! return le64_to_cpu(((NONRESIDENT_ATTRIBUTE_RECORD_HEADER*)
(a))->data_size);
else
! return (__u64)le32_to_cpu(((RESIDENT_ATTRIBUTE_RECORD_HEADER*)
(a))->value_length);
errno = EINVAL;
--- 327,334 ----
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;
***************
*** 209,213 ****
}
! __u64 get_attribute_value(const ntfs_volume *vol,
const ATTRIBUTE_RECORD_HEADER *a, __u8 *b)
{
--- 336,340 ----
}
! __s64 get_attribute_value(const ntfs_volume *vol, const MFT_RECORD_HEADER *m,
const ATTRIBUTE_RECORD_HEADER *a, __u8 *b)
{
***************
*** 234,243 ****
le32_to_cpu(RA(a)->value_length));
errno = 0;
! return (__u64)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;
! __u64 total;
int r, i;
--- 361,370 ----
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;
int r, i;
***************
*** 247,250 ****
--- 374,380 ----
return 0;
}
+ /*
+ * FIXME: What about attribute lists?!? (AIA)
+ */
/* Decompress the mapping pairs array into a run list. */
rl = decompress_run_list(NA(a));
***************
*** 288,292 ****
/*
* FIXME: If compressed file: Only read if
! * lcn != 0. Otherwise, we are dealing with a
* sparse run and we just memset the user buffer
* to 0 for the length of the run, which should
--- 418,422 ----
/*
* FIXME: If compressed file: Only read if
! * lcn != -1. Otherwise, we are dealing with a
* sparse run and we just memset the user buffer
* to 0 for the length of the run, which should
***************
*** 320,330 ****
}
memcpy(b + total, intbuf,
! le64_to_cpu(NA(a)->data_size) - total);
free(intbuf);
! total = le64_to_cpu(NA(a)->data_size);
} else {
/*
* FIXME: If compressed file: Only read if
! * lcn != 0. Otherwise, we are dealing with a
* sparse run and we just memset the user buffer
* to 0 for the length of the run, which should
--- 450,460 ----
}
memcpy(b + total, intbuf,
! sle64_to_cpu(NA(a)->data_size) - total);
free(intbuf);
! total = sle64_to_cpu(NA(a)->data_size);
} else {
/*
* FIXME: If compressed file: Only read if
! * lcn != -1. Otherwise, we are dealing with a
* sparse run and we just memset the user buffer
* to 0 for the length of the run, which should
***************
*** 366,370 ****
int set_attribute_value(ntfs_volume *vol, ATTRIBUTE_RECORD_HEADER *a,
! const __u8 *b, __u64 l)
{
/* Sanity check. */
--- 496,500 ----
int set_attribute_value(ntfs_volume *vol, ATTRIBUTE_RECORD_HEADER *a,
! const __u8 *b, __s64 l)
{
/* Sanity check. */
***************
*** 401,405 ****
#define NA(a) ((NONRESIDENT_ATTRIBUTE_RECORD_HEADER*)(a))
run_list rl;
! __u64 total;
int w, i;
--- 531,535 ----
#define NA(a) ((NONRESIDENT_ATTRIBUTE_RECORD_HEADER*)(a))
run_list rl;
! __s64 total;
int w, i;
***************
*** 490,494 ****
}
/* Start at vcn = lowest_vcn and lcn 0. */
! vcn = le64_to_cpu(attr->lowest_vcn);
lcn = 0;
/* Get start of the mapping pairs array. */
--- 620,624 ----
}
/* Start at vcn = lowest_vcn and lcn 0. */
! vcn = sle64_to_cpu(attr->lowest_vcn);
lcn = 0;
/* Get start of the mapping pairs array. */
***************
*** 534,556 ****
}
/* Enter the current run length into the current
! * run_list_element. */
(rl + rlpos)->length = deltaxcn;
/* Increment the current vcn by the current run length. */
vcn += deltaxcn;
! /* Get the lcn change which really can be negative. */
! for (b = (*buf & 0xf) + ((*buf >> 4) & 0xf),
! deltaxcn = (__s8)buf[b--]; b > (*buf & 0xf); b--) {
! deltaxcn = (deltaxcn << 8) + buf[b];
}
- /* Change the current lcn to it's new value. */
- lcn += deltaxcn;
- /* Enter the current lcn into the current run_list_element. */
- (rl + rlpos)->lcn = lcn;
/* Get to the next run_list_element. */
rlpos++;
/* Increment the buffer position to the next mapping pair. */
! buf += (*buf & 0xf) + ((*buf >> 4) & 0xf) + 1;
}
! /* If there were no mapping pairs in the run_list, then rl will still
be NULL. */
if (rl) {
--- 664,692 ----
}
/* Enter the current run length into the current
! run_list_element. */
(rl + rlpos)->length = deltaxcn;
/* Increment the current vcn by the current run length. */
vcn += deltaxcn;
! /* There might be no lcn change at all, as is the case for
! sparse clusters, in which case we set the lcn to -1. */
! if (!(*buf & 0xf0))
! (rl + rlpos)->lcn = -1;
! else {
! /* Get the lcn change which really can be negative. */
! for (b = (*buf & 0xf) + ((*buf >> 4) & 0xf),
! deltaxcn = (__s8)buf[b--]; b > (*buf & 0xf); b--) {
! deltaxcn = (deltaxcn << 8) + buf[b];
! }
! /* Change the current lcn to it's new value. */
! lcn += deltaxcn;
! /* Enter the current lcn into the run_list_element. */
! (rl + rlpos)->lcn = lcn;
}
/* Get to the next run_list_element. */
rlpos++;
/* Increment the buffer position to the next mapping pair. */
! buf += (*buf & 0xf) + ((*buf >> 4) & 0xf) + 1;
}
! /* If there were no mapping pairs in the run_list, then rl will stil
be NULL. */
if (rl) {
***************
*** 570,580 ****
/*
* This is not necessary, but do it for completeness sake.
! * FIXME: Do we really want this zero? Zero means it is sparse,
! * but I guess better zero than an undefined random value...
*/
! (rl + rlpos)->lcn = 0;
/* The final vcn - 1 has to be equal to highest_vcn or
something has gone badly wrong. */
! if (vcn - 1 != le64_to_cpu(attr->highest_vcn)) {
free(rl);
puts("Corrupt Mapping Pairs Array in non-resident "
--- 706,716 ----
/*
* This is not necessary, but do it for completeness sake.
! * FIXME: Do we really want this -1? -1 means it is sparse,
! * but I guess better that than an undefined random value...
*/
! (rl + rlpos)->lcn = -1;
/* The final vcn - 1 has to be equal to highest_vcn or
something has gone badly wrong. */
! if (vcn - 1 != sle64_to_cpu(attr->highest_vcn)) {
free(rl);
puts("Corrupt Mapping Pairs Array in non-resident "
Index: disk_io.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/disk_io.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** disk_io.c 2001/01/26 00:34:10 1.1
--- disk_io.c 2001/03/02 15:05:53 1.2
***************
*** 65,113 ****
}
__u64 mst_pwrite(int fd, const void *b, __u64 count, const __u64 pos)
{
! __u64 written, total;
char retry;
- void *buf;
if (!b) {
errno = EINVAL;
! return -1;
}
! if (!count)
! return 0;
/* Locate to position. */
! if (lseek(fd, pos, SEEK_SET) == (off_t)-1)
! return -1;
! /* Get memory for copy of data. */
! if (!(buf = malloc(count)))
! return -1;
! /* Make a copy of the data. */
! memcpy(buf, b, count);
! /* Prepare copied data for writing. */
! if (pre_write_mst_fixup((NTFS_RECORD_HEADER*)buf, count)) {
! __u16 *usn_pos;
! __u16 usn;
! /*
! * Ok, need to update usn in original buffer (b) as well,
! * otherwise two writes of the same data would result in the
! * same usn being written on top of the same usn, which means
! * no protection after first write and in fact it actually
! * would cause corruption and not just lack of protection!!!
! */
! usn_pos = (__u16*)((__u8*)b +
! le16_to_cpu(((NTFS_RECORD_HEADER*)b)->usa_ofs));
! usn = le16_to_cpup(usn_pos) + 1;
! if (usn == 0xffff || !usn)
! usn = 1;
! *usn_pos = cpu_to_le16(usn);
}
! /* Write the prepared data (copy). */
total = retry = 0;
do {
! written = write(fd, ((char *)buf) + total, count);
if (written == -1) {
! free(buf);
! return written;
}
else if (!written)
--- 65,105 ----
}
+ /*
+ * NOTE: We mst protect the data, write it, then mst deprotect it using a quick
+ * deprotect algorithm (no checking). This saves us from making a copy before
+ * the write and at the same causes the usn to be incremented in the buffer.
+ * This conceptually fits in better with the idea that cached data is always
+ * deprotected and protection is performed when the data is actually going to
+ * hit the disk and the cache is immediately deprotected again simulating an
+ * mst read on the written data. This way cache coherency is achieved.
+ */
__u64 mst_pwrite(int fd, const void *b, __u64 count, const __u64 pos)
{
! __u64 written, total, error;
char retry;
if (!b) {
errno = EINVAL;
! error = -1;
! goto error_end;
}
! if (!count) {
! error = 0;
! goto error_end;
! }
/* Locate to position. */
! if (lseek(fd, pos, SEEK_SET) == (off_t)-1) {
! error = -1;
! goto error_end;
}
! /* Prepare data for writing. */
! pre_write_mst_fixup((NTFS_RECORD_HEADER*)b, count);
! /* Write the prepared data. */
total = retry = 0;
do {
! written = write(fd, ((char *)b) + total, count);
if (written == -1) {
! error = -1;
! goto finished;
}
else if (!written)
***************
*** 117,127 ****
total += written;
} while (count && (retry < 3));
- /* Don't need the copy of the data anymore. */
- free(buf);
/* Sync write to disk. */
! if (fdatasync(fd) == -1)
! return -1;
/* Finally return the number of bytes written. */
! return total;
}
--- 109,124 ----
total += written;
} while (count && (retry < 3));
/* Sync write to disk. */
! if (fdatasync(fd) == -1) {
! error = -1;
! goto finished;
! }
/* Finally return the number of bytes written. */
! error = total;
! finished:
! /* Quickly deprotect the data again. */
! __post_read_mft_fixup((NTFS_RECORD_HEADER*)b, count);
! error_end:
! return error;
}
Index: ntfs_rec.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/ntfs_rec.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** ntfs_rec.c 2001/01/25 22:25:43 1.1
--- ntfs_rec.c 2001/03/02 15:05:54 1.2
***************
*** 25,28 ****
--- 25,54 ----
#include "endians.h"
+ __inline__ void __post_read_mst_fixup(NTFS_RECORD_HEADER *b, const __u32 size)
+ {
+ __u16 usa_ofs, usa_count;
+ __u16 *usa_pos, *data_pos;
+
+ /* Setup the variables. */
+ usa_ofs = le16_to_cpu(b->usa_ofs);
+ usa_count = le16_to_cpu(b->usa_count) - 1;
+ /* Position of usn in update sequence array. */
+ usa_pos = (__u16*)b + usa_ofs/sizeof(__u16);
+ /*
+ * Position in protected data of first __u16 that needs fixing up.
+ */
+ data_pos = (__u16*)b + NTFS_SECTOR_SIZE/sizeof(__u16) - 1;
+ /* Fixup all sectors. */
+ while (usa_count--) {
+ /*
+ * Increment position in usa and restore original data from
+ * the usa into the data buffer.
+ */
+ *data_pos = *(++usa_pos);
+ /* Increment position in data as well. */
+ data_pos += NTFS_SECTOR_SIZE/sizeof(__u16);
+ }
+ }
+
int post_read_mst_fixup(NTFS_RECORD_HEADER *b, const __u32 size)
{
***************
*** 55,59 ****
*/
data_pos = (__u16*)b + NTFS_SECTOR_SIZE/sizeof(__u16) - 1;
! /* Fixup all sectors. */
while (usa_count--) {
if (*data_pos != usn) {
--- 81,87 ----
*/
data_pos = (__u16*)b + NTFS_SECTOR_SIZE/sizeof(__u16) - 1;
! /*
! * Check for incomplete multi sector transfer(s).
! */
while (usa_count--) {
if (*data_pos != usn) {
***************
*** 66,69 ****
--- 94,103 ----
return 0;
}
+ data_pos += NTFS_SECTOR_SIZE/sizeof(__u16);
+ /* Re-setup the variables. */
+ usa_count = le16_to_cpu(b->usa_count) - 1;
+ data_pos = (__u16*)b + NTFS_SECTOR_SIZE/sizeof(__u16) - 1;
+ /* Fixup all sectors. */
+ while (usa_count--) {
/*
* Increment position in usa and restore original data from
Index: volume.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/volume.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -r1.3 -r1.4
*** volume.c 2001/01/30 12:55:21 1.3
--- volume.c 2001/03/02 15:05:54 1.4
***************
*** 222,226 ****
}
/* Find the bitmap attribute. */
! a = find_attribute(mb, $BITMAP, NULL);
if (!a) {
puts(FAILED);
--- 222,226 ----
}
/* Find the bitmap attribute. */
! a = find_first_attribute(vol, mb, $BITMAP, NULL);
if (!a) {
puts(FAILED);
***************
*** 253,257 ****
}
/* Find the $DATA attribute in $Mft. */
! a = find_attribute(mb, $DATA, NULL);
if (!a) {
puts(FAILED);
--- 253,257 ----
}
/* Find the $DATA attribute in $Mft. */
! a = find_first_attribute(vol, mb, $DATA, NULL);
if (!a) {
puts(FAILED);
***************
*** 310,314 ****
}
/* Find the bitmap (it is in the $DATA attribute). */
! a = find_attribute(mb, $DATA, NULL);
if (!a) {
puts(FAILED);
--- 310,314 ----
}
/* Find the bitmap (it is in the $DATA attribute). */
! a = find_first_attribute(vol, mb, $DATA, NULL);
if (!a) {
puts(FAILED);
***************
*** 365,369 ****
}
/* Find the bitmap (it is in the $DATA attribute). */
! a = find_attribute(mb, $DATA, NULL);
if (!a) {
puts(FAILED);
--- 365,369 ----
}
/* Find the bitmap (it is in the $DATA attribute). */
! a = find_first_attribute(vol, mb, $DATA, NULL);
if (!a) {
puts(FAILED);
***************
*** 429,433 ****
}
/* Find the $VOLUME_INFORMATION attribute. */
! a = find_attribute(mb, $VOLUME_INFORMATION, NULL);
if (!a) {
puts(FAILED);
--- 429,433 ----
}
/* Find the $VOLUME_INFORMATION attribute. */
! a = find_first_attribute(vol, mb, $VOLUME_INFORMATION, NULL);
if (!a) {
puts(FAILED);
***************
*** 468,472 ****
/* Phew! Done. */
! /* FIXME: Need to initialise vol->dev_name as well. */
puts(OK);
--- 468,472 ----
/* Phew! Done. */
! /* FIXME: Need to initialise vol->vol_name as well. */
puts(OK);
|