Skip to content

Commit 9b3efa7

Browse files
committed
Ignore the stat error in readdir
1 parent b0bb752 commit 9b3efa7

File tree

1 file changed

+43
-36
lines changed

1 file changed

+43
-36
lines changed

core/src/Streamly/Internal/FileSystem/Posix/ReadDir.hsc

Lines changed: 43 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -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
138144
gstatDname 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 #-}
161167
checkDirStatus
162-
:: PosixPath -> Ptr CChar -> #{type unsigned char} -> IO (Bool, Bool)
168+
:: PosixPath -> Ptr CChar -> #{type unsigned char} -> IO GStatRes
163169
#ifdef FORCE_LSTAT_READDIR
164170
checkDirStatus 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

Comments
 (0)