1*9663SMark.Logan@Sun.COM /** 2*9663SMark.Logan@Sun.COM * collate.c - NTFS collation handling. Part of the Linux-NTFS project. 3*9663SMark.Logan@Sun.COM * 4*9663SMark.Logan@Sun.COM * Copyright (c) 2004 Anton Altaparmakov 5*9663SMark.Logan@Sun.COM * Copyright (c) 2005 Yura Pakhuchiy 6*9663SMark.Logan@Sun.COM * 7*9663SMark.Logan@Sun.COM * This program/include file is free software; you can redistribute it and/or 8*9663SMark.Logan@Sun.COM * modify it under the terms of the GNU General Public License as published 9*9663SMark.Logan@Sun.COM * by the Free Software Foundation; either version 2 of the License, or 10*9663SMark.Logan@Sun.COM * (at your option) any later version. 11*9663SMark.Logan@Sun.COM * 12*9663SMark.Logan@Sun.COM * This program/include file is distributed in the hope that it will be 13*9663SMark.Logan@Sun.COM * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 14*9663SMark.Logan@Sun.COM * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*9663SMark.Logan@Sun.COM * GNU General Public License for more details. 16*9663SMark.Logan@Sun.COM * 17*9663SMark.Logan@Sun.COM * You should have received a copy of the GNU General Public License 18*9663SMark.Logan@Sun.COM * along with this program (in the main directory of the Linux-NTFS 19*9663SMark.Logan@Sun.COM * distribution in the file COPYING); if not, write to the Free Software 20*9663SMark.Logan@Sun.COM * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21*9663SMark.Logan@Sun.COM */ 22*9663SMark.Logan@Sun.COM 23*9663SMark.Logan@Sun.COM #ifdef HAVE_CONFIG_H 24*9663SMark.Logan@Sun.COM #include "config.h" 25*9663SMark.Logan@Sun.COM #endif 26*9663SMark.Logan@Sun.COM 27*9663SMark.Logan@Sun.COM #ifdef HAVE_STRING_H 28*9663SMark.Logan@Sun.COM #include <string.h> 29*9663SMark.Logan@Sun.COM #endif 30*9663SMark.Logan@Sun.COM 31*9663SMark.Logan@Sun.COM #include "collate.h" 32*9663SMark.Logan@Sun.COM #include "debug.h" 33*9663SMark.Logan@Sun.COM #include "unistr.h" 34*9663SMark.Logan@Sun.COM #include "logging.h" 35*9663SMark.Logan@Sun.COM 36*9663SMark.Logan@Sun.COM /** 37*9663SMark.Logan@Sun.COM * ntfs_collate_binary - Which of two binary objects should be listed first 38*9663SMark.Logan@Sun.COM * @vol: unused 39*9663SMark.Logan@Sun.COM * @data1: 40*9663SMark.Logan@Sun.COM * @data1_len: 41*9663SMark.Logan@Sun.COM * @data2: 42*9663SMark.Logan@Sun.COM * @data2_len: 43*9663SMark.Logan@Sun.COM * 44*9663SMark.Logan@Sun.COM * Description... 45*9663SMark.Logan@Sun.COM * 46*9663SMark.Logan@Sun.COM * Returns: 47*9663SMark.Logan@Sun.COM */ 48*9663SMark.Logan@Sun.COM static int ntfs_collate_binary(ntfs_volume *vol __attribute__((unused)), 49*9663SMark.Logan@Sun.COM const void *data1, size_t data1_len, 50*9663SMark.Logan@Sun.COM const void *data2, size_t data2_len) 51*9663SMark.Logan@Sun.COM { 52*9663SMark.Logan@Sun.COM int rc; 53*9663SMark.Logan@Sun.COM 54*9663SMark.Logan@Sun.COM ntfs_log_trace("Entering.\n"); 55*9663SMark.Logan@Sun.COM rc = memcmp(data1, data2, min(data1_len, data2_len)); 56*9663SMark.Logan@Sun.COM if (!rc && (data1_len != data2_len)) { 57*9663SMark.Logan@Sun.COM if (data1_len < data2_len) 58*9663SMark.Logan@Sun.COM rc = -1; 59*9663SMark.Logan@Sun.COM else 60*9663SMark.Logan@Sun.COM rc = 1; 61*9663SMark.Logan@Sun.COM } 62*9663SMark.Logan@Sun.COM ntfs_log_trace("Done, returning %i.\n", rc); 63*9663SMark.Logan@Sun.COM return rc; 64*9663SMark.Logan@Sun.COM } 65*9663SMark.Logan@Sun.COM 66*9663SMark.Logan@Sun.COM /** 67*9663SMark.Logan@Sun.COM * ntfs_collate_ntofs_ulong - Which of two long ints should be listed first 68*9663SMark.Logan@Sun.COM * @vol: unused 69*9663SMark.Logan@Sun.COM * @data1: 70*9663SMark.Logan@Sun.COM * @data1_len: 71*9663SMark.Logan@Sun.COM * @data2: 72*9663SMark.Logan@Sun.COM * @data2_len: 73*9663SMark.Logan@Sun.COM * 74*9663SMark.Logan@Sun.COM * Description... 75*9663SMark.Logan@Sun.COM * 76*9663SMark.Logan@Sun.COM * Returns: 77*9663SMark.Logan@Sun.COM */ 78*9663SMark.Logan@Sun.COM static int ntfs_collate_ntofs_ulong(ntfs_volume *vol __attribute__((unused)), 79*9663SMark.Logan@Sun.COM const void *data1, size_t data1_len, 80*9663SMark.Logan@Sun.COM const void *data2, size_t data2_len) 81*9663SMark.Logan@Sun.COM { 82*9663SMark.Logan@Sun.COM int rc; 83*9663SMark.Logan@Sun.COM u32 d1, d2; 84*9663SMark.Logan@Sun.COM 85*9663SMark.Logan@Sun.COM ntfs_log_trace("Entering.\n"); 86*9663SMark.Logan@Sun.COM if (data1_len != data2_len || data1_len != 4) { 87*9663SMark.Logan@Sun.COM ntfs_log_error("data1_len or/and data2_len not equal to 4.\n"); 88*9663SMark.Logan@Sun.COM return NTFS_COLLATION_ERROR; 89*9663SMark.Logan@Sun.COM } 90*9663SMark.Logan@Sun.COM d1 = le32_to_cpup(data1); 91*9663SMark.Logan@Sun.COM d2 = le32_to_cpup(data2); 92*9663SMark.Logan@Sun.COM if (d1 < d2) 93*9663SMark.Logan@Sun.COM rc = -1; 94*9663SMark.Logan@Sun.COM else { 95*9663SMark.Logan@Sun.COM if (d1 == d2) 96*9663SMark.Logan@Sun.COM rc = 0; 97*9663SMark.Logan@Sun.COM else 98*9663SMark.Logan@Sun.COM rc = 1; 99*9663SMark.Logan@Sun.COM } 100*9663SMark.Logan@Sun.COM ntfs_log_trace("Done, returning %i.\n", rc); 101*9663SMark.Logan@Sun.COM return rc; 102*9663SMark.Logan@Sun.COM } 103*9663SMark.Logan@Sun.COM 104*9663SMark.Logan@Sun.COM /** 105*9663SMark.Logan@Sun.COM * ntfs_collate_file_name - Which of two filenames should be listed first 106*9663SMark.Logan@Sun.COM * @vol: 107*9663SMark.Logan@Sun.COM * @data1: 108*9663SMark.Logan@Sun.COM * @data1_len: unused 109*9663SMark.Logan@Sun.COM * @data2: 110*9663SMark.Logan@Sun.COM * @data2_len: unused 111*9663SMark.Logan@Sun.COM * 112*9663SMark.Logan@Sun.COM * Description... 113*9663SMark.Logan@Sun.COM * 114*9663SMark.Logan@Sun.COM * Returns: 115*9663SMark.Logan@Sun.COM */ 116*9663SMark.Logan@Sun.COM static int ntfs_collate_file_name(ntfs_volume *vol, 117*9663SMark.Logan@Sun.COM const void *data1, size_t data1_len __attribute__((unused)), 118*9663SMark.Logan@Sun.COM const void *data2, size_t data2_len __attribute__((unused))) 119*9663SMark.Logan@Sun.COM { 120*9663SMark.Logan@Sun.COM int rc; 121*9663SMark.Logan@Sun.COM 122*9663SMark.Logan@Sun.COM ntfs_log_trace("Entering.\n"); 123*9663SMark.Logan@Sun.COM rc = ntfs_file_values_compare(data1, data2, NTFS_COLLATION_ERROR, 124*9663SMark.Logan@Sun.COM IGNORE_CASE, vol->upcase, vol->upcase_len); 125*9663SMark.Logan@Sun.COM if (!rc) 126*9663SMark.Logan@Sun.COM rc = ntfs_file_values_compare(data1, data2, 127*9663SMark.Logan@Sun.COM NTFS_COLLATION_ERROR, CASE_SENSITIVE, 128*9663SMark.Logan@Sun.COM vol->upcase, vol->upcase_len); 129*9663SMark.Logan@Sun.COM ntfs_log_trace("Done, returning %i.\n", rc); 130*9663SMark.Logan@Sun.COM return rc; 131*9663SMark.Logan@Sun.COM } 132*9663SMark.Logan@Sun.COM 133*9663SMark.Logan@Sun.COM typedef int (*ntfs_collate_func_t)(ntfs_volume *, const void *, size_t, 134*9663SMark.Logan@Sun.COM const void *, size_t); 135*9663SMark.Logan@Sun.COM 136*9663SMark.Logan@Sun.COM static ntfs_collate_func_t ntfs_do_collate0x0[3] = { 137*9663SMark.Logan@Sun.COM ntfs_collate_binary, 138*9663SMark.Logan@Sun.COM ntfs_collate_file_name, 139*9663SMark.Logan@Sun.COM NULL/*ntfs_collate_unicode_string*/, 140*9663SMark.Logan@Sun.COM }; 141*9663SMark.Logan@Sun.COM 142*9663SMark.Logan@Sun.COM static ntfs_collate_func_t ntfs_do_collate0x1[4] = { 143*9663SMark.Logan@Sun.COM ntfs_collate_ntofs_ulong, 144*9663SMark.Logan@Sun.COM NULL/*ntfs_collate_ntofs_sid*/, 145*9663SMark.Logan@Sun.COM NULL/*ntfs_collate_ntofs_security_hash*/, 146*9663SMark.Logan@Sun.COM NULL/*ntfs_collate_ntofs_ulongs*/, 147*9663SMark.Logan@Sun.COM }; 148*9663SMark.Logan@Sun.COM 149*9663SMark.Logan@Sun.COM /** 150*9663SMark.Logan@Sun.COM * ntfs_is_collation_rule_supported - Check if a collation rule is implemented. 151*9663SMark.Logan@Sun.COM * @cr: The to-be-checked collation rule 152*9663SMark.Logan@Sun.COM * 153*9663SMark.Logan@Sun.COM * Use this function to know if @cr is supported by libntfs. 154*9663SMark.Logan@Sun.COM * 155*9663SMark.Logan@Sun.COM * 7 collation rules are known to be supported by NTFS as defined 156*9663SMark.Logan@Sun.COM * in layout.h. However, libntfs only support 3 of them ATM. 157*9663SMark.Logan@Sun.COM * 158*9663SMark.Logan@Sun.COM * Return TRUE if @cr is supported. FALSE otherwise. 159*9663SMark.Logan@Sun.COM */ 160*9663SMark.Logan@Sun.COM BOOL ntfs_is_collation_rule_supported(COLLATION_RULES cr) 161*9663SMark.Logan@Sun.COM { 162*9663SMark.Logan@Sun.COM return (cr == COLLATION_BINARY || cr == COLLATION_NTOFS_ULONG || 163*9663SMark.Logan@Sun.COM cr == COLLATION_FILE_NAME); 164*9663SMark.Logan@Sun.COM /* 165*9663SMark.Logan@Sun.COM * FIXME: At the moment we only support COLLATION_BINARY, 166*9663SMark.Logan@Sun.COM * COLLATION_NTOFS_ULONG and COLLATION_FILE_NAME. 167*9663SMark.Logan@Sun.COM * The correct future implementation of this function should be: 168*9663SMark.Logan@Sun.COM * 169*9663SMark.Logan@Sun.COM * u32 i = le32_to_cpu(cr); 170*9663SMark.Logan@Sun.COM * return ((i <= 0x02) || ((i >= 0x10) && (i <= 0x13))); 171*9663SMark.Logan@Sun.COM */ 172*9663SMark.Logan@Sun.COM } 173*9663SMark.Logan@Sun.COM 174*9663SMark.Logan@Sun.COM /** 175*9663SMark.Logan@Sun.COM * ntfs_collate - collate two data items using a specified collation rule 176*9663SMark.Logan@Sun.COM * @vol: ntfs volume to which the data items belong 177*9663SMark.Logan@Sun.COM * @cr: collation rule to use when comparing the items 178*9663SMark.Logan@Sun.COM * @data1: first data item to collate 179*9663SMark.Logan@Sun.COM * @data1_len: length in bytes of @data1 180*9663SMark.Logan@Sun.COM * @data2: second data item to collate 181*9663SMark.Logan@Sun.COM * @data2_len: length in bytes of @data2 182*9663SMark.Logan@Sun.COM * 183*9663SMark.Logan@Sun.COM * Collate the two data items @data1 and @data2 using the collation rule @cr 184*9663SMark.Logan@Sun.COM * and return -1, 0, or 1 if @data1 is found, respectively, to collate before, 185*9663SMark.Logan@Sun.COM * to match, or to collate after @data2. 186*9663SMark.Logan@Sun.COM * 187*9663SMark.Logan@Sun.COM * For speed we use the collation rule @cr as an index into two tables of 188*9663SMark.Logan@Sun.COM * function pointers to call the appropriate collation function. 189*9663SMark.Logan@Sun.COM * 190*9663SMark.Logan@Sun.COM * Return NTFS_COLLATION_ERROR if error occurred. 191*9663SMark.Logan@Sun.COM */ 192*9663SMark.Logan@Sun.COM int ntfs_collate(ntfs_volume *vol, COLLATION_RULES cr, 193*9663SMark.Logan@Sun.COM const void *data1, size_t data1_len, 194*9663SMark.Logan@Sun.COM const void *data2, size_t data2_len) 195*9663SMark.Logan@Sun.COM { 196*9663SMark.Logan@Sun.COM u32 i; 197*9663SMark.Logan@Sun.COM 198*9663SMark.Logan@Sun.COM ntfs_log_trace("Entering.\n"); 199*9663SMark.Logan@Sun.COM if (!vol || !data1 || !data2) { 200*9663SMark.Logan@Sun.COM ntfs_log_error("Invalid arguments passed.\n"); 201*9663SMark.Logan@Sun.COM return NTFS_COLLATION_ERROR; 202*9663SMark.Logan@Sun.COM } 203*9663SMark.Logan@Sun.COM 204*9663SMark.Logan@Sun.COM if (!ntfs_is_collation_rule_supported(cr)) 205*9663SMark.Logan@Sun.COM goto err; 206*9663SMark.Logan@Sun.COM i = le32_to_cpu(cr); 207*9663SMark.Logan@Sun.COM if (i <= 0x02) 208*9663SMark.Logan@Sun.COM return ntfs_do_collate0x0[i](vol, data1, data1_len, 209*9663SMark.Logan@Sun.COM data2, data2_len); 210*9663SMark.Logan@Sun.COM if (i < 0x10) 211*9663SMark.Logan@Sun.COM goto err; 212*9663SMark.Logan@Sun.COM i -= 0x10; 213*9663SMark.Logan@Sun.COM if (i <= 3) 214*9663SMark.Logan@Sun.COM return ntfs_do_collate0x1[i](vol, data1, data1_len, 215*9663SMark.Logan@Sun.COM data2, data2_len); 216*9663SMark.Logan@Sun.COM err: 217*9663SMark.Logan@Sun.COM ntfs_log_debug("Unknown collation rule.\n"); 218*9663SMark.Logan@Sun.COM return NTFS_COLLATION_ERROR; 219*9663SMark.Logan@Sun.COM } 220