@@ -273,72 +273,64 @@ isMetaDir dname = do
273273 then return True
274274 else return False
275275
276- data GStatRes
277- = GSIsMetaDir
278- | GSIsRegDir
279- | GSIsNotDir
280- | GSIgnoreError Errno
281-
282- {-# NOINLINE gstatDname #-}
283- gstatDname
284- :: ReadOptions -> PosixPath -> Ptr CChar -> IO GStatRes
285- gstatDname conf parent dname = do
286- isMeta <- liftIO $ isMetaDir dname
287- if isMeta
288- then pure GSIsMetaDir
289- else do
290- -- XXX We can create a pinned array right here since the next call pins
291- -- it anyway.
292- path <- appendCString parent dname
293- Array. asCStringUnsafe (Path. toChunk path) $ \ cStr -> do
294- res <- stat (_followSymlinks conf) cStr
295- case res of
296- Right mode -> pure $
297- if (mode == s_IFDIR)
298- then GSIsRegDir
299- else GSIsNotDir
300- Left errno -> do
301- if errno == eNOENT
302- then unless (_ignoreNonExistingFiles conf) $
303- throwErrno (errMsg path)
304- else if errno == eACCES
305- then unless (_ignoreInAccessibleFiles conf) $
306- throwErrno (errMsg path)
307- else if errno == eLOOP
308- then unless (_ignoreSymlinkLoopErrors conf) $
309- throwErrno (errMsg path)
310- else throwErrno (errMsg path)
311- pure $ GSIgnoreError errno
276+ data EntryType = EntryIsDir | EntryIsNotDir | EntryIgnored
277+
278+ {-# NOINLINE statEntryType #-}
279+ statEntryType
280+ :: ReadOptions -> PosixPath -> Ptr CChar -> IO EntryType
281+ statEntryType conf parent dname = do
282+ -- XXX We can create a pinned array right here since the next call pins
283+ -- it anyway.
284+ path <- appendCString parent dname
285+ Array. asCStringUnsafe (Path. toChunk path) $ \ cStr -> do
286+ res <- stat (_followSymlinks conf) cStr
287+ case res of
288+ Right mode -> pure $
289+ if (mode == s_IFDIR)
290+ then EntryIsDir
291+ else EntryIsNotDir
292+ Left errno -> do
293+ if errno == eNOENT
294+ then unless (_ignoreNonExistingFiles conf) $
295+ throwErrno (errMsg path)
296+ else if errno == eACCES
297+ then unless (_ignoreInAccessibleFiles conf) $
298+ throwErrno (errMsg path)
299+ else if errno == eLOOP
300+ then unless (_ignoreSymlinkLoopErrors conf) $
301+ throwErrno (errMsg path)
302+ else throwErrno (errMsg path)
303+ pure $ EntryIgnored
312304 where
305+
313306 errMsg path =
314307 let pathStr = Path. toString_ path
315- in " statDname : " ++ pathStr
308+ in " statEntryType : " ++ pathStr
316309
317- -- | Checks if dname is a directory and additionaly returns if dname is a meta
318- -- directory.
319- {-# INLINE checkDirStatus #-}
320- checkDirStatus
310+ -- | Checks if dname is a directory, not dir or should be ignored.
311+ {-# INLINE getEntryType #-}
312+ getEntryType
321313 :: ReadOptions
322- -> PosixPath -> Ptr CChar -> # {type unsigned char } -> IO GStatRes
314+ -> PosixPath -> Ptr CChar -> # {type unsigned char } -> IO EntryType
315+ getEntryType conf parent dname dtype = do
316+ let needStat =
323317#ifdef FORCE_LSTAT_READDIR
324- checkDirStatus conf parent dname _ =
325- gstatDname conf parent dname
318+ True
326319#else
327- checkDirStatus conf parent dname dtype =
328- if dtype == (# const DT_DIR )
329- then do
330- isMeta <- liftIO $ isMetaDir dname
331- pure $ if isMeta then GSIsMetaDir else GSIsRegDir
332- else if dtype == (# const DT_LNK )
333- then
334- if _followSymlinks conf
335- then gstatDname conf parent dname
336- else pure GSIsNotDir
337- else if dtype /= # const DT_UNKNOWN
338- then pure GSIsNotDir
339- else gstatDname conf parent dname
320+ (dtype == (# const DT_LNK ) && _followSymlinks conf)
321+ || dtype == # const DT_UNKNOWN
340322#endif
341323
324+ if dtype /= (# const DT_DIR ) && not needStat
325+ then pure EntryIsNotDir
326+ else do
327+ isMeta <- liftIO $ isMetaDir dname
328+ if isMeta
329+ then pure EntryIgnored
330+ else if dtype == (# const DT_DIR )
331+ then pure EntryIsDir
332+ else statEntryType conf parent dname
333+
342334-------------------------------------------------------------------------------
343335-- streaming reads
344336-------------------------------------------------------------------------------
@@ -376,12 +368,11 @@ readDirStreamEither confMod (curdir, (DirStream dirp)) = loop
376368 -- fromPtrN, but it is not straightforward because the reclen is
377369 -- padded to 8-byte boundary.
378370 name <- Array. fromCString (castPtr dname)
379- gsRes <- checkDirStatus conf curdir dname dtype
380- case gsRes of
381- GSIsRegDir -> return (Just (Left (mkPath name)))
382- GSIsNotDir -> return (Just (Right (mkPath name)))
383- -- Loop if it's a meta directory or an error that we can ignore
384- _ -> loop
371+ etype <- getEntryType conf curdir dname dtype
372+ case etype of
373+ EntryIsDir -> return (Just (Left (mkPath name)))
374+ EntryIsNotDir -> return (Just (Right (mkPath name)))
375+ EntryIgnored -> loop
385376 else do
386377 errno <- getErrno
387378 if (errno == eINTR)
@@ -515,9 +506,9 @@ readEitherChunks confMod alldirs =
515506 dtype :: # {type unsigned char } <-
516507 liftIO $ # {peek struct dirent, d_type} dentPtr
517508
518- gsRes <- liftIO $ checkDirStatus conf curdir dname dtype
519- case gsRes of
520- GSIsRegDir -> do
509+ etype <- liftIO $ getEntryType conf curdir dname dtype
510+ case etype of
511+ EntryIsDir -> do
521512 path <- liftIO $ appendCString curdir dname
522513 let dirs1 = path : dirs
523514 ndirs1 = ndirs + 1
@@ -526,7 +517,7 @@ readEitherChunks confMod alldirs =
526517 (ChunkStreamLoop curdir xs dirp [] 0 files nfiles)
527518 else return $ Skip
528519 (ChunkStreamLoop curdir xs dirp dirs1 ndirs1 files nfiles)
529- GSIsNotDir -> do
520+ EntryIsNotDir -> do
530521 path <- liftIO $ appendCString curdir dname
531522 let files1 = path : files
532523 nfiles1 = nfiles + 1
@@ -535,8 +526,7 @@ readEitherChunks confMod alldirs =
535526 (ChunkStreamLoop curdir xs dirp dirs ndirs [] 0 )
536527 else return $ Skip
537528 (ChunkStreamLoop curdir xs dirp dirs ndirs files1 nfiles1)
538- -- Loop if it's a meta directory or an error that we can ignore
539- _ -> return $ Skip st
529+ EntryIgnored -> return $ Skip st
540530 else do
541531 errno <- liftIO getErrno
542532 if (errno == eINTR)
@@ -684,9 +674,9 @@ readEitherByteChunks confMod alldirs =
684674 -- because it has a StreamK in the middle.
685675 -- Keep the file check first as it is more likely
686676
687- gsRes <- liftIO $ checkDirStatus conf curdir dname dtype
688- case gsRes of
689- GSIsNotDir -> do
677+ etype <- liftIO $ getEntryType conf curdir dname dtype
678+ case etype of
679+ EntryIsNotDir -> do
690680 r <- copyToBuf mbarr pos curdir dname
691681 case r of
692682 Just pos1 ->
@@ -703,7 +693,7 @@ readEitherByteChunks confMod alldirs =
703693 else
704694 return $ Skip
705695 (ChunkStreamByteLoopPending dname curdir xs dirp mbarr pos)
706- GSIsRegDir -> do
696+ EntryIsDir -> do
707697 path <- liftIO $ appendCString curdir dname
708698 let dirs1 = path : dirs
709699 ndirs1 = ndirs + 1
@@ -718,8 +708,7 @@ readEitherByteChunks confMod alldirs =
718708 -- otherwise skip.
719709 return $ Yield (Left dirs1)
720710 (ChunkStreamByteLoopPending dname curdir xs dirp mbarr pos)
721- -- Loop if it's a meta directory or an error that we can ignore
722- _ -> return $ Skip st
711+ EntryIgnored -> return $ Skip st
723712 else do
724713 errno <- liftIO getErrno
725714 if (errno == eINTR)
@@ -843,9 +832,9 @@ readEitherByteChunksAt confMod (ppath, alldirs) =
843832 liftIO $ # {peek struct dirent, d_type} dentPtr
844833
845834 -- Keep the file check first as it is more likely
846- gsRes <- liftIO $ checkDirStatus conf curdir dname dtype
847- case gsRes of
848- GSIsNotDir -> do
835+ etype <- liftIO $ getEntryType conf curdir dname dtype
836+ case etype of
837+ EntryIsNotDir -> do
849838 r <- copyToBuf mbarr pos curdir dname
850839 case r of
851840 Just pos1 ->
@@ -856,7 +845,7 @@ readEitherByteChunksAt confMod (ppath, alldirs) =
856845 return $ Skip
857846 (ByteChunksAtRealloc
858847 dname pfd dirp curdir xs dirs ndirs mbarr pos)
859- GSIsRegDir -> do
848+ EntryIsDir -> do
860849 arr <- Array. fromCString (castPtr dname)
861850 let path = Path. unsafeFromChunk arr
862851 let dirs1 = path : dirs
@@ -882,8 +871,7 @@ readEitherByteChunksAt confMod (ppath, alldirs) =
882871 return $ Skip
883872 (ByteChunksAtRealloc
884873 dname pfd dirp curdir xs dirs1 ndirs1 mbarr pos)
885- -- Loop if it's a meta directory or an error that we can ignore
886- _ -> return $ Skip st
874+ EntryIgnored -> return $ Skip st
887875 else do
888876 errno <- liftIO getErrno
889877 if (errno == eINTR)
0 commit comments