2009-04-01 22:03:56 +00:00
# include "quakedef.h"
# include "fs.h"
2011-05-30 04:32:04 +00:00
# include "errno.h"
2009-04-01 22:03:56 +00:00
2013-08-07 14:20:24 +00:00
# if !defined(NACL) && !defined(FTE_TARGET_WEB)
2012-04-09 19:12:12 +00:00
2009-11-04 21:16:50 +00:00
# ifdef WEBSVONLY
# define Z_Free free
# define Z_Malloc malloc
# else
2014-03-30 08:55:06 +00:00
# if !defined(_WIN32) || defined(FTE_SDL) || defined(WINRT)
2013-06-23 02:17:02 +00:00
# define FSSTDIO_OpenPath VFSOS_OpenPath
2009-05-24 10:11:17 +00:00
# endif
# define FSSTDIO_OpenTemp FS_OpenTemp
2009-11-04 21:16:50 +00:00
# endif
2009-05-24 10:11:17 +00:00
2012-05-09 15:30:53 +00:00
typedef struct {
2013-06-23 02:17:02 +00:00
searchpathfuncs_t pub ;
2012-05-09 15:30:53 +00:00
int depth ;
2013-05-03 04:28:08 +00:00
void ( QDECL * AddFileHash ) ( int depth , const char * fname , fsbucket_t * filehandle , void * pathhandle ) ;
2013-05-04 10:37:21 +00:00
char rootpath [ 1 ] ;
2012-05-09 15:30:53 +00:00
} stdiopath_t ;
2009-04-01 22:03:56 +00:00
typedef struct {
vfsfile_t funcs ;
FILE * handle ;
2009-05-24 10:11:17 +00:00
} vfsstdiofile_t ;
2013-05-03 04:28:08 +00:00
static int QDECL VFSSTDIO_ReadBytes ( struct vfsfile_s * file , void * buffer , int bytestoread )
2009-04-01 22:03:56 +00:00
{
2009-05-24 10:11:17 +00:00
vfsstdiofile_t * intfile = ( vfsstdiofile_t * ) file ;
2009-04-01 22:03:56 +00:00
return fread ( buffer , 1 , bytestoread , intfile - > handle ) ;
}
2013-05-03 04:28:08 +00:00
static int QDECL VFSSTDIO_WriteBytes ( struct vfsfile_s * file , const void * buffer , int bytestoread )
2009-04-01 22:03:56 +00:00
{
2009-05-24 10:11:17 +00:00
vfsstdiofile_t * intfile = ( vfsstdiofile_t * ) file ;
2009-04-01 22:03:56 +00:00
return fwrite ( buffer , 1 , bytestoread , intfile - > handle ) ;
}
2014-02-07 08:38:40 +00:00
static qboolean QDECL VFSSTDIO_Seek ( struct vfsfile_s * file , qofs_t pos )
2009-04-01 22:03:56 +00:00
{
2009-05-24 10:11:17 +00:00
vfsstdiofile_t * intfile = ( vfsstdiofile_t * ) file ;
2009-04-01 22:03:56 +00:00
return fseek ( intfile - > handle , pos , SEEK_SET ) = = 0 ;
}
2014-02-07 08:38:40 +00:00
static qofs_t QDECL VFSSTDIO_Tell ( struct vfsfile_s * file )
2009-04-01 22:03:56 +00:00
{
2009-05-24 10:11:17 +00:00
vfsstdiofile_t * intfile = ( vfsstdiofile_t * ) file ;
2009-04-01 22:03:56 +00:00
return ftell ( intfile - > handle ) ;
}
2013-05-03 04:28:08 +00:00
static void QDECL VFSSTDIO_Flush ( struct vfsfile_s * file )
2009-04-01 22:03:56 +00:00
{
2009-05-24 10:11:17 +00:00
vfsstdiofile_t * intfile = ( vfsstdiofile_t * ) file ;
2009-04-01 22:03:56 +00:00
fflush ( intfile - > handle ) ;
}
2014-02-07 08:38:40 +00:00
static qofs_t QDECL VFSSTDIO_GetSize ( struct vfsfile_s * file )
2009-04-01 22:03:56 +00:00
{
2009-05-24 10:11:17 +00:00
vfsstdiofile_t * intfile = ( vfsstdiofile_t * ) file ;
2009-04-01 22:03:56 +00:00
unsigned int curpos ;
unsigned int maxlen ;
curpos = ftell ( intfile - > handle ) ;
fseek ( intfile - > handle , 0 , SEEK_END ) ;
maxlen = ftell ( intfile - > handle ) ;
fseek ( intfile - > handle , curpos , SEEK_SET ) ;
return maxlen ;
}
2014-03-30 08:55:06 +00:00
static qboolean QDECL VFSSTDIO_Close ( vfsfile_t * file )
2009-04-01 22:03:56 +00:00
{
2014-03-30 08:55:06 +00:00
qboolean success ;
2009-05-24 10:11:17 +00:00
vfsstdiofile_t * intfile = ( vfsstdiofile_t * ) file ;
2014-03-30 08:55:06 +00:00
success = ! ferror ( intfile - > handle ) ;
2009-04-01 22:03:56 +00:00
fclose ( intfile - > handle ) ;
Z_Free ( file ) ;
2014-03-30 08:55:06 +00:00
return success ;
2009-04-01 22:03:56 +00:00
}
2011-12-27 08:35:19 +00:00
# ifdef _WIN32
2014-03-30 08:55:06 +00:00
static qboolean QDECL VFSSTDIO_CloseTemp ( vfsfile_t * file )
2011-12-27 08:35:19 +00:00
{
2014-03-30 08:55:06 +00:00
qboolean success ;
2011-12-27 08:35:19 +00:00
vfsstdiofile_t * intfile = ( vfsstdiofile_t * ) file ;
char * fname = ( char * ) ( intfile + 1 ) ;
2014-03-30 08:55:06 +00:00
success = ! ferror ( intfile - > handle ) ;
2011-12-27 08:35:19 +00:00
fclose ( intfile - > handle ) ;
_unlink ( fname ) ;
Z_Free ( file ) ;
2014-03-30 08:55:06 +00:00
return success ;
2011-12-27 08:35:19 +00:00
}
# endif
2009-05-24 10:11:17 +00:00
vfsfile_t * FSSTDIO_OpenTemp ( void )
2009-04-01 22:03:56 +00:00
{
FILE * f ;
2009-05-24 10:11:17 +00:00
vfsstdiofile_t * file ;
2009-04-01 22:03:56 +00:00
2011-12-27 08:35:19 +00:00
# ifdef _WIN32
/*warning: annother app might manage to open the file before we can. if the file is not opened exclusively then we can end up with issues
on windows , fopen is typically exclusive anyway , but not on unix . but on unix , tmpfile is actually usable , so special - case the windows code */
char * fname = _tempnam ( NULL , " ftemp " ) ;
f = fopen ( fname , " w+b " ) ;
if ( ! f )
return NULL ;
file = Z_Malloc ( sizeof ( vfsstdiofile_t ) + strlen ( fname ) + 1 ) ;
file - > funcs . Close = VFSSTDIO_CloseTemp ;
strcpy ( ( char * ) ( file + 1 ) , fname ) ;
free ( fname ) ;
# else
2009-04-01 22:03:56 +00:00
f = tmpfile ( ) ;
if ( ! f )
return NULL ;
2009-05-24 10:11:17 +00:00
file = Z_Malloc ( sizeof ( vfsstdiofile_t ) ) ;
2011-12-27 08:35:19 +00:00
file - > funcs . Close = VFSSTDIO_Close ;
2012-07-05 19:42:36 +00:00
# endif
# ifdef _DEBUG
Q_strncpyz ( file - > funcs . dbgname , " FSSTDIO_OpenTemp " , sizeof ( file - > funcs . dbgname ) ) ;
2011-12-27 08:35:19 +00:00
# endif
2009-05-24 10:11:17 +00:00
file - > funcs . ReadBytes = VFSSTDIO_ReadBytes ;
file - > funcs . WriteBytes = VFSSTDIO_WriteBytes ;
file - > funcs . Seek = VFSSTDIO_Seek ;
file - > funcs . Tell = VFSSTDIO_Tell ;
file - > funcs . GetLen = VFSSTDIO_GetSize ;
file - > funcs . Flush = VFSSTDIO_Flush ;
2009-04-01 22:03:56 +00:00
file - > handle = f ;
return ( vfsfile_t * ) file ;
}
2011-09-16 05:56:54 +00:00
#if 0 //def ANDROID
2011-09-05 01:48:23 +00:00
vfsfile_t * Sys_OpenAsset ( const char * fname ) ;
# endif
2012-11-27 03:23:19 +00:00
vfsfile_t * VFSSTDIO_Open ( const char * osname , const char * mode , qboolean * needsflush )
2009-04-01 22:03:56 +00:00
{
FILE * f ;
2009-05-24 10:11:17 +00:00
vfsstdiofile_t * file ;
2009-04-01 22:03:56 +00:00
qboolean read = ! ! strchr ( mode , ' r ' ) ;
qboolean write = ! ! strchr ( mode , ' w ' ) ;
qboolean append = ! ! strchr ( mode , ' a ' ) ;
qboolean text = ! ! strchr ( mode , ' t ' ) ;
char newmode [ 3 ] ;
int modec = 0 ;
2012-05-09 15:30:53 +00:00
if ( needsflush )
* needsflush = false ;
2011-09-16 05:56:54 +00:00
#if 0 //def ANDROID
2011-09-05 01:48:23 +00:00
// if (!strncmp("asset/", osname, 6))
{
if ( append | | write )
return NULL ;
return Sys_OpenAsset ( osname ) ;
}
# endif
2009-04-01 22:03:56 +00:00
if ( read )
newmode [ modec + + ] = ' r ' ;
if ( write )
newmode [ modec + + ] = ' w ' ;
if ( append )
newmode [ modec + + ] = ' a ' ;
if ( text )
newmode [ modec + + ] = ' t ' ;
else
newmode [ modec + + ] = ' b ' ;
newmode [ modec + + ] = ' \0 ' ;
f = fopen ( osname , newmode ) ;
if ( ! f )
return NULL ;
2012-05-09 15:30:53 +00:00
if ( write | | append )
{
if ( needsflush )
* needsflush = true ;
}
2009-05-24 10:11:17 +00:00
file = Z_Malloc ( sizeof ( vfsstdiofile_t ) ) ;
2012-07-05 19:42:36 +00:00
# ifdef _DEBUG
Q_strncpyz ( file - > funcs . dbgname , osname , sizeof ( file - > funcs . dbgname ) ) ;
# endif
2013-06-24 09:04:00 +00:00
file - > funcs . ReadBytes = VFSSTDIO_ReadBytes ;
file - > funcs . WriteBytes = VFSSTDIO_WriteBytes ;
2009-05-24 10:11:17 +00:00
file - > funcs . Seek = VFSSTDIO_Seek ;
file - > funcs . Tell = VFSSTDIO_Tell ;
file - > funcs . GetLen = VFSSTDIO_GetSize ;
file - > funcs . Close = VFSSTDIO_Close ;
file - > funcs . Flush = VFSSTDIO_Flush ;
2009-04-01 22:03:56 +00:00
file - > handle = f ;
return ( vfsfile_t * ) file ;
}
2014-03-30 08:55:06 +00:00
# if !defined(_WIN32) || defined(FTE_SDL) || defined(WINRT)
2012-05-09 15:30:53 +00:00
vfsfile_t * VFSOS_Open ( const char * osname , const char * mode )
{
vfsfile_t * f ;
qboolean needsflush ;
f = VFSSTDIO_Open ( osname , mode , & needsflush ) ;
if ( needsflush )
FS_FlushFSHashReally ( ) ;
return f ;
}
# endif
2009-11-04 21:16:50 +00:00
# ifndef WEBSVONLY
2013-06-23 03:59:48 +00:00
static vfsfile_t * QDECL FSSTDIO_OpenVFS ( searchpathfuncs_t * handle , flocation_t * loc , const char * mode )
2009-04-01 22:03:56 +00:00
{
2012-05-09 15:30:53 +00:00
vfsfile_t * f ;
2013-06-23 03:59:48 +00:00
stdiopath_t * sp = ( void * ) handle ;
2012-05-09 15:30:53 +00:00
qboolean needsflush ;
2009-04-01 22:03:56 +00:00
2013-06-23 01:26:43 +00:00
f = VFSSTDIO_Open ( loc - > rawname , mode , & needsflush ) ;
2013-05-03 04:28:08 +00:00
if ( needsflush & & sp - > AddFileHash )
sp - > AddFileHash ( sp - > depth , loc - > rawname , NULL , sp ) ;
2012-05-09 15:30:53 +00:00
return f ;
2009-04-01 22:03:56 +00:00
}
2013-06-23 03:59:48 +00:00
static void QDECL FSSTDIO_ClosePath ( searchpathfuncs_t * handle )
2009-04-01 22:03:56 +00:00
{
Z_Free ( handle ) ;
}
2013-06-23 03:59:48 +00:00
static qboolean QDECL FSSTDIO_PollChanges ( searchpathfuncs_t * handle )
2012-05-09 15:30:53 +00:00
{
2013-03-12 22:47:42 +00:00
// stdiopath_t *np = handle;
2012-05-09 15:30:53 +00:00
return true ; //can't verify that or not, so we have to assume the worst
}
2014-02-07 08:38:40 +00:00
static int QDECL FSSTDIO_RebuildFSHash ( const char * filename , qofs_t filesize , void * data , searchpathfuncs_t * spath )
2009-04-01 22:03:56 +00:00
{
2013-06-23 03:59:48 +00:00
stdiopath_t * sp = ( void * ) spath ;
2013-05-03 04:28:08 +00:00
void ( QDECL * AddFileHash ) ( int depth , const char * fname , fsbucket_t * filehandle , void * pathhandle ) = data ;
2009-04-01 22:03:56 +00:00
if ( filename [ strlen ( filename ) - 1 ] = = ' / ' )
{ //this is actually a directory
char childpath [ 256 ] ;
2011-07-22 15:11:35 +00:00
Q_snprintfz ( childpath , sizeof ( childpath ) , " %s* " , filename ) ;
2013-03-31 04:21:08 +00:00
Sys_EnumerateFiles ( sp - > rootpath , childpath , FSSTDIO_RebuildFSHash , data , spath ) ;
2009-04-01 22:03:56 +00:00
return true ;
}
2013-05-03 04:28:08 +00:00
AddFileHash ( sp - > depth , filename , NULL , sp ) ;
2009-04-01 22:03:56 +00:00
return true ;
}
2013-06-23 03:59:48 +00:00
static void QDECL FSSTDIO_BuildHash ( searchpathfuncs_t * handle , int depth , void ( QDECL * AddFileHash ) ( int depth , const char * fname , fsbucket_t * filehandle , void * pathhandle ) )
2009-04-01 22:03:56 +00:00
{
2013-06-23 03:59:48 +00:00
stdiopath_t * sp = ( void * ) handle ;
2012-05-09 15:30:53 +00:00
sp - > depth = depth ;
2013-05-03 04:28:08 +00:00
sp - > AddFileHash = AddFileHash ;
Sys_EnumerateFiles ( sp - > rootpath , " * " , FSSTDIO_RebuildFSHash , AddFileHash , handle ) ;
2009-04-01 22:03:56 +00:00
}
2014-02-07 08:38:40 +00:00
static unsigned int QDECL FSSTDIO_FLocate ( searchpathfuncs_t * handle , flocation_t * loc , const char * filename , void * hashedresult )
2009-04-01 22:03:56 +00:00
{
2013-06-23 03:59:48 +00:00
stdiopath_t * sp = ( void * ) handle ;
2009-04-01 22:03:56 +00:00
int len ;
char netpath [ MAX_OSPATH ] ;
if ( hashedresult & & ( void * ) hashedresult ! = handle )
2014-01-13 02:42:25 +00:00
return FF_NOTFOUND ;
2009-04-01 22:03:56 +00:00
/*
if ( ! static_registered )
{ // if not a registered version, don't ever go beyond base
if ( strchr ( filename , ' / ' ) | | strchr ( filename , ' \\ ' ) )
continue ;
}
*/
// check a file in the directory tree
2012-05-09 15:30:53 +00:00
snprintf ( netpath , sizeof ( netpath ) - 1 , " %s/%s " , sp - > rootpath , filename ) ;
2009-04-01 22:03:56 +00:00
2011-09-05 01:48:23 +00:00
# ifdef ANDROID
{
2012-05-11 01:57:00 +00:00
vfsfile_t * f = VFSSTDIO_Open ( netpath , " rb " , NULL ) ;
2011-09-05 01:48:23 +00:00
if ( ! f )
return false ;
len = VFS_GETLEN ( f ) ;
VFS_CLOSE ( f ) ;
}
# else
{
FILE * f = fopen ( netpath , " rb " ) ;
if ( ! f )
2014-01-13 02:42:25 +00:00
return FF_NOTFOUND ;
2009-04-01 22:03:56 +00:00
2011-09-05 01:48:23 +00:00
fseek ( f , 0 , SEEK_END ) ;
len = ftell ( f ) ;
fclose ( f ) ;
}
# endif
2009-04-01 22:03:56 +00:00
if ( loc )
{
loc - > len = len ;
loc - > offset = 0 ;
loc - > index = 0 ;
2013-06-23 01:26:43 +00:00
Q_strncpyz ( loc - > rawname , netpath , sizeof ( loc - > rawname ) ) ;
2009-04-01 22:03:56 +00:00
}
2014-01-13 02:42:25 +00:00
return FF_FOUND ;
2009-04-01 22:03:56 +00:00
}
2013-06-23 03:59:48 +00:00
static void QDECL FSSTDIO_ReadFile ( searchpathfuncs_t * handle , flocation_t * loc , char * buffer )
2009-04-01 22:03:56 +00:00
{
FILE * f ;
2011-05-15 13:23:13 +00:00
size_t result ;
2009-04-01 22:03:56 +00:00
f = fopen ( loc - > rawname , " rb " ) ;
if ( ! f ) //err...
return ;
fseek ( f , loc - > offset , SEEK_SET ) ;
2011-05-15 13:23:13 +00:00
result = fread ( buffer , 1 , loc - > len , f ) ; // do soemthing with result
2011-05-30 04:32:04 +00:00
if ( result ! = loc - > len )
2014-03-30 00:39:37 +00:00
Con_Printf ( " FSSTDIO_ReadFile() fread: Filename: %s, expected %u, result was %u (%s) \n " , loc - > rawname , ( unsigned int ) loc - > len , ( unsigned int ) result , strerror ( errno ) ) ;
2011-05-30 04:32:04 +00:00
2009-04-01 22:03:56 +00:00
fclose ( f ) ;
}
2014-02-07 08:38:40 +00:00
static int QDECL FSSTDIO_EnumerateFiles ( searchpathfuncs_t * handle , const char * match , int ( QDECL * func ) ( const char * , qofs_t , void * , searchpathfuncs_t * spath ) , void * parm )
2009-04-01 22:03:56 +00:00
{
2013-06-23 02:17:02 +00:00
stdiopath_t * sp = ( stdiopath_t * ) handle ;
2013-03-31 04:21:08 +00:00
return Sys_EnumerateFiles ( sp - > rootpath , match , func , parm , handle ) ;
2009-04-01 22:03:56 +00:00
}
2013-06-23 02:17:02 +00:00
2013-06-23 03:59:48 +00:00
searchpathfuncs_t * QDECL FSSTDIO_OpenPath ( vfsfile_t * mustbenull , const char * desc )
2013-06-23 02:17:02 +00:00
{
stdiopath_t * np ;
int dlen = strlen ( desc ) ;
if ( mustbenull )
return NULL ;
np = Z_Malloc ( sizeof ( * np ) + dlen ) ;
if ( np )
{
np - > depth = 0 ;
memcpy ( np - > rootpath , desc , dlen + 1 ) ;
}
np - > pub . fsver = FSVER ;
np - > pub . ClosePath = FSSTDIO_ClosePath ;
np - > pub . BuildHash = FSSTDIO_BuildHash ;
np - > pub . FindFile = FSSTDIO_FLocate ;
np - > pub . ReadFile = FSSTDIO_ReadFile ;
np - > pub . EnumerateFiles = FSSTDIO_EnumerateFiles ;
np - > pub . OpenVFS = FSSTDIO_OpenVFS ;
np - > pub . PollChanges = FSSTDIO_PollChanges ;
2013-06-23 03:59:48 +00:00
return & np - > pub ;
2013-06-23 02:17:02 +00:00
}
2009-11-04 21:16:50 +00:00
# endif
2012-07-08 12:33:08 +00:00
# endif