Files
harbour-core/harbour/contrib/hbmemio/memio.c
Przemyslaw Czerpak 4bebbd6ac3 2011-06-09 15:31 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/include/hbapifs.h
  * harbour/src/rtl/filesys.c
    % removed unnecessary PID setting in POSIX file lock function.
    + added new C function:
         int hb_fsLockTest( HB_FHANDLE hFileHandle, HB_FOFFSET nStart,
                            HB_FOFFSET nLength, HB_USHORT uiMode );
      It allows to test file range lock status.
      It returns -1 on error, 0 when lock can be set and value greater
      then 0 if part of given range is locked by other process. In POSIX
      systems this value is PID of current lock owner. In other systems
      it's always 1.
      In uiMode only FLX_SHARED bit is significant.

  * harbour/include/hbapifs.h
  * harbour/src/rtl/filebuf.c
    + added new C function:
         int hb_fileLockTest( PHB_FILE pFile, HB_FOFFSET nStart,
                              HB_FOFFSET nLen, int iType );
      It's redirected to hb_fsLockTest()

  * harbour/contrib/hbnetio/netio.h
  * harbour/contrib/hbnetio/netiocli.c
  * harbour/contrib/hbnetio/netiosrv.c
  * harbour/contrib/hbmemio/memio.c
    + implemented hb_fileLockTest() low level code

  * harbour/include/dbinfo.ch
    + added DBI_LOCKTEST

  * harbour/src/rdd/dbf1.c
    % small code simplification
    + implemented DBI_LOCKTEST
         dbInfo( DBI_LOCKTEST [, <nRecNo> ] ) -> <nStatus>
      returns corresponding results to C level hb_fsLockTest() function.
      If current workarea is already locked then 0 is returned.
      If low level FS is located on POSIX system (accessed directly or by
      HBNETIO) then value greater then 0 is PID of current lock owner.
      If the lock is hold by aliased area or other thread of calling
      process then <nStatus> is current PID. In Other systems 1 is returned
      when lock cannot be set in current workarea.
      If <nRecNo> is given then the test is for RLOCK() otherwise FLOCK()
      operation.
2011-06-09 13:32:19 +00:00

897 lines
23 KiB
C

/*
* $Id$
*/
/*
* Harbour Project source code:
* Memory file system
* I/O driver for Memory file system
*
* Copyright 2009 Mindaugas Kavaliauskas <dbtopas at dbtopas.lt>
* www - http://harbour-project.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* 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
* along with this software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
*
* As a special exception, the Harbour Project gives permission for
* additional uses of the text contained in its release of Harbour.
*
* The exception is that, if you link the Harbour libraries with other
* files to produce an executable, this does not by itself cause the
* resulting executable to be covered by the GNU General Public License.
* Your use of that executable is in no way restricted on account of
* linking the Harbour library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the Harbour
* Project under the name Harbour. If you copy code from other
* Harbour Project or Free Software Foundation releases into a copy of
* Harbour, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for Harbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
*/
/* this has to be declared before hbapifs.h is included */
#define _HB_FILE_IMPLEMENTATION_
#include "hbapi.h"
#include "hbapifs.h"
#include "hbapierr.h"
#include "hbthread.h"
#include "hbvm.h"
#include "hbinit.h"
/******************************************************
*
* Memory file system
*
*******************************************************/
/* change this define for public hb_memfs*() API */
#ifdef HB_MEMFS_PUBLIC_API
#define HB_MEMFS_EXPORT
#else
#define HB_MEMFS_EXPORT static
#endif
#define HB_MEMFS_INITSIZE 16
/* File access flags */
#define FOX_READ 1
#define FOX_WRITE 2
#define FOX_READWRITE 3
/* File sharing flags */
#define FOX_DENYNONE 0
#define FOX_DENYREAD 16
#define FOX_DENYWRITE 32
#define FOX_EXCLUSIVE 48
#define FOX_DENYFLAGS 48
typedef struct _HB_MEMFS_INODE
{
HB_FOFFSET llSize;
HB_FOFFSET llAlloc;
char * pData;
char * szName;
unsigned int uiCount;
unsigned int uiCountRead, uiCountWrite;
HB_USHORT uiDeny;
} HB_MEMFS_INODE, * PHB_MEMFS_INODE;
typedef struct _HB_MEMFS_FILE
{
PHB_MEMFS_INODE pInode;
HB_FOFFSET llPos;
HB_USHORT uiFlags;
} HB_MEMFS_FILE, * PHB_MEMFS_FILE;
typedef struct _HB_MEMFS_FS
{
HB_ULONG ulInodeCount;
HB_ULONG ulInodeAlloc;
PHB_MEMFS_INODE * pInodes;
HB_ULONG ulFileAlloc;
HB_ULONG ulFileLast;
PHB_MEMFS_FILE * pFiles;
} HB_MEMFS_FS, * PHB_MEMFS_FS;
static HB_MEMFS_FS s_fs;
static HB_ERRCODE s_error;
static HB_CRITICAL_NEW( s_mtx );
#define HB_MEMFSMT_LOCK hb_threadEnterCriticalSection( &s_mtx );
#define HB_MEMFSMT_UNLOCK hb_threadLeaveCriticalSection( &s_mtx );
static void memfsInodeFree( PHB_MEMFS_INODE pInode );
static void memfsExit( void * cargo )
{
HB_ULONG ul;
HB_SYMBOL_UNUSED( cargo );
for( ul = 0; ul < s_fs.ulFileAlloc; ul++ )
{
if( s_fs.pFiles[ ul ] )
hb_xfree( s_fs.pFiles[ ul ] );
}
hb_xfree( s_fs.pFiles );
for( ul = 0; ul < s_fs.ulInodeCount; ul++ )
{
memfsInodeFree( s_fs.pInodes[ ul ] );
}
hb_xfree( s_fs.pInodes );
}
static void memfsInit( void )
{
/* HB_CRITICAL_INIT( s_mtx ); */
s_error = 0;
s_fs.ulInodeCount = 0;
s_fs.ulInodeAlloc = HB_MEMFS_INITSIZE;
s_fs.pInodes = ( PHB_MEMFS_INODE * ) hb_xgrab( sizeof( PHB_MEMFS_INODE ) * s_fs.ulInodeAlloc );
s_fs.ulFileAlloc = HB_MEMFS_INITSIZE;
s_fs.pFiles = ( PHB_MEMFS_FILE * ) hb_xgrab( sizeof( PHB_MEMFS_FILE ) * s_fs.ulFileAlloc );
memset( s_fs.pFiles, 0, sizeof( PHB_MEMFS_FILE ) * s_fs.ulFileAlloc );
s_fs.ulFileLast = 0;
hb_vmAtQuit( memfsExit, NULL );
}
/* Note: returns 1 based index! */
static HB_ULONG memfsInodeFind( const char * szName, HB_ULONG * pulPos )
{
HB_ULONG ulLeft, ulRight, ulMiddle;
int i;
ulLeft = 0;
ulRight = s_fs.ulInodeCount;
while( ulLeft < ulRight )
{
ulMiddle = ( ulLeft + ulRight ) >> 1;
i = strcmp( szName, s_fs.pInodes[ ulMiddle ]->szName );
if( i == 0 )
return ulMiddle + 1;
else if( i < 0 )
ulRight = ulMiddle;
else
ulLeft = ulMiddle + 1;
}
if( pulPos )
*pulPos = ulLeft;
return 0;
}
static PHB_MEMFS_INODE memfsInodeAlloc( const char* szName )
{
PHB_MEMFS_INODE pInode = ( PHB_MEMFS_INODE ) hb_xgrab( sizeof( HB_MEMFS_INODE ) );
HB_ULONG ulInode = 0;
pInode->llSize = 0;
pInode->llAlloc = HB_MEMFS_INITSIZE;
pInode->pData = ( char * ) hb_xgrab( ( HB_ULONG ) pInode->llAlloc );
memset( pInode->pData, 0, ( HB_SIZE ) pInode->llAlloc );
pInode->szName = hb_strdup( szName );
pInode->uiCount = 1;
pInode->uiCountRead = pInode->uiCountWrite = 0;
pInode->uiDeny = 0;
/* Insert into inode array. Inode should not exist!!! */
if( s_fs.ulInodeCount >= s_fs.ulInodeAlloc )
{
s_fs.ulInodeAlloc += s_fs.ulInodeAlloc >> 1;
s_fs.pInodes = ( PHB_MEMFS_INODE * ) hb_xrealloc( s_fs.pInodes, s_fs.ulInodeAlloc * sizeof( PHB_MEMFS_INODE ) );
}
if( memfsInodeFind( szName, &ulInode ) )
{
hb_errInternal( 9999, "memfsInodeAlloc: Inode already exists", NULL, NULL );
return NULL;
}
if( ulInode < s_fs.ulInodeCount )
{
memmove( s_fs.pInodes + ulInode + 1, s_fs.pInodes + ulInode, ( s_fs.ulInodeCount - ulInode ) * sizeof( PHB_MEMFS_INODE ) );
}
s_fs.pInodes[ ulInode ] = pInode;
s_fs.ulInodeCount++;
return pInode;
}
static void memfsInodeFree( PHB_MEMFS_INODE pInode )
{
hb_xfree( pInode->pData );
hb_xfree( pInode->szName );
hb_xfree( pInode );
}
static PHB_MEMFS_FILE memfsFileAlloc( PHB_MEMFS_INODE pInode )
{
PHB_MEMFS_FILE pFile = ( PHB_MEMFS_FILE ) hb_xgrab( sizeof( HB_MEMFS_FILE ) );
pFile->pInode = pInode;
pFile->llPos = 0;
pInode->uiCount++;
return pFile;
}
static PHB_MEMFS_FILE memfsHandleToFile( HB_FHANDLE hFile )
{
if( hFile == FS_ERROR || ( HB_ULONG ) hFile == 0 || ( HB_ULONG ) hFile > s_fs.ulFileAlloc || s_fs.pFiles[ ( HB_ULONG ) hFile - 1 ] == NULL )
{
/* hb_errInternal( 9999, "memfsHandleToFile: Invalid file handle", NULL, NULL ); */
return NULL;
}
else
return s_fs.pFiles[ ( HB_ULONG ) hFile - 1 ];
}
static HB_FHANDLE memfsHandleAlloc( PHB_MEMFS_FILE pFile )
{
HB_ULONG ul;
/* This allocation will help to avoid reallocation of just released file handle. */
for( ul = s_fs.ulFileLast; ul < s_fs.ulFileAlloc; ul++ )
{
if( ! s_fs.pFiles[ ul ] )
{
s_fs.pFiles[ ul ] = pFile;
s_fs.ulFileLast = ul + 1;
return ( HB_FHANDLE ) ( ul + 1 );
}
}
for( ul = 0; ul < s_fs.ulFileLast; ul++ )
{
if( ! s_fs.pFiles[ ul ] )
{
s_fs.pFiles[ ul ] = pFile;
s_fs.ulFileLast = ul + 1;
return ( HB_FHANDLE ) ( ul + 1 );
}
}
s_fs.pFiles = ( PHB_MEMFS_FILE * ) hb_xrealloc( s_fs.pFiles, ( s_fs.ulFileAlloc << 1 ) * sizeof( PHB_MEMFS_FILE ) );
memset( s_fs.pFiles + s_fs.ulFileAlloc, 0, s_fs.ulFileAlloc * sizeof( PHB_MEMFS_FILE ) );
ul = s_fs.ulFileAlloc;
s_fs.ulFileAlloc <<= 1;
s_fs.pFiles[ ul ] = pFile;
s_fs.ulFileLast = ul + 1;
return ( HB_FHANDLE ) ( ul + 1 );
}
/* ======== Public Memory FS functions ======== */
HB_MEMFS_EXPORT HB_ERRCODE hb_memfsError( void )
{
return s_error;
}
HB_MEMFS_EXPORT HB_BOOL hb_memfsFileExists( const char * szName )
{
HB_BOOL bRet;
HB_MEMFSMT_LOCK
bRet = memfsInodeFind( szName, NULL ) != 0;
HB_MEMFSMT_UNLOCK
return bRet;
}
HB_MEMFS_EXPORT HB_BOOL hb_memfsDelete( const char * szName )
{
PHB_MEMFS_INODE pInode;
HB_ULONG ulFile;
HB_MEMFSMT_LOCK
if( ( ulFile = memfsInodeFind( szName, NULL ) ) == 0 )
{
HB_MEMFSMT_UNLOCK
return HB_FALSE;
}
pInode = s_fs.pInodes[ ulFile - 1 ];
if( ulFile < s_fs.ulInodeCount )
memmove( s_fs.pInodes + ulFile - 1, s_fs.pInodes + ulFile, ( s_fs.ulInodeCount - ulFile ) * sizeof( PHB_MEMFS_INODE ) );
s_fs.ulInodeCount--;
if( --pInode->uiCount == 0 )
memfsInodeFree( pInode );
HB_MEMFSMT_UNLOCK
return HB_TRUE;
}
HB_MEMFS_EXPORT HB_BOOL hb_memfsRename( const char * szName, const char * szNewName )
{
HB_ULONG ulInode;
HB_MEMFSMT_LOCK
if( ( ulInode = memfsInodeFind( szName, NULL ) ) == 0 )
{
HB_MEMFSMT_UNLOCK
/* File not found */
return HB_FALSE;
}
if( memfsInodeFind( szNewName, NULL ) )
{
HB_MEMFSMT_UNLOCK
/* File already exists */
return HB_FALSE;
}
hb_xfree( s_fs.pInodes[ ulInode - 1 ]->szName );
s_fs.pInodes[ ulInode - 1 ]->szName = hb_strdup( szNewName );
HB_MEMFSMT_UNLOCK
return HB_TRUE;
}
HB_MEMFS_EXPORT HB_FHANDLE hb_memfsOpen( const char * szName, HB_USHORT uiFlags )
{
PHB_MEMFS_FILE pFile = NULL;
HB_FHANDLE hFile;
HB_ULONG ulInode;
HB_ERRCODE uiError = 0;
/*
Recalculate flags. Bit should indicate feature: 1=read, 2=write, 16=denyread, 32=denywrite.
So, 3=readwrite, 48=exclusive.
Compatibility mode == DenyNone.
*/
uiFlags = ( uiFlags & ( FO_CREAT | FO_TRUNC | FO_EXCL ) ) |
( uiFlags & FO_READWRITE ? FOX_READWRITE : ( uiFlags & FO_WRITE ? FOX_WRITE : FOX_READ ) ) |
( ( uiFlags & 0xf0 ) == FO_EXCLUSIVE ? FOX_EXCLUSIVE :
( ( uiFlags & 0xf0 ) == FO_DENYWRITE ? FOX_DENYWRITE :
( ( uiFlags & 0xf0 ) == FO_DENYREAD ? FOX_DENYREAD : FOX_DENYNONE ) ) );
HB_MEMFSMT_LOCK
ulInode = memfsInodeFind( szName, NULL );
if( uiFlags & FO_CREAT )
{
if( uiFlags & FO_EXCL )
{
/* create new */
if( ulInode )
uiError = 80;
}
else if( uiFlags & FO_TRUNC )
{
/* create always */
if( ulInode && s_fs.pInodes[ ulInode - 1 ]->uiDeny & FOX_DENYWRITE )
uiError = 32;
}
else
{
/* open always */
/* Do nothing */
}
}
else if( uiFlags & FO_TRUNC )
{
/* truncate existing */
if( ulInode )
{
if( s_fs.pInodes[ ulInode - 1 ]->uiDeny & FOX_DENYWRITE )
uiError = 32;
}
else
uiError = 2;
}
else
{
/* open existing */
if( ! ulInode )
uiError = 2;
}
if( ! uiError )
{
if( ulInode )
{
if( ( uiFlags & FOX_READ && s_fs.pInodes[ ulInode - 1 ]->uiDeny & FOX_DENYREAD ) ||
( uiFlags & FOX_WRITE && s_fs.pInodes[ ulInode - 1 ]->uiDeny & FOX_DENYWRITE ) ||
s_fs.pInodes[ ulInode - 1 ]->uiDeny & uiFlags )
uiError = 32;
else
pFile = memfsFileAlloc( s_fs.pInodes[ ulInode - 1 ] );
}
else
pFile = memfsFileAlloc( memfsInodeAlloc( szName ) );
}
s_error = uiError;
if( !pFile )
{
HB_MEMFSMT_UNLOCK
return FS_ERROR;
}
pFile->pInode->uiDeny |= uiFlags & FOX_DENYFLAGS;
if( uiFlags & FOX_READ )
pFile->pInode->uiCountRead++;
if( uiFlags & FOX_WRITE )
pFile->pInode->uiCountWrite++;
pFile->uiFlags = uiFlags;
hFile = memfsHandleAlloc( pFile );
HB_MEMFSMT_UNLOCK
return hFile;
}
HB_MEMFS_EXPORT void hb_memfsClose( HB_FHANDLE hFile )
{
PHB_MEMFS_FILE pFile;
PHB_MEMFS_INODE pInode;
HB_MEMFSMT_LOCK
if( ( pFile = memfsHandleToFile( hFile ) ) == NULL )
{
HB_MEMFSMT_UNLOCK
return; /* invalid handle */
}
s_fs.pFiles[ hFile - 1 ] = NULL;
pInode = pFile->pInode;
if( --pInode->uiCount == 0 )
{
memfsInodeFree( pInode );
}
else
{
if( pFile->uiFlags & FOX_READ )
pInode->uiCountRead--;
if( pFile->uiFlags & FOX_WRITE )
pInode->uiCountWrite--;
pInode->uiDeny ^= pFile->uiFlags & FOX_DENYFLAGS;
}
HB_MEMFSMT_UNLOCK
hb_xfree( pFile );
}
HB_MEMFS_EXPORT HB_SIZE hb_memfsReadAt( HB_FHANDLE hFile, void * pBuff, HB_SIZE nCount, HB_FOFFSET llOffset )
{
PHB_MEMFS_FILE pFile;
PHB_MEMFS_INODE pInode;
HB_SIZE nRead;
if( ( pFile = memfsHandleToFile( hFile ) ) == NULL )
return 0; /* invalid handle */
pInode = pFile->pInode;
if( ( pFile->uiFlags & FOX_READ ) == 0 )
return 0; /* access denied */
if( llOffset < 0 || pInode->llSize <= llOffset )
return 0;
HB_MEMFSMT_LOCK
if( pInode->llSize >= llOffset + ( HB_FOFFSET ) nCount )
nRead = nCount;
else
nRead = ( HB_SIZE ) ( pInode->llSize - llOffset );
memcpy( pBuff, pInode->pData + ( HB_SIZE ) llOffset, nRead );
HB_MEMFSMT_UNLOCK
pFile->llPos = llOffset + ( HB_FOFFSET ) nCount;
return nRead;
}
HB_MEMFS_EXPORT HB_SIZE hb_memfsWriteAt( HB_FHANDLE hFile, const void * pBuff, HB_SIZE nCount, HB_FOFFSET llOffset )
{
PHB_MEMFS_FILE pFile;
PHB_MEMFS_INODE pInode;
if( ( pFile = memfsHandleToFile( hFile ) ) == NULL )
return 0; /* invalid handle */
pInode = pFile->pInode;
if( ( pFile->uiFlags & FOX_WRITE ) == 0 )
return 0; /* access denied */
if( llOffset < 0 )
return 0;
HB_MEMFSMT_LOCK
/* Reallocate if neccesary */
if( pInode->llAlloc < llOffset + ( HB_FOFFSET ) nCount )
{
HB_FOFFSET llNewAlloc = pInode->llAlloc + ( pInode->llAlloc >> 1 );
if( llNewAlloc < llOffset + ( HB_FOFFSET ) nCount )
llNewAlloc = llOffset + ( HB_FOFFSET ) nCount;
pInode->pData = ( char * ) hb_xrealloc( pInode->pData, ( HB_SIZE ) llNewAlloc );
memset( pInode->pData + ( HB_SIZE ) pInode->llAlloc, 0, ( HB_SIZE ) ( llNewAlloc - pInode->llAlloc ) );
pInode->llAlloc = llNewAlloc;
}
memcpy( pInode->pData + ( HB_SIZE ) llOffset, pBuff, nCount );
if( pInode->llSize < llOffset + ( HB_FOFFSET ) nCount )
pInode->llSize = llOffset + ( HB_FOFFSET ) nCount;
HB_MEMFSMT_UNLOCK
pFile->llPos = llOffset + ( HB_FOFFSET ) nCount;
return nCount;
}
#ifdef HB_MEMFS_PUBLIC_API
HB_MEMFS_EXPORT HB_SIZE hb_memfsRead( HB_FHANDLE hFile, void * pBuff, HB_SIZE nCount )
{
return hb_memfsReadAt( hFile, pBuff, nCount, ( ( PHB_MEMFS_FILE ) pFile )->llPos );
}
HB_MEMFS_EXPORT HB_SIZE hb_memfsWrite( HB_FHANDLE hFile, const void * pBuff, HB_SIZE nCount )
{
return hb_memfsWriteAt( hFile, pBuff, nCount, ( ( PHB_MEMFS_FILE ) pFile )->llPos );
}
#endif
HB_MEMFS_EXPORT HB_BOOL hb_memfsTruncAt( HB_FHANDLE hFile, HB_FOFFSET llOffset )
{
PHB_MEMFS_FILE pFile;
PHB_MEMFS_INODE pInode;
HB_FOFFSET llNewAlloc;
if( ( pFile = memfsHandleToFile( hFile ) ) == NULL )
return HB_FALSE; /* invalid handle */
pInode = pFile->pInode;
if( ( pFile->uiFlags & FOX_WRITE ) == 0 )
return HB_FALSE; /* access denied */
if( llOffset < 0 )
return HB_FALSE;
HB_MEMFSMT_LOCK
/* Reallocate if neccesary */
if( pInode->llAlloc < llOffset )
{
llNewAlloc = pInode->llAlloc + ( pInode->llAlloc >> 1 );
if( llNewAlloc < llOffset )
llNewAlloc = llOffset;
pInode->pData = ( char * ) hb_xrealloc( pInode->pData, ( HB_SIZE ) llNewAlloc );
memset( pInode->pData + ( HB_SIZE ) pInode->llAlloc, 0, ( HB_SIZE ) ( llNewAlloc - pInode->llAlloc ) );
pInode->llAlloc = llNewAlloc;
}
else if( ( pInode->llAlloc >> 2 ) > ( llOffset > HB_MEMFS_INITSIZE ? llOffset : HB_MEMFS_INITSIZE ) )
{
pInode->llAlloc = ( llOffset > HB_MEMFS_INITSIZE ? llOffset : HB_MEMFS_INITSIZE );
pInode->pData = ( char * ) hb_xrealloc( pInode->pData, ( HB_SIZE ) pInode->llAlloc );
}
memset( pInode->pData + ( HB_SIZE ) llOffset, 0, ( HB_SIZE ) ( pInode->llAlloc - llOffset ) );
pInode->llSize = llOffset;
HB_MEMFSMT_UNLOCK
return HB_TRUE;
}
HB_MEMFS_EXPORT HB_FOFFSET hb_memfsSeek( HB_FHANDLE hFile, HB_FOFFSET llOffset, HB_USHORT uiFlags )
{
PHB_MEMFS_FILE pFile;
PHB_MEMFS_INODE pInode;
HB_FOFFSET llPos;
if( ( pFile = memfsHandleToFile( hFile ) ) == NULL )
return 0; /* invalid handle */
pInode = pFile->pInode;
HB_MEMFSMT_LOCK
if( uiFlags & FS_END )
llPos = pInode->llSize + llOffset;
else if( uiFlags & FS_RELATIVE )
llPos = pFile->llPos + llOffset;
else
llPos = llOffset;
if( llPos < 0 )
llPos = 0;
if( llPos > pInode->llSize )
llPos = pInode->llSize;
HB_MEMFSMT_UNLOCK
pFile->llPos = llPos;
return llPos;
}
HB_MEMFS_EXPORT void hb_memfsFlush( HB_FHANDLE hFile, HB_BOOL fDirty )
{
HB_SYMBOL_UNUSED( hFile );
HB_SYMBOL_UNUSED( fDirty );
return;
}
HB_MEMFS_EXPORT void hb_memfsCommit( HB_FHANDLE hFile )
{
HB_SYMBOL_UNUSED( hFile );
return;
}
HB_MEMFS_EXPORT HB_BOOL hb_memfsLock( HB_FHANDLE hFile, HB_FOFFSET ulStart, HB_FOFFSET nLength, int iMode )
{
HB_SYMBOL_UNUSED( hFile );
HB_SYMBOL_UNUSED( ulStart );
HB_SYMBOL_UNUSED( nLength );
HB_SYMBOL_UNUSED( iMode );
return HB_TRUE;
}
HB_MEMFS_EXPORT int hb_memfsLockTest( HB_FHANDLE hFile, HB_FOFFSET ulStart, HB_FOFFSET nLength, int iMode )
{
HB_SYMBOL_UNUSED( hFile );
HB_SYMBOL_UNUSED( ulStart );
HB_SYMBOL_UNUSED( nLength );
HB_SYMBOL_UNUSED( iMode );
return 0;
}
/******************************************************
*
* I/O Driver for Memory file system
*
*******************************************************/
#define FILE_PREFIX "mem:"
#define FILE_PREFIX_LEN strlen( FILE_PREFIX )
typedef struct _HB_FILE
{
const HB_FILE_FUNCS * pFuncs;
HB_FHANDLE hFile;
}
HB_FILE;
static PHB_FILE s_fileNew( HB_FHANDLE hFile );
static HB_BOOL s_fileAccept( const char * pFilename )
{
return hb_strnicmp( pFilename, FILE_PREFIX, FILE_PREFIX_LEN ) == 0;
}
static HB_BOOL s_fileExists( const char * pFilename, char * pRetPath )
{
if( hb_memfsFileExists( pFilename + FILE_PREFIX_LEN ) )
{
/* Warning: return buffer could be the same memory place as filename parameter! */
if( pRetPath && pRetPath != pFilename )
hb_strncpy( pRetPath, pFilename, HB_PATH_MAX );
return HB_TRUE;
}
return HB_FALSE;
}
static HB_BOOL s_fileDelete( const char * pFilename )
{
return hb_memfsDelete( pFilename + FILE_PREFIX_LEN );
}
static HB_BOOL s_fileRename( const char * szName, const char * szNewName )
{
szName += FILE_PREFIX_LEN;
if( s_fileAccept( szNewName ) )
{
szNewName += FILE_PREFIX_LEN;
return hb_memfsRename( szName, szNewName );
}
return HB_FALSE;
}
static PHB_FILE s_fileOpen( const char * szName, const char * szDefExt, HB_USHORT uiExFlags, const char * pPaths, PHB_ITEM pError )
{
HB_FHANDLE hFile;
char szNameNew[ HB_PATH_MAX + 1 ];
HB_USHORT uiFlags;
HB_SIZE nLen;
HB_SYMBOL_UNUSED( pPaths );
HB_SYMBOL_UNUSED( pError );
hb_strncpy( szNameNew, szName + FILE_PREFIX_LEN, HB_PATH_MAX );
nLen = strlen( szNameNew );
do {
if( nLen == 0 || strchr( HB_OS_PATH_DELIM_CHR_LIST, szNameNew[ nLen - 1 ] ) )
{
hb_strncat( szNameNew, szDefExt, HB_PATH_MAX );
break;
}
}
while( szNameNew[ --nLen ] != '.' );
uiFlags = uiExFlags & 0xff;
if( uiExFlags & ( FXO_TRUNCATE | FXO_APPEND | FXO_UNIQUE ) )
{
uiFlags |= FO_CREAT;
if( uiExFlags & FXO_UNIQUE )
uiFlags |= FO_EXCL;
else if( uiExFlags & FXO_TRUNCATE )
uiFlags |= FO_TRUNC;
}
hFile = hb_memfsOpen( szNameNew, uiFlags );
if( hFile != FS_ERROR )
return s_fileNew( hFile );
else
{
if( pError )
{
hb_errPutFileName( pError, szName );
hb_errPutOsCode( pError, hb_memfsError() );
hb_errPutGenCode( pError, ( HB_ERRCODE ) ( ( uiExFlags & FXO_TRUNCATE ) ? EG_CREATE : EG_OPEN ) );
}
return NULL;
}
}
static void s_fileClose( PHB_FILE pFile )
{
hb_memfsClose( pFile->hFile );
hb_xfree( pFile );
}
static HB_BOOL s_fileLock( PHB_FILE pFile, HB_FOFFSET ulStart,
HB_FOFFSET nLen, int iType )
{
return hb_memfsLock( pFile->hFile, ulStart, nLen, iType );
}
static int s_fileLockTest( PHB_FILE pFile, HB_FOFFSET ulStart,
HB_FOFFSET nLen, int iType )
{
return hb_memfsLockTest( pFile->hFile, ulStart, nLen, iType );
}
static HB_SIZE s_fileReadAt( PHB_FILE pFile, void * buffer,
HB_SIZE nSize, HB_FOFFSET llOffset )
{
return hb_memfsReadAt( pFile->hFile, buffer, nSize, llOffset );
}
static HB_SIZE s_fileWriteAt( PHB_FILE pFile, const void * buffer,
HB_SIZE nSize, HB_FOFFSET llOffset )
{
return hb_memfsWriteAt( pFile->hFile, buffer, nSize, llOffset );
}
static HB_BOOL s_fileTruncAt( PHB_FILE pFile, HB_FOFFSET llOffset )
{
return hb_memfsTruncAt( pFile->hFile, llOffset );
}
static HB_FOFFSET s_fileSize( PHB_FILE pFile )
{
return hb_memfsSeek( pFile->hFile, 0, FS_END );
}
static void s_fileFlush( PHB_FILE pFile, HB_BOOL fDirty )
{
hb_memfsFlush( pFile->hFile, fDirty );
}
static void s_fileCommit( PHB_FILE pFile )
{
hb_memfsCommit( pFile->hFile );
}
static HB_FHANDLE s_fileHandle( PHB_FILE pFile )
{
return pFile ? pFile->hFile : FS_ERROR;
}
static const HB_FILE_FUNCS s_fileFuncs =
{
s_fileAccept,
s_fileExists,
s_fileDelete,
s_fileRename,
s_fileOpen,
s_fileClose,
s_fileLock,
s_fileLockTest,
s_fileReadAt,
s_fileWriteAt,
s_fileTruncAt,
s_fileSize,
s_fileFlush,
s_fileCommit,
s_fileHandle
};
static PHB_FILE s_fileNew( HB_FHANDLE hFile )
{
PHB_FILE pFile = ( PHB_FILE ) hb_xgrab( sizeof( HB_FILE ) );
pFile->pFuncs = &s_fileFuncs;
pFile->hFile = hFile;
return pFile;
}
HB_FUNC( HB_MEMIO ) {;}
HB_CALL_ON_STARTUP_BEGIN( _hb_file_memio_init_ )
memfsInit();
hb_fileRegister( &s_fileFuncs );
HB_CALL_ON_STARTUP_END( _hb_file_memio_init_ )
#if defined( HB_PRAGMA_STARTUP )
#pragma startup _hb_file_memio_init_
#elif defined( HB_DATASEG_STARTUP )
#define HB_DATASEG_BODY HB_DATASEG_FUNC( _hb_file_memio_init_ )
#include "hbiniseg.h"
#endif