xref: /haiku/src/add-ons/kernel/file_systems/ntfs/libntfs/collate.c (revision be3db2942c0e8dda63cdd226ec3c99309d3eab0c)
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