~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to fs/hfsplus/ioctl.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  linux/fs/hfsplus/ioctl.c
 
3
 *
 
4
 * Copyright (C) 2003
 
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)
 
11
 *
 
12
 * hfsplus ioctls
 
13
 */
 
14
 
 
15
#include <linux/capability.h>
 
16
#include <linux/fs.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"
 
22
 
 
23
static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
 
24
{
 
25
        struct inode *inode = file->f_path.dentry->d_inode;
 
26
        struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
 
27
        unsigned int flags = 0;
 
28
 
 
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;
 
35
 
 
36
        return put_user(flags, user_flags);
 
37
}
 
38
 
 
39
static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
 
40
{
 
41
        struct inode *inode = file->f_path.dentry->d_inode;
 
42
        struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
 
43
        unsigned int flags;
 
44
        int err = 0;
 
45
 
 
46
        err = mnt_want_write(file->f_path.mnt);
 
47
        if (err)
 
48
                goto out;
 
49
 
 
50
        if (!inode_owner_or_capable(inode)) {
 
51
                err = -EACCES;
 
52
                goto out_drop_write;
 
53
        }
 
54
 
 
55
        if (get_user(flags, user_flags)) {
 
56
                err = -EFAULT;
 
57
                goto out_drop_write;
 
58
        }
 
59
 
 
60
        mutex_lock(&inode->i_mutex);
 
61
 
 
62
        if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) ||
 
63
            inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
 
64
                if (!capable(CAP_LINUX_IMMUTABLE)) {
 
65
                        err = -EPERM;
 
66
                        goto out_unlock_inode;
 
67
                }
 
68
        }
 
69
 
 
70
        /* don't silently ignore unsupported ext2 flags */
 
71
        if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
 
72
                err = -EOPNOTSUPP;
 
73
                goto out_unlock_inode;
 
74
        }
 
75
 
 
76
        if (flags & FS_IMMUTABLE_FL)
 
77
                inode->i_flags |= S_IMMUTABLE;
 
78
        else
 
79
                inode->i_flags &= ~S_IMMUTABLE;
 
80
 
 
81
        if (flags & FS_APPEND_FL)
 
82
                inode->i_flags |= S_APPEND;
 
83
        else
 
84
                inode->i_flags &= ~S_APPEND;
 
85
 
 
86
        if (flags & FS_NODUMP_FL)
 
87
                hip->userflags |= HFSPLUS_FLG_NODUMP;
 
88
        else
 
89
                hip->userflags &= ~HFSPLUS_FLG_NODUMP;
 
90
 
 
91
        inode->i_ctime = CURRENT_TIME_SEC;
 
92
        mark_inode_dirty(inode);
 
93
 
 
94
out_unlock_inode:
 
95
        mutex_unlock(&inode->i_mutex);
 
96
out_drop_write:
 
97
        mnt_drop_write(file->f_path.mnt);
 
98
out:
 
99
        return err;
 
100
}
 
101
 
 
102
long hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
103
{
 
104
        void __user *argp = (void __user *)arg;
 
105
 
 
106
        switch (cmd) {
 
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);
 
111
        default:
 
112
                return -ENOTTY;
 
113
        }
 
114
}
 
115
 
 
116
int hfsplus_setxattr(struct dentry *dentry, const char *name,
 
117
                     const void *value, size_t size, int flags)
 
118
{
 
119
        struct inode *inode = dentry->d_inode;
 
120
        struct hfs_find_data fd;
 
121
        hfsplus_cat_entry entry;
 
122
        struct hfsplus_cat_file *file;
 
123
        int res;
 
124
 
 
125
        if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode))
 
126
                return -EOPNOTSUPP;
 
127
 
 
128
        res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
 
129
        if (res)
 
130
                return res;
 
131
        res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
 
132
        if (res)
 
133
                goto out;
 
134
        hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
 
135
                        sizeof(struct hfsplus_cat_file));
 
136
        file = &entry.file;
 
137
 
 
138
        if (!strcmp(name, "hfs.type")) {
 
139
                if (size == 4)
 
140
                        memcpy(&file->user_info.fdType, value, 4);
 
141
                else
 
142
                        res = -ERANGE;
 
143
        } else if (!strcmp(name, "hfs.creator")) {
 
144
                if (size == 4)
 
145
                        memcpy(&file->user_info.fdCreator, value, 4);
 
146
                else
 
147
                        res = -ERANGE;
 
148
        } else
 
149
                res = -EOPNOTSUPP;
 
150
        if (!res) {
 
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);
 
154
        }
 
155
out:
 
156
        hfs_find_exit(&fd);
 
157
        return res;
 
158
}
 
159
 
 
160
ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
 
161
                         void *value, size_t size)
 
162
{
 
163
        struct inode *inode = dentry->d_inode;
 
164
        struct hfs_find_data fd;
 
165
        hfsplus_cat_entry entry;
 
166
        struct hfsplus_cat_file *file;
 
167
        ssize_t res = 0;
 
168
 
 
169
        if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode))
 
170
                return -EOPNOTSUPP;
 
171
 
 
172
        if (size) {
 
173
                res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
 
174
                if (res)
 
175
                        return res;
 
176
                res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
 
177
                if (res)
 
178
                        goto out;
 
179
                hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
 
180
                                sizeof(struct hfsplus_cat_file));
 
181
        }
 
182
        file = &entry.file;
 
183
 
 
184
        if (!strcmp(name, "hfs.type")) {
 
185
                if (size >= 4) {
 
186
                        memcpy(value, &file->user_info.fdType, 4);
 
187
                        res = 4;
 
188
                } else
 
189
                        res = size ? -ERANGE : 4;
 
190
        } else if (!strcmp(name, "hfs.creator")) {
 
191
                if (size >= 4) {
 
192
                        memcpy(value, &file->user_info.fdCreator, 4);
 
193
                        res = 4;
 
194
                } else
 
195
                        res = size ? -ERANGE : 4;
 
196
        } else
 
197
                res = -EOPNOTSUPP;
 
198
out:
 
199
        if (size)
 
200
                hfs_find_exit(&fd);
 
201
        return res;
 
202
}
 
203
 
 
204
#define HFSPLUS_ATTRLIST_SIZE (sizeof("hfs.creator")+sizeof("hfs.type"))
 
205
 
 
206
ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
 
207
{
 
208
        struct inode *inode = dentry->d_inode;
 
209
 
 
210
        if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode))
 
211
                return -EOPNOTSUPP;
 
212
 
 
213
        if (!buffer || !size)
 
214
                return HFSPLUS_ATTRLIST_SIZE;
 
215
        if (size < HFSPLUS_ATTRLIST_SIZE)
 
216
                return -ERANGE;
 
217
        strcpy(buffer, "hfs.type");
 
218
        strcpy(buffer + sizeof("hfs.type"), "hfs.creator");
 
219
 
 
220
        return HFSPLUS_ATTRLIST_SIZE;
 
221
}