ref: 5ddffb5961175beb6f5946b13cbc977662955115
parent: 6e79cef4b05e2863fef1eb0da4de7a4afc920494
author: root <ngkaho1234@gmail.com>
date: Fri Oct 9 09:22:40 EDT 2015
Experimental EA public routines.
--- a/lwext4/ext4.c
+++ b/lwext4/ext4.c
@@ -1925,6 +1925,259 @@
return r;
}
+int ext4_setxattr(char *path,
+ char *name,
+ size_t name_len,
+ void *data,
+ size_t data_size,
+ bool replace)
+{
+ int r = EOK;
+ ext4_file f;
+ uint32_t inode;
+ uint8_t name_index;
+ char *dissected_name = NULL;
+ size_t dissected_len = 0;
+ struct ext4_xattr_ref xattr_ref;
+ struct ext4_inode_ref inode_ref;
+ struct ext4_mountpoint *mp = ext4_get_mount(path);
+ if (!mp)
+ return ENOENT;
+
+ dissected_name = ext4_extract_xattr_name(name, name_len,
+ &name_index, &dissected_len);
+ if (!dissected_len)
+ return EINVAL;
+
+ EXT4_MP_LOCK(mp);
+ r = ext4_generic_open2(&f, path, O_RDWR,
+ EXT4_DIRENTRY_UNKNOWN, 0, 0);
+ if (r != EOK)
+ goto Finish;
+ inode = f.inode;
+ ext4_fclose(&f);
+
+ r = ext4_fs_get_inode_ref(&mp->fs, inode, &inode_ref);
+ if (r != EOK)
+ goto Finish;
+
+ r = ext4_fs_get_xattr_ref(&mp->fs, &inode_ref,
+ &xattr_ref);
+ if (r != EOK) {
+ ext4_fs_put_inode_ref(&inode_ref);
+ goto Finish;
+ }
+
+ r = ext4_fs_set_xattr(&xattr_ref, name_index,
+ dissected_name, dissected_len,
+ data, data_size,
+ replace);
+
+ ext4_fs_put_xattr_ref(&xattr_ref);
+ ext4_fs_put_inode_ref(&inode_ref);
+Finish:
+ EXT4_MP_UNLOCK(mp);
+ return r;
+}
+
+int ext4_getxattr(char *path,
+ char *name,
+ size_t name_len,
+ void *buf,
+ size_t buf_size,
+ size_t *data_size)
+{
+ int r = EOK;
+ ext4_file f;
+ uint32_t inode;
+ uint8_t name_index;
+ char *dissected_name = NULL;
+ size_t dissected_len = 0;
+ struct ext4_xattr_ref xattr_ref;
+ struct ext4_inode_ref inode_ref;
+ struct ext4_mountpoint *mp = ext4_get_mount(path);
+ if (!mp)
+ return ENOENT;
+
+ dissected_name = ext4_extract_xattr_name(name, name_len,
+ &name_index, &dissected_len);
+ if (!dissected_len)
+ return EINVAL;
+
+ EXT4_MP_LOCK(mp);
+ r = ext4_generic_open2(&f, path, O_RDWR,
+ EXT4_DIRENTRY_UNKNOWN, 0, 0);
+ if (r != EOK)
+ goto Finish;
+ inode = f.inode;
+ ext4_fclose(&f);
+
+ r = ext4_fs_get_inode_ref(&mp->fs, inode, &inode_ref);
+ if (r != EOK)
+ goto Finish;
+
+ r = ext4_fs_get_xattr_ref(&mp->fs, &inode_ref,
+ &xattr_ref);
+ if (r != EOK) {
+ ext4_fs_put_inode_ref(&inode_ref);
+ goto Finish;
+ }
+
+ r = ext4_fs_get_xattr(&xattr_ref, name_index,
+ dissected_name, dissected_len,
+ buf, buf_size, data_size);
+
+ ext4_fs_put_xattr_ref(&xattr_ref);
+ ext4_fs_put_inode_ref(&inode_ref);
+Finish:
+ EXT4_MP_UNLOCK(mp);
+ return r;
+}
+
+struct ext4_listxattr_iterator {
+ char *list;
+ char *list_ptr;
+ size_t size;
+ size_t ret_size;
+ bool list_too_small;
+ bool get_required_size;
+};
+
+static int ext4_iterate_ea_list(struct ext4_xattr_ref *ref,
+ struct ext4_xattr_item *item)
+{
+ struct ext4_listxattr_iterator *lxi;
+ lxi = ref->iter_arg;
+ if (!lxi->get_required_size) {
+ size_t prefix_len;
+ const char *prefix;
+ prefix = ext4_get_xattr_name_prefix(item->name_index,
+ &prefix_len);
+ if (lxi->ret_size +
+ prefix_len + item->name_len + 1 >
+ lxi->size) {
+
+ lxi->list_too_small = 1;
+ return EXT4_XATTR_ITERATE_STOP;
+ }
+ if (prefix) {
+ memcpy(lxi->list_ptr, prefix, prefix_len);
+ lxi->list_ptr += prefix_len;
+ }
+ memcpy(lxi->list_ptr, item->name, item->name_len);
+ lxi->list_ptr[item->name_len] = 0;
+ lxi->list_ptr += item->name_len + 1;
+ }
+ lxi->ret_size += item->name_len + 1;
+ return EXT4_XATTR_ITERATE_CONT;
+}
+
+int ext4_listxattr(const char *path, char *list, size_t size,
+ size_t *ret_size)
+{
+ int r = EOK;
+ ext4_file f;
+ uint32_t inode;
+ struct ext4_xattr_ref xattr_ref;
+ struct ext4_inode_ref inode_ref;
+ struct ext4_listxattr_iterator lxi;
+ struct ext4_mountpoint *mp = ext4_get_mount(path);
+ if (!mp)
+ return ENOENT;
+
+ lxi.list = list;
+ lxi.list_ptr = list;
+ lxi.size = size;
+ lxi.ret_size = 0;
+ lxi.list_too_small = false;
+ lxi.get_required_size = (!size) ? true : false;
+
+ EXT4_MP_LOCK(mp);
+ r = ext4_generic_open2(&f, path, O_RDWR,
+ EXT4_DIRENTRY_UNKNOWN, 0, 0);
+ if (r != EOK)
+ goto Finish;
+ inode = f.inode;
+ ext4_fclose(&f);
+
+ r = ext4_fs_get_inode_ref(&mp->fs, inode, &inode_ref);
+ if (r != EOK)
+ goto Finish;
+
+ r = ext4_fs_get_xattr_ref(&mp->fs, &inode_ref,
+ &xattr_ref);
+ if (r != EOK) {
+ ext4_fs_put_inode_ref(&inode_ref);
+ goto Finish;
+ }
+
+ xattr_ref.iter_arg = &lxi;
+ ext4_fs_xattr_iterate(&xattr_ref, ext4_iterate_ea_list);
+ if (ret_size && lxi.list_too_small) {
+ *ret_size = lxi.ret_size;
+ r = ERANGE;
+ }
+
+ ext4_fs_put_xattr_ref(&xattr_ref);
+ ext4_fs_put_inode_ref(&inode_ref);
+Finish:
+ EXT4_MP_UNLOCK(mp);
+ return r;
+
+}
+
+int ext4_removexattr(char *path,
+ char *name,
+ size_t name_len)
+{
+ int r = EOK;
+ ext4_file f;
+ uint32_t inode;
+ uint8_t name_index;
+ char *dissected_name = NULL;
+ size_t dissected_len = 0;
+ struct ext4_xattr_ref xattr_ref;
+ struct ext4_inode_ref inode_ref;
+ struct ext4_mountpoint *mp = ext4_get_mount(path);
+ if (!mp)
+ return ENOENT;
+
+ dissected_name = ext4_extract_xattr_name(name, name_len,
+ &name_index, &dissected_len);
+ if (!dissected_len)
+ return EINVAL;
+
+ EXT4_MP_LOCK(mp);
+ r = ext4_generic_open2(&f, path, O_RDWR,
+ EXT4_DIRENTRY_UNKNOWN, 0, 0);
+ if (r != EOK)
+ goto Finish;
+ inode = f.inode;
+ ext4_fclose(&f);
+
+ r = ext4_fs_get_inode_ref(&mp->fs, inode, &inode_ref);
+ if (r != EOK)
+ goto Finish;
+
+ r = ext4_fs_get_xattr_ref(&mp->fs, &inode_ref,
+ &xattr_ref);
+ if (r != EOK) {
+ ext4_fs_put_inode_ref(&inode_ref);
+ goto Finish;
+ }
+
+ r = ext4_fs_remove_xattr(&xattr_ref,
+ name_index, dissected_name,
+ dissected_len);
+
+ ext4_fs_put_xattr_ref(&xattr_ref);
+ ext4_fs_put_inode_ref(&inode_ref);
+Finish:
+ EXT4_MP_UNLOCK(mp);
+ return r;
+
+}
+
/*********************************DIRECTORY OPERATION************************/
int ext4_dir_rm(const char *path)
--- a/lwext4/ext4.h
+++ b/lwext4/ext4.h
@@ -363,6 +363,18 @@
int ext4_readlink(const char *path, char *buf, size_t bufsize, size_t *rcnt);
+int ext4_setxattr(char *path, char *name, size_t name_len,
+ void *data, size_t data_size,
+ bool replace);
+int ext4_getxattr(char *path, char *name, size_t name_len,
+ void *buf, size_t buf_size, size_t *data_size);
+int ext4_listxattr(const char *path, char *list, size_t size,
+ size_t *ret_size);
+int ext4_removexattr(char *path,
+ char *name,
+ size_t name_len);
+
+
/*********************************DIRECTORY OPERATION***********************/
/**@brief Recursive directory remove.
--- a/lwext4/ext4_types.h
+++ b/lwext4/ext4_types.h
@@ -689,6 +689,7 @@
size_t ea_size;
struct ext4_fs *fs;
+ void *iter_arg;
struct ext4_xattr_item *iter_from;
RB_HEAD(ext4_xattr_tree,
--- a/lwext4/ext4_xattr.c
+++ b/lwext4/ext4_xattr.c
@@ -655,7 +655,7 @@
}
void ext4_fs_xattr_iterate(struct ext4_xattr_ref *ref,
- int(iter)(struct ext4_xattr_ref *ref,
+ int (*iter)(struct ext4_xattr_ref *ref,
struct ext4_xattr_item *item))
{
struct ext4_xattr_item *item;
@@ -723,7 +723,7 @@
int ext4_fs_get_xattr(struct ext4_xattr_ref *ref, uint8_t name_index,
char *name, size_t name_len, void *buf, size_t buf_size,
- size_t *size_got)
+ size_t *data_size)
{
int ret = EOK;
size_t item_size = 0;
@@ -742,8 +742,8 @@
memcpy(buf, item->data, buf_size);
Finish:
- if (size_got)
- *size_got = buf_size;
+ if (data_size)
+ *data_size = item_size;
return ret;
}
@@ -799,7 +799,7 @@
}
struct xattr_prefix {
- char *prefix;
+ const char *prefix;
uint8_t name_index;
};
@@ -816,8 +816,12 @@
{
int i;
ext4_assert(name_index);
- if (!full_name_len)
+ if (!full_name_len) {
+ if (name_len)
+ *name_len = 0;
+
return NULL;
+ }
for (i = 0; prefix_tbl[i].prefix; i++) {
size_t prefix_len = strlen(prefix_tbl[i].prefix);
@@ -832,6 +836,25 @@
}
if (name_len)
*name_len = 0;
+
+ return NULL;
+}
+
+const char *ext4_get_xattr_name_prefix(uint8_t name_index, size_t *ret_prefix_len)
+{
+ int i;
+
+ for (i = 0; prefix_tbl[i].prefix; i++) {
+ size_t prefix_len = strlen(prefix_tbl[i].prefix);
+ if (prefix_tbl[i].name_index == name_index) {
+ if (ret_prefix_len)
+ *ret_prefix_len = prefix_len;
+
+ return prefix_tbl[i].prefix;
+ }
+ }
+ if (ret_prefix_len)
+ *ret_prefix_len = 0;
return NULL;
}
--- a/lwext4/ext4_xattr.h
+++ b/lwext4/ext4_xattr.h
@@ -54,10 +54,10 @@
int ext4_fs_get_xattr(struct ext4_xattr_ref *ref, uint8_t name_index,
char *name, size_t name_len, void *buf, size_t buf_size,
- size_t *size_got);
+ size_t *data_size);
void ext4_fs_xattr_iterate(struct ext4_xattr_ref *ref,
- int(iter)(struct ext4_xattr_ref *ref,
+ int (*iter)(struct ext4_xattr_ref *ref,
struct ext4_xattr_item *item));
void ext4_fs_xattr_iterate_reset(struct ext4_xattr_ref *ref);
@@ -64,6 +64,9 @@
char *ext4_extract_xattr_name(char *full_name, size_t full_name_len,
uint8_t *name_index, size_t *name_len);
+
+const char *ext4_get_xattr_name_prefix(uint8_t name_index,
+ size_t *ret_prefix_len);
#endif
/**