diff options
| author | root <ngkaho1234@gmail.com> | 2015-10-09 13:22:40 +0000 |
|---|---|---|
| committer | root <ngkaho1234@gmail.com> | 2015-10-09 13:22:40 +0000 |
| commit | 5ddffb5961175beb6f5946b13cbc977662955115 (patch) | |
| tree | 8b87241306542911df9b1b723b1e6488d17472d2 | |
| parent | 6e79cef4b05e2863fef1eb0da4de7a4afc920494 (diff) | |
Experimental EA public routines.
| -rw-r--r-- | lwext4/ext4.c | 253 | ||||
| -rw-r--r-- | lwext4/ext4.h | 12 | ||||
| -rw-r--r-- | lwext4/ext4_types.h | 1 | ||||
| -rw-r--r-- | lwext4/ext4_xattr.c | 35 | ||||
| -rw-r--r-- | lwext4/ext4_xattr.h | 7 |
5 files changed, 300 insertions, 8 deletions
diff --git a/lwext4/ext4.c b/lwext4/ext4.c index 0cdf045..446d026 100644 --- a/lwext4/ext4.c +++ b/lwext4/ext4.c @@ -1925,6 +1925,259 @@ Finish: 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) diff --git a/lwext4/ext4.h b/lwext4/ext4.h index ae70501..9b44f36 100644 --- a/lwext4/ext4.h +++ b/lwext4/ext4.h @@ -363,6 +363,18 @@ int ext4_fsymlink(const char *target, const char *path); 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. diff --git a/lwext4/ext4_types.h b/lwext4/ext4_types.h index cdd298f..52e12d8 100644 --- a/lwext4/ext4_types.h +++ b/lwext4/ext4_types.h @@ -689,6 +689,7 @@ struct ext4_xattr_ref { size_t ea_size; struct ext4_fs *fs; + void *iter_arg; struct ext4_xattr_item *iter_from; RB_HEAD(ext4_xattr_tree, diff --git a/lwext4/ext4_xattr.c b/lwext4/ext4_xattr.c index 25681c6..2eb6edf 100644 --- a/lwext4/ext4_xattr.c +++ b/lwext4/ext4_xattr.c @@ -655,7 +655,7 @@ Finish: } 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_remove_xattr(struct ext4_xattr_ref *ref, uint8_t name_index, 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 @@ int ext4_fs_get_xattr(struct ext4_xattr_ref *ref, uint8_t name_index, 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 @@ void ext4_fs_put_xattr_ref(struct ext4_xattr_ref *ref) } struct xattr_prefix { - char *prefix; + const char *prefix; uint8_t name_index; }; @@ -816,8 +816,12 @@ char *ext4_extract_xattr_name(char *full_name, size_t full_name_len, { 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); @@ -836,6 +840,25 @@ char *ext4_extract_xattr_name(char *full_name, size_t full_name_len, 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; +} + /** * @} */ diff --git a/lwext4/ext4_xattr.h b/lwext4/ext4_xattr.h index f03bae3..d353d1e 100644 --- a/lwext4/ext4_xattr.h +++ b/lwext4/ext4_xattr.h @@ -54,10 +54,10 @@ int ext4_fs_remove_xattr(struct ext4_xattr_ref *ref, uint8_t name_index, 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); @@ -65,6 +65,9 @@ void ext4_fs_xattr_iterate_reset(struct ext4_xattr_ref *ref); 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 /** * @} |
