hfsplus: add support of manipulation by attributes file
[firefly-linux-kernel-4.4.55.git] / fs / hfsplus / dir.c
index 6b9f921ef2fa178d75ed2e24d0e7a2a424fbf4d2..031c24e5052182fb31351e8b79ba5166959485b7 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
+#include "xattr.h"
 
 static inline void hfsplus_instantiate(struct dentry *dentry,
                                       struct inode *inode, u32 cnid)
@@ -122,7 +123,7 @@ fail:
 
 static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct inode *inode = filp->f_path.dentry->d_inode;
+       struct inode *inode = file_inode(filp);
        struct super_block *sb = inode->i_sb;
        int len, err;
        char strbuf[HFSPLUS_MAX_STRLEN + 1];
@@ -138,7 +139,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;
 
@@ -421,6 +422,15 @@ static int hfsplus_symlink(struct inode *dir, struct dentry *dentry,
        if (res)
                goto out_err;
 
+       res = hfsplus_init_inode_security(inode, dir, &dentry->d_name);
+       if (res == -EOPNOTSUPP)
+               res = 0; /* Operation is not supported. */
+       else if (res) {
+               /* Try to delete anyway without error analysis. */
+               hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name);
+               goto out_err;
+       }
+
        hfsplus_instantiate(dentry, inode, inode->i_ino);
        mark_inode_dirty(inode);
        goto out;
@@ -450,15 +460,26 @@ static int hfsplus_mknod(struct inode *dir, struct dentry *dentry,
                init_special_inode(inode, mode, rdev);
 
        res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
-       if (res) {
-               clear_nlink(inode);
-               hfsplus_delete_inode(inode);
-               iput(inode);
-               goto out;
+       if (res)
+               goto failed_mknod;
+
+       res = hfsplus_init_inode_security(inode, dir, &dentry->d_name);
+       if (res == -EOPNOTSUPP)
+               res = 0; /* Operation is not supported. */
+       else if (res) {
+               /* Try to delete anyway without error analysis. */
+               hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name);
+               goto failed_mknod;
        }
 
        hfsplus_instantiate(dentry, inode, inode->i_ino);
        mark_inode_dirty(inode);
+       goto out;
+
+failed_mknod:
+       clear_nlink(inode);
+       hfsplus_delete_inode(inode);
+       iput(inode);
 out:
        mutex_unlock(&sbi->vh_mutex);
        return res;
@@ -499,15 +520,19 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry,
 }
 
 const struct inode_operations hfsplus_dir_inode_operations = {
-       .lookup         = hfsplus_lookup,
-       .create         = hfsplus_create,
-       .link           = hfsplus_link,
-       .unlink         = hfsplus_unlink,
-       .mkdir          = hfsplus_mkdir,
-       .rmdir          = hfsplus_rmdir,
-       .symlink        = hfsplus_symlink,
-       .mknod          = hfsplus_mknod,
-       .rename         = hfsplus_rename,
+       .lookup                 = hfsplus_lookup,
+       .create                 = hfsplus_create,
+       .link                   = hfsplus_link,
+       .unlink                 = hfsplus_unlink,
+       .mkdir                  = hfsplus_mkdir,
+       .rmdir                  = hfsplus_rmdir,
+       .symlink                = hfsplus_symlink,
+       .mknod                  = hfsplus_mknod,
+       .rename                 = hfsplus_rename,
+       .setxattr               = generic_setxattr,
+       .getxattr               = generic_getxattr,
+       .listxattr              = hfsplus_listxattr,
+       .removexattr            = hfsplus_removexattr,
 };
 
 const struct file_operations hfsplus_dir_operations = {