Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *
0004  * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
0005  *
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/types.h>
0010 
0011 #include "ntfs_fs.h"
0012 
0013 static inline u16 upcase_unicode_char(const u16 *upcase, u16 chr)
0014 {
0015     if (chr < 'a')
0016         return chr;
0017 
0018     if (chr <= 'z')
0019         return chr - ('a' - 'A');
0020 
0021     return upcase[chr];
0022 }
0023 
0024 /*
0025  * ntfs_cmp_names
0026  *
0027  * Thanks Kari Argillander <kari.argillander@gmail.com> for idea and implementation 'bothcase'
0028  *
0029  * Straight way to compare names:
0030  * - Case insensitive
0031  * - If name equals and 'bothcases' then
0032  * - Case sensitive
0033  * 'Straight way' code scans input names twice in worst case.
0034  * Optimized code scans input names only once.
0035  */
0036 int ntfs_cmp_names(const __le16 *s1, size_t l1, const __le16 *s2, size_t l2,
0037            const u16 *upcase, bool bothcase)
0038 {
0039     int diff1 = 0;
0040     int diff2;
0041     size_t len = min(l1, l2);
0042 
0043     if (!bothcase && upcase)
0044         goto case_insentive;
0045 
0046     for (; len; s1++, s2++, len--) {
0047         diff1 = le16_to_cpu(*s1) - le16_to_cpu(*s2);
0048         if (diff1) {
0049             if (bothcase && upcase)
0050                 goto case_insentive;
0051 
0052             return diff1;
0053         }
0054     }
0055     return l1 - l2;
0056 
0057 case_insentive:
0058     for (; len; s1++, s2++, len--) {
0059         diff2 = upcase_unicode_char(upcase, le16_to_cpu(*s1)) -
0060             upcase_unicode_char(upcase, le16_to_cpu(*s2));
0061         if (diff2)
0062             return diff2;
0063     }
0064 
0065     diff2 = l1 - l2;
0066     return diff2 ? diff2 : diff1;
0067 }
0068 
0069 int ntfs_cmp_names_cpu(const struct cpu_str *uni1, const struct le_str *uni2,
0070                const u16 *upcase, bool bothcase)
0071 {
0072     const u16 *s1 = uni1->name;
0073     const __le16 *s2 = uni2->name;
0074     size_t l1 = uni1->len;
0075     size_t l2 = uni2->len;
0076     size_t len = min(l1, l2);
0077     int diff1 = 0;
0078     int diff2;
0079 
0080     if (!bothcase && upcase)
0081         goto case_insentive;
0082 
0083     for (; len; s1++, s2++, len--) {
0084         diff1 = *s1 - le16_to_cpu(*s2);
0085         if (diff1) {
0086             if (bothcase && upcase)
0087                 goto case_insentive;
0088 
0089             return diff1;
0090         }
0091     }
0092     return l1 - l2;
0093 
0094 case_insentive:
0095     for (; len; s1++, s2++, len--) {
0096         diff2 = upcase_unicode_char(upcase, *s1) -
0097             upcase_unicode_char(upcase, le16_to_cpu(*s2));
0098         if (diff2)
0099             return diff2;
0100     }
0101 
0102     diff2 = l1 - l2;
0103     return diff2 ? diff2 : diff1;
0104 }