11e9ea7e0SNamjae Jeon // SPDX-License-Identifier: GPL-2.0-or-later 21e9ea7e0SNamjae Jeon /* 3*5218cd10SNamjae Jeon * NTFS kernel collation handling. 41e9ea7e0SNamjae Jeon * 51e9ea7e0SNamjae Jeon * Copyright (c) 2004 Anton Altaparmakov 6*5218cd10SNamjae Jeon * 7*5218cd10SNamjae Jeon * Part of this file is based on code from the NTFS-3G. 8*5218cd10SNamjae Jeon * and is copyrighted by the respective authors below: 9*5218cd10SNamjae Jeon * Copyright (c) 2004 Anton Altaparmakov 10*5218cd10SNamjae Jeon * Copyright (c) 2005 Yura Pakhuchiy 111e9ea7e0SNamjae Jeon */ 121e9ea7e0SNamjae Jeon 131e9ea7e0SNamjae Jeon #include "collate.h" 141e9ea7e0SNamjae Jeon #include "debug.h" 151e9ea7e0SNamjae Jeon #include "ntfs.h" 161e9ea7e0SNamjae Jeon 17*5218cd10SNamjae Jeon #include <linux/sort.h> 18*5218cd10SNamjae Jeon 19*5218cd10SNamjae Jeon static int ntfs_collate_binary(struct ntfs_volume *vol, 20*5218cd10SNamjae Jeon const void *data1, const u32 data1_len, 21*5218cd10SNamjae Jeon const void *data2, const u32 data2_len) 221e9ea7e0SNamjae Jeon { 231e9ea7e0SNamjae Jeon int rc; 241e9ea7e0SNamjae Jeon 251e9ea7e0SNamjae Jeon rc = memcmp(data1, data2, min(data1_len, data2_len)); 261e9ea7e0SNamjae Jeon if (!rc && (data1_len != data2_len)) { 271e9ea7e0SNamjae Jeon if (data1_len < data2_len) 281e9ea7e0SNamjae Jeon rc = -1; 291e9ea7e0SNamjae Jeon else 301e9ea7e0SNamjae Jeon rc = 1; 311e9ea7e0SNamjae Jeon } 321e9ea7e0SNamjae Jeon return rc; 331e9ea7e0SNamjae Jeon } 341e9ea7e0SNamjae Jeon 35*5218cd10SNamjae Jeon static int ntfs_collate_ntofs_ulong(struct ntfs_volume *vol, 36*5218cd10SNamjae Jeon const void *data1, const u32 data1_len, 37*5218cd10SNamjae Jeon const void *data2, const u32 data2_len) 381e9ea7e0SNamjae Jeon { 391e9ea7e0SNamjae Jeon int rc; 40*5218cd10SNamjae Jeon u32 d1 = le32_to_cpup(data1), d2 = le32_to_cpup(data2); 411e9ea7e0SNamjae Jeon 42*5218cd10SNamjae Jeon if (data1_len != data2_len || data1_len != 4) 43*5218cd10SNamjae Jeon return -EINVAL; 44*5218cd10SNamjae Jeon 451e9ea7e0SNamjae Jeon if (d1 < d2) 461e9ea7e0SNamjae Jeon rc = -1; 471e9ea7e0SNamjae Jeon else { 481e9ea7e0SNamjae Jeon if (d1 == d2) 491e9ea7e0SNamjae Jeon rc = 0; 501e9ea7e0SNamjae Jeon else 511e9ea7e0SNamjae Jeon rc = 1; 521e9ea7e0SNamjae Jeon } 531e9ea7e0SNamjae Jeon return rc; 541e9ea7e0SNamjae Jeon } 551e9ea7e0SNamjae Jeon 56*5218cd10SNamjae Jeon /* 57*5218cd10SNamjae Jeon * ntfs_collate_ntofs_ulongs - Which of two le32 arrays should be listed first 58*5218cd10SNamjae Jeon * @vol: ntfs volume 59*5218cd10SNamjae Jeon * @data1: first ulong array to collate 60*5218cd10SNamjae Jeon * @data1_len: length in bytes of @data1 61*5218cd10SNamjae Jeon * @data2: second ulong array to collate 62*5218cd10SNamjae Jeon * @data2_len: length in bytes of @data2 63*5218cd10SNamjae Jeon * 64*5218cd10SNamjae Jeon * Returns: -1, 0 or 1 depending of how the arrays compare 65*5218cd10SNamjae Jeon */ 66*5218cd10SNamjae Jeon static int ntfs_collate_ntofs_ulongs(struct ntfs_volume *vol, 67*5218cd10SNamjae Jeon const void *data1, const u32 data1_len, 68*5218cd10SNamjae Jeon const void *data2, const u32 data2_len) 69*5218cd10SNamjae Jeon { 70*5218cd10SNamjae Jeon int len; 71*5218cd10SNamjae Jeon const __le32 *p1 = data1, *p2 = data2; 72*5218cd10SNamjae Jeon u32 d1, d2; 731e9ea7e0SNamjae Jeon 74*5218cd10SNamjae Jeon if (data1_len != data2_len || data1_len & 3) { 75*5218cd10SNamjae Jeon ntfs_error(vol->sb, "data1_len or data2_len not valid\n"); 76*5218cd10SNamjae Jeon return -1; 77*5218cd10SNamjae Jeon } 781e9ea7e0SNamjae Jeon 79*5218cd10SNamjae Jeon len = data1_len; 80*5218cd10SNamjae Jeon do { 81*5218cd10SNamjae Jeon d1 = le32_to_cpup(p1); 82*5218cd10SNamjae Jeon p1++; 83*5218cd10SNamjae Jeon d2 = le32_to_cpup(p2); 84*5218cd10SNamjae Jeon p2++; 85*5218cd10SNamjae Jeon } while (d1 == d2 && (len -= 4) > 0); 86*5218cd10SNamjae Jeon return cmp_int(d1, d2); 87*5218cd10SNamjae Jeon } 881e9ea7e0SNamjae Jeon 89*5218cd10SNamjae Jeon /* 90*5218cd10SNamjae Jeon * ntfs_collate_file_name - Which of two filenames should be listed first 91*5218cd10SNamjae Jeon * @vol: ntfs volume 92*5218cd10SNamjae Jeon * @data1: first filename to collate 93*5218cd10SNamjae Jeon * @data1_len: length in bytes of @data1(unused) 94*5218cd10SNamjae Jeon * @data2: second filename to collate 95*5218cd10SNamjae Jeon * @data2_len: length in bytes of @data2(unused) 96*5218cd10SNamjae Jeon */ 97*5218cd10SNamjae Jeon static int ntfs_collate_file_name(struct ntfs_volume *vol, 98*5218cd10SNamjae Jeon const void *data1, const u32 data1_len, 99*5218cd10SNamjae Jeon const void *data2, const u32 data2_len) 100*5218cd10SNamjae Jeon { 101*5218cd10SNamjae Jeon int rc; 102*5218cd10SNamjae Jeon 103*5218cd10SNamjae Jeon rc = ntfs_file_compare_values(data1, data2, -EINVAL, 104*5218cd10SNamjae Jeon IGNORE_CASE, vol->upcase, vol->upcase_len); 105*5218cd10SNamjae Jeon if (!rc) 106*5218cd10SNamjae Jeon rc = ntfs_file_compare_values(data1, data2, 107*5218cd10SNamjae Jeon -EINVAL, CASE_SENSITIVE, vol->upcase, vol->upcase_len); 108*5218cd10SNamjae Jeon return rc; 109*5218cd10SNamjae Jeon } 110*5218cd10SNamjae Jeon 111*5218cd10SNamjae Jeon /* 1121e9ea7e0SNamjae Jeon * ntfs_collate - collate two data items using a specified collation rule 1131e9ea7e0SNamjae Jeon * @vol: ntfs volume to which the data items belong 1141e9ea7e0SNamjae Jeon * @cr: collation rule to use when comparing the items 1151e9ea7e0SNamjae Jeon * @data1: first data item to collate 1161e9ea7e0SNamjae Jeon * @data1_len: length in bytes of @data1 1171e9ea7e0SNamjae Jeon * @data2: second data item to collate 1181e9ea7e0SNamjae Jeon * @data2_len: length in bytes of @data2 1191e9ea7e0SNamjae Jeon * 1201e9ea7e0SNamjae Jeon * Collate the two data items @data1 and @data2 using the collation rule @cr 1211e9ea7e0SNamjae Jeon * and return -1, 0, ir 1 if @data1 is found, respectively, to collate before, 122*5218cd10SNamjae Jeon * to match, or to collate after @data2. return -EINVAL if an error occurred. 1231e9ea7e0SNamjae Jeon */ 124*5218cd10SNamjae Jeon int ntfs_collate(struct ntfs_volume *vol, __le32 cr, 125*5218cd10SNamjae Jeon const void *data1, const u32 data1_len, 126*5218cd10SNamjae Jeon const void *data2, const u32 data2_len) 127*5218cd10SNamjae Jeon { 128*5218cd10SNamjae Jeon switch (le32_to_cpu(cr)) { 129*5218cd10SNamjae Jeon case le32_to_cpu(COLLATION_BINARY): 130*5218cd10SNamjae Jeon return ntfs_collate_binary(vol, data1, data1_len, 1311e9ea7e0SNamjae Jeon data2, data2_len); 132*5218cd10SNamjae Jeon case le32_to_cpu(COLLATION_FILE_NAME): 133*5218cd10SNamjae Jeon return ntfs_collate_file_name(vol, data1, data1_len, 1341e9ea7e0SNamjae Jeon data2, data2_len); 135*5218cd10SNamjae Jeon case le32_to_cpu(COLLATION_NTOFS_ULONG): 136*5218cd10SNamjae Jeon return ntfs_collate_ntofs_ulong(vol, data1, data1_len, 137*5218cd10SNamjae Jeon data2, data2_len); 138*5218cd10SNamjae Jeon case le32_to_cpu(COLLATION_NTOFS_ULONGS): 139*5218cd10SNamjae Jeon return ntfs_collate_ntofs_ulongs(vol, data1, data1_len, 140*5218cd10SNamjae Jeon data2, data2_len); 141*5218cd10SNamjae Jeon default: 142*5218cd10SNamjae Jeon ntfs_error(vol->sb, "Unknown collation rule 0x%x", 143*5218cd10SNamjae Jeon le32_to_cpu(cr)); 144*5218cd10SNamjae Jeon return -EINVAL; 145*5218cd10SNamjae Jeon } 1461e9ea7e0SNamjae Jeon } 147