<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, May 18, 2021 at 3:03 PM Ryan Long <<a href="mailto:ryan.long@oarcorp.com">ryan.long@oarcorp.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Improved tests for utime() and utimes() and update license.<br>
<br>
Close #4399<br>
---<br>
 testsuites/psxtests/psx13/main.c |   5 +-<br>
 testsuites/psxtests/psx13/test.c | 499 +++++++++++++++++++++++++++++++++++++--<br>
 2 files changed, 481 insertions(+), 23 deletions(-)<br>
<br>
diff --git a/testsuites/psxtests/psx13/main.c b/testsuites/psxtests/psx13/main.c<br>
index f9e7907..7a560f9 100644<br>
--- a/testsuites/psxtests/psx13/main.c<br>
+++ b/testsuites/psxtests/psx13/main.c<br>
@@ -1,5 +1,3 @@<br>
-/*  SPDX-License-Identifier: BSD-2-Clause */<br>
-<br></blockquote><div><br></div><div>Agree with Gedare. This shouldn't have been removed.</div><div><br></div><div>There were some dates changed in the copyrights. </div><div><br></div><div>Check all of the issues against all of the patches. </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
 /**<br>
  *  @file<br>
  *<br>
@@ -8,8 +6,7 @@<br>
  */<br>
<br>
 /*<br>
- *  COPYRIGHT (c) 1989-2009, 2021.<br>
- *  On-Line Applications Research Corporation (OAR).<br>
+ * COPYRIGHT (C) 1989, 2021 On-Line Applications Research Corporation (OAR).<br></blockquote><div><br></div><div>This changes the years which is wrong.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
  *<br>
  * Redistribution and use in source and binary forms, with or without<br>
  * modification, are permitted provided that the following conditions<br>
diff --git a/testsuites/psxtests/psx13/test.c b/testsuites/psxtests/psx13/test.c<br>
index e98b03a..0754dbc 100644<br>
--- a/testsuites/psxtests/psx13/test.c<br>
+++ b/testsuites/psxtests/psx13/test.c<br>
@@ -1,4 +1,4 @@<br>
-/*  SPDX-License-Identifier: BSD-2-Clause */<br>
+/* SPDX-License-Identifier: BSD-2-Clause */<br>
<br>
 /**<br>
  *  @file<br>
@@ -17,12 +17,13 @@<br>
  *     - umask()<br>
  *     - utime()<br>
  *     - utimes()<br>
+ *     - utimensat()<br>
+ *     - futimens()<br>
  *     - sync()<br>
  */<br>
<br>
 /*<br>
- *  COPYRIGHT (c) 1989-2009, 2021.<br>
- *  On-Line Applications Research Corporation (OAR).<br>
+ * COPYRIGHT (C) 1989, 2021 On-Line Applications Research Corporation (OAR).<br></blockquote><div><br></div><div>Again a year change. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
  *<br>
  * Redistribution and use in source and binary forms, with or without<br>
  * modification, are permitted provided that the following conditions<br>
@@ -52,6 +53,8 @@<br>
<br>
 #include <rtems.h><br>
 #include <rtems/libio.h><br>
+#include <rtems/score/timespec.h><br>
+#include <rtems/score/todimpl.h><br>
 #include <sys/time.h><br>
 #include <fcntl.h><br>
 #include <unistd.h><br>
@@ -210,8 +213,7 @@ static void Dup2Test( void )<br>
 }<br>
<br>
 /**<br>
- * @brief Exercises fdatasync(). Does NOT test the functionality of the<br>
- *        underlying fdatasync entry in the IMFS op table.<br>
+ * @brief Exercises fdatasync().<br>
  */<br>
 static void FDataSyncTest( void )<br>
 {<br>
@@ -259,60 +261,517 @@ static void UMaskTest( void )<br>
 }<br>
<br>
 /**<br>
- * @brief Exercises utime(). Does not test the functionality of the<br>
- *        underlying utime entry in the IMFS op table.<br>
+ * @brief Exercises utime().<br>
  */<br>
 static void UTimeTest( void )<br>
 {<br>
   int rv;<br>
   struct utimbuf time;<br>
+  struct timespec current_time;<br>
   struct stat fstat;<br>
<br>
-  /* First, an invalid filename. */<br>
+  /* ENOENT test case */<br>
+<br>
+  /* Case: Pass an invalid filename. */<br>
   rv = utime( "!This is an =invalid p@thname!!! :)", NULL );<br>
   rtems_test_assert( rv == -1 );<br>
   rtems_test_assert( errno == ENOENT );<br>
<br>
-  /* Now, the success test. */<br>
+  /* EACCES test case */<br>
+<br>
+  /* Case: Change user ID to someone besides root */<br>
+  rv = seteuid( 1 );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  rv = utime( "testfile1.tst", NULL );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EACCES );<br>
+<br>
+  rv = seteuid( 0 );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  /* EINVAL test cases */<br>
+<br>
+  /* Case: Invalid access time */<br>
+  time.actime  = -1;<br>
+  time.modtime = 54321;<br>
+<br>
+  rv = utime( "testfile1.tst", &time );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Case: Invalid modified time */<br>
+  time.actime  = 12345;<br>
+  time.modtime = -1;<br>
+<br>
+  rv = utime( "testfile1.tst", &time );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Successful test cases */<br>
+<br>
+  /* Case: Test without times argument */<br>
+  clock_gettime( CLOCK_REALTIME, &current_time );<br>
+<br>
+  rv = utime( "testfile1.tst", NULL );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  rv = stat( "testfile1.tst", &fstat );<br>
+  rtems_test_assert( rv == 0 );<br>
+  rtems_test_assert( current_time.tv_sec <= fstat.st_atim.tv_sec );<br>
+  rtems_test_assert( current_time.tv_sec <= fstat.st_mtim.tv_sec );<br>
+<br>
+  /* Case: time is filled with valid values */<br>
   time.actime  = 12345;<br>
   time.modtime = 54321;<br>
<br>
   rv = utime( "testfile1.tst", &time );<br>
   rtems_test_assert( rv == 0 );<br>
<br>
-  /* But, did it set the time? */<br>
+  /* Check that it actually changed the time */<br>
   rv = stat( "testfile1.tst", &fstat );<br>
   rtems_test_assert( rv == 0 );<br>
   rtems_test_assert( fstat.st_atime == 12345 );<br>
   rtems_test_assert( fstat.st_mtime == 54321 );<br>
-<br>
-  rv = utime( "testfile1.tst", NULL );<br>
-  rtems_test_assert( rv == 0 );<br>
 }<br>
<br>
 /**<br>
- * @brief Exercises utimes(). Does NOT test the functionality of the<br>
- *        underlying utime entry in the IMFS op table.<br>
+ * @brief Exercises utimes().<br>
  */<br>
 static void UTimesTest( void )<br>
 {<br>
   int rv;<br>
   struct timeval time[2];<br>
+  struct timespec current_time;<br>
   struct stat fstat;<br>
<br>
-  /* First, an invalid filename. */<br>
+  /* ENOENT test case */<br>
+<br>
+  /* Case: First, an invalid filename. */<br>
   rv = utimes( "!This is an =invalid p@thname!!! : )", NULL);<br>
   rtems_test_assert( rv == -1 );<br>
   rtems_test_assert( errno == ENOENT );<br>
<br>
-  /* Now, the success test. */<br>
+  /* EACCES test case */<br>
+<br>
+  /* Change the user ID of the process to someone besides root */<br>
+  rv = seteuid( 1 );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  rv = utimes( "testfile1.tst", NULL );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EACCES );<br>
+<br>
+  rv = seteuid( 0 );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  /* EINVAL test cases */<br>
+<br>
+  /* Case: Negative access time tv_sec value */<br>
+  time[0].tv_sec = -1;<br>
+  time[0].tv_usec = 12345;<br>
+  time[1].tv_sec = 54321;<br>
+  time[1].tv_usec = 54321;<br>
+<br>
+  rv = utimes( "testfile1.tst", time );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Case: Negative modified time second value */<br>
   time[0].tv_sec = 12345;<br>
+  time[1].tv_sec = -1;<br>
+<br>
+  rv = utimes( "testfile1.tst", time );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Case: Negative access time microsecond value */<br>
   time[1].tv_sec = 54321;<br>
+  time[0].tv_usec = -1;<br>
+<br>
+  rv = utimes( "testfile1.tst", time );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Case: Negative modified time microsecond value */<br>
+  time[0].tv_usec = 12345;<br>
+  time[1].tv_usec = -1;<br>
+<br>
+  rv = utimes( "testfile1.tst", time );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Case: Access time microsecond value too large */<br>
+  time[0].tv_usec = 1000000;<br>
+  time[1].tv_usec = 54321;<br>
+<br>
+  rv = utimes( "testfile1.tst", time );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Case: Modified time microsecond value too large */<br>
+  time[1].tv_usec = 1000000;<br>
+  time[0].tv_usec = 12345;<br>
+<br>
+  rv = utimes( "testfile1.tst", time );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Successful test cases */<br>
+<br>
+  /* Case: Test without times argument */<br>
+  clock_gettime( CLOCK_REALTIME, &current_time );<br>
+<br>
+  rv = utimes( "testfile1.tst", NULL );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  rv = stat( "testfile1.tst", &fstat );<br>
+  rtems_test_assert( rv == 0 );<br>
+  rtems_test_assert( current_time.tv_sec <= fstat.st_atim.tv_sec );<br>
+  rtems_test_assert( current_time.tv_sec <= fstat.st_mtim.tv_sec );<br>
+<br>
+  /* Case: time is filled with valid values */<br>
+  time[0].tv_sec = 12345;<br>
+  time[0].tv_usec = 12345;<br>
+  time[1].tv_sec = 54321;<br>
+  time[1].tv_usec = 54321;<br>
+<br>
+  rv = utimes( "testfile1.tst", time );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  /* Check that it actually changed the time */<br>
+  rv = stat( "testfile1.tst", &fstat );<br>
+  rtems_test_assert( rv == 0 );<br>
+  rtems_test_assert( fstat.st_atime == 12345 );<br>
+  rtems_test_assert( fstat.st_mtime == 54321 );<br>
+}<br>
+<br>
+/**<br>
+ * @brief Exercises utimensat().<br>
+ */<br>
+static void UTimensatTest( void )<br>
+{<br>
+  int rv;<br>
+  struct timespec time[2];<br>
+  struct timespec current_time;<br>
+  struct stat fstat;<br>
+<br>
+  /* ENOSYS test cases */<br>
+<br>
+  /* Case: Pass an unsupported file descriptor */<br>
+  rv = utimensat(<br>
+    0,<br>
+    "!This is an =invalid p@thname!!! : )",<br>
+    NULL,<br>
+    0<br>
+  );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == ENOSYS );<br>
+<br>
+  /* Case: Pass unsupported flag */<br>
+  rv = utimensat(<br>
+    AT_FDCWD,<br>
+    "!This is an =invalid p@thname!!! : )",<br>
+    NULL,<br>
+    1<br>
+  );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == ENOSYS );<br>
+<br>
+  /* ENOENT test case */<br>
+<br>
+  /* Use an invalid filename. */<br>
+  rv = utimensat(<br>
+    AT_FDCWD,<br>
+    "!This is an =invalid p@thname!!! : )",<br>
+    NULL,<br>
+    0<br>
+  );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == ENOENT );<br>
+<br>
+  rv = stat( "testfile1.tst", &fstat );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  /* EACCES test Cases */<br>
+<br>
+  /* Case: When times is NULL and the user has insufficient privileges */<br>
+<br>
+  /* Change the user ID of the process to someone besides root */<br>
+  rv = seteuid( 1 );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  rv = utimensat( AT_FDCWD, "testfile1.tst", NULL, 0 );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EACCES );<br>
+<br>
+  rv = seteuid( 0 );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  /* Case: File is read-only and time's tv_nsec members are UTIME_NOW */<br>
+<br>
+  /* Change file to be read-only */<br>
+  rv = chmod( "testfile1.tst", 06444 );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  _Timespec_Set( &time[0], 0, UTIME_NOW );<br>
+  _Timespec_Set( &time[1], 0, UTIME_NOW );<br>
+<br>
+  rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EACCES );<br>
+<br>
+  rv = chmod( "testfile1.tst", fstat.st_mode );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  /* EINVAL test cases */<br>
+<br>
+  /* Case: Negative access time second value */<br>
+  _Timespec_Set( &time[0], -12345, 12345 );<br>
+  _Timespec_Set( &time[1], 54321, 54321 );<br>
+<br>
+  rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Case: Negative modified time second value */<br>
+  _Timespec_Set( &time[0], 12345, 12345 );<br>
+  _Timespec_Set( &time[1], -54321, 54321 );<br>
+<br>
+  rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Case: Negative access time nanosecond value */<br>
+  _Timespec_Set( &time[0], 12345, -12345 );<br>
+  _Timespec_Set( &time[1], 54321, 54321 );<br>
+<br>
+  rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Case: Negative modified time nanosecond value */<br>
+  _Timespec_Set( &time[0], 12345, 12345 );<br>
+  _Timespec_Set( &time[1], 54321, -54321 );<br>
+<br>
+  rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Case: Access time nanosecond value too large */<br>
+  _Timespec_Set( &time[0], 12345, TOD_NANOSECONDS_PER_SECOND );<br>
+  _Timespec_Set( &time[1], 54321, 54321 );<br>
+<br>
+  rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Case: Modified time nanosecond value too large */<br>
+  _Timespec_Set( &time[0], 12345, 12345 );<br>
+  _Timespec_Set( &time[1], 54321, TOD_NANOSECONDS_PER_SECOND );<br>
+<br>
+  rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Successful test cases */<br>
+<br>
+  /* Case: Test without times argument */<br>
+  clock_gettime( CLOCK_REALTIME, &current_time );<br>
+<br>
+  rv = utimensat( AT_FDCWD, "testfile1.tst", NULL, 0 );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  rv = stat( "testfile1.tst", &fstat );<br>
+  rtems_test_assert( rv == 0 );<br>
+  rtems_test_assert( current_time.tv_sec <= fstat.st_atim.tv_sec );<br>
+  rtems_test_assert( current_time.tv_sec <= fstat.st_mtim.tv_sec );<br>
+<br>
+  /* Case: Running with access time nanosecond field equal to UTIME_NOW */<br>
+  _Timespec_Set( &time[0], 12345, UTIME_NOW );<br>
+  _Timespec_Set( &time[1], 54321, 54321 );<br>
+<br>
+  rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  rv = stat( "testfile1.tst", &fstat );<br>
+  rtems_test_assert( rv == 0 );<br>
+  rtems_test_assert( current_time.tv_sec <= fstat.st_atim.tv_sec );<br>
+  rtems_test_assert( fstat.st_mtime == 54321 );<br>
+<br>
+  /* Case: Running with modified time nanosecond field equal to UTIME_NOW */<br>
+  _Timespec_Set( &time[0], 12345, 12345 );<br>
+  _Timespec_Set( &time[1], 54321, UTIME_NOW );<br>
+<br>
+  rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  rv = stat( "testfile1.tst", &fstat );<br>
+  rtems_test_assert( rv == 0 );<br>
+  rtems_test_assert( fstat.st_atime == 12345 );<br>
+  rtems_test_assert( current_time.tv_sec <= fstat.st_mtim.tv_sec );<br>
+<br>
+  /* Case: Normal run */<br>
+  _Timespec_Set( &time[0], 12345, 12345 );<br>
+  _Timespec_Set( &time[1], 54321, 54321 );<br>
+<br>
+  rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  /* Check that it actually changed the time */<br>
+  rv = stat( "testfile1.tst", &fstat );<br>
+  rtems_test_assert( rv == 0 );<br>
+  rtems_test_assert( fstat.st_atime == 12345 );<br>
+  rtems_test_assert( fstat.st_mtime == 54321 );<br>
+}<br>
+<br>
+/**<br>
+ * @brief Exercises futimens().<br>
+ */<br>
+static void FutimensTest( void )<br>
+{<br>
+  int rv;<br>
+  int fd;<br>
+  struct timespec time[2];<br>
+  struct timespec current_time;<br>
+  struct stat fstat;<br>
+<br>
+  /* EBADF test case */<br>
+<br>
+  /* Case: Pass an invalid file descriptor */<br>
+  rv = futimens( -1, time );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EBADF );<br>
+<br>
+  fd = open( "testfile1.tst", O_RDWR );<br>
+  rtems_test_assert( fd != -1 );<br>
+<br>
+  /* EACCES test cases */<br>
+<br>
+  /* Case: When times is NULL and the user has insufficient privileges */<br>
+<br>
+  /* Change the user ID of the process to someone besides root */<br>
+  rv = seteuid( 1 );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  rv = futimens( fd, NULL );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EACCES );<br>
+<br>
+  rv = seteuid( 0 );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  /* Case: File is read-only and time's tv_nsec members are UTIME_NOW */<br>
+<br>
+  /* Change file to be read-only */<br>
+  rv = chmod( "testfile1.tst", 06444 );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  _Timespec_Set( &time[0], 0, UTIME_NOW );<br>
+  _Timespec_Set( &time[1], 0, UTIME_NOW );<br>
+<br>
+  rv = futimens( fd, time );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EACCES );<br>
+<br>
+  rv = chmod( "testfile1.tst", fstat.st_mode );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  /* EINVAL test cases */<br>
+<br>
+  /* Case: Negative access time second value */<br>
+  _Timespec_Set( &time[0], -12345, 12345 );<br>
+  _Timespec_Set( &time[1], 54321, 54321 );<br>
+<br>
+  rv = futimens( fd, time );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Case: Negative modified time second value */<br>
+  _Timespec_Set( &time[0], 12345, 12345 );<br>
+  _Timespec_Set( &time[1], -54321, 54321 );<br>
+<br>
+  rv = futimens( fd, time );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Case: Negative access time nanosecond value */<br>
+  _Timespec_Set( &time[0], 12345, -12345 );<br>
+  _Timespec_Set( &time[1], 54321, 54321 );<br>
+<br>
+  rv = futimens( fd, time );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Case: Negative modified time nanosecond value */<br>
+  _Timespec_Set( &time[0], 12345, 12345 );<br>
+  _Timespec_Set( &time[1], 54321, -54321 );<br>
+<br>
+  rv = futimens( fd, time );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Case: Access time nanosecond value too large */<br>
+  _Timespec_Set( &time[0], 12345, TOD_NANOSECONDS_PER_SECOND );<br>
+  _Timespec_Set( &time[1], 54321, 54321 );<br>
+<br>
+  rv = futimens( fd, time );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Case: Modified time nanosecond value too large */<br>
+  _Timespec_Set( &time[0], 12345, 12345 );<br>
+  _Timespec_Set( &time[1], 54321, TOD_NANOSECONDS_PER_SECOND );<br>
+<br>
+  rv = futimens( fd, time );<br>
+  rtems_test_assert( rv == -1 );<br>
+  rtems_test_assert( errno == EINVAL );<br>
+<br>
+  /* Successful test cases */<br>
+<br>
+  /* Case: Test without times argument */<br>
+  clock_gettime( CLOCK_REALTIME, &current_time );<br>
+<br>
+  rv = futimens( fd, NULL );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  rv = stat( "testfile1.tst", &fstat );<br>
+  rtems_test_assert( rv == 0 );<br>
+  rtems_test_assert( current_time.tv_sec <= fstat.st_atim.tv_sec );<br>
+  rtems_test_assert( current_time.tv_sec <= fstat.st_mtim.tv_sec );<br>
+<br>
+/* Case: Running with access time nanosecond field equal to UTIME_NOW */<br>
+  _Timespec_Set( &time[0], 12345, UTIME_NOW );<br>
+  _Timespec_Set( &time[1], 54321, 54321 );<br>
+<br>
+  rv = futimens( fd, time );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  rv = stat( "testfile1.tst", &fstat );<br>
+  rtems_test_assert( rv == 0 );<br>
+  rtems_test_assert( current_time.tv_sec <= fstat.st_atim.tv_sec );<br>
+  rtems_test_assert( fstat.st_mtime == 54321 );<br>
+<br>
+  /* Case: Running with modified time nanosecond field equal to UTIME_NOW */<br>
+  _Timespec_Set( &time[0], 12345, 12345 );<br>
+  _Timespec_Set( &time[1], 54321, UTIME_NOW );<br>
+<br>
+  rv = futimens( fd, time );<br>
+  rtems_test_assert( rv == 0 );<br>
+<br>
+  rv = stat( "testfile1.tst", &fstat );<br>
+  rtems_test_assert( rv == 0 );<br>
+  rtems_test_assert( fstat.st_atime == 12345 );<br>
+  rtems_test_assert( current_time.tv_sec <= fstat.st_mtim.tv_sec );<br>
+<br>
+  /* Case: Normal run */<br>
+  _Timespec_Set( &time[0], 12345, 12345 );<br>
+  _Timespec_Set( &time[1], 54321, 54321 );<br>
<br>
-  rv = utimes( "testfile1.tst", (struct timeval *)&time );<br>
+  rv = futimens( fd, time );<br>
   rtems_test_assert( rv == 0 );<br>
<br>
-  /* But, did it set the time? */<br>
+  /* Check that it actually changed the time */<br>
   rv = stat( "testfile1.tst", &fstat );<br>
   rtems_test_assert( rv == 0 );<br>
   rtems_test_assert( fstat.st_atime == 12345 );<br>
@@ -443,6 +902,8 @@ int test_main( void )<br>
   UMaskTest();<br>
   UTimeTest();<br>
   UTimesTest();<br>
+  UTimensatTest();<br>
+  FutimensTest();<br>
   FSyncTest();<br>
   PathConfTest();<br>
   FPathConfTest();<br>
-- <br>
1.8.3.1<br>
<br>
_______________________________________________<br>
devel mailing list<br>
<a href="mailto:devel@rtems.org" target="_blank">devel@rtems.org</a><br>
<a href="http://lists.rtems.org/mailman/listinfo/devel" rel="noreferrer" target="_blank">http://lists.rtems.org/mailman/listinfo/devel</a><br>
</blockquote></div></div>