Import 2.3.12pre9
[davej-history.git] / fs / attr.c
blob21adfd00ebbb38beadb40135506c348f75f82bb2
1 /*
2 * linux/fs/attr.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 * changes by Thomas Schoebel-Theuer
6 */
8 #include <linux/sched.h>
9 #include <linux/mm.h>
10 #include <linux/string.h>
12 /* Taken over from the old code... */
14 /* POSIX UID/GID verification for setting inode attributes. */
15 int inode_change_ok(struct inode *inode, struct iattr *attr)
17 int retval = -EPERM;
18 unsigned int ia_valid = attr->ia_valid;
20 /* If force is set do it anyway. */
21 if (ia_valid & ATTR_FORCE)
22 goto fine;
24 /* Make sure a caller can chown. */
25 if ((ia_valid & ATTR_UID) &&
26 (current->fsuid != inode->i_uid ||
27 attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN))
28 goto error;
30 /* Make sure caller can chgrp. */
31 if ((ia_valid & ATTR_GID) &&
32 (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid) &&
33 !capable(CAP_CHOWN))
34 goto error;
36 /* Make sure a caller can chmod. */
37 if (ia_valid & ATTR_MODE) {
38 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
39 goto error;
40 /* Also check the setgid bit! */
41 if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
42 inode->i_gid) && !capable(CAP_FSETID))
43 attr->ia_mode &= ~S_ISGID;
46 /* Check for setting the inode time. */
47 if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
48 if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
49 goto error;
51 fine:
52 retval = 0;
53 error:
54 return retval;
57 void inode_setattr(struct inode * inode, struct iattr * attr)
59 unsigned int ia_valid = attr->ia_valid;
61 if (ia_valid & ATTR_UID)
62 inode->i_uid = attr->ia_uid;
63 if (ia_valid & ATTR_GID)
64 inode->i_gid = attr->ia_gid;
65 if (ia_valid & ATTR_SIZE)
66 inode->i_size = attr->ia_size;
67 if (ia_valid & ATTR_ATIME)
68 inode->i_atime = attr->ia_atime;
69 if (ia_valid & ATTR_MTIME)
70 inode->i_mtime = attr->ia_mtime;
71 if (ia_valid & ATTR_CTIME)
72 inode->i_ctime = attr->ia_ctime;
73 if (ia_valid & ATTR_MODE) {
74 inode->i_mode = attr->ia_mode;
75 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
76 inode->i_mode &= ~S_ISGID;
78 mark_inode_dirty(inode);
81 int notify_change(struct dentry * dentry, struct iattr * attr)
83 struct inode *inode = dentry->d_inode;
84 int error;
85 time_t now = CURRENT_TIME;
86 unsigned int ia_valid = attr->ia_valid;
88 attr->ia_ctime = now;
89 if (!(ia_valid & ATTR_ATIME_SET))
90 attr->ia_atime = now;
91 if (!(ia_valid & ATTR_MTIME_SET))
92 attr->ia_mtime = now;
94 if (inode->i_sb && inode->i_sb->s_op &&
95 inode->i_sb->s_op->notify_change)
96 error = inode->i_sb->s_op->notify_change(dentry, attr);
97 else {
98 error = inode_change_ok(inode, attr);
99 if (!error)
100 inode_setattr(inode, attr);
102 return error;