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:
Spoike 2021-06-21 13:45:20 +00:00
parent be0c0b1821
commit 7c162c1b5b
3 changed files with 92 additions and 10 deletions

View File

@ -2,7 +2,7 @@
#include "fs.h"
#include "errno.h"
#if !defined(NACL) && !defined(FTE_TARGET_WEB)
#if !defined(NACL) && !defined(FTE_TARGET_WEB) && !defined(_WIN32)
#ifdef WEBSVONLY
#define Z_Free free
@ -120,7 +120,8 @@ vfsfile_t *FSSTDIO_OpenTemp(void)
vfsstdiofile_t *file;
#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
we also have a special close function to ensure the file is deleted too
*/

View File

@ -201,6 +201,7 @@ void MyRegDeleteKeyValue(void *base, const char *keyname, const char *valuename)
#define VFSW32_Open VFSOS_Open
#define VFSW32_OpenPath VFSOS_OpenPath
#define VFSW32_OpenTemp FS_OpenTemp
typedef struct {
searchpathfuncs_t pub;
@ -314,6 +315,75 @@ static qboolean QDECL VFSW32_Close(vfsfile_t *file)
Z_Free(file);
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
static vfsfile_t *QDECL VFSW32_OpenInternal(vfsw32path_t *handle, const char *quakename, const char *osname, const char *mode)

View File

@ -2994,13 +2994,19 @@ typedef struct
struct xz_dec *s;
} 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;
VFS_CLOSE(n->outfile);
vfsfile_t *r = n->outfile;
if (n->s)
xz_dec_end(n->s);
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;
}
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))
{ //okay, looks like an xz.
vfsfile_t *pipe = VFSPIPE_Open(2, false);
vfsfile_t *xzpipe = FS_XZ_DecompressWriteFilter(pipe);
vfsfile_t *xzpipe = FS_OpenTemp();
if (!xzpipe)
xzpipe = VFSPIPE_Open(1, true);
xzpipe = FS_XZ_DecompressWriteFilter(xzpipe);
for (;blocksize;)
{
if (blocksize < 0 || blocksize != VFS_WRITE(xzpipe, block, blocksize))
{
VFS_CLOSE(pipe);
pipe = NULL;
VFS_CLOSE(xzpipe);
xzpipe = NULL;
break;
}
blocksize = VFS_READ(srcfile, block, sizeof(block));
}
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);
return srcfile;