/
githubmirror
/
xfsprogs
Обзор
Документация
Войти
/
githubmirror
/
xfsprogs
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
preadv2
db/bit.c
168 строк
4 KB
Mark Tinguely
xfs_db: fix the setting of unaligned directory fields
19 фев 2014, 04:16
19 фев 2014, 04:16
dc15132
Код
Авторство
О чём код?
/* * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <xfs/libxfs.h> #include "bit.h" #undef setbit /* defined in param.h on Linux */ static int getbit(char *ptr, int bit); static void setbit(char *ptr, int bit, int val); static int getbit( char *ptr, int bit) { int mask; int shift; ptr += byteize(bit); bit = bitoffs(bit); shift = 7 - bit; mask = 1 << shift; return (*ptr & mask) >> shift; } static void setbit( char *ptr, int bit, int val) { int mask; int shift; ptr += byteize(bit); bit = bitoffs(bit); shift = 7 - bit; mask = (1 << shift); if (val) { *ptr |= mask; } else { mask = ~mask; *ptr &= mask; } } __int64_t getbitval( void *obj, int bitoff, int nbits, int flags) { int bit; int i; char *p; __int64_t rval; int signext; int z1, z2, z3, z4; ASSERT(nbits<=64); p = (char *)obj + byteize(bitoff); bit = bitoffs(bitoff); signext = (flags & BVSIGNED) != 0; z4 = ((__psint_t)p & 0xf) == 0 && bit == 0; if (nbits == 64 && z4) return be64_to_cpu(*(__be64 *)p); z3 = ((__psint_t)p & 0x7) == 0 && bit == 0; if (nbits == 32 && z3) { if (signext) return (__s32)be32_to_cpu(*(__be32 *)p); else return (__u32)be32_to_cpu(*(__be32 *)p); } z2 = ((__psint_t)p & 0x3) == 0 && bit == 0; if (nbits == 16 && z2) { if (signext) return (__s16)be16_to_cpu(*(__be16 *)p); else return (__u16)be16_to_cpu(*(__be16 *)p); } z1 = ((__psint_t)p & 0x1) == 0 && bit == 0; if (nbits == 8 && z1) { if (signext) return *(__s8 *)p; else return *(__u8 *)p; } for (i = 0, rval = 0LL; i < nbits; i++) { if (getbit(p, bit + i)) { /* If the last bit is on and we care about sign * bits and we don't have a full 64 bit * container, turn all bits on between the * sign bit and the most sig bit. */ /* handle endian swap here */ #if __BYTE_ORDER == LITTLE_ENDIAN if (i == 0 && signext && nbits < 64) rval = -1LL << nbits; rval |= 1LL << (nbits - i - 1); #else if ((i == (nbits - 1)) && signext && nbits < 64) rval |= (-1LL << nbits); rval |= 1LL << (nbits - i - 1); #endif } } return rval; } /* * The input data can be 8, 16, 32, and 64 sized numeric values * aligned on a byte boundry, or odd sized numbers stored on odd * aligned offset (for example the bmbt fields). * * The input data sent to this routine has been converted to big endian * and has been adjusted in the array so that the first input bit is to * be written in the first bit in the output. * * If the field length and the output buffer are byte aligned, then use * memcpy from the input to the output, but if either entries are not byte * aligned, then loop over the entire bit range reading the input value * and set/clear the matching bit in the output. * * example when ibuf is not multiple of a byte in length: * * ibuf: | BBBBBBBB | bbbxxxxx | * \\\\\\\\--\\\\ * obuf+bitoff: | xBBBBBBB | Bbbbxxxx | * */ void setbitval( void *obuf, /* start of buffer to write into */ int bitoff, /* bit offset into the output buffer */ int nbits, /* number of bits to write */ void *ibuf) /* source bits */ { char *in = ibuf; char *out = obuf; int bit; if (bitoff % NBBY || nbits % NBBY) { for (bit = 0; bit < nbits; bit++) setbit(out, bit + bitoff, getbit(in, bit)); } else memcpy(out + byteize(bitoff), in, byteize(nbits)); }