@@ -133,12 +133,18 @@ isMetaDir dname = do
133133 then return True
134134 else return False
135135
136+ data GStatRes
137+ = GSIsMetaDir
138+ | GSIsRegDir
139+ | GSIsNotDir
140+ | GSStatError
141+
136142{-# NOINLINE gstatDname #-}
137- gstatDname :: Bool -> PosixPath -> Ptr CChar -> IO ( Bool , Bool )
143+ gstatDname :: Bool -> PosixPath -> Ptr CChar -> IO GStatRes
138144gstatDname followSym parent dname = do
139145 isMeta <- liftIO $ isMetaDir dname
140146 if isMeta
141- then pure ( True , True )
147+ then pure GSIsMetaDir
142148 else do
143149 -- XXX We can create a pinned array right here since the next call pins
144150 -- it anyway.
@@ -149,17 +155,17 @@ gstatDname followSym parent dname = do
149155 then c_stat_is_directory cStr
150156 else c_lstat_is_directory cStr
151157 case res of
152- x | x == 1 -> pure ( True , False )
153- x | x == 0 -> pure ( False , False )
158+ x | x == 1 -> pure GSIsRegDir
159+ x | x == 0 -> pure GSIsNotDir
154160 -- XXX Need to check if and how we should handle some errors
155161 -- like EACCES.
156- _ -> throwErrno ( " gstatDname: " ++ Path. toString path)
162+ _ -> pure GSStatError
157163
158164-- | Checks if dname is a directory and additionaly returns if dname is a meta
159165-- directory.
160166{-# INLINE checkDirStatus #-}
161167checkDirStatus
162- :: PosixPath -> Ptr CChar -> # {type unsigned char } -> IO ( Bool , Bool )
168+ :: PosixPath -> Ptr CChar -> # {type unsigned char } -> IO GStatRes
163169#ifdef FORCE_LSTAT_READDIR
164170checkDirStatus parent dname _ = gstatDname False parent dname
165171#elif defined(FORCE_STAT_READDIR)
@@ -169,7 +175,7 @@ checkDirStatus parent dname dtype =
169175 if dtype == (# const DT_DIR )
170176 then do
171177 isMeta <- liftIO $ isMetaDir dname
172- pure ( True , isMeta)
178+ pure $ if isMeta then GSIsMetaDir else GSIsRegDir
173179 else if dtype /= # const DT_UNKNOWN
174180 then pure (False , False )
175181 else gstatDname False parent dname
@@ -205,13 +211,13 @@ readDirStreamEither (curdir, (DirStream dirp)) = loop
205211 -- fromPtrN, but it is not straightforward because the reclen is
206212 -- padded to 8-byte boundary.
207213 name <- Array. fromCString (castPtr dname)
208- (isDir, isMeta) <- checkDirStatus curdir dname dtype
209- if isDir
210- then do
211- if isMeta
212- then loop
213- else return ( Just ( Left (mkPath name)))
214- else return ( Just ( Right (mkPath name)))
214+ gsRes <- checkDirStatus curdir dname dtype
215+ case gsRes of
216+ GSIsRegDir -> return ( Just ( Left (mkPath name)))
217+ GSIsMetaDir -> loop
218+ GSIsNotDir -> return ( Just ( Right (mkPath name)))
219+ -- We ignore the error in this case
220+ GSStatError -> loop
215221 else do
216222 errno <- getErrno
217223 if (errno == eINTR)
@@ -332,12 +338,9 @@ readEitherChunks alldirs =
332338 dtype :: # {type unsigned char } <-
333339 liftIO $ # {peek struct dirent, d_type} dentPtr
334340
335- (isDir, isMeta) <- liftIO $ checkDirStatus curdir dname dtype
336- if isDir
337- then do
338- if isMeta
339- then return $ Skip st
340- else do
341+ gsRes <- liftIO $ checkDirStatus curdir dname dtype
342+ case gsRes of
343+ GSIsRegDir -> do
341344 path <- liftIO $ appendCString curdir dname
342345 let dirs1 = path : dirs
343346 ndirs1 = ndirs + 1
@@ -346,7 +349,8 @@ readEitherChunks alldirs =
346349 (ChunkStreamLoop curdir xs dirp [] 0 files nfiles)
347350 else return $ Skip
348351 (ChunkStreamLoop curdir xs dirp dirs1 ndirs1 files nfiles)
349- else do
352+ GSIsMetaDir -> return $ Skip st
353+ GSIsNotDir -> do
350354 path <- liftIO $ appendCString curdir dname
351355 let files1 = path : files
352356 nfiles1 = nfiles + 1
@@ -355,6 +359,8 @@ readEitherChunks alldirs =
355359 (ChunkStreamLoop curdir xs dirp dirs ndirs [] 0 )
356360 else return $ Skip
357361 (ChunkStreamLoop curdir xs dirp dirs ndirs files1 nfiles1)
362+ -- We ignore the error in this case
363+ GSStatError -> return $ Skip st
358364 else do
359365 errno <- liftIO getErrno
360366 if (errno == eINTR)
@@ -497,9 +503,10 @@ readEitherByteChunks alldirs =
497503 -- XXX Skips come around the entire loop, does that impact perf
498504 -- because it has a StreamK in the middle.
499505 -- Keep the file check first as it is more likely
500- (isDir, isMeta) <- liftIO $ checkDirStatus curdir dname dtype
501- if not isDir
502- then do
506+
507+ gsRes <- liftIO $ checkDirStatus curdir dname dtype
508+ case gsRes of
509+ GSIsNotDir -> do
503510 r <- copyToBuf mbarr pos curdir dname
504511 case r of
505512 Just pos1 ->
@@ -516,10 +523,7 @@ readEitherByteChunks alldirs =
516523 else
517524 return $ Skip
518525 (ChunkStreamByteLoopPending dname curdir xs dirp mbarr pos)
519- else do
520- if isMeta
521- then return $ Skip st
522- else do
526+ GSIsRegDir -> do
523527 path <- liftIO $ appendCString curdir dname
524528 let dirs1 = path : dirs
525529 ndirs1 = ndirs + 1
@@ -534,7 +538,10 @@ readEitherByteChunks alldirs =
534538 -- otherwise skip.
535539 return $ Yield (Left dirs1)
536540 (ChunkStreamByteLoopPending dname curdir xs dirp mbarr pos)
537- else do
541+ GSIsMetaDir -> return $ Skip st
542+ -- We ignore the error in this case
543+ GSStatError -> return $ Skip st
544+ else do
538545 errno <- liftIO getErrno
539546 if (errno == eINTR)
540547 then return $ Skip st
@@ -656,9 +663,9 @@ readEitherByteChunksAt (ppath, alldirs) =
656663 liftIO $ # {peek struct dirent, d_type} dentPtr
657664
658665 -- Keep the file check first as it is more likely
659- (isDir, isMeta) <- liftIO $ checkDirStatus curdir dname dtype
660- if not isDir
661- then do
666+ gsRes <- liftIO $ checkDirStatus curdir dname dtype
667+ case gsRes of
668+ GSIsNotDir -> do
662669 r <- copyToBuf mbarr pos curdir dname
663670 case r of
664671 Just pos1 ->
@@ -669,10 +676,7 @@ readEitherByteChunksAt (ppath, alldirs) =
669676 return $ Skip
670677 (ByteChunksAtRealloc
671678 dname pfd dirp curdir xs dirs ndirs mbarr pos)
672- else do
673- if isMeta
674- then return $ Skip st
675- else do
679+ GSIsRegDir -> do
676680 arr <- Array. fromCString (castPtr dname)
677681 let path = Path. unsafeFromChunk arr
678682 let dirs1 = path : dirs
@@ -698,6 +702,9 @@ readEitherByteChunksAt (ppath, alldirs) =
698702 return $ Skip
699703 (ByteChunksAtRealloc
700704 dname pfd dirp curdir xs dirs1 ndirs1 mbarr pos)
705+ GSIsMetaDir -> return $ Skip st
706+ -- We ignore the error in this case
707+ GSStatError -> return $ Skip st
701708 else do
702709 errno <- liftIO getErrno
703710 if (errno == eINTR)
0 commit comments