xref: /haiku/src/add-ons/kernel/file_systems/ntfs/libntfs/collate.c (revision 0d2c294fa19def5bc72f57f28f2f2c8c21a879dd)
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  */
ntfs_collate_binary(ntfs_volume * vol,const void * data1,const int data1_len,const void * data2,const int data2_len)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  */
ntfs_collate_ntofs_ulong(ntfs_volume * vol,const void * data1,const int data1_len,const void * data2,const int data2_len)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 
ntfs_collate_ntofs_ulongs(ntfs_volume * vol,const void * data1,const int data1_len,const void * data2,const int data2_len)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  */
ntfs_collate_ntofs_security_hash(ntfs_volume * vol,const void * data1,const int data1_len,const void * data2,const int data2_len)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  */
ntfs_collate_file_name(ntfs_volume * vol,const void * data1,const int data1_len,const void * data2,const int data2_len)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 
ntfs_get_collate_function(COLLATION_RULES cr)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