1212#include <stdlib.h>
1313#include <string.h>
1414#include <unistd.h>
15+ #include <time.h>
1516#include <sys/stat.h>
1617
1718
@@ -31,6 +32,23 @@ void setup() {
3132 symlink ("file" , "folder/file-link" );
3233}
3334
35+ void check_times (int fd , struct timespec * expected , int tolerance ) {
36+ struct stat s ;
37+ int rtn = fstatat (fd , "" , & s , AT_EMPTY_PATH );
38+ assert (rtn == 0 );
39+ printf ("atime: tv_sec=%lld tv_nsec=%ld\n" , s .st_atim .tv_sec , s .st_atim .tv_nsec );
40+ printf ("mtime: tv_sec=%lld tv_nsec=%ld\n" , s .st_mtim .tv_sec , s .st_mtim .tv_nsec );
41+ printf ("expected atime: tv_sec=%lld tv_nsec=%ld\n" , expected [0 ].tv_sec , expected [0 ].tv_nsec );
42+ printf ("expected mtime: tv_sec=%lld tv_nsec=%ld\n" , expected [1 ].tv_sec , expected [1 ].tv_nsec );
43+ if (tolerance ) {
44+ assert (llabs (expected [0 ].tv_sec - s .st_atim .tv_sec ) <= tolerance );
45+ assert (llabs (expected [1 ].tv_sec - s .st_mtim .tv_sec ) <= tolerance );
46+ } else {
47+ assert (expected [0 ].tv_sec == s .st_atim .tv_sec );
48+ assert (expected [1 ].tv_sec == s .st_mtim .tv_sec );
49+ }
50+ }
51+
3452void test () {
3553 int err ;
3654 struct stat s ;
@@ -49,18 +67,72 @@ void test() {
4967 assert (s .st_rdev == 0 );
5068 assert (s .st_size == 8 );
5169 assert (s .st_ctime );
52- #ifdef __EMSCRIPTEN__
70+ #if defined( __EMSCRIPTEN__ ) && !defined( NODERAWFS )
5371 assert (s .st_blksize == 4096 );
5472 assert (s .st_blocks == 1 );
5573#endif
5674
57- struct timespec origTimes [2 ];
58- origTimes [0 ].tv_sec = (time_t )s .st_atime ;
59- origTimes [0 ].tv_nsec = origTimes [0 ].tv_sec * 1000 ;
60- origTimes [1 ].tv_sec = (time_t )s .st_mtime ;
61- origTimes [1 ].tv_nsec = origTimes [1 ].tv_sec * 1000 ;
62- err = futimens (fd , origTimes );
75+ struct timespec times [2 ];
76+ times [0 ].tv_sec = s .st_atim .tv_sec ;
77+ times [0 ].tv_nsec = s .st_atim .tv_nsec ;
78+ times [1 ].tv_sec = s .st_mtim .tv_sec ;
79+ times [1 ].tv_nsec = s .st_mtim .tv_nsec ;
80+
81+ // set the timestampe to the current value
82+ err = futimens (fd , times );
83+ assert (!err );
84+ check_times (fd , times , 0 );
85+
86+ // UTIME_OMIT means that the timeval is ignored, so
87+ // this call should do nothing.
88+ printf ("check double UTIME_OMIT...\n" );
89+ struct timespec newtimes [2 ];
90+ newtimes [0 ].tv_sec = 42 ;
91+ newtimes [0 ].tv_nsec = UTIME_OMIT ;
92+ newtimes [1 ].tv_sec = 42 ;
93+ newtimes [1 ].tv_nsec = UTIME_OMIT ;
94+ err = futimens (fd , newtimes );
95+ assert (!err );
96+ check_times (fd , times , 0 );
97+
98+ // Setting just one of the two times to UTIME_OMIT means
99+ // the other should be honored.
100+ printf ("check single UTIME_OMIT...\n" );
101+ newtimes [0 ].tv_sec = 41 ;
102+ newtimes [0 ].tv_nsec = UTIME_OMIT ;
103+ newtimes [1 ].tv_sec = 42 ;
104+ newtimes [1 ].tv_nsec = 88 ;
105+ err = futimens (fd , newtimes );
106+ assert (!err );
107+
108+ #if defined(__EMSCRIPTEN__ ) && !defined(WASMFS ) && !defined(NODERAWFS )
109+ // The original emscripten FS (in JS) only supports a single timestamp so both
110+ // mtime and atime will always be the same.
111+ times [0 ].tv_sec = 42 ;
112+ times [0 ].tv_nsec = 88 ;
113+ #endif
114+ times [1 ].tv_sec = 42 ;
115+ times [1 ].tv_nsec = 88 ;
116+ check_times (fd , times , 0 );
117+
118+ // UTIME_NOW means use the current date and ignore the seconds value
119+ printf ("check single UTIME_NOW...\n" );
120+ newtimes [0 ].tv_sec = 99 ;
121+ newtimes [0 ].tv_nsec = UTIME_NOW ;
122+ newtimes [1 ].tv_sec = 99 ;
123+ newtimes [1 ].tv_nsec = UTIME_NOW ;
124+ err = futimens (fd , newtimes );
125+ assert (!err );
126+
127+ struct timespec now ;
128+ err = clock_gettime (CLOCK_REALTIME , & now );
129+ printf ("now: %lld %ld\n" , now .tv_sec , now .tv_nsec );
63130 assert (!err );
131+ times [0 ].tv_sec = now .tv_sec ;
132+ times [0 ].tv_nsec = now .tv_nsec ;
133+ times [1 ].tv_sec = now .tv_sec ;
134+ times [1 ].tv_nsec = now .tv_nsec ;
135+ check_times (fd , times , 1 );
64136
65137 close (fd );
66138
0 commit comments