1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * NTFS kernel collation handling. 4 * 5 * Copyright (c) 2004 Anton Altaparmakov 6 * 7 * Part of this file is based on code from the NTFS-3G. 8 * and is copyrighted by the respective authors below: 9 * Copyright (c) 2004 Anton Altaparmakov 10 * Copyright (c) 2005 Yura Pakhuchiy 11 */ 12 13 #include "collate.h" 14 #include "debug.h" 15 #include "ntfs.h" 16 17 #include <linux/sort.h> 18 19 static int ntfs_collate_binary(struct ntfs_volume *vol, 20 const void *data1, const u32 data1_len, 21 const void *data2, const u32 data2_len) 22 { 23 int rc; 24 25 rc = memcmp(data1, data2, min(data1_len, data2_len)); 26 if (!rc && (data1_len != data2_len)) { 27 if (data1_len < data2_len) 28 rc = -1; 29 else 30 rc = 1; 31 } 32 return rc; 33 } 34 35 static int ntfs_collate_ntofs_ulong(struct ntfs_volume *vol, 36 const void *data1, const u32 data1_len, 37 const void *data2, const u32 data2_len) 38 { 39 int rc; 40 u32 d1 = le32_to_cpup(data1), d2 = le32_to_cpup(data2); 41 42 if (data1_len != data2_len || data1_len != 4) 43 return -EINVAL; 44 45 if (d1 < d2) 46 rc = -1; 47 else { 48 if (d1 == d2) 49 rc = 0; 50 else 51 rc = 1; 52 } 53 return rc; 54 } 55 56 /* 57 * ntfs_collate_ntofs_ulongs - Which of two le32 arrays should be listed first 58 * @vol: ntfs volume 59 * @data1: first ulong array to collate 60 * @data1_len: length in bytes of @data1 61 * @data2: second ulong array to collate 62 * @data2_len: length in bytes of @data2 63 * 64 * Returns: -1, 0 or 1 depending of how the arrays compare 65 */ 66 static int ntfs_collate_ntofs_ulongs(struct ntfs_volume *vol, 67 const void *data1, const u32 data1_len, 68 const void *data2, const u32 data2_len) 69 { 70 int len; 71 const __le32 *p1 = data1, *p2 = data2; 72 u32 d1, d2; 73 74 if (data1_len != data2_len || data1_len & 3) { 75 ntfs_error(vol->sb, "data1_len or data2_len not valid\n"); 76 return -1; 77 } 78 79 len = data1_len; 80 do { 81 d1 = le32_to_cpup(p1); 82 p1++; 83 d2 = le32_to_cpup(p2); 84 p2++; 85 } while (d1 == d2 && (len -= 4) > 0); 86 return cmp_int(d1, d2); 87 } 88 89 /* 90 * ntfs_collate_file_name - Which of two filenames should be listed first 91 * @vol: ntfs volume 92 * @data1: first filename to collate 93 * @data1_len: length in bytes of @data1(unused) 94 * @data2: second filename to collate 95 * @data2_len: length in bytes of @data2(unused) 96 */ 97 static int ntfs_collate_file_name(struct ntfs_volume *vol, 98 const void *data1, const u32 data1_len, 99 const void *data2, const u32 data2_len) 100 { 101 int rc; 102 103 rc = ntfs_file_compare_values(data1, data2, -EINVAL, 104 IGNORE_CASE, vol->upcase, vol->upcase_len); 105 if (!rc) 106 rc = ntfs_file_compare_values(data1, data2, 107 -EINVAL, CASE_SENSITIVE, vol->upcase, vol->upcase_len); 108 return rc; 109 } 110 111 /* 112 * ntfs_collate - collate two data items using a specified collation rule 113 * @vol: ntfs volume to which the data items belong 114 * @cr: collation rule to use when comparing the items 115 * @data1: first data item to collate 116 * @data1_len: length in bytes of @data1 117 * @data2: second data item to collate 118 * @data2_len: length in bytes of @data2 119 * 120 * Collate the two data items @data1 and @data2 using the collation rule @cr 121 * and return -1, 0, ir 1 if @data1 is found, respectively, to collate before, 122 * to match, or to collate after @data2. return -EINVAL if an error occurred. 123 */ 124 int ntfs_collate(struct ntfs_volume *vol, __le32 cr, 125 const void *data1, const u32 data1_len, 126 const void *data2, const u32 data2_len) 127 { 128 switch (le32_to_cpu(cr)) { 129 case le32_to_cpu(COLLATION_BINARY): 130 return ntfs_collate_binary(vol, data1, data1_len, 131 data2, data2_len); 132 case le32_to_cpu(COLLATION_FILE_NAME): 133 return ntfs_collate_file_name(vol, data1, data1_len, 134 data2, data2_len); 135 case le32_to_cpu(COLLATION_NTOFS_ULONG): 136 return ntfs_collate_ntofs_ulong(vol, data1, data1_len, 137 data2, data2_len); 138 case le32_to_cpu(COLLATION_NTOFS_ULONGS): 139 return ntfs_collate_ntofs_ulongs(vol, data1, data1_len, 140 data2, data2_len); 141 default: 142 ntfs_error(vol->sb, "Unknown collation rule 0x%x", 143 le32_to_cpu(cr)); 144 return -EINVAL; 145 } 146 } 147