Merge tag 'mm-hotfixes-stable-2023-05-03-16-27' of git://git.kernel.org/pub/scm/linux...
[linux-block.git] / fs / ntfs3 / upcase.c
CommitLineData
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
13static 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 <kari.argillander@gmail.com> 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 */
36int 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
57case_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
69int 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
94case_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. */
107unsigned 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}