@@ -156,6 +156,8 @@ LXT_VARIATION_HANDLER DrvFsTestFatWslPath;
156156
157157LXT_VARIATION_HANDLER DrvFsTestFstat ;
158158
159+ LXT_VARIATION_HANDLER DrvFsTestStatx ;
160+
159161LXT_VARIATION_HANDLER DrvFsTestGetDents64Alignment ;
160162
161163LXT_VARIATION_HANDLER DrvFsTestGetDentsAlignment ;
@@ -246,6 +248,7 @@ static const LXT_VARIATION g_LxtVariations[] = {
246248 {"DrvFs - hard links" , DrvFsTestHardLinks },
247249 {"DrvFs - block count" , DrvFsTestBlockCount },
248250 {"DrvFs - fstat" , DrvFsTestFstat },
251+ {"DrvFs - statx" , DrvFsTestStatx },
249252 {"DrvFs - reopen unlinked file" , DrvFsTestReopenUnlinked },
250253 {"DrvFs - delete loop" , DrvFsTestDeleteLoop },
251254 {"DrvFs - seek" , DrvFsTestSeek },
@@ -336,6 +339,7 @@ static const LXT_VARIATION g_LxtMetadataVariations[] = {
336339 {"DrvFs - hard links" , DrvFsTestHardLinks },
337340 {"DrvFs - block count" , DrvFsTestBlockCount },
338341 {"DrvFs - fstat" , DrvFsTestFstat },
342+ {"DrvFs - statx" , DrvFsTestStatx },
339343 {"DrvFs - reopen unlinked file" , DrvFsTestReopenUnlinked },
340344 {"DrvFs - delete loop" , DrvFsTestDeleteLoop },
341345 {"DrvFs - seek" , DrvFsTestSeek },
@@ -368,6 +372,7 @@ static const LXT_VARIATION g_LxtReFsVariations[] = {
368372 {"DrvFs - hard links" , DrvFsTestHardLinks },
369373 {"DrvFs - block count" , DrvFsTestBlockCount },
370374 {"DrvFs - fstat" , DrvFsTestFstat },
375+ {"DrvFs - statx" , DrvFsTestStatx },
371376 {"DrvFs - reopen unlinked file" , DrvFsTestReopenUnlinked },
372377 {"DrvFs - delete loop" , DrvFsTestDeleteLoop },
373378 {"DrvFs - seek" , DrvFsTestSeek },
@@ -1389,13 +1394,6 @@ Return Value:
13891394
13901395 int Result ;
13911396
1392- if (g_LxtFsInfo .FsType == LxtFsTypeVirtioFs )
1393- {
1394- LxtLogInfo ("TODO: debug this test on virtiofs." );
1395- Result = 0 ;
1396- goto ErrorExit ;
1397- }
1398-
13991397 LxtCheckErrno (LxtFsDeleteCurrentWorkingDirectoryCommon (DRVFS_PREFIX , FS_DELETE_DRVFS ));
14001398
14011399ErrorExit :
@@ -2027,6 +2025,180 @@ Return Value:
20272025 return Result ;
20282026}
20292027
2028+ int DrvFsTestStatx (PLXT_ARGS Args )
2029+
2030+ /*++
2031+
2032+ Description:
2033+
2034+ This routine tests the statx system call on drvfs files.
2035+
2036+ Arguments:
2037+
2038+ Args - Supplies the command line arguments.
2039+
2040+ Return Value:
2041+
2042+ Returns 0 on success, -1 on failure.
2043+
2044+ --*/
2045+
2046+ {
2047+
2048+ int Fd ;
2049+ int Result ;
2050+ struct stat Stat1 ;
2051+ struct statx Statx1 ;
2052+ struct statx Statx2 ;
2053+
2054+ Fd = -1 ;
2055+
2056+ if (g_LxtFsInfo .FsType == LxtFsTypeDrvFs )
2057+ {
2058+ LxtLogInfo ("statx is not supported on drvfs in WSL1." );
2059+ Result = 0 ;
2060+ goto ErrorExit ;
2061+ }
2062+
2063+ //
2064+ // Create a test file and symlink.
2065+ //
2066+
2067+ LxtCheckErrnoZeroSuccess (mkdir (DRVFS_BASIC_PREFIX , 0777 ));
2068+ LxtCheckErrno (Fd = creat (DRVFS_BASIC_PREFIX "/testfile" , 0666 ));
2069+ LxtCheckErrnoZeroSuccess (symlink (DRVFS_BASIC_PREFIX "/testfile" , DRVFS_BASIC_PREFIX "/testlink" ));
2070+
2071+ //
2072+ // Stat and statx should have consistent results.
2073+ //
2074+
2075+ LxtCheckErrnoZeroSuccess (stat (DRVFS_BASIC_PREFIX "/testfile" , & Stat1 ));
2076+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testfile" , 0 , STATX_BASIC_STATS , & Statx1 ));
2077+ LxtCheckEqual (Stat1 .st_ino , Statx1 .stx_ino , "%llu" );
2078+ LxtCheckEqual (Stat1 .st_size , Statx1 .stx_size , "%llu" );
2079+ LxtCheckEqual (Stat1 .st_mode , Statx1 .stx_mode , "0%o" );
2080+
2081+ //
2082+ // Statx with AT_EMPTY_PATH on an fd.
2083+ //
2084+
2085+ LxtCheckErrnoZeroSuccess (statx (Fd , "" , AT_EMPTY_PATH , STATX_BASIC_STATS , & Statx2 ));
2086+ LxtCheckEqual (Statx1 .stx_ino , Statx2 .stx_ino , "%llu" );
2087+
2088+ //
2089+ // Test AT_SYMLINK_NOFOLLOW flag.
2090+ //
2091+
2092+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testlink" , AT_SYMLINK_NOFOLLOW , STATX_BASIC_STATS , & Statx2 ));
2093+ LxtCheckTrue (S_ISLNK (Statx2 .stx_mode ));
2094+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testlink" , 0 , STATX_BASIC_STATS , & Statx2 ));
2095+ LxtCheckTrue (S_ISREG (Statx2 .stx_mode ));
2096+
2097+ //
2098+ // Test STATX_BTIME (birth/creation time).
2099+ //
2100+
2101+ memset (& Statx2 , 0 , sizeof (Statx2 ));
2102+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testfile" , 0 , STATX_BASIC_STATS | STATX_BTIME , & Statx2 ));
2103+ if (Statx2 .stx_mask & STATX_BTIME )
2104+ {
2105+ LxtLogInfo ("Birth time supported: tv_sec=%lld" , (long long )Statx2 .stx_btime .tv_sec );
2106+ }
2107+
2108+ //
2109+ // Test sync flags.
2110+ //
2111+
2112+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testfile" , AT_STATX_FORCE_SYNC , STATX_BASIC_STATS , & Statx2 ));
2113+ LxtCheckEqual (Statx1 .stx_ino , Statx2 .stx_ino , "%llu" );
2114+
2115+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testfile" , AT_STATX_DONT_SYNC , STATX_BASIC_STATS , & Statx2 ));
2116+ LxtCheckEqual (Statx1 .stx_ino , Statx2 .stx_ino , "%llu" );
2117+
2118+ //
2119+ // Test individual field masks.
2120+ //
2121+
2122+ memset (& Statx2 , 0 , sizeof (Statx2 ));
2123+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testfile" , 0 , STATX_TYPE , & Statx2 ));
2124+ LxtCheckTrue ((Statx2 .stx_mask & STATX_TYPE ) != 0 );
2125+ LxtCheckTrue (S_ISREG (Statx2 .stx_mode ));
2126+
2127+ memset (& Statx2 , 0 , sizeof (Statx2 ));
2128+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testfile" , 0 , STATX_MODE , & Statx2 ));
2129+ LxtCheckTrue ((Statx2 .stx_mask & STATX_MODE ) != 0 );
2130+ LxtCheckEqual ((Statx1 .stx_mode & 0777 ), (Statx2 .stx_mode & 0777 ), "0%o" );
2131+
2132+ memset (& Statx2 , 0 , sizeof (Statx2 ));
2133+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testfile" , 0 , STATX_NLINK , & Statx2 ));
2134+ LxtCheckTrue ((Statx2 .stx_mask & STATX_NLINK ) != 0 );
2135+ LxtCheckEqual (Statx1 .stx_nlink , Statx2 .stx_nlink , "%u" );
2136+
2137+ memset (& Statx2 , 0 , sizeof (Statx2 ));
2138+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testfile" , 0 , STATX_UID , & Statx2 ));
2139+ LxtCheckTrue ((Statx2 .stx_mask & STATX_UID ) != 0 );
2140+ LxtCheckEqual (Statx1 .stx_uid , Statx2 .stx_uid , "%u" );
2141+
2142+ memset (& Statx2 , 0 , sizeof (Statx2 ));
2143+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testfile" , 0 , STATX_GID , & Statx2 ));
2144+ LxtCheckTrue ((Statx2 .stx_mask & STATX_GID ) != 0 );
2145+ LxtCheckEqual (Statx1 .stx_gid , Statx2 .stx_gid , "%u" );
2146+
2147+ memset (& Statx2 , 0 , sizeof (Statx2 ));
2148+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testfile" , 0 , STATX_ATIME , & Statx2 ));
2149+ LxtCheckTrue ((Statx2 .stx_mask & STATX_ATIME ) != 0 );
2150+ LxtCheckEqual (Statx1 .stx_atime .tv_sec , Statx2 .stx_atime .tv_sec , "%lld" );
2151+
2152+ memset (& Statx2 , 0 , sizeof (Statx2 ));
2153+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testfile" , 0 , STATX_MTIME , & Statx2 ));
2154+ LxtCheckTrue ((Statx2 .stx_mask & STATX_MTIME ) != 0 );
2155+ LxtCheckEqual (Statx1 .stx_mtime .tv_sec , Statx2 .stx_mtime .tv_sec , "%lld" );
2156+
2157+ memset (& Statx2 , 0 , sizeof (Statx2 ));
2158+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testfile" , 0 , STATX_CTIME , & Statx2 ));
2159+ LxtCheckTrue ((Statx2 .stx_mask & STATX_CTIME ) != 0 );
2160+ LxtCheckEqual (Statx1 .stx_ctime .tv_sec , Statx2 .stx_ctime .tv_sec , "%lld" );
2161+
2162+ memset (& Statx2 , 0 , sizeof (Statx2 ));
2163+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testfile" , 0 , STATX_INO , & Statx2 ));
2164+ LxtCheckTrue ((Statx2 .stx_mask & STATX_INO ) != 0 );
2165+ LxtCheckEqual (Statx1 .stx_ino , Statx2 .stx_ino , "%llu" );
2166+
2167+ memset (& Statx2 , 0 , sizeof (Statx2 ));
2168+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testfile" , 0 , STATX_SIZE , & Statx2 ));
2169+ LxtCheckTrue ((Statx2 .stx_mask & STATX_SIZE ) != 0 );
2170+ LxtCheckEqual (Statx1 .stx_size , Statx2 .stx_size , "%llu" );
2171+
2172+ memset (& Statx2 , 0 , sizeof (Statx2 ));
2173+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/testfile" , 0 , STATX_BLOCKS , & Statx2 ));
2174+ LxtCheckTrue ((Statx2 .stx_mask & STATX_BLOCKS ) != 0 );
2175+ LxtCheckEqual (Statx1 .stx_blocks , Statx2 .stx_blocks , "%llu" );
2176+
2177+ //
2178+ // Test on a directory.
2179+ //
2180+
2181+ LxtCheckErrnoZeroSuccess (statx (AT_FDCWD , DRVFS_BASIC_PREFIX , 0 , STATX_BASIC_STATS , & Statx2 ));
2182+ LxtCheckTrue (S_ISDIR (Statx2 .stx_mode ));
2183+
2184+ //
2185+ // Test error case.
2186+ //
2187+
2188+ LxtCheckErrnoFailure (statx (AT_FDCWD , DRVFS_BASIC_PREFIX "/nonexistent" , 0 , STATX_BASIC_STATS , & Statx2 ), ENOENT );
2189+
2190+ ErrorExit :
2191+ if (Fd >= 0 )
2192+ {
2193+ close (Fd );
2194+ }
2195+
2196+ unlink (DRVFS_BASIC_PREFIX "/testlink" );
2197+ unlink (DRVFS_BASIC_PREFIX "/testfile" );
2198+ rmdir (DRVFS_BASIC_PREFIX );
2199+ return Result ;
2200+ }
2201+
20302202int DrvFsTestGetDents64Alignment (PLXT_ARGS Args )
20312203
20322204/*++
0 commit comments