388 lines
8.1 KiB
C++
388 lines
8.1 KiB
C++
/********************************************************************************
|
|
XFile.cpp: The truth is out there
|
|
Copyright (C) 2001-2012 Hugh Bailey <obs.jim@gmail.com>
|
|
|
|
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 of the License, 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 program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
|
********************************************************************************/
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
#define _WIN32_WINDOWS 0x0410
|
|
#define _WIN32_WINNT 0x0403
|
|
#include <windows.h>
|
|
#include "XT.h"
|
|
|
|
|
|
|
|
XFile::XFile()
|
|
{
|
|
hFile = INVALID_HANDLE_VALUE;
|
|
qwPos = 0;
|
|
bHasWritten = false;
|
|
}
|
|
|
|
XFile::XFile(CTSTR lpFile, DWORD dwAccess, DWORD dwCreationDisposition)
|
|
{
|
|
assert(lpFile);
|
|
bHasWritten = false;
|
|
Open(lpFile, dwAccess, dwCreationDisposition);
|
|
}
|
|
|
|
BOOL XFile::Open(CTSTR lpFile, DWORD dwAccess, DWORD dwCreationDisposition)
|
|
{
|
|
qwPos = 0;
|
|
|
|
DWORD dwFileAccess = 0;
|
|
DWORD dwShareAccess = 0;
|
|
|
|
if(dwAccess & XFILE_READ)
|
|
{
|
|
dwFileAccess |= GENERIC_READ;
|
|
if(dwAccess & XFILE_SHARED)
|
|
dwShareAccess |= FILE_SHARE_READ | FILE_SHARE_WRITE;
|
|
}
|
|
if(dwAccess & XFILE_WRITE)
|
|
{
|
|
dwFileAccess |= GENERIC_WRITE;
|
|
if(dwAccess & XFILE_SHARED)
|
|
dwShareAccess |= FILE_SHARE_READ;
|
|
}
|
|
|
|
assert(lpFile);
|
|
if((hFile = CreateFile(lpFile, dwFileAccess, dwShareAccess, NULL, dwCreationDisposition, 0, NULL)) == INVALID_HANDLE_VALUE)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
BOOL XFile::IsOpen()
|
|
{
|
|
return hFile != INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
DWORD XFile::Read(LPVOID lpBuffer, DWORD dwBytes)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
assert(lpBuffer);
|
|
|
|
if(!lpBuffer) return XFILE_ERROR;
|
|
|
|
if(!hFile) return XFILE_ERROR;
|
|
|
|
qwPos += dwBytes;
|
|
|
|
ReadFile(hFile, lpBuffer, dwBytes, &dwRet, NULL);
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD XFile::Write(const void *lpBuffer, DWORD dwBytes)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
assert(lpBuffer);
|
|
|
|
if(!hFile) return XFILE_ERROR;
|
|
|
|
qwPos += dwBytes;
|
|
|
|
WriteFile(hFile, lpBuffer, dwBytes, &dwRet, NULL);
|
|
|
|
if(dwRet)
|
|
bHasWritten = TRUE;
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
BOOL XFile::WriteStr(CWSTR lpBuffer)
|
|
{
|
|
assert(lpBuffer);
|
|
|
|
if(!hFile) return XFILE_ERROR;
|
|
|
|
DWORD dwElements = (DWORD)wcslen(lpBuffer);
|
|
|
|
char lpDest[4096];
|
|
DWORD dwBytes = (DWORD)wchar_to_utf8(lpBuffer, dwElements, lpDest, 4095, 0);
|
|
DWORD retVal = (Write(lpDest, dwBytes) == dwBytes);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
void XFile::FlushFileBuffers()
|
|
{
|
|
::FlushFileBuffers(hFile);
|
|
}
|
|
|
|
BOOL XFile::WriteStr(LPCSTR lpBuffer)
|
|
{
|
|
assert(lpBuffer);
|
|
|
|
if (!hFile) return false;
|
|
|
|
DWORD dwElements = (DWORD)strlen(lpBuffer);
|
|
|
|
return (Write(lpBuffer, dwElements) == dwElements);
|
|
}
|
|
|
|
BOOL XFile::WriteAsUTF8(CTSTR lpBuffer, DWORD dwElements)
|
|
{
|
|
DWORD retVal = 0;
|
|
|
|
if(!lpBuffer)
|
|
return false;
|
|
|
|
if (!hFile) return false;
|
|
|
|
if (!lpBuffer[0])
|
|
return true;
|
|
|
|
if(!dwElements)
|
|
dwElements = slen(lpBuffer);
|
|
|
|
#ifdef UNICODE
|
|
DWORD dwBytes = (DWORD)wchar_to_utf8_len(lpBuffer, dwElements, 0);
|
|
LPSTR lpDest = (LPSTR)Allocate(dwBytes+1);
|
|
|
|
if (wchar_to_utf8(lpBuffer, dwElements, lpDest, dwBytes, 0))
|
|
retVal = (Write(lpDest, dwBytes) == dwBytes);
|
|
else
|
|
Log(TEXT("XFile::WriteAsUTF8: wchar_to_utf8 failed: %d"), GetLastError());
|
|
|
|
Free(lpDest);
|
|
#else
|
|
DWORD retVal = (Write(lpBuffer, dwElements) == dwBytes);
|
|
#endif
|
|
|
|
return retVal;
|
|
}
|
|
|
|
BOOL XFile::SetFileSize(DWORD dwSize)
|
|
{
|
|
assert(hFile != INVALID_HANDLE_VALUE);
|
|
|
|
if(!hFile) return 0;
|
|
|
|
if(qwPos > dwSize)
|
|
qwPos = dwSize;
|
|
|
|
SetPos(dwSize, XFILE_BEGIN);
|
|
return SetEndOfFile(hFile);
|
|
}
|
|
|
|
QWORD XFile::GetFileSize() const
|
|
{
|
|
UINT64 size = 0;
|
|
size |= ::GetFileSize(hFile, (DWORD*)(((BYTE*)&size)+4));
|
|
|
|
return size;
|
|
}
|
|
|
|
UINT64 XFile::SetPos(INT64 iPos, DWORD dwMoveMethod) //uses the SetFilePointer 4th parameter flags
|
|
{
|
|
assert(hFile != INVALID_HANDLE_VALUE);
|
|
|
|
if(!hFile) return 0;
|
|
|
|
DWORD moveValue = FILE_CURRENT;
|
|
|
|
switch(dwMoveMethod)
|
|
{
|
|
//case XFILE_CURPOS:
|
|
// moveValue = FILE_CURRENT;
|
|
// break;
|
|
|
|
case XFILE_END:
|
|
moveValue = FILE_END;
|
|
break;
|
|
|
|
case XFILE_BEGIN:
|
|
moveValue = FILE_BEGIN;
|
|
break;
|
|
}
|
|
|
|
XLARGE_INT largeInt;
|
|
largeInt.largeVal = iPos;
|
|
|
|
DWORD newPosLow = SetFilePointer(hFile, LONG(largeInt.lowVal), &largeInt.highVal, moveValue);
|
|
largeInt.lowVal = newPosLow;
|
|
|
|
return largeInt.largeVal;
|
|
}
|
|
|
|
void XFile::Close()
|
|
{
|
|
if(hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
//this is not really necessary and kills performance
|
|
//if(bHasWritten)
|
|
// ::FlushFileBuffers(hFile);
|
|
CloseHandle(hFile);
|
|
hFile = INVALID_HANDLE_VALUE;
|
|
}
|
|
}
|
|
|
|
String GetPathFileName(CTSTR lpPath, BOOL bExtension)
|
|
{
|
|
assert(lpPath);
|
|
if(!lpPath)
|
|
return String();
|
|
|
|
OSFindData ofd;
|
|
HANDLE hFind = OSFindFirstFile(lpPath, ofd);
|
|
|
|
if(!hFind)
|
|
ofd.bDirectory = FALSE;
|
|
else
|
|
OSFindClose(hFind);
|
|
|
|
if(!ofd.bDirectory)
|
|
{
|
|
CTSTR lpDirectoryEnd = srchr(lpPath, '/');
|
|
|
|
if(!lpDirectoryEnd)
|
|
lpDirectoryEnd = srchr(lpPath, '/');
|
|
|
|
if(lpDirectoryEnd)
|
|
lpPath = lpDirectoryEnd+1;
|
|
}
|
|
|
|
String newPath = lpPath;
|
|
if(newPath.IsValid())
|
|
{
|
|
if(!bExtension)
|
|
{
|
|
TSTR pDot = srchr(newPath, '.');
|
|
if(pDot)
|
|
newPath.SetLength((int)((((UPARAM)pDot)-((UPARAM)newPath.Array()))/sizeof(TCHAR)));
|
|
}
|
|
}
|
|
|
|
return newPath;
|
|
}
|
|
|
|
String GetPathDirectory(CTSTR lpPath)
|
|
{
|
|
assert(lpPath);
|
|
if(!lpPath)
|
|
return String();
|
|
|
|
OSFindData ofd;
|
|
HANDLE hFind = OSFindFirstFile(lpPath, ofd);
|
|
|
|
if(!hFind)
|
|
ofd.bDirectory = FALSE;
|
|
else
|
|
OSFindClose(hFind);
|
|
|
|
int nDirectoryEnd;
|
|
|
|
if(!ofd.bDirectory)
|
|
{
|
|
CTSTR lpDirectoryEnd = srchr(lpPath, '/');
|
|
|
|
if(!lpDirectoryEnd)
|
|
lpDirectoryEnd = srchr(lpPath, '\\');
|
|
|
|
if(lpDirectoryEnd)
|
|
nDirectoryEnd = (int)((((UPARAM)lpDirectoryEnd)-((UPARAM)lpPath))/sizeof(TCHAR));
|
|
else
|
|
nDirectoryEnd = slen(lpPath);
|
|
}
|
|
else
|
|
nDirectoryEnd = slen(lpPath);
|
|
|
|
String newPath = lpPath;
|
|
|
|
newPath.SetLength(nDirectoryEnd);
|
|
return newPath;
|
|
}
|
|
|
|
String GetPathWithoutExtension(CTSTR lpPath)
|
|
{
|
|
assert(lpPath);
|
|
if(!lpPath)
|
|
return String();
|
|
|
|
TSTR lpExtensionStart = srchr(lpPath, '.');
|
|
if(lpExtensionStart)
|
|
{
|
|
UINT newLength = (UINT)(UPARAM)(lpExtensionStart-lpPath);
|
|
if(!newLength)
|
|
return String();
|
|
|
|
String newString;
|
|
newString.SetLength(newLength);
|
|
scpy_n(newString, lpPath, newLength);
|
|
|
|
return newString;
|
|
}
|
|
else
|
|
return String(lpPath);
|
|
}
|
|
|
|
String GetPathExtension(CTSTR lpPath)
|
|
{
|
|
assert(lpPath);
|
|
if(!lpPath)
|
|
return String();
|
|
|
|
TSTR lpExtensionStart = srchr(lpPath, '.');
|
|
if(lpExtensionStart)
|
|
return String(lpExtensionStart+1);
|
|
else
|
|
return String();
|
|
}
|
|
|
|
BOOL IsSafeFilename(CTSTR path)
|
|
{
|
|
const TCHAR *p;
|
|
|
|
p = path;
|
|
|
|
if (!*p)
|
|
return FALSE;
|
|
|
|
if (sstr(path, TEXT("..")))
|
|
return FALSE;
|
|
|
|
if (*p == '/')
|
|
return FALSE;
|
|
|
|
while (*p)
|
|
{
|
|
if (!isalnum(*p) && *p != ' ' && *p != '.' && *p != '/' && *p != '_' && *p != '-')
|
|
return FALSE;
|
|
p++;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL CreatePath(CTSTR lpPath)
|
|
{
|
|
if(OSFileExists(lpPath))
|
|
return true;
|
|
if(OSCreateDirectory(lpPath))
|
|
return true;
|
|
else
|
|
if(!CreatePath(GetPathDirectory(lpPath)))
|
|
return false;
|
|
return OSCreateDirectory(lpPath);
|
|
}
|
|
|
|
#endif
|