/* 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 #define S4LOCKING #endif #ifdef __ZTC__ #ifndef S4WINDOWS extern int errno ; #endif #endif #ifdef _MSC_VER #include #include #endif #endif #include #include #endif /* */ /* */ /* */ #include #ifndef S4WINDOWS #include #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 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 ; }