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 #ifdef HAVE_STDLIB_H 27 #include <stdlib.h> 28 #endif 29 #ifdef HAVE_STRING_H 30 #include <string.h> 31 #endif 32 #ifdef HAVE_ERRNO_H 33 #include <errno.h> 34 #endif 35 36 #include "attrib.h" 37 #include "index.h" 38 #include "collate.h" 39 #include "debug.h" 40 #include "unistr.h" 41 #include "logging.h" 42 43 /** 44 * ntfs_collate_binary - Which of two binary objects should be listed first 45 * @vol: unused 46 * @data1: 47 * @data1_len: 48 * @data2: 49 * @data2_len: 50 * 51 * Description... 52 * 53 * Returns: 54 */ 55 static int ntfs_collate_binary(ntfs_volume *vol __attribute__((unused)), 56 const void *data1, const int data1_len, 57 const void *data2, const int data2_len) 58 { 59 int rc; 60 61 ntfs_log_trace("Entering.\n"); 62 rc = memcmp(data1, data2, min(data1_len, data2_len)); 63 if (!rc && (data1_len != data2_len)) { 64 if (data1_len < data2_len) 65 rc = -1; 66 else 67 rc = 1; 68 } 69 ntfs_log_trace("Done, returning %i.\n", rc); 70 return rc; 71 } 72 73 /** 74 * ntfs_collate_ntofs_ulong - Which of two long ints should be listed first 75 * @vol: unused 76 * @data1: 77 * @data1_len: 78 * @data2: 79 * @data2_len: 80 * 81 * Description... 82 * 83 * Returns: 84 */ 85 static int ntfs_collate_ntofs_ulong(ntfs_volume *vol __attribute__((unused)), 86 const void *data1, const int data1_len, 87 const void *data2, const int data2_len) 88 { 89 int rc; 90 u32 d1, d2; 91 92 ntfs_log_trace("Entering.\n"); 93 if (data1_len != data2_len || data1_len != 4) { 94 ntfs_log_error("data1_len or/and data2_len not equal to 4.\n"); 95 return NTFS_COLLATION_ERROR; 96 } 97 d1 = le32_to_cpup(data1); 98 d2 = le32_to_cpup(data2); 99 if (d1 < d2) 100 rc = -1; 101 else { 102 if (d1 == d2) 103 rc = 0; 104 else 105 rc = 1; 106 } 107 ntfs_log_trace("Done, returning %i.\n", rc); 108 return rc; 109 } 110 111 /** 112 * ntfs_collate_ntofs_ulongs - Which of two le32 arrays should be listed first 113 * 114 * Returns: -1, 0 or 1 depending of how the arrays compare 115 */ 116 117 static int ntfs_collate_ntofs_ulongs(ntfs_volume *vol __attribute__((unused)), 118 const void *data1, const int data1_len, 119 const void *data2, const int data2_len) 120 { 121 int rc; 122 int len; 123 const le32 *p1, *p2; 124 u32 d1, d2; 125 126 ntfs_log_trace("Entering.\n"); 127 if ((data1_len != data2_len) || (data1_len <= 0) || (data1_len & 3)) { 128 ntfs_log_error("data1_len or data2_len not valid\n"); 129 return NTFS_COLLATION_ERROR; 130 } 131 p1 = (const le32*)data1; 132 p2 = (const le32*)data2; 133 len = data1_len; 134 do { 135 d1 = le32_to_cpup(p1); 136 p1++; 137 d2 = le32_to_cpup(p2); 138 p2++; 139 } while ((d1 == d2) && ((len -= 4) > 0)); 140 if (d1 < d2) 141 rc = -1; 142 else { 143 if (d1 == d2) 144 rc = 0; 145 else 146 rc = 1; 147 } 148 ntfs_log_trace("Done, returning %i.\n", rc); 149 return rc; 150 } 151 152 /** 153 * ntfs_collate_ntofs_security_hash - Which of two security descriptors 154 * should be listed first 155 * @vol: unused 156 * @data1: 157 * @data1_len: 158 * @data2: 159 * @data2_len: 160 * 161 * JPA compare two security hash keys made of two unsigned le32 162 * 163 * Returns: -1, 0 or 1 depending of how the keys compare 164 */ 165 static int ntfs_collate_ntofs_security_hash(ntfs_volume *vol __attribute__((unused)), 166 const void *data1, const int data1_len, 167 const void *data2, const int data2_len) 168 { 169 int rc; 170 u32 d1, d2; 171 const le32 *p1, *p2; 172 173 ntfs_log_trace("Entering.\n"); 174 if (data1_len != data2_len || data1_len != 8) { 175 ntfs_log_error("data1_len or/and data2_len not equal to 8.\n"); 176 return NTFS_COLLATION_ERROR; 177 } 178 p1 = (const le32*)data1; 179 p2 = (const le32*)data2; 180 d1 = le32_to_cpup(p1); 181 d2 = le32_to_cpup(p2); 182 if (d1 < d2) 183 rc = -1; 184 else { 185 if (d1 > d2) 186 rc = 1; 187 else { 188 p1++; 189 p2++; 190 d1 = le32_to_cpup(p1); 191 d2 = le32_to_cpup(p2); 192 if (d1 < d2) 193 rc = -1; 194 else { 195 if (d1 > d2) 196 rc = 1; 197 else 198 rc = 0; 199 } 200 } 201 } 202 ntfs_log_trace("Done, returning %i.\n", rc); 203 return rc; 204 } 205 206 /** 207 * ntfs_collate_file_name - Which of two filenames should be listed first 208 * @vol: 209 * @data1: 210 * @data1_len: unused 211 * @data2: 212 * @data2_len: unused 213 * 214 * Description... 215 * 216 * Returns: 217 */ 218 static int ntfs_collate_file_name(ntfs_volume *vol, 219 const void *data1, const int data1_len __attribute__((unused)), 220 const void *data2, const int data2_len __attribute__((unused))) 221 { 222 const FILE_NAME_ATTR *file_name_attr1; 223 const FILE_NAME_ATTR *file_name_attr2; 224 int rc; 225 226 ntfs_log_trace("Entering.\n"); 227 file_name_attr1 = (const FILE_NAME_ATTR*)data1; 228 file_name_attr2 = (const FILE_NAME_ATTR*)data2; 229 rc = ntfs_names_full_collate( 230 (ntfschar*)&file_name_attr1->file_name, 231 file_name_attr1->file_name_length, 232 (ntfschar*)&file_name_attr2->file_name, 233 file_name_attr2->file_name_length, 234 CASE_SENSITIVE, vol->upcase, vol->upcase_len); 235 ntfs_log_trace("Done, returning %i.\n", rc); 236 return rc; 237 } 238 239 /* 240 * Get a pointer to appropriate collation function. 241 * 242 * Returns NULL if the needed function is not implemented 243 */ 244 245 COLLATE ntfs_get_collate_function(COLLATION_RULES cr) 246 { 247 COLLATE collate; 248 249 switch (cr) { 250 case COLLATION_BINARY : 251 collate = ntfs_collate_binary; 252 break; 253 case COLLATION_FILE_NAME : 254 collate = ntfs_collate_file_name; 255 break; 256 case COLLATION_NTOFS_SECURITY_HASH : 257 collate = ntfs_collate_ntofs_security_hash; 258 break; 259 case COLLATION_NTOFS_ULONG : 260 collate = ntfs_collate_ntofs_ulong; 261 break; 262 case COLLATION_NTOFS_ULONGS : 263 collate = ntfs_collate_ntofs_ulongs; 264 break; 265 default : 266 errno = EOPNOTSUPP; 267 collate = (COLLATE)NULL; 268 break; 269 } 270 return (collate); 271 } 272