cleanup
[linux-2.4.git] / fs / attr.c
1 /*
2  *  linux/fs/attr.c
3  *
4  *  Copyright (C) 1991, 1992  Linus Torvalds
5  *  changes by Thomas Schoebel-Theuer
6  */
7
8 #include <linux/sched.h>
9 #include <linux/mm.h>
10 #include <linux/string.h>
11 #include <linux/smp_lock.h>
12 #include <linux/dnotify.h>
13 #include <linux/fcntl.h>
14 #include <linux/quotaops.h>
15
16 /* Taken over from the old code... */
17
18 /* POSIX UID/GID verification for setting inode attributes. */
19 int inode_change_ok(struct inode *inode, struct iattr *attr)
20 {
21         int retval = -EPERM;
22         unsigned int ia_valid = attr->ia_valid;
23
24         /* If force is set do it anyway. */
25         if (ia_valid & ATTR_FORCE)
26                 goto fine;
27
28         /* Make sure a caller can chown. */
29         if ((ia_valid & ATTR_UID) &&
30             (current->fsuid != inode->i_uid ||
31              attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN))
32                 goto error;
33
34         /* Make sure caller can chgrp. */
35         if ((ia_valid & ATTR_GID) &&
36             (current->fsuid != inode->i_uid ||
37             (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid)) &&
38             !capable(CAP_CHOWN))
39                 goto error;
40
41         /* Make sure a caller can chmod. */
42         if (ia_valid & ATTR_MODE) {
43                 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
44                         goto error;
45                 /* Also check the setgid bit! */
46                 if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
47                                 inode->i_gid) && !capable(CAP_FSETID))
48                         attr->ia_mode &= ~S_ISGID;
49         }
50
51         /* Check for setting the inode time. */
52         if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
53                 if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
54                         goto error;
55         }
56 fine:
57         retval = 0;
58 error:
59         return retval;
60 }
61
62 int inode_setattr(struct inode * inode, struct iattr * attr)
63 {
64         unsigned int ia_valid = attr->ia_valid;
65         int error = 0;
66
67         if (ia_valid & ATTR_SIZE) {
68                 error = vmtruncate(inode, attr->ia_size);
69                 if (error)
70                         goto out;
71         }
72
73         if (ia_valid & ATTR_UID)
74                 inode->i_uid = attr->ia_uid;
75         if (ia_valid & ATTR_GID)
76                 inode->i_gid = attr->ia_gid;
77         if (ia_valid & ATTR_ATIME)
78                 inode->i_atime = attr->ia_atime;
79         if (ia_valid & ATTR_MTIME)
80                 inode->i_mtime = attr->ia_mtime;
81         if (ia_valid & ATTR_CTIME)
82                 inode->i_ctime = attr->ia_ctime;
83         if (ia_valid & ATTR_MODE) {
84                 inode->i_mode = attr->ia_mode;
85                 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
86                         inode->i_mode &= ~S_ISGID;
87         }
88         mark_inode_dirty(inode);
89 out:
90         return error;
91 }
92
93 static int setattr_mask(unsigned int ia_valid)
94 {
95         unsigned long dn_mask = 0;
96
97         if (ia_valid & ATTR_UID)
98                 dn_mask |= DN_ATTRIB;
99         if (ia_valid & ATTR_GID)
100                 dn_mask |= DN_ATTRIB;
101         if (ia_valid & ATTR_SIZE)
102                 dn_mask |= DN_MODIFY;
103         /* both times implies a utime(s) call */
104         if ((ia_valid & (ATTR_ATIME|ATTR_MTIME)) == (ATTR_ATIME|ATTR_MTIME))
105                 dn_mask |= DN_ATTRIB;
106         else if (ia_valid & ATTR_ATIME)
107                 dn_mask |= DN_ACCESS;
108         else if (ia_valid & ATTR_MTIME)
109                 dn_mask |= DN_MODIFY;
110         if (ia_valid & ATTR_MODE)
111                 dn_mask |= DN_ATTRIB;
112         return dn_mask;
113 }
114
115 int notify_change(struct dentry * dentry, struct iattr * attr)
116 {
117         struct inode *inode = dentry->d_inode;
118         int error;
119         time_t now = CURRENT_TIME;
120         unsigned int ia_valid = attr->ia_valid;
121
122         if (!inode)
123                 BUG();
124
125         attr->ia_ctime = now;
126         if (!(ia_valid & ATTR_ATIME_SET))
127                 attr->ia_atime = now;
128         if (!(ia_valid & ATTR_MTIME_SET))
129                 attr->ia_mtime = now;
130
131         lock_kernel();
132         if (inode->i_op && inode->i_op->setattr) 
133                 error = inode->i_op->setattr(dentry, attr);
134         else {
135                 error = inode_change_ok(inode, attr);
136                 if (!error) {
137                         if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
138                             (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid))
139                                 error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
140                         if (!error)
141                                 error = inode_setattr(inode, attr);
142                 }
143         }
144         unlock_kernel();
145         if (!error) {
146                 unsigned long dn_mask = setattr_mask(ia_valid);
147                 if (dn_mask)
148                         dnotify_parent(dentry, dn_mask);
149         }
150         return error;
151 }