19663SMark.Logan@Sun.COM /** 29663SMark.Logan@Sun.COM * collate.c - NTFS collation handling. Part of the Linux-NTFS project. 39663SMark.Logan@Sun.COM * 49663SMark.Logan@Sun.COM * Copyright (c) 2004 Anton Altaparmakov 59663SMark.Logan@Sun.COM * Copyright (c) 2005 Yura Pakhuchiy 69663SMark.Logan@Sun.COM * 79663SMark.Logan@Sun.COM * This program/include file is free software; you can redistribute it and/or 89663SMark.Logan@Sun.COM * modify it under the terms of the GNU General Public License as published 99663SMark.Logan@Sun.COM * by the Free Software Foundation; either version 2 of the License, or 109663SMark.Logan@Sun.COM * (at your option) any later version. 119663SMark.Logan@Sun.COM * 129663SMark.Logan@Sun.COM * This program/include file is distributed in the hope that it will be 139663SMark.Logan@Sun.COM * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 149663SMark.Logan@Sun.COM * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 159663SMark.Logan@Sun.COM * GNU General Public License for more details. 169663SMark.Logan@Sun.COM * 179663SMark.Logan@Sun.COM * You should have received a copy of the GNU General Public License 189663SMark.Logan@Sun.COM * along with this program (in the main directory of the Linux-NTFS 199663SMark.Logan@Sun.COM * distribution in the file COPYING); if not, write to the Free Software 209663SMark.Logan@Sun.COM * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 219663SMark.Logan@Sun.COM */ 229663SMark.Logan@Sun.COM 239663SMark.Logan@Sun.COM #ifdef HAVE_CONFIG_H 249663SMark.Logan@Sun.COM #include "config.h" 259663SMark.Logan@Sun.COM #endif 269663SMark.Logan@Sun.COM 279663SMark.Logan@Sun.COM #ifdef HAVE_STRING_H 289663SMark.Logan@Sun.COM #include <string.h> 299663SMark.Logan@Sun.COM #endif 309663SMark.Logan@Sun.COM 31*10214SMark.Logan@Sun.COM #include "compat.h" 329663SMark.Logan@Sun.COM #include "collate.h" 339663SMark.Logan@Sun.COM #include "debug.h" 349663SMark.Logan@Sun.COM #include "unistr.h" 359663SMark.Logan@Sun.COM #include "logging.h" 369663SMark.Logan@Sun.COM 379663SMark.Logan@Sun.COM /** 389663SMark.Logan@Sun.COM * ntfs_collate_binary - Which of two binary objects should be listed first 399663SMark.Logan@Sun.COM * @vol: unused 409663SMark.Logan@Sun.COM * @data1: 419663SMark.Logan@Sun.COM * @data1_len: 429663SMark.Logan@Sun.COM * @data2: 439663SMark.Logan@Sun.COM * @data2_len: 449663SMark.Logan@Sun.COM * 459663SMark.Logan@Sun.COM * Description... 469663SMark.Logan@Sun.COM * 479663SMark.Logan@Sun.COM * Returns: 489663SMark.Logan@Sun.COM */ 499663SMark.Logan@Sun.COM static int ntfs_collate_binary(ntfs_volume *vol __attribute__((unused)), 509663SMark.Logan@Sun.COM const void *data1, size_t data1_len, 519663SMark.Logan@Sun.COM const void *data2, size_t data2_len) 529663SMark.Logan@Sun.COM { 539663SMark.Logan@Sun.COM int rc; 549663SMark.Logan@Sun.COM 559663SMark.Logan@Sun.COM ntfs_log_trace("Entering.\n"); 569663SMark.Logan@Sun.COM rc = memcmp(data1, data2, min(data1_len, data2_len)); 579663SMark.Logan@Sun.COM if (!rc && (data1_len != data2_len)) { 589663SMark.Logan@Sun.COM if (data1_len < data2_len) 599663SMark.Logan@Sun.COM rc = -1; 609663SMark.Logan@Sun.COM else 619663SMark.Logan@Sun.COM rc = 1; 629663SMark.Logan@Sun.COM } 639663SMark.Logan@Sun.COM ntfs_log_trace("Done, returning %i.\n", rc); 649663SMark.Logan@Sun.COM return rc; 659663SMark.Logan@Sun.COM } 669663SMark.Logan@Sun.COM 679663SMark.Logan@Sun.COM /** 689663SMark.Logan@Sun.COM * ntfs_collate_ntofs_ulong - Which of two long ints should be listed first 699663SMark.Logan@Sun.COM * @vol: unused 709663SMark.Logan@Sun.COM * @data1: 719663SMark.Logan@Sun.COM * @data1_len: 729663SMark.Logan@Sun.COM * @data2: 739663SMark.Logan@Sun.COM * @data2_len: 749663SMark.Logan@Sun.COM * 759663SMark.Logan@Sun.COM * Description... 769663SMark.Logan@Sun.COM * 779663SMark.Logan@Sun.COM * Returns: 789663SMark.Logan@Sun.COM */ 799663SMark.Logan@Sun.COM static int ntfs_collate_ntofs_ulong(ntfs_volume *vol __attribute__((unused)), 809663SMark.Logan@Sun.COM const void *data1, size_t data1_len, 819663SMark.Logan@Sun.COM const void *data2, size_t data2_len) 829663SMark.Logan@Sun.COM { 839663SMark.Logan@Sun.COM int rc; 849663SMark.Logan@Sun.COM u32 d1, d2; 859663SMark.Logan@Sun.COM 869663SMark.Logan@Sun.COM ntfs_log_trace("Entering.\n"); 879663SMark.Logan@Sun.COM if (data1_len != data2_len || data1_len != 4) { 889663SMark.Logan@Sun.COM ntfs_log_error("data1_len or/and data2_len not equal to 4.\n"); 899663SMark.Logan@Sun.COM return NTFS_COLLATION_ERROR; 909663SMark.Logan@Sun.COM } 919663SMark.Logan@Sun.COM d1 = le32_to_cpup(data1); 929663SMark.Logan@Sun.COM d2 = le32_to_cpup(data2); 939663SMark.Logan@Sun.COM if (d1 < d2) 949663SMark.Logan@Sun.COM rc = -1; 959663SMark.Logan@Sun.COM else { 969663SMark.Logan@Sun.COM if (d1 == d2) 979663SMark.Logan@Sun.COM rc = 0; 989663SMark.Logan@Sun.COM else 999663SMark.Logan@Sun.COM rc = 1; 1009663SMark.Logan@Sun.COM } 1019663SMark.Logan@Sun.COM ntfs_log_trace("Done, returning %i.\n", rc); 1029663SMark.Logan@Sun.COM return rc; 1039663SMark.Logan@Sun.COM } 1049663SMark.Logan@Sun.COM 1059663SMark.Logan@Sun.COM /** 1069663SMark.Logan@Sun.COM * ntfs_collate_file_name - Which of two filenames should be listed first 1079663SMark.Logan@Sun.COM * @vol: 1089663SMark.Logan@Sun.COM * @data1: 1099663SMark.Logan@Sun.COM * @data1_len: unused 1109663SMark.Logan@Sun.COM * @data2: 1119663SMark.Logan@Sun.COM * @data2_len: unused 1129663SMark.Logan@Sun.COM * 1139663SMark.Logan@Sun.COM * Description... 1149663SMark.Logan@Sun.COM * 1159663SMark.Logan@Sun.COM * Returns: 1169663SMark.Logan@Sun.COM */ 1179663SMark.Logan@Sun.COM static int ntfs_collate_file_name(ntfs_volume *vol, 1189663SMark.Logan@Sun.COM const void *data1, size_t data1_len __attribute__((unused)), 1199663SMark.Logan@Sun.COM const void *data2, size_t data2_len __attribute__((unused))) 1209663SMark.Logan@Sun.COM { 1219663SMark.Logan@Sun.COM int rc; 1229663SMark.Logan@Sun.COM 1239663SMark.Logan@Sun.COM ntfs_log_trace("Entering.\n"); 1249663SMark.Logan@Sun.COM rc = ntfs_file_values_compare(data1, data2, NTFS_COLLATION_ERROR, 1259663SMark.Logan@Sun.COM IGNORE_CASE, vol->upcase, vol->upcase_len); 1269663SMark.Logan@Sun.COM if (!rc) 1279663SMark.Logan@Sun.COM rc = ntfs_file_values_compare(data1, data2, 1289663SMark.Logan@Sun.COM NTFS_COLLATION_ERROR, CASE_SENSITIVE, 1299663SMark.Logan@Sun.COM vol->upcase, vol->upcase_len); 1309663SMark.Logan@Sun.COM ntfs_log_trace("Done, returning %i.\n", rc); 1319663SMark.Logan@Sun.COM return rc; 1329663SMark.Logan@Sun.COM } 1339663SMark.Logan@Sun.COM 1349663SMark.Logan@Sun.COM typedef int (*ntfs_collate_func_t)(ntfs_volume *, const void *, size_t, 1359663SMark.Logan@Sun.COM const void *, size_t); 1369663SMark.Logan@Sun.COM 1379663SMark.Logan@Sun.COM static ntfs_collate_func_t ntfs_do_collate0x0[3] = { 1389663SMark.Logan@Sun.COM ntfs_collate_binary, 1399663SMark.Logan@Sun.COM ntfs_collate_file_name, 1409663SMark.Logan@Sun.COM NULL/*ntfs_collate_unicode_string*/, 1419663SMark.Logan@Sun.COM }; 1429663SMark.Logan@Sun.COM 1439663SMark.Logan@Sun.COM static ntfs_collate_func_t ntfs_do_collate0x1[4] = { 1449663SMark.Logan@Sun.COM ntfs_collate_ntofs_ulong, 1459663SMark.Logan@Sun.COM NULL/*ntfs_collate_ntofs_sid*/, 1469663SMark.Logan@Sun.COM NULL/*ntfs_collate_ntofs_security_hash*/, 1479663SMark.Logan@Sun.COM NULL/*ntfs_collate_ntofs_ulongs*/, 1489663SMark.Logan@Sun.COM }; 1499663SMark.Logan@Sun.COM 1509663SMark.Logan@Sun.COM /** 1519663SMark.Logan@Sun.COM * ntfs_is_collation_rule_supported - Check if a collation rule is implemented. 1529663SMark.Logan@Sun.COM * @cr: The to-be-checked collation rule 1539663SMark.Logan@Sun.COM * 1549663SMark.Logan@Sun.COM * Use this function to know if @cr is supported by libntfs. 1559663SMark.Logan@Sun.COM * 1569663SMark.Logan@Sun.COM * 7 collation rules are known to be supported by NTFS as defined 1579663SMark.Logan@Sun.COM * in layout.h. However, libntfs only support 3 of them ATM. 1589663SMark.Logan@Sun.COM * 1599663SMark.Logan@Sun.COM * Return TRUE if @cr is supported. FALSE otherwise. 1609663SMark.Logan@Sun.COM */ 1619663SMark.Logan@Sun.COM BOOL ntfs_is_collation_rule_supported(COLLATION_RULES cr) 1629663SMark.Logan@Sun.COM { 1639663SMark.Logan@Sun.COM return (cr == COLLATION_BINARY || cr == COLLATION_NTOFS_ULONG || 1649663SMark.Logan@Sun.COM cr == COLLATION_FILE_NAME); 1659663SMark.Logan@Sun.COM /* 1669663SMark.Logan@Sun.COM * FIXME: At the moment we only support COLLATION_BINARY, 1679663SMark.Logan@Sun.COM * COLLATION_NTOFS_ULONG and COLLATION_FILE_NAME. 1689663SMark.Logan@Sun.COM * The correct future implementation of this function should be: 1699663SMark.Logan@Sun.COM * 1709663SMark.Logan@Sun.COM * u32 i = le32_to_cpu(cr); 1719663SMark.Logan@Sun.COM * return ((i <= 0x02) || ((i >= 0x10) && (i <= 0x13))); 1729663SMark.Logan@Sun.COM */ 1739663SMark.Logan@Sun.COM } 1749663SMark.Logan@Sun.COM 1759663SMark.Logan@Sun.COM /** 1769663SMark.Logan@Sun.COM * ntfs_collate - collate two data items using a specified collation rule 1779663SMark.Logan@Sun.COM * @vol: ntfs volume to which the data items belong 1789663SMark.Logan@Sun.COM * @cr: collation rule to use when comparing the items 1799663SMark.Logan@Sun.COM * @data1: first data item to collate 1809663SMark.Logan@Sun.COM * @data1_len: length in bytes of @data1 1819663SMark.Logan@Sun.COM * @data2: second data item to collate 1829663SMark.Logan@Sun.COM * @data2_len: length in bytes of @data2 1839663SMark.Logan@Sun.COM * 1849663SMark.Logan@Sun.COM * Collate the two data items @data1 and @data2 using the collation rule @cr 1859663SMark.Logan@Sun.COM * and return -1, 0, or 1 if @data1 is found, respectively, to collate before, 1869663SMark.Logan@Sun.COM * to match, or to collate after @data2. 1879663SMark.Logan@Sun.COM * 1889663SMark.Logan@Sun.COM * For speed we use the collation rule @cr as an index into two tables of 1899663SMark.Logan@Sun.COM * function pointers to call the appropriate collation function. 1909663SMark.Logan@Sun.COM * 1919663SMark.Logan@Sun.COM * Return NTFS_COLLATION_ERROR if error occurred. 1929663SMark.Logan@Sun.COM */ 1939663SMark.Logan@Sun.COM int ntfs_collate(ntfs_volume *vol, COLLATION_RULES cr, 1949663SMark.Logan@Sun.COM const void *data1, size_t data1_len, 1959663SMark.Logan@Sun.COM const void *data2, size_t data2_len) 1969663SMark.Logan@Sun.COM { 1979663SMark.Logan@Sun.COM u32 i; 1989663SMark.Logan@Sun.COM 1999663SMark.Logan@Sun.COM ntfs_log_trace("Entering.\n"); 2009663SMark.Logan@Sun.COM if (!vol || !data1 || !data2) { 2019663SMark.Logan@Sun.COM ntfs_log_error("Invalid arguments passed.\n"); 2029663SMark.Logan@Sun.COM return NTFS_COLLATION_ERROR; 2039663SMark.Logan@Sun.COM } 2049663SMark.Logan@Sun.COM 2059663SMark.Logan@Sun.COM if (!ntfs_is_collation_rule_supported(cr)) 2069663SMark.Logan@Sun.COM goto err; 2079663SMark.Logan@Sun.COM i = le32_to_cpu(cr); 2089663SMark.Logan@Sun.COM if (i <= 0x02) 2099663SMark.Logan@Sun.COM return ntfs_do_collate0x0[i](vol, data1, data1_len, 2109663SMark.Logan@Sun.COM data2, data2_len); 2119663SMark.Logan@Sun.COM if (i < 0x10) 2129663SMark.Logan@Sun.COM goto err; 2139663SMark.Logan@Sun.COM i -= 0x10; 2149663SMark.Logan@Sun.COM if (i <= 3) 2159663SMark.Logan@Sun.COM return ntfs_do_collate0x1[i](vol, data1, data1_len, 2169663SMark.Logan@Sun.COM data2, data2_len); 2179663SMark.Logan@Sun.COM err: 2189663SMark.Logan@Sun.COM ntfs_log_debug("Unknown collation rule.\n"); 2199663SMark.Logan@Sun.COM return NTFS_COLLATION_ERROR; 2209663SMark.Logan@Sun.COM } 221