1 /** 2 * collate.c - NTFS collation handling. Originated from 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 NTFS-3G 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 "collate.h" 32 #include "debug.h" 33 #include "unistr.h" 34 #include "logging.h" 35 36 BOOL ntfs_is_collation_rule_supported(COLLATION_RULES cr) 37 { 38 int i; 39 40 /* 41 * FIXME: At the moment we only support COLLATION_BINARY, 42 * COLLATION_NTOFS_ULONG and COLLATION_FILE_NAME so we return false 43 * for everything else. 44 */ 45 if (cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG && 46 cr != COLLATION_FILE_NAME) 47 return FALSE; 48 i = le32_to_cpu(cr); 49 if (((i >= 0) && (i <= 0x02)) || 50 ((i >= 0x10) && (i <= 0x13))) 51 return TRUE; 52 53 return FALSE; 54 } 55 56 /** 57 * ntfs_collate_binary - Which of two binary objects should be listed first 58 * @vol: unused 59 * @data1: 60 * @data1_len: 61 * @data2: 62 * @data2_len: 63 * 64 * Description... 65 * 66 * Returns: 67 */ 68 static int ntfs_collate_binary(ntfs_volume *vol __attribute__((unused)), 69 const void *data1, const int data1_len, 70 const void *data2, const int data2_len) 71 { 72 int rc; 73 74 ntfs_log_trace("Entering.\n"); 75 rc = memcmp(data1, data2, min(data1_len, data2_len)); 76 if (!rc && (data1_len != data2_len)) { 77 if (data1_len < data2_len) 78 rc = -1; 79 else 80 rc = 1; 81 } 82 ntfs_log_trace("Done, returning %i.\n", rc); 83 return rc; 84 } 85 86 /** 87 * ntfs_collate_ntofs_ulong - Which of two long ints should be listed first 88 * @vol: unused 89 * @data1: 90 * @data1_len: 91 * @data2: 92 * @data2_len: 93 * 94 * Description... 95 * 96 * Returns: 97 */ 98 static int ntfs_collate_ntofs_ulong(ntfs_volume *vol __attribute__((unused)), 99 const void *data1, const int data1_len, 100 const void *data2, const int data2_len) 101 { 102 int rc; 103 u32 d1, d2; 104 105 ntfs_log_trace("Entering.\n"); 106 if (data1_len != data2_len || data1_len != 4) { 107 ntfs_log_error("data1_len or/and data2_len not equal to 4.\n"); 108 return NTFS_COLLATION_ERROR; 109 } 110 d1 = le32_to_cpup(data1); 111 d2 = le32_to_cpup(data2); 112 if (d1 < d2) 113 rc = -1; 114 else { 115 if (d1 == d2) 116 rc = 0; 117 else 118 rc = 1; 119 } 120 ntfs_log_trace("Done, returning %i.\n", rc); 121 return rc; 122 } 123 124 /** 125 * ntfs_collate_file_name - Which of two filenames should be listed first 126 * @vol: 127 * @data1: 128 * @data1_len: unused 129 * @data2: 130 * @data2_len: unused 131 * 132 * Description... 133 * 134 * Returns: 135 */ 136 static int ntfs_collate_file_name(ntfs_volume *vol, 137 const void *data1, const int data1_len __attribute__((unused)), 138 const void *data2, const int data2_len __attribute__((unused))) 139 { 140 int rc; 141 142 ntfs_log_trace("Entering.\n"); 143 rc = ntfs_file_values_compare(data1, data2, NTFS_COLLATION_ERROR, 144 IGNORE_CASE, vol->upcase, vol->upcase_len); 145 if (!rc) 146 rc = ntfs_file_values_compare(data1, data2, 147 NTFS_COLLATION_ERROR, CASE_SENSITIVE, 148 vol->upcase, vol->upcase_len); 149 ntfs_log_trace("Done, returning %i.\n", rc); 150 return rc; 151 } 152 153 typedef int (*ntfs_collate_func_t)(ntfs_volume *, const void *, const int, 154 const void *, const int); 155 156 static ntfs_collate_func_t ntfs_do_collate0x0[3] = { 157 ntfs_collate_binary, 158 ntfs_collate_file_name, 159 NULL/*ntfs_collate_unicode_string*/, 160 }; 161 162 static ntfs_collate_func_t ntfs_do_collate0x1[4] = { 163 ntfs_collate_ntofs_ulong, 164 NULL/*ntfs_collate_ntofs_sid*/, 165 NULL/*ntfs_collate_ntofs_security_hash*/, 166 NULL/*ntfs_collate_ntofs_ulongs*/, 167 }; 168 169 /** 170 * ntfs_collate - collate two data items using a specified collation rule 171 * @vol: ntfs volume to which the data items belong 172 * @cr: collation rule to use when comparing the items 173 * @data1: first data item to collate 174 * @data1_len: length in bytes of @data1 175 * @data2: second data item to collate 176 * @data2_len: length in bytes of @data2 177 * 178 * Collate the two data items @data1 and @data2 using the collation rule @cr 179 * and return -1, 0, or 1 if @data1 is found, respectively, to collate before, 180 * to match, or to collate after @data2. 181 * 182 * For speed we use the collation rule @cr as an index into two tables of 183 * function pointers to call the appropriate collation function. 184 * 185 * Return NTFS_COLLATION_ERROR if error occurred. 186 */ 187 int ntfs_collate(ntfs_volume *vol, COLLATION_RULES cr, 188 const void *data1, const int data1_len, 189 const void *data2, const int data2_len) 190 { 191 int i; 192 193 ntfs_log_trace("Entering.\n"); 194 if (!vol || !data1 || !data2 || data1_len < 0 || data2_len < 0) { 195 ntfs_log_error("Invalid arguments passed.\n"); 196 return NTFS_COLLATION_ERROR; 197 } 198 /* 199 * FIXME: At the moment we only support COLLATION_BINARY, 200 * COLLATION_NTOFS_ULONG and COLLATION_FILE_NAME so we return error 201 * for everything else. 202 */ 203 if (cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG && 204 cr != COLLATION_FILE_NAME) 205 goto err; 206 i = le32_to_cpu(cr); 207 if (i < 0) 208 goto err; 209 if (i <= 0x02) 210 return ntfs_do_collate0x0[i](vol, data1, data1_len, 211 data2, data2_len); 212 if (i < 0x10) 213 goto err; 214 i -= 0x10; 215 if (i <= 3) 216 return ntfs_do_collate0x1[i](vol, data1, data1_len, 217 data2, data2_len); 218 err: 219 ntfs_log_debug("Unknown collation rule.\n"); 220 return NTFS_COLLATION_ERROR; 221 } 222