]>
Commit | Line | Data |
---|---|---|
4534a70b KK |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * | |
4 | * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved. | |
5 | * | |
6 | */ | |
e8b8e97f | 7 | |
f9767661 KA |
8 | #include <linux/kernel.h> |
9 | #include <linux/types.h> | |
4534a70b | 10 | |
4534a70b KK |
11 | #include "ntfs_fs.h" |
12 | ||
13 | static inline u16 upcase_unicode_char(const u16 *upcase, u16 chr) | |
14 | { | |
15 | if (chr < 'a') | |
16 | return chr; | |
17 | ||
18 | if (chr <= 'z') | |
19 | return chr - ('a' - 'A'); | |
20 | ||
21 | return upcase[chr]; | |
22 | } | |
23 | ||
24 | /* | |
e8b8e97f KA |
25 | * ntfs_cmp_names |
26 | * | |
4534a70b KK |
27 | * Thanks Kari Argillander <[email protected]> for idea and implementation 'bothcase' |
28 | * | |
f8d87ed9 | 29 | * Straight way to compare names: |
e8b8e97f KA |
30 | * - Case insensitive |
31 | * - If name equals and 'bothcases' then | |
32 | * - Case sensitive | |
d3624466 | 33 | * 'Straight way' code scans input names twice in worst case. |
e8b8e97f | 34 | * Optimized code scans input names only once. |
4534a70b KK |
35 | */ |
36 | int ntfs_cmp_names(const __le16 *s1, size_t l1, const __le16 *s2, size_t l2, | |
37 | const u16 *upcase, bool bothcase) | |
38 | { | |
39 | int diff1 = 0; | |
40 | int diff2; | |
41 | size_t len = min(l1, l2); | |
42 | ||
43 | if (!bothcase && upcase) | |
44 | goto case_insentive; | |
45 | ||
46 | for (; len; s1++, s2++, len--) { | |
47 | diff1 = le16_to_cpu(*s1) - le16_to_cpu(*s2); | |
48 | if (diff1) { | |
49 | if (bothcase && upcase) | |
50 | goto case_insentive; | |
51 | ||
52 | return diff1; | |
53 | } | |
54 | } | |
55 | return l1 - l2; | |
56 | ||
57 | case_insentive: | |
58 | for (; len; s1++, s2++, len--) { | |
59 | diff2 = upcase_unicode_char(upcase, le16_to_cpu(*s1)) - | |
60 | upcase_unicode_char(upcase, le16_to_cpu(*s2)); | |
61 | if (diff2) | |
62 | return diff2; | |
63 | } | |
64 | ||
65 | diff2 = l1 - l2; | |
66 | return diff2 ? diff2 : diff1; | |
67 | } | |
68 | ||
69 | int ntfs_cmp_names_cpu(const struct cpu_str *uni1, const struct le_str *uni2, | |
70 | const u16 *upcase, bool bothcase) | |
71 | { | |
72 | const u16 *s1 = uni1->name; | |
73 | const __le16 *s2 = uni2->name; | |
74 | size_t l1 = uni1->len; | |
75 | size_t l2 = uni2->len; | |
76 | size_t len = min(l1, l2); | |
77 | int diff1 = 0; | |
78 | int diff2; | |
79 | ||
80 | if (!bothcase && upcase) | |
81 | goto case_insentive; | |
82 | ||
83 | for (; len; s1++, s2++, len--) { | |
84 | diff1 = *s1 - le16_to_cpu(*s2); | |
85 | if (diff1) { | |
86 | if (bothcase && upcase) | |
87 | goto case_insentive; | |
88 | ||
89 | return diff1; | |
90 | } | |
91 | } | |
92 | return l1 - l2; | |
93 | ||
94 | case_insentive: | |
95 | for (; len; s1++, s2++, len--) { | |
96 | diff2 = upcase_unicode_char(upcase, *s1) - | |
97 | upcase_unicode_char(upcase, le16_to_cpu(*s2)); | |
98 | if (diff2) | |
99 | return diff2; | |
100 | } | |
101 | ||
102 | diff2 = l1 - l2; | |
103 | return diff2 ? diff2 : diff1; | |
104 | } | |
a3a956c7 KK |
105 | |
106 | /* Helper function for ntfs_d_hash. */ | |
107 | unsigned long ntfs_names_hash(const u16 *name, size_t len, const u16 *upcase, | |
108 | unsigned long hash) | |
109 | { | |
110 | while (len--) { | |
111 | unsigned int c = upcase_unicode_char(upcase, *name++); | |
112 | hash = partial_name_hash(c, hash); | |
113 | } | |
114 | ||
115 | return hash; | |
116 | } |