~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/attr.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 15 /* Taken over from the old code... */
 16 
 17 /* POSIX UID/GID verification for setting inode attributes. */
 18 int inode_change_ok(struct inode *inode, struct iattr *attr)
 19 {
 20         int retval = -EPERM;
 21         unsigned int ia_valid = attr->ia_valid;
 22 
 23         /* If force is set do it anyway. */
 24         if (ia_valid & ATTR_FORCE)
 25                 goto fine;
 26 
 27         /* Make sure a caller can chown. */
 28         if ((ia_valid & ATTR_UID) &&
 29             (current->fsuid != inode->i_uid ||
 30              attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN))
 31                 goto error;
 32 
 33         /* Make sure caller can chgrp. */
 34         if ((ia_valid & ATTR_GID) &&
 35             (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid) &&
 36             !capable(CAP_CHOWN))
 37                 goto error;
 38 
 39         /* Make sure a caller can chmod. */
 40         if (ia_valid & ATTR_MODE) {
 41                 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
 42                         goto error;
 43                 /* Also check the setgid bit! */
 44                 if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
 45                                 inode->i_gid) && !capable(CAP_FSETID))
 46                         attr->ia_mode &= ~S_ISGID;
 47         }
 48 
 49         /* Check for setting the inode time. */
 50         if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
 51                 if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
 52                         goto error;
 53         }
 54 fine:
 55         retval = 0;
 56 error:
 57         return retval;
 58 }
 59 
 60 void inode_setattr(struct inode * inode, struct iattr * attr)
 61 {
 62         unsigned int ia_valid = attr->ia_valid;
 63 
 64         if (ia_valid & ATTR_UID)
 65                 inode->i_uid = attr->ia_uid;
 66         if (ia_valid & ATTR_GID)
 67                 inode->i_gid = attr->ia_gid;
 68         if (ia_valid & ATTR_SIZE)
 69                 vmtruncate(inode, attr->ia_size);
 70         if (ia_valid & ATTR_ATIME)
 71                 inode->i_atime = attr->ia_atime;
 72         if (ia_valid & ATTR_MTIME)
 73                 inode->i_mtime = attr->ia_mtime;
 74         if (ia_valid & ATTR_CTIME)
 75                 inode->i_ctime = attr->ia_ctime;
 76         if (ia_valid & ATTR_MODE) {
 77                 inode->i_mode = attr->ia_mode;
 78                 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
 79                         inode->i_mode &= ~S_ISGID;
 80         }
 81         mark_inode_dirty(inode);
 82 }
 83 
 84 static int setattr_mask(unsigned int ia_valid)
 85 {
 86         unsigned long dn_mask = 0;
 87 
 88         if (ia_valid & ATTR_UID)
 89                 dn_mask |= DN_ATTRIB;
 90         if (ia_valid & ATTR_GID)
 91                 dn_mask |= DN_ATTRIB;
 92         if (ia_valid & ATTR_SIZE)
 93                 dn_mask |= DN_MODIFY;
 94         /* both times implies a utime(s) call */
 95         if ((ia_valid & (ATTR_ATIME|ATTR_MTIME)) == (ATTR_ATIME|ATTR_MTIME))
 96                 dn_mask |= DN_ATTRIB;
 97         else if (ia_valid & ATTR_ATIME)
 98                 dn_mask |= DN_ACCESS;
 99         else if (ia_valid & ATTR_MTIME)
100                 dn_mask |= DN_MODIFY;
101         if (ia_valid & ATTR_MODE)
102                 dn_mask |= DN_ATTRIB;
103         return dn_mask;
104 }
105 
106 int notify_change(struct dentry * dentry, struct iattr * attr)
107 {
108         struct inode *inode = dentry->d_inode;
109         int error;
110         time_t now = CURRENT_TIME;
111         unsigned int ia_valid = attr->ia_valid;
112 
113         if (!inode)
114                 BUG();
115 
116         attr->ia_ctime = now;
117         if (!(ia_valid & ATTR_ATIME_SET))
118                 attr->ia_atime = now;
119         if (!(ia_valid & ATTR_MTIME_SET))
120                 attr->ia_mtime = now;
121 
122         lock_kernel();
123         if (inode->i_op && inode->i_op->setattr) 
124                 error = inode->i_op->setattr(dentry, attr);
125         else {
126                 error = inode_change_ok(inode, attr);
127                 if (!error)
128                         inode_setattr(inode, attr);
129         }
130         unlock_kernel();
131         if (!error) {
132                 unsigned long dn_mask = setattr_mask(ia_valid);
133                 if (dn_mask)
134                         inode_dir_notify(dentry->d_parent->d_inode, dn_mask);
135         }
136         return error;
137 }
138 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.