Re: [PATCH v2 4/4] hfsplus: add support of manipulation by attributes file

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



--- On Sun, 23/9/12, Vyacheslav Dubeyko <slava@xxxxxxxxxxx> wrote:

> Hi,
> 
> This patch adds support of manipulation by attributes file.
> 
> With the best regards,
> Vyacheslav Dubeyko.
> ---
> From: Vyacheslav Dubeyko <slava@xxxxxxxxxxx>
> Subject: [PATCH v2 4/4] hfsplus: add support of manipulation
> by attributes file
> 
> This patch adds support of manipulation by attributes file.
> 
> Reported-by: Hin-Tak Leung <htl10@xxxxxxxxxxxxxxxxxxxxx>
> Signed-off-by: Vyacheslav Dubeyko <slava@xxxxxxxxxxx>

Tested-by: Hin-Tak Leung <htl10@xxxxxxxxxxxxxxxxxxxxx>

Tried these 4 patches -together with the 5th which acted on code reviews and feedback. Works okay and fixed the two minor problems I had work v 1 (dubious warnings and interactions with selinux's use of extended atttributes).

There is a small problem though - this set of patches changes the file modes of some of the files, as seen below - just scroll further down... The other patches also touch the file modes where files are modified.

Hin-Tak

> ---
>  fs/hfsplus/bfind.c     
> |   79
> ++++++++++++++++++++++++++++++++++++++++-------
>  fs/hfsplus/bnode.c      |    6
> ++--
>  fs/hfsplus/brec.c   
>    |   23 ++++++++------
>  fs/hfsplus/btree.c      |    8
> +++++
>  fs/hfsplus/catalog.c    |   36
> ++++++++++++---------
>  fs/hfsplus/dir.c        |   
> 6 +++-
>  fs/hfsplus/extents.c    |    4 +--
>  fs/hfsplus/hfsplus_fs.h |   41
> +++++++++++++++++++++---
>  fs/hfsplus/inode.c     
> |   13 ++++++++
>  fs/hfsplus/super.c     
> |   36 +++++++++++++++++++--
>  fs/hfsplus/unicode.c    |    7 +++--
>  11 files changed, 210 insertions(+), 49 deletions(-)
>  mode change 100644 => 100755 fs/hfsplus/bfind.c
>  mode change 100644 => 100755 fs/hfsplus/bnode.c
>  mode change 100644 => 100755 fs/hfsplus/brec.c
>  mode change 100644 => 100755 fs/hfsplus/btree.c
>  mode change 100644 => 100755 fs/hfsplus/catalog.c
>  mode change 100644 => 100755 fs/hfsplus/dir.c
>  mode change 100644 => 100755 fs/hfsplus/extents.c
>  mode change 100644 => 100755 fs/hfsplus/hfsplus_fs.h
>  mode change 100644 => 100755 fs/hfsplus/inode.c
>  mode change 100644 => 100755 fs/hfsplus/super.c
>  mode change 100644 => 100755 fs/hfsplus/unicode.c

Here - the file modes should not be touched...

> diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
> old mode 100644
> new mode 100755
> index 5d799c1..55baffa
> --- a/fs/hfsplus/bfind.c
> +++ b/fs/hfsplus/bfind.c
> @@ -38,15 +38,73 @@ void hfs_find_exit(struct hfs_find_data
> *fd)
>      fd->tree = NULL;
>  }
>  
> -/* Find the record in bnode that best matches key (not
> greater than...)*/
> -int __hfs_brec_find(struct hfs_bnode *bnode, struct
> hfs_find_data *fd)
> +int hfs_find_1st_rec_by_cnid(struct hfs_bnode *bnode,
> +           
>     struct hfs_find_data *fd,
> +           
>     int *begin,
> +           
>     int *end,
> +           
>     int *cur_rec)
> +{
> +    __be32 cur_cnid, search_cnid;
> +
> +    if (bnode->tree->cnid ==
> HFSPLUS_EXT_CNID) {
> +        cur_cnid =
> fd->key->ext.cnid;
> +        search_cnid =
> fd->search_key->ext.cnid;
> +    } else if (bnode->tree->cnid ==
> HFSPLUS_CAT_CNID) {
> +        cur_cnid =
> fd->key->cat.parent;
> +        search_cnid =
> fd->search_key->cat.parent;
> +    } else if (bnode->tree->cnid ==
> HFSPLUS_ATTR_CNID) {
> +        cur_cnid =
> fd->key->attr.cnid;
> +        search_cnid =
> fd->search_key->attr.cnid;
> +    } else
> +        BUG();
> +
> +    if (cur_cnid == search_cnid) {
> +        (*end) = (*cur_rec);
> +        if ((*begin) ==
> (*end))
> +           
> return 1;
> +    } else {
> +        if
> (be32_to_cpu(cur_cnid) < be32_to_cpu(search_cnid))
> +           
> (*begin) = (*cur_rec) + 1;
> +        else
> +           
> (*end) = (*cur_rec) - 1;
> +    }
> +
> +    return 0;
> +}
> +
> +int hfs_find_rec_by_key(struct hfs_bnode *bnode,
> +           
>     struct hfs_find_data *fd,
> +           
>     int *begin,
> +           
>     int *end,
> +           
>     int *cur_rec)
>  {
>      int cmpval;
> +
> +    cmpval =
> bnode->tree->keycmp(fd->key, fd->search_key);
> +    if (!cmpval) {
> +        (*end) = (*cur_rec);
> +        return 1;
> +    }
> +    if (cmpval < 0)
> +        (*begin) = (*cur_rec)
> + 1;
> +    else
> +        *(end) = (*cur_rec) -
> 1;
> +
> +    return 0;
> +}
> +
> +/* Find the record in bnode that best matches key (not
> greater than...)*/
> +int __hfs_brec_find(struct hfs_bnode *bnode, struct
> hfs_find_data *fd,
> +           
>         search_strategy_t
> rec_found)
> +{
>      u16 off, len, keylen;
>      int rec;
>      int b, e;
>      int res;
>  
> +    if (!rec_found)
> +        BUG();
> +
>      b = 0;
>      e = bnode->num_recs - 1;
>      res = -ENOENT;
> @@ -59,17 +117,12 @@ int __hfs_brec_find(struct hfs_bnode
> *bnode, struct hfs_find_data *fd)
>             
> goto fail;
>          }
>          hfs_bnode_read(bnode,
> fd->key, off, keylen);
> -        cmpval =
> bnode->tree->keycmp(fd->key, fd->search_key);
> -        if (!cmpval) {
> -            e
> = rec;
> +        if (rec_found(bnode,
> fd, &b, &e, &rec)) {
>             
> res = 0;
>             
> goto done;
>          }
> -        if (cmpval < 0)
> -            b
> = rec + 1;
> -        else
> -            e
> = rec - 1;
>      } while (b <= e);
> +
>      if (rec != e && e >= 0) {
>          len =
> hfs_brec_lenoff(bnode, e, &off);
>          keylen =
> hfs_brec_keylen(bnode, e);
> @@ -79,19 +132,21 @@ int __hfs_brec_find(struct hfs_bnode
> *bnode, struct hfs_find_data *fd)
>          }
>          hfs_bnode_read(bnode,
> fd->key, off, keylen);
>      }
> +
>  done:
>      fd->record = e;
>      fd->keyoffset = off;
>      fd->keylength = keylen;
>      fd->entryoffset = off + keylen;
>      fd->entrylength = len - keylen;
> +
>  fail:
>      return res;
>  }
>  
>  /* Traverse a B*Tree from the root to a leaf finding best
> fit to key */
>  /* Return allocated copy of node found, set recnum to best
> record */
> -int hfs_brec_find(struct hfs_find_data *fd)
> +int hfs_brec_find(struct hfs_find_data *fd,
> search_strategy_t do_key_compare)
>  {
>      struct hfs_btree *tree;
>      struct hfs_bnode *bnode;
> @@ -122,7 +177,7 @@ int hfs_brec_find(struct hfs_find_data
> *fd)
>             
> goto invalid;
>          bnode->parent =
> parent;
>  
> -        res =
> __hfs_brec_find(bnode, fd);
> +        res =
> __hfs_brec_find(bnode, fd, do_key_compare);
>          if (!height)
>             
> break;
>          if (fd->record
> < 0)
> @@ -149,7 +204,7 @@ int hfs_brec_read(struct hfs_find_data
> *fd, void *rec, int rec_len)
>  {
>      int res;
>  
> -    res = hfs_brec_find(fd);
> +    res = hfs_brec_find(fd,
> hfs_find_rec_by_key);
>      if (res)
>          return res;
>      if (fd->entrylength > rec_len)
> diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
> old mode 100644
> new mode 100755
> index 1c42cc5..5c125ce
> --- a/fs/hfsplus/bnode.c
> +++ b/fs/hfsplus/bnode.c
> @@ -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;
> diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c
> old mode 100644
> new mode 100755
> index 2a734cf..298d4e4
> --- a/fs/hfsplus/brec.c
> +++ b/fs/hfsplus/brec.c
> @@ -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);
>          }
> diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
> old mode 100644
> new mode 100755
> index 21023d9..44294af
> --- a/fs/hfsplus/btree.c
> +++ b/fs/hfsplus/btree.c
> @@ -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;
> diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
> old mode 100644
> new mode 100755
> index ec2a9c2..c285c8d
> --- a/fs/hfsplus/catalog.c
> +++ b/fs/hfsplus/catalog.c
> @@ -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;
> diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
> old mode 100644
> new mode 100755
> index 6b9f921..40ceeab
> --- a/fs/hfsplus/dir.c
> +++ b/fs/hfsplus/dir.c
> @@ -138,7 +138,7 @@ static int hfsplus_readdir(struct file
> *filp, void *dirent, filldir_t filldir)
>      if (err)
>          return err;
>      hfsplus_cat_build_key(sb, fd.search_key,
> inode->i_ino, NULL);
> -    err = hfs_brec_find(&fd);
> +    err = hfs_brec_find(&fd,
> hfs_find_rec_by_key);
>      if (err)
>          goto out;
>  
> @@ -508,6 +508,10 @@ const struct inode_operations
> hfsplus_dir_inode_operations = {
>      .symlink    =
> hfsplus_symlink,
>      .mknod   
>     = hfsplus_mknod,
>      .rename   
>     = hfsplus_rename,
> +    .setxattr    =
> hfsplus_setxattr,
> +    .getxattr    =
> hfsplus_getxattr,
> +    .listxattr    =
> hfsplus_listxattr,
> +    .removexattr    =
> hfsplus_removexattr,
>  };
>  
>  const struct file_operations hfsplus_dir_operations = {
> diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
> old mode 100644
> new mode 100755
> index 5849e3e..87e59e9
> --- a/fs/hfsplus/extents.c
> +++ b/fs/hfsplus/extents.c
> @@ -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 ||
> diff --git a/fs/hfsplus/hfsplus_fs.h
> b/fs/hfsplus/hfsplus_fs.h
> old mode 100644
> new mode 100755
> index 558dbb4..03ed580
> --- a/fs/hfsplus/hfsplus_fs.h
> +++ b/fs/hfsplus/hfsplus_fs.h
> @@ -23,6 +23,7 @@
>  #define DBG_SUPER    0x00000010
>  #define DBG_EXTENT    0x00000020
>  #define DBG_BITMAP    0x00000040
> +#define DBG_ATTR_MOD    0x00000080
>  
>  #if 0
>  #define DBG_MASK   
> (DBG_EXTENT|DBG_INODE|DBG_BNODE_MOD)
> @@ -223,6 +224,7 @@ struct hfsplus_inode_info {
>  #define HFSPLUS_I_CAT_DIRTY   
> 1    /* has changes in the catalog tree */
>  #define HFSPLUS_I_EXT_DIRTY   
> 2    /* has changes in the extent tree */
>  #define HFSPLUS_I_ALLOC_DIRTY   
> 3    /* has changes in the allocation file
> */
> +#define HFSPLUS_I_ATTR_DIRTY   
> 4    /* has changes in the attributes tree
> */
>  
>  #define HFSPLUS_IS_RSRC(inode) \
>      test_bit(HFSPLUS_I_RSRC,
> &HFSPLUS_I(inode)->flags)
> @@ -302,7 +304,7 @@ static inline unsigned short
> hfsplus_min_io_size(struct super_block *sb)
>  #define hfs_brec_remove hfsplus_brec_remove
>  #define hfs_find_init hfsplus_find_init
>  #define hfs_find_exit hfsplus_find_exit
> -#define __hfs_brec_find __hplusfs_brec_find
> +#define __hfs_brec_find __hfsplus_brec_find
>  #define hfs_brec_find hfsplus_brec_find
>  #define hfs_brec_read hfsplus_brec_read
>  #define hfs_brec_goto hfsplus_brec_goto
> @@ -324,10 +326,33 @@ static inline unsigned short
> hfsplus_min_io_size(struct super_block *sb)
>   */
>  #define HFSPLUS_IOC_BLESS _IO('h', 0x80)
>  
> +typedef int (*search_strategy_t)(struct hfs_bnode *,
> +           
>     struct hfs_find_data *,
> +           
>     int *, int *, int *);
> +
>  /*
>   * Functions in any *.c used in other files
>   */
>  
> +/* attributes.c */
> +int hfsplus_create_attr_tree_cache(void);
> +void hfsplus_destroy_attr_tree_cache(void);
> +hfsplus_attr_entry *hfsplus_alloc_attr_entry(void);
> +void hfsplus_destroy_attr_entry(hfsplus_attr_entry
> *entry_p);
> +int hfsplus_attr_bin_cmp_key(const hfsplus_btree_key *,
> +        const
> hfsplus_btree_key *);
> +int hfsplus_attr_build_key(struct super_block *,
> hfsplus_btree_key *,
> +           
> u32, const char *);
> +void hfsplus_attr_build_key_uni(hfsplus_btree_key *key,
> +           
>         u32 cnid,
> +           
>         struct
> hfsplus_attr_unistr *name);
> +int hfsplus_find_attr(struct super_block *, u32,
> +           
> const char *, struct hfs_find_data *);
> +int hfsplus_attr_exists(struct inode *inode, const char
> *name);
> +int hfsplus_create_attr(struct inode *, const char *, const
> void *, size_t);
> +int hfsplus_delete_attr(struct inode *, const char *);
> +int hfsplus_delete_all_attrs(struct inode *dir, u32 cnid);
> +
>  /* bitmap.c */
>  int hfsplus_block_allocate(struct super_block *, u32, u32,
> u32 *);
>  int hfsplus_block_free(struct super_block *, u32, u32);
> @@ -369,8 +394,15 @@ int hfs_brec_remove(struct
> hfs_find_data *);
>  /* bfind.c */
>  int hfs_find_init(struct hfs_btree *, struct hfs_find_data
> *);
>  void hfs_find_exit(struct hfs_find_data *);
> -int __hfs_brec_find(struct hfs_bnode *, struct
> hfs_find_data *);
> -int hfs_brec_find(struct hfs_find_data *);
> +int hfs_find_1st_rec_by_cnid(struct hfs_bnode *,
> +           
>     struct hfs_find_data *,
> +           
>     int *, int *, int *);
> +int hfs_find_rec_by_key(struct hfs_bnode *,
> +           
>     struct hfs_find_data *,
> +           
>     int *, int *, int *);
> +int __hfs_brec_find(struct hfs_bnode *, struct
> hfs_find_data *,
> +           
>     search_strategy_t);
> +int hfs_brec_find(struct hfs_find_data *,
> search_strategy_t);
>  int hfs_brec_read(struct hfs_find_data *, void *, int);
>  int hfs_brec_goto(struct hfs_find_data *, int);
>  
> @@ -422,6 +454,7 @@ int hfsplus_setxattr(struct dentry
> *dentry, const char *name,
>  ssize_t hfsplus_getxattr(struct dentry *dentry, const char
> *name,
>         
>      void *value, size_t size);
>  ssize_t hfsplus_listxattr(struct dentry *dentry, char
> *buffer, size_t size);
> +int hfsplus_removexattr(struct dentry *dentry, const char
> *name);
>  
>  /* options.c */
>  int hfsplus_parse_options(char *, struct hfsplus_sb_info
> *);
> @@ -446,7 +479,7 @@ int hfsplus_strcmp(const struct
> hfsplus_unistr *,
>  int hfsplus_uni2asc(struct super_block *,
>          const struct
> hfsplus_unistr *, char *, int *);
>  int hfsplus_asc2uni(struct super_block *,
> -        struct hfsplus_unistr
> *, const char *, int);
> +        struct hfsplus_unistr
> *, int, const char *, int);
>  int hfsplus_hash_dentry(const struct dentry *dentry,
>          const struct inode
> *inode, struct qstr *str);
>  int hfsplus_compare_dentry(const struct dentry *parent,
> diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
> old mode 100644
> new mode 100755
> index 3d8b4a6..98a6210
> --- a/fs/hfsplus/inode.c
> +++ b/fs/hfsplus/inode.c
> @@ -342,6 +342,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)
> @@ -363,6 +375,7 @@ static const struct inode_operations
> hfsplus_file_inode_operations = {
>      .setxattr    =
> hfsplus_setxattr,
>      .getxattr    =
> hfsplus_getxattr,
>      .listxattr    =
> hfsplus_listxattr,
> +    .removexattr    =
> hfsplus_removexattr,
>  };
>  
>  static const struct file_operations hfsplus_file_operations
> = {
> diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
> old mode 100644
> new mode 100755
> index fdafb2d..5a7c91e
> --- a/fs/hfsplus/super.c
> +++ b/fs/hfsplus/super.c
> @@ -118,6 +118,7 @@ static int
> hfsplus_system_write_inode(struct inode *inode)
>      case HFSPLUS_ATTR_CNID:
>          fork =
> &vhdr->attr_file;
>          tree =
> sbi->attr_tree;
> +        break;
>      default:
>          return -EIO;
>      }
> @@ -185,6 +186,12 @@ static int hfsplus_sync_fs(struct
> super_block *sb, int wait)
>      error2 =
> filemap_write_and_wait(sbi->ext_tree->inode->i_mapping);
>      if (!error)
>          error = error2;
> +    if (sbi->attr_tree) {
> +        error2 =
> +           
> filemap_write_and_wait(sbi->attr_tree->inode->i_mapping);
> +        if (!error)
> +           
> error = error2;
> +    }
>      error2 =
> filemap_write_and_wait(sbi->alloc_file->i_mapping);
>      if (!error)
>          error = error2;
> @@ -272,6 +279,7 @@ static void hfsplus_put_super(struct
> super_block *sb)
>          hfsplus_sync_fs(sb,
> 1);
>      }
>  
> +    hfs_btree_close(sbi->attr_tree);
>      hfs_btree_close(sbi->cat_tree);
>      hfs_btree_close(sbi->ext_tree);
>      iput(sbi->alloc_file);
> @@ -468,12 +476,19 @@ static int hfsplus_fill_super(struct
> super_block *sb, void *data, int silent)
>          printk(KERN_ERR "hfs:
> failed to load catalog file\n");
>          goto
> out_close_ext_tree;
>      }
> +    if (vhdr->attr_file.total_blocks !=
> 0) {
> +        sbi->attr_tree =
> hfs_btree_open(sb, HFSPLUS_ATTR_CNID);
> +        if
> (!sbi->attr_tree) {
> +           
> printk(KERN_ERR "hfs: failed to load attributes file\n");
> +           
> goto out_close_cat_tree;
> +        }
> +    }
>  
>      inode = hfsplus_iget(sb,
> HFSPLUS_ALLOC_CNID);
>      if (IS_ERR(inode)) {
>          printk(KERN_ERR "hfs:
> failed to load allocation file\n");
>          err =
> PTR_ERR(inode);
> -        goto
> out_close_cat_tree;
> +        goto
> out_close_attr_tree;
>      }
>      sbi->alloc_file = inode;
>  
> @@ -553,6 +568,8 @@ out_put_root:
>      sb->s_root = NULL;
>  out_put_alloc_file:
>      iput(sbi->alloc_file);
> +out_close_attr_tree:
> +    hfs_btree_close(sbi->attr_tree);
>  out_close_cat_tree:
>      hfs_btree_close(sbi->cat_tree);
>  out_close_ext_tree:
> @@ -626,15 +643,30 @@ static int __init
> init_hfsplus_fs(void)
>          hfsplus_init_once);
>      if (!hfsplus_inode_cachep)
>          return -ENOMEM;
> +
> +    err = hfsplus_create_attr_tree_cache();
> +    if (err)
> +        goto
> destroy_inode_cache;
> +
>      err =
> register_filesystem(&hfsplus_fs_type);
>      if (err)
> -       
> kmem_cache_destroy(hfsplus_inode_cachep);
> +        goto
> destroy_attr_tree_cache;
> +
> +    return 0;
> +
> +destroy_attr_tree_cache:
> +    hfsplus_destroy_attr_tree_cache();
> +
> +destroy_inode_cache:
> +   
> kmem_cache_destroy(hfsplus_inode_cachep);
> +
>      return err;
>  }
>  
>  static void __exit exit_hfsplus_fs(void)
>  {
>     
> unregister_filesystem(&hfsplus_fs_type);
> +    hfsplus_destroy_attr_tree_cache();
>     
> kmem_cache_destroy(hfsplus_inode_cachep);
>  }
>  
> diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
> old mode 100644
> new mode 100755
> index a32998f..2c2e47d
> --- a/fs/hfsplus/unicode.c
> +++ b/fs/hfsplus/unicode.c
> @@ -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++);
> -- 
> 1.7.9.5
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux