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