mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-27 06:02:16 +00:00
6a831e2f99
enabled ssl support in windows for plugins. updated jabber plugin. tweaked downloading logic in an effort to end the madness. Updated sql code to support sleeping the qc thread until query completion, as a more readable alternative to callbacks. Client updates should be more explicit now, removing a potential bug. networked terrain editing should now be in a better state. updated the dir command to show paths too (so when the same file is listed twice, the pak its in will at least be different). Many files changed because of this. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4273 fc73d0e0-1445-4013-8a0c-d673dee63da5
336 lines
8.5 KiB
C
336 lines
8.5 KiB
C
#include "quakedef.h"
|
|
#include "fs.h"
|
|
#include <windows.h>
|
|
|
|
#ifndef INVALID_SET_FILE_POINTER
|
|
#define INVALID_SET_FILE_POINTER ~0
|
|
#endif
|
|
|
|
//read-only memory mapped files.
|
|
//for write access, we use the stdio module as a fallback.
|
|
|
|
#define VFSW32_Open VFSOS_Open
|
|
#define w32filefuncs osfilefuncs
|
|
|
|
typedef struct {
|
|
HANDLE changenotification;
|
|
int hashdepth;
|
|
char rootpath[1];
|
|
} vfsw32path_t;
|
|
typedef struct {
|
|
vfsfile_t funcs;
|
|
HANDLE hand;
|
|
HANDLE mmh;
|
|
void *mmap;
|
|
unsigned int length;
|
|
unsigned int offset;
|
|
} vfsw32file_t;
|
|
static int VFSW32_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread)
|
|
{
|
|
DWORD read;
|
|
vfsw32file_t *intfile = (vfsw32file_t*)file;
|
|
if (intfile->mmap)
|
|
{
|
|
if (intfile->offset+bytestoread > intfile->length)
|
|
bytestoread = intfile->length-intfile->offset;
|
|
|
|
memcpy(buffer, (char*)intfile->mmap + intfile->offset, bytestoread);
|
|
intfile->offset += bytestoread;
|
|
return bytestoread;
|
|
}
|
|
if (!ReadFile(intfile->hand, buffer, bytestoread, &read, NULL))
|
|
return 0;
|
|
return read;
|
|
}
|
|
static int VFSW32_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread)
|
|
{
|
|
DWORD written;
|
|
vfsw32file_t *intfile = (vfsw32file_t*)file;
|
|
if (intfile->mmap)
|
|
{
|
|
if (intfile->offset+bytestoread > intfile->length)
|
|
bytestoread = intfile->length-intfile->offset;
|
|
|
|
memcpy((char*)intfile->mmap + intfile->offset, buffer, bytestoread);
|
|
intfile->offset += bytestoread;
|
|
return bytestoread;
|
|
}
|
|
|
|
if (!WriteFile(intfile->hand, buffer, bytestoread, &written, NULL))
|
|
return 0;
|
|
return written;
|
|
}
|
|
static qboolean VFSW32_Seek (struct vfsfile_s *file, unsigned long pos)
|
|
{
|
|
unsigned long upper, lower;
|
|
vfsw32file_t *intfile = (vfsw32file_t*)file;
|
|
if (intfile->mmap)
|
|
{
|
|
intfile->offset = pos;
|
|
return true;
|
|
}
|
|
|
|
lower = (pos & 0xffffffff);
|
|
upper = ((pos>>16)>>16);
|
|
|
|
return SetFilePointer(intfile->hand, lower, &upper, FILE_BEGIN) != INVALID_SET_FILE_POINTER;
|
|
}
|
|
static unsigned long VFSW32_Tell (struct vfsfile_s *file)
|
|
{
|
|
vfsw32file_t *intfile = (vfsw32file_t*)file;
|
|
if (intfile->mmap)
|
|
return intfile->offset;
|
|
return SetFilePointer(intfile->hand, 0, NULL, FILE_CURRENT);
|
|
}
|
|
static void VFSW32_Flush(struct vfsfile_s *file)
|
|
{
|
|
vfsw32file_t *intfile = (vfsw32file_t*)file;
|
|
if (intfile->mmap)
|
|
FlushViewOfFile(intfile->mmap, intfile->length);
|
|
FlushFileBuffers(intfile->hand);
|
|
}
|
|
static unsigned long VFSW32_GetSize (struct vfsfile_s *file)
|
|
{
|
|
vfsw32file_t *intfile = (vfsw32file_t*)file;
|
|
|
|
if (intfile->mmap)
|
|
return intfile->length;
|
|
return GetFileSize(intfile->hand, NULL);
|
|
}
|
|
static void VFSW32_Close(vfsfile_t *file)
|
|
{
|
|
vfsw32file_t *intfile = (vfsw32file_t*)file;
|
|
if (intfile->mmap)
|
|
{
|
|
UnmapViewOfFile(intfile->mmap);
|
|
CloseHandle(intfile->mmh);
|
|
}
|
|
CloseHandle(intfile->hand);
|
|
Z_Free(file);
|
|
|
|
COM_FlushFSCache();
|
|
}
|
|
|
|
vfsfile_t *VFSW32_Open(const char *osname, const char *mode)
|
|
{
|
|
HANDLE h, mh;
|
|
unsigned int fsize;
|
|
void *mmap;
|
|
|
|
vfsw32file_t *file;
|
|
qboolean read = !!strchr(mode, 'r');
|
|
qboolean write = !!strchr(mode, 'w');
|
|
qboolean append = !!strchr(mode, 'a');
|
|
qboolean text = !!strchr(mode, 't');
|
|
write |= append;
|
|
if (strchr(mode, '+'))
|
|
read = write = true;
|
|
|
|
if ((write && read) || append)
|
|
h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
else if (write)
|
|
h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
else if (read)
|
|
h = CreateFileA(osname, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
else
|
|
h = INVALID_HANDLE_VALUE;
|
|
if (h == INVALID_HANDLE_VALUE)
|
|
return NULL;
|
|
|
|
if (write || append || text)
|
|
{
|
|
fsize = 0;
|
|
mh = INVALID_HANDLE_VALUE;
|
|
mmap = NULL;
|
|
|
|
/*if appending, set the access position to the end of the file*/
|
|
if (append)
|
|
SetFilePointer(h, 0, NULL, FILE_END);
|
|
}
|
|
else
|
|
{
|
|
fsize = GetFileSize(h, NULL);
|
|
mh = CreateFileMapping(h, NULL, PAGE_READONLY, 0, 0, NULL);
|
|
if (mh == INVALID_HANDLE_VALUE)
|
|
mmap = NULL;
|
|
else
|
|
{
|
|
mmap = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, fsize);
|
|
if (mmap == NULL)
|
|
{
|
|
CloseHandle(mh);
|
|
mh = INVALID_HANDLE_VALUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
file = Z_Malloc(sizeof(vfsw32file_t));
|
|
#ifdef _DEBUG
|
|
Q_strncpyz(file->funcs.dbgname, osname, sizeof(file->funcs.dbgname));
|
|
#endif
|
|
file->funcs.ReadBytes = read?VFSW32_ReadBytes:NULL;
|
|
file->funcs.WriteBytes = (write||append)?VFSW32_WriteBytes:NULL;
|
|
file->funcs.Seek = VFSW32_Seek;
|
|
file->funcs.Tell = VFSW32_Tell;
|
|
file->funcs.GetLen = VFSW32_GetSize;
|
|
file->funcs.Close = VFSW32_Close;
|
|
file->funcs.Flush = VFSW32_Flush;
|
|
file->hand = h;
|
|
file->mmh = mh;
|
|
file->mmap = mmap;
|
|
file->offset = 0;
|
|
file->length = fsize;
|
|
|
|
return (vfsfile_t*)file;
|
|
}
|
|
|
|
static vfsfile_t *VFSW32_OpenVFS(void *handle, flocation_t *loc, const char *mode)
|
|
{
|
|
//path is already cleaned, as anything that gets a valid loc needs cleaning up first.
|
|
|
|
return VFSW32_Open(loc->rawname, mode);
|
|
}
|
|
|
|
static void VFSW32_GetDisplayPath(void *handle, char *out, unsigned int outlen)
|
|
{
|
|
vfsw32path_t *wp = handle;
|
|
Q_strncpyz(out, wp->rootpath, outlen);
|
|
}
|
|
static void VFSW32_ClosePath(void *handle)
|
|
{
|
|
vfsw32path_t *wp = handle;
|
|
if (wp->changenotification != INVALID_HANDLE_VALUE)
|
|
FindCloseChangeNotification(wp->changenotification);
|
|
Z_Free(wp);
|
|
}
|
|
static qboolean VFSW32_PollChanges(void *handle)
|
|
{
|
|
qboolean result = false;
|
|
vfsw32path_t *wp = handle;
|
|
|
|
if (wp->changenotification == INVALID_HANDLE_VALUE)
|
|
return true;
|
|
for(;;)
|
|
{
|
|
switch(WaitForSingleObject(wp->changenotification, 0))
|
|
{
|
|
case WAIT_OBJECT_0:
|
|
result = true;
|
|
break;
|
|
case WAIT_TIMEOUT:
|
|
return result;
|
|
default:
|
|
FindCloseChangeNotification(wp->changenotification);
|
|
wp->changenotification = INVALID_HANDLE_VALUE;
|
|
return true;
|
|
}
|
|
FindNextChangeNotification(wp->changenotification);
|
|
}
|
|
return result;
|
|
}
|
|
static void *VFSW32_OpenPath(vfsfile_t *mustbenull, const char *desc)
|
|
{
|
|
vfsw32path_t *np;
|
|
int dlen = strlen(desc);
|
|
if (mustbenull)
|
|
return NULL;
|
|
np = Z_Malloc(sizeof(*np) + dlen);
|
|
if (np)
|
|
{
|
|
memcpy(np->rootpath, desc, dlen+1);
|
|
|
|
np->changenotification = FindFirstChangeNotification(np->rootpath, true, FILE_NOTIFY_CHANGE_FILE_NAME);
|
|
}
|
|
return np;
|
|
}
|
|
static int VFSW32_RebuildFSHash(const char *filename, int filesize, void *handle, void *spath)
|
|
{
|
|
vfsw32path_t *wp = handle;
|
|
if (filename[strlen(filename)-1] == '/')
|
|
{ //this is actually a directory
|
|
|
|
char childpath[256];
|
|
Q_snprintfz(childpath, sizeof(childpath), "%s*", filename);
|
|
Sys_EnumerateFiles(wp->rootpath, childpath, VFSW32_RebuildFSHash, wp, handle);
|
|
return true;
|
|
}
|
|
|
|
FS_AddFileHash(wp->hashdepth, filename, NULL, wp);
|
|
return true;
|
|
}
|
|
static void VFSW32_BuildHash(void *handle, int hashdepth)
|
|
{
|
|
vfsw32path_t *wp = handle;
|
|
wp->hashdepth = hashdepth;
|
|
Sys_EnumerateFiles(wp->rootpath, "*", VFSW32_RebuildFSHash, handle, handle);
|
|
}
|
|
static qboolean VFSW32_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult)
|
|
{
|
|
vfsw32path_t *wp = handle;
|
|
FILE *f;
|
|
int len;
|
|
char netpath[MAX_OSPATH];
|
|
|
|
|
|
if (hashedresult && (void *)hashedresult != wp)
|
|
return false;
|
|
|
|
/*
|
|
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
|
|
snprintf (netpath, sizeof(netpath)-1, "%s/%s", wp->rootpath, filename);
|
|
|
|
f = fopen(netpath, "rb");
|
|
if (!f)
|
|
return false;
|
|
|
|
fseek(f, 0, SEEK_END);
|
|
len = ftell(f);
|
|
fclose(f);
|
|
if (loc)
|
|
{
|
|
loc->len = len;
|
|
loc->offset = 0;
|
|
loc->index = 0;
|
|
snprintf(loc->rawname, sizeof(loc->rawname), "%s/%s", wp->rootpath, filename);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
static void VFSW32_ReadFile(void *handle, flocation_t *loc, char *buffer)
|
|
{
|
|
// vfsw32path_t *wp = handle;
|
|
|
|
FILE *f;
|
|
f = fopen(loc->rawname, "rb");
|
|
if (!f) //err...
|
|
return;
|
|
fseek(f, loc->offset, SEEK_SET);
|
|
fread(buffer, 1, loc->len, f);
|
|
fclose(f);
|
|
}
|
|
static int VFSW32_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *, void *spath), void *parm)
|
|
{
|
|
vfsw32path_t *wp = handle;
|
|
return Sys_EnumerateFiles(wp->rootpath, match, func, parm, handle);
|
|
}
|
|
|
|
|
|
searchpathfuncs_t w32filefuncs = {
|
|
VFSW32_GetDisplayPath,
|
|
VFSW32_ClosePath,
|
|
VFSW32_BuildHash,
|
|
VFSW32_FLocate,
|
|
VFSW32_ReadFile,
|
|
VFSW32_EnumerateFiles,
|
|
VFSW32_OpenPath,
|
|
NULL,
|
|
VFSW32_OpenVFS,
|
|
VFSW32_PollChanges
|
|
};
|