summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sys/stat.h1
-rw-r--r--libc/sysdeps/linux/common/futimens.c23
-rw-r--r--libc/sysdeps/linux/common/utimensat.c2
-rw-r--r--test/.gitignore2
-rw-r--r--test/time/tst-futimens1.c90
5 files changed, 118 insertions, 0 deletions
diff --git a/include/sys/stat.h b/include/sys/stat.h
index d84ace5a2..170a4e633 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -375,6 +375,7 @@ extern int utimensat (int __fd, __const char *__path,
__const struct timespec __times[2],
int __flags)
__THROW __nonnull ((2));
+libc_hidden_proto(utimensat)
#endif
#ifdef __USE_XOPEN2K8
diff --git a/libc/sysdeps/linux/common/futimens.c b/libc/sysdeps/linux/common/futimens.c
new file mode 100644
index 000000000..090dfa69c
--- /dev/null
+++ b/libc/sysdeps/linux/common/futimens.c
@@ -0,0 +1,23 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * futimens() implementation for uClibc
+ *
+ * Copyright (C) 2009 Bernhard Reutner-Fischer <uclibc@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <sys/syscall.h>
+#define __need_timespec
+#include <time.h>
+#ifdef __NR_utimensat
+extern int utimensat (int __fd, __const char *__path,
+ __const struct timespec __times[2],
+ int __flags) __THROW;
+libc_hidden_proto(utimensat)
+
+int futimens (int fd, __const struct timespec ts[2])
+{
+ return utimensat(fd, 0, ts, 0);
+}
+#endif
diff --git a/libc/sysdeps/linux/common/utimensat.c b/libc/sysdeps/linux/common/utimensat.c
index 3c5af8586..2cfb8247d 100644
--- a/libc/sysdeps/linux/common/utimensat.c
+++ b/libc/sysdeps/linux/common/utimensat.c
@@ -11,6 +11,8 @@
#ifdef __NR_utimensat
_syscall4(int, utimensat, int, fd, const char *, path, const struct timespec *, times, int, flags)
+libc_hidden_def(utimensat)
#else
/* should add emulation with utimens() and /proc/self/fd/ ... */
#endif
+
diff --git a/test/.gitignore b/test/.gitignore
index d438af7d0..1e7cd584e 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -237,6 +237,8 @@ string/tst-strxfrm
termios/termios
time/clocktest
time/test_time
+time/tst-ftime_l
+time/tst-futimens1
time/tst-mktime
time/tst-mktime3
time/tst-strptime2
diff --git a/test/time/tst-futimens1.c b/test/time/tst-futimens1.c
new file mode 100644
index 000000000..a452de2c7
--- /dev/null
+++ b/test/time/tst-futimens1.c
@@ -0,0 +1,90 @@
+/* vi: set sw=4 ts=4: */
+/* testcase
+ * Copyright (C) 2009 Bernhard Reutner-Fischer <uClibc@uClibc.org>
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+struct
+{
+ char *name; /* name of file to open */
+ int flags; /* flags for file descriptor */
+ const struct timespec ts[2];
+ int err; /* expected errno */
+} tests [] =
+{
+ {"futimens.tst", (O_CREAT|O_TRUNC), {{0,0},{0,0}}, 0},
+ {"futimens.tst", (O_CREAT|O_TRUNC), {{99,0},{0,0}}, 0},
+ {"futimens.tst", (O_CREAT|O_TRUNC), {{0,99},{0,0}}, 0},
+ {"futimens.tst", (O_CREAT|O_TRUNC), {{0,0},{99,0}}, 0},
+ {"futimens.tst", (O_CREAT|O_TRUNC), {{0,0},{0,99}}, 0},
+ {"futimens.tst", (O_CREAT|O_TRUNC), {{11,2},{3,4}}, 0},
+};
+int do_test(int argc, char **argv) {
+ char *name;
+ int i, errors;
+ errors = argc - argc + 0;
+
+ for (i=0; i < (int) (sizeof(tests)/sizeof(tests[0])); ++i) {
+ int err, fd;
+ struct stat sb;
+ name = tests[i].name;
+ if (*name != '.')
+ unlink(name);
+ fd = open(name, tests[i].flags);
+ if (fd < 0)
+ abort();
+ errno = 0;
+ err = futimens(fd, tests[i].ts);
+ if ((errno && !err) || (!errno && err)) {
+ err = errno;
+ printf("%s: FAILED test %d (errno and return value disagree)\n",
+ argv[0], i);
+ ++errors;
+ } else
+ err = errno;
+ if (err != tests[i].err) {
+ printf("%s: FAILED test %d (expected errno %d, got %d)\n",
+ argv[0], i, tests[i].err, err);
+ ++errors;
+ continue;
+ }
+ if (stat(name, &sb) < 0) {
+ printf("%s: FAILED test %d (verification)\n", argv[0], i);
+ ++errors;
+ continue;
+ } else {
+ unsigned wrong = tests[i].ts[0].tv_sec != sb.st_atim.tv_sec ||
+ tests[i].ts[0].tv_nsec != sb.st_atim.tv_nsec ||
+ tests[i].ts[1].tv_sec != sb.st_mtim.tv_sec ||
+ tests[i].ts[1].tv_nsec != sb.st_mtim.tv_nsec;
+ if (wrong) {
+ ++errors;
+ if (tests[i].ts[0].tv_sec != sb.st_atim.tv_sec)
+ printf("%s: FAILED test %d (access time, sec: expected %ld, got %ld)\n",
+ argv[0], i, tests[i].ts[0].tv_sec, sb.st_atim.tv_sec);
+ if (tests[i].ts[0].tv_nsec != sb.st_atim.tv_nsec)
+ printf("%s: FAILED test %d (access time, nsec: expected %ld, got %ld)\n",
+ argv[0], i, tests[i].ts[0].tv_nsec, sb.st_atim.tv_nsec);
+
+ if (tests[i].ts[1].tv_sec != sb.st_mtim.tv_sec)
+ printf("%s: FAILED test %d (modification time, sec: expected %ld, got %ld)\n",
+ argv[0], i, tests[i].ts[1].tv_sec, sb.st_mtim.tv_sec);
+ if (tests[i].ts[1].tv_nsec != sb.st_mtim.tv_nsec)
+ printf("%s: FAILED test %d (modification time, nsec: expected %ld, got %ld)\n",
+ argv[0], i, tests[i].ts[1].tv_nsec, sb.st_mtim.tv_nsec);
+ }
+ }
+ }
+ if (*name != '.')
+ unlink(name);
+ printf("%d errors.\n", errors);
+ return (!errors) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+#include <test-skeleton.c>