src: major cleanups, introduce new eXtended Span class
- initial minimally invasive eXtended Span implementation - rename ptr_diff to ptr_diff_bytes - move some files to util subdir - lots of cleanups - start using the new checked pointers - this needs some real-world testing
This commit is contained in:
+88
-246
@@ -25,59 +25,48 @@
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "file.h"
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
// static functions
|
||||
**************************************************************************/
|
||||
|
||||
void File::chmod(const char *name, int mode)
|
||||
{
|
||||
void FileBase::chmod(const char *name, int mode) {
|
||||
#if (HAVE_CHMOD)
|
||||
if (::chmod(name,mode) != 0)
|
||||
throwIOException(name,errno);
|
||||
if (::chmod(name, mode) != 0)
|
||||
throwIOException(name, errno);
|
||||
#else
|
||||
UNUSED(name); UNUSED(mode);
|
||||
UNUSED(name);
|
||||
UNUSED(mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void File::rename(const char *old_, const char *new_)
|
||||
{
|
||||
void FileBase::rename(const char *old_, const char *new_) {
|
||||
#if (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||
if (::_rename(old_,new_) != 0)
|
||||
if (::_rename(old_, new_) != 0)
|
||||
#else
|
||||
if (::rename(old_,new_) != 0)
|
||||
if (::rename(old_, new_) != 0)
|
||||
#endif
|
||||
throwIOException("rename error",errno);
|
||||
throwIOException("rename error", errno);
|
||||
}
|
||||
|
||||
|
||||
void File::unlink(const char *name)
|
||||
{
|
||||
void FileBase::unlink(const char *name) {
|
||||
if (::unlink(name) != 0)
|
||||
throwIOException(name,errno);
|
||||
throwIOException(name, errno);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
FileBase::FileBase() :
|
||||
_fd(-1), _flags(0), _shflags(0), _mode(0), _name(nullptr), _offset(0), _length(0)
|
||||
{
|
||||
memset(&st,0,sizeof(st));
|
||||
FileBase::FileBase()
|
||||
: _fd(-1), _flags(0), _shflags(0), _mode(0), _name(nullptr), _offset(0), _length(0) {
|
||||
memset(&st, 0, sizeof(st));
|
||||
}
|
||||
|
||||
|
||||
FileBase::~FileBase()
|
||||
{
|
||||
#if 0 && defined(__GNUC__) // debug
|
||||
FileBase::~FileBase() {
|
||||
#if 0 && defined(__GNUC__) // debug
|
||||
if (isOpen())
|
||||
fprintf(stderr,"%s: %s\n", _name, __PRETTY_FUNCTION__);
|
||||
#endif
|
||||
@@ -87,17 +76,14 @@ FileBase::~FileBase()
|
||||
closex();
|
||||
}
|
||||
|
||||
|
||||
bool FileBase::do_sopen()
|
||||
{
|
||||
bool FileBase::do_sopen() {
|
||||
if (_shflags < 0)
|
||||
_fd = ::open(_name, _flags, _mode);
|
||||
else
|
||||
{
|
||||
else {
|
||||
#if (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||
_fd = ::open(_name,_flags | _shflags, _mode);
|
||||
_fd = ::open(_name, _flags | _shflags, _mode);
|
||||
#elif defined(__MINT__)
|
||||
_fd = ::open(_name,_flags | (_shflags & O_SHMODE), _mode);
|
||||
_fd = ::open(_name, _flags | (_shflags & O_SHMODE), _mode);
|
||||
#elif defined(SH_DENYRW)
|
||||
_fd = ::sopen(_name, _flags, _shflags, _mode);
|
||||
#else
|
||||
@@ -112,9 +98,7 @@ bool FileBase::do_sopen()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FileBase::close()
|
||||
{
|
||||
bool FileBase::close() {
|
||||
bool ok = true;
|
||||
if (isOpen() && _fd != STDIN_FILENO && _fd != STDOUT_FILENO && _fd != STDERR_FILENO)
|
||||
if (::close(_fd) == -1)
|
||||
@@ -128,53 +112,15 @@ bool FileBase::close()
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
void FileBase::closex()
|
||||
{
|
||||
void FileBase::closex() {
|
||||
if (!close())
|
||||
throwIOException("close failed",errno);
|
||||
throwIOException("close failed", errno);
|
||||
}
|
||||
|
||||
|
||||
int FileBase::read(void *buf, int len)
|
||||
{
|
||||
if (!isOpen() || len < 0)
|
||||
throwIOException("bad read");
|
||||
mem_size_assert(1, len); // sanity check
|
||||
errno = 0;
|
||||
long l = acc_safe_hread(_fd, buf, len);
|
||||
if (errno)
|
||||
throwIOException("read error",errno);
|
||||
return (int) l;
|
||||
}
|
||||
|
||||
|
||||
int FileBase::readx(void *buf, int len)
|
||||
{
|
||||
int l = this->read(buf, len);
|
||||
if (l != len)
|
||||
throwEOFException();
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
void FileBase::write(const void *buf, int len)
|
||||
{
|
||||
if (!isOpen() || len < 0)
|
||||
throwIOException("bad write");
|
||||
mem_size_assert(1, len); // sanity check
|
||||
errno = 0;
|
||||
long l = acc_safe_hwrite(_fd, buf, len);
|
||||
if (l != len)
|
||||
throwIOException("write error",errno);
|
||||
}
|
||||
|
||||
|
||||
upx_off_t FileBase::seek(upx_off_t off, int whence)
|
||||
{
|
||||
mem_size_assert(1, off >= 0 ? off : -off); // sanity check
|
||||
upx_off_t FileBase::seek(upx_off_t off, int whence) {
|
||||
if (!isOpen())
|
||||
throwIOException("bad seek 1");
|
||||
mem_size_assert(1, off >= 0 ? off : -off); // sanity check
|
||||
if (whence == SEEK_SET) {
|
||||
if (off < 0)
|
||||
throwIOException("bad seek 2");
|
||||
@@ -186,51 +132,34 @@ upx_off_t FileBase::seek(upx_off_t off, int whence)
|
||||
off += _offset + _length;
|
||||
whence = SEEK_SET;
|
||||
}
|
||||
if (::lseek(_fd,off,whence) < 0)
|
||||
throwIOException("seek error",errno);
|
||||
if (::lseek(_fd, off, whence) < 0)
|
||||
throwIOException("seek error", errno);
|
||||
return off - _offset;
|
||||
}
|
||||
|
||||
|
||||
upx_off_t FileBase::tell() const
|
||||
{
|
||||
upx_off_t FileBase::tell() const {
|
||||
if (!isOpen())
|
||||
throwIOException("bad tell");
|
||||
upx_off_t l = ::lseek(_fd, 0, SEEK_CUR);
|
||||
if (l < 0)
|
||||
throwIOException("tell error",errno);
|
||||
throwIOException("tell error", errno);
|
||||
return l - _offset;
|
||||
}
|
||||
|
||||
|
||||
void FileBase::set_extent(upx_off_t offset, upx_off_t length)
|
||||
{
|
||||
void FileBase::set_extent(upx_off_t offset, upx_off_t length) {
|
||||
_offset = offset;
|
||||
_length = length;
|
||||
}
|
||||
|
||||
upx_off_t FileBase::st_size() const
|
||||
{
|
||||
return _length;
|
||||
}
|
||||
|
||||
upx_off_t FileBase::st_size() const { return _length; }
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
InputFile::InputFile()
|
||||
{
|
||||
}
|
||||
InputFile::InputFile() {}
|
||||
|
||||
|
||||
InputFile::~InputFile()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void InputFile::sopen(const char *name, int flags, int shflags)
|
||||
{
|
||||
void InputFile::sopen(const char *name, int flags, int shflags) {
|
||||
close();
|
||||
_name = name;
|
||||
_flags = flags;
|
||||
@@ -238,8 +167,7 @@ void InputFile::sopen(const char *name, int flags, int shflags)
|
||||
_mode = 0;
|
||||
_offset = 0;
|
||||
_length = 0;
|
||||
if (!FileBase::do_sopen())
|
||||
{
|
||||
if (!super::do_sopen()) {
|
||||
if (errno == ENOENT)
|
||||
throw FileNotFoundException(_name, errno);
|
||||
else if (errno == EEXIST)
|
||||
@@ -250,80 +178,40 @@ void InputFile::sopen(const char *name, int flags, int shflags)
|
||||
_length_orig = _length;
|
||||
}
|
||||
|
||||
|
||||
int InputFile::read(void *buf, int len)
|
||||
{
|
||||
return super::read(buf, len);
|
||||
int InputFile::read(SPAN_P(void) buf, int len) {
|
||||
if (!isOpen() || len < 0)
|
||||
throwIOException("bad read");
|
||||
mem_size_assert(1, len); // sanity check
|
||||
errno = 0;
|
||||
long l = acc_safe_hread(_fd, raw_bytes(buf, len), len);
|
||||
if (errno)
|
||||
throwIOException("read error", errno);
|
||||
return (int) l;
|
||||
}
|
||||
|
||||
int InputFile::readx(void *buf, int len)
|
||||
{
|
||||
return super::readx(buf, len);
|
||||
int InputFile::readx(SPAN_P(void) buf, int len) {
|
||||
int l = this->read(buf, len);
|
||||
if (l != len)
|
||||
throwEOFException();
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
int InputFile::read(MemBuffer *buf, int len)
|
||||
{
|
||||
buf->checkState();
|
||||
assert((unsigned)len <= buf->getSize());
|
||||
return read(buf->getVoidPtr(), len);
|
||||
}
|
||||
|
||||
int InputFile::readx(MemBuffer *buf, int len)
|
||||
{
|
||||
buf->checkState();
|
||||
assert((unsigned)len <= buf->getSize());
|
||||
return read(buf->getVoidPtr(), len);
|
||||
}
|
||||
|
||||
|
||||
int InputFile::read(MemBuffer &buf, int len)
|
||||
{
|
||||
return read(&buf, len);
|
||||
}
|
||||
|
||||
int InputFile::readx(MemBuffer &buf, int len)
|
||||
{
|
||||
return readx(&buf, len);
|
||||
}
|
||||
|
||||
|
||||
upx_off_t InputFile::seek(upx_off_t off, int whence)
|
||||
{
|
||||
upx_off_t InputFile::seek(upx_off_t off, int whence) {
|
||||
upx_off_t pos = super::seek(off, whence);
|
||||
if (_length < pos)
|
||||
throwIOException("bad seek 4");
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
upx_off_t InputFile::tell() const
|
||||
{
|
||||
return super::tell();
|
||||
}
|
||||
|
||||
upx_off_t InputFile::st_size_orig() const
|
||||
{
|
||||
return _length_orig;
|
||||
}
|
||||
upx_off_t InputFile::st_size_orig() const { return _length_orig; }
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
OutputFile::OutputFile() :
|
||||
bytes_written(0)
|
||||
{
|
||||
}
|
||||
OutputFile::OutputFile() : bytes_written(0) {}
|
||||
|
||||
|
||||
OutputFile::~OutputFile()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void OutputFile::sopen(const char *name, int flags, int shflags, int mode)
|
||||
{
|
||||
void OutputFile::sopen(const char *name, int flags, int shflags, int mode) {
|
||||
close();
|
||||
_name = name;
|
||||
_flags = flags;
|
||||
@@ -331,8 +219,7 @@ void OutputFile::sopen(const char *name, int flags, int shflags, int mode)
|
||||
_mode = mode;
|
||||
_offset = 0;
|
||||
_length = 0;
|
||||
if (!FileBase::do_sopen())
|
||||
{
|
||||
if (!super::do_sopen()) {
|
||||
#if 0
|
||||
// don't throw FileNotFound here -- this is confusing
|
||||
if (errno == ENOENT)
|
||||
@@ -340,15 +227,13 @@ void OutputFile::sopen(const char *name, int flags, int shflags, int mode)
|
||||
else
|
||||
#endif
|
||||
if (errno == EEXIST)
|
||||
throw FileAlreadyExistsException(_name,errno);
|
||||
throw FileAlreadyExistsException(_name, errno);
|
||||
else
|
||||
throwIOException(_name,errno);
|
||||
throwIOException(_name, errno);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool OutputFile::openStdout(int flags, bool force)
|
||||
{
|
||||
bool OutputFile::openStdout(int flags, bool force) {
|
||||
close();
|
||||
int fd = STDOUT_FILENO;
|
||||
if (!force && acc_isatty(fd))
|
||||
@@ -365,17 +250,27 @@ bool OutputFile::openStdout(int flags, bool force)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void OutputFile::write(const void *buf, int len)
|
||||
{
|
||||
super::write(buf, len);
|
||||
void OutputFile::write(SPAN_0(const void) buf, int len) {
|
||||
if (!isOpen() || len < 0)
|
||||
throwIOException("bad write");
|
||||
// allow nullptr if len == 0
|
||||
if (len == 0)
|
||||
return;
|
||||
mem_size_assert(1, len); // sanity check
|
||||
errno = 0;
|
||||
#if 0
|
||||
fprintf(stderr, "write %p %zd (%p) %d\n", buf.raw_ptr(), buf.raw_size_in_bytes(),
|
||||
buf.raw_base(), len);
|
||||
#endif
|
||||
long l = acc_safe_hwrite(_fd, raw_bytes(buf, len), len);
|
||||
if (l != len)
|
||||
throwIOException("write error", errno);
|
||||
bytes_written += len;
|
||||
}
|
||||
|
||||
upx_off_t OutputFile::st_size() const
|
||||
{
|
||||
if (opt->to_stdout) { // might be a pipe ==> .st_size is invalid
|
||||
return bytes_written; // too big if seek()+write() instead of rewrite()
|
||||
upx_off_t OutputFile::st_size() const {
|
||||
if (opt->to_stdout) { // might be a pipe ==> .st_size is invalid
|
||||
return bytes_written; // too big if seek()+write() instead of rewrite()
|
||||
}
|
||||
struct stat my_st;
|
||||
my_st.st_size = 0;
|
||||
@@ -384,34 +279,13 @@ upx_off_t OutputFile::st_size() const
|
||||
return my_st.st_size;
|
||||
}
|
||||
|
||||
|
||||
void OutputFile::write(const MemBuffer *buf, int len)
|
||||
{
|
||||
buf->checkState();
|
||||
assert((unsigned)len <= buf->getSize());
|
||||
write(buf->getVoidPtr(), len);
|
||||
}
|
||||
|
||||
|
||||
void OutputFile::write(const MemBuffer &buf, int len)
|
||||
{
|
||||
write(&buf, len);
|
||||
}
|
||||
|
||||
void OutputFile::rewrite(const void *buf, int len)
|
||||
{
|
||||
void OutputFile::rewrite(SPAN_P(const void) buf, int len) {
|
||||
assert(!opt->to_stdout);
|
||||
write(buf, len);
|
||||
bytes_written -= len; // restore
|
||||
bytes_written -= len; // restore
|
||||
}
|
||||
|
||||
upx_off_t OutputFile::tell() const
|
||||
{
|
||||
return super::tell();
|
||||
}
|
||||
|
||||
upx_off_t OutputFile::seek(upx_off_t off, int whence)
|
||||
{
|
||||
upx_off_t OutputFile::seek(upx_off_t off, int whence) {
|
||||
mem_size_assert(1, off >= 0 ? off : -off); // sanity check
|
||||
assert(!opt->to_stdout);
|
||||
switch (whence) {
|
||||
@@ -419,18 +293,18 @@ upx_off_t OutputFile::seek(upx_off_t off, int whence)
|
||||
if (bytes_written < off) {
|
||||
bytes_written = off;
|
||||
}
|
||||
_length = bytes_written; // cheap, lazy update; needed?
|
||||
_length = bytes_written; // cheap, lazy update; needed?
|
||||
} break;
|
||||
case SEEK_END: {
|
||||
_length = bytes_written; // necessary
|
||||
_length = bytes_written; // necessary
|
||||
} break;
|
||||
}
|
||||
return super::seek(off,whence);
|
||||
return super::seek(off, whence);
|
||||
}
|
||||
|
||||
// WARNING: fsync() does not exist in some Windows environments.
|
||||
// This trick works only on UNIX-like systems.
|
||||
//int OutputFile::read(void *buf, int len)
|
||||
// int OutputFile::read(void *buf, int len)
|
||||
//{
|
||||
// fsync(_fd);
|
||||
// InputFile infile;
|
||||
@@ -439,19 +313,17 @@ upx_off_t OutputFile::seek(upx_off_t off, int whence)
|
||||
// return infile.read(buf, len);
|
||||
//}
|
||||
|
||||
void OutputFile::set_extent(upx_off_t offset, upx_off_t length)
|
||||
{
|
||||
void OutputFile::set_extent(upx_off_t offset, upx_off_t length) {
|
||||
super::set_extent(offset, length);
|
||||
bytes_written = 0;
|
||||
if (0==offset && (upx_off_t)~0u==length) {
|
||||
if (0 == offset && (upx_off_t) ~0u == length) {
|
||||
if (::fstat(_fd, &st) != 0)
|
||||
throwIOException(_name, errno);
|
||||
_length = st.st_size - offset;
|
||||
}
|
||||
}
|
||||
|
||||
upx_off_t OutputFile::unset_extent()
|
||||
{
|
||||
upx_off_t OutputFile::unset_extent() {
|
||||
upx_off_t l = ::lseek(_fd, 0, SEEK_END);
|
||||
if (l < 0)
|
||||
throwIOException("lseek error", errno);
|
||||
@@ -461,44 +333,14 @@ upx_off_t OutputFile::unset_extent()
|
||||
return _length;
|
||||
}
|
||||
|
||||
void OutputFile::dump(const char *name, const void *buf, int len, int flags)
|
||||
{
|
||||
void OutputFile::dump(const char *name, SPAN_P(const void) buf, int len, int flags) {
|
||||
if (flags < 0)
|
||||
flags = O_CREAT | O_TRUNC;
|
||||
flags = O_CREAT | O_TRUNC;
|
||||
flags |= O_WRONLY | O_BINARY;
|
||||
OutputFile f;
|
||||
f.open(name, flags, 0600);
|
||||
f.write(buf, len);
|
||||
f.write(raw_bytes(buf, len), len);
|
||||
f.closex();
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
#if 0
|
||||
|
||||
MemoryOutputFile::MemoryOutputFile() :
|
||||
b(nullptr), b_size(0), b_pos(0), bytes_written(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void MemoryOutputFile::write(const void *buf, int len)
|
||||
{
|
||||
if (!isOpen() || len < 0)
|
||||
throwIOException("bad write");
|
||||
if (len == 0)
|
||||
return;
|
||||
if (b_pos + len > b_size)
|
||||
throwIOException("write error",ENOSPC);
|
||||
memcpy(b + b_pos, buf, len);
|
||||
b_pos += len;
|
||||
bytes_written += len;
|
||||
}
|
||||
|
||||
|
||||
#endif /* if 0 */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
Reference in New Issue
Block a user