hfsplus: rework functionality of getting, setting and deleting of extended attributes
Subsystems (2)
Vyacheslav Dubeyko
maintainerPATCH v3 4/5 hfsplus: rework functionality of getting, setting and deleting of extended attributes
Hi,
This patch reworks functionality of getting, setting and deleting of extended attributes.
With the best regards,
Vyacheslav Dubeyko.
---
From: Vyacheslav Dubeyko <[email protected]>
Subject: [PATCH v3 4/5] hfsplus: rework functionality of getting, setting and deleting of extended attributes
This patch reworks functionality of getting, setting and deleting of extended attributes.
Reported-by Hin-Tak Leung <[email protected]>
Signed-off-by Vyacheslav Dubeyko <[email protected]>
--- fs/hfsplus/xattr.c | 708 +++++++++++++++++++++++++++++++++++++++++++ fs/hfsplus/xattr.h | 60 ++++ fs/hfsplus/xattr_security.c | 104 +++++++ fs/hfsplus/xattr_trusted.c | 63 ++++ fs/hfsplus/xattr_user.c | 63 ++++ 5 files changed, 998 insertions(+) create mode 100644 fs/hfsplus/xattr.c create mode 100644 fs/hfsplus/xattr.h create mode 100644 fs/hfsplus/xattr_security.c create mode 100644 fs/hfsplus/xattr_trusted.c create mode 100644 fs/hfsplus/xattr_user.c
fs/hfsplus/xattr.c new file +708 -0
@@ -0,0 +1,708 @@ +/* +* linux/fs/hfsplus/xattr.c +* +* Vyacheslav Dubeyko <[email protected]> +* +* Logic of processing extended attributes +*/ + +#include "hfsplus_fs.h" +#include "xattr.h" + +const struct xattr_handler *hfsplus_xattr_handlers[] = { + &hfsplus_xattr_osx_handler, + &hfsplus_xattr_user_handler, + &hfsplus_xattr_trusted_handler, + &hfsplus_xattr_security_handler, +NULL +}; + +static int strcmp_xattr_finder_info (const char *name) +{ +if (name) { +return strncmp (name,HFSPLUS_XATTR_FINDER_INFO_NAME , +sizeof (HFSPLUS_XATTR_FINDER_INFO_NAME )); + } +return -1 ; +} + +static int strcmp_xattr_acl (const char *name) +{ +if (name) { +return strncmp (name,HFSPLUS_XATTR_ACL_NAME , +sizeof (HFSPLUS_XATTR_ACL_NAME )); + } +return -1 ; +} + +static inline int is_known_namespace (const char *name) +{ +if (strncmp (name,XATTR_SYSTEM_PREFIX ,XATTR_SYSTEM_PREFIX_LEN ) && +strncmp (name,XATTR_USER_PREFIX ,XATTR_USER_PREFIX_LEN ) && +strncmp (name,XATTR_SECURITY_PREFIX ,XATTR_SECURITY_PREFIX_LEN ) && +strncmp (name,XATTR_TRUSTED_PREFIX ,XATTR_TRUSTED_PREFIX_LEN )) +return false; + +return true; +} + +static int can_set_xattr (struct inode *inode,const char *name, +const void *value,size_t value_len) +{ +if (!strncmp (name,XATTR_SYSTEM_PREFIX ,XATTR_SYSTEM_PREFIX_LEN )) +return -EOPNOTSUPP ;/* TODO: implement ACL support */ + +if (!strncmp (name,XATTR_MAC_OSX_PREFIX ,XATTR_MAC_OSX_PREFIX_LEN )) { +/* +* This makes sure that we aren't trying to set an +* attribute in a different namespace by prefixing it +* with "osx." +*/ +if (is_known_namespace (name +XATTR_MAC_OSX_PREFIX_LEN )) +return -EOPNOTSUPP ; + +return 0 ; + } + +/* +* Don't allow setting an attribute in an unknown namespace. +*/ +if (strncmp (name,XATTR_TRUSTED_PREFIX ,XATTR_TRUSTED_PREFIX_LEN ) && +strncmp (name,XATTR_SECURITY_PREFIX ,XATTR_SECURITY_PREFIX_LEN ) && +strncmp (name,XATTR_USER_PREFIX ,XATTR_USER_PREFIX_LEN )) +return -EOPNOTSUPP ; + +return 0 ; +} + +int __hfsplus_setxattr (struct inode *inode,const char *name, +const void *value,size_t size,int flags) +{ +int err =0 ; +struct hfs_find_data cat_fd; +hfsplus_cat_entry entry; +u16 cat_entry_flags, cat_entry_type; +u16 folder_finderinfo_len =sizeof (struct DInfo ) + +sizeof (struct DXInfo ); +u16 file_finderinfo_len =sizeof (struct FInfo ) + +sizeof (struct FXInfo ); + +if ((!S_ISREG (inode->i_mode) && + !S_ISDIR (inode->i_mode)) || +HFSPLUS_IS_RSRC (inode)) +return -EOPNOTSUPP ; + + err =can_set_xattr (inode, name, value, size); +if (err) +return err; + +if (strncmp (name,XATTR_MAC_OSX_PREFIX , +XATTR_MAC_OSX_PREFIX_LEN ) ==0 ) + name +=XATTR_MAC_OSX_PREFIX_LEN ; + +if (value ==NULL ) { + value ="" ; + size =0 ; + } + + err =hfs_find_init (HFSPLUS_SB (inode->i_sb)->cat_tree, &cat_fd); +if (err) { +printk (KERN_ERR "hfs: can't init xattr find struct\n" ); +return err; + } + + err =hfsplus_find_cat (inode->i_sb, inode->i_ino, &cat_fd); +if (err) { +printk (KERN_ERR "hfs: catalog searching failed\n" ); + goto end_setxattr; + } + +if (!strcmp_xattr_finder_info (name)) { +if (flags &XATTR_CREATE ) { +printk (KERN_ERR "hfs: xattr exists yet\n" ); + err = -EOPNOTSUPP ; + goto end_setxattr; + } +hfs_bnode_read (cat_fd.bnode, &entry, cat_fd.entryoffset, +sizeof (hfsplus_cat_entry)); +if (be16_to_cpu (entry.type) ==HFSPLUS_FOLDER ) { +if (size == folder_finderinfo_len) { +memcpy (&entry.folder.user_info, value, + folder_finderinfo_len); +hfs_bnode_write (cat_fd.bnode, &entry, + cat_fd.entryoffset, +sizeof (struct hfsplus_cat_folder )); +hfsplus_mark_inode_dirty (inode, +HFSPLUS_I_CAT_DIRTY ); + }else { + err = -ERANGE ; + goto end_setxattr; + } + }else if (be16_to_cpu (entry.type) ==HFSPLUS_FILE ) { +if (size == file_finderinfo_len) { +memcpy (&entry.file.user_info, value, + file_finderinfo_len); +hfs_bnode_write (cat_fd.bnode, &entry, + cat_fd.entryoffset, +sizeof (struct hfsplus_cat_file )); +hfsplus_mark_inode_dirty (inode, +HFSPLUS_I_CAT_DIRTY ); + }else { + err = -ERANGE ; + goto end_setxattr; + } + }else { + err = -EOPNOTSUPP ; + goto end_setxattr; + } + goto end_setxattr; + } + +if (!HFSPLUS_SB (inode->i_sb)->attr_tree) { + err = -EOPNOTSUPP ; + goto end_setxattr; + } + +if (hfsplus_attr_exists (inode, name)) { +if (flags &XATTR_CREATE ) { +printk (KERN_ERR "hfs: xattr exists yet\n" ); + err = -EOPNOTSUPP ; + goto end_setxattr; + } + err =hfsplus_delete_attr (inode, name); +if (err) + goto end_setxattr; + err =hfsplus_create_attr (inode, name, value, size); +if (err) + goto end_setxattr; + }else { +if (flags &XATTR_REPLACE ) { +printk (KERN_ERR "hfs: cannot replace xattr\n" ); + err = -EOPNOTSUPP ; + goto end_setxattr; + } + err =hfsplus_create_attr (inode, name, value, size); +if (err) + goto end_setxattr; + } + + cat_entry_type =hfs_bnode_read_u16 (cat_fd.bnode, cat_fd.entryoffset); +if (cat_entry_type ==HFSPLUS_FOLDER ) { + cat_entry_flags =hfs_bnode_read_u16 (cat_fd.bnode, + cat_fd.entryoffset + + offsetof(struct hfsplus_cat_folder , flags)); + cat_entry_flags |=HFSPLUS_XATTR_EXISTS ; +if (!strcmp_xattr_acl (name)) + cat_entry_flags |=HFSPLUS_ACL_EXISTS ; +hfs_bnode_write_u16 (cat_fd.bnode, cat_fd.entryoffset + + offsetof(struct hfsplus_cat_folder , flags), + cat_entry_flags); +hfsplus_mark_inode_dirty (inode,HFSPLUS_I_CAT_DIRTY ); + }else if (cat_entry_type ==HFSPLUS_FILE ) { + cat_entry_flags =hfs_bnode_read_u16 (cat_fd.bnode, + cat_fd.entryoffset + + offsetof(struct hfsplus_cat_file , flags)); + cat_entry_flags |=HFSPLUS_XATTR_EXISTS ; +if (!strcmp_xattr_acl (name)) + cat_entry_flags |=HFSPLUS_ACL_EXISTS ; +hfs_bnode_write_u16 (cat_fd.bnode, cat_fd.entryoffset + + offsetof(struct hfsplus_cat_file , flags), + cat_entry_flags); +hfsplus_mark_inode_dirty (inode,HFSPLUS_I_CAT_DIRTY ); + }else { +printk (KERN_ERR "hfs: invalid catalog entry type\n" ); + err = -EIO ; + goto end_setxattr; + } + +end_setxattr: +hfs_find_exit (&cat_fd); +return err; +} + +static inline int is_osx_xattr (const char *xattr_name) +{ +return !is_known_namespace (xattr_name); +} + +static int name_len (const char *xattr_name,int xattr_name_len) +{ +int len = xattr_name_len +1 ; + +if (is_osx_xattr (xattr_name)) + len +=XATTR_MAC_OSX_PREFIX_LEN ; + +return len; +} + +static int copy_name (char *buffer,const char *xattr_name,int name_len) +{ +int len = name_len; +int offset =0 ; + +if (is_osx_xattr (xattr_name)) { +strncpy (buffer,XATTR_MAC_OSX_PREFIX ,XATTR_MAC_OSX_PREFIX_LEN ); + offset +=XATTR_MAC_OSX_PREFIX_LEN ; + len +=XATTR_MAC_OSX_PREFIX_LEN ; + } + +strncpy (buffer + offset, xattr_name, name_len); +memset (buffer + offset + name_len,0 ,1 ); + len +=1 ; + +return len; +} + +static ssize_t hfsplus_getxattr_finder_info (struct dentry *dentry, +void *value,size_t size) +{ +ssize_t res =0 ; +struct inode *inode = dentry->d_inode; +struct hfs_find_data fd; +u16 entry_type; +u16 folder_rec_len =sizeof (struct DInfo ) +sizeof (struct DXInfo ); +u16 file_rec_len =sizeof (struct FInfo ) +sizeof (struct FXInfo ); +u16 record_len =max (folder_rec_len, file_rec_len); +u8 folder_finder_info[sizeof (struct DInfo ) +sizeof (struct DXInfo )]; +u8 file_finder_info[sizeof (struct FInfo ) +sizeof (struct FXInfo )]; + +if (size >= record_len) { + res =hfs_find_init (HFSPLUS_SB (inode->i_sb)->cat_tree, &fd); +if (res) { +printk (KERN_ERR "hfs: can't init xattr find struct\n" ); +return res; + } + res =hfsplus_find_cat (inode->i_sb, inode->i_ino, &fd); +if (res) + goto end_getxattr_finder_info; + entry_type =hfs_bnode_read_u16 (fd.bnode, fd.entryoffset); + +if (entry_type ==HFSPLUS_FOLDER ) { +hfs_bnode_read (fd.bnode, folder_finder_info, + fd.entryoffset + + offsetof(struct hfsplus_cat_folder , user_info), + folder_rec_len); +memcpy (value, folder_finder_info, folder_rec_len); + res = folder_rec_len; + }else if (entry_type ==HFSPLUS_FILE ) { +hfs_bnode_read (fd.bnode, file_finder_info, + fd.entryoffset + + offsetof(struct hfsplus_cat_file , user_info), + file_rec_len); +memcpy (value, file_finder_info, file_rec_len); + res = file_rec_len; + }else { + res = -EOPNOTSUPP ; + goto end_getxattr_finder_info; + } + }else + res = size ? -ERANGE : record_len; + +end_getxattr_finder_info: +if (size >= record_len) +hfs_find_exit (&fd); +return res; +} + +ssize_t hfsplus_getxattr (struct dentry *dentry,const char *name, +void *value,size_t size) +{ +struct inode *inode = dentry->d_inode; +struct hfs_find_data fd; +hfsplus_attr_entry *entry; +u32 record_type; +u16 record_length =0 ; +ssize_t res =0 ; + +if ((!S_ISREG (inode->i_mode) && + !S_ISDIR (inode->i_mode)) || +HFSPLUS_IS_RSRC (inode)) +return -EOPNOTSUPP ; + +if (strncmp (name,XATTR_MAC_OSX_PREFIX , +XATTR_MAC_OSX_PREFIX_LEN ) ==0 ) { +/* skip "osx." prefix */ + name +=XATTR_MAC_OSX_PREFIX_LEN ; +/* +* Don't allow retrieving properly prefixed attributes +* by prepending them with "osx." +*/ +if (is_known_namespace (name)) +return -EOPNOTSUPP ; + } + +if (!strcmp_xattr_finder_info (name)) +return hfsplus_getxattr_finder_info (dentry, value, size); + +if (!HFSPLUS_SB (inode->i_sb)->attr_tree) +return -EOPNOTSUPP ; + + entry =hfsplus_alloc_attr_entry (); +if (!entry) { +printk (KERN_ERR "hfs: can't allocate xattr entry\n" ); +return -ENOMEM ; + } + + res =hfs_find_init (HFSPLUS_SB (inode->i_sb)->attr_tree, &fd); +if (res) { +printk (KERN_ERR "hfs: can't init xattr find struct\n" ); + goto failed_getxattr_init; + } + + res =hfsplus_find_attr (inode->i_sb, inode->i_ino, name, &fd); +if (res) { +if (res == -ENOENT ) + res = -ENODATA ; +else +printk (KERN_ERR "hfs: xattr searching failed\n" ); + goto out; + } + +hfs_bnode_read (fd.bnode, &record_type, + fd.entryoffset,sizeof (record_type)); + record_type =be32_to_cpu (record_type); +if (record_type ==HFSPLUS_ATTR_INLINE_DATA ) { + record_length =hfs_bnode_read_u16 (fd.bnode, + fd.entryoffset + + offsetof(struct hfsplus_attr_inline_data , + length)); +if (record_length >HFSPLUS_MAX_INLINE_DATA_SIZE ) { +printk (KERN_ERR "hfs: invalid xattr record size\n" ); + res = -EIO ; + goto out; + } + }else if (record_type ==HFSPLUS_ATTR_FORK_DATA || + record_type ==HFSPLUS_ATTR_EXTENTS ) { +printk (KERN_ERR "hfs: only inline data xattr are supported\n" ); + res = -EOPNOTSUPP ; + goto out; + }else { +printk (KERN_ERR "hfs: invalid xattr record\n" ); + res = -EIO ; + goto out; + } + +if (size) { +hfs_bnode_read (fd.bnode, entry, fd.entryoffset, + offsetof(struct hfsplus_attr_inline_data , + raw_bytes) + record_length); + } + +if (size >= record_length) { +memcpy (value, entry->inline_data.raw_bytes, record_length); + res = record_length; + }else + res = size ? -ERANGE : record_length; + +out: +hfs_find_exit (&fd); + +failed_getxattr_init: +hfsplus_destroy_attr_entry (entry); +return res; +} + +static inline int can_list (const char *xattr_name) +{ +if (!xattr_name) +return 0 ; + +return strncmp (xattr_name,XATTR_TRUSTED_PREFIX , +XATTR_TRUSTED_PREFIX_LEN ) || +capable (CAP_SYS_ADMIN ); +} + +static ssize_t hfsplus_listxattr_finder_info (struct dentry *dentry, +char *buffer,size_t size) +{ +ssize_t res =0 ; +struct inode *inode = dentry->d_inode; +struct hfs_find_data fd; +u16 entry_type; +u8 folder_finder_info[sizeof (struct DInfo ) +sizeof (struct DXInfo )]; +u8 file_finder_info[sizeof (struct FInfo ) +sizeof (struct FXInfo )]; +unsigned long len, found_bit; +int xattr_name_len, symbols_count; + + res =hfs_find_init (HFSPLUS_SB (inode->i_sb)->cat_tree, &fd); +if (res) { +printk (KERN_ERR "hfs: can't init xattr find struct\n" ); +return res; + } + + res =hfsplus_find_cat (inode->i_sb, inode->i_ino, &fd); +if (res) + goto end_listxattr_finder_info; + + entry_type =hfs_bnode_read_u16 (fd.bnode, fd.entryoffset); +if (entry_type ==HFSPLUS_FOLDER ) { + len =sizeof (struct DInfo ) +sizeof (struct DXInfo ); +hfs_bnode_read (fd.bnode, folder_finder_info, + fd.entryoffset + + offsetof(struct hfsplus_cat_folder , user_info), + len); + found_bit =find_first_bit ((void *)folder_finder_info, len*8 ); + }else if (entry_type ==HFSPLUS_FILE ) { + len =sizeof (struct FInfo ) +sizeof (struct FXInfo ); +hfs_bnode_read (fd.bnode, file_finder_info, + fd.entryoffset + + offsetof(struct hfsplus_cat_file , user_info), + len); + found_bit =find_first_bit ((void *)file_finder_info, len*8 ); + }else { + res = -EOPNOTSUPP ; + goto end_listxattr_finder_info; + } + +if (found_bit >= (len*8 )) + res =0 ; +else { + symbols_count =sizeof (HFSPLUS_XATTR_FINDER_INFO_NAME ) -1 ; + xattr_name_len = +name_len (HFSPLUS_XATTR_FINDER_INFO_NAME , symbols_count); +if (!buffer || !size) { +if (can_list (HFSPLUS_XATTR_FINDER_INFO_NAME )) + res = xattr_name_len; + }else if (can_list (HFSPLUS_XATTR_FINDER_INFO_NAME )) { +if (size < xattr_name_len) + res = -ERANGE ; +else { + res =copy_name (buffer, +HFSPLUS_XATTR_FINDER_INFO_NAME , + symbols_count); + } + } + } + +end_listxattr_finder_info: +hfs_find_exit (&fd); + +return res; +} + +ssize_t hfsplus_listxattr (struct dentry *dentry,char *buffer,size_t size) +{ +ssize_t err; +ssize_t res =0 ; +struct inode *inode = dentry->d_inode; +struct hfs_find_data fd; +u16 key_len =0 ; +struct hfsplus_attr_key attr_key; +char strbuf[HFSPLUS_ATTR_MAX_STRLEN + +XATTR_MAC_OSX_PREFIX_LEN +1 ] = {0 }; +int xattr_name_len; + +if ((!S_ISREG (inode->i_mode) && + !S_ISDIR (inode->i_mode)) || +HFSPLUS_IS_RSRC (inode)) +return -EOPNOTSUPP ; + + res =hfsplus_listxattr_finder_info (dentry, buffer, size); +if (res <0 ) +return res; +else if (!HFSPLUS_SB (inode->i_sb)->attr_tree) +return (res ==0 ) ? -EOPNOTSUPP : res; + + err =hfs_find_init (HFSPLUS_SB (inode->i_sb)->attr_tree, &fd); +if (err) { +printk (KERN_ERR "hfs: can't init xattr find struct\n" ); +return err; + } + + err =hfsplus_find_attr (inode->i_sb, inode->i_ino,NULL , &fd); +if (err) { +if (err == -ENOENT ) { +if (res ==0 ) + res = -ENODATA ; + goto end_listxattr; + }else { + res = err; + goto end_listxattr; + } + } + +for (;;) { + key_len =hfs_bnode_read_u16 (fd.bnode, fd.keyoffset); +if (key_len ==0 || key_len > fd.tree->max_key_len) { +printk (KERN_ERR "hfs: invalid xattr key length: %d\n" , + key_len); + res = -EIO ; + goto end_listxattr; + } + +hfs_bnode_read (fd.bnode, &attr_key, + fd.keyoffset, key_len +sizeof (key_len)); + +if (be32_to_cpu (attr_key.cnid) != inode->i_ino) + goto end_listxattr; + + xattr_name_len =HFSPLUS_ATTR_MAX_STRLEN ; +if (hfsplus_uni2asc (inode->i_sb, + (const struct hfsplus_unistr *)&fd.key->attr.key_name, + strbuf, &xattr_name_len)) { +printk (KERN_ERR "hfs: unicode conversion failed\n" ); + res = -EIO ; + goto end_listxattr; + } + +if (!buffer || !size) { +if (can_list (strbuf)) + res +=name_len (strbuf, xattr_name_len); + }else if (can_list (strbuf)) { +if (size < (res +name_len (strbuf, xattr_name_len))) { + res = -ERANGE ; + goto end_listxattr; + }else + res +=copy_name (buffer + res, + strbuf, xattr_name_len); + } + +if (hfs_brec_goto (&fd,1 )) + goto end_listxattr; + } + +end_listxattr: +hfs_find_exit (&fd); +return res; +} + +int hfsplus_removexattr (struct dentry *dentry,const char *name) +{ +int err =0 ; +struct inode *inode = dentry->d_inode; +struct hfs_find_data cat_fd; +u16 flags; +u16 cat_entry_type; +int is_xattr_acl_deleted =0 ; +int is_all_xattrs_deleted =0 ; + +if ((!S_ISREG (inode->i_mode) && + !S_ISDIR (inode->i_mode)) || +HFSPLUS_IS_RSRC (inode)) +return -EOPNOTSUPP ; + +if (!HFSPLUS_SB (inode->i_sb)->attr_tree) +return -EOPNOTSUPP ; + + err =can_set_xattr (inode, name,NULL ,0 ); +if (err) +return err; + +if (strncmp (name,XATTR_MAC_OSX_PREFIX , +XATTR_MAC_OSX_PREFIX_LEN ) ==0 ) + name +=XATTR_MAC_OSX_PREFIX_LEN ; + +if (!strcmp_xattr_finder_info (name)) +return -EOPNOTSUPP ; + + err =hfs_find_init (HFSPLUS_SB (inode->i_sb)->cat_tree, &cat_fd); +if (err) { +printk (KERN_ERR "hfs: can't init xattr find struct\n" ); +return err; + } + + err =hfsplus_find_cat (inode->i_sb, inode->i_ino, &cat_fd); +if (err) { +printk (KERN_ERR "hfs: catalog searching failed\n" ); + goto end_removexattr; + } + + err =hfsplus_delete_attr (inode, name); +if (err) + goto end_removexattr; + + is_xattr_acl_deleted = !strcmp_xattr_acl (name); + is_all_xattrs_deleted = !hfsplus_attr_exists (inode,NULL ); + +if (!is_xattr_acl_deleted && !is_all_xattrs_deleted) + goto end_removexattr; + + cat_entry_type =hfs_bnode_read_u16 (cat_fd.bnode, cat_fd.entryoffset); + +if (cat_entry_type ==HFSPLUS_FOLDER ) { + flags =hfs_bnode_read_u16 (cat_fd.bnode, cat_fd.entryoffset + + offsetof(struct hfsplus_cat_folder , flags)); +if (is_xattr_acl_deleted) + flags &= ~HFSPLUS_ACL_EXISTS ; +if (is_all_xattrs_deleted) + flags &= ~HFSPLUS_XATTR_EXISTS ; +hfs_bnode_write_u16 (cat_fd.bnode, cat_fd.entryoffset + + offsetof(struct hfsplus_cat_folder , flags), + flags); +hfsplus_mark_inode_dirty (inode,HFSPLUS_I_CAT_DIRTY ); + }else if (cat_entry_type ==HFSPLUS_FILE ) { + flags =hfs_bnode_read_u16 (cat_fd.bnode, cat_fd.entryoffset + + offsetof(struct hfsplus_cat_file , flags)); +if (is_xattr_acl_deleted) + flags &= ~HFSPLUS_ACL_EXISTS ; +if (is_all_xattrs_deleted) + flags &= ~HFSPLUS_XATTR_EXISTS ; +hfs_bnode_write_u16 (cat_fd.bnode, cat_fd.entryoffset + + offsetof(struct hfsplus_cat_file , flags), + flags); +hfsplus_mark_inode_dirty (inode,HFSPLUS_I_CAT_DIRTY ); + }else { +printk (KERN_ERR "hfs: invalid catalog entry type\n" ); + err = -EIO ; + goto end_removexattr; + } + +end_removexattr: +hfs_find_exit (&cat_fd); +return err; +} + +static int hfsplus_osx_getxattr (struct dentry *dentry,const char *name, +void *buffer,size_t size,int type) +{ +char xattr_name[HFSPLUS_ATTR_MAX_STRLEN + +XATTR_MAC_OSX_PREFIX_LEN +1 ] = {0 }; +size_t len =strlen (name); + +if (!strcmp (name,"" )) +return -EINVAL ; + +if (len >HFSPLUS_ATTR_MAX_STRLEN ) +return -EOPNOTSUPP ; + +strcpy (xattr_name,XATTR_MAC_OSX_PREFIX ); +strcpy (xattr_name +XATTR_MAC_OSX_PREFIX_LEN , name); + +return hfsplus_getxattr (dentry, xattr_name, buffer, size); +} + +static int hfsplus_osx_setxattr (struct dentry *dentry,const char *name, +const void *buffer,size_t size,int flags,int type) +{ +char xattr_name[HFSPLUS_ATTR_MAX_STRLEN + +XATTR_MAC_OSX_PREFIX_LEN +1 ] = {0 }; +size_t len =strlen (name); + +if (!strcmp (name,"" )) +return -EINVAL ; + +if (len >HFSPLUS_ATTR_MAX_STRLEN ) +return -EOPNOTSUPP ; + +strcpy (xattr_name,XATTR_MAC_OSX_PREFIX ); +strcpy (xattr_name +XATTR_MAC_OSX_PREFIX_LEN , name); + +return hfsplus_setxattr (dentry, xattr_name, buffer, size, flags); +} + +static size_t hfsplus_osx_listxattr (struct dentry *dentry,char *list, +size_t list_size,const char *name,size_t name_len,int type) +{ +/* +* This method is not used. +* It is used hfsplus_listxattr() instead of generic_listxattr(). +*/ +return -EOPNOTSUPP ; +} + +const struct xattr_handler hfsplus_xattr_osx_handler = { + .prefix =XATTR_MAC_OSX_PREFIX , + .list = hfsplus_osx_listxattr, + .get = hfsplus_osx_getxattr, + .set = hfsplus_osx_setxattr, +};
fs/hfsplus/xattr.h new file +60 -0
60 lines not on this page · raw message
fs/hfsplus/xattr_security.c new file +104 -0
104 lines not on this page · raw message
fs/hfsplus/xattr_trusted.c new file +63 -0
63 lines not on this page · raw message
fs/hfsplus/xattr_user.c new file +63 -0
63 lines not on this page · raw message
Signature · 1 line
1.7.9.5