|  | // 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; | 
|  | } |