diff options
author | Jeff Mahoney <jeffm@suse.com> | 2014-03-11 15:10:43 -0400 |
---|---|---|
committer | Jeff Mahoney <jeffm@suse.com> | 2014-03-11 16:39:52 -0400 |
commit | 6bdb171b9e0cf655b16207a4906219600bbbdf06 (patch) | |
tree | 8d2aec3416c1a06e7bcf96c4f027376937c41b81 | |
parent | e51777cf55df2a5dd9295ecf4048118ac6eb0702 (diff) | |
download | reiserfsprogs-6bdb171b9e0cf655b16207a4906219600bbbdf06.tar.gz |
reiserfslib: add basic extended attribute helpers
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
-rw-r--r-- | include/reiserfs_fs.h | 26 | ||||
-rw-r--r-- | include/reiserfs_lib.h | 5 | ||||
-rw-r--r-- | reiserfscore/Makefile.am | 2 | ||||
-rw-r--r-- | reiserfscore/xattr.c | 116 |
4 files changed, 147 insertions, 2 deletions
diff --git a/include/reiserfs_fs.h b/include/reiserfs_fs.h index cb84fa8..fc39d7a 100644 --- a/include/reiserfs_fs.h +++ b/include/reiserfs_fs.h @@ -1402,6 +1402,32 @@ struct buffer_info { #define MAX_DIRECT_ITEM_LEN(size) ((size) - BLKH_SIZE - 2*IH_SIZE - SD_SIZE - UNFM_P_SIZE) #define MAX_INDIRECT_ITEM_LEN(size) MAX_ITEM_LEN(size) +/* Extended attributes */ +/* Magic value in header */ +#define REISERFS_XATTR_MAGIC 0x52465841 /* "RFXA" */ + +struct reiserfs_xattr_header { + __le32 h_magic; + __le32 h_hash; +}; + +/* ACLs */ +#define REISERFS_ACL_VERSION 0x0001 +struct reiserfs_acl_entry { + __le16 e_tag; + __le16 e_perm; + __le32 e_id; +}; + +struct reiserfs_acl_entry_short { + __le16 e_tag; + __le16 e_perm; +}; + +struct reiserfs_acl_header { + __le32 a_version; +}; + /***************************************************************************/ /* FUNCTION DECLARATIONS */ /***************************************************************************/ diff --git a/include/reiserfs_lib.h b/include/reiserfs_lib.h index 3513071..e00099c 100644 --- a/include/reiserfs_lib.h +++ b/include/reiserfs_lib.h @@ -431,5 +431,8 @@ int can_we_format_it(char *device_name, int force); return 0;\ }\ - +/* xattr.c */ +__u32 reiserfs_xattr_hash(const char *msg, int len); +int reiserfs_check_xattr(const void *body, int len); +int reiserfs_acl_count(size_t size); #endif /* REISERFSPROGS_LIB_H */ diff --git a/reiserfscore/Makefile.am b/reiserfscore/Makefile.am index f9b1e61..a140a23 100644 --- a/reiserfscore/Makefile.am +++ b/reiserfscore/Makefile.am @@ -2,7 +2,7 @@ lib_LTLIBRARIES = libreiserfscore.la libreiserfscore_la_SOURCES = do_balan.c fix_node.c hashes.c ibalance.c \ lbalance.c prints.c stree.c node_formats.c \ - reiserfslib.c bitmap.c journal.c includes.h + reiserfslib.c bitmap.c journal.c xattr.c includes.h libreiserfscore_la_LIBADD = ../lib/libmisc.la pkgconfigdir = $(libdir)/pkgconfig diff --git a/reiserfscore/xattr.c b/reiserfscore/xattr.c new file mode 100644 index 0000000..8ad81f3 --- /dev/null +++ b/reiserfscore/xattr.c @@ -0,0 +1,116 @@ +#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; + } +} |