| #include <sys/types.h> |
| #include <stdio.h> |
| #include <errno.h> |
| #include <sys/acl.h> |
| #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; |
| } |
| } |