whitespace and include guards

2002/07/02 23:47:10-00:00 !antona
Global replacement of __[su]{8,16,32,64} with [su]{8,16,32,64} and layout.h define it.

2002/04/22 10:34:31-00:00 !antona
Attribute list support (merging done, part 2, some stuff still incomplete). mkntfs ntfs volume creation. See the changelog...

2002/04/20 23:09:42-00:00 !antona
Port attribute lookup functions with attribute list support from ntfs tng driver. Port/reimplement extent mft record handling code as well. Rename out all dollar signs from type names and constants. Adapt all callers to new API. Note mkntfs is currently broken due to some needed work.

2002/04/20 01:53:02-00:00 !antona
Rename mft code adding ntfs_ prefix. Change all return values to zero on success. Thanks to mattjf for pointing out the inconsistencies.

2002/04/19 21:09:55-00:00 !antona
Finished provisional inode.c::ntfs_{open,close}_inode() functions. Also, started defining API provided by attrib.[ch], so far only done search context related stuff.

2001/04/02 02:04:37-00:00 !antona
Everything compiles again! Yey! (Don't know about working though, haven't tried
it... So be careful...)
The definitely final find_{first_}attr() functions are in place. Currently
still no support for attribute lists.
The two new _RE files contain the C-fied and more or less (more less than more
actually) cleaned up functions from the ntfs driver. Once they are cleaned
up (find_attr() is already completed but I left it in the _RE files for future
reference/educational value) and modified to suit my ideas of how they should
work, which are not quite the same as the driver way, they will make it into
attrib.[ch].
If anyone gives the new code a try, I would be interested in whether it worked
or not... (-;

(Logical change 1.5)
This commit is contained in:
!flatcap 2002-08-22 18:09:47 +00:00
parent c9180f848e
commit 10a361fafa

View File

@ -0,0 +1,449 @@
/* Reverse engineered functions in more or less modified form. find_attr()
* is quite heavily modified but should be functionally equivalent to original.
* lookup and lookup_external are less modified. Both should be functionally
* equivalent to originals. */
/*
* attr_search_context - used in attribute search functions
* @mrec: buffer containing mft record to search
* @attr: attribute record in @mrec where to begin/continue search
* @alist_mrec: mft record containing attribute list (i.e. base mft record)
* @alist_attr: attribute list attribute record
* @alist_val: attribute list value (if alist is resident in @alist_mrec)
* @alist_val_end: end of attribute list value + 1
* @alist_val_len: length of attribute list in bytes
* @is_first: if true lookup_attr() begins search with @attr, else after @attr
*
* Structure must be initialized to zero before the first call to one of the
* attribute search functions. If the mft record in which to search has already
* been loaded into memory, then initialize @base and @mrec to point to it,
* @attr to point to the first attribute within @mrec, and set @is_first to
* TRUE.
*
* @is_first is only honoured in lookup_attr() and only when called with @mrec
* not NULL. Then, if @is_first is TRUE, lookup_attr() begins the search with
* @attr. If @is_first is FALSE, lookup_attr() begins the search after @attr.
* This is so that, after the first call to lookup_attr(), we can call
* lookup_attr() again, without any modification of the search context, to
* automagically get the next matching attribute.
*
* In contrast, find_attr() ignores @is_first and always begins the search with
* @attr. find_attr() shouldn't really be called directly; it is just for
* internal use. FIXME: Might want to change this behaviour later, but not
* before I am finished with lookup_external_attr(). (AIA)
*/
typedef struct {
u8 *base;
MFT_RECORD *mrec;
ATTR_RECORD *attr;
u8 *alist_val_base;
MFT_RECORD *alist_mrec;
ATTR_RECORD *alist_attr;
ATTR_LIST_ENTRY *alist_val;
ATTR_LIST_ENTRY *alist_val_end;
u32 alist_val_len;
IS_FIRST_BOOL is_first;
u8 *alist_old_base;
} attr_search_context;
BOOL find_attr(const ntfs_volume *vol, const ATTR_TYPES type,
const wchar_t *name, const u32 name_len,
const IGNORE_CASE_BOOL ic, const u8 *val, const u32 val_len,
ntfs_attr_search_ctx *ctx)
{
ATTR_RECORD *a;
#ifdef DEBUG
if (!vol || !ctx || !ctx->mrec || !ctx->attr) {
printf(stderr, "find_attr() received NULL pointer!\n");
return FALSE;
}
#endif
a = ctx->attr;
/*
* Iterate over attributes in mft record starting at @ctx->attr.
* Note: Not using while/do/for loops so the comparison code
* does not get indented out of the 80 characters wide screen... (AIA)
*/
goto search_loop;
do_next:
a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length));
if (a < ctx->mrec || a > (char*)ctx->mrec + vol->mft_record_size)
goto file_corrupt;
ctx->attr = a;
search_loop:
/* 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 do_next;
/* If no @name is specified, check for @val. */
if (!name) {
register int rv;
/* If no @val specified, we are done. */
if (!val) {
found_it:
return TRUE;
}
rv = memcmp(val, (char*)a + le16_to_cpu(a->value_offset),
min(val_len, le32_to_cpu(a->value_length)));
/* If @val collates after the current attribute's value,
continue searching as a matching attribute might follow. */
if (!rv) {
register u32 avl = le32_to_cpu(a->value_length);
if (val_len == avl)
goto found_it;
if (val_len > avl)
goto do_next;
} else if (rv > 0)
goto do_next;
goto not_found;
}
if (ntfs_are_names_equal(name, name_len,
(wchar_t*)((char*)a + le16_to_cpu(a->name_offset)),
a->name_length, ic, vol->upcase, vol->upcase_len))
goto found_it;
{ register int rc = ntfs_collate_names(vol->upcase,
vol->upcase_len, name, name_len,
(wchar_t*)((char*)a + le16_to_cpu(a->name_offset)),
a->name_length, IGNORE_CASE, 1);
/* If case insensitive collation of names collates @name
before a->name, there is no matching attribute. */
if (rc == -1)
goto not_found;
/* If the strings are not equal, continue search. */
if (rc)
goto do_next;
}
/* If case sensitive collation of names doesn't collate @name before
a->name, we continue the search. Otherwise we haven't found it. */
if (ntfs_collate_names(vol->upcase, vol->upcase_len, name, name_len,
(wchar_t*)((char*)a + le16_to_cpu(a->name_offset)),
a->name_length, CASE_SENSITIVE, 1) != -1)
goto do_next;
not_found:
return FALSE;
file_corrupt:
#ifdef DEBUG
printf(stderr, "find_attr(): File is corrupt. Run chkdsk.\n");
#endif
goto not_found;
}
BOOL lookup_external_attr(const ntfs_volume *vol, const MFT_REFERENCE mref,
const ATTR_TYPES type, const wchar_t *name,
const u32 name_len, const IGNORE_CASE_BOOL ic,
const s64 lowest_vcn, const u8 *val,
const u32 val_len, ntfs_attr_search_ctx *ctx)
{
ATTR_LIST_ENTRY *al_pos, **al_val, *al_val_start, *al_next_pos;
ATTR_RECORD *attr_pos;
MFT_RECORD *mrec, *m;
u8 var1 = 0;
u8 var2 = 0;
u8 var3;
int rc;
wchar_t *al_name;
u32 al_name_len;
al_val = &ctx->alist_val;
if (ctx->alist_val_end <= *al_val && !ctx->is_first)
goto file_corrupt;
al_val_start = 0;
if (ctx->base) {
if (ctx->is_first)
goto already_have_the_base_and_is_first;
al_val_start = *al_val;
al_pos = (char*)*al_val + le16_to_cpu((*al_val)->length);
} else
al_pos = *al_val;
do_next:
if (al_pos < ctx->alist_val_end)
goto al_pos_below_alist_val_end;
var1 = var2 = 1;
al_pos = *al_val;
do_next_2:
*al_val = al_pos;
if (!type || var1 || type == al_pos->type)
goto compare_names;
if (le32_to_cpu(al_pos->type) > le32_to_cpu(type))
goto gone_too_far;
al_pos = al_next_pos;
goto do_next;
already_have_the_base_and_is_first:
ctx->is_first = FALSE;
if (*al_val < ctx->alist_val_end)
goto do_next;
if (ctx->base) {
// FIXME: CcUnpinData(ctx->base);
ctx->base = NULL;
}
if (!type)
return FALSE;
if (ntfs_read_file_record(vol, mref, &ctx->mrec, &ctx->attr) < 0)
return FALSE;
ctx->base = ctx->mrec;
find_attr(vol, type, name, name_len, ic, val, val_len, ctx);
return FALSE;
al_pos_below_alist_val_end:
if (al_pos < ctx->alist_val)
goto file_corrupt;
if (al_pos >= ctx->alist_val_end)
goto file_corrupt;
if (!al_pos->length)
goto file_corrupt;
al_next_pos = (ATTR_LIST_ENTRY*)((char*)al_pos +
le16_to_cpu(al_pos->length));
goto do_next_2;
gone_too_far:
var1 = 1;
compare_names:
al_name_len = al_pos->name_length;
al_name = (wchar_t*)((char*)al_pos + al_pos->name_offset);
if (!name || var1)
goto compare_lowest_vcn;
if (ic == CASE_SENSITIVE) {
if (name_len == al_name_len &&
!memcmp(al_name, name, al_name_len << 1))
rc = TRUE;
else
rc = FALSE;
} else /* IGNORE_CASE */
rc = ntfs_are_names_equal(al_name, al_name_len, name, name_len,
ic, vol->upcase, vol->upcase_len);
if (rc)
goto compare_lowest_vcn;
rc = ntfs_collate_names(vol->upcase, vol->upcase_len, name, name_len,
al_name, al_name_len, IGNORE_CASE, 1);
if (rc == -1)
goto name_collates_before_al_name;
if (!rc && ntfs_collate_names(vol->upcase, vol->upcase_len, name,
name_len, al_name, al_name_len,
IGNORE_CASE, 0) == -1)
goto name_collates_before_al_name;
al_pos = al_next_pos;
goto do_next;
name_collates_before_al_name:
var1 = 1;
compare_lowest_vcn:
if (lowest_vcn && !var1 && al_next_pos < ctx->alist_val_end &&
sle64_to_cpu(al_next_pos->lowest_vcn) <= sle64_to_cpu(lowest_vcn) &&
al_next_pos->type == al_pos->type &&
al_next_pos->name_length == al_name_len &&
!memcmp((char*)al_next_pos + al_next_pos->name_offset, al_name,
al_name_len << 1)) {
al_pos = al_next_pos;
goto do_next;
}
/* Don't mask the sequence number. If it isn't equal, the ref is stale.
*/
if (al_val_start &&
al_pos->mft_reference == al_val_start->mft_reference) {
mrec = ctx->mrec;
attr_pos = (ATTR_RECORD*)((char*)mrec +
le16_to_cpu(mrec->attrs_offset));
} else {
if (ctx->base) {
// FIXME: CcUnpinData(ctx->base);
ctx->base = 0;
}
if (ntfs_read_file_record(vol,
le64_to_cpu(al_pos->mft_reference),
&m, &attr_pos) < 0)
return FALSE;
mrec = ctx->mrec;
ctx->base = ctx->mrec = m;
}
var3 = 0;
do_next_attr_loop_start:
if (attr_pos < mrec || attr_pos > (char*)mrec + vol->mft_record_size)
goto file_corrupt;
if (attr_pos->type == AT_END)
goto do_next_al_entry;
if (!attr_pos->length)
goto file_corrupt;
if (al_pos->instance != attr_pos->instance)
goto do_next_attr;
if (al_pos->type != attr_pos->type)
goto do_next_al_entry;
if (!name)
goto skip_name_comparison;
if (attr_pos->name_length != al_name_len)
goto do_next_al_entry;
if (memcmp((wchar_t*)((char*)attr_pos +
le16_to_cpu(attr_pos->name_offset)), al_name,
attr_pos->name_length << 1))
goto do_next_al_entry;
skip_name_comparison:
var3 = 1;
ctx->attr = attr_pos;
if (var1)
goto loc_5217c;
if (!val)
return TRUE;
if (attr_pos->non_resident)
goto do_next_attr;
if (le32_to_cpu(attr_pos->value_length) != val_len)
goto do_next_attr;
if (!memcmp((char*)attr_pos + le16_to_cpu(attr_pos->value_offset),
val, val_len))
return TRUE;
do_next_attr:
attr_pos = (ATTR_RECORD*)((char*)attr_pos +
le32_to_cpu(attr_pos->length));
goto do_next_attr_loop_start;
do_next_al_entry:
if (!var3)
goto file_corrupt;
al_pos = (ATTR_RECORD*)((char*)al_pos + le16_to_cpu(al_pos->length));
goto do_next;
loc_5217c:
if (var2)
*al_val = (ATTR_RECORD*)((char*)al_pos +
le16_to_cpu(al_pos->length));
if (ctx->base) {
// FIXME: CcUnpinData(ctx->base);
ctx->base = 0;
}
if (!type)
return FALSE;
if (ntfs_read_file_record(vol, mref, &mrec, &ctx->attr) < 0)
return FALSE;
ctx->base = mrec;
find_attr(vol, type, name, name_len, ic, val, val_len, ctx);
return FALSE;
file_corrupt:
#ifdef DEBUG
fprintf(stderr, "lookup_attr() encountered corrupt file record.\n");
#endif
return FALSE;
}
BOOL lookup_attr(const ntfs_volume *vol, const MFT_REFERENCE *mref,
const ATTR_TYPES type, const wchar_t *name,
const u32 name_len, const IGNORE_CASE_BOOL ic,
const s64 lowest_vcn, const u8 *val, const u32 val_len,
ntfs_attr_search_ctx *ctx)
{
MFT_RECORD *m;
ATTR_RECORD *a;
s64 len;
if (!vol || !ctx) {
#ifdef DEBUG
printf(stderr, "lookup_attr() received NULL pointer!\n");
#endif
return FALSE;
}
if (ctx->base)
goto already_have_the_base;
if (ntfs_read_file_record(vol, mref, &m, &a) < 0)
return FALSE;
ctx->base = ctx->mrec = m;
ctx->attr = a;
ctx->alist_mrec = ctx->alist_attr = ctx->alist_val = NULL;
/*
* Look for an attribute list and at the same time check for attributes
* which collate before the attribute list (i.e. $STANDARD_INFORMATION).
*/
if (le32_to_cpu(a->type) > le32_to_cpu(AT_ATTRIBUTE_LIST))
goto no_attr_list;
do_next:
if (!a->length)
goto file_corrupt;
if (a->type == AT_ATTRIBUTE_LIST)
goto attr_list_present;
a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length));
if (a < m || a > (char*)m + vol->mft_record_size)
goto file_corrupt;
if (le32_to_cpu(a->type) <= le32_to_cpu(AT_ATTRIBUTE_LIST))
goto do_next;
no_attr_list:
if (!type || type == AT_STANDARD_INFORMATION &&
a->type == AT_STANDARD_INFORMATION)
goto found_it;
call_find_attr:
return find_attr(vol, type, name, name_len, ic, val, val_len, ctx);
found_it:
ctx->attr = a;
return TRUE;
already_have_the_base:
/*
* If ctx->is_first, search starting with ctx->attr. Otherwise
* continue search after ctx->attr.
*/
if (ctx->is_first) {
a = ctx->attr;
ctx->is_first = 0;
} else
a = (ATTR_RECORD*)((char*)ctx->attr +
le32_to_cpu(ctx->attr->length));
if (a < m || a > (char*)m + vol->mft_record_size)
goto file_corrupt;
if (a->type == AT_END)
return FALSE;
if (!a->length)
goto file_corrupt;
if (type)
goto call_find_attr;
goto found_it;
attr_list_present:
/*
* Looking for zero means we return the first attribute, which will
* be the first one listed in the attribute list.
*/
ctx->attr = a;
if (!type)
goto search_attr_list;
if (type == AT_ATTRIBUTE_LIST)
return TRUE;
search_attr_list:
/*
* "a" contains the attribute list attribute at this stage.
*/
ctx->alist_attr = a;
len = get_attribute_value_length(a);
#ifdef DEBUG
if (len > 0x40000LL) {
printf(stderr, "lookup_attr() found corrupt attribute list.\n");
return FALSE;
}
#endif
ctx->alist_val_len = len;
if (!(ctx->alist_val = malloc(ctx->alist_val_len))) {
#ifdef DEBUG
printf(stderr, "lookup_attr() failed to allocate memory for "
"attribute list value.\n");
#endif
return FALSE;
}
if (get_attribute_value(vol, ctx->mrec, a, ctx->alist_val) !=
ctx->alist_val_len) {
#ifdef DEBUG
printf(stderr, "lookup_attr() failed to read attribute list "
"value.\n");
#endif
return FALSE;
}
ctx->alist_val_end = (char*)ctx->alist_val + ctx->alist_val_len;
if (a->non_resident) {
ctx->alist_old_base = ctx->alist_val_base;
ctx->alist_val_base = ctx->base;
ctx->base = NULL;
} else if (ctx->base) {
// FIXME: CcUnpinData(ctx->base);
ctx->base = NULL;
}
lookup_external:
return lookup_external_attr(vol, mref, type, name, name_len, ic,
lowest_vcn, val, val_len, ctx);
file_corrupt:
#ifdef DEBUG
fprintf(stderr, "lookup_attr() encountered corrupt file record.\n");
#endif
return FALSE;
}