Improved IO error checking.

This commit is contained in:
Markus F.X.J. Oberhumer 2007-11-06 03:21:32 +01:00
parent eab5da075a
commit 07baed1581
4 changed files with 48 additions and 28 deletions

View File

@ -36,7 +36,7 @@ endif
$(MAKE) -C doc $@
ifneq ($(wildcard .hg/data/.),)
ifneq ($(wildcard .hg/.),)
# automatically generate ChangeLog from local Mercurial repo
ChangeLog:
hg log --style=changelog > $@

View File

@ -88,7 +88,7 @@ FileBase::~FileBase()
}
void FileBase::sopen()
bool FileBase::do_sopen()
{
if (_shflags < 0)
_fd = ::open(_name, _flags, _mode);
@ -101,13 +101,15 @@ void FileBase::sopen()
#elif defined(SH_DENYRW)
_fd = ::sopen(_name, _flags, _shflags, _mode);
#else
assert(0);
throwInternalError("bad usage of do_sopen()");
#endif
}
if (!(_fd < 0)) {
::fstat(_fd, &st);
_length = st.st_size;
}
if (_fd < 0)
return false;
if (::fstat(_fd, &st) != 0)
throwIOException(_name, errno);
_length = st.st_size;
return true;
}
@ -232,8 +234,7 @@ void InputFile::sopen(const char *name, int flags, int shflags)
_mode = 0;
_offset = 0;
_length = 0;
FileBase::sopen();
if (!isOpen())
if (!FileBase::do_sopen())
{
if (errno == ENOENT)
throw FileNotFoundException(_name, errno);
@ -318,8 +319,7 @@ void OutputFile::sopen(const char *name, int flags, int shflags, int mode)
_mode = mode;
_offset = 0;
_length = 0;
FileBase::sopen();
if (!isOpen())
if (!FileBase::do_sopen())
{
#if 0
// don't throw FileNotFound here -- this is confusing
@ -366,7 +366,8 @@ off_t OutputFile::st_size() const
return bytes_written; // too big if seek()+write() instead of rewrite()
}
struct stat my_st;
::fstat(_fd, &my_st);
if (::fstat(_fd, &my_st) != 0)
throwIOException(_name, errno);
return my_st.st_size;
}
@ -402,15 +403,19 @@ void OutputFile::set_extent(off_t offset, off_t length)
super::set_extent(offset, length);
bytes_written = 0;
if (0==offset && (off_t)~0u==length) {
::fstat(_fd, &st);
if (::fstat(_fd, &st) != 0)
throwIOException(_name, errno);
_length = st.st_size - offset;
}
}
off_t OutputFile::unset_extent()
{
off_t l = ::lseek(_fd, 0, SEEK_END);
if (l < 0)
throwIOException("lseek error", errno);
_offset = 0;
_length = ::lseek(_fd, 0, SEEK_END);
_length = l;
bytes_written = _length;
return _length;
}

View File

@ -63,7 +63,7 @@ public:
virtual void set_extent(off_t offset, off_t length);
protected:
void sopen();
bool do_sopen();
virtual int read(void *buf, int len);
virtual int readx(void *buf, int len);
virtual void write(const void *buf, int len);

View File

@ -51,6 +51,9 @@
# define SH_DENYWR (-1)
#endif
// ignore errors in some cases and silence __attribute__((__warn_unused_result__))
#define IGNORE_ERROR(var) ACC_UNUSED(var)
/*************************************************************************
// process one file
@ -98,8 +101,13 @@ void do_one_file(const char *iname, char *oname)
fi.sopen(iname, O_RDONLY | O_BINARY, SH_DENYWR);
#if defined(USE_FTIME)
struct ftime fit;
getftime(fi.getFd(),&fit);
struct ftime fi_ftime;
memset(&fi_ftime, 0, sizeof(fi_ftime));
if (opt->preserve_timestamp)
{
if (getftime(fi.getFd(), &fi_ftime) != 0)
throwIOException("cannot determine file timestamp");
}
#endif
// open output file
@ -124,9 +132,11 @@ void do_one_file(const char *iname, char *oname)
if (opt->force >= 2)
{
#if defined(HAVE_CHMOD)
(void) ::chmod(tname, 0777);
r = chmod(tname, 0777);
IGNORE_ERROR(r);
#endif
(void) ::unlink(tname);
r = unlink(tname);
IGNORE_ERROR(r);
}
int flags = O_CREAT | O_WRONLY | O_BINARY;
if (opt->force)
@ -165,15 +175,17 @@ void do_one_file(const char *iname, char *oname)
throwInternalError("invalid command");
// copy time stamp
if (oname[0] && fo.isOpen())
if (opt->preserve_timestamp && oname[0] && fo.isOpen())
{
#if defined(USE_FTIME)
setftime(fo.getFd(),&fit);
r = setftime(fo.getFd(), &fi_ftime);
IGNORE_ERROR(r);
#elif defined(USE__FUTIME)
struct _utimbuf u;
u.actime = st.st_atime;
u.modtime = st.st_mtime;
(void) _futime(fo.getFd(),&u);
r = _futime(fo.getFd(), &u);
IGNORE_ERROR(r);
#endif
}
@ -188,7 +200,8 @@ void do_one_file(const char *iname, char *oname)
if (!opt->backup)
{
#if defined(HAVE_CHMOD)
(void) ::chmod(iname, 0777);
r = chmod(iname, 0777);
IGNORE_ERROR(r);
#endif
File::unlink(iname);
}
@ -217,7 +230,7 @@ void do_one_file(const char *iname, char *oname)
u.actime = st.st_atime;
u.modtime = st.st_mtime;
r = utime(name, &u);
UNUSED(r);
IGNORE_ERROR(r);
}
#endif
#if defined(HAVE_CHMOD)
@ -225,7 +238,7 @@ void do_one_file(const char *iname, char *oname)
if (opt->preserve_mode)
{
r = chmod(name, st.st_mode);
UNUSED(r);
IGNORE_ERROR(r);
}
#endif
#if defined(HAVE_CHOWN)
@ -233,7 +246,7 @@ void do_one_file(const char *iname, char *oname)
if (opt->preserve_ownership)
{
r = chown(name, st.st_uid, st.st_gid);
UNUSED(r);
IGNORE_ERROR(r);
}
#endif
}
@ -251,9 +264,11 @@ static void unlink_ofile(char *oname)
if (oname && oname[0])
{
#if defined(HAVE_CHMOD)
(void) ::chmod(oname, 0777);
int r;
r = chmod(oname, 0777);
IGNORE_ERROR(r);
#endif
if (::unlink(oname) == 0)
if (unlink(oname) == 0)
oname[0] = 0;
}
}