__NOMIPS16 #endif asmlinkage long sys_utime(char * filename, struct utimbuf * times) { int error; struct nameidata nd; struct inode * inode; struct iattr newattrs; error = user_path_walk(filename, &nd); if (error) goto out; inode = nd.dentry->d_inode; error = -EROFS; if (IS_RDONLY(inode)) goto dput_and_out; /* Don't worry, the checks are done in inode_change_ok() */ newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME; if (times) { error = get_user(newattrs.ia_atime, ×->actime); if (!error) error = get_user(newattrs.ia_mtime, ×->modtime); if (error) goto dput_and_out; newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; } else { if (current->fsuid != inode->i_uid && (error = permission(inode,MAY_WRITE)) != 0) goto dput_and_out; } error = notify_change(nd.dentry, &newattrs); dput_and_out: path_release(&nd); out: return error; }
__NOMIPS16 #endif asmlinkage long sys_utimes(char * filename, struct timeval * utimes) { int error; struct nameidata nd; struct inode * inode; struct iattr newattrs; error = user_path_walk(filename, &nd); if (error) goto out; inode = nd.dentry->d_inode; error = -EROFS; if (IS_RDONLY(inode)) goto dput_and_out; /* Don't worry, the checks are done in inode_change_ok() */ newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME; if (utimes) { struct timeval times[2]; error = -EFAULT; if (copy_from_user(×, utimes, sizeof(times))) goto dput_and_out; newattrs.ia_atime = times[0].tv_sec; newattrs.ia_mtime = times[1].tv_sec; newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; } else { if ((error = permission(inode,MAY_WRITE)) != 0) goto dput_and_out; } error = notify_change(nd.dentry, &newattrs); dput_and_out: path_release(&nd); out: return error; }
static long do_sys_truncate(const char __user * path, loff_t length) { struct nameidata nd; struct inode * inode; int error; error = -EINVAL; if (length < 0) /* sorry, but loff_t says... */ goto out; error = user_path_walk(path, &nd); if (error) goto out; inode = nd.path.dentry->d_inode; /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ error = -EISDIR; if (S_ISDIR(inode->i_mode)) goto dput_and_out; error = -EINVAL; if (!S_ISREG(inode->i_mode)) goto dput_and_out; error = mnt_want_write(nd.path.mnt); if (error) goto dput_and_out; error = vfs_permission(&nd, MAY_WRITE); if (error) goto mnt_drop_write_and_out; error = -EPERM; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto mnt_drop_write_and_out; error = get_write_access(inode); if (error) goto mnt_drop_write_and_out; /* * Make sure that there are no leases. get_write_access() protects * against the truncate racing with a lease-granting setlease(). */ error = break_lease(inode, FMODE_WRITE); if (error) goto put_write_and_out; error = locks_verify_truncate(inode, NULL, length); if (!error) { DQUOT_INIT(inode); error = do_truncate(nd.path.dentry, length, 0, NULL); } put_write_and_out: put_write_access(inode); mnt_drop_write_and_out: mnt_drop_write(nd.path.mnt); dput_and_out: path_put(&nd.path); out: return error; }