553 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			553 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* f4create.c   (c)Copyright Sequiter Software Inc., 1988-1996.  All rights reserved. */
 | 
						|
 | 
						|
#include "d4all.h"
 | 
						|
 | 
						|
#ifdef __TURBOC__
 | 
						|
   #pragma hdrstop
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4TEMP
 | 
						|
   #include "t4test.h"
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4TRACK_FILES
 | 
						|
   extern unsigned int numFiles ;
 | 
						|
   extern int f4print ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4WINTEL
 | 
						|
   #ifndef S4IBMOS2
 | 
						|
      #ifndef __TURBOC__
 | 
						|
         #include <sys\locking.h>
 | 
						|
         #define S4LOCKING
 | 
						|
      #endif
 | 
						|
      #ifdef __ZTC__
 | 
						|
         #ifndef S4WINDOWS
 | 
						|
            extern int  errno ;
 | 
						|
         #endif
 | 
						|
      #endif
 | 
						|
      #ifdef _MSC_VER
 | 
						|
         #include <sys\types.h>
 | 
						|
         #include <sys\locking.h>
 | 
						|
      #endif
 | 
						|
   #endif
 | 
						|
   #include <sys\stat.h>
 | 
						|
   #include <share.h>
 | 
						|
#endif
 | 
						|
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
 | 
						|
#include <fcntl.h>
 | 
						|
 | 
						|
#ifndef S4WINDOWS
 | 
						|
   #include <errno.h>
 | 
						|
   #ifdef S4ERRNO
 | 
						|
      extern int errno ;
 | 
						|
   #endif
 | 
						|
#endif
 | 
						|
 | 
						|
/*
 | 
						|
**  file4createLow() generic outline:
 | 
						|
**
 | 
						|
**  - clear any postive error values
 | 
						|
**  - set read/write access flag (for create it is always both read and write)
 | 
						|
**  - set the shared flag based on CODE4::accessMode
 | 
						|
**    3 possible settings: OPEN4DENY_NONE, OPEN4DENY_WRITE, OPEN4DENY_RW.
 | 
						|
**    return failure if no the setting is invalid.
 | 
						|
**  - set the safety (open existing) flag based on CODE4::safety
 | 
						|
**  - determine if file exists
 | 
						|
**    if it does exist, ensure that nobody else has it open (exclusive access)
 | 
						|
**    many operating systems allow creates on open files, which result in
 | 
						|
**    failures for the other applications.  Avoid this for safety reasons.
 | 
						|
**  - physically attempt to create the file
 | 
						|
**  - return the result
 | 
						|
**
 | 
						|
**  Returns: 0 = success, r4noCreate = failure
 | 
						|
**
 | 
						|
**  Notes:
 | 
						|
**     This routine shouldn't generate a CodeBase error
 | 
						|
*/
 | 
						|
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
#ifdef S4UNIX
 | 
						|
static int file4createLow( FILE4 *file, CODE4 *c4, const char *name )
 | 
						|
{
 | 
						|
   int extraFlag, oflag, pmode ;
 | 
						|
   int rc = 0 ;
 | 
						|
   #ifdef S4NO_FLOCK
 | 
						|
      struct flock lck;
 | 
						|
 | 
						|
      lck.l_whence = SEEK_SET ;
 | 
						|
      lck.l_start  = 0 ;
 | 
						|
      lck.l_len = 1000000000 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   error4set( c4, 0 ) ;  /* clear positive error values */
 | 
						|
 | 
						|
   /*set to invalid by default, since not created yet.*/
 | 
						|
   file->hand = -1;
 | 
						|
 | 
						|
   /* first determine the basic access values */
 | 
						|
   oflag = (int)(O_CREAT | O_RDWR| O_EXCL) ;
 | 
						|
 | 
						|
   switch ( c4->accessMode )
 | 
						|
   {
 | 
						|
      case OPEN4DENY_NONE:
 | 
						|
         pmode = 0666 ;  /* Allow full read/write permission  */
 | 
						|
         break;
 | 
						|
      case OPEN4DENY_WRITE:
 | 
						|
         pmode = 0644 ;  /*Allow full read permission  */
 | 
						|
         break;
 | 
						|
      case OPEN4DENY_RW:
 | 
						|
         pmode = 0600 ;  /* Allow exclusive read/write permission  */
 | 
						|
         break;
 | 
						|
      default:
 | 
						|
         return r4noCreate;
 | 
						|
   }
 | 
						|
 | 
						|
   /*Check for files existence*/
 | 
						|
   file->hand = open(name, oflag, pmode) ;
 | 
						|
   if (file->hand<0)
 | 
						|
   {                        /*problem creating the file*/
 | 
						|
      if ( errno == EACCES )  /*If this is the error, we would have lost it on the next open*/
 | 
						|
      {
 | 
						|
         file->hand = -1 ;
 | 
						|
         return r4noCreate ;
 | 
						|
      }
 | 
						|
      file->hand = open(name, O_RDWR) ;
 | 
						|
      if (file->hand < 0)   /*Does the file not exist*/
 | 
						|
      {
 | 
						|
          file->hand = -1;
 | 
						|
          return r4noCreate;
 | 
						|
      }
 | 
						|
      else     /*file does exist*/
 | 
						|
         if ( !c4->safety )
 | 
						|
         {    /*overwrite file if no one else is using it*/
 | 
						|
            #ifndef S4NO_FLOCK
 | 
						|
               rc = flock (file->hand, LOCK_EX|LOCK_NB) ;
 | 
						|
            #else
 | 
						|
               lck.l_type = F_WRLCK ;
 | 
						|
               rc = fcntl(file->hand, F_GETLK, &lck ) ;
 | 
						|
            #endif
 | 
						|
            if (rc<0)
 | 
						|
            {   /*someone else is using it*/
 | 
						|
               close(file->hand);
 | 
						|
               file->hand = -1;
 | 
						|
               return r4noCreate;
 | 
						|
            }
 | 
						|
            else  /*no one is using it so kill it*/
 | 
						|
            {
 | 
						|
               #ifdef S4NO_CHSIZE
 | 
						|
                  ftruncate(file->hand, 0) ;
 | 
						|
               #else
 | 
						|
                  chsize(file->hand, 0) ;
 | 
						|
               #endif
 | 
						|
               #ifndef S4NO_FLOCK
 | 
						|
                  flock(file->hand,LOCK_UN);
 | 
						|
               #endif
 | 
						|
            }
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {    /*SInce the file exists, and we have safeties, we can't create*/
 | 
						|
            close(file->hand);
 | 
						|
            file->hand = -1;
 | 
						|
            return r4noCreate;
 | 
						|
         }
 | 
						|
    }
 | 
						|
 | 
						|
 /*  if ( file->hand < 0 )
 | 
						|
   {
 | 
						|
      file->hand = -1 ;
 | 
						|
      return r4noCreate ;
 | 
						|
   }*/
 | 
						|
 | 
						|
   switch ( c4->accessMode )
 | 
						|
   {
 | 
						|
      case OPEN4DENY_NONE:
 | 
						|
      case OPEN4DENY_WRITE:
 | 
						|
         #ifndef S4NO_FLOCK
 | 
						|
            rc = flock (file->hand, LOCK_SH|LOCK_NB) ;
 | 
						|
         #else
 | 
						|
            lck.l_type = F_RDLCK ;
 | 
						|
            rc = fcntl (file->hand, F_SETLK, &lck ) ;
 | 
						|
         #endif
 | 
						|
         break;
 | 
						|
      case OPEN4DENY_RW:
 | 
						|
         #ifndef S4NO_FLOCK
 | 
						|
            rc = flock (file->hand, LOCK_EX|LOCK_NB) ;
 | 
						|
         #else
 | 
						|
            lck.l_type = F_WRLCK ;
 | 
						|
            rc = fcntl (file->hand, F_SETLK, &lck ) ;
 | 
						|
         #endif
 | 
						|
         break;
 | 
						|
      default:
 | 
						|
         close(file->hand);
 | 
						|
         file->hand = -1;
 | 
						|
         return r4noCreate;
 | 
						|
   }
 | 
						|
 | 
						|
   if (rc!=0)
 | 
						|
      return r4noCreate ;
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#endif /* S4UNIX */
 | 
						|
 | 
						|
#ifdef S4WIN32
 | 
						|
static int file4createLow( FILE4 *file, CODE4 *c4, const char *name )
 | 
						|
{
 | 
						|
   int existHandle ;
 | 
						|
   DWORD fdwAccess, fdwShareMode, fdwCreate ;
 | 
						|
 | 
						|
   error4set( c4, 0 ) ;  /* clear positive error values */
 | 
						|
 | 
						|
   /* set to invalid by default, since not created yet */
 | 
						|
   file->hand = (int)INVALID_HANDLE_VALUE ;
 | 
						|
 | 
						|
   /* first determine the basic access values */
 | 
						|
   fdwAccess = GENERIC_WRITE | GENERIC_READ ;
 | 
						|
   #ifdef S4OFF_MULTI
 | 
						|
      #ifdef E4DEBUG
 | 
						|
         /* open in shared mode for debugging to allow other programs to examine */
 | 
						|
         fdwShareMode = FILE_SHARE_WRITE | FILE_SHARE_READ ;
 | 
						|
      #else
 | 
						|
         /* otherwise, if single-user, file should be opened exclusively */
 | 
						|
         fdwShareMode = 0 ;
 | 
						|
      #endif
 | 
						|
   #else
 | 
						|
      switch( c4->accessMode )
 | 
						|
      {
 | 
						|
         case OPEN4DENY_NONE:
 | 
						|
            fdwShareMode = FILE_SHARE_WRITE | FILE_SHARE_READ ;
 | 
						|
            break ;
 | 
						|
         case OPEN4DENY_WRITE:
 | 
						|
            fdwShareMode = FILE_SHARE_READ ;
 | 
						|
            break ;
 | 
						|
         case OPEN4DENY_RW:
 | 
						|
            fdwShareMode = 0 ;
 | 
						|
            break ;
 | 
						|
         default:
 | 
						|
            return r4noCreate ;
 | 
						|
      }
 | 
						|
   #endif  /* S4OFF_MULTI */
 | 
						|
   if ( c4->safety )
 | 
						|
      fdwCreate = CREATE_NEW ;
 | 
						|
   else
 | 
						|
      fdwCreate = CREATE_ALWAYS ;
 | 
						|
 | 
						|
   /* existHandle will be >= 0 if the file exists and is allowed access */
 | 
						|
   existHandle = access( name, 0 ) ;
 | 
						|
 | 
						|
   if ( existHandle >= 0 )   /* file exists and is available */
 | 
						|
   {
 | 
						|
      /* if safety is != 0, function will fall through since file
 | 
						|
         already exists */
 | 
						|
      if ( c4->safety == 0 ) /* ensure exclusive access, otherwise problems ensue */
 | 
						|
      {
 | 
						|
         file->hand = (int)CreateFile( name, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 ) ;
 | 
						|
         if ( file->hand == (int)INVALID_HANDLE_VALUE )
 | 
						|
         {
 | 
						|
            file->hand = -1 ;
 | 
						|
            return r4noCreate ;
 | 
						|
         }
 | 
						|
         CloseHandle( (HANDLE)file->hand ) ;
 | 
						|
         existHandle = -1 ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   if ( existHandle < 0 )  /* file doesn't exist, or exclusive access is available, so attempt create */
 | 
						|
      file->hand = (int)CreateFile( name, fdwAccess, fdwShareMode, 0, fdwCreate, FILE_ATTRIBUTE_NORMAL, 0 ) ;
 | 
						|
 | 
						|
   if ( file->hand == (int)INVALID_HANDLE_VALUE )
 | 
						|
   {
 | 
						|
      file->hand = -1 ;
 | 
						|
      return r4noCreate ;
 | 
						|
   }
 | 
						|
 | 
						|
   #ifdef S4MULTI_THREAD
 | 
						|
      InitializeCriticalSection( &file->critical4file ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#endif /* S4WIN32 */
 | 
						|
 | 
						|
#ifdef S4WIN16
 | 
						|
static int file4createLow( FILE4 *file, CODE4 *c4, const char *name )
 | 
						|
{
 | 
						|
   int existHandle, shmode, omode ;
 | 
						|
 | 
						|
   error4set( c4, 0 ) ;  /* clear positive error values */
 | 
						|
 | 
						|
   existHandle = access( name, 0 ) ;  /* if file doesn't exist, create */
 | 
						|
 | 
						|
   if ( existHandle != -1 )   /* file exists, see if open if not safety... */
 | 
						|
   {
 | 
						|
      if ( c4->safety == 0 )
 | 
						|
      {
 | 
						|
         file->hand = _lopen( name, OF_READWRITE | OF_SHARE_EXCLUSIVE ) ;
 | 
						|
         if ( file->hand < 0 )
 | 
						|
            return r4noCreate ;
 | 
						|
         _lclose( file->hand ) ;
 | 
						|
         existHandle = -1 ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   if ( existHandle < 0 )  /* if file doesn't exist, create */
 | 
						|
   {
 | 
						|
      /* do initial creation in exclusive mode */
 | 
						|
      file->hand = _lcreat( name, 0 ) ;   /* attr == 0 : read/write permission */
 | 
						|
 | 
						|
      if ( file->hand >= 0 )  /* now that file is created, move to regular r/w mode */
 | 
						|
      {
 | 
						|
         _lclose( file->hand ) ;
 | 
						|
         omode = OF_READWRITE ;
 | 
						|
         switch( c4->accessMode )
 | 
						|
         {
 | 
						|
            case OPEN4DENY_RW:
 | 
						|
               shmode = OF_SHARE_EXCLUSIVE ;
 | 
						|
               break ;
 | 
						|
            case OPEN4DENY_WRITE:
 | 
						|
               shmode = OF_SHARE_DENY_WRITE ;
 | 
						|
               break ;
 | 
						|
            case OPEN4DENY_NONE:
 | 
						|
               shmode = OF_SHARE_DENY_NONE ;
 | 
						|
               break ;
 | 
						|
            default:
 | 
						|
               file->hand = -1 ;
 | 
						|
               return r4noCreate ;
 | 
						|
         }
 | 
						|
         file->hand = _lopen( name, omode | shmode ) ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   if ( file->hand < 0 )
 | 
						|
      return r4noCreate ;
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#endif /* S4WIN16 */
 | 
						|
 | 
						|
/* now for all other instances */
 | 
						|
#ifdef S4WINTEL
 | 
						|
#ifndef S4WIN32
 | 
						|
#ifndef S4WIN16
 | 
						|
static int file4createLow( FILE4 *file, CODE4 *c4, const char *name )
 | 
						|
{
 | 
						|
   int extraFlag, oflag, pmode, shmode ;
 | 
						|
 | 
						|
   error4set( c4, 0 ) ;  /* clear positive error values */
 | 
						|
 | 
						|
   oflag = (int)( O_CREAT | O_TRUNC | O_BINARY | O_RDWR ) ;
 | 
						|
   pmode = (int)( S_IREAD  | S_IWRITE ) ;
 | 
						|
   if ( c4->safety )
 | 
						|
      extraFlag = O_EXCL ;
 | 
						|
   else
 | 
						|
      extraFlag = 0 ;
 | 
						|
 | 
						|
   /* ensure first that nobody else has access to the file */
 | 
						|
   file->hand = sopen( name, O_RDWR, SH_DENYRW, pmode ) ;
 | 
						|
   if ( file->hand < 0 )
 | 
						|
      switch ( errno )
 | 
						|
      {
 | 
						|
         case ENOENT:   /* file not found, so can create */
 | 
						|
            break ;
 | 
						|
         default:  /* access or misc. error, return failure */
 | 
						|
            return r4noCreate ;
 | 
						|
      }
 | 
						|
 | 
						|
   close( file->hand ) ;
 | 
						|
 | 
						|
   #ifdef S4OFF_MULTI
 | 
						|
      shmode = SH_DENYRW ;
 | 
						|
   #else
 | 
						|
      switch( c4->accessMode )
 | 
						|
      {
 | 
						|
         case OPEN4DENY_RW:
 | 
						|
            shmode = SH_DENYRW ;
 | 
						|
            break ;
 | 
						|
         case OPEN4DENY_WRITE:
 | 
						|
            shmode = SH_DENYWR ;
 | 
						|
            break ;
 | 
						|
         case OPEN4DENY_NONE:
 | 
						|
            shmode = SH_DENYNO ;
 | 
						|
            break ;
 | 
						|
         default:
 | 
						|
            file->hand = -1 ;
 | 
						|
            return r4noCreate ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   file->hand = sopen( name, extraFlag | oflag, shmode, pmode ) ;
 | 
						|
   if ( file->hand < 0 )
 | 
						|
      return r4noCreate ;
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#endif /* S4WINTEL */
 | 
						|
#endif /* S4WIN32 */
 | 
						|
#endif /* S4WIN16 */
 | 
						|
 | 
						|
int S4FUNCTION file4create( FILE4 *file, CODE4 *c4, S4CONST char *name, const int doAlloc )
 | 
						|
{
 | 
						|
   int rc, len ;
 | 
						|
 | 
						|
   #ifdef E4PARM_HIGH
 | 
						|
      if ( file == 0 || c4 == 0 )
 | 
						|
         return error4( c4, e4parm_null, E90602 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifndef S4OPTIMIZE_OFF
 | 
						|
      code4memStartMaxSet( c4, c4->memMaxPercent ) ;  /* start optimization if not enabled and not suspended */
 | 
						|
   #endif
 | 
						|
 | 
						|
   memset( (void *)file, 0, sizeof( FILE4 ) ) ;
 | 
						|
   file->codeBase = c4 ;
 | 
						|
   file->hand = -1 ;
 | 
						|
 | 
						|
   if ( error4code( c4 ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   if ( name == 0 )
 | 
						|
   {
 | 
						|
      rc = file4tempLow( file, c4, c4->createTemp ) ;
 | 
						|
      if ( rc == 0 )
 | 
						|
         return 0 ;
 | 
						|
   }
 | 
						|
   else
 | 
						|
      rc = file4createLow( file, c4, name ) ;
 | 
						|
 | 
						|
   #ifdef S4SERVER
 | 
						|
      if ( rc == r4noCreate )   /* free up any open unused file handles */
 | 
						|
      {
 | 
						|
         error4set( c4, 0 ) ;
 | 
						|
         rc = code4dataFileCloseAll( c4 ) ;
 | 
						|
         if ( rc < 0 )
 | 
						|
            return rc ;
 | 
						|
         if ( name == 0 )
 | 
						|
            return file4tempLow( file, c4, c4->createTemp ) ;
 | 
						|
         else
 | 
						|
            rc = file4createLow( file, c4, name ) ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( rc < 0 )
 | 
						|
      return rc ;
 | 
						|
 | 
						|
   if ( rc == r4noCreate )
 | 
						|
   {
 | 
						|
      if ( c4->errCreate )
 | 
						|
         return error4describe( c4, e4create, E90602, name, (char *) 0, (char *) 0 ) ;
 | 
						|
      error4set( c4, r4noCreate ) ;
 | 
						|
      return r4noCreate ;
 | 
						|
   }
 | 
						|
 | 
						|
   if ( doAlloc )
 | 
						|
   {
 | 
						|
      len = strlen(name) + 1 ;
 | 
						|
      file->nameBuf = (char *)u4allocEr( c4, (long)len ) ;
 | 
						|
      if ( file->nameBuf == 0 )
 | 
						|
      {
 | 
						|
         file4close( file ) ;
 | 
						|
         return e4memory ;
 | 
						|
      }
 | 
						|
      u4ncpy( file->nameBuf, name, (unsigned int)len ) ;
 | 
						|
      file->name = file->nameBuf ;
 | 
						|
      file->doAllocFree = 1 ;
 | 
						|
   }
 | 
						|
   else
 | 
						|
      file->name = name ;
 | 
						|
 | 
						|
   #ifndef S4OFF_MULTI
 | 
						|
      file->lowAccessMode = c4->accessMode ;
 | 
						|
   #endif
 | 
						|
   #ifndef S4OFF_OPTIMIZE
 | 
						|
      file->fileCreated = 1 ;
 | 
						|
   #endif
 | 
						|
   if ( c4->createTemp == 1 )
 | 
						|
      file->isTemp = 1 ;
 | 
						|
 | 
						|
   #ifdef S4TRACK_FILES
 | 
						|
      if ( f4print != -1 )
 | 
						|
      {
 | 
						|
          #ifdef S4WINDOWS
 | 
						|
             #ifdef S4TESTING
 | 
						|
                if ( mem4displayPtr == 0 )
 | 
						|
                   error4( 0, e4info, E50101 ) ;
 | 
						|
                d4display_str( mem4displayPtr, "\r\nfile created: ", 1 ) ;
 | 
						|
                d4display_str( mem4displayPtr, f4print, file->name ) ;
 | 
						|
             #else
 | 
						|
                u4writeErr( "file created: ", 1 ) ;
 | 
						|
                u4writeErr( file->name, 0 ) ;
 | 
						|
             #endif
 | 
						|
          #else
 | 
						|
             if ( f4print )
 | 
						|
                fprintf( stdprn, "\r\nfile created: %s", file->name ) ;
 | 
						|
             else
 | 
						|
                printf( "\r\nfile created: %s", file->name ) ;
 | 
						|
          #endif
 | 
						|
       }
 | 
						|
      numFiles++ ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 |