| // SPDX-License-Identifier: GPL-2.0 | 
 | /* | 
 |  * | 
 |  * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved. | 
 |  * | 
 |  */ | 
 |  | 
 | #include <linux/types.h> | 
 |  | 
 | #include "ntfs_fs.h" | 
 |  | 
 | #define BITS_IN_SIZE_T (sizeof(size_t) * 8) | 
 |  | 
 | /* | 
 |  * fill_mask[i] - first i bits are '1' , i = 0,1,2,3,4,5,6,7,8 | 
 |  * fill_mask[i] = 0xFF >> (8-i) | 
 |  */ | 
 | static const u8 fill_mask[] = { 0x00, 0x01, 0x03, 0x07, 0x0F, | 
 | 				0x1F, 0x3F, 0x7F, 0xFF }; | 
 |  | 
 | /* | 
 |  * zero_mask[i] - first i bits are '0' , i = 0,1,2,3,4,5,6,7,8 | 
 |  * zero_mask[i] = 0xFF << i | 
 |  */ | 
 | static const u8 zero_mask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, | 
 | 				0xE0, 0xC0, 0x80, 0x00 }; | 
 |  | 
 | /* | 
 |  * are_bits_clear | 
 |  * | 
 |  * Return: True if all bits [bit, bit+nbits) are zeros "0". | 
 |  */ | 
 | bool are_bits_clear(const void *lmap, size_t bit, size_t nbits) | 
 | { | 
 | 	size_t pos = bit & 7; | 
 | 	const u8 *map = (u8 *)lmap + (bit >> 3); | 
 |  | 
 | 	if (pos) { | 
 | 		if (8 - pos >= nbits) | 
 | 			return !nbits || !(*map & fill_mask[pos + nbits] & | 
 | 					   zero_mask[pos]); | 
 |  | 
 | 		if (*map++ & zero_mask[pos]) | 
 | 			return false; | 
 | 		nbits -= 8 - pos; | 
 | 	} | 
 |  | 
 | 	pos = ((size_t)map) & (sizeof(size_t) - 1); | 
 | 	if (pos) { | 
 | 		pos = sizeof(size_t) - pos; | 
 | 		if (nbits >= pos * 8) { | 
 | 			for (nbits -= pos * 8; pos; pos--, map++) { | 
 | 				if (*map) | 
 | 					return false; | 
 | 			} | 
 | 		} | 
 | 	} | 
 |  | 
 | 	for (pos = nbits / BITS_IN_SIZE_T; pos; pos--, map += sizeof(size_t)) { | 
 | 		if (*((size_t *)map)) | 
 | 			return false; | 
 | 	} | 
 |  | 
 | 	for (pos = (nbits % BITS_IN_SIZE_T) >> 3; pos; pos--, map++) { | 
 | 		if (*map) | 
 | 			return false; | 
 | 	} | 
 |  | 
 | 	pos = nbits & 7; | 
 | 	if (pos && (*map & fill_mask[pos])) | 
 | 		return false; | 
 |  | 
 | 	return true; | 
 | } | 
 |  | 
 | /* | 
 |  * are_bits_set | 
 |  * | 
 |  * Return: True if all bits [bit, bit+nbits) are ones "1". | 
 |  */ | 
 | bool are_bits_set(const void *lmap, size_t bit, size_t nbits) | 
 | { | 
 | 	u8 mask; | 
 | 	size_t pos = bit & 7; | 
 | 	const u8 *map = (u8 *)lmap + (bit >> 3); | 
 |  | 
 | 	if (pos) { | 
 | 		if (8 - pos >= nbits) { | 
 | 			mask = fill_mask[pos + nbits] & zero_mask[pos]; | 
 | 			return !nbits || (*map & mask) == mask; | 
 | 		} | 
 |  | 
 | 		mask = zero_mask[pos]; | 
 | 		if ((*map++ & mask) != mask) | 
 | 			return false; | 
 | 		nbits -= 8 - pos; | 
 | 	} | 
 |  | 
 | 	pos = ((size_t)map) & (sizeof(size_t) - 1); | 
 | 	if (pos) { | 
 | 		pos = sizeof(size_t) - pos; | 
 | 		if (nbits >= pos * 8) { | 
 | 			for (nbits -= pos * 8; pos; pos--, map++) { | 
 | 				if (*map != 0xFF) | 
 | 					return false; | 
 | 			} | 
 | 		} | 
 | 	} | 
 |  | 
 | 	for (pos = nbits / BITS_IN_SIZE_T; pos; pos--, map += sizeof(size_t)) { | 
 | 		if (*((size_t *)map) != MINUS_ONE_T) | 
 | 			return false; | 
 | 	} | 
 |  | 
 | 	for (pos = (nbits % BITS_IN_SIZE_T) >> 3; pos; pos--, map++) { | 
 | 		if (*map != 0xFF) | 
 | 			return false; | 
 | 	} | 
 |  | 
 | 	pos = nbits & 7; | 
 | 	if (pos) { | 
 | 		mask = fill_mask[pos]; | 
 | 		if ((*map & mask) != mask) | 
 | 			return false; | 
 | 	} | 
 |  | 
 | 	return true; | 
 | } |