safe_touch: use utimes(2) if utimensat(2) is not defined
If utimensat(2) is not defined on the platform we switch
to using utimes(2).
Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com>
diff --git a/lib/safe_file_ops.c b/lib/safe_file_ops.c
index 8cfd264..b5075c7 100644
--- a/lib/safe_file_ops.c
+++ b/lib/safe_file_ops.c
@@ -21,11 +21,15 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include "config.h"
#include <stdarg.h>
#include <stdio.h>
+#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <unistd.h>
+#include <utime.h>
#include "safe_file_ops.h"
@@ -156,6 +160,26 @@
}
}
+#ifndef HAVE_UTIMENSAT
+
+static void set_time(struct timeval *res, struct timespec *src,
+ long cur_tv_sec, long cur_tv_usec)
+{
+ switch (src->tv_nsec) {
+ case UTIME_NOW:
+ break;
+ case UTIME_OMIT:
+ res->tv_sec = cur_tv_sec;
+ res->tv_usec = cur_tv_usec;
+ break;
+ default:
+ res->tv_sec = src->tv_sec;
+ res->tv_usec = src->tv_nsec / 1000;
+ }
+}
+
+#endif
+
void safe_touch(const char *file, const int lineno,
void (*cleanup_fn)(void),
const char *pathname,
@@ -186,10 +210,40 @@
pathname, file, lineno);
}
- ret = utimensat(AT_FDCWD, pathname, times, 0);
- if (ret == -1)
- tst_brkm(TBROK | TERRNO, cleanup_fn,
- "Failed to do utimensat() on file '%s' at %s:%d",
- pathname, file, lineno);
-}
+#if HAVE_UTIMENSAT
+ ret = utimensat(AT_FDCWD, pathname, times, 0);
+#else
+ if (times == NULL) {
+ ret = utimes(pathname, NULL);
+ } else {
+ struct stat sb;
+ struct timeval cotimes[2];
+
+ ret = stat(pathname, &sb);
+ if (ret == -1)
+ tst_brkm(TBROK | TERRNO, cleanup_fn,
+ "Failed to stat file '%s' at %s:%d",
+ pathname, file, lineno);
+
+ ret = gettimeofday(cotimes, NULL);
+ if (ret == -1)
+ tst_brkm(TBROK | TERRNO, cleanup_fn,
+ "Failed to gettimeofday() at %s:%d",
+ file, lineno);
+ cotimes[1] = cotimes[0];
+
+ set_time(cotimes, times,
+ sb.st_atime, sb.st_atim.tv_nsec / 1000);
+ set_time(cotimes + 1, times + 1,
+ sb.st_mtime, sb.st_mtim.tv_nsec / 1000);
+
+ ret = utimes(pathname, cotimes);
+ }
+#endif
+ if (ret == -1) {
+ tst_brkm(TBROK | TERRNO, cleanup_fn,
+ "Failed to update the access/modification time on file"
+ " '%s' at %s:%d", pathname, file, lineno);
+ }
+}