162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * collate.c - NTFS kernel collation handling.  Part of the Linux-NTFS project.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2004 Anton Altaparmakov
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "collate.h"
962306a36Sopenharmony_ci#include "debug.h"
1062306a36Sopenharmony_ci#include "ntfs.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistatic int ntfs_collate_binary(ntfs_volume *vol,
1362306a36Sopenharmony_ci		const void *data1, const int data1_len,
1462306a36Sopenharmony_ci		const void *data2, const int data2_len)
1562306a36Sopenharmony_ci{
1662306a36Sopenharmony_ci	int rc;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	ntfs_debug("Entering.");
1962306a36Sopenharmony_ci	rc = memcmp(data1, data2, min(data1_len, data2_len));
2062306a36Sopenharmony_ci	if (!rc && (data1_len != data2_len)) {
2162306a36Sopenharmony_ci		if (data1_len < data2_len)
2262306a36Sopenharmony_ci			rc = -1;
2362306a36Sopenharmony_ci		else
2462306a36Sopenharmony_ci			rc = 1;
2562306a36Sopenharmony_ci	}
2662306a36Sopenharmony_ci	ntfs_debug("Done, returning %i", rc);
2762306a36Sopenharmony_ci	return rc;
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistatic int ntfs_collate_ntofs_ulong(ntfs_volume *vol,
3162306a36Sopenharmony_ci		const void *data1, const int data1_len,
3262306a36Sopenharmony_ci		const void *data2, const int data2_len)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	int rc;
3562306a36Sopenharmony_ci	u32 d1, d2;
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	ntfs_debug("Entering.");
3862306a36Sopenharmony_ci	// FIXME:  We don't really want to bug here.
3962306a36Sopenharmony_ci	BUG_ON(data1_len != data2_len);
4062306a36Sopenharmony_ci	BUG_ON(data1_len != 4);
4162306a36Sopenharmony_ci	d1 = le32_to_cpup(data1);
4262306a36Sopenharmony_ci	d2 = le32_to_cpup(data2);
4362306a36Sopenharmony_ci	if (d1 < d2)
4462306a36Sopenharmony_ci		rc = -1;
4562306a36Sopenharmony_ci	else {
4662306a36Sopenharmony_ci		if (d1 == d2)
4762306a36Sopenharmony_ci			rc = 0;
4862306a36Sopenharmony_ci		else
4962306a36Sopenharmony_ci			rc = 1;
5062306a36Sopenharmony_ci	}
5162306a36Sopenharmony_ci	ntfs_debug("Done, returning %i", rc);
5262306a36Sopenharmony_ci	return rc;
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_citypedef int (*ntfs_collate_func_t)(ntfs_volume *, const void *, const int,
5662306a36Sopenharmony_ci		const void *, const int);
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic ntfs_collate_func_t ntfs_do_collate0x0[3] = {
5962306a36Sopenharmony_ci	ntfs_collate_binary,
6062306a36Sopenharmony_ci	NULL/*ntfs_collate_file_name*/,
6162306a36Sopenharmony_ci	NULL/*ntfs_collate_unicode_string*/,
6262306a36Sopenharmony_ci};
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistatic ntfs_collate_func_t ntfs_do_collate0x1[4] = {
6562306a36Sopenharmony_ci	ntfs_collate_ntofs_ulong,
6662306a36Sopenharmony_ci	NULL/*ntfs_collate_ntofs_sid*/,
6762306a36Sopenharmony_ci	NULL/*ntfs_collate_ntofs_security_hash*/,
6862306a36Sopenharmony_ci	NULL/*ntfs_collate_ntofs_ulongs*/,
6962306a36Sopenharmony_ci};
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/**
7262306a36Sopenharmony_ci * ntfs_collate - collate two data items using a specified collation rule
7362306a36Sopenharmony_ci * @vol:	ntfs volume to which the data items belong
7462306a36Sopenharmony_ci * @cr:		collation rule to use when comparing the items
7562306a36Sopenharmony_ci * @data1:	first data item to collate
7662306a36Sopenharmony_ci * @data1_len:	length in bytes of @data1
7762306a36Sopenharmony_ci * @data2:	second data item to collate
7862306a36Sopenharmony_ci * @data2_len:	length in bytes of @data2
7962306a36Sopenharmony_ci *
8062306a36Sopenharmony_ci * Collate the two data items @data1 and @data2 using the collation rule @cr
8162306a36Sopenharmony_ci * and return -1, 0, ir 1 if @data1 is found, respectively, to collate before,
8262306a36Sopenharmony_ci * to match, or to collate after @data2.
8362306a36Sopenharmony_ci *
8462306a36Sopenharmony_ci * For speed we use the collation rule @cr as an index into two tables of
8562306a36Sopenharmony_ci * function pointers to call the appropriate collation function.
8662306a36Sopenharmony_ci */
8762306a36Sopenharmony_ciint ntfs_collate(ntfs_volume *vol, COLLATION_RULE cr,
8862306a36Sopenharmony_ci		const void *data1, const int data1_len,
8962306a36Sopenharmony_ci		const void *data2, const int data2_len) {
9062306a36Sopenharmony_ci	int i;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	ntfs_debug("Entering.");
9362306a36Sopenharmony_ci	/*
9462306a36Sopenharmony_ci	 * FIXME:  At the moment we only support COLLATION_BINARY and
9562306a36Sopenharmony_ci	 * COLLATION_NTOFS_ULONG, so we BUG() for everything else for now.
9662306a36Sopenharmony_ci	 */
9762306a36Sopenharmony_ci	BUG_ON(cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG);
9862306a36Sopenharmony_ci	i = le32_to_cpu(cr);
9962306a36Sopenharmony_ci	BUG_ON(i < 0);
10062306a36Sopenharmony_ci	if (i <= 0x02)
10162306a36Sopenharmony_ci		return ntfs_do_collate0x0[i](vol, data1, data1_len,
10262306a36Sopenharmony_ci				data2, data2_len);
10362306a36Sopenharmony_ci	BUG_ON(i < 0x10);
10462306a36Sopenharmony_ci	i -= 0x10;
10562306a36Sopenharmony_ci	if (likely(i <= 3))
10662306a36Sopenharmony_ci		return ntfs_do_collate0x1[i](vol, data1, data1_len,
10762306a36Sopenharmony_ci				data2, data2_len);
10862306a36Sopenharmony_ci	BUG();
10962306a36Sopenharmony_ci	return 0;
11062306a36Sopenharmony_ci}
111