#line 778 "/home/travis/build/felix-lang/felix/src/packages/filesystem.fdoc"
  
  class Win32FileSystem
  {
    //------------------------------------------------------------
    // File access and create modes
    //------------------------------------------------------------
    pod type file_perm_t = "int" requires Posix_headers::fcntl_h;
    const _O_BINARY     : file_perm_t;
    const _O_RDONLY     : file_perm_t;
    const _O_WRONLY     : file_perm_t;
    const _O_RDWR       : file_perm_t;
    const _O_NONBLOCK   : file_perm_t;
    const _O_APPEND     : file_perm_t;
    const _O_CREAT      : file_perm_t;
    const _O_TRUNC      : file_perm_t;
    const _O_EXCL       : file_perm_t;
    const _O_SHLOCK     : file_perm_t;
    const _O_EXLOCK     : file_perm_t;
    const _O_NOFOLLOW   : file_perm_t;
    const _O_SYMLINK    : file_perm_t;
    const _O_EVTONLY    : file_perm_t;
    fun \& : file_perm_t * file_perm_t -> file_perm_t = "$1&$2";
    fun \|  : file_perm_t * file_perm_t -> file_perm_t = "$1|$2";
  
    //------------------------------------------------------------
    // File I/O functions
    //------------------------------------------------------------
    pod type posix_file = "int" requires Win32_headers::io_h;
    fun valid: posix_file -> bool = "$1 != -1";
    ctor int : posix_file = "$1";
    const fd0 : posix_file = "0";
    const fd1 : posix_file = "1";
    const fd2 : posix_file = "2";
  
    gen open: string * file_perm_t * Win32FileStat::mode_t -> posix_file = "_open($1.c_str(), $2, $3)";
    gen open: string * file_perm_t -> posix_file = "_open($1.c_str(), $2)";
  
    gen ropen: string -> posix_file = 'open($1.c_str(), _O_RDONLY | _O_BINARY,0)' requires Posix_headers::fcntl_h, Posix_headers::sys_stat_h;
    gen wopen: string -> posix_file = 'open($1.c_str(), _O_WRONLY  | _O_BINARY | _O_CREAT | _O_TRUNC, S_IRUSR | S_IWUSR)' requires Win32_headers::io_h, Posix_headers::sys_stat_h;
    gen rwopen: string -> posix_file = 'open($1.c_str(), _O_RDWR | _O_BINARY,0)' requires Win32_headers::io_h, Posix_headers::sys_stat_h;
    gen creat: string * Win32FileStat::mode_t-> posix_file = 'open($1.c_str(), _O_WRONLY | _O_BINARY | _O_CREAT | _O_TRUNC, $2)' requires Win32_headers::io_h, Posix_headers::sys_stat_h;
  
    gen close: posix_file -> int = "_close($1)";
    gen read: posix_file * &char * size -> size = "read($1, $2, $3)";
    gen write: posix_file * &char * size -> size = "write($1, $2, $3)";
  
    gen dup: posix_file -> posix_file = "dup($1)" requires Win32_headers::io_h;
    gen dup2: posix_file * posix_file -> posix_file = "dup2($1,$2)" requires Win32_headers::io_h;
    header piper_def = """
      struct _piper_hack { int i; int o; };
    """;
    body piper_def = """
      _piper_hack _piper() {
        _piper_hack p;
        pipe((int*)(void*)&p);
        return p;
      }
    """ requires Posix_headers::unistd_h;
    private cstruct _piper_hack { i:posix_file; o:posix_file; };
    private gen _piper: 1 -> _piper_hack requires piper_def;
    private fun _mkpair (x: _piper_hack) => x.i, x.o;
    gen pipe () => _mkpair #_piper;
  
    gen fdopen_input: posix_file ->  ifile = 'fdopen($1,"r")';
    gen fdopen_output: posix_file ->  ofile = 'fdopen($1,"w")';
  
    //------------------------------------------------------------
    // delete (unlink) a file
    //------------------------------------------------------------
    gen unlink_file: string -> int = "unlink($1.c_str())";
  
    //------------------------------------------------------------
    // rename a file
    //------------------------------------------------------------
    gen rename_file: string * string -> int = "rename($1.c_str(),$2.c_str())";
  
    //------------------------------------------------------------
    // copy a file, preserving last access and modification times
    // owner, group, and permissions
    //------------------------------------------------------------
    gen filecopy(src: string, dst: string) :  bool =
    {
      //eprintln$ "Copy " + src + " -> " + dst;
      if Env::getenv ("FLX_REPORT_FILECOPY") != "" do
        eprintln$ "[Win32FileSystem::filecopy] '" + src + "' -> '" + dst+ "'";
      done
  
      val now = Time::time(); // seconds
      var stat_buf: Win32FileStat::stat_t;
      if not Win32FileStat::stat (src, &stat_buf) do
        eprintln$ "Can't stat source file " + src;
        return false;
      done;
      val permissions = Win32FileStat::file_perm$ Win32FileStat::raw_mode (&stat_buf);
      val last_modification = Win32FileStat::filetime(src);
      var fsrc = open (src,_O_RDONLY \| _O_BINARY);
      if not valid fsrc do
        eprintln$ " Bad src file in Filesystem::filecopy " + src;
        return false;
      done
      var fdst = open (dst,_O_WRONLY \| _O_BINARY \| _O_CREAT \| _O_TRUNC, permissions);
      if not valid fdst do
        eprintln$ " Bad dst file in Filesystem::filecopy " + dst + ", Error: " + str errno + "=" + #strerror;
        return false;
      done
      bsiz := size (4096 * 1024); // 4 Meg
      var buffer = C_hack::cast[&char] (C_hack::malloc(bsiz)); // 4 MEG
      var bread = read (fsrc, buffer, bsiz);
      while bread > size 0 do
        var bwrite = write (fdst,buffer,bread);
        if bread != bwrite do
          if bwrite.int == -1 do
            eprintln$
              "Dest des = " + str fdst.int+ " "+
              "Attempt to copy " + str bread + " bytes from " + src + " to " + dst +
              " failed with errno = " + str errno + ": " + strerror()
            ;
          else
            eprintln$
              "Attempt to copy " + str bread + " bytes from " + src + " to " + dst +
              " failed with " +  str bwrite + " only copied!"
            ;
          done
        done
        bread = read (fsrc, buffer, bsiz);
      done
      var res = close fsrc;
      if res != 0 do
        eprintln$ "In filesystem::filecopy close on src " + src + " failed: " + str errno + "=" + #strerror;
      done
      res = close fdst;
      if res != 0 do
        eprintln$ "In filesystem::filecopy close on dst " + dst + " failed: " + str errno + "=" + #strerror;
      done
      C_hack::ignore(Win32FileStat::utime(dst,now,last_modification));
      C_hack::free(C_hack::cast[address] buffer);
      return true;
    }
  
  
    //------------------------------------------------------------
    // generate temporary file name
    //------------------------------------------------------------
    body tmpnam = """
      std::string flx_tmpnam() {
        char tmpn[] = "/tmp/flx_XXXXXX";
        close(mkstemp(tmpn));
        return std::string(tmpn);
       }
    """ requires header '#include <unistd.h>';
  
    gen tmp_filename: 1 -> string = "flx_tmpnam()" requires tmpnam;
  
  }