Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.4.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 *
  4 * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
  5 *
  6 */
  7
  8#include <linux/kernel.h>
  9#include <linux/types.h>
 10
 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/*
 25 * ntfs_cmp_names
 26 *
 27 * Thanks Kari Argillander <kari.argillander@gmail.com> for idea and implementation 'bothcase'
 28 *
 29 * Straight way to compare names:
 30 * - Case insensitive
 31 * - If name equals and 'bothcases' then
 32 * - Case sensitive
 33 * 'Straight way' code scans input names twice in worst case.
 34 * Optimized code scans input names only once.
 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}
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}