| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- *
- * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
- *
- */
- #include <linux/kernel.h>
- #include <linux/types.h>
- #include "ntfs_fs.h"
- static inline u16 upcase_unicode_char(const u16 *upcase, u16 chr)
- {
- if (chr < 'a')
- return chr;
- if (chr <= 'z')
- return chr - ('a' - 'A');
- return upcase[chr];
- }
- /*
- * ntfs_cmp_names
- *
- * Thanks Kari Argillander <kari.argillander@gmail.com> for idea and implementation 'bothcase'
- *
- * Straight way to compare names:
- * - Case insensitive
- * - If name equals and 'bothcases' then
- * - Case sensitive
- * 'Straight way' code scans input names twice in worst case.
- * Optimized code scans input names only once.
- */
- int ntfs_cmp_names(const __le16 *s1, size_t l1, const __le16 *s2, size_t l2,
- const u16 *upcase, bool bothcase)
- {
- int diff1 = 0;
- int diff2;
- size_t len = min(l1, l2);
- if (!bothcase && upcase)
- goto case_insentive;
- for (; len; s1++, s2++, len--) {
- diff1 = le16_to_cpu(*s1) - le16_to_cpu(*s2);
- if (diff1) {
- if (bothcase && upcase)
- goto case_insentive;
- return diff1;
- }
- }
- return l1 - l2;
- case_insentive:
- for (; len; s1++, s2++, len--) {
- diff2 = upcase_unicode_char(upcase, le16_to_cpu(*s1)) -
- upcase_unicode_char(upcase, le16_to_cpu(*s2));
- if (diff2)
- return diff2;
- }
- diff2 = l1 - l2;
- return diff2 ? diff2 : diff1;
- }
- int ntfs_cmp_names_cpu(const struct cpu_str *uni1, const struct le_str *uni2,
- const u16 *upcase, bool bothcase)
- {
- const u16 *s1 = uni1->name;
- const __le16 *s2 = uni2->name;
- size_t l1 = uni1->len;
- size_t l2 = uni2->len;
- size_t len = min(l1, l2);
- int diff1 = 0;
- int diff2;
- if (!bothcase && upcase)
- goto case_insentive;
- for (; len; s1++, s2++, len--) {
- diff1 = *s1 - le16_to_cpu(*s2);
- if (diff1) {
- if (bothcase && upcase)
- goto case_insentive;
- return diff1;
- }
- }
- return l1 - l2;
- case_insentive:
- for (; len; s1++, s2++, len--) {
- diff2 = upcase_unicode_char(upcase, *s1) -
- upcase_unicode_char(upcase, le16_to_cpu(*s2));
- if (diff2)
- return diff2;
- }
- diff2 = l1 - l2;
- return diff2 ? diff2 : diff1;
- }
- /* Helper function for ntfs_d_hash. */
- unsigned long ntfs_names_hash(const u16 *name, size_t len, const u16 *upcase,
- unsigned long hash)
- {
- while (len--) {
- unsigned int c = upcase_unicode_char(upcase, *name++);
- hash = partial_name_hash(c, hash);
- }
- return hash;
- }
|