Merge branch 'devel' into next
[pandora-kernel.git] / fs / utimes.c
index af059d5..b6b664e 100644 (file)
@@ -40,14 +40,9 @@ asmlinkage long sys_utime(char __user *filename, struct utimbuf __user *times)
 
 #endif
 
-static bool nsec_special(long nsec)
-{
-       return nsec == UTIME_OMIT || nsec == UTIME_NOW;
-}
-
 static bool nsec_valid(long nsec)
 {
-       if (nsec_special(nsec))
+       if (nsec == UTIME_OMIT || nsec == UTIME_NOW)
                return true;
 
        return nsec >= 0 && nsec <= 999999999;
@@ -102,7 +97,11 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
        if (error)
                goto dput_and_out;
 
-       /* Don't worry, the checks are done in inode_change_ok() */
+       if (times && times[0].tv_nsec == UTIME_NOW &&
+                    times[1].tv_nsec == UTIME_NOW)
+               times = NULL;
+
+       /* In most cases, the checks are done in inode_change_ok() */
        newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
        if (times) {
                error = -EPERM;
@@ -124,28 +123,34 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
                        newattrs.ia_mtime.tv_nsec = times[1].tv_nsec;
                        newattrs.ia_valid |= ATTR_MTIME_SET;
                }
-       }
 
-       /*
-        * If times is NULL or both times are either UTIME_OMIT or
-        * UTIME_NOW, then need to check permissions, because
-        * inode_change_ok() won't do it.
-        */
-       if (!times || (nsec_special(times[0].tv_nsec) &&
-                      nsec_special(times[1].tv_nsec))) {
+               /*
+                * For the UTIME_OMIT/UTIME_NOW and UTIME_NOW/UTIME_OMIT
+                * cases, we need to make an extra check that is not done by
+                * inode_change_ok().
+                */
+               if (((times[0].tv_nsec == UTIME_NOW &&
+                           times[1].tv_nsec == UTIME_OMIT)
+                    ||
+                    (times[0].tv_nsec == UTIME_OMIT &&
+                           times[1].tv_nsec == UTIME_NOW))
+                   && !is_owner_or_cap(inode))
+                       goto mnt_drop_write_and_out;
+       } else {
+
+               /*
+                * If times is NULL (or both times are UTIME_NOW),
+                * then we need to check permissions, because
+                * inode_change_ok() won't do it.
+                */
                error = -EACCES;
                 if (IS_IMMUTABLE(inode))
                        goto mnt_drop_write_and_out;
 
                if (!is_owner_or_cap(inode)) {
-                       if (f) {
-                               if (!(f->f_mode & FMODE_WRITE))
-                                       goto mnt_drop_write_and_out;
-                       } else {
-                               error = vfs_permission(&nd, MAY_WRITE);
-                               if (error)
-                                       goto mnt_drop_write_and_out;
-                       }
+                       error = permission(inode, MAY_WRITE, NULL);
+                       if (error)
+                               goto mnt_drop_write_and_out;
                }
        }
        mutex_lock(&inode->i_mutex);
@@ -169,14 +174,6 @@ asmlinkage long sys_utimensat(int dfd, char __user *filename, struct timespec __
        if (utimes) {
                if (copy_from_user(&tstimes, utimes, sizeof(tstimes)))
                        return -EFAULT;
-               if ((tstimes[0].tv_nsec == UTIME_OMIT ||
-                    tstimes[0].tv_nsec == UTIME_NOW) &&
-                   tstimes[0].tv_sec != 0)
-                       return -EINVAL;
-               if ((tstimes[1].tv_nsec == UTIME_OMIT ||
-                    tstimes[1].tv_nsec == UTIME_NOW) &&
-                   tstimes[1].tv_sec != 0)
-                       return -EINVAL;
 
                /* Nothing to do, we must not even check the path.  */
                if (tstimes[0].tv_nsec == UTIME_OMIT &&