summaryrefslogtreecommitdiff
path: root/ghc/compiler/utils/DirUtils.lhs
blob: dffd408e9b1f3685d53de7d3fef1e76d4406e6e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
%
% (c) The GRASP/AQUA Project, Glasgow University, 1998
%
\section[DirUtils]{Directory functions}

\begin{code}
{-# OPTIONS -#include <dirent.h> #-}
module DirUtils
       (
	getDirectoryContents
       ) where

#if !defined(__GLASGOW_HASKELL__) || __GLASGOW_HASKELL__ >= 302
import Directory
#else

#if __GLASGOW_HASKELL__ >= 300
import PrelPack   ( unpackNBytesST )
#else
import PackBase   ( unpackNBytesST )
#endif
import PrimPacked ( strLength )
import GlaExts    ( stToIO )
import Addr	  ( Addr )

\end{code}

The implementation of Directory.getDirectoryContents that ships
with ghc-X ( X<=301) is wrong (the C stub fails to allocate
space for the terminating NUL for each directory entry name.)

To counter for this, we supply a working version here, which will
be nuked once we can assume that ghc-3.02 or later is used to 
compile the compiler sources.

\begin{code}
getDirectoryContents :: String -> IO [String]
getDirectoryContents path = do
    dir <- _ccall_ opendir path
    if dir == ``NULL'' 
	then fail (userError ("DirUtils.getDirectoryContents: couldn't open "++ path))
     	else loop dir
  where
    loop :: Addr -> IO [String]
    loop dir  = do
      dirent_ptr <- _ccall_ readdir dir
      if (dirent_ptr::Addr) == ``NULL'' 
       then do
          _ccall_ closedir dir
	  return [] 
       else do
          str     <- _casm_ `` %r=(char*)((struct dirent*)%0)->d_name; '' dirent_ptr
	  entry   <- stToIO (unpackNBytesST str (strLength str))
          entries <- loop dir
          return (entry:entries)
#endif
\end{code}