2
* linux/fs/hfsplus/ioctl.c
5
* Ethan Benson <erbenson@alaska.net>
6
* partially derived from linux/fs/ext2/ioctl.c
7
* Copyright (C) 1993, 1994, 1995
8
* Remy Card (card@masi.ibp.fr)
9
* Laboratoire MASI - Institut Blaise Pascal
10
* Universite Pierre et Marie Curie (Paris VI)
15
#include <linux/capability.h>
17
#include <linux/mount.h>
18
#include <linux/sched.h>
19
#include <linux/xattr.h>
20
#include <asm/uaccess.h>
21
#include "hfsplus_fs.h"
23
static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
25
struct inode *inode = file->f_path.dentry->d_inode;
26
struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
27
unsigned int flags = 0;
29
if (inode->i_flags & S_IMMUTABLE)
30
flags |= FS_IMMUTABLE_FL;
31
if (inode->i_flags & S_APPEND)
32
flags |= FS_APPEND_FL;
33
if (hip->userflags & HFSPLUS_FLG_NODUMP)
34
flags |= FS_NODUMP_FL;
36
return put_user(flags, user_flags);
39
static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
41
struct inode *inode = file->f_path.dentry->d_inode;
42
struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
46
err = mnt_want_write(file->f_path.mnt);
50
if (!inode_owner_or_capable(inode)) {
55
if (get_user(flags, user_flags)) {
60
mutex_lock(&inode->i_mutex);
62
if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) ||
63
inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
64
if (!capable(CAP_LINUX_IMMUTABLE)) {
66
goto out_unlock_inode;
70
/* don't silently ignore unsupported ext2 flags */
71
if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
73
goto out_unlock_inode;
76
if (flags & FS_IMMUTABLE_FL)
77
inode->i_flags |= S_IMMUTABLE;
79
inode->i_flags &= ~S_IMMUTABLE;
81
if (flags & FS_APPEND_FL)
82
inode->i_flags |= S_APPEND;
84
inode->i_flags &= ~S_APPEND;
86
if (flags & FS_NODUMP_FL)
87
hip->userflags |= HFSPLUS_FLG_NODUMP;
89
hip->userflags &= ~HFSPLUS_FLG_NODUMP;
91
inode->i_ctime = CURRENT_TIME_SEC;
92
mark_inode_dirty(inode);
95
mutex_unlock(&inode->i_mutex);
97
mnt_drop_write(file->f_path.mnt);
102
long hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
104
void __user *argp = (void __user *)arg;
107
case HFSPLUS_IOC_EXT2_GETFLAGS:
108
return hfsplus_ioctl_getflags(file, argp);
109
case HFSPLUS_IOC_EXT2_SETFLAGS:
110
return hfsplus_ioctl_setflags(file, argp);
116
int hfsplus_setxattr(struct dentry *dentry, const char *name,
117
const void *value, size_t size, int flags)
119
struct inode *inode = dentry->d_inode;
120
struct hfs_find_data fd;
121
hfsplus_cat_entry entry;
122
struct hfsplus_cat_file *file;
125
if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode))
128
res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
131
res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
134
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
135
sizeof(struct hfsplus_cat_file));
138
if (!strcmp(name, "hfs.type")) {
140
memcpy(&file->user_info.fdType, value, 4);
143
} else if (!strcmp(name, "hfs.creator")) {
145
memcpy(&file->user_info.fdCreator, value, 4);
151
hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
152
sizeof(struct hfsplus_cat_file));
153
hfsplus_mark_inode_dirty(inode, HFSPLUS_I_CAT_DIRTY);
160
ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
161
void *value, size_t size)
163
struct inode *inode = dentry->d_inode;
164
struct hfs_find_data fd;
165
hfsplus_cat_entry entry;
166
struct hfsplus_cat_file *file;
169
if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode))
173
res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
176
res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
179
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
180
sizeof(struct hfsplus_cat_file));
184
if (!strcmp(name, "hfs.type")) {
186
memcpy(value, &file->user_info.fdType, 4);
189
res = size ? -ERANGE : 4;
190
} else if (!strcmp(name, "hfs.creator")) {
192
memcpy(value, &file->user_info.fdCreator, 4);
195
res = size ? -ERANGE : 4;
204
#define HFSPLUS_ATTRLIST_SIZE (sizeof("hfs.creator")+sizeof("hfs.type"))
206
ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
208
struct inode *inode = dentry->d_inode;
210
if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode))
213
if (!buffer || !size)
214
return HFSPLUS_ATTRLIST_SIZE;
215
if (size < HFSPLUS_ATTRLIST_SIZE)
217
strcpy(buffer, "hfs.type");
218
strcpy(buffer + sizeof("hfs.type"), "hfs.creator");
220
return HFSPLUS_ATTRLIST_SIZE;