adding to GHC/win32 Handle operations support of Unicode filenamesand files larger than 4 GB

Simon Marlow simonmar at
Wed Nov 23 06:22:02 EST 2005

This sounds like a good idea to me.

As far as possible, we should keep the platform-dependence restricted to
the implementation of one module (System.Posix.Internals will do, even
though this isn't really POSIX any more).  So System.Posix.Internals
exports the CFilePath/CFileOffset types, and the foreign functions that
operate on them.

Alternatively (and perhaps this is better), we could hide the difference
even further, and provide functions like

  rmDir :: FilePath -> IO CInt

in System.Posix.Internals.  Similarly for functions that operate on
COff, they would take/return Integer (eg. we already have

As regards whether to use feature tests or just #ifdef mingw32_HOST_OS,
in general feature tests are the right thing, but sometimes it doesn't
buy you very much when there is (and always will be) only one platform
that has some particular quirk.  Writing a bunch of autoconf code that
would, if we're lucky, handle properly the case when some future version
of Windows removes the quirk, is not a good use of developer time.
Furthermore, Windows hardly ever changes APIs, they just add new ones.
So I don't see occasional use of #ifdef mingw32_HOST_OS as a big deal.
It's more important to organise the codebase and make sure all the
#ifdefs are behind suitable abstractions.


On 21 November 2005 12:01, Bulat Ziganshin wrote:

> Simon, what you will say about the following plan?
> ghc/win32 currently don't support operations with files with Unicode
> filenames, nor it can tell/seek in files for positions larger than 4
> GB. it is because Unix-compatible functions open/fstat/tell/... that
> is supported in Mingw32 works only with "char[]" for filenames and
> off_t (which is 32 bit) for file sizes/positions
> half year ago i discussed with Simon Marlow how support for unicode
> names and large files can be added to GHC. now i implemented my own
> library for such files, and got an idea how this can incorporated to
> GHC with minimal efforts:
> GHC currently uses CString type to represent C-land filenames and COff
> type to represent C-land fileseizes/positions. We need to
> systematically change these usages to CFilePath and CFileOffset,
> respectively, defined as follows:
> #ifdef mingw32_HOST_OS
> type CFilePath = LPCTSTR
> type CFileOffset = Int64
> withCFilePath = withTString
> peekCFilePath = peekTString
> #else
> type CFilePath = CString
> type CFileOffset = COff
> withCFilePath = withCString
> peekCFilePath = peekCString
> #endif
> and of course change using of withCString/peekCString, where it is
> applied to filenames, to withCFilePath/peekCFilePath (this will touch
> modules System.Posix.Internals, System.Directory, GHC.Handle)
> the last change needed is to conditionally define all "c_*" functions
> in System.Posix.Internals, whose types contain references to filenames
> or offsets:
> #ifdef mingw32_HOST_OS
> foreign import ccall unsafe "HsBase.h _wrmdir"
>    c_rmdir :: CFilePath -> IO CInt
> ....
> #else
> foreign import ccall unsafe "HsBase.h rmdir"
>    c_rmdir :: CFilePath -> IO CInt
> ....
> #endif
> (note that actual C function used is _wrmdir for Windows and rmdir for
> Unix). of course, all such functions defined in HsBase.h, also need to
> be defined conditionally, like:
> #ifdef mingw32_HOST_OS
> INLINE time_t __hscore_st_mtime ( struct _stati64* st ) { return
> st->st_mtime; } #else
> INLINE time_t __hscore_st_mtime ( struct stat* st ) { return
> st->st_mtime; } #endif
> That's all! of course, this will broke compatibility with current
> programs which directly uses these c_* functions (c_open, c_lseek,
> c_stat and 
> so on). this may be issue for some libs. are someone really use these
> functions??? of course, we can go in another, fully
> backward-compatible way, by adding some "f_*" functions and changing
> high-level modules to work with these functions

More information about the Glasgow-haskell-users mailing list