Skip to content

Commit 004a0bc

Browse files
committed
Add test for dirent d_type
co-authored by @sjshuck
1 parent 268b8ff commit 004a0bc

File tree

3 files changed

+107
-0
lines changed

3 files changed

+107
-0
lines changed

configure.ac

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,66 @@ FP_CHECK_CONST([DT_WHT], [
6565
#include <dirent.h>
6666
#endif], [-9])
6767

68+
AC_LANG(C)
69+
AC_MSG_CHECKING(whether kernel returns a useful d_type)
70+
AC_RUN_IFELSE(
71+
[AC_LANG_SOURCE([[
72+
#if HAVE_STRUCT_DIRENT_D_TYPE
73+
#include <dirent.h>
74+
#include <errno.h>
75+
#include <stdio.h>
76+
#include <stdlib.h>
77+
#include <string.h>
78+
#include <sys/types.h>
79+
80+
void check_error(const char *msg) {
81+
if (errno) {
82+
perror(msg);
83+
exit(1);
84+
}
85+
}
86+
87+
int main() {
88+
DIR *dir = opendir(".");
89+
check_error("opendir");
90+
91+
struct dirent *de = NULL;
92+
93+
do {
94+
de = readdir(dir);
95+
check_error("readdir");
96+
} while (de && strcmp(de->d_name, ".") != 0);
97+
// We found the . dir or encountered end of dir stream
98+
99+
int status = 0;
100+
101+
if (!de) {
102+
status = 1;
103+
} else if (de->d_type == DT_DIR) {
104+
} else if (de->d_type == DT_UNKNOWN) {
105+
// Signal that we should skip test for non-zero d_type
106+
status = 2;
107+
} else {
108+
status = 1;
109+
}
110+
111+
closedir(dir);
112+
check_error("closedir");
113+
114+
exit(status);
115+
}
116+
#else
117+
int main() { exit(2); }
118+
#endif
119+
]])],
120+
[AC_MSG_RESULT(yes)],
121+
[if test $? -eq 1 ; then
122+
AC_MSG_FAILURE(Unexpected failure when testing for kernels d_type)
123+
else
124+
AC_MSG_RESULT(no (skipping DirEnt test))
125+
AC_DEFINE([NO_DTIR_TEST], [1], [Define to 1 if we want to stkip DirEnt test.])
126+
fi])
127+
68128
AC_CHECK_FUNCS([getgrgid_r getgrnam_r getpwnam_r getpwuid_r getpwnam getpwuid])
69129
AC_CHECK_FUNCS([getpwent getgrent])
70130
AC_CHECK_FUNCS([lchown setenv sysconf unsetenv clearenv])

tests/DirEnt.hsc

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{-# LANGUAGE LambdaCase #-}
2+
3+
#include "HsUnixConfig.h"
4+
5+
module Main (main) where
6+
#if defined(NO_DTIR_TEST)
7+
main :: IO ()
8+
main = do
9+
putStrLn "Skipping DirEnt test, since kernel seems to always return DT_UNKNOWN"
10+
#else
11+
12+
import Control.Exception (bracket, finally)
13+
import Foreign.C.String (peekCString)
14+
import System.Exit
15+
import System.Posix.Directory
16+
import System.Posix.Directory.Internals
17+
18+
peekDirEnt :: DirEnt -> IO (String, DirType)
19+
peekDirEnt dirEnt = do
20+
dName <- dirEntName dirEnt >>= peekCString
21+
dType <- dirEntType dirEnt
22+
return (dName, dType)
23+
24+
testDirTypeOfDot :: DirStream -> IO ()
25+
testDirTypeOfDot dirStream = go where
26+
go = readDirStreamWith peekDirEnt dirStream >>= \case
27+
Just (".", DirectoryType) -> do
28+
putStrLn "Got DirectoryType for . dir"
29+
exitSuccess
30+
Just (".", dType) -> die $ "Got " ++ show dType ++ " for . dir!"
31+
Just _ -> go
32+
Nothing -> die "Read cwd in Haskell and didn't find . dir!"
33+
34+
main :: IO ()
35+
main = do
36+
putStrLn "Running Haskell test of dirEntType"
37+
bracket (openDirStream ".") closeDirStream testDirTypeOfDot
38+
#endif

unix.cabal

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,3 +382,12 @@ test-suite T13660
382382
else
383383
build-depends: filepath >= 1.4.100.0 && < 1.5.0.0
384384
ghc-options: -Wall
385+
386+
test-suite DirEnt
387+
hs-source-dirs: tests
388+
main-is: DirEnt.hs
389+
type: exitcode-stdio-1.0
390+
default-language: Haskell2010
391+
build-depends: base, unix
392+
ghc-options: -Wall
393+

0 commit comments

Comments
 (0)