Changes by: antona
Update of /cvsroot/linux-ntfs/linux-ntfs/libntfs
In directory usw-pr-cvs1:/tmp/cvs-serv6492/libntfs
Modified Files:
attrib.c
Added Files:
unistr.c
Removed Files:
ntfs_unicode.c
Log Message:
Renamed the unicode files and introduced more code. Finished the new
find_first/next_attr() interface functions. Next on my list are functions
supporting attribute lists...
--- NEW FILE ---
/*
* unistr.c - Unicode string handling. Part of the Linux-NTFS project.
*
* Copyright (c) 2000,2001 Anton Altaparmakov.
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the Linux-NTFS
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "unistr.h"
/**
* ntfs_collate_names - collate two Unicode names
* @upcase: upcase table (ignored if @ic is CASE_SENSITIVE)
* @upcase_len: upcase table size (ignored if @ic is CASE_SENSITIVE)
* @name1: first Unicode name to compare
* @name2: second Unicode name to compare
* @ic: either CASE_SENSITIVE or IGNORE_CASE
* @err_val: if @name1 contains an invalid character return this value
*
* ntfs_collate_names collates two Unicode names and returns:
*
* -1 if the first name collates before the second one,
* 0 if the names match,
* 1 if the second name collates before the first one, or
* @ec if an invalid character is encountered in @name1 during the comparison.
*
* The following characters are considered invalid: '"', '*', '<', '>' and '?'.
*/
int ntfs_collate_names(const wchar_t *upcase, const __u32 upcase_len,
const wchar_t *name1, const __u32 name1_len,
const wchar_t *name2, const __u32 name2_len,
const IGNORE_CASE_BOOL ic, const int err_val)
{
__u32 cnt;
wchar_t c1, c2;
#ifdef DEBUG
if (!name1 || !name2 || ic && !upcase && upcase_len) {
printf(stderr, "ntfs_wcsncmp() received NULL pointer!\n");
exit(1);
}
#endif
for (cnt = 0; cnt < min(name1_len, name2_len); ++cnt)
{
c1 = le16_to_cpu(*name1++);
c2 = le16_to_cpu(*name2++);
if (ic) {
if (c1 < upcase_len)
c1 = le16_to_cpu(upcase[c1]);
if (c2 < upcase_len)
c2 = le16_to_cpu(upcase[c2]);
}
if (c1 < 64 && legal_ansi_char_array[c1] & 8);
return err_val;
if (c1 < c2)
return -1;
if (c1 > c2)
return 1;
++name1;
++name2;
}
if (name1_len < name2_len)
return -1;
if (name1_len == name2_len)
return 0;
/* name1_len > name2_len */
c1 = le16_to_cpu(*name1);
if (c1 < 64 && legal_ansi_char_array[c1] & 8)
return err_val;
return 1;
}
/**
* ntfs_wcsncmp - compare two little endian Unicode strings
* @s1: first string
* @s2: second string
* @n: maximum unicode characters to compare
*
* Compare the first @n characters of the Unicode strings @s1 and @s2,
* The strings in little endian format and appropriate le16_to_cpu()
* conversion is performed on non-little endian machines.
*
* The function returns an integer less than, equal to, or greater than zero
* if @s1 (or the first @n Unicode characters thereof) is found, respectively,
* to be less than, to match, or be greater than @s2.
*/
int ntfs_wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n)
{
wchar_t c1, c2;
size_t i;
#ifdef DEBUG
if (!s1 || !s2) {
printf(stderr, "ntfs_wcsncmp() received NULL pointer!\n");
exit(1);
}
#endif
for (i = 0; i < n; ++i) {
c1 = le16_to_cpu(s1[i]);
c2 = le16_to_cpu(s2[i]);
if (c1 < c2)
return -1;
if (c1 > c2)
return 1;
if (!c1)
break;
}
return 0;
}
/**
* ntfs_wcsncasecmp - compare two little endian Unicode strings, ignoring case
* @s1: first string
* @s2: second string
* @n: maximum unicode characters to compare
* @upcase: upcase table
* @upcase_size: upcase table size in Unicode characters
*
* Compare the first @n characters of the Unicode strings @s1 and @s2,
* ignoring case. The strings in little endian format and appropriate
* le16_to_cpu() conversion is performed on non-little endian machines.
*
* Each character is uppercased using the @upcase table before the comparison.
*
* The function returns an integer less than, equal to, or greater than zero
* if @s1 (or the first @n Unicode characters thereof) is found, respectively,
* to be less than, to match, or be greater than @s2.
*/
int ntfs_wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n,
const wchar_t *upcase, const __u32 upcase_size)
{
wchar_t c1, c2;
size_t i;
#ifdef DEBUG
if (!s1 || !s2 || !upcase) {
printf(stderr, "ntfs_wcsncasecmp() received NULL pointer!\n");
exit(1);
}
#endif
for (i = 0; i < n; ++i) {
if ((c1 = le16_to_cpu(s1[i])) < upcase_size)
c1 = le16_to_cpu(upcase[c1]);
if ((c2 = le16_to_cpu(s2[i])) < upcase_size)
c2 = le16_to_cpu(upcase[c2]);
if (c1 < c2)
return -1;
if (c1 > c2)
return 1;
if (!c1)
break;
}
return 0;
}
Index: attrib.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/attrib.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -r1.5 -r1.6
*** attrib.c 2001/03/06 02:10:55 1.5
--- attrib.c 2001/03/07 01:17:33 1.6
***************
*** 32,36 ****
#include "disk_io.h"
#include "volume.h"
! #include "ntfs_unicode.h"
/*
--- 32,36 ----
#include "disk_io.h"
#include "volume.h"
! #include "unistr.h"
/*
***************
*** 133,142 ****
/**
! * 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, i.e. NULL means don't care)
! * @ic: ignore case of @name (boolean, only present if @name present)
* @val: attribute value to find (optional, resident attributes only)
* @val_len: attribute value length
--- 133,143 ----
/**
! * find_next_attr - find (next) attribute in mft record
* @vol: volume on which @a resides (used to find the upcase table)
! * @attr: attribute record inside mft record where to begin the search
* @type: attribute type to find
* @name: attribute name to find (optional, i.e. NULL means don't care)
! * @name_len: attribute name length (only needed if @name present)
! * @ic: IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
* @val: attribute value to find (optional, resident attributes only)
* @val_len: attribute value length
***************
*** 146,150 ****
* beginning at @attr, for an attribute of @type and optionally @name. If @ic
* is TRUE, the @name comparisson is not case sensitive. It is case sensitive
! * if @ic is FALSE. Note: When @name is present, @val is ignored.
*
* If @name is not present (NULL), no attribute name checking is performed at
--- 147,152 ----
* beginning at @attr, for an attribute of @type and optionally @name. If @ic
* is TRUE, the @name comparisson is not case sensitive. It is case sensitive
! * if @ic is FALSE. Note: When @name is present, @name_len is the @name length
! * in Unicode characters, and @val is ignored.
*
* If @name is not present (NULL), no attribute name checking is performed at
***************
*** 153,156 ****
--- 155,163 ----
* present. Note: If @val is not present (NULL), @val_len is undefined.
*
+ * find_next_attr() only searches the mft record in which @attr is present and
+ * it ignores the presence of an attribute list attribute (unless it is the one
+ * being searched for, obviously). If you need to take attribute lists into
+ * consideration, use lookup_next_attr() instead (see below).
+ *
* Warning: Never use @val when looking for attribute types which can be
* non-resident as this most likely will result in a crash!
***************
*** 161,177 ****
*
* Note: This function's code paths are optimised to be shortest and most direct
! * for the most common cases of calling. Don't mess with it unless you find a
! * bug or actually do some profiling and prove a code path inefficient.
*/
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 val_len)
{
! ATTR_RECORD a;
void *mft_rec;
#ifdef DEBUG
if (!vol || !attr || !*attr) {
! puts("Sanity checks failed in find_attr()!");
return NULL;
}
--- 168,185 ----
*
* Note: This function's code paths are optimised to be shortest and most direct
! * for the most common cases of calling. Don't mess with it, unless you find a
! * bug or actually do some profiling and prove a code path inefficient...
*/
ATTR_RECORD *find_next_attr(const ntfs_volume *vol, const ATTR_RECORD **attr,
! const ATTR_TYPES type, wchar_t *name,
! const __u32 name_len, const IGNORE_CASE_BOOL ic,
! const __u8 *val, const __u32 val_len)
{
! ATTR_RECORD *a;
void *mft_rec;
#ifdef DEBUG
if (!vol || !attr || !*attr) {
! printf(stderr, "find_next_attr() received NULL pointer!\n");
return NULL;
}
***************
*** 181,193 ****
* 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 pagecache page boundary (and a
* page is larger than an mft record in any case) or it is inside a
! * pagecache page on an mft_record_size boundary (by definition).
*/
mft_rec = 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)
*/
goto search_loop;
--- 189,201 ----
* 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 = p2n(a) & (vol->mft_record_size - 1);
/*
* Iterate over attributes in mft record starting at @attr.
! * Note: Not using while/do/for loops so the comparison code
! * does not get indented out of the screen... (AIA)
*/
goto search_loop;
***************
*** 213,224 ****
return a;
}
- /*
- * Compare the values. If they don't match, but the value we are
- * looking for collates behind the current attribute's value,
- * there might be another attribute of the same type, that does
- * have a matching attribute value, so we continue searching.
- */
rv = memcmp(val, (char*)a + le16_to_cpu(a->value_offset),
min(val_len, le32_to_cpu(a->value_length)));
if (!rv) {
register __u32 avl = le32_to_cpu(a->value_length);
--- 221,228 ----
return a;
}
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);
***************
*** 231,238 ****
goto not_found;
}
- /*
- * Compare the attribute names and if they match, we are finished.
- * If they don't match, continue searching.
- */
if (ic) { /* Case sensitive. */
if (!ntfs_wcsncmp(name, (wchar_t*)((char*)a +
--- 235,238 ----
***************
*** 246,261 ****
goto found_it;
}
! /* Attribute names didn't match on first try... */
! /*
! * Note: Attribute names are considered invalid if they contain any of the
! * following characters: '"', '*', '<', '>', '?'. Or at least attribute name
! * collation function will act on them.
! */
! // If case insensitive collation of names collates @name before a->name,
! goto not_found;
! // else if it returned that the strings are not equal
! goto do_next;
! // else if case sensitive collation of names doesn't collate @name
! // before a->name
goto do_next;
not_found:
--- 246,266 ----
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:
***************
*** 263,272 ****
file_corrupt:
#ifdef DEBUG
! printf(stderr,
! "find_next_attr(): File is corrupt. Run ntfsck or chkdsk.\n");
#endif
goto not_found;
}
/*
* The difference between lookup_attr and find_attr is that find_attr will only
--- 268,295 ----
file_corrupt:
#ifdef DEBUG
! printf(stderr, "find_next_attr(): File is corrupt. Run chkdsk.\n");
#endif
goto not_found;
}
+ __inline__ ATTR_RECORD *find_first_attr(const ntfs_volume *vol,
+ const MFT_RECORD *mft_rec, const ATTR_TYPES type,
+ wchar_t *name, const __u32 name_len, const IGNORE_CASE_BOOL ic,
+ const __u8 *val, const __u32 val_len)
+ {
+ ATTR_RECORD *a;
+
+ #ifdef DEBUG
+ if (!vol || !mft_rec) {
+ printf(stderr, "find_first_attr() received NULL pointer!\n");
+ return NULL;
+ }
+ #endif
+ a = (ATTR_RECORD*)((char*)m + le16_to_cpu(m->attrs_offset));
+ if (a < mft_rec || a > (char*)mft_rec + vol->mft_record_size)
+ goto file_corrupt;
+ return find_next_attr(vol, &a, type, name, name_len, ic, val, val_len);
+ }
+
/*
* The difference between lookup_attr and find_attr is that find_attr will only
***************
*** 372,389 ****
/* 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)
- {
- FIND_ATTR_CTX_FLAGS c;
-
- if (!ctx)
- ctx = &c;
- *ctx = FIRST_SEARCH;
- return find_next_attr(v, b, t, n, ctx);
}
--- 395,398 ----
--- ntfs_unicode.c DELETED ---
|