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 $@ $(MAKE) -C doc $@
ifneq ($(wildcard .hg/data/.),) ifneq ($(wildcard .hg/.),)
# automatically generate ChangeLog from local Mercurial repo # automatically generate ChangeLog from local Mercurial repo
ChangeLog: ChangeLog:
hg log --style=changelog > $@ hg log --style=changelog > $@

View File

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

View File

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

View File

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