original_kernel/arch/sparc64/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
..
Makefile [SPARC64]: SUN4U PCI-E controller support. 2007-05-06 22:44:06 -07:00
asm-offsets.c
audit.c
auxio.c
binfmt_aout32.c
binfmt_elf32.c
central.c [SPARC64]: Fix section mismatch warnings in arch/sparc64/kernel/console.c 2007-05-07 00:00:37 -07:00
chmc.c [SPARC64]: constify of_get_property return: arch/sparc64 2007-04-26 01:54:24 -07:00
compat_audit.c
cpu.c
devices.c
dtlb_miss.S
dtlb_prot.S
ebus.c [SPARC64] ebus: Convert to use pci_device_to_OF_node(). 2007-04-26 01:55:04 -07:00
entry.S
etrap.S
head.S
idprom.c
init_task.c
iommu_common.c
iommu_common.h
irq.c [SPARC64]: SUN4U PCI-E controller support. 2007-05-06 22:44:06 -07:00
isa.c [SPARC64] isa: Convert to use pci_device_to_OF_node(). 2007-04-26 01:55:05 -07:00
itlb_miss.S
kprobes.c move die notifier handling to common code 2007-05-08 11:15:04 -07:00
ktlb.S [SPARC64]: Get DEBUG_PAGEALLOC working again. 2007-03-16 17:20:28 -07:00
module.c
of_device.c [SPARC64]: Fix PCI rework to adhere to of_get_property() const return. 2007-04-26 01:55:37 -07:00
pci.c header cleaning: don't include smp_lock.h when not used 2007-05-08 11:15:07 -07:00
pci_common.c [SPARC64]: Fix PCI rework to adhere to of_get_property() const return. 2007-04-26 01:55:37 -07:00
pci_fire.c [SPARC64]: SUN4U PCI-E controller support. 2007-05-06 22:44:06 -07:00
pci_impl.h [SPARC64]: Add dummy host controller to root of all PCI domains. 2007-04-26 01:55:19 -07:00
pci_iommu.c [SPARC64]: SUN4U PCI-E controller support. 2007-05-06 22:44:06 -07:00
pci_psycho.c [SPARC64]: Convert PCI over to generic struct iommu/strbuf. 2007-04-26 21:08:21 -07:00
pci_sabre.c [SPARC64]: Convert PCI over to generic struct iommu/strbuf. 2007-04-26 21:08:21 -07:00
pci_schizo.c [SPARC64]: Convert PCI over to generic struct iommu/strbuf. 2007-04-26 21:08:21 -07:00
pci_sun4v.c MSI: arch must connect the irq and the msi_desc 2007-05-02 19:02:38 -07:00
pci_sun4v.h [SPARC64]: Add PCI MSI support on Niagara. 2007-02-10 23:50:37 -08:00
pci_sun4v_asm.S [SPARC64]: Add PCI MSI support on Niagara. 2007-02-10 23:50:37 -08:00
power.c
process.c header cleaning: don't include smp_lock.h when not used 2007-05-08 11:15:07 -07:00
prom.c [SPARC64]: Fix section mismatch warnings in arch/sparc64/kernel/prom.c 2007-05-07 00:02:24 -07:00
ptrace.c
rtrap.S
sbus.c [SPARC64]: Convert SBUS over to generic iommu/strbuf structs. 2007-04-26 01:55:44 -07:00
semaphore.c
setup.c [PATCH] Dynamic kernel command-line: sparc64 2007-02-12 09:48:39 -08:00
signal.c header cleaning: don't include smp_lock.h when not used 2007-05-08 11:15:07 -07:00
signal32.c header cleaning: don't include smp_lock.h when not used 2007-05-08 11:15:07 -07:00
smp.c header cleaning: don't include smp_lock.h when not used 2007-05-08 11:15:07 -07:00
sparc64_ksyms.c [SPARC64]: Internalize pci_memspace_mask. 2007-04-26 01:55:07 -07:00
stacktrace.c simplify the stacktrace code 2007-05-08 11:14:58 -07:00
starfire.c
sun4v_ivec.S
sun4v_tlb_miss.S [SPARC64]: Set g4/g5 properly in sun4v dtlb-prot handling. 2007-01-26 18:56:01 -08:00
sunos_ioctl32.c header cleaning: don't include smp_lock.h when not used 2007-05-08 11:15:07 -07:00
sys32.S [SPARC64]: Fix arg passing to compat_sys_ipc(). 2007-04-13 13:27:08 -07:00
sys_sparc.c header cleaning: don't include smp_lock.h when not used 2007-05-08 11:15:07 -07:00
sys_sparc32.c utimensat implementation 2007-05-08 11:15:18 -07:00
sys_sunos32.c [SPARC]: avoid CHILD_MAX and OPEN_MAX constants 2007-04-12 13:13:42 -07:00
systbls.S [SPARC64]: Fix arg passing to compat_sys_ipc(). 2007-04-13 13:27:08 -07:00
time.c [SPARC64]: constify of_get_property return: arch/sparc64 2007-04-26 01:54:24 -07:00
trampoline.S
traps.c header cleaning: don't include smp_lock.h when not used 2007-05-08 11:15:07 -07:00
tsb.S [SPARC64]: store-init needs trailing membar. 2007-03-19 13:27:33 -07:00
ttable.S [SPARC64]: Unify timer interrupt handler. 2007-04-26 01:54:11 -07:00
una_asm.S
unaligned.c header cleaning: don't include smp_lock.h when not used 2007-05-08 11:15:07 -07:00
us2e_cpufreq.c
us3_cpufreq.c
visemul.c
vmlinux.lds.S [PATCH] disable init/initramfs.c: architectures 2007-02-11 10:51:25 -08:00
winfixup.S