#3130: fix error handling: report original error before close()

This commit is contained in:
Günter Obiltschnig 2021-06-14 18:59:56 +02:00
parent 90be9b0e53
commit 97ae6924dd
2 changed files with 36 additions and 22 deletions

View File

@ -65,6 +65,7 @@ protected:
FileSizeImpl totalSpaceImpl() const;
FileSizeImpl usableSpaceImpl() const;
FileSizeImpl freeSpaceImpl() const;
static void handleLastErrorImpl(int err, const std::string& path);
static void handleLastErrorImpl(const std::string& path);
private:

View File

@ -336,8 +336,9 @@ void FileImpl::copyToImpl(const std::string& path, int options) const
struct stat st;
if (fstat(sd, &st) != 0)
{
int err = errno;
close(sd);
handleLastErrorImpl(_path);
handleLastErrorImpl(err, _path);
}
const long blockSize = st.st_blksize;
int dd;
@ -348,8 +349,9 @@ void FileImpl::copyToImpl(const std::string& path, int options) const
}
if (dd == -1)
{
int err = errno;
close(sd);
handleLastErrorImpl(path);
handleLastErrorImpl(err, path);
}
Buffer<char> buffer(blockSize);
try
@ -361,8 +363,10 @@ void FileImpl::copyToImpl(const std::string& path, int options) const
handleLastErrorImpl(path);
}
if (n < 0)
{
handleLastErrorImpl(_path);
}
}
catch (...)
{
close(sd);
@ -372,11 +376,14 @@ void FileImpl::copyToImpl(const std::string& path, int options) const
close(sd);
if (fsync(dd) != 0)
{
int err = errno;
close(dd);
handleLastErrorImpl(path);
handleLastErrorImpl(err, path);
}
if (close(dd) != 0)
{
handleLastErrorImpl(path);
}
}
@ -490,43 +497,49 @@ FileImpl::FileSizeImpl FileImpl::freeSpaceImpl() const
}
void FileImpl::handleLastErrorImpl(const std::string& path)
void FileImpl::handleLastErrorImpl(int err, const std::string& path)
{
switch (errno)
switch (err)
{
case EIO:
throw IOException(path, errno);
throw IOException(path, err);
case EPERM:
throw FileAccessDeniedException("insufficient permissions", path, errno);
throw FileAccessDeniedException("insufficient permissions", path, err);
case EACCES:
throw FileAccessDeniedException(path, errno);
throw FileAccessDeniedException(path, err);
case ENOENT:
throw FileNotFoundException(path, errno);
throw FileNotFoundException(path, err);
case ENOTDIR:
throw OpenFileException("not a directory", path, errno);
throw OpenFileException("not a directory", path, err);
case EISDIR:
throw OpenFileException("not a file", path, errno);
throw OpenFileException("not a file", path, err);
case EROFS:
throw FileReadOnlyException(path, errno);
throw FileReadOnlyException(path, err);
case EEXIST:
throw FileExistsException(path, errno);
throw FileExistsException(path, err);
case ENOSPC:
throw FileException("no space left on device", path, errno);
throw FileException("no space left on device", path, err);
case EDQUOT:
throw FileException("disk quota exceeded", path, errno);
throw FileException("disk quota exceeded", path, err);
#if !defined(_AIX)
case ENOTEMPTY:
throw DirectoryNotEmptyException(path, errno);
throw DirectoryNotEmptyException(path, err);
#endif
case ENAMETOOLONG:
throw PathSyntaxException(path, errno);
throw PathSyntaxException(path, err);
case ENFILE:
case EMFILE:
throw FileException("too many open files", path, errno);
throw FileException("too many open files", path, err);
default:
throw FileException(Error::getMessage(errno), path, errno);
throw FileException(Error::getMessage(err), path, err);
}
}
void FileImpl::handleLastErrorImpl(const std::string& path)
{
handleLastErrorImpl(errno, path);
}
} // namespace Poco