- pre4:
[davej-history.git] / fs / attr.c
blob9af530c8bd682d8689b417b5ae27d21fde0f0e9b
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>
11 #include <linux/smp_lock.h>
13 /* Taken over from the old code... */
15 /* POSIX UID/GID verification for setting inode attributes. */
16 int inode_change_ok(struct inode *inode, struct iattr *attr)
18 int retval = -EPERM;
19 unsigned int ia_valid = attr->ia_valid;
21 /* If force is set do it anyway. */
22 if (ia_valid & ATTR_FORCE)
23 goto fine;
25 /* Make sure a caller can chown. */
26 if ((ia_valid & ATTR_UID) &&
27 (current->fsuid != inode->i_uid ||
28 attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN))
29 goto error;
31 /* Make sure caller can chgrp. */
32 if ((ia_valid & ATTR_GID) &&
33 (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid) &&
34 !capable(CAP_CHOWN))
35 goto error;
37 /* Make sure a caller can chmod. */
38 if (ia_valid & ATTR_MODE) {
39 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
40 goto error;
41 /* Also check the setgid bit! */
42 if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
43 inode->i_gid) && !capable(CAP_FSETID))
44 attr->ia_mode &= ~S_ISGID;
47 /* Check for setting the inode time. */
48 if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
49 if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
50 goto error;
52 fine:
53 retval = 0;
54 error:
55 return retval;
58 void inode_setattr(struct inode * inode, struct iattr * attr)
60 unsigned int ia_valid = attr->ia_valid;
62 if (ia_valid & ATTR_UID)
63 inode->i_uid = attr->ia_uid;
64 if (ia_valid & ATTR_GID)
65 inode->i_gid = attr->ia_gid;
66 if (ia_valid & ATTR_SIZE)
67 vmtruncate(inode, attr->ia_size);
68 if (ia_valid & ATTR_ATIME)
69 inode->i_atime = attr->ia_atime;
70 if (ia_valid & ATTR_MTIME)
71 inode->i_mtime = attr->ia_mtime;
72 if (ia_valid & ATTR_CTIME)
73 inode->i_ctime = attr->ia_ctime;
74 if (ia_valid & ATTR_MODE) {
75 inode->i_mode = attr->ia_mode;
76 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
77 inode->i_mode &= ~S_ISGID;
79 mark_inode_dirty(inode);
82 int notify_change(struct dentry * dentry, struct iattr * attr)
84 struct inode *inode = dentry->d_inode;
85 int error;
86 time_t now = CURRENT_TIME;
87 unsigned int ia_valid = attr->ia_valid;
89 attr->ia_ctime = now;
90 if (!(ia_valid & ATTR_ATIME_SET))
91 attr->ia_atime = now;
92 if (!(ia_valid & ATTR_MTIME_SET))
93 attr->ia_mtime = now;
95 lock_kernel();
96 if (inode && inode->i_op && inode->i_op->setattr)
97 error = inode->i_op->setattr(dentry, attr);
98 else {
99 error = inode_change_ok(inode, attr);
100 if (!error)
101 inode_setattr(inode, attr);
103 unlock_kernel();
104 return error;