simplify file implementation (remove unnecessary layer of abstraction)

ensure struct stat has 64-bit fields on windows
also fixed some warnings

This was SVN commit r7120.
This commit is contained in:
janwas 2009-08-24 21:04:01 +00:00
parent 94c7677c25
commit 93ab45e434
14 changed files with 227 additions and 180 deletions

View File

@ -95,8 +95,8 @@ template<typename T>
inline T bits(T num, size_t lo_idx, size_t hi_idx)
{
const size_t count = (hi_idx - lo_idx)+1; // # bits to return
T result = num >> T(lo_idx);
result &= bit_mask<T>(count);
T result = T(num >> lo_idx);
result = T(result & bit_mask<T>(count));
return result;
}

View File

@ -11,4 +11,4 @@ FUNC(BOOL, SymSetContext, (__in HANDLE hProcess, __in PIMAGEHLP_STACK_FRAME Stac
FUNC(BOOL, SymEnumSymbolsW, (__in HANDLE hProcess, __in ULONG64 BaseOfDll, __in_opt PCWSTR Mask, __in PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback, __in_opt PVOID UserContext))
FUNC(PIMAGE_NT_HEADERS, ImageNtHeader, (__in PVOID Base))
FUNC(BOOL, MiniDumpWriteDump, (IN HANDLE hProcess, IN DWORD ProcessId, IN HANDLE hFile, IN MINIDUMP_TYPE DumpType, IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL))
FUNC(BOOL, StackWalk64, (__in DWORD MachineType, __in HANDLE hProcess, __in HANDLE hThread, __inout LPSTACKFRAME64 StackFrame, __inout PVOID ContextRecord, __in_opt PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, __in_opt PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, __in_opt PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress))
FUNC(BOOL, StackWalk64, (__in DWORD MachineType, __in HANDLE hProcess, __in HANDLE hThread, __inout LPSTACKFRAME64 StackFrame, __inout PVOID ContextRecord, __in_opt PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, __in_opt PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, __in_opt PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress))

View File

@ -239,7 +239,7 @@ cassert(sizeof(ECDR) == 22);
class ArchiveFile_Zip : public IArchiveFile
{
public:
ArchiveFile_Zip(const PIFile& file, off_t ofs, off_t csize, u32 checksum, ZipMethod method)
ArchiveFile_Zip(const PFile& file, off_t ofs, off_t csize, u32 checksum, ZipMethod method)
: m_file(file), m_ofs(ofs)
, m_csize(csize), m_checksum(checksum), m_method((u16)method)
, m_flags(NeedsFixup)
@ -350,7 +350,7 @@ private:
m_ofs += (off_t)lfh.Size();
}
PIFile m_file;
PFile m_file;
// all relevant LFH/CDFH fields not covered by FileInfo
mutable off_t m_ofs;
@ -369,10 +369,8 @@ class ArchiveReader_Zip : public IArchiveReader
{
public:
ArchiveReader_Zip(const fs::path& pathname)
: m_file(CreateFile_Posix())
: m_file(new File(pathname, 'r'))
{
m_file->Open(pathname, 'r');
FileInfo fileInfo;
GetFileInfo(pathname, &fileInfo);
m_fileSize = fileInfo.Size();
@ -448,7 +446,7 @@ private:
// search for ECDR in the last <maxScanSize> bytes of the file.
// if found, fill <dst_ecdr> with a copy of the (little-endian) ECDR and
// return INFO::OK, otherwise IO error or ERR::CORRUPTED.
static LibError ScanForEcdr(const PIFile& file, off_t fileSize, u8* buf, size_t maxScanSize, size_t& cd_numEntries, off_t& cd_ofs, size_t& cd_size)
static LibError ScanForEcdr(const PFile& file, off_t fileSize, u8* buf, size_t maxScanSize, size_t& cd_numEntries, off_t& cd_ofs, size_t& cd_size)
{
// don't scan more than the entire file
const size_t scanSize = std::min(maxScanSize, size_t(fileSize));
@ -467,7 +465,7 @@ private:
return INFO::OK;
}
static LibError LocateCentralDirectory(const PIFile& file, off_t fileSize, off_t& cd_ofs, size_t& cd_numEntries, size_t& cd_size)
static LibError LocateCentralDirectory(const PFile& file, off_t fileSize, off_t& cd_ofs, size_t& cd_numEntries, size_t& cd_size)
{
const size_t maxScanSize = 66000u; // see below
shared_ptr<u8> buf = io_Allocate(maxScanSize, BLOCK_SIZE-1); // assume worst-case for alignment
@ -498,7 +496,7 @@ private:
WARN_RETURN(ERR::ARCHIVE_UNKNOWN_FORMAT);
}
PIFile m_file;
PFile m_file;
off_t m_fileSize;
};
@ -516,11 +514,10 @@ class ArchiveWriter_Zip : public IArchiveWriter
{
public:
ArchiveWriter_Zip(const fs::path& archivePathname)
: m_file(CreateFile_Posix()), m_fileSize(0)
: m_file(new File(archivePathname, 'w')), m_fileSize(0)
, m_unalignedWriter(new UnalignedWriter(m_file, 0))
, m_numEntries(0)
{
THROW_ERR(m_file->Open(archivePathname, 'w'));
THROW_ERR(pool_create(&m_cdfhPool, 10*MiB, 0));
}
@ -564,7 +561,7 @@ public:
if(!usize)
return INFO::SKIPPED;
PIFile file = CreateFile_Posix();
PFile file(new File);
RETURN_ERR(file->Open(pathname, 'r'));
const size_t pathnameLength = pathname.string().length();
@ -647,7 +644,7 @@ private:
return false;
}
PIFile m_file;
PFile m_file;
off_t m_fileSize;
PUnalignedWriter m_unalignedWriter;

View File

@ -43,7 +43,7 @@ RealDirectory::RealDirectory(const fs::path& path, size_t priority, size_t flags
/*virtual*/ LibError RealDirectory::Load(const std::string& name, const shared_ptr<u8>& buf, size_t size) const
{
PIFile file = CreateFile_Posix();
PFile file(new File);
RETURN_ERR(file->Open(m_path/name, 'r'));
RETURN_ERR(io_ReadAligned(file, 0, buf.get(), size));
@ -56,7 +56,7 @@ LibError RealDirectory::Store(const std::string& name, const shared_ptr<u8>& fil
const fs::path pathname(m_path/name);
{
PIFile file = CreateFile_Posix();
PFile file(new File);
RETURN_ERR(file->Open(pathname, 'w'));
RETURN_ERR(io_WriteAligned(file, 0, fileContents.get(), size));
}

View File

@ -29,132 +29,110 @@ ERROR_ASSOCIATE(ERR::FILE_ACCESS, "Insufficient access rights to open file", EAC
ERROR_ASSOCIATE(ERR::IO, "Error during IO", EIO);
class File_Posix : public IFile
fs::path path_from_wpath(const fs::wpath& pathname)
{
public:
~File_Posix()
{
Close();
}
virtual LibError Open(const fs::path& pathname, char mode)
{
debug_assert(mode == 'w' || mode == 'r');
m_pathname = pathname;
m_mode = mode;
int oflag = (mode == 'r')? O_RDONLY : O_WRONLY|O_CREAT|O_TRUNC;
#if OS_WIN
oflag |= O_BINARY_NP;
#endif
m_fd = open(m_pathname.external_file_string().c_str(), oflag, S_IRWXO|S_IRWXU|S_IRWXG);
if(m_fd < 0)
WARN_RETURN(ERR::FILE_ACCESS);
stats_open();
return INFO::OK;
}
virtual LibError Open(const fs::wpath& pathname, char mode)
{
char pathname_c[PATH_MAX];
size_t numConverted = wcstombs(pathname_c, pathname.file_string().c_str(), PATH_MAX);
debug_assert(numConverted < PATH_MAX);
return Open(pathname_c, mode);
}
virtual void Close()
{
m_mode = '\0';
if(m_fd)
{
close(m_fd);
m_fd = 0;
}
}
virtual const fs::path& Pathname() const
{
return m_pathname;
}
virtual char Mode() const
{
return m_mode;
}
virtual LibError Issue(aiocb& req, off_t alignedOfs, u8* alignedBuf, size_t alignedSize) const
{
memset(&req, 0, sizeof(req));
req.aio_lio_opcode = (m_mode == 'w')? LIO_WRITE : LIO_READ;
req.aio_buf = (volatile void*)alignedBuf;
req.aio_fildes = m_fd;
req.aio_offset = alignedOfs;
req.aio_nbytes = alignedSize;
struct sigevent* sig = 0; // no notification signal
aiocb* const reqs = &req;
if(lio_listio(LIO_NOWAIT, &reqs, 1, sig) != 0)
return LibError_from_errno();
return INFO::OK;
}
virtual LibError WaitUntilComplete(aiocb& req, u8*& alignedBuf, size_t& alignedSize)
{
// wait for transfer to complete.
while(aio_error(&req) == EINPROGRESS)
{
aiocb* const reqs = &req;
aio_suspend(&reqs, 1, (timespec*)0); // wait indefinitely
}
const ssize_t bytesTransferred = aio_return(&req);
if(bytesTransferred == -1) // transfer failed
WARN_RETURN(ERR::IO);
alignedBuf = (u8*)req.aio_buf; // cast from volatile void*
alignedSize = bytesTransferred;
return INFO::OK;
}
virtual LibError Write(off_t ofs, const u8* buf, size_t size) const
{
return IO(ofs, const_cast<u8*>(buf), size);
}
virtual LibError Read(off_t ofs, u8* buf, size_t size) const
{
return IO(ofs, buf, size);
}
private:
LibError IO(off_t ofs, u8* buf, size_t size) const
{
ScopedIoMonitor monitor;
lseek(m_fd, ofs, SEEK_SET);
errno = 0;
const ssize_t ret = (m_mode == 'w')? write(m_fd, buf, size) : read(m_fd, buf, size);
if(ret < 0)
return LibError_from_errno();
const size_t totalTransferred = (size_t)ret;
if(totalTransferred != size)
WARN_RETURN(ERR::IO);
monitor.NotifyOfSuccess(FI_LOWIO, m_mode, totalTransferred);
return INFO::OK;
}
fs::path m_pathname;
char m_mode;
int m_fd;
};
PIFile CreateFile_Posix()
{
return PIFile(new File_Posix);
char pathname_c[PATH_MAX];
size_t numConverted = wcstombs(pathname_c, pathname.file_string().c_str(), PATH_MAX);
debug_assert(numConverted < PATH_MAX);
return fs::path(pathname_c);
}
namespace FileImpl {
LibError Open(const fs::path& pathname, char mode, int& fd)
{
int oflag = -1;
switch(mode)
{
case 'r':
oflag = O_RDONLY;
break;
case 'w':
oflag = O_WRONLY|O_CREAT|O_TRUNC;
break;
case '+':
oflag = O_RDWR;
break;
default:
debug_assert(0);
}
#if OS_WIN
oflag |= O_BINARY_NP;
#endif
fd = open(pathname.file_string().c_str(), oflag, S_IRWXO|S_IRWXU|S_IRWXG);
if(fd < 0)
WARN_RETURN(ERR::FILE_ACCESS);
stats_open();
return INFO::OK;
}
void Close(int& fd)
{
if(fd)
{
close(fd);
fd = 0;
}
}
LibError IO(int fd, char mode, off_t ofs, u8* buf, size_t size)
{
debug_assert(mode == 'r' || mode == 'w');
ScopedIoMonitor monitor;
lseek(fd, ofs, SEEK_SET);
errno = 0;
const ssize_t ret = (mode == 'w')? write(fd, buf, size) : read(fd, buf, size);
if(ret < 0)
return LibError_from_errno();
const size_t totalTransferred = (size_t)ret;
if(totalTransferred != size)
WARN_RETURN(ERR::IO);
monitor.NotifyOfSuccess(FI_LOWIO, mode, totalTransferred);
return INFO::OK;
}
LibError Issue(aiocb& req, int fd, char mode, off_t alignedOfs, u8* alignedBuf, size_t alignedSize)
{
memset(&req, 0, sizeof(req));
req.aio_lio_opcode = (mode == 'w')? LIO_WRITE : LIO_READ;
req.aio_buf = (volatile void*)alignedBuf;
req.aio_fildes = fd;
req.aio_offset = alignedOfs;
req.aio_nbytes = alignedSize;
struct sigevent* sig = 0; // no notification signal
aiocb* const reqs = &req;
if(lio_listio(LIO_NOWAIT, &reqs, 1, sig) != 0)
return LibError_from_errno();
return INFO::OK;
}
LibError WaitUntilComplete(aiocb& req, u8*& alignedBuf, size_t& alignedSize)
{
// wait for transfer to complete.
while(aio_error(&req) == EINPROGRESS)
{
aiocb* const reqs = &req;
aio_suspend(&reqs, 1, (timespec*)0); // wait indefinitely
}
const ssize_t bytesTransferred = aio_return(&req);
if(bytesTransferred == -1) // transfer failed
WARN_RETURN(ERR::IO);
alignedBuf = (u8*)req.aio_buf; // cast from volatile void*
alignedSize = bytesTransferred;
return INFO::OK;
}
} // namespace FileImpl

View File

@ -28,24 +28,94 @@ namespace ERR
const LibError IO = -110301;
}
struct IFile
LIB_API fs::path path_from_wpath(const fs::wpath& pathname);
namespace FileImpl
{
virtual LibError Open(const fs::path& pathname, char mode) = 0;
virtual LibError Open(const fs::wpath& pathname, char mode) = 0;
virtual void Close() = 0;
LIB_API LibError Open(const fs::path& pathname, char mode, int& fd);
LIB_API void Close(int& fd);
LIB_API LibError IO(int fd, char mode, off_t ofs, u8* buf, size_t size);
LIB_API LibError Issue(aiocb& req, int fd, char mode, off_t alignedOfs, u8* alignedBuf, size_t alignedSize);
LIB_API LibError WaitUntilComplete(aiocb& req, u8*& alignedBuf, size_t& alignedSize);
}
virtual const fs::path& Pathname() const = 0;
virtual char Mode() const = 0;
virtual LibError Issue(aiocb& req, off_t alignedOfs, u8* alignedBuf, size_t alignedSize) const = 0;
virtual LibError WaitUntilComplete(aiocb& req, u8*& alignedBuf, size_t& alignedSize) = 0;
class File
{
NONCOPYABLE(File);
public:
File()
: m_pathname(), m_fd(0)
{
}
virtual LibError Read(off_t ofs, u8* buf, size_t size) const = 0;
virtual LibError Write(off_t ofs, const u8* buf, size_t size) const = 0;
LibError Open(const fs::path& pathname, char mode)
{
RETURN_ERR(FileImpl::Open(pathname, mode, m_fd));
m_pathname = pathname;
m_mode = mode;
return INFO::OK;
}
LibError Open(const fs::wpath& pathname, char mode)
{
m_pathname = path_from_wpath(pathname);
RETURN_ERR(FileImpl::Open(m_pathname, mode, m_fd));
m_mode = mode;
return INFO::OK;
}
void Close()
{
FileImpl::Close(m_fd);
}
File(const fs::path& pathname, char mode)
{
(void)Open(pathname, mode);
}
File(const fs::wpath& pathname, char mode)
{
(void)Open(pathname, mode);
}
~File()
{
Close();
}
const fs::path& Pathname() const
{
return m_pathname;
}
char Mode() const
{
return m_mode;
}
LibError Issue(aiocb& req, char mode, off_t alignedOfs, u8* alignedBuf, size_t alignedSize) const
{
return FileImpl::Issue(req, m_fd, mode, alignedOfs, alignedBuf, alignedSize);
}
LibError Write(off_t ofs, const u8* buf, size_t size)
{
return FileImpl::IO(m_fd, 'w', ofs, const_cast<u8*>(buf), size);
}
LibError Read(off_t ofs, u8* buf, size_t size) const
{
return FileImpl::IO(m_fd, 'r', ofs, buf, size);
}
private:
fs::path m_pathname;
int m_fd;
char m_mode;
};
typedef shared_ptr<IFile> PIFile;
LIB_API PIFile CreateFile_Posix();
typedef shared_ptr<File> PFile;
#endif // #ifndef INCLUDED_FILE

View File

@ -121,9 +121,8 @@ shared_ptr<u8> io_Allocate(size_t size, off_t ofs)
class BlockIo
{
public:
LibError Issue(const PIFile& file, off_t alignedOfs, u8* alignedBuf)
LibError Issue(const PFile& file, off_t alignedOfs, u8* alignedBuf)
{
m_file = file;
m_blockId = BlockId(file->Pathname(), alignedOfs);
if(file->Mode() == 'r')
{
@ -166,7 +165,7 @@ public:
m_alignedBuf = const_cast<u8*>(m_tempBlock.get());
}
return file->Issue(m_req, alignedOfs, m_alignedBuf, BLOCK_SIZE);
return file->Issue(m_req, file->Mode(), alignedOfs, m_alignedBuf, BLOCK_SIZE);
}
LibError WaitUntilComplete(const u8*& block, size_t& blockSize)
@ -178,7 +177,7 @@ public:
return INFO::OK;
}
RETURN_ERR(m_file->WaitUntilComplete(m_req, const_cast<u8*&>(block), blockSize));
RETURN_ERR(FileImpl::WaitUntilComplete(m_req, const_cast<u8*&>(block), blockSize));
if(m_tempBlock)
s_blockCache.Add(m_blockId, m_tempBlock);
@ -189,8 +188,6 @@ public:
private:
static BlockCache s_blockCache;
PIFile m_file;
BlockId m_blockId;
// the address that WaitUntilComplete will return
@ -223,7 +220,7 @@ public:
m_misalignment = size_t(ofs - m_alignedOfs);
}
LibError Run(const PIFile& file, IoCallback cb = 0, uintptr_t cbData = 0)
LibError Run(const PFile& file, IoCallback cb = 0, uintptr_t cbData = 0)
{
ScopedIoMonitor monitor;
@ -302,7 +299,7 @@ private:
};
LibError io_Scan(const PIFile& file, off_t ofs, off_t size, IoCallback cb, uintptr_t cbData)
LibError io_Scan(const PFile& file, off_t ofs, off_t size, IoCallback cb, uintptr_t cbData)
{
u8* alignedBuf = 0; // use temporary block buffers
IoSplitter splitter(ofs, alignedBuf, size);
@ -310,7 +307,7 @@ LibError io_Scan(const PIFile& file, off_t ofs, off_t size, IoCallback cb, uintp
}
LibError io_Read(const PIFile& file, off_t ofs, u8* alignedBuf, off_t size, u8*& data)
LibError io_Read(const PFile& file, off_t ofs, u8* alignedBuf, off_t size, u8*& data)
{
IoSplitter splitter(ofs, alignedBuf, size);
RETURN_ERR(splitter.Run(file));
@ -319,7 +316,7 @@ LibError io_Read(const PIFile& file, off_t ofs, u8* alignedBuf, off_t size, u8*&
}
LibError io_WriteAligned(const PIFile& file, off_t alignedOfs, const u8* alignedData, off_t size)
LibError io_WriteAligned(const PFile& file, off_t alignedOfs, const u8* alignedData, off_t size)
{
debug_assert(IsAligned_Offset(alignedOfs));
debug_assert(IsAligned_Data(alignedData));
@ -329,7 +326,7 @@ LibError io_WriteAligned(const PIFile& file, off_t alignedOfs, const u8* aligned
}
LibError io_ReadAligned(const PIFile& file, off_t alignedOfs, u8* alignedBuf, off_t size)
LibError io_ReadAligned(const PFile& file, off_t alignedOfs, u8* alignedBuf, off_t size)
{
debug_assert(IsAligned_Offset(alignedOfs));
debug_assert(IsAligned_Data(alignedBuf));

View File

@ -40,11 +40,11 @@ LIB_API shared_ptr<u8> io_Allocate(size_t size, off_t ofs = 0);
**/
typedef LibError (*IoCallback)(uintptr_t cbData, const u8* block, size_t blockSize);
LIB_API LibError io_Scan(const PIFile& file, off_t ofs, off_t size, IoCallback cb, uintptr_t cbData);
LIB_API LibError io_Scan(const PFile& file, off_t ofs, off_t size, IoCallback cb, uintptr_t cbData);
LIB_API LibError io_Read(const PIFile& file, off_t ofs, u8* alignedBuf, off_t size, u8*& data);
LIB_API LibError io_Read(const PFile& file, off_t ofs, u8* alignedBuf, off_t size, u8*& data);
LIB_API LibError io_WriteAligned(const PIFile& file, off_t alignedOfs, const u8* alignedData, off_t size);
LIB_API LibError io_ReadAligned(const PIFile& file, off_t alignedOfs, u8* alignedBuf, off_t size);
LIB_API LibError io_WriteAligned(const PFile& file, off_t alignedOfs, const u8* alignedData, off_t size);
LIB_API LibError io_ReadAligned(const PFile& file, off_t alignedOfs, u8* alignedBuf, off_t size);
#endif // #ifndef INCLUDED_IO

View File

@ -56,7 +56,7 @@ void WriteBuffer::Overwrite(const void* data, size_t size, size_t offset)
// UnalignedWriter
//-----------------------------------------------------------------------------
UnalignedWriter::UnalignedWriter(const PIFile& file, off_t ofs)
UnalignedWriter::UnalignedWriter(const PFile& file, off_t ofs)
: m_file(file), m_alignedBuf(io_Allocate(BLOCK_SIZE))
{
m_alignedOfs = AlignedOffset(ofs);

View File

@ -50,7 +50,7 @@ class UnalignedWriter
{
NONCOPYABLE(UnalignedWriter);
public:
UnalignedWriter(const PIFile& file, off_t ofs);
UnalignedWriter(const PFile& file, off_t ofs);
~UnalignedWriter();
/**
@ -67,7 +67,7 @@ public:
private:
LibError WriteBlock() const;
PIFile m_file;
PFile m_file;
shared_ptr<u8> m_alignedBuf;
mutable off_t m_alignedOfs;
mutable size_t m_bytesUsed;

View File

@ -51,6 +51,8 @@ enum VfsMountFlags
struct IVFS
{
virtual ~IVFS() {}
/**
* mount a directory into the VFS.
*

View File

@ -19,11 +19,11 @@
* detection of CPU and cache topology
*/
#include <set>
#include "precompiled.h"
#include "topology.h"
#include <set>
#include "lib/bits.h"
#include "lib/sysdep/cpu.h" // ERR::CPU_FEATURE_MISSING
#include "lib/sysdep/os_cpu.h"

View File

@ -52,10 +52,10 @@ public:
// retrieve capabilities and ID
{
const u64 caps_and_id = Read64(CAPS_AND_ID);
const u8 revision = bits(caps_and_id, 0, 7);
const u8 revision = (u8)bits(caps_and_id, 0, 7);
debug_assert(revision != 0); // "the value must NOT be 00h"
m_counterBits = (caps_and_id & Bit<u64>(13))? 64 : 32;
const u16 vendorID = bits(caps_and_id, 16, 31);
const u16 vendorID = (u16)bits(caps_and_id, 16, 31);
const u32 period_fs = (u32)bits(caps_and_id, 32, 63);
debug_assert(period_fs != 0); // "a value of 0 in this field is not permitted"
debug_assert(period_fs <= 0x05F5E100); // 100 ns (min freq is 10 MHz)

View File

@ -28,9 +28,12 @@
// (use VC8's stat because it defines helpful inline macros)
#include <sys/stat.h>
// defined by MinGW but not VC
#if MSC_VERSION
// defined by MinGW but not VC
typedef unsigned int mode_t;
// we need 64-bit st_size and time_t currently defaults to 64-bit
#define stat _stat64
#endif
// (christmas-tree values because mkdir mode is ignored anyway)