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:
Markus F.X.J. Oberhumer
2022-09-11 16:03:56 +02:00
parent 4318cc22ee
commit c75d7a685d
54 changed files with 3521 additions and 1196 deletions
+88 -246
View File
@@ -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: */