Try to get windows to delete temporary files early, so they don't linger over crashes or whatever. win9x still sucks.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5898 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
be0c0b1821
commit
7c162c1b5b
3 changed files with 92 additions and 10 deletions
|
@ -2,7 +2,7 @@
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "errno.h"
|
#include "errno.h"
|
||||||
|
|
||||||
#if !defined(NACL) && !defined(FTE_TARGET_WEB)
|
#if !defined(NACL) && !defined(FTE_TARGET_WEB) && !defined(_WIN32)
|
||||||
|
|
||||||
#ifdef WEBSVONLY
|
#ifdef WEBSVONLY
|
||||||
#define Z_Free free
|
#define Z_Free free
|
||||||
|
@ -120,7 +120,8 @@ vfsfile_t *FSSTDIO_OpenTemp(void)
|
||||||
vfsstdiofile_t *file;
|
vfsstdiofile_t *file;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#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
|
/*microsoft's tmpfile will nearly always fail, as it insists on writing to the root directory and that requires running everything with full admin rights.
|
||||||
|
warning: there's a race condition between tempnam and fopen. 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
|
on windows, fopen is typically exclusive anyway, but not on unix. but on unix, tmpfile is actually usable, so special-case the windows code
|
||||||
we also have a special close function to ensure the file is deleted too
|
we also have a special close function to ensure the file is deleted too
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -201,6 +201,7 @@ void MyRegDeleteKeyValue(void *base, const char *keyname, const char *valuename)
|
||||||
|
|
||||||
#define VFSW32_Open VFSOS_Open
|
#define VFSW32_Open VFSOS_Open
|
||||||
#define VFSW32_OpenPath VFSOS_OpenPath
|
#define VFSW32_OpenPath VFSOS_OpenPath
|
||||||
|
#define VFSW32_OpenTemp FS_OpenTemp
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
searchpathfuncs_t pub;
|
searchpathfuncs_t pub;
|
||||||
|
@ -314,6 +315,75 @@ static qboolean QDECL VFSW32_Close(vfsfile_t *file)
|
||||||
Z_Free(file);
|
Z_Free(file);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
static qboolean QDECL VFSW32_CloseTemp(vfsfile_t *file)
|
||||||
|
{
|
||||||
|
vfsw32file_t *intfile = (vfsw32file_t*)file;
|
||||||
|
if (intfile->mmap)
|
||||||
|
{
|
||||||
|
UnmapViewOfFile(intfile->mmap);
|
||||||
|
CloseHandle(intfile->mmh);
|
||||||
|
}
|
||||||
|
CloseHandle(intfile->hand);
|
||||||
|
DeleteFileA((char*)(intfile+1));
|
||||||
|
Z_Free(file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfsfile_t *QDECL VFSW32_OpenTemp(void)
|
||||||
|
{
|
||||||
|
static int seq=-1;
|
||||||
|
HANDLE h = INVALID_HANDLE_VALUE;
|
||||||
|
vfsw32file_t *file;
|
||||||
|
if (WinNT)
|
||||||
|
{ //gotta use wide stuff.
|
||||||
|
//on the plus side, FILE_SHARE_DELETE works.
|
||||||
|
wchar_t osname[MAX_PATH];
|
||||||
|
wchar_t tmppath[MAX_PATH];
|
||||||
|
if (GetTempPathW(countof(tmppath), tmppath))
|
||||||
|
if ((seq=GetTempFileNameW(tmppath, L"fte", ++seq, osname)))
|
||||||
|
h = CreateFileW(osname, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE, NULL);
|
||||||
|
if (!h)
|
||||||
|
return VFSPIPE_Open(1, true);
|
||||||
|
DeleteFileW(osname);
|
||||||
|
|
||||||
|
file = Z_Malloc(sizeof(vfsw32file_t));
|
||||||
|
#ifdef _DEBUG
|
||||||
|
narrowen(file->funcs.dbgname, sizeof(file->funcs.dbgname), osname);
|
||||||
|
#endif
|
||||||
|
file->funcs.Close = VFSW32_Close; //we already deleted it. woo.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ //can't use wide stuff.
|
||||||
|
//FLIE_SHARE_DELETE doesn't work. we have to faff around ourselves.
|
||||||
|
char osname[MAX_PATH];
|
||||||
|
char tmppath[MAX_PATH];
|
||||||
|
if (GetTempPathA(countof(tmppath), tmppath))
|
||||||
|
if ((seq=GetTempFileNameA(tmppath, "fte", ++seq, osname)))
|
||||||
|
h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL);
|
||||||
|
if (!h)
|
||||||
|
return VFSPIPE_Open(1, true);
|
||||||
|
|
||||||
|
file = Z_Malloc(sizeof(vfsw32file_t) + strlen(osname)+1);
|
||||||
|
strcpy((char*)(file+1), osname);
|
||||||
|
#ifdef _DEBUG
|
||||||
|
narrowen(file->funcs.dbgname, sizeof(file->funcs.dbgname), osname);
|
||||||
|
#endif
|
||||||
|
file->funcs.Close = VFSW32_CloseTemp; //gotta delete it after close. hopefully we won't crash too often...
|
||||||
|
}
|
||||||
|
file->funcs.ReadBytes = VFSW32_ReadBytes;
|
||||||
|
file->funcs.WriteBytes = VFSW32_WriteBytes;
|
||||||
|
file->funcs.Seek = VFSW32_Seek;
|
||||||
|
file->funcs.Tell = VFSW32_Tell;
|
||||||
|
file->funcs.GetLen = VFSW32_GetSize;
|
||||||
|
file->funcs.Flush = VFSW32_Flush;
|
||||||
|
file->hand = h;
|
||||||
|
file->mmh = INVALID_HANDLE_VALUE;
|
||||||
|
file->mmap = NULL;
|
||||||
|
file->offset = 0;
|
||||||
|
file->length = 0;
|
||||||
|
|
||||||
|
return &file->funcs;
|
||||||
|
}
|
||||||
|
|
||||||
//WARNING: handle can be null
|
//WARNING: handle can be null
|
||||||
static vfsfile_t *QDECL VFSW32_OpenInternal(vfsw32path_t *handle, const char *quakename, const char *osname, const char *mode)
|
static vfsfile_t *QDECL VFSW32_OpenInternal(vfsw32path_t *handle, const char *quakename, const char *osname, const char *mode)
|
||||||
|
|
|
@ -2994,13 +2994,19 @@ typedef struct
|
||||||
struct xz_dec *s;
|
struct xz_dec *s;
|
||||||
} vf_xz_dec_t;
|
} vf_xz_dec_t;
|
||||||
|
|
||||||
static qboolean QDECL FS_XZ_Dec_Close(vfsfile_t *f)
|
static vfsfile_t *FS_XZ_Finish(vfsfile_t *f)
|
||||||
{
|
{
|
||||||
vf_xz_dec_t *n = (vf_xz_dec_t*)f;
|
vf_xz_dec_t *n = (vf_xz_dec_t*)f;
|
||||||
VFS_CLOSE(n->outfile);
|
vfsfile_t *r = n->outfile;
|
||||||
if (n->s)
|
if (n->s)
|
||||||
xz_dec_end(n->s);
|
xz_dec_end(n->s);
|
||||||
Z_Free(n);
|
Z_Free(n);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
static qboolean QDECL FS_XZ_Dec_Close(vfsfile_t *f)
|
||||||
|
{
|
||||||
|
vfsfile_t *orig = FS_XZ_Finish(f);
|
||||||
|
VFS_CLOSE(orig);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
static int QDECL FS_XZ_Dec_Write(vfsfile_t *f, const void *buffer, int len)
|
static int QDECL FS_XZ_Dec_Write(vfsfile_t *f, const void *buffer, int len)
|
||||||
|
@ -3126,21 +3132,26 @@ vfsfile_t *FS_XZ_DecompressReadFilter(vfsfile_t *srcfile)
|
||||||
|
|
||||||
if (blocksize == HEADER_MAGIC_SIZE && !memcmp(block, HEADER_MAGIC, HEADER_MAGIC_SIZE))
|
if (blocksize == HEADER_MAGIC_SIZE && !memcmp(block, HEADER_MAGIC, HEADER_MAGIC_SIZE))
|
||||||
{ //okay, looks like an xz.
|
{ //okay, looks like an xz.
|
||||||
vfsfile_t *pipe = VFSPIPE_Open(2, false);
|
vfsfile_t *xzpipe = FS_OpenTemp();
|
||||||
vfsfile_t *xzpipe = FS_XZ_DecompressWriteFilter(pipe);
|
if (!xzpipe)
|
||||||
|
xzpipe = VFSPIPE_Open(1, true);
|
||||||
|
xzpipe = FS_XZ_DecompressWriteFilter(xzpipe);
|
||||||
for (;blocksize;)
|
for (;blocksize;)
|
||||||
{
|
{
|
||||||
if (blocksize < 0 || blocksize != VFS_WRITE(xzpipe, block, blocksize))
|
if (blocksize < 0 || blocksize != VFS_WRITE(xzpipe, block, blocksize))
|
||||||
{
|
{
|
||||||
VFS_CLOSE(pipe);
|
VFS_CLOSE(xzpipe);
|
||||||
pipe = NULL;
|
xzpipe = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
blocksize = VFS_READ(srcfile, block, sizeof(block));
|
blocksize = VFS_READ(srcfile, block, sizeof(block));
|
||||||
}
|
}
|
||||||
VFS_CLOSE(srcfile);
|
VFS_CLOSE(srcfile);
|
||||||
VFS_CLOSE(xzpipe);
|
|
||||||
return pipe;
|
if (xzpipe)
|
||||||
|
xzpipe = FS_XZ_Finish(xzpipe);
|
||||||
|
VFS_SEEK(xzpipe, 0);
|
||||||
|
return xzpipe;
|
||||||
}
|
}
|
||||||
VFS_SEEK(srcfile, 0);
|
VFS_SEEK(srcfile, 0);
|
||||||
return srcfile;
|
return srcfile;
|
||||||
|
|
Loading…
Reference in a new issue