Patch title: Release 81 bulk changes
Abstract:
File: /pliant/language/os/file.c
Key:
    Removed line
    Added line
// Copyright  Hubert Tonneau  hubert.tonneau@pliant.cx
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// version 2 along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

/*
abstract
  text "Entry level file functions access"
doc
  text "It's used by Pliant to load the modules, because at the very early stage, the 'Stream' data type is not available."
*/


#if defined(_LINUX_API_) || defined(_POSIX_API_)
  #ifdef _POSIX_API_
    #include <fcntl.h>
  #endif

  FUNCTION Any file_open(struct Str *name,Int mode) {
    Char unixname[256]; Int handle;
    memory_copy(name->chars,unixname,minimum(Str_len(name),255));
    unixname[minimum(Str_len(name),255)]='\0';
    handle=open(unixname,(mode&file_in_out)==file_in_out ? O_RDWR|O_CREAT : mode&file_in ? O_RDONLY : O_WRONLY|O_CREAT|O_TRUNC, 0666);
    return (handle>=0 ? (Any)handle : (Any)-1); }


  FUNCTION Int file_read(Any handle,Address buffer,Int size) {
    return (Int)read((Int)handle,buffer,size); }


  FUNCTION Int file_write(Any handle,Address buffer,Int size) {
    return (Int)write((Int)handle,buffer,size); }


  FUNCTION Err file_close(Any handle) {
    return close((Int)handle); }

#endif


#ifdef _WIN32_API_

  FUNCTION Any file_open(struct Str *name,Int mode) {
    Char ntname[256]; Int i;
    HANDLE handle;
    for(i=0; i<minimum(Str_len(name),255); i++)
      ntname[i]=(name->chars[i]!='/' ? name->chars[i] : '\\');
    ntname[i]='\0';
    handle=CreateFile(
      ntname,
      (mode&file_in ? GENERIC_READ : 0)|(mode&file_out ? GENERIC_WRITE : 0),
      FILE_SHARE_READ|FILE_SHARE_WRITE,
      null,
      ((mode&file_in_out)==file_in_out ? OPEN_ALWAYS : (mode&file_out ? CREATE_ALWAYS : OPEN_EXISTING)),
      FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,
      null );
    return ((Int)handle>=0 ? (Any)handle : (Any)-1); }


  FUNCTION Int file_read(Any handle,Address buffer,Int size) {
    DWORD red;
    if(!ReadFile((HANDLE)handle,buffer,(DWORD)size,&red,null)) red=0L;
    return (Int)red; }


  FUNCTION Int file_write(Any handle,Address buffer,Int size) {
    DWORD written;
    if(!WriteFile((HANDLE)handle,buffer,(DWORD)size,&written,null)) return 0;
    return (Int)written; }


  FUNCTION Err file_close(Any handle) {
    return !CloseHandle((HANDLE)handle); }

#endif


#ifdef _OS2_API_

  FUNCTION Any file_open(struct Str *name,Int mode) {
    Char os2name[256]; Int i;
    HFILE handle; uInt32 openflag;
    Bool firsttime=true;
    Err err; uInt32 action; LONG add; ULONG nb;
    for(i=0; i<minimum(Str_len(name),255); i++)
      os2name[i]=(name->chars[i]!='/' ? name->chars[i] : '\\');
    os2name[i]='\0';
    switch(mode&file_in_out) {
      case file_in: openflag=OPEN_ACTION_FAIL_IF_NEW|OPEN_ACTION_OPEN_IF_EXISTS; break;
      case file_out: openflag=OPEN_ACTION_CREATE_IF_NEW|OPEN_ACTION_REPLACE_IF_EXISTS; break;
      case file_in_out: openflag=OPEN_ACTION_CREATE_IF_NEW|OPEN_ACTION_OPEN_IF_EXISTS; break;
      default: openflag=0; }
    retry:
    err=DosOpen((PSZ)os2name,&handle,&action,0L,FILE_NORMAL,openflag,
                OPEN_FLAGS_SEQUENTIAL|
                OPEN_SHARE_DENYNONE|
                ((mode&file_in_out)==file_in_out ? OPEN_ACCESS_READWRITE : (mode&file_in ? OPEN_ACCESS_READONLY : OPEN_ACCESS_WRITEONLY)),
                null);
    if(err==ERROR_TOO_MANY_OPEN_FILES && firsttime) {
      add=5; DosSetRelMaxFH(&add,&nb);
      firsttime=false; goto retry; }
    return (!err ? (Any)handle : (Any)-1); }


  FUNCTION Int file_read(Any handle,Address buffer,Int size) {
    ULONG red;
    if(DosRead((HFILE)handle,buffer,(ULONG)size,&red)) red=0L;
    return (Int)red; }


  FUNCTION Int file_write(Any handle,Address buffer,Int size) {
    ULONG written;
    if(DosWrite((HFILE)handle,buffer,(ULONG)size,&written)) written=0L;
    return (Int)written; }


  FUNCTION Err file_close(Any handle) {
    return DosClose((HFILE)handle); }

#endif