hfsplus: add support of manipulation by attributes file
Subsystems (2)
Vyacheslav Dubeyko
maintainerPATCH v3 5/5 hfsplus: add support of manipulation by attributes file
Hi,
This patch adds support of manipulation by attributes file.
With the best regards,
Vyacheslav Dubeyko.
---
From: Vyacheslav Dubeyko <[email protected]>
Subject: [PATCH v3 5/5] hfsplus: add support of manipulation by attributes file
This patch adds support of manipulation by attributes file.
Reported-by Hin-Tak Leung <[email protected]>
Signed-off-by Vyacheslav Dubeyko <[email protected]>
--- fs/hfsplus/Makefile | 4 +- fs/hfsplus/bfind.c | 93 ++++++++++++++++++++++++++++++++++------ fs/hfsplus/bnode.c | 6 ++- fs/hfsplus/brec.c | 23 ++++++---- fs/hfsplus/btree.c | 8 ++++ fs/hfsplus/catalog.c | 36 ++++++++++------ fs/hfsplus/dir.c | 55 +++++++++++++++++------- fs/hfsplus/extents.c | 4 +- fs/hfsplus/hfsplus_fs.h | 52 +++++++++++++++++++---- fs/hfsplus/inode.c | 18 +++++++- fs/hfsplus/ioctl.c | 108 ----------------------------------------------- fs/hfsplus/super.c | 56 ++++++++++++++++++++++-- fs/hfsplus/unicode.c | 7 +-- 13 files changed, 287 insertions(+), 183 deletions(-)
fs/hfsplus/Makefile +2 -2
@@ -5,5 +5,5 @@ obj-$(CONFIG_HFSPLUS_FS) += hfsplus.o hfsplus-objs := super.o options.o inode.o ioctl.o extents.o catalog.o dir.o btree.o \ - bnode.o brec.o bfind.o tables.o unicode.o wrapper.o bitmap.o part_tbl.o - + bnode.o brec.o bfind.o tables.o unicode.o wrapper.o bitmap.o part_tbl.o \ + attributes.o xattr.o xattr_user.o xattr_security.o xattr_trusted.o
fs/hfsplus/bfind.c +80 -13
152 lines not on this page · raw message
fs/hfsplus/bnode.c +4 -2
@@ -62,7 +62,8 @@ void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off) tree = node->tree;if (node->type ==HFS_NODE_LEAF || - tree->attributes &HFS_TREE_VARIDXKEYS ) + tree->attributes &HFS_TREE_VARIDXKEYS || + node->tree->cnid ==HFSPLUS_ATTR_CNID ) key_len =hfs_bnode_read_u16 (node, off) +2 ;else key_len = tree->max_key_len +2 ;
@@ -314,7 +315,8 @@ void hfs_bnode_dump(struct hfs_bnode *node)if (i && node->type ==HFS_NODE_INDEX ) {int tmp; -if (node->tree->attributes &HFS_TREE_VARIDXKEYS ) +if (node->tree->attributes &HFS_TREE_VARIDXKEYS || + node->tree->cnid ==HFSPLUS_ATTR_CNID ) tmp =hfs_bnode_read_u16 (node, key_off) +2 ;else tmp = node->tree->max_key_len +2 ;
fs/hfsplus/brec.c +14 -9
@@ -36,7 +36,8 @@ u16 hfs_brec_keylen(struct hfs_bnode *node, u16 rec)return 0 ;if ((node->type ==HFS_NODE_INDEX ) && - !(node->tree->attributes &HFS_TREE_VARIDXKEYS )) { + !(node->tree->attributes &HFS_TREE_VARIDXKEYS ) && + (node->tree->cnid !=HFSPLUS_ATTR_CNID )) { retval = node->tree->max_key_len +2 ; }else { recoff = hfs_bnode_read_u16(node,
@@ -151,12 +152,13 @@ skip:/* get index key */ hfs_bnode_read_key (new_node, fd->search_key,14 ); -__hfs_brec_find (fd->bnode, fd); +__hfs_brec_find (fd->bnode, fd, hfs_find_rec_by_key);hfs_bnode_put (new_node); new_node =NULL ; -if (tree->attributes &HFS_TREE_VARIDXKEYS ) +if ((tree->attributes &HFS_TREE_VARIDXKEYS ) || + (tree->cnid ==HFSPLUS_ATTR_CNID )) key_len =be16_to_cpu (fd->search_key->key_len) +2 ;else { fd->search_key->key_len =
@@ -201,7 +203,7 @@ again:hfs_bnode_put (node); node = fd->bnode = parent; -__hfs_brec_find (node, fd); +__hfs_brec_find (node, fd, hfs_find_rec_by_key); goto again; } hfs_bnode_write_u16(node,
@@ -367,12 +369,13 @@ again: parent =hfs_bnode_find (tree, node->parent);if (IS_ERR (parent))return PTR_ERR (parent); -__hfs_brec_find (parent, fd); +__hfs_brec_find (parent, fd, hfs_find_rec_by_key);hfs_bnode_dump (parent); rec = fd->record;/* size difference between old and new key */ -if (tree->attributes &HFS_TREE_VARIDXKEYS ) +if ((tree->attributes &HFS_TREE_VARIDXKEYS ) || + (tree->cnid ==HFSPLUS_ATTR_CNID )) newkeylen =hfs_bnode_read_u16 (node,14 ) +2 ;else fd->keylength = newkeylen = tree->max_key_len +2 ;
@@ -427,7 +430,7 @@ skip:hfs_bnode_read_key (new_node, fd->search_key,14 ); cnid =cpu_to_be32 (new_node->this); -__hfs_brec_find (fd->bnode, fd); +__hfs_brec_find (fd->bnode, fd, hfs_find_rec_by_key);hfs_brec_insert (fd, &cnid,sizeof (cnid));hfs_bnode_put (fd->bnode);hfs_bnode_put (new_node);
@@ -495,13 +498,15 @@ static int hfs_btree_inc_height(struct hfs_btree *tree)/* insert old root idx into new root */ node->parent = tree->root;if (node->type ==HFS_NODE_LEAF || - tree->attributes &HFS_TREE_VARIDXKEYS ) + tree->attributes &HFS_TREE_VARIDXKEYS || + tree->cnid ==HFSPLUS_ATTR_CNID ) key_size =hfs_bnode_read_u16 (node,14 ) +2 ;else key_size = tree->max_key_len +2 ;hfs_bnode_copy (new_node,14 , node,14 , key_size); -if (!(tree->attributes &HFS_TREE_VARIDXKEYS )) { +if (!(tree->attributes &HFS_TREE_VARIDXKEYS ) && + (tree->cnid !=HFSPLUS_ATTR_CNID )) { key_size = tree->max_key_len +2 ;hfs_bnode_write_u16 (new_node,14 , tree->max_key_len); }
fs/hfsplus/btree.c +8 -0
@@ -98,6 +98,14 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)set_bit (HFSPLUS_SB_CASEFOLD , &HFSPLUS_SB (sb)->flags); }break ; +case HFSPLUS_ATTR_CNID : +if (tree->max_key_len !=HFSPLUS_ATTR_KEYLEN -sizeof (u16)) { +printk (KERN_ERR "hfs: invalid attributes max_key_len %d\n" , + tree->max_key_len); + goto fail_page; + } + tree->keycmp = hfsplus_attr_bin_cmp_key; +break ;default :printk (KERN_ERR "hfs: unknown B*Tree requested\n" ); goto fail_page;
fs/hfsplus/catalog.c +22 -14
@@ -45,7 +45,8 @@ void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *key, key->cat.parent =cpu_to_be32 (parent);if (str) { -hfsplus_asc2uni (sb, &key->cat.name, str->name, str->len); +hfsplus_asc2uni (sb, &key->cat.name,HFSPLUS_MAX_STRLEN , + str->name, str->len); len =be16_to_cpu (key->cat.name.length); }else { key->cat.name.length =0 ;
@@ -167,7 +168,8 @@ static int hfsplus_fill_cat_thread(struct super_block *sb, entry->type =cpu_to_be16 (type); entry->thread.reserved =0 ; entry->thread.parentID =cpu_to_be32 (parentid); -hfsplus_asc2uni (sb, &entry->thread.nodeName, str->name, str->len); +hfsplus_asc2uni (sb, &entry->thread.nodeName,HFSPLUS_MAX_STRLEN , + str->name, str->len);return 10 +be16_to_cpu (entry->thread.nodeName.length) *2 ; }
@@ -198,7 +200,7 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid,hfsplus_cat_build_key_uni (fd->search_key,be32_to_cpu (tmp.thread.parentID), &tmp.thread.nodeName); -return hfs_brec_find (fd); +return hfs_brec_find (fd, hfs_find_rec_by_key); } int hfsplus_create_cat(u32 cnid, struct inode *dir,
@@ -221,7 +223,7 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir,S_ISDIR (inode->i_mode) ?HFSPLUS_FOLDER_THREAD :HFSPLUS_FILE_THREAD , dir->i_ino, str); - err =hfs_brec_find (&fd); + err =hfs_brec_find (&fd, hfs_find_rec_by_key);if (err != -ENOENT ) {if (!err) err = -EEXIST ;
@@ -233,7 +235,7 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir,hfsplus_cat_build_key (sb, fd.search_key, dir->i_ino, str); entry_size =hfsplus_cat_build_record (&entry, cnid, inode); - err =hfs_brec_find (&fd); + err =hfs_brec_find (&fd, hfs_find_rec_by_key);if (err != -ENOENT ) {/* panic? */ if (!err)
@@ -253,7 +255,7 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir, err1:hfsplus_cat_build_key (sb, fd.search_key, cnid,NULL ); -if (!hfs_brec_find (&fd)) +if (!hfs_brec_find (&fd, hfs_find_rec_by_key))hfs_brec_remove (&fd); err2:hfs_find_exit (&fd);
@@ -279,7 +281,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)int len;hfsplus_cat_build_key (sb, fd.search_key, cnid,NULL ); - err =hfs_brec_find (&fd); + err =hfs_brec_find (&fd, hfs_find_rec_by_key);if (err) goto out;
@@ -296,7 +298,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) }else hfsplus_cat_build_key (sb, fd.search_key, dir->i_ino, str); - err =hfs_brec_find (&fd); + err =hfs_brec_find (&fd, hfs_find_rec_by_key);if (err) goto out;
@@ -326,7 +328,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) goto out;hfsplus_cat_build_key (sb, fd.search_key, cnid,NULL ); - err =hfs_brec_find (&fd); + err =hfs_brec_find (&fd, hfs_find_rec_by_key);if (err) goto out;
@@ -337,6 +339,12 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) dir->i_size--; dir->i_mtime = dir->i_ctime =CURRENT_TIME_SEC ;hfsplus_mark_inode_dirty (dir,HFSPLUS_I_CAT_DIRTY ); + +if (type ==HFSPLUS_FILE || type ==HFSPLUS_FOLDER ) { +if (HFSPLUS_SB (sb)->attr_tree) +hfsplus_delete_all_attrs (dir, cnid); + } + out:hfs_find_exit (&fd);
@@ -363,7 +371,7 @@ int hfsplus_rename_cat(u32 cnid,/* find the old dir entry and read the data */ hfsplus_cat_build_key (sb, src_fd.search_key, src_dir->i_ino, src_name); - err =hfs_brec_find (&src_fd); + err =hfs_brec_find (&src_fd, hfs_find_rec_by_key);if (err) goto out;if (src_fd.entrylength >sizeof (entry) || src_fd.entrylength <0 ) {
@@ -376,7 +384,7 @@ int hfsplus_rename_cat(u32 cnid,/* create new dir entry with the data from the old entry */ hfsplus_cat_build_key (sb, dst_fd.search_key, dst_dir->i_ino, dst_name); - err =hfs_brec_find (&dst_fd); + err =hfs_brec_find (&dst_fd, hfs_find_rec_by_key);if (err != -ENOENT ) {if (!err) err = -EEXIST ;
@@ -391,7 +399,7 @@ int hfsplus_rename_cat(u32 cnid,/* finally remove the old entry */ hfsplus_cat_build_key (sb, src_fd.search_key, src_dir->i_ino, src_name); - err =hfs_brec_find (&src_fd); + err =hfs_brec_find (&src_fd, hfs_find_rec_by_key);if (err) goto out; err =hfs_brec_remove (&src_fd);
@@ -402,7 +410,7 @@ int hfsplus_rename_cat(u32 cnid,/* remove old thread entry */ hfsplus_cat_build_key (sb, src_fd.search_key, cnid,NULL ); - err =hfs_brec_find (&src_fd); + err =hfs_brec_find (&src_fd, hfs_find_rec_by_key);if (err) goto out; type =hfs_bnode_read_u16 (src_fd.bnode, src_fd.entryoffset);
@@ -414,7 +422,7 @@ int hfsplus_rename_cat(u32 cnid,hfsplus_cat_build_key (sb, dst_fd.search_key, cnid,NULL ); entry_size =hfsplus_fill_cat_thread (sb, &entry, type, dst_dir->i_ino, dst_name); - err =hfs_brec_find (&dst_fd); + err =hfs_brec_find (&dst_fd, hfs_find_rec_by_key);if (err != -ENOENT ) {if (!err) err = -EEXIST ;
fs/hfsplus/dir.c +40 -15
89 lines not on this page · raw message
fs/hfsplus/extents.c +2 -2
@@ -95,7 +95,7 @@ static void __hfsplus_ext_write_extent(struct inode *inode,HFSPLUS_IS_RSRC (inode) ? HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA); - res =hfs_brec_find (fd); + res =hfs_brec_find (fd, hfs_find_rec_by_key);if (hip->extent_state &HFSPLUS_EXT_NEW ) {if (res != -ENOENT )return ;
@@ -154,7 +154,7 @@ static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd,hfsplus_ext_build_key (fd->search_key, cnid, block, type); fd->key->ext.cnid =0 ; - res =hfs_brec_find (fd); + res =hfs_brec_find (fd, hfs_find_rec_by_key);if (res && res != -ENOENT )return res; if (fd->key->ext.cnid != fd->search_key->ext.cnid ||
fs/hfsplus/hfsplus_fs.h +43 -9
104 lines not on this page · raw message
fs/hfsplus/inode.c +16 -2
@@ -17,6 +17,7 @@#include "hfsplus_fs.h" #include "hfsplus_raw.h" +#include "xattr.h" static int hfsplus_readpage (struct file *file,struct page *page) {
@@ -342,6 +343,18 @@ int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end, error = error2; } +if (test_and_clear_bit (HFSPLUS_I_ATTR_DIRTY , &hip->flags)) { +if (sbi->attr_tree) { + error2 = +filemap_write_and_wait ( + sbi->attr_tree->inode->i_mapping); +if (!error) + error = error2; + }else { +printk (KERN_ERR "hfs: sync non-existent attributes tree\n" ); + } + } +if (test_and_clear_bit (HFSPLUS_I_ALLOC_DIRTY , &hip->flags)) { error2 =filemap_write_and_wait (sbi->alloc_file->i_mapping);if (!error)
@@ -360,9 +373,10 @@ static const struct inode_operations hfsplus_file_inode_operations = { .lookup = hfsplus_file_lookup, .truncate = hfsplus_file_truncate, .setattr = hfsplus_setattr, - .setxattr = hfsplus_setxattr, - .getxattr = hfsplus_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = hfsplus_listxattr, + .removexattr = hfsplus_removexattr, };static const struct file_operations hfsplus_file_operations = {
fs/hfsplus/ioctl.c +0 -108
117 lines not on this page · raw message
fs/hfsplus/super.c +52 -4
119 lines not on this page · raw message
fs/hfsplus/unicode.c +4 -3
@@ -295,7 +295,8 @@ static inline u16 *decompose_unichar(wchar_t uc, int *size)return hfsplus_decompose_table + (off /4 ); } -int hfsplus_asc2uni (struct super_block *sb,struct hfsplus_unistr *ustr, +int hfsplus_asc2uni (struct super_block *sb, +struct hfsplus_unistr *ustr,int max_unistr_len,const char *astr,int len) {int size, dsize, decompose;
@@ -303,7 +304,7 @@ int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr,wchar_t c; decompose = !test_bit (HFSPLUS_SB_NODECOMPOSE , &HFSPLUS_SB (sb)->flags); -while (outlen <HFSPLUS_MAX_STRLEN && len >0 ) { +while (outlen < max_unistr_len && len >0 ) { size =asc2unichar (sb, astr, len, &c);if (decompose)
@@ -311,7 +312,7 @@ int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr,else dstr =NULL ;if (dstr) { -if (outlen + dsize >HFSPLUS_MAX_STRLEN ) +if (outlen + dsize > max_unistr_len)break ; do { ustr->unicode[outlen++] = cpu_to_be16(*dstr++);
Signature · 1 line
1.7.9.5