1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <linux/slab.h>
23
24#include "types.h"
25#include "debug.h"
26#include "ntfs.h"
27
28
29
30
31
32
33
34
35
36
37
38
39
40static const u8 legal_ansi_char_array[0x40] = {
41 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
42 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
43
44 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
45 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
46
47 0x17, 0x07, 0x18, 0x17, 0x17, 0x17, 0x17, 0x17,
48 0x17, 0x17, 0x18, 0x16, 0x16, 0x17, 0x07, 0x00,
49
50 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
51 0x17, 0x17, 0x04, 0x16, 0x18, 0x16, 0x18, 0x18,
52};
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68bool ntfs_are_names_equal(const ntfschar *s1, size_t s1_len,
69 const ntfschar *s2, size_t s2_len, const IGNORE_CASE_BOOL ic,
70 const ntfschar *upcase, const u32 upcase_size)
71{
72 if (s1_len != s2_len)
73 return false;
74 if (ic == CASE_SENSITIVE)
75 return !ntfs_ucsncmp(s1, s2, s1_len);
76 return !ntfs_ucsncasecmp(s1, s2, s1_len, upcase, upcase_size);
77}
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97int ntfs_collate_names(const ntfschar *name1, const u32 name1_len,
98 const ntfschar *name2, const u32 name2_len,
99 const int err_val, const IGNORE_CASE_BOOL ic,
100 const ntfschar *upcase, const u32 upcase_len)
101{
102 u32 cnt, min_len;
103 u16 c1, c2;
104
105 min_len = name1_len;
106 if (name1_len > name2_len)
107 min_len = name2_len;
108 for (cnt = 0; cnt < min_len; ++cnt) {
109 c1 = le16_to_cpu(*name1++);
110 c2 = le16_to_cpu(*name2++);
111 if (ic) {
112 if (c1 < upcase_len)
113 c1 = le16_to_cpu(upcase[c1]);
114 if (c2 < upcase_len)
115 c2 = le16_to_cpu(upcase[c2]);
116 }
117 if (c1 < 64 && legal_ansi_char_array[c1] & 8)
118 return err_val;
119 if (c1 < c2)
120 return -1;
121 if (c1 > c2)
122 return 1;
123 }
124 if (name1_len < name2_len)
125 return -1;
126 if (name1_len == name2_len)
127 return 0;
128
129 c1 = le16_to_cpu(*name1);
130 if (c1 < 64 && legal_ansi_char_array[c1] & 8)
131 return err_val;
132 return 1;
133}
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149int ntfs_ucsncmp(const ntfschar *s1, const ntfschar *s2, size_t n)
150{
151 u16 c1, c2;
152 size_t i;
153
154 for (i = 0; i < n; ++i) {
155 c1 = le16_to_cpu(s1[i]);
156 c2 = le16_to_cpu(s2[i]);
157 if (c1 < c2)
158 return -1;
159 if (c1 > c2)
160 return 1;
161 if (!c1)
162 break;
163 }
164 return 0;
165}
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185int ntfs_ucsncasecmp(const ntfschar *s1, const ntfschar *s2, size_t n,
186 const ntfschar *upcase, const u32 upcase_size)
187{
188 size_t i;
189 u16 c1, c2;
190
191 for (i = 0; i < n; ++i) {
192 if ((c1 = le16_to_cpu(s1[i])) < upcase_size)
193 c1 = le16_to_cpu(upcase[c1]);
194 if ((c2 = le16_to_cpu(s2[i])) < upcase_size)
195 c2 = le16_to_cpu(upcase[c2]);
196 if (c1 < c2)
197 return -1;
198 if (c1 > c2)
199 return 1;
200 if (!c1)
201 break;
202 }
203 return 0;
204}
205
206void ntfs_upcase_name(ntfschar *name, u32 name_len, const ntfschar *upcase,
207 const u32 upcase_len)
208{
209 u32 i;
210 u16 u;
211
212 for (i = 0; i < name_len; i++)
213 if ((u = le16_to_cpu(name[i])) < upcase_len)
214 name[i] = upcase[u];
215}
216
217void ntfs_file_upcase_value(FILE_NAME_ATTR *file_name_attr,
218 const ntfschar *upcase, const u32 upcase_len)
219{
220 ntfs_upcase_name((ntfschar*)&file_name_attr->file_name,
221 file_name_attr->file_name_length, upcase, upcase_len);
222}
223
224int ntfs_file_compare_values(FILE_NAME_ATTR *file_name_attr1,
225 FILE_NAME_ATTR *file_name_attr2,
226 const int err_val, const IGNORE_CASE_BOOL ic,
227 const ntfschar *upcase, const u32 upcase_len)
228{
229 return ntfs_collate_names((ntfschar*)&file_name_attr1->file_name,
230 file_name_attr1->file_name_length,
231 (ntfschar*)&file_name_attr2->file_name,
232 file_name_attr2->file_name_length,
233 err_val, ic, upcase, upcase_len);
234}
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259int ntfs_nlstoucs(const ntfs_volume *vol, const char *ins,
260 const int ins_len, ntfschar **outs)
261{
262 struct nls_table *nls = vol->nls_map;
263 ntfschar *ucs;
264 wchar_t wc;
265 int i, o, wc_len;
266
267
268 if (likely(ins)) {
269 ucs = kmem_cache_alloc(ntfs_name_cache, GFP_NOFS);
270 if (likely(ucs)) {
271 for (i = o = 0; i < ins_len; i += wc_len) {
272 wc_len = nls->char2uni(ins + i, ins_len - i,
273 &wc);
274 if (likely(wc_len >= 0 &&
275 o < NTFS_MAX_NAME_LEN)) {
276 if (likely(wc)) {
277 ucs[o++] = cpu_to_le16(wc);
278 continue;
279 }
280 break;
281 }
282
283 goto name_err;
284 }
285 ucs[o] = 0;
286 *outs = ucs;
287 return o;
288 }
289 ntfs_error(vol->sb, "Failed to allocate buffer for converted "
290 "name from ntfs_name_cache.");
291 return -ENOMEM;
292 }
293 ntfs_error(vol->sb, "Received NULL pointer.");
294 return -EINVAL;
295name_err:
296 kmem_cache_free(ntfs_name_cache, ucs);
297 if (wc_len < 0) {
298 ntfs_error(vol->sb, "Name using character set %s contains "
299 "characters that cannot be converted to "
300 "Unicode.", nls->charset);
301 i = -EILSEQ;
302 } else {
303 ntfs_error(vol->sb, "Name is too long (maximum length for a "
304 "name on NTFS is %d Unicode characters.",
305 NTFS_MAX_NAME_LEN);
306 i = -ENAMETOOLONG;
307 }
308 return i;
309}
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336int ntfs_ucstonls(const ntfs_volume *vol, const ntfschar *ins,
337 const int ins_len, unsigned char **outs, int outs_len)
338{
339 struct nls_table *nls = vol->nls_map;
340 unsigned char *ns;
341 int i, o, ns_len, wc;
342
343
344 if (ins) {
345 ns = *outs;
346 ns_len = outs_len;
347 if (ns && !ns_len) {
348 wc = -ENAMETOOLONG;
349 goto conversion_err;
350 }
351 if (!ns) {
352 ns_len = ins_len * NLS_MAX_CHARSET_SIZE;
353 ns = kmalloc(ns_len + 1, GFP_NOFS);
354 if (!ns)
355 goto mem_err_out;
356 }
357 for (i = o = 0; i < ins_len; i++) {
358retry: wc = nls->uni2char(le16_to_cpu(ins[i]), ns + o,
359 ns_len - o);
360 if (wc > 0) {
361 o += wc;
362 continue;
363 } else if (!wc)
364 break;
365 else if (wc == -ENAMETOOLONG && ns != *outs) {
366 unsigned char *tc;
367
368 tc = kmalloc((ns_len + 64) &
369 ~63, GFP_NOFS);
370 if (tc) {
371 memcpy(tc, ns, ns_len);
372 ns_len = ((ns_len + 64) & ~63) - 1;
373 kfree(ns);
374 ns = tc;
375 goto retry;
376 }
377 }
378 goto conversion_err;
379 }
380 ns[o] = 0;
381 *outs = ns;
382 return o;
383 }
384 ntfs_error(vol->sb, "Received NULL pointer.");
385 return -EINVAL;
386conversion_err:
387 ntfs_error(vol->sb, "Unicode name contains characters that cannot be "
388 "converted to character set %s. You might want to "
389 "try to use the mount option nls=utf8.", nls->charset);
390 if (ns != *outs)
391 kfree(ns);
392 if (wc != -ENAMETOOLONG)
393 wc = -EILSEQ;
394 return wc;
395mem_err_out:
396 ntfs_error(vol->sb, "Failed to allocate name!");
397 return -ENOMEM;
398}
399