/* f4open.c   (c)Copyright Sequiter Software Inc., 1990-1994.  All rights reserved. */

#include "d4all.h"
#ifndef S4UNIX
#ifdef __TURBOC__
#pragma hdrstop
#endif
#endif

#ifdef S4TEMP
#include "t4test.h"
#endif

#include <time.h>

#ifndef S4UNIX
#ifndef S4IBMOS2
#ifndef __TURBOC__
#include <sys\locking.h>
#define S4LOCKING
#endif
#ifdef __ZTC__
extern int  errno ;
#endif
#ifdef _MSC_VER
#include <sys\locking.h>
#endif
#ifdef __TURBOC__
/*      extern int cdecl errno ; */
#endif

#include <dos.h>
#endif
#include <sys\types.h>
#include <sys\stat.h>
#include <share.h>
#endif

#include <fcntl.h>
#include <errno.h>

#ifndef S4WIN32
#ifndef S4WINDOWS
#ifndef S4OS2
#ifdef __TURBOC__
#define S4USE_CHMOD
#endif
#ifdef _MSC_VER
#define S4USE_CHMOD
#endif
#endif
#endif
#endif

#ifdef S4ERRNO
extern int errno ;
#endif

int S4FUNCTION file4open( FILE4 *file, CODE4 *code_base, char *name, int do_alloc )
{
  int oflag, len ;
#ifdef _MSC_VER
  unsigned attribute ;
#endif
#ifdef S4UNIX
#ifdef S4MACINTOSH
  char MACname[128] ;
  FSSpec MACfile ;
#else
  int pmode ;
#endif
#endif
#ifdef S4WIN32     /* NT defaults */
  DWORD fdwAccess ;
  DWORD fdwShareMode ;
#endif

#ifdef S4DEBUG
  if ( file == 0 || code_base == 0 || name == 0 )
    e4severe( e4parm, E4_F4OPEN ) ;
#endif
  if ( code_base->error_code < 0 )
    return -1 ;

  memset( (void *)file, 0, sizeof( FILE4 ) ) ;
  file->code_base = code_base ;
  file->hand = -1 ;

  code_base->error_code = 0 ;

#ifdef S4UNIX
  if ( code_base->read_only == 1 )
  {
    file->is_read_only = 1 ;
    oflag = (int)O_RDONLY ;
  }
  else
    oflag = (int)O_RDWR ;

#ifdef S4MACINTOSH
  memcpy( MACname, name, sizeof(MACname) ) ;
  CtoPstr( (char *)MACname ) ;  /* convert C string to Pascal string */

  if ( FSMakeFSSpec( 0, 0, MACname, &MACfile ) == fnfErr ) /* initialize 'FFSpec' */
    if ( file->code_base->open_error )
      return e4describe( file->code_base, e4open, E4_CREATE_FIL, name, (char *) 0 ) ;
    else
    {
      code_base->error_code = r4no_open ;
      return r4no_open ;
    }
  if ( code_base->exclusive )
    FSpOpenDF( &MACfile, fsCurPerm, (short *)&file->hand ) ;
  else
    FSpOpenDF( &MACfile, fsRdWrShPerm, (short *)&file->hand ) ;
#else
  if ( code_base->exclusive )
    pmode = 0600 ;  /* Allow exclusive read/write permission  */
  else
    pmode = 0666 ;  /* Allow full read/write permission  */

  file->hand = open( name, oflag , pmode ) ;
#endif
#else
  /* check the file's dos read only attrib */
#ifdef S4USE_CHMOD
  errno = 0 ;
#ifdef __TURBOC__
  if ( _A_RDONLY & _chmod( name, 0 ) )
#endif
#ifdef _MSC_VER
    _dos_getfileattr( name, &attribute ) ;
  if (_A_RDONLY & attribute )
#endif
  {
    if ( errno == ENOENT )  /* file doesn't exist */
    {
      file->hand = -1 ;
      if ( file->code_base->open_error )
        return e4describe( file->code_base, e4open, E4_CREATE_FIL, name, (char *) 0 ) ;
      else
      {
        code_base->error_code = r4no_open ;
        return r4no_open ;
      }
    }
    file->is_read_only = 1 ;
    file->is_exclusive = 1 ;  /* can at least emulate it */
#ifdef S4WINDOWS
    oflag = (int)OF_READ ;
#else
    oflag = (int)(O_BINARY | O_RDONLY) ;
#endif
  }
else
{
#endif
  if ( code_base->read_only == 1 )
  {
    file->is_read_only = 1 ;
#ifdef S4WIN32
    fdwAccess = GENERIC_READ ;
#else
#ifdef S4WINDOWS
    oflag = (int)OF_READ ;
#else
    oflag = (int)(O_BINARY | O_RDONLY) ;
#endif
#endif
  }
  else
  {
#ifdef S4WIN32
    fdwAccess = GENERIC_WRITE | GENERIC_READ ;
#else
#ifdef S4WINDOWS
    oflag = (int)OF_READWRITE ;
#else
    oflag = (int)(O_BINARY | O_RDWR) ;
#endif
#endif
  }
#ifdef S4USE_CHMOD
}
#endif

#ifdef S4WIN32
if ( code_base->exclusive )
  fdwShareMode = 0 ;
else
fdwShareMode = FILE_SHARE_WRITE | FILE_SHARE_READ ;
file->hand = (int) CreateFile( name, fdwAccess, fdwShareMode, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 ) ;
#else
#ifdef S4WINDOWS
if ( code_base->exclusive )
  oflag |= (int)OF_SHARE_EXCLUSIVE ;
else
oflag |= (int)OF_SHARE_DENY_NONE ;
file->hand = _lopen( name, oflag ) ;
#else
if ( code_base->exclusive )
  file->hand = sopen( name, oflag, SH_DENYRW, 0 ) ;
else
file->hand = sopen( name, oflag , SH_DENYNO, 0 ) ;
#endif
#endif
#endif

#ifdef S4MACINTOSH
if ( file->hand <= 0 )
#else
#ifdef S4WIN32
  if ( file->hand == (int)INVALID_HANDLE_VALUE )
#else
  if ( file->hand < 0 )
#endif
#endif
{
#ifdef S4WIN32
  //file->hand = GetLastError() ;
#endif
  if ( file->code_base->open_error )
    return e4describe( file->code_base, e4open, E4_CREATE_FIL, name, (char *) 0 ) ;
  else
  {
    code_base->error_code = r4no_open ;
    return r4no_open ;
  }
}

if ( do_alloc )
{
  len = strlen(name) + 1 ;
  file->name = (char *)u4alloc_free( code_base, len ) ;
  if ( file->name == 0 )
  {
    file4close( file ) ;
    return e4( file->code_base, e4memory, 0 ) ;
  }
  file->do_alloc_free = 1 ;
  u4ncpy( file->name, name, (unsigned) len ) ;
}
else
file->name = name ;

file->is_exclusive = (char) code_base->exclusive ;
file->file_created = 1 ;
return 0 ;
}

int S4FUNCTION file4open_test( FILE4 *f4 )
{
  return f4->hand >= 0 ;
}