linux/arch/alpha/kernel
Ulrich Drepper 1c710c896e utimensat implementation
Implement utimensat(2) which is an extension to futimesat(2) in that it

a) supports nano-second resolution for the timestamps
b) allows to selectively ignore the atime/mtime value
c) allows to selectively use the current time for either atime or mtime
d) supports changing the atime/mtime of a symlink itself along the lines
   of the BSD lutimes(3) functions

For this change the internally used do_utimes() functions was changed to
accept a timespec time value and an additional flags parameter.

Additionally the sys_utime function was changed to match compat_sys_utime
which already use do_utimes instead of duplicating the work.

Also, the completely missing futimensat() functionality is added.  We have
such a function in glibc but we have to resort to using /proc/self/fd/* which
not everybody likes (chroot etc).

Test application (the syscall number will need per-arch editing):

#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <sys/time.h>
#include <stddef.h>
#include <syscall.h>

#define __NR_utimensat 280

#define UTIME_NOW       ((1l << 30) - 1l)
#define UTIME_OMIT      ((1l << 30) - 2l)

int
main(void)
{
  int status = 0;

  int fd = open("ttt", O_RDWR|O_CREAT|O_EXCL, 0666);
  if (fd == -1)
    error (1, errno, "failed to create test file \"ttt\"");

  struct stat64 st1;
  if (fstat64 (fd, &st1) != 0)
    error (1, errno, "fstat failed");

  struct timespec t[2];
  t[0].tv_sec = 0;
  t[0].tv_nsec = 0;
  t[1].tv_sec = 0;
  t[1].tv_nsec = 0;
  if (syscall(__NR_utimensat, AT_FDCWD, "ttt", t, 0) != 0)
    error (1, errno, "utimensat failed");

  struct stat64 st2;
  if (fstat64 (fd, &st2) != 0)
    error (1, errno, "fstat failed");

  if (st2.st_atim.tv_sec != 0 || st2.st_atim.tv_nsec != 0)
    {
      puts ("atim not reset to zero");
      status = 1;
    }
  if (st2.st_mtim.tv_sec != 0 || st2.st_mtim.tv_nsec != 0)
    {
      puts ("mtim not reset to zero");
      status = 1;
    }
  if (status != 0)
    goto out;

  t[0] = st1.st_atim;
  t[1].tv_sec = 0;
  t[1].tv_nsec = UTIME_OMIT;
  if (syscall(__NR_utimensat, AT_FDCWD, "ttt", t, 0) != 0)
    error (1, errno, "utimensat failed");

  if (fstat64 (fd, &st2) != 0)
    error (1, errno, "fstat failed");

  if (st2.st_atim.tv_sec != st1.st_atim.tv_sec
      || st2.st_atim.tv_nsec != st1.st_atim.tv_nsec)
    {
      puts ("atim not set");
      status = 1;
    }
  if (st2.st_mtim.tv_sec != 0 || st2.st_mtim.tv_nsec != 0)
    {
      puts ("mtim changed from zero");
      status = 1;
    }
  if (status != 0)
    goto out;

  t[0].tv_sec = 0;
  t[0].tv_nsec = UTIME_OMIT;
  t[1] = st1.st_mtim;
  if (syscall(__NR_utimensat, AT_FDCWD, "ttt", t, 0) != 0)
    error (1, errno, "utimensat failed");

  if (fstat64 (fd, &st2) != 0)
    error (1, errno, "fstat failed");

  if (st2.st_atim.tv_sec != st1.st_atim.tv_sec
      || st2.st_atim.tv_nsec != st1.st_atim.tv_nsec)
    {
      puts ("mtim changed from original time");
      status = 1;
    }
  if (st2.st_mtim.tv_sec != st1.st_mtim.tv_sec
      || st2.st_mtim.tv_nsec != st1.st_mtim.tv_nsec)
    {
      puts ("mtim not set");
      status = 1;
    }
  if (status != 0)
    goto out;

  sleep (2);

  t[0].tv_sec = 0;
  t[0].tv_nsec = UTIME_NOW;
  t[1].tv_sec = 0;
  t[1].tv_nsec = UTIME_NOW;
  if (syscall(__NR_utimensat, AT_FDCWD, "ttt", t, 0) != 0)
    error (1, errno, "utimensat failed");

  if (fstat64 (fd, &st2) != 0)
    error (1, errno, "fstat failed");

  struct timeval tv;
  gettimeofday(&tv,NULL);

  if (st2.st_atim.tv_sec <= st1.st_atim.tv_sec
      || st2.st_atim.tv_sec > tv.tv_sec)
    {
      puts ("atim not set to NOW");
      status = 1;
    }
  if (st2.st_mtim.tv_sec <= st1.st_mtim.tv_sec
      || st2.st_mtim.tv_sec > tv.tv_sec)
    {
      puts ("mtim not set to NOW");
      status = 1;
    }

  if (symlink ("ttt", "tttsym") != 0)
    error (1, errno, "cannot create symlink");

  t[0].tv_sec = 0;
  t[0].tv_nsec = 0;
  t[1].tv_sec = 0;
  t[1].tv_nsec = 0;
  if (syscall(__NR_utimensat, AT_FDCWD, "tttsym", t, AT_SYMLINK_NOFOLLOW) != 0)
    error (1, errno, "utimensat failed");

  if (lstat64 ("tttsym", &st2) != 0)
    error (1, errno, "lstat failed");

  if (st2.st_atim.tv_sec != 0 || st2.st_atim.tv_nsec != 0)
    {
      puts ("symlink atim not reset to zero");
      status = 1;
    }
  if (st2.st_mtim.tv_sec != 0 || st2.st_mtim.tv_nsec != 0)
    {
      puts ("symlink mtim not reset to zero");
      status = 1;
    }
  if (status != 0)
    goto out;

  t[0].tv_sec = 1;
  t[0].tv_nsec = 0;
  t[1].tv_sec = 1;
  t[1].tv_nsec = 0;
  if (syscall(__NR_utimensat, fd, NULL, t, 0) != 0)
    error (1, errno, "utimensat failed");

  if (fstat64 (fd, &st2) != 0)
    error (1, errno, "fstat failed");

  if (st2.st_atim.tv_sec != 1 || st2.st_atim.tv_nsec != 0)
    {
      puts ("atim not reset to one");
      status = 1;
    }
  if (st2.st_mtim.tv_sec != 1 || st2.st_mtim.tv_nsec != 0)
    {
      puts ("mtim not reset to one");
      status = 1;
    }

  if (status == 0)
     puts ("all OK");

 out:
  close (fd);
  unlink ("ttt");
  unlink ("tttsym");

  return status;
}

[akpm@linux-foundation.org: add missing i386 syscall table entry]
Signed-off-by: Ulrich Drepper <drepper@redhat.com>
Cc: Alexey Dobriyan <adobriyan@openvz.org>
Cc: Michael Kerrisk <mtk-manpages@gmx.net>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-08 11:15:18 -07:00
..
alpha_ksyms.c [PATCH] fixing includes in alpha_ksyms.c 2006-10-12 12:25:27 -07:00
asm-offsets.c [PATCH] alpha: Fix getxpid on alpha so it works for threads 2006-02-01 08:53:21 -08:00
console.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
core_apecs.c [PATCH] alpha pt_regs cleanups: machine_check() 2006-10-08 12:32:36 -07:00
core_cia.c [PATCH] alpha pt_regs cleanups: machine_check() 2006-10-08 12:32:36 -07:00
core_irongate.c [PATCH] alpha_ksyms.c cleanup 2006-10-11 11:17:07 -07:00
core_lca.c [PATCH] alpha pt_regs cleanups: machine_check() 2006-10-08 12:32:36 -07:00
core_marvel.c [PATCH] Don't pass boot parameters to argv_init[] 2006-03-31 12:18:53 -08:00
core_mcpcia.c alpha: fixes for specific machine types 2007-04-17 16:36:27 -07:00
core_polaris.c [PATCH] alpha pt_regs cleanups: machine_check() 2006-10-08 12:32:36 -07:00
core_t2.c [PATCH] alpha pt_regs cleanups: machine_check() 2006-10-08 12:32:36 -07:00
core_titan.c Linux-2.6.12-rc2 2005-04-16 15:20:36 -07:00
core_tsunami.c [PATCH] alpha pt_regs cleanups: machine_check() 2006-10-08 12:32:36 -07:00
core_wildfire.c [PATCH] alpha pt_regs cleanups: machine_check() 2006-10-08 12:32:36 -07:00
entry.S [PATCH] rename the provided execve functions to kernel_execve 2006-10-02 07:57:23 -07:00
err_common.c PCI: Cleanup the includes of <linux/pci.h> 2007-05-02 19:02:35 -07:00
err_ev6.c PCI: Cleanup the includes of <linux/pci.h> 2007-05-02 19:02:35 -07:00
err_ev7.c PCI: Cleanup the includes of <linux/pci.h> 2007-05-02 19:02:35 -07:00
err_impl.h [PATCH] alpha pt_regs cleanups: machine_check() 2006-10-08 12:32:36 -07:00
err_marvel.c [PATCH] alpha pt_regs cleanups: machine_check() 2006-10-08 12:32:36 -07:00
err_titan.c alpha: fixes for specific machine types 2007-04-17 16:36:27 -07:00
es1888.c Linux-2.6.12-rc2 2005-04-16 15:20:36 -07:00
gct.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
head.S fix file specification in comments 2006-10-03 23:01:26 +02:00
init_task.c [PATCH] nsproxy: move init_nsproxy into kernel/nsproxy.c 2006-10-02 07:57:20 -07:00
io.c Linux-2.6.12-rc2 2005-04-16 15:20:36 -07:00
irq_alpha.c [PATCH] alpha_ksyms.c cleanup 2006-10-11 11:17:07 -07:00
irq_i8259.c [PATCH] alpha pt_regs cleanups: handle_irq() 2006-10-08 12:32:35 -07:00
irq_impl.h [PATCH] alpha pt_regs cleanups: handle_irq() 2006-10-08 12:32:35 -07:00
irq_pyxis.c [PATCH] alpha pt_regs cleanups: handle_irq() 2006-10-08 12:32:35 -07:00
irq_srm.c [PATCH] alpha pt_regs cleanups: handle_irq() 2006-10-08 12:32:35 -07:00
irq.c [PATCH] alpha pt_regs cleanups: handle_irq() 2006-10-08 12:32:35 -07:00
machvec_impl.h fix file specification in comments 2006-10-03 23:01:26 +02:00
Makefile Linux-2.6.12-rc2 2005-04-16 15:20:36 -07:00
module.c alpha: fixes for specific machine types 2007-04-17 16:36:27 -07:00
ns87312.c Linux-2.6.12-rc2 2005-04-16 15:20:36 -07:00
osf_sys.c utimensat implementation 2007-05-08 11:15:18 -07:00
pci_impl.h Linux-2.6.12-rc2 2005-04-16 15:20:36 -07:00
pci_iommu.c [PATCH] alpha_ksyms.c cleanup 2006-10-11 11:17:07 -07:00
pci-noop.c [PATCH] alpha_ksyms.c cleanup 2006-10-11 11:17:07 -07:00
pci.c PCI: make isa_bridge Alpha-only 2007-02-07 15:50:06 -08:00
process.c header cleaning: don't include smp_lock.h when not used 2007-05-08 11:15:07 -07:00
proto.h [PATCH] fallout from alpha pt_regs patches 2006-10-09 14:19:07 -07:00
ptrace.c [PATCH] alpha: task_pt_regs() 2006-01-12 09:08:50 -08:00
semaphore.c Linux-2.6.12-rc2 2005-04-16 15:20:36 -07:00
setup.c Fixes and cleanups for earlyprintk aka boot console 2007-05-08 11:15:04 -07:00
signal.c header cleaning: don't include smp_lock.h when not used 2007-05-08 11:15:07 -07:00
smc37c93x.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
smc37c669.c Linux-2.6.12-rc2 2005-04-16 15:20:36 -07:00
smp.c header cleaning: don't include smp_lock.h when not used 2007-05-08 11:15:07 -07:00
srm_env.c Update for the srm_env driver. 2006-11-07 23:50:37 +01:00
srmcons.c Fixes and cleanups for earlyprintk aka boot console 2007-05-08 11:15:04 -07:00
sys_alcor.c [PATCH] alpha pt_regs cleanups: handle_irq() 2006-10-08 12:32:35 -07:00
sys_cabriolet.c [PATCH] alpha pt_regs cleanups: handle_irq() 2006-10-08 12:32:35 -07:00
sys_dp264.c [PATCH] alpha pt_regs cleanups: handle_irq() 2006-10-08 12:32:35 -07:00
sys_eb64p.c [PATCH] alpha pt_regs cleanups: handle_irq() 2006-10-08 12:32:35 -07:00
sys_eiger.c [PATCH] alpha pt_regs cleanups: handle_irq() 2006-10-08 12:32:35 -07:00
sys_jensen.c [PATCH] alpha pt_regs cleanups: machine_check() 2006-10-08 12:32:36 -07:00
sys_marvel.c [PATCH] alpha pt_regs cleanups: handle_irq() 2006-10-08 12:32:35 -07:00
sys_miata.c [PATCH] alpha: switch to pci_get API 2006-12-07 08:39:26 -08:00
sys_mikasa.c [PATCH] alpha pt_regs cleanups: machine_check() 2006-10-08 12:32:36 -07:00
sys_nautilus.c alpha: more fixes for specific machine types 2007-04-17 16:36:27 -07:00
sys_noritake.c alpha: fixes for specific machine types 2007-04-17 16:36:27 -07:00
sys_rawhide.c alpha: fixes for specific machine types 2007-04-17 16:36:27 -07:00
sys_ruffian.c [PATCH] arch/alpha: Use ARRAY_SIZE macro 2006-07-31 13:28:38 -07:00
sys_rx164.c [PATCH] alpha pt_regs cleanups: handle_irq() 2006-10-08 12:32:35 -07:00
sys_sable.c [PATCH] alpha pt_regs cleanups: handle_irq() 2006-10-08 12:32:35 -07:00
sys_sio.c alpha: fixes for specific machine types 2007-04-17 16:36:27 -07:00
sys_sx164.c alpha: more fixes for specific machine types 2007-04-17 16:36:27 -07:00
sys_takara.c [PATCH] alpha pt_regs cleanups: handle_irq() 2006-10-08 12:32:35 -07:00
sys_titan.c alpha: build fixes - force architecture 2007-04-17 16:36:27 -07:00
sys_wildfire.c [PATCH] alpha pt_regs cleanups: handle_irq() 2006-10-08 12:32:35 -07:00
systbls.S Remove all inclusions of <linux/config.h> 2006-10-04 03:38:54 -04:00
time.c [PATCH] Consolidate default sched_clock() 2007-02-11 10:51:28 -08:00
traps.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
vmlinux.lds.S [PATCH] x86: Allow percpu variables to be page-aligned 2007-05-02 19:27:12 +02:00