Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] Create fs/utimes.c

* fs/open.c is getting bit crowdy
* preparation to lutimes(2)

Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Alexey Dobriyan and committed by
Linus Torvalds
82b0547c 52978be6

+141 -135
+1 -1
fs/Makefile
··· 10 10 ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \ 11 11 attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \ 12 12 seq_file.o xattr.o libfs.o fs-writeback.o \ 13 - pnode.o drop_caches.o splice.o sync.o 13 + pnode.o drop_caches.o splice.o sync.o utimes.o 14 14 15 15 ifeq ($(CONFIG_BLOCK),y) 16 16 obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
-134
fs/open.c
··· 6 6 7 7 #include <linux/string.h> 8 8 #include <linux/mm.h> 9 - #include <linux/utime.h> 10 9 #include <linux/file.h> 11 10 #include <linux/smp_lock.h> 12 11 #include <linux/quotaops.h> ··· 27 28 #include <linux/syscalls.h> 28 29 #include <linux/rcupdate.h> 29 30 #include <linux/audit.h> 30 - 31 - #include <asm/unistd.h> 32 31 33 32 int vfs_statfs(struct dentry *dentry, struct kstatfs *buf) 34 33 { ··· 349 352 return ret; 350 353 } 351 354 #endif 352 - 353 - #ifdef __ARCH_WANT_SYS_UTIME 354 - 355 - /* 356 - * sys_utime() can be implemented in user-level using sys_utimes(). 357 - * Is this for backwards compatibility? If so, why not move it 358 - * into the appropriate arch directory (for those architectures that 359 - * need it). 360 - */ 361 - 362 - /* If times==NULL, set access and modification to current time, 363 - * must be owner or have write permission. 364 - * Else, update from *times, must be owner or super user. 365 - */ 366 - asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times) 367 - { 368 - int error; 369 - struct nameidata nd; 370 - struct inode * inode; 371 - struct iattr newattrs; 372 - 373 - error = user_path_walk(filename, &nd); 374 - if (error) 375 - goto out; 376 - inode = nd.dentry->d_inode; 377 - 378 - error = -EROFS; 379 - if (IS_RDONLY(inode)) 380 - goto dput_and_out; 381 - 382 - /* Don't worry, the checks are done in inode_change_ok() */ 383 - newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME; 384 - if (times) { 385 - error = -EPERM; 386 - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) 387 - goto dput_and_out; 388 - 389 - error = get_user(newattrs.ia_atime.tv_sec, &times->actime); 390 - newattrs.ia_atime.tv_nsec = 0; 391 - if (!error) 392 - error = get_user(newattrs.ia_mtime.tv_sec, &times->modtime); 393 - newattrs.ia_mtime.tv_nsec = 0; 394 - if (error) 395 - goto dput_and_out; 396 - 397 - newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; 398 - } else { 399 - error = -EACCES; 400 - if (IS_IMMUTABLE(inode)) 401 - goto dput_and_out; 402 - 403 - if (current->fsuid != inode->i_uid && 404 - (error = vfs_permission(&nd, MAY_WRITE)) != 0) 405 - goto dput_and_out; 406 - } 407 - mutex_lock(&inode->i_mutex); 408 - error = notify_change(nd.dentry, &newattrs); 409 - mutex_unlock(&inode->i_mutex); 410 - dput_and_out: 411 - path_release(&nd); 412 - out: 413 - return error; 414 - } 415 - 416 - #endif 417 - 418 - /* If times==NULL, set access and modification to current time, 419 - * must be owner or have write permission. 420 - * Else, update from *times, must be owner or super user. 421 - */ 422 - long do_utimes(int dfd, char __user *filename, struct timeval *times) 423 - { 424 - int error; 425 - struct nameidata nd; 426 - struct inode * inode; 427 - struct iattr newattrs; 428 - 429 - error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd); 430 - 431 - if (error) 432 - goto out; 433 - inode = nd.dentry->d_inode; 434 - 435 - error = -EROFS; 436 - if (IS_RDONLY(inode)) 437 - goto dput_and_out; 438 - 439 - /* Don't worry, the checks are done in inode_change_ok() */ 440 - newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME; 441 - if (times) { 442 - error = -EPERM; 443 - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) 444 - goto dput_and_out; 445 - 446 - newattrs.ia_atime.tv_sec = times[0].tv_sec; 447 - newattrs.ia_atime.tv_nsec = times[0].tv_usec * 1000; 448 - newattrs.ia_mtime.tv_sec = times[1].tv_sec; 449 - newattrs.ia_mtime.tv_nsec = times[1].tv_usec * 1000; 450 - newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; 451 - } else { 452 - error = -EACCES; 453 - if (IS_IMMUTABLE(inode)) 454 - goto dput_and_out; 455 - 456 - if (current->fsuid != inode->i_uid && 457 - (error = vfs_permission(&nd, MAY_WRITE)) != 0) 458 - goto dput_and_out; 459 - } 460 - mutex_lock(&inode->i_mutex); 461 - error = notify_change(nd.dentry, &newattrs); 462 - mutex_unlock(&inode->i_mutex); 463 - dput_and_out: 464 - path_release(&nd); 465 - out: 466 - return error; 467 - } 468 - 469 - asmlinkage long sys_futimesat(int dfd, char __user *filename, struct timeval __user *utimes) 470 - { 471 - struct timeval times[2]; 472 - 473 - if (utimes && copy_from_user(&times, utimes, sizeof(times))) 474 - return -EFAULT; 475 - return do_utimes(dfd, filename, utimes ? times : NULL); 476 - } 477 - 478 - asmlinkage long sys_utimes(char __user *filename, struct timeval __user *utimes) 479 - { 480 - return sys_futimesat(AT_FDCWD, filename, utimes); 481 - } 482 - 483 355 484 356 /* 485 357 * access() needs to use the real uid/gid, not the effective uid/gid.
+137
fs/utimes.c
··· 1 + #include <linux/compiler.h> 2 + #include <linux/fs.h> 3 + #include <linux/linkage.h> 4 + #include <linux/namei.h> 5 + #include <linux/utime.h> 6 + #include <asm/uaccess.h> 7 + #include <asm/unistd.h> 8 + 9 + #ifdef __ARCH_WANT_SYS_UTIME 10 + 11 + /* 12 + * sys_utime() can be implemented in user-level using sys_utimes(). 13 + * Is this for backwards compatibility? If so, why not move it 14 + * into the appropriate arch directory (for those architectures that 15 + * need it). 16 + */ 17 + 18 + /* If times==NULL, set access and modification to current time, 19 + * must be owner or have write permission. 20 + * Else, update from *times, must be owner or super user. 21 + */ 22 + asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times) 23 + { 24 + int error; 25 + struct nameidata nd; 26 + struct inode * inode; 27 + struct iattr newattrs; 28 + 29 + error = user_path_walk(filename, &nd); 30 + if (error) 31 + goto out; 32 + inode = nd.dentry->d_inode; 33 + 34 + error = -EROFS; 35 + if (IS_RDONLY(inode)) 36 + goto dput_and_out; 37 + 38 + /* Don't worry, the checks are done in inode_change_ok() */ 39 + newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME; 40 + if (times) { 41 + error = -EPERM; 42 + if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) 43 + goto dput_and_out; 44 + 45 + error = get_user(newattrs.ia_atime.tv_sec, &times->actime); 46 + newattrs.ia_atime.tv_nsec = 0; 47 + if (!error) 48 + error = get_user(newattrs.ia_mtime.tv_sec, &times->modtime); 49 + newattrs.ia_mtime.tv_nsec = 0; 50 + if (error) 51 + goto dput_and_out; 52 + 53 + newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; 54 + } else { 55 + error = -EACCES; 56 + if (IS_IMMUTABLE(inode)) 57 + goto dput_and_out; 58 + 59 + if (current->fsuid != inode->i_uid && 60 + (error = vfs_permission(&nd, MAY_WRITE)) != 0) 61 + goto dput_and_out; 62 + } 63 + mutex_lock(&inode->i_mutex); 64 + error = notify_change(nd.dentry, &newattrs); 65 + mutex_unlock(&inode->i_mutex); 66 + dput_and_out: 67 + path_release(&nd); 68 + out: 69 + return error; 70 + } 71 + 72 + #endif 73 + 74 + /* If times==NULL, set access and modification to current time, 75 + * must be owner or have write permission. 76 + * Else, update from *times, must be owner or super user. 77 + */ 78 + long do_utimes(int dfd, char __user *filename, struct timeval *times) 79 + { 80 + int error; 81 + struct nameidata nd; 82 + struct inode * inode; 83 + struct iattr newattrs; 84 + 85 + error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd); 86 + 87 + if (error) 88 + goto out; 89 + inode = nd.dentry->d_inode; 90 + 91 + error = -EROFS; 92 + if (IS_RDONLY(inode)) 93 + goto dput_and_out; 94 + 95 + /* Don't worry, the checks are done in inode_change_ok() */ 96 + newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME; 97 + if (times) { 98 + error = -EPERM; 99 + if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) 100 + goto dput_and_out; 101 + 102 + newattrs.ia_atime.tv_sec = times[0].tv_sec; 103 + newattrs.ia_atime.tv_nsec = times[0].tv_usec * 1000; 104 + newattrs.ia_mtime.tv_sec = times[1].tv_sec; 105 + newattrs.ia_mtime.tv_nsec = times[1].tv_usec * 1000; 106 + newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; 107 + } else { 108 + error = -EACCES; 109 + if (IS_IMMUTABLE(inode)) 110 + goto dput_and_out; 111 + 112 + if (current->fsuid != inode->i_uid && 113 + (error = vfs_permission(&nd, MAY_WRITE)) != 0) 114 + goto dput_and_out; 115 + } 116 + mutex_lock(&inode->i_mutex); 117 + error = notify_change(nd.dentry, &newattrs); 118 + mutex_unlock(&inode->i_mutex); 119 + dput_and_out: 120 + path_release(&nd); 121 + out: 122 + return error; 123 + } 124 + 125 + asmlinkage long sys_futimesat(int dfd, char __user *filename, struct timeval __user *utimes) 126 + { 127 + struct timeval times[2]; 128 + 129 + if (utimes && copy_from_user(&times, utimes, sizeof(times))) 130 + return -EFAULT; 131 + return do_utimes(dfd, filename, utimes ? times : NULL); 132 + } 133 + 134 + asmlinkage long sys_utimes(char __user *filename, struct timeval __user *utimes) 135 + { 136 + return sys_futimesat(AT_FDCWD, filename, utimes); 137 + }
+1
include/linux/namei.h
··· 1 1 #ifndef _LINUX_NAMEI_H 2 2 #define _LINUX_NAMEI_H 3 3 4 + #include <linux/dcache.h> 4 5 #include <linux/linkage.h> 5 6 6 7 struct vfsmount;
+2
include/linux/utime.h
··· 1 1 #ifndef _LINUX_UTIME_H 2 2 #define _LINUX_UTIME_H 3 3 4 + #include <linux/types.h> 5 + 4 6 struct utimbuf { 5 7 time_t actime; 6 8 time_t modtime;