
Hi Viktor,
Thanks for looking into this.
This cannot be a TOCTOU bug as the code to check the existence of the
file is only introduced for debugging this issue, to report in case
the file exists for some reason. Our understanding is that this file
cannot exist in the first place. We have never seen the "File exists"
message being printed, I will make that an error to make sure. The
tests create a temporary file using a random directory name in the
system temp directory, the directory is destroyed at the end of the
test. Also, tests do not run in parallel, we are using hspec to run
tests and it does not run tests in parallel unless we explicitly say
so, so there is no possibility that two tests could be trying to use
the same file. We will double check that. Also, this happens only on
Linux. We will also try the append mode as you suggested.
-harendra
On Mon, 7 Oct 2024 at 16:22, Viktor Dukhovni
On Mon, Oct 07, 2024 at 08:25:21AM +0530, Harendra Kumar wrote:
exists <- doesFileExist filepath if not exists then do putStrLn $ "Creating file: " ++ (parent > file) openFile (parent > file) WriteMode >>= hClose putStrLn $ "Created file: " ++ (parent > file) else error $ "File exists: " ++ filepath
This is a classic TOCTOU bug. The file can come into existence between the "doesFileExist" test and the attempt to create it. To create a file only if it does not exist, you need to use an "open" variant that creates the file if necessary, and leaves it unmodified if it already exists. "AppendMode" works for this, because you're closing the file immediately, so the fact that any writes would "append" is not material.
So replace the above with:
openFile filepath AppendMode >>= hClose
If you need to know whether the file got created by this call, or was found to exist already, you need a lower-level API, such as (Unix C):
/* In some cases 0600 is more appropriate */ int fd = open(path, O_WRONLY|O_CREAT|O_EXCL, 0666);
if (fd >= 0) { /* Just created */ (void) close(fd); ... } else if (errno == EEXIST) { /* Already present */ ... } else { /* Permission or other problem */ ... }
-- Viktor. _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs