Skip to content

Commit

Permalink
Fix createDirectoryIfMissing silently failing
Browse files Browse the repository at this point in the history
In some cases, `createDirectoryIfMissing` would silently fail. For
example the following invocation would fail to report via an exception
that it couldn't create a folder:

  let testdir = "/tmp/sometestdir"
  writeFile testdir ""
  createDirectoryIfMissing False testdir

A related issue was the failure to create a folder hierarchy due to lack
of permissions, for instance

  createDirectoryIfMissing True "/foo"

for a non-priviledged user would silently fail (i.e. no exception
thrown), even though "/foo" was not created.

Fixes #4 (see also #10 for discussion)
  • Loading branch information
hvr committed Jan 19, 2015
1 parent a5d0c5b commit 1f11393
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 10 deletions.
16 changes: 6 additions & 10 deletions System/Directory.hs
Original file line number Diff line number Diff line change
Expand Up @@ -393,19 +393,15 @@ createDirectoryIfMissing create_parents path0
-- This caused GHCi to crash when loading a module in the root
-- directory.
| isAlreadyExistsError e
|| isPermissionError e -> (do
|| isPermissionError e -> do
#ifdef mingw32_HOST_OS
withFileStatus "createDirectoryIfMissing" dir $ \st -> do
isDir <- isDirectory st
if isDir then return ()
else throwIO e
canIgnore <- (withFileStatus "createDirectoryIfMissing" dir isDirectory)
#else
stat <- Posix.getFileStatus dir
if Posix.isDirectory stat
then return ()
else throwIO e
canIgnore <- (Posix.isDirectory `fmap` Posix.getFileStatus dir)
#endif
) `E.catch` ((\_ -> return ()) :: IOException -> IO ())
`catch` ((\ _ -> return (isAlreadyExistsError e))
:: IOException -> IO Bool)
unless canIgnore (throwIO e)
| otherwise -> throwIO e

#if __GLASGOW_HASKELL__
Expand Down
12 changes: 12 additions & 0 deletions tests/createDirectoryIfMissing001.hs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@ main = do

cleanup

-- these are all supposed to fail

writeFile testdir testdir
report $ createDirectoryIfMissing False testdir
removeFile testdir
cleanup

writeFile testdir testdir
report $ createDirectoryIfMissing True testdir_a
removeFile testdir
cleanup

-- createDirectoryIfMissing is allowed to fail with isDoesNotExistError if
-- another process/thread removes one of the directories during the proces
-- of creating the hierarchy.
Expand Down
2 changes: 2 additions & 0 deletions tests/createDirectoryIfMissing001.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ createDirectoryIfMissing001.d/a: createDirectory: does not exist (No such file o
()
()
()
createDirectoryIfMissing001.d: createDirectory: already exists (File exists)
createDirectoryIfMissing001.d/a: createDirectory: inappropriate type (Not a directory)

0 comments on commit 1f11393

Please sign in to comment.