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