xref: /linux/fs/ntfs/collate.c (revision cdd4dc3aebeab43a72ce0bc2b5bab6f0a80b97a5)
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