aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2014-03-11 15:10:43 -0400
committerJeff Mahoney <jeffm@suse.com>2014-03-11 16:39:52 -0400
commit6bdb171b9e0cf655b16207a4906219600bbbdf06 (patch)
tree8d2aec3416c1a06e7bcf96c4f027376937c41b81
parente51777cf55df2a5dd9295ecf4048118ac6eb0702 (diff)
downloadreiserfsprogs-6bdb171b9e0cf655b16207a4906219600bbbdf06.tar.gz
reiserfslib: add basic extended attribute helpers
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
-rw-r--r--include/reiserfs_fs.h26
-rw-r--r--include/reiserfs_lib.h5
-rw-r--r--reiserfscore/Makefile.am2
-rw-r--r--reiserfscore/xattr.c116
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;
+ }
+}