SafeHaskell: Added SafeHaskell to base
[packages/base.git] / System / IO.hs
1 {-# LANGUAGE Trustworthy #-}
2 {-# LANGUAGE CPP, NoImplicitPrelude #-}
3
4 -----------------------------------------------------------------------------
5 -- |
6 -- Module : System.IO
7 -- Copyright : (c) The University of Glasgow 2001
8 -- License : BSD-style (see the file libraries/base/LICENSE)
9 --
10 -- Maintainer : libraries@haskell.org
11 -- Stability : stable
12 -- Portability : portable
13 --
14 -- The standard IO library.
15 --
16 -----------------------------------------------------------------------------
17
18 module System.IO (
19 -- * The IO monad
20
21 IO, -- instance MonadFix
22 fixIO, -- :: (a -> IO a) -> IO a
23
24 -- * Files and handles
25
26 FilePath, -- :: String
27
28 Handle, -- abstract, instance of: Eq, Show.
29
30 -- | GHC note: a 'Handle' will be automatically closed when the garbage
31 -- collector detects that it has become unreferenced by the program.
32 -- However, relying on this behaviour is not generally recommended:
33 -- the garbage collector is unpredictable. If possible, use
34 -- an explicit 'hClose' to close 'Handle's when they are no longer
35 -- required. GHC does not currently attempt to free up file
36 -- descriptors when they have run out, it is your responsibility to
37 -- ensure that this doesn't happen.
38
39 -- ** Standard handles
40
41 -- | Three handles are allocated during program initialisation,
42 -- and are initially open.
43
44 stdin, stdout, stderr, -- :: Handle
45
46 -- * Opening and closing files
47
48 -- ** Opening files
49
50 withFile,
51 openFile, -- :: FilePath -> IOMode -> IO Handle
52 IOMode(ReadMode,WriteMode,AppendMode,ReadWriteMode),
53
54 -- ** Closing files
55
56 hClose, -- :: Handle -> IO ()
57
58 -- ** Special cases
59
60 -- | These functions are also exported by the "Prelude".
61
62 readFile, -- :: FilePath -> IO String
63 writeFile, -- :: FilePath -> String -> IO ()
64 appendFile, -- :: FilePath -> String -> IO ()
65
66 -- ** File locking
67
68 -- $locking
69
70 -- * Operations on handles
71
72 -- ** Determining and changing the size of a file
73
74 hFileSize, -- :: Handle -> IO Integer
75 #ifdef __GLASGOW_HASKELL__
76 hSetFileSize, -- :: Handle -> Integer -> IO ()
77 #endif
78
79 -- ** Detecting the end of input
80
81 hIsEOF, -- :: Handle -> IO Bool
82 isEOF, -- :: IO Bool
83
84 -- ** Buffering operations
85
86 BufferMode(NoBuffering,LineBuffering,BlockBuffering),
87 hSetBuffering, -- :: Handle -> BufferMode -> IO ()
88 hGetBuffering, -- :: Handle -> IO BufferMode
89 hFlush, -- :: Handle -> IO ()
90
91 -- ** Repositioning handles
92
93 hGetPosn, -- :: Handle -> IO HandlePosn
94 hSetPosn, -- :: HandlePosn -> IO ()
95 HandlePosn, -- abstract, instance of: Eq, Show.
96
97 hSeek, -- :: Handle -> SeekMode -> Integer -> IO ()
98 SeekMode(AbsoluteSeek,RelativeSeek,SeekFromEnd),
99 #if !defined(__NHC__)
100 hTell, -- :: Handle -> IO Integer
101 #endif
102
103 -- ** Handle properties
104
105 hIsOpen, hIsClosed, -- :: Handle -> IO Bool
106 hIsReadable, hIsWritable, -- :: Handle -> IO Bool
107 hIsSeekable, -- :: Handle -> IO Bool
108
109 -- ** Terminal operations (not portable: GHC\/Hugs only)
110
111 #if !defined(__NHC__)
112 hIsTerminalDevice, -- :: Handle -> IO Bool
113
114 hSetEcho, -- :: Handle -> Bool -> IO ()
115 hGetEcho, -- :: Handle -> IO Bool
116 #endif
117
118 -- ** Showing handle state (not portable: GHC only)
119
120 #ifdef __GLASGOW_HASKELL__
121 hShow, -- :: Handle -> IO String
122 #endif
123
124 -- * Text input and output
125
126 -- ** Text input
127
128 hWaitForInput, -- :: Handle -> Int -> IO Bool
129 hReady, -- :: Handle -> IO Bool
130 hGetChar, -- :: Handle -> IO Char
131 hGetLine, -- :: Handle -> IO [Char]
132 hLookAhead, -- :: Handle -> IO Char
133 hGetContents, -- :: Handle -> IO [Char]
134
135 -- ** Text output
136
137 hPutChar, -- :: Handle -> Char -> IO ()
138 hPutStr, -- :: Handle -> [Char] -> IO ()
139 hPutStrLn, -- :: Handle -> [Char] -> IO ()
140 hPrint, -- :: Show a => Handle -> a -> IO ()
141
142 -- ** Special cases for standard input and output
143
144 -- | These functions are also exported by the "Prelude".
145
146 interact, -- :: (String -> String) -> IO ()
147 putChar, -- :: Char -> IO ()
148 putStr, -- :: String -> IO ()
149 putStrLn, -- :: String -> IO ()
150 print, -- :: Show a => a -> IO ()
151 getChar, -- :: IO Char
152 getLine, -- :: IO String
153 getContents, -- :: IO String
154 readIO, -- :: Read a => String -> IO a
155 readLn, -- :: Read a => IO a
156
157 -- * Binary input and output
158
159 withBinaryFile,
160 openBinaryFile, -- :: FilePath -> IOMode -> IO Handle
161 hSetBinaryMode, -- :: Handle -> Bool -> IO ()
162 hPutBuf, -- :: Handle -> Ptr a -> Int -> IO ()
163 hGetBuf, -- :: Handle -> Ptr a -> Int -> IO Int
164 #if !defined(__NHC__) && !defined(__HUGS__)
165 hGetBufSome, -- :: Handle -> Ptr a -> Int -> IO Int
166 hPutBufNonBlocking, -- :: Handle -> Ptr a -> Int -> IO Int
167 hGetBufNonBlocking, -- :: Handle -> Ptr a -> Int -> IO Int
168 #endif
169
170 -- * Temporary files
171
172 openTempFile,
173 openBinaryTempFile,
174 openTempFileWithDefaultPermissions,
175 openBinaryTempFileWithDefaultPermissions,
176
177 #if !defined(__NHC__) && !defined(__HUGS__)
178 -- * Unicode encoding\/decoding
179
180 -- | A text-mode 'Handle' has an associated 'TextEncoding', which
181 -- is used to decode bytes into Unicode characters when reading,
182 -- and encode Unicode characters into bytes when writing.
183 --
184 -- The default 'TextEncoding' is the same as the default encoding
185 -- on your system, which is also available as 'localeEncoding'.
186 -- (GHC note: on Windows, we currently do not support double-byte
187 -- encodings; if the console\'s code page is unsupported, then
188 -- 'localeEncoding' will be 'latin1'.)
189 --
190 -- Encoding and decoding errors are always detected and reported,
191 -- except during lazy I/O ('hGetContents', 'getContents', and
192 -- 'readFile'), where a decoding error merely results in
193 -- termination of the character stream, as with other I/O errors.
194
195 hSetEncoding,
196 hGetEncoding,
197
198 -- ** Unicode encodings
199 TextEncoding,
200 latin1,
201 utf8, utf8_bom,
202 utf16, utf16le, utf16be,
203 utf32, utf32le, utf32be,
204 localeEncoding,
205 char8,
206 mkTextEncoding,
207 #endif
208
209 #if !defined(__NHC__) && !defined(__HUGS__)
210 -- * Newline conversion
211
212 -- | In Haskell, a newline is always represented by the character
213 -- '\n'. However, in files and external character streams, a
214 -- newline may be represented by another character sequence, such
215 -- as '\r\n'.
216 --
217 -- A text-mode 'Handle' has an associated 'NewlineMode' that
218 -- specifies how to transate newline characters. The
219 -- 'NewlineMode' specifies the input and output translation
220 -- separately, so that for instance you can translate '\r\n'
221 -- to '\n' on input, but leave newlines as '\n' on output.
222 --
223 -- The default 'NewlineMode' for a 'Handle' is
224 -- 'nativeNewlineMode', which does no translation on Unix systems,
225 -- but translates '\r\n' to '\n' and back on Windows.
226 --
227 -- Binary-mode 'Handle's do no newline translation at all.
228 --
229 hSetNewlineMode,
230 Newline(..), nativeNewline,
231 NewlineMode(..),
232 noNewlineTranslation, universalNewlineMode, nativeNewlineMode,
233 #endif
234 ) where
235
236 import Control.Exception.Base
237
238 #ifndef __NHC__
239 import Data.Bits
240 import Data.List
241 import Data.Maybe
242 import Foreign.C.Error
243 import Foreign.C.Types
244 import System.Posix.Internals
245 import System.Posix.Types
246 #endif
247
248 #ifdef __GLASGOW_HASKELL__
249 import GHC.Base
250 import GHC.IO hiding ( bracket, onException )
251 import GHC.IO.IOMode
252 import GHC.IO.Handle.FD
253 import qualified GHC.IO.FD as FD
254 import GHC.IO.Handle
255 import GHC.IO.Handle.Text ( hGetBufSome, hPutStrLn )
256 import GHC.IORef
257 import GHC.IO.Exception ( userError )
258 import GHC.IO.Encoding
259 import GHC.Num
260 import Text.Read
261 import GHC.Show
262 #endif
263
264 #ifdef __HUGS__
265 import Hugs.IO
266 import Hugs.IOExts
267 import Hugs.IORef
268 import System.IO.Unsafe ( unsafeInterleaveIO )
269 #endif
270
271 #ifdef __NHC__
272 import IO
273 ( Handle ()
274 , HandlePosn ()
275 , IOMode (ReadMode,WriteMode,AppendMode,ReadWriteMode)
276 , BufferMode (NoBuffering,LineBuffering,BlockBuffering)
277 , SeekMode (AbsoluteSeek,RelativeSeek,SeekFromEnd)
278 , stdin, stdout, stderr
279 , openFile -- :: FilePath -> IOMode -> IO Handle
280 , hClose -- :: Handle -> IO ()
281 , hFileSize -- :: Handle -> IO Integer
282 , hIsEOF -- :: Handle -> IO Bool
283 , isEOF -- :: IO Bool
284 , hSetBuffering -- :: Handle -> BufferMode -> IO ()
285 , hGetBuffering -- :: Handle -> IO BufferMode
286 , hFlush -- :: Handle -> IO ()
287 , hGetPosn -- :: Handle -> IO HandlePosn
288 , hSetPosn -- :: HandlePosn -> IO ()
289 , hSeek -- :: Handle -> SeekMode -> Integer -> IO ()
290 , hWaitForInput -- :: Handle -> Int -> IO Bool
291 , hGetChar -- :: Handle -> IO Char
292 , hGetLine -- :: Handle -> IO [Char]
293 , hLookAhead -- :: Handle -> IO Char
294 , hGetContents -- :: Handle -> IO [Char]
295 , hPutChar -- :: Handle -> Char -> IO ()
296 , hPutStr -- :: Handle -> [Char] -> IO ()
297 , hPutStrLn -- :: Handle -> [Char] -> IO ()
298 , hPrint -- :: Handle -> [Char] -> IO ()
299 , hReady -- :: Handle -> [Char] -> IO ()
300 , hIsOpen, hIsClosed -- :: Handle -> IO Bool
301 , hIsReadable, hIsWritable -- :: Handle -> IO Bool
302 , hIsSeekable -- :: Handle -> IO Bool
303 , bracket
304
305 , IO ()
306 , FilePath -- :: String
307 )
308 import NHC.IOExtras (fixIO, hPutBuf, hGetBuf)
309 import NHC.FFI (Ptr)
310 #endif
311
312 -- -----------------------------------------------------------------------------
313 -- Standard IO
314
315 #ifdef __GLASGOW_HASKELL__
316 -- | Write a character to the standard output device
317 -- (same as 'hPutChar' 'stdout').
318
319 putChar :: Char -> IO ()
320 putChar c = hPutChar stdout c
321
322 -- | Write a string to the standard output device
323 -- (same as 'hPutStr' 'stdout').
324
325 putStr :: String -> IO ()
326 putStr s = hPutStr stdout s
327
328 -- | The same as 'putStr', but adds a newline character.
329
330 putStrLn :: String -> IO ()
331 putStrLn s = hPutStrLn stdout s
332
333 -- | The 'print' function outputs a value of any printable type to the
334 -- standard output device.
335 -- Printable types are those that are instances of class 'Show'; 'print'
336 -- converts values to strings for output using the 'show' operation and
337 -- adds a newline.
338 --
339 -- For example, a program to print the first 20 integers and their
340 -- powers of 2 could be written as:
341 --
342 -- > main = print ([(n, 2^n) | n <- [0..19]])
343
344 print :: Show a => a -> IO ()
345 print x = putStrLn (show x)
346
347 -- | Read a character from the standard input device
348 -- (same as 'hGetChar' 'stdin').
349
350 getChar :: IO Char
351 getChar = hGetChar stdin
352
353 -- | Read a line from the standard input device
354 -- (same as 'hGetLine' 'stdin').
355
356 getLine :: IO String
357 getLine = hGetLine stdin
358
359 -- | The 'getContents' operation returns all user input as a single string,
360 -- which is read lazily as it is needed
361 -- (same as 'hGetContents' 'stdin').
362
363 getContents :: IO String
364 getContents = hGetContents stdin
365
366 -- | The 'interact' function takes a function of type @String->String@
367 -- as its argument. The entire input from the standard input device is
368 -- passed to this function as its argument, and the resulting string is
369 -- output on the standard output device.
370
371 interact :: (String -> String) -> IO ()
372 interact f = do s <- getContents
373 putStr (f s)
374
375 -- | The 'readFile' function reads a file and
376 -- returns the contents of the file as a string.
377 -- The file is read lazily, on demand, as with 'getContents'.
378
379 readFile :: FilePath -> IO String
380 readFile name = openFile name ReadMode >>= hGetContents
381
382 -- | The computation 'writeFile' @file str@ function writes the string @str@,
383 -- to the file @file@.
384 writeFile :: FilePath -> String -> IO ()
385 writeFile f txt = withFile f WriteMode (\ hdl -> hPutStr hdl txt)
386
387 -- | The computation 'appendFile' @file str@ function appends the string @str@,
388 -- to the file @file@.
389 --
390 -- Note that 'writeFile' and 'appendFile' write a literal string
391 -- to a file. To write a value of any printable type, as with 'print',
392 -- use the 'show' function to convert the value to a string first.
393 --
394 -- > main = appendFile "squares" (show [(x,x*x) | x <- [0,0.1..2]])
395
396 appendFile :: FilePath -> String -> IO ()
397 appendFile f txt = withFile f AppendMode (\ hdl -> hPutStr hdl txt)
398
399 -- | The 'readLn' function combines 'getLine' and 'readIO'.
400
401 readLn :: Read a => IO a
402 readLn = do l <- getLine
403 r <- readIO l
404 return r
405
406 -- | The 'readIO' function is similar to 'read' except that it signals
407 -- parse failure to the 'IO' monad instead of terminating the program.
408
409 readIO :: Read a => String -> IO a
410 readIO s = case (do { (x,t) <- reads s ;
411 ("","") <- lex t ;
412 return x }) of
413 [x] -> return x
414 [] -> ioError (userError "Prelude.readIO: no parse")
415 _ -> ioError (userError "Prelude.readIO: ambiguous parse")
416 #endif /* __GLASGOW_HASKELL__ */
417
418 #ifndef __NHC__
419 -- | Computation 'hReady' @hdl@ indicates whether at least one item is
420 -- available for input from handle @hdl@.
421 --
422 -- This operation may fail with:
423 --
424 -- * 'System.IO.Error.isEOFError' if the end of file has been reached.
425
426 hReady :: Handle -> IO Bool
427 hReady h = hWaitForInput h 0
428
429 -- | Computation 'hPrint' @hdl t@ writes the string representation of @t@
430 -- given by the 'shows' function to the file or channel managed by @hdl@
431 -- and appends a newline.
432 --
433 -- This operation may fail with:
434 --
435 -- * 'System.IO.Error.isFullError' if the device is full; or
436 --
437 -- * 'System.IO.Error.isPermissionError' if another system resource limit would be exceeded.
438
439 hPrint :: Show a => Handle -> a -> IO ()
440 hPrint hdl = hPutStrLn hdl . show
441 #endif /* !__NHC__ */
442
443 -- | @'withFile' name mode act@ opens a file using 'openFile' and passes
444 -- the resulting handle to the computation @act@. The handle will be
445 -- closed on exit from 'withFile', whether by normal termination or by
446 -- raising an exception. If closing the handle raises an exception, then
447 -- this exception will be raised by 'withFile' rather than any exception
448 -- raised by 'act'.
449 withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r
450 withFile name mode = bracket (openFile name mode) hClose
451
452 -- | @'withBinaryFile' name mode act@ opens a file using 'openBinaryFile'
453 -- and passes the resulting handle to the computation @act@. The handle
454 -- will be closed on exit from 'withBinaryFile', whether by normal
455 -- termination or by raising an exception.
456 withBinaryFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r
457 withBinaryFile name mode = bracket (openBinaryFile name mode) hClose
458
459 -- ---------------------------------------------------------------------------
460 -- fixIO
461
462 #if defined(__GLASGOW_HASKELL__) || defined(__HUGS__)
463 fixIO :: (a -> IO a) -> IO a
464 fixIO k = do
465 ref <- newIORef (throw NonTermination)
466 ans <- unsafeInterleaveIO (readIORef ref)
467 result <- k ans
468 writeIORef ref result
469 return result
470
471 -- NOTE: we do our own explicit black holing here, because GHC's lazy
472 -- blackholing isn't enough. In an infinite loop, GHC may run the IO
473 -- computation a few times before it notices the loop, which is wrong.
474 #endif
475
476 #if defined(__NHC__)
477 -- Assume a unix platform, where text and binary I/O are identical.
478 openBinaryFile = openFile
479 hSetBinaryMode _ _ = return ()
480
481 type CMode = Int
482 #endif
483
484 -- | The function creates a temporary file in ReadWrite mode.
485 -- The created file isn\'t deleted automatically, so you need to delete it manually.
486 --
487 -- The file is creates with permissions such that only the current
488 -- user can read\/write it.
489 --
490 -- With some exceptions (see below), the file will be created securely
491 -- in the sense that an attacker should not be able to cause
492 -- openTempFile to overwrite another file on the filesystem using your
493 -- credentials, by putting symbolic links (on Unix) in the place where
494 -- the temporary file is to be created. On Unix the @O_CREAT@ and
495 -- @O_EXCL@ flags are used to prevent this attack, but note that
496 -- @O_EXCL@ is sometimes not supported on NFS filesystems, so if you
497 -- rely on this behaviour it is best to use local filesystems only.
498 --
499 openTempFile :: FilePath -- ^ Directory in which to create the file
500 -> String -- ^ File name template. If the template is \"foo.ext\" then
501 -- the created file will be \"fooXXX.ext\" where XXX is some
502 -- random number.
503 -> IO (FilePath, Handle)
504 openTempFile tmp_dir template
505 = openTempFile' "openTempFile" tmp_dir template False 0o600
506
507 -- | Like 'openTempFile', but opens the file in binary mode. See 'openBinaryFile' for more comments.
508 openBinaryTempFile :: FilePath -> String -> IO (FilePath, Handle)
509 openBinaryTempFile tmp_dir template
510 = openTempFile' "openBinaryTempFile" tmp_dir template True 0o600
511
512 -- | Like 'openTempFile', but uses the default file permissions
513 openTempFileWithDefaultPermissions :: FilePath -> String
514 -> IO (FilePath, Handle)
515 openTempFileWithDefaultPermissions tmp_dir template
516 = openTempFile' "openBinaryTempFile" tmp_dir template False 0o666
517
518 -- | Like 'openBinaryTempFile', but uses the default file permissions
519 openBinaryTempFileWithDefaultPermissions :: FilePath -> String
520 -> IO (FilePath, Handle)
521 openBinaryTempFileWithDefaultPermissions tmp_dir template
522 = openTempFile' "openBinaryTempFile" tmp_dir template True 0o666
523
524 openTempFile' :: String -> FilePath -> String -> Bool -> CMode
525 -> IO (FilePath, Handle)
526 openTempFile' loc tmp_dir template binary mode = do
527 pid <- c_getpid
528 findTempName pid
529 where
530 -- We split off the last extension, so we can use .foo.ext files
531 -- for temporary files (hidden on Unix OSes). Unfortunately we're
532 -- below filepath in the hierarchy here.
533 (prefix,suffix) =
534 case break (== '.') $ reverse template of
535 -- First case: template contains no '.'s. Just re-reverse it.
536 (rev_suffix, "") -> (reverse rev_suffix, "")
537 -- Second case: template contains at least one '.'. Strip the
538 -- dot from the prefix and prepend it to the suffix (if we don't
539 -- do this, the unique number will get added after the '.' and
540 -- thus be part of the extension, which is wrong.)
541 (rev_suffix, '.':rest) -> (reverse rest, '.':reverse rev_suffix)
542 -- Otherwise, something is wrong, because (break (== '.')) should
543 -- always return a pair with either the empty string or a string
544 -- beginning with '.' as the second component.
545 _ -> error "bug in System.IO.openTempFile"
546
547 #ifndef __NHC__
548 oflags1 = rw_flags .|. o_EXCL
549
550 binary_flags
551 | binary = o_BINARY
552 | otherwise = 0
553
554 oflags = oflags1 .|. binary_flags
555 #endif
556
557 #if defined(__NHC__)
558 findTempName x = do h <- openFile filepath ReadWriteMode
559 return (filepath, h)
560 #elif defined(__GLASGOW_HASKELL__)
561 findTempName x = do
562 fd <- withFilePath filepath $ \ f ->
563 c_open f oflags mode
564 if fd < 0
565 then do
566 errno <- getErrno
567 if errno == eEXIST
568 then findTempName (x+1)
569 else ioError (errnoToIOError loc errno Nothing (Just tmp_dir))
570 else do
571
572 (fD,fd_type) <- FD.mkFD fd ReadWriteMode Nothing{-no stat-}
573 False{-is_socket-}
574 True{-is_nonblock-}
575
576 h <- mkHandleFromFD fD fd_type filepath ReadWriteMode False{-set non-block-}
577 (Just localeEncoding)
578
579 return (filepath, h)
580 #else
581 h <- fdToHandle fd `onException` c_close fd
582 return (filepath, h)
583 #endif
584
585 where
586 filename = prefix ++ show x ++ suffix
587 filepath = tmp_dir `combine` filename
588
589 -- XXX bits copied from System.FilePath, since that's not available here
590 combine a b
591 | null b = a
592 | null a = b
593 | last a == pathSeparator = a ++ b
594 | otherwise = a ++ [pathSeparator] ++ b
595
596 #if __HUGS__
597 fdToHandle fd = openFd (fromIntegral fd) False ReadWriteMode binary
598 #endif
599
600 -- XXX Should use filepath library
601 pathSeparator :: Char
602 #ifdef mingw32_HOST_OS
603 pathSeparator = '\\'
604 #else
605 pathSeparator = '/'
606 #endif
607
608 #ifndef __NHC__
609 -- XXX Copied from GHC.Handle
610 std_flags, output_flags, rw_flags :: CInt
611 std_flags = o_NONBLOCK .|. o_NOCTTY
612 output_flags = std_flags .|. o_CREAT
613 rw_flags = output_flags .|. o_RDWR
614 #endif
615
616 #ifdef __NHC__
617 foreign import ccall "getpid" c_getpid :: IO Int
618 #endif
619
620 -- $locking
621 -- Implementations should enforce as far as possible, at least locally to the
622 -- Haskell process, multiple-reader single-writer locking on files.
623 -- That is, /there may either be many handles on the same file which manage input, or just one handle on the file which manages output/. If any
624 -- open or semi-closed handle is managing a file for output, no new
625 -- handle can be allocated for that file. If any open or semi-closed
626 -- handle is managing a file for input, new handles can only be allocated
627 -- if they do not manage output. Whether two files are the same is
628 -- implementation-dependent, but they should normally be the same if they
629 -- have the same absolute path name and neither has been renamed, for
630 -- example.
631 --
632 -- /Warning/: the 'readFile' operation holds a semi-closed handle on
633 -- the file until the entire contents of the file have been consumed.
634 -- It follows that an attempt to write to a file (using 'writeFile', for
635 -- example) that was earlier opened by 'readFile' will usually result in
636 -- failure with 'System.IO.Error.isAlreadyInUseError'.