mirror of
https://github.com/pocoproject/poco.git
synced 2025-04-01 09:24:55 +02:00
#3130: fix error handling: report original error before close()
This commit is contained in:
parent
90be9b0e53
commit
97ae6924dd
@ -27,7 +27,7 @@ namespace Poco {
|
|||||||
class FileImpl
|
class FileImpl
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
enum Options
|
enum Options
|
||||||
{
|
{
|
||||||
OPT_FAIL_ON_OVERWRITE_IMPL = 0x01
|
OPT_FAIL_ON_OVERWRITE_IMPL = 0x01
|
||||||
};
|
};
|
||||||
@ -65,6 +65,7 @@ protected:
|
|||||||
FileSizeImpl totalSpaceImpl() const;
|
FileSizeImpl totalSpaceImpl() const;
|
||||||
FileSizeImpl usableSpaceImpl() const;
|
FileSizeImpl usableSpaceImpl() const;
|
||||||
FileSizeImpl freeSpaceImpl() const;
|
FileSizeImpl freeSpaceImpl() const;
|
||||||
|
static void handleLastErrorImpl(int err, const std::string& path);
|
||||||
static void handleLastErrorImpl(const std::string& path);
|
static void handleLastErrorImpl(const std::string& path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -336,20 +336,22 @@ void FileImpl::copyToImpl(const std::string& path, int options) const
|
|||||||
struct stat st;
|
struct stat st;
|
||||||
if (fstat(sd, &st) != 0)
|
if (fstat(sd, &st) != 0)
|
||||||
{
|
{
|
||||||
|
int err = errno;
|
||||||
close(sd);
|
close(sd);
|
||||||
handleLastErrorImpl(_path);
|
handleLastErrorImpl(err, _path);
|
||||||
}
|
}
|
||||||
const long blockSize = st.st_blksize;
|
const long blockSize = st.st_blksize;
|
||||||
int dd;
|
int dd;
|
||||||
if (options & OPT_FAIL_ON_OVERWRITE_IMPL) {
|
if (options & OPT_FAIL_ON_OVERWRITE_IMPL) {
|
||||||
dd = open(path.c_str(), O_CREAT | O_TRUNC | O_EXCL | O_WRONLY, st.st_mode);
|
dd = open(path.c_str(), O_CREAT | O_TRUNC | O_EXCL | O_WRONLY, st.st_mode);
|
||||||
} else {
|
} else {
|
||||||
dd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, st.st_mode);
|
dd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, st.st_mode);
|
||||||
}
|
}
|
||||||
if (dd == -1)
|
if (dd == -1)
|
||||||
{
|
{
|
||||||
|
int err = errno;
|
||||||
close(sd);
|
close(sd);
|
||||||
handleLastErrorImpl(path);
|
handleLastErrorImpl(err, path);
|
||||||
}
|
}
|
||||||
Buffer<char> buffer(blockSize);
|
Buffer<char> buffer(blockSize);
|
||||||
try
|
try
|
||||||
@ -361,7 +363,9 @@ void FileImpl::copyToImpl(const std::string& path, int options) const
|
|||||||
handleLastErrorImpl(path);
|
handleLastErrorImpl(path);
|
||||||
}
|
}
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
|
{
|
||||||
handleLastErrorImpl(_path);
|
handleLastErrorImpl(_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
@ -372,11 +376,14 @@ void FileImpl::copyToImpl(const std::string& path, int options) const
|
|||||||
close(sd);
|
close(sd);
|
||||||
if (fsync(dd) != 0)
|
if (fsync(dd) != 0)
|
||||||
{
|
{
|
||||||
|
int err = errno;
|
||||||
close(dd);
|
close(dd);
|
||||||
handleLastErrorImpl(path);
|
handleLastErrorImpl(err, path);
|
||||||
}
|
}
|
||||||
if (close(dd) != 0)
|
if (close(dd) != 0)
|
||||||
|
{
|
||||||
handleLastErrorImpl(path);
|
handleLastErrorImpl(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -387,7 +394,7 @@ void FileImpl::renameToImpl(const std::string& path, int options)
|
|||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (stat(path.c_str(), &st) == 0 && (options & OPT_FAIL_ON_OVERWRITE_IMPL))
|
if (stat(path.c_str(), &st) == 0 && (options & OPT_FAIL_ON_OVERWRITE_IMPL))
|
||||||
throw FileExistsException(path, EEXIST);
|
throw FileExistsException(path, EEXIST);
|
||||||
|
|
||||||
if (rename(_path.c_str(), path.c_str()) != 0)
|
if (rename(_path.c_str(), path.c_str()) != 0)
|
||||||
handleLastErrorImpl(_path);
|
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:
|
case EIO:
|
||||||
throw IOException(path, errno);
|
throw IOException(path, err);
|
||||||
case EPERM:
|
case EPERM:
|
||||||
throw FileAccessDeniedException("insufficient permissions", path, errno);
|
throw FileAccessDeniedException("insufficient permissions", path, err);
|
||||||
case EACCES:
|
case EACCES:
|
||||||
throw FileAccessDeniedException(path, errno);
|
throw FileAccessDeniedException(path, err);
|
||||||
case ENOENT:
|
case ENOENT:
|
||||||
throw FileNotFoundException(path, errno);
|
throw FileNotFoundException(path, err);
|
||||||
case ENOTDIR:
|
case ENOTDIR:
|
||||||
throw OpenFileException("not a directory", path, errno);
|
throw OpenFileException("not a directory", path, err);
|
||||||
case EISDIR:
|
case EISDIR:
|
||||||
throw OpenFileException("not a file", path, errno);
|
throw OpenFileException("not a file", path, err);
|
||||||
case EROFS:
|
case EROFS:
|
||||||
throw FileReadOnlyException(path, errno);
|
throw FileReadOnlyException(path, err);
|
||||||
case EEXIST:
|
case EEXIST:
|
||||||
throw FileExistsException(path, errno);
|
throw FileExistsException(path, err);
|
||||||
case ENOSPC:
|
case ENOSPC:
|
||||||
throw FileException("no space left on device", path, errno);
|
throw FileException("no space left on device", path, err);
|
||||||
case EDQUOT:
|
case EDQUOT:
|
||||||
throw FileException("disk quota exceeded", path, errno);
|
throw FileException("disk quota exceeded", path, err);
|
||||||
#if !defined(_AIX)
|
#if !defined(_AIX)
|
||||||
case ENOTEMPTY:
|
case ENOTEMPTY:
|
||||||
throw DirectoryNotEmptyException(path, errno);
|
throw DirectoryNotEmptyException(path, err);
|
||||||
#endif
|
#endif
|
||||||
case ENAMETOOLONG:
|
case ENAMETOOLONG:
|
||||||
throw PathSyntaxException(path, errno);
|
throw PathSyntaxException(path, err);
|
||||||
case ENFILE:
|
case ENFILE:
|
||||||
case EMFILE:
|
case EMFILE:
|
||||||
throw FileException("too many open files", path, errno);
|
throw FileException("too many open files", path, err);
|
||||||
default:
|
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
|
} // namespace Poco
|
||||||
|
Loading…
x
Reference in New Issue
Block a user