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