Stubs and parsing for rename and timestamps (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 22 Jul 2014 23:45:21 +0000 (16:45 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 22 Jul 2014 23:54:34 +0000 (16:54 -0700)
Glibc calls for utime, utimes, futimens, and whatever all call wstat
underneath.  The kernel just prints out the request and fails.

Any of the "at" calls will error out if you give them a directory fd.
We'll eventually support those.

We don't support the symlink flags for utimensat either.  Those are just
ignored, since wstat doesn't follow links (at least not explicitly, and
it might for the VFS).  Will probably need to handle that for all wstat
too (either a flag or lwstat).  Can address that when we sort out the
"at".

12 files changed:
kern/src/syscall.c
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/ftruncate.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/ftruncate64.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/futimens.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/futimes.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/futimesat.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/rename.c
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/truncate.c
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/truncate64.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/utime.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/utimensat.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/utimes.c [new file with mode: 0644]

index a1a1ed6..b982bb7 100644 (file)
@@ -1788,6 +1788,27 @@ static int vfs_wstat(struct file *file, uint8_t *stat_m, size_t stat_sz,
                if (retval < 0)
                        goto out;
        }
+       if (flags & WSTAT_LENGTH) {
+               printk("Got truncate for file %s to length %d\n", file_name(file),
+                      dir->length);
+               /* Fail for now */
+               retval = -1;
+               goto out;
+       }
+       if (flags & WSTAT_ATIME) {
+               printk("Got atime change for file %s to time %d\n", file_name(file),
+                      dir->atime);
+               /* Fail for now */
+               retval = -1;
+               goto out;
+       }
+       if (flags & WSTAT_MTIME) {
+               printk("Got mtime change for file %s to time %d\n", file_name(file),
+                      dir->mtime);
+               /* Fail for now */
+               retval = -1;
+               goto out;
+       }
 
 out:
        kfree(dir);
@@ -1842,6 +1863,7 @@ intreg_t sys_fwstat(struct proc *p, int fd, uint8_t *stat_m, size_t stat_sz,
 intreg_t sys_rename(struct proc *p, char *old_path, size_t old_path_l,
                     char *new_path, size_t new_path_l)
 {
+       printk("got rename from %s to %s\n", old_path, new_path);
        /* this might trick userspace code to fallback to copying, for now */
        set_errno(EXDEV);
        return -1;
diff --git a/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/ftruncate.c b/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/ftruncate.c
new file mode 100644 (file)
index 0000000..d015757
--- /dev/null
@@ -0,0 +1,31 @@
+/* Copyright (C) 1991, 1995, 1996, 1997, 1998, 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/* Truncate the file referenced by FD to LENGTH bytes.  */
+int
+__ftruncate (fd, length)
+     int fd;
+     off_t length;
+{
+  return ftruncate64(fd, length);
+}
+weak_alias (__ftruncate, ftruncate)
diff --git a/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/ftruncate64.c b/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/ftruncate64.c
new file mode 100644 (file)
index 0000000..fc2d111
--- /dev/null
@@ -0,0 +1,47 @@
+/* Copyright (C) 1997, 1998, 2001, 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcall.h>
+
+/* Truncate the file referenced by FD to LENGTH bytes.  */
+int
+__ftruncate64 (fd, length)
+     int fd;
+     off64_t length;
+{
+  struct dir dir;
+  size_t mlen;
+  char mbuf[STATFIXLEN];
+  int ret;
+
+  if (fd < 0)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  init_empty_dir(&dir);
+  dir.length = length;
+  mlen = convD2M(&dir, mbuf, STATFIXLEN);
+  ret = ros_syscall(SYS_fwstat, fd, mbuf, mlen, WSTAT_LENGTH, 0, 0);
+  return (ret == mlen ? 0 : -1);
+}
+weak_alias (__ftruncate64, ftruncate64)
diff --git a/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/futimens.c b/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/futimens.c
new file mode 100644 (file)
index 0000000..52b9983
--- /dev/null
@@ -0,0 +1,90 @@
+/* Change access and modification times of open file.  Linux version.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+#include <sysdep.h>
+#include <fcall.h>
+#include <sys/time.h>
+#include <ros/syscall.h>
+
+/* Change the access time of the file associated with FD to TSP[0] and
+   the modification time of FILE to TSP[1].  */
+
+
+/* brho notes: gettimeofday doesn't have nsec precision, and we also drop down
+ * to second precision for wstat (for now).  also, on some systems, modifying
+ * the mtime may change the atime too.  could be surprising. */
+int
+futimens (int fd, const struct timespec tsp[2])
+{
+  struct dir dir;
+  size_t mlen;
+  char mbuf[STATFIXLEN];
+  int ret;
+  int wstat_flags = 0;
+  struct timeval tv_now = {0};
+
+  if (fd < 0)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  init_empty_dir(&dir);
+
+  /* copy-and-pasted with utimensat */
+  if (!tsp) {
+       if (gettimeofday(&tv_now, 0) < 0)
+               return -1;
+       dir.atime = tv_now.tv_sec;
+       dir.mtime = tv_now.tv_sec;
+       wstat_flags = WSTAT_ATIME | WSTAT_MTIME;
+  } else {
+       /* atime */
+    if (tsp[0].tv_nsec == UTIME_NOW) {
+               if (gettimeofday(&tv_now, 0) < 0)
+                       return -1;
+               dir.atime = tv_now.tv_sec;
+               wstat_flags |= WSTAT_ATIME;
+       } else if (tsp[0].tv_nsec != UTIME_OMIT) {
+               dir.atime = tsp[0].tv_sec;
+               wstat_flags |= WSTAT_ATIME;
+       }
+       /* mtime */
+    if (tsp[1].tv_nsec == UTIME_NOW) {
+               if (gettimeofday(&tv_now, 0) < 0)
+                       return -1;
+               dir.mtime = tv_now.tv_sec;
+               wstat_flags |= WSTAT_MTIME;
+       } else if (tsp[1].tv_nsec != UTIME_OMIT) {
+               dir.mtime = tsp[1].tv_sec;
+               wstat_flags |= WSTAT_MTIME;
+       }
+  }
+
+  if (!wstat_flags)
+       return 0;
+
+  mlen = convD2M(&dir, mbuf, STATFIXLEN);
+  ret = ros_syscall(SYS_fwstat, fd, mbuf, mlen, wstat_flags, 0, 0);
+  return (ret == mlen ? 0 : -1);
+}
diff --git a/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/futimes.c b/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/futimes.c
new file mode 100644 (file)
index 0000000..f48ff25
--- /dev/null
@@ -0,0 +1,39 @@
+/* futimes -- change access and modification times of open file.  Stub version.
+   Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sys/time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/* Change the access time of FILE to TVP[0] and
+   the modification time of FILE to TVP[1], but do not follow symlinks.  */
+int
+__futimes (int fd, const struct timeval tvp[2])
+{
+  struct timespec tsp[2];
+  if (!tvp)
+       return futimens(fd, 0);
+  tsp[0].tv_sec = tvp[0].tv_sec;
+  tsp[0].tv_nsec = 0;
+  tsp[1].tv_sec = tvp[1].tv_sec;
+  tsp[1].tv_nsec = 0;
+  return futimens(fd, tsp);
+}
+weak_alias (__futimes, futimes)
diff --git a/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/futimesat.c b/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/futimesat.c
new file mode 100644 (file)
index 0000000..235fafa
--- /dev/null
@@ -0,0 +1,41 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+/* Change the access time of FILE relative to FD to TVP[0] and
+   the modification time of FILE to TVP[1].  */
+int
+futimesat (fd, file, tvp)
+     int fd;
+     const char *file;
+     const struct timeval tvp[2];
+{
+  struct timespec tsp[2];
+  if (!tvp)
+       return utimensat(fd, file, 0, 0);
+  tsp[0].tv_sec = tvp[0].tv_sec;
+  tsp[0].tv_nsec = 0;
+  tsp[1].tv_sec = tvp[1].tv_sec;
+  tsp[1].tv_nsec = 0;
+  return utimensat(fd, file, tsp, 0);
+}
index b7d8392..c7e8b35 100644 (file)
@@ -31,11 +31,5 @@ rename (old, new)
       __set_errno (EINVAL);
       return -1;
     }
-
-  __set_errno (ENOSYS);
-  return -1;
+  return ros_syscall(SYS_rename, old, strlen(old), new, strlen(new), 0, 0);
 }
-
-
-stub_warning (rename)
-#include <stub-tag.h>
index 9f8b2c5..d8b9d83 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1995, 1996, 1997, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
 #include <sys/types.h>
 #include <errno.h>
 #include <unistd.h>
-#include <fcntl.h>
 
 /* Truncate PATH to LENGTH bytes.  */
 int
-__truncate (const char* path, off_t length)
+__truncate (path, length)
+     const char *path;
+     off_t length;
 {
-  int fd, ret, save;
-
-  fd = open (path, O_WRONLY);
-  if (fd < 0)
-    return -1;
-
-  ret = ftruncate (fd, length);
-  save = errno;
-  (void) close (fd);
-  if (ret < 0)
-    __set_errno (save);
-  return ret;
+  return truncate64(path, length);
 }
-weak_alias(__truncate,truncate)
+weak_alias (__truncate, truncate)
diff --git a/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/truncate64.c b/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/truncate64.c
new file mode 100644 (file)
index 0000000..dbd37bc
--- /dev/null
@@ -0,0 +1,46 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcall.h>
+
+/* Truncate PATH to LENGTH bytes.  */
+int
+truncate64 (path, length)
+     const char *path;
+     off64_t length;
+{
+  struct dir dir;
+  size_t mlen;
+  char mbuf[STATFIXLEN];
+  int ret;
+
+  if (path == NULL)
+  {
+    __set_errno (EINVAL);
+    return -1;
+  }
+
+  init_empty_dir(&dir);
+  dir.length = length;
+  mlen = convD2M(&dir, mbuf, STATFIXLEN);
+  ret = ros_syscall(SYS_wstat, path, strlen(path), mbuf, mlen, WSTAT_LENGTH, 0);
+  return (ret == mlen ? 0 : -1);
+}
diff --git a/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/utime.c b/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/utime.c
new file mode 100644 (file)
index 0000000..f708e2e
--- /dev/null
@@ -0,0 +1,41 @@
+/* Copyright (C) 1991,95,96,97,2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <stddef.h>
+#include <utime.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* Set the access and modification times of FILE to those given in TIMES.
+   If TIMES is NULL, set them to the current time.  */
+int
+utime (file, times)
+     const char *file;
+     const struct utimbuf *times;
+{
+  struct timespec tsp[2];
+  if (!times)
+       return utimensat(AT_FDCWD, file, 0, 0);
+  tsp[0].tv_sec = times->actime;
+  tsp[0].tv_nsec = 0;
+  tsp[1].tv_sec = times->modtime;
+  tsp[1].tv_nsec = 0;
+  return utimensat(AT_FDCWD, file, tsp, 0);
+}
+libc_hidden_def (utime)
diff --git a/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/utimensat.c b/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/utimensat.c
new file mode 100644 (file)
index 0000000..a685417
--- /dev/null
@@ -0,0 +1,94 @@
+/* Change access and modification times of open file.  Stub version.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcall.h>
+#include <sys/time.h>
+#include <ros/syscall.h>
+#include <fcntl.h>
+
+/* Change the access time of FILE to TSP[0] and
+   the modification time of FILE to TSP[1].  */
+
+/* check futimens for notes.  additionally, we don't support the symlink flags
+ * yet. */
+int
+utimensat (int fd, const char *file, const struct timespec tsp[2],
+          int flags)
+{
+  struct dir dir;
+  size_t mlen;
+  char mbuf[STATFIXLEN];
+  int ret;
+  int wstat_flags = 0;
+  struct timeval tv_now = {0};
+
+  if (file == NULL)
+  {
+    __set_errno (EINVAL);
+    return -1;
+  }
+  /* don't support the openat yet */
+  if (fd != AT_FDCWD && file[0] != '/')
+    {
+      __set_errno (EBADF);
+      return -1;
+    }
+
+
+  init_empty_dir(&dir);
+
+  /* copy-and-pasted with futimens */
+  if (!tsp) {
+       if (gettimeofday(&tv_now, 0) < 0)
+               return -1;
+       dir.atime = tv_now.tv_sec;
+       dir.mtime = tv_now.tv_sec;
+       wstat_flags = WSTAT_ATIME | WSTAT_MTIME;
+  } else {
+       /* atime */
+    if (tsp[0].tv_nsec == UTIME_NOW) {
+               if (gettimeofday(&tv_now, 0) < 0)
+                       return -1;
+               dir.atime = tv_now.tv_sec;
+               wstat_flags |= WSTAT_ATIME;
+       } else if (tsp[0].tv_nsec != UTIME_OMIT) {
+               dir.atime = tsp[0].tv_sec;
+               wstat_flags |= WSTAT_ATIME;
+       }
+       /* mtime */
+    if (tsp[1].tv_nsec == UTIME_NOW) {
+               if (gettimeofday(&tv_now, 0) < 0)
+                       return -1;
+               dir.mtime = tv_now.tv_sec;
+               wstat_flags |= WSTAT_MTIME;
+       } else if (tsp[1].tv_nsec != UTIME_OMIT) {
+               dir.mtime = tsp[1].tv_sec;
+               wstat_flags |= WSTAT_MTIME;
+       }
+  }
+
+  if (!wstat_flags)
+       return 0;
+
+  mlen = convD2M(&dir, mbuf, STATFIXLEN);
+  ret = ros_syscall(SYS_wstat, file, strlen(file), mbuf, mlen, wstat_flags, 0);
+  return (ret == mlen ? 0 : -1);
+}
diff --git a/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/utimes.c b/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/utimes.c
new file mode 100644 (file)
index 0000000..c9c650e
--- /dev/null
@@ -0,0 +1,41 @@
+/* Copyright (C) 1991,95,96,97,2000,02 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sys/time.h>
+#include <errno.h>
+#include <stddef.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* Change the access time of FILE to TVP[0] and
+   the modification time of FILE to TVP[1].  */
+int
+__utimes (file, tvp)
+     const char *file;
+     const struct timeval tvp[2];
+{
+  struct timespec tsp[2];
+  if (!tvp)
+       return utimensat(AT_FDCWD, file, 0, 0);
+  tsp[0].tv_sec = tvp[0].tv_sec;
+  tsp[0].tv_nsec = 0;
+  tsp[1].tv_sec = tvp[1].tv_sec;
+  tsp[1].tv_nsec = 0;
+  return utimensat(AT_FDCWD, file, tsp, 0);
+}
+weak_alias (__utimes, utimes)