@@ -273,72 +273,64 @@ isMetaDir dname = do
273
273
then return True
274
274
else return False
275
275
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
312
304
where
305
+
313
306
errMsg path =
314
307
let pathStr = Path. toString_ path
315
- in " statDname : " ++ pathStr
308
+ in " statEntryType : " ++ pathStr
316
309
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
321
313
:: 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 =
323
317
#ifdef FORCE_LSTAT_READDIR
324
- checkDirStatus conf parent dname _ =
325
- gstatDname conf parent dname
318
+ True
326
319
#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
340
322
#endif
341
323
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
+
342
334
-------------------------------------------------------------------------------
343
335
-- streaming reads
344
336
-------------------------------------------------------------------------------
@@ -376,12 +368,11 @@ readDirStreamEither confMod (curdir, (DirStream dirp)) = loop
376
368
-- fromPtrN, but it is not straightforward because the reclen is
377
369
-- padded to 8-byte boundary.
378
370
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
385
376
else do
386
377
errno <- getErrno
387
378
if (errno == eINTR)
@@ -515,9 +506,9 @@ readEitherChunks confMod alldirs =
515
506
dtype :: # {type unsigned char } <-
516
507
liftIO $ # {peek struct dirent, d_type} dentPtr
517
508
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
521
512
path <- liftIO $ appendCString curdir dname
522
513
let dirs1 = path : dirs
523
514
ndirs1 = ndirs + 1
@@ -526,7 +517,7 @@ readEitherChunks confMod alldirs =
526
517
(ChunkStreamLoop curdir xs dirp [] 0 files nfiles)
527
518
else return $ Skip
528
519
(ChunkStreamLoop curdir xs dirp dirs1 ndirs1 files nfiles)
529
- GSIsNotDir -> do
520
+ EntryIsNotDir -> do
530
521
path <- liftIO $ appendCString curdir dname
531
522
let files1 = path : files
532
523
nfiles1 = nfiles + 1
@@ -535,8 +526,7 @@ readEitherChunks confMod alldirs =
535
526
(ChunkStreamLoop curdir xs dirp dirs ndirs [] 0 )
536
527
else return $ Skip
537
528
(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
540
530
else do
541
531
errno <- liftIO getErrno
542
532
if (errno == eINTR)
@@ -684,9 +674,9 @@ readEitherByteChunks confMod alldirs =
684
674
-- because it has a StreamK in the middle.
685
675
-- Keep the file check first as it is more likely
686
676
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
690
680
r <- copyToBuf mbarr pos curdir dname
691
681
case r of
692
682
Just pos1 ->
@@ -703,7 +693,7 @@ readEitherByteChunks confMod alldirs =
703
693
else
704
694
return $ Skip
705
695
(ChunkStreamByteLoopPending dname curdir xs dirp mbarr pos)
706
- GSIsRegDir -> do
696
+ EntryIsDir -> do
707
697
path <- liftIO $ appendCString curdir dname
708
698
let dirs1 = path : dirs
709
699
ndirs1 = ndirs + 1
@@ -718,8 +708,7 @@ readEitherByteChunks confMod alldirs =
718
708
-- otherwise skip.
719
709
return $ Yield (Left dirs1)
720
710
(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
723
712
else do
724
713
errno <- liftIO getErrno
725
714
if (errno == eINTR)
@@ -843,9 +832,9 @@ readEitherByteChunksAt confMod (ppath, alldirs) =
843
832
liftIO $ # {peek struct dirent, d_type} dentPtr
844
833
845
834
-- 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
849
838
r <- copyToBuf mbarr pos curdir dname
850
839
case r of
851
840
Just pos1 ->
@@ -856,7 +845,7 @@ readEitherByteChunksAt confMod (ppath, alldirs) =
856
845
return $ Skip
857
846
(ByteChunksAtRealloc
858
847
dname pfd dirp curdir xs dirs ndirs mbarr pos)
859
- GSIsRegDir -> do
848
+ EntryIsDir -> do
860
849
arr <- Array. fromCString (castPtr dname)
861
850
let path = Path. unsafeFromChunk arr
862
851
let dirs1 = path : dirs
@@ -882,8 +871,7 @@ readEitherByteChunksAt confMod (ppath, alldirs) =
882
871
return $ Skip
883
872
(ByteChunksAtRealloc
884
873
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
887
875
else do
888
876
errno <- liftIO getErrno
889
877
if (errno == eINTR)
0 commit comments