From: Roman Zippel This exports the hfs type/creator info via xattr. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton --- 25-akpm/fs/hfs/Makefile | 2 25-akpm/fs/hfs/attr.c | 121 ++++++++++++++++++++++++++++++++++++++++ 25-akpm/fs/hfs/hfs_fs.h | 7 ++ 25-akpm/fs/hfs/inode.c | 3 25-akpm/fs/hfsplus/hfsplus_fs.h | 5 + 25-akpm/fs/hfsplus/inode.c | 3 25-akpm/fs/hfsplus/ioctl.c | 106 +++++++++++++++++++++++++++++++++++ 7 files changed, 246 insertions(+), 1 deletion(-) diff -puN /dev/null fs/hfs/attr.c --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/fs/hfs/attr.c Wed Oct 20 16:41:26 2004 @@ -0,0 +1,121 @@ +/* + * linux/fs/hfs/attr.c + * + * (C) 2003 Ardis Technologies + * + * Export hfs data via xattr + */ + + +#include +#include + +#include "hfs_fs.h" +#include "btree.h" + +int hfs_setxattr(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags) +{ + struct inode *inode = dentry->d_inode; + struct hfs_find_data fd; + hfs_cat_rec rec; + struct hfs_cat_file *file; + int res; + + if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode)) + return -EOPNOTSUPP; + + res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd); + if (res) + return res; + fd.search_key->cat = HFS_I(inode)->cat_key; + res = hfs_brec_find(&fd); + if (res) + goto out; + hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, + sizeof(struct hfs_cat_file)); + file = &rec.file; + + if (!strcmp(name, "type")) { + if (size == 4) + memcpy(&file->UsrWds.fdType, value, 4); + else + res = -ERANGE; + } else if (!strcmp(name, "creator")) { + if (size == 4) + memcpy(&file->UsrWds.fdCreator, value, 4); + else + res = -ERANGE; + } else + res = -EOPNOTSUPP; + if (!res) + hfs_bnode_write(fd.bnode, &rec, fd.entryoffset, + sizeof(struct hfs_cat_file)); +out: + hfs_find_exit(&fd); + return res; +} + +ssize_t hfs_getxattr(struct dentry *dentry, const char *name, + void *value, size_t size) +{ + struct inode *inode = dentry->d_inode; + struct hfs_find_data fd; + hfs_cat_rec rec; + struct hfs_cat_file *file; + ssize_t res = 0; + + if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode)) + return -EOPNOTSUPP; + + if (size) { + res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd); + if (res) + return res; + fd.search_key->cat = HFS_I(inode)->cat_key; + res = hfs_brec_find(&fd); + if (res) + goto out; + hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, + sizeof(struct hfs_cat_file)); + } + file = &rec.file; + + if (!strcmp(name, "type")) { + if (size >= 4) { + memcpy(value, &file->UsrWds.fdType, 4); + res = 4; + } else + res = size ? -ERANGE : 4; + } else if (!strcmp(name, "creator")) { + if (size >= 4) { + memcpy(value, &file->UsrWds.fdCreator, 4); + res = 4; + } else + res = size ? -ERANGE : 4; + } else + res = -ENODATA; +out: + if (size) + hfs_find_exit(&fd); + return res; +} + +#define HFS_ATTRLIST_SIZE (sizeof("creator")+sizeof("type")) + +ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size) +{ + struct inode *inode = dentry->d_inode; + + if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode)) + return -EOPNOTSUPP; + + if (!size) + return HFS_ATTRLIST_SIZE; + if (size < HFS_ATTRLIST_SIZE) + return -ERANGE; + strcpy(buffer, "type"); + strcpy(buffer + 5, "creator"); + + return HFS_ATTRLIST_SIZE; +} diff -puN fs/hfs/hfs_fs.h~hfs-export-type-creator-via-xattr fs/hfs/hfs_fs.h --- 25/fs/hfs/hfs_fs.h~hfs-export-type-creator-via-xattr Wed Oct 20 16:41:26 2004 +++ 25-akpm/fs/hfs/hfs_fs.h Wed Oct 20 16:41:26 2004 @@ -207,6 +207,13 @@ extern struct inode *hfs_iget(struct sup extern void hfs_clear_inode(struct inode *); extern void hfs_delete_inode(struct inode *); +/* attr.c */ +extern int hfs_setxattr(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags); +extern ssize_t hfs_getxattr(struct dentry *dentry, const char *name, + void *value, size_t size); +extern ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size); + /* mdb.c */ extern int hfs_mdb_get(struct super_block *); extern void hfs_mdb_commit(struct super_block *); diff -puN fs/hfs/inode.c~hfs-export-type-creator-via-xattr fs/hfs/inode.c --- 25/fs/hfs/inode.c~hfs-export-type-creator-via-xattr Wed Oct 20 16:41:26 2004 +++ 25-akpm/fs/hfs/inode.c Wed Oct 20 16:41:26 2004 @@ -627,4 +627,7 @@ struct inode_operations hfs_file_inode_o .truncate = hfs_file_truncate, .setattr = hfs_inode_setattr, .permission = hfs_permission, + .setxattr = hfs_setxattr, + .getxattr = hfs_getxattr, + .listxattr = hfs_listxattr, }; diff -puN fs/hfs/Makefile~hfs-export-type-creator-via-xattr fs/hfs/Makefile --- 25/fs/hfs/Makefile~hfs-export-type-creator-via-xattr Wed Oct 20 16:41:26 2004 +++ 25-akpm/fs/hfs/Makefile Wed Oct 20 16:41:26 2004 @@ -5,6 +5,6 @@ obj-$(CONFIG_HFS_FS) += hfs.o hfs-objs := bitmap.o bfind.o bnode.o brec.o btree.o \ - catalog.o dir.o extent.o inode.o mdb.o \ + catalog.o dir.o extent.o inode.o attr.o mdb.o \ part_tbl.o string.o super.o sysdep.o trans.o diff -puN fs/hfsplus/hfsplus_fs.h~hfs-export-type-creator-via-xattr fs/hfsplus/hfsplus_fs.h --- 25/fs/hfsplus/hfsplus_fs.h~hfs-export-type-creator-via-xattr Wed Oct 20 16:41:26 2004 +++ 25-akpm/fs/hfsplus/hfsplus_fs.h Wed Oct 20 16:41:26 2004 @@ -341,6 +341,11 @@ void hfsplus_delete_inode(struct inode * /* ioctl.c */ int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +int hfsplus_setxattr(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags); +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); /* options.c */ int parse_options(char *, struct hfsplus_sb_info *); diff -puN fs/hfsplus/inode.c~hfs-export-type-creator-via-xattr fs/hfsplus/inode.c --- 25/fs/hfsplus/inode.c~hfs-export-type-creator-via-xattr Wed Oct 20 16:41:26 2004 +++ 25-akpm/fs/hfsplus/inode.c Wed Oct 20 16:41:26 2004 @@ -301,6 +301,9 @@ struct inode_operations hfsplus_file_ino .lookup = hfsplus_file_lookup, .truncate = hfsplus_file_truncate, .permission = hfsplus_permission, + .setxattr = hfsplus_setxattr, + .getxattr = hfsplus_getxattr, + .listxattr = hfsplus_listxattr, }; struct file_operations hfsplus_file_operations = { diff -puN fs/hfsplus/ioctl.c~hfs-export-type-creator-via-xattr fs/hfsplus/ioctl.c --- 25/fs/hfsplus/ioctl.c~hfs-export-type-creator-via-xattr Wed Oct 20 16:41:26 2004 +++ 25-akpm/fs/hfsplus/ioctl.c Wed Oct 20 16:41:26 2004 @@ -14,6 +14,7 @@ #include #include +#include #include #include "hfsplus_fs.h" @@ -80,3 +81,108 @@ int hfsplus_ioctl(struct inode *inode, s return -ENOTTY; } } + +int hfsplus_setxattr(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags) +{ + struct inode *inode = dentry->d_inode; + struct hfs_find_data fd; + hfsplus_cat_entry entry; + struct hfsplus_cat_file *file; + int res; + + if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode)) + return -EOPNOTSUPP; + + res = hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd); + if (res) + return res; + res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); + if (res) + goto out; + hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, + sizeof(struct hfsplus_cat_file)); + file = &entry.file; + + if (!strcmp(name, "type")) { + if (size == 4) + memcpy(&file->user_info.fdType, value, 4); + else + res = -ERANGE; + } else if (!strcmp(name, "creator")) { + if (size == 4) + memcpy(&file->user_info.fdCreator, value, 4); + else + res = -ERANGE; + } else + res = -EOPNOTSUPP; + if (!res) + hfs_bnode_write(fd.bnode, &entry, fd.entryoffset, + sizeof(struct hfsplus_cat_file)); +out: + 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_cat_entry entry; + struct hfsplus_cat_file *file; + ssize_t res = 0; + + if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode)) + return -EOPNOTSUPP; + + if (size) { + res = hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd); + if (res) + return res; + res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); + if (res) + goto out; + hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, + sizeof(struct hfsplus_cat_file)); + } + file = &entry.file; + + if (!strcmp(name, "type")) { + if (size >= 4) { + memcpy(value, &file->user_info.fdType, 4); + res = 4; + } else + res = size ? -ERANGE : 4; + } else if (!strcmp(name, "creator")) { + if (size >= 4) { + memcpy(value, &file->user_info.fdCreator, 4); + res = 4; + } else + res = size ? -ERANGE : 4; + } else + res = -ENODATA; +out: + if (size) + hfs_find_exit(&fd); + return res; +} + +#define HFSPLUS_ATTRLIST_SIZE (sizeof("creator")+sizeof("type")) + +ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size) +{ + struct inode *inode = dentry->d_inode; + + if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode)) + return -EOPNOTSUPP; + + if (!size) + return HFSPLUS_ATTRLIST_SIZE; + if (size < HFSPLUS_ATTRLIST_SIZE) + return -ERANGE; + strcpy(buffer, "type"); + strcpy(buffer + 5, "creator"); + + return HFSPLUS_ATTRLIST_SIZE; +} _