xref: /onnv-gate/usr/src/lib/libntfs/common/libntfs/collate.c (revision 10214:1f70f0c2183c)
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  */
ntfs_collate_binary(ntfs_volume * vol,const void * data1,size_t data1_len,const void * data2,size_t data2_len)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  */
ntfs_collate_ntofs_ulong(ntfs_volume * vol,const void * data1,size_t data1_len,const void * data2,size_t data2_len)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  */
ntfs_collate_file_name(ntfs_volume * vol,const void * data1,size_t data1_len,const void * data2,size_t data2_len)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  */
ntfs_is_collation_rule_supported(COLLATION_RULES cr)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  */
ntfs_collate(ntfs_volume * vol,COLLATION_RULES cr,const void * data1,size_t data1_len,const void * data2,size_t data2_len)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 }
221