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/blkdev.h> 9 #include <linux/buffer_head.h> 10 #include <linux/module.h> 11 #include <linux/nls.h> 12 13 #include "debug.h" 14 #include "ntfs.h" 15 #include "ntfs_fs.h" 16 17 static inline u16 upcase_unicode_char(const u16 *upcase, u16 chr) 18 { 19 if (chr < 'a') 20 return chr; 21 22 if (chr <= 'z') 23 return chr - ('a' - 'A'); 24 25 return upcase[chr]; 26 } 27 28 /* 29 * ntfs_cmp_names 30 * 31 * Thanks Kari Argillander <kari.argillander@gmail.com> for idea and implementation 'bothcase' 32 * 33 * Straight way to compare names: 34 * - Case insensitive 35 * - If name equals and 'bothcases' then 36 * - Case sensitive 37 * 'Straight way' code scans input names twice in worst case. 38 * Optimized code scans input names only once. 39 */ 40 int ntfs_cmp_names(const __le16 *s1, size_t l1, const __le16 *s2, size_t l2, 41 const u16 *upcase, bool bothcase) 42 { 43 int diff1 = 0; 44 int diff2; 45 size_t len = min(l1, l2); 46 47 if (!bothcase && upcase) 48 goto case_insentive; 49 50 for (; len; s1++, s2++, len--) { 51 diff1 = le16_to_cpu(*s1) - le16_to_cpu(*s2); 52 if (diff1) { 53 if (bothcase && upcase) 54 goto case_insentive; 55 56 return diff1; 57 } 58 } 59 return l1 - l2; 60 61 case_insentive: 62 for (; len; s1++, s2++, len--) { 63 diff2 = upcase_unicode_char(upcase, le16_to_cpu(*s1)) - 64 upcase_unicode_char(upcase, le16_to_cpu(*s2)); 65 if (diff2) 66 return diff2; 67 } 68 69 diff2 = l1 - l2; 70 return diff2 ? diff2 : diff1; 71 } 72 73 int ntfs_cmp_names_cpu(const struct cpu_str *uni1, const struct le_str *uni2, 74 const u16 *upcase, bool bothcase) 75 { 76 const u16 *s1 = uni1->name; 77 const __le16 *s2 = uni2->name; 78 size_t l1 = uni1->len; 79 size_t l2 = uni2->len; 80 size_t len = min(l1, l2); 81 int diff1 = 0; 82 int diff2; 83 84 if (!bothcase && upcase) 85 goto case_insentive; 86 87 for (; len; s1++, s2++, len--) { 88 diff1 = *s1 - le16_to_cpu(*s2); 89 if (diff1) { 90 if (bothcase && upcase) 91 goto case_insentive; 92 93 return diff1; 94 } 95 } 96 return l1 - l2; 97 98 case_insentive: 99 for (; len; s1++, s2++, len--) { 100 diff2 = upcase_unicode_char(upcase, *s1) - 101 upcase_unicode_char(upcase, le16_to_cpu(*s2)); 102 if (diff2) 103 return diff2; 104 } 105 106 diff2 = l1 - l2; 107 return diff2 ? diff2 : diff1; 108 } 109