#include #include #include #include "reiserfs_lib.h" static inline unsigned short from32to16(unsigned int x) { /* add up 16-bit and 16-bit for 16+c bit */ x = (x & 0xffff) + (x >> 16); /* add up carry.. */ x = (x & 0xffff) + (x >> 16); return x; } static unsigned int do_csum(const unsigned char *buff, int len) { int odd; unsigned int result = 0; if (len <= 0) goto out; odd = 1 & (unsigned long) buff; if (odd) { #ifdef __LITTLE_ENDIAN result += (*buff << 8); #else result = *buff; #endif len--; buff++; } if (len >= 2) { if (2 & (unsigned long) buff) { result += *(unsigned short *) buff; len -= 2; buff += 2; } if (len >= 4) { const unsigned char *end = buff + ((unsigned)len & ~3); unsigned int carry = 0; do { unsigned int w = *(unsigned int *) buff; buff += 4; result += carry; result += w; carry = (w > result); } while (buff < end); result += carry; result = (result & 0xffff) + (result >> 16); } if (len & 2) { result += *(unsigned short *) buff; buff += 2; } } if (len & 1) #ifdef __LITTLE_ENDIAN result += *buff; #else result += (*buff << 8); #endif result = from32to16(result); if (odd) result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); out: return result; } __wsum csum_partial(const void *buff, int len, __wsum wsum) { unsigned int sum = (__force unsigned int)wsum; unsigned int result = do_csum(buff, len); /* add in old sum, and carry.. */ result += sum; if (sum > result) result += 1; return (__force __wsum)result; } inline __u32 reiserfs_xattr_hash(const char *msg, int len) { return csum_partial(msg, len, 0); } int reiserfs_check_xattr(const void *body, int len) { const struct reiserfs_xattr_header *xah = body; int hdrsz = sizeof(struct reiserfs_xattr_header); __u32 hash; if (len < hdrsz) return -EINVAL; hash = reiserfs_xattr_hash(body + hdrsz, len - hdrsz); return xah->h_magic == cpu_to_le32(REISERFS_XATTR_MAGIC) && le32_to_cpu(xah->h_hash) == hash; } int reiserfs_acl_count(size_t size) { ssize_t s; size -= sizeof(struct reiserfs_acl_header); s = size - 4 * sizeof(struct reiserfs_acl_entry_short); if (s < 0) { if (size % sizeof(struct reiserfs_acl_entry_short)) return -1; return size / sizeof(struct reiserfs_acl_entry_short); } else { if (s % sizeof(struct reiserfs_acl_entry)) return -1; return s / sizeof(struct reiserfs_acl_entry) + 4; } }