mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-12 18:20:26 +01:00
Merge pull request #2842 from KevDi/feature/FileFailOnOverwrite
File fail on overwrite
This commit is contained in:
commit
56fe4eaf97
@ -70,6 +70,12 @@ public:
|
||||
LINK_SYMBOLIC = 1 /// symbolic link
|
||||
};
|
||||
|
||||
enum Options
|
||||
/// Options for File Copy/Movement
|
||||
{
|
||||
OPT_FAIL_ON_OVERWRITE = OPT_FAIL_ON_OVERWRITE_IMPL
|
||||
};
|
||||
|
||||
File();
|
||||
/// Creates the file.
|
||||
|
||||
@ -183,18 +189,24 @@ public:
|
||||
///
|
||||
/// Does nothing on Windows.
|
||||
|
||||
void copyTo(const std::string& path) const;
|
||||
void copyTo(const std::string& path, int options = 0) const;
|
||||
/// Copies the file (or directory) to the given path.
|
||||
/// The target path can be a directory.
|
||||
///
|
||||
/// A directory is copied recursively.
|
||||
/// If options is set to OPT_FAIL_ON_OVERWRITE the Method throws an FileExists Exception
|
||||
/// if the File already exists.
|
||||
|
||||
void moveTo(const std::string& path);
|
||||
void moveTo(const std::string& path, int options = 0);
|
||||
/// Copies the file (or directory) to the given path and
|
||||
/// removes the original file. The target path can be a directory.
|
||||
/// If options is set to OPT_FAIL_ON_OVERWRITE the Method throws an FileExists Exception
|
||||
/// if the File already exists.
|
||||
|
||||
void renameTo(const std::string& path);
|
||||
void renameTo(const std::string& path, int options = 0);
|
||||
/// Renames the file to the new name.
|
||||
/// If options is set to OPT_FAIL_ON_OVERWRITE the Method throws an FileExists Exception
|
||||
/// if the File already exists.
|
||||
|
||||
void linkTo(const std::string& path, LinkType type = LINK_SYMBOLIC) const;
|
||||
/// Creates a link (symbolic or hard, depending on type argument)
|
||||
@ -253,7 +265,7 @@ public:
|
||||
/// exception for the last file-related error.
|
||||
|
||||
protected:
|
||||
void copyDirectory(const std::string& path) const;
|
||||
void copyDirectory(const std::string& path, int options = 0) const;
|
||||
/// Copies a directory. Used internally by copyTo().
|
||||
};
|
||||
|
||||
|
@ -27,6 +27,11 @@ namespace Poco {
|
||||
class FileImpl
|
||||
{
|
||||
protected:
|
||||
|
||||
enum Options {
|
||||
OPT_FAIL_ON_OVERWRITE_IMPL = 0x01
|
||||
};
|
||||
|
||||
typedef UInt64 FileSizeImpl;
|
||||
|
||||
FileImpl();
|
||||
@ -51,8 +56,8 @@ protected:
|
||||
void setSizeImpl(FileSizeImpl size);
|
||||
void setWriteableImpl(bool flag = true);
|
||||
void setExecutableImpl(bool flag = true);
|
||||
void copyToImpl(const std::string& path) const;
|
||||
void renameToImpl(const std::string& path);
|
||||
void copyToImpl(const std::string& path, int options = 0) const;
|
||||
void renameToImpl(const std::string& path, int options = 0);
|
||||
void linkToImpl(const std::string& path, int type) const;
|
||||
void removeImpl();
|
||||
bool createFileImpl();
|
||||
|
@ -27,6 +27,11 @@ namespace Poco {
|
||||
class FileImpl
|
||||
{
|
||||
protected:
|
||||
|
||||
enum Options {
|
||||
OPT_FAIL_ON_OVERWRITE_IMPL = 0x01
|
||||
};
|
||||
|
||||
typedef UInt64 FileSizeImpl;
|
||||
|
||||
FileImpl();
|
||||
@ -51,8 +56,8 @@ protected:
|
||||
void setSizeImpl(FileSizeImpl size);
|
||||
void setWriteableImpl(bool flag = true);
|
||||
void setExecutableImpl(bool flag = true);
|
||||
void copyToImpl(const std::string& path) const;
|
||||
void renameToImpl(const std::string& path);
|
||||
void copyToImpl(const std::string& path, int options = 0) const;
|
||||
void renameToImpl(const std::string& path, int options = 0);
|
||||
void linkToImpl(const std::string& path, int type) const;
|
||||
void removeImpl();
|
||||
bool createFileImpl();
|
||||
|
@ -28,6 +28,11 @@ namespace Poco {
|
||||
class Foundation_API FileImpl
|
||||
{
|
||||
protected:
|
||||
|
||||
enum Options {
|
||||
OPT_FAIL_ON_OVERWRITE_IMPL = 0x01
|
||||
};
|
||||
|
||||
typedef UInt64 FileSizeImpl;
|
||||
|
||||
FileImpl();
|
||||
@ -52,8 +57,8 @@ protected:
|
||||
void setSizeImpl(FileSizeImpl size);
|
||||
void setWriteableImpl(bool flag = true);
|
||||
void setExecutableImpl(bool flag = true);
|
||||
void copyToImpl(const std::string& path) const;
|
||||
void renameToImpl(const std::string& path);
|
||||
void copyToImpl(const std::string& path, int options = 0) const;
|
||||
void renameToImpl(const std::string& path, int options = 0);
|
||||
void linkToImpl(const std::string& path, int type) const;
|
||||
void removeImpl();
|
||||
bool createFileImpl();
|
||||
|
@ -28,6 +28,11 @@ namespace Poco {
|
||||
class Foundation_API FileImpl
|
||||
{
|
||||
protected:
|
||||
|
||||
enum Options {
|
||||
OPT_FAIL_ON_OVERWRITE_IMPL = 0x01
|
||||
};
|
||||
|
||||
typedef UInt64 FileSizeImpl;
|
||||
|
||||
FileImpl();
|
||||
@ -52,8 +57,8 @@ protected:
|
||||
void setSizeImpl(FileSizeImpl size);
|
||||
void setWriteableImpl(bool flag = true);
|
||||
void setExecutableImpl(bool flag = true);
|
||||
void copyToImpl(const std::string& path) const;
|
||||
void renameToImpl(const std::string& path);
|
||||
void copyToImpl(const std::string& path, int options = 0) const;
|
||||
void renameToImpl(const std::string& path, int options = 0);
|
||||
void linkToImpl(const std::string& path, int type) const;
|
||||
void removeImpl();
|
||||
bool createFileImpl();
|
||||
|
@ -28,6 +28,11 @@ namespace Poco {
|
||||
class Foundation_API FileImpl
|
||||
{
|
||||
protected:
|
||||
|
||||
enum Options {
|
||||
OPT_FAIL_ON_OVERWRITE_IMPL = 0x01
|
||||
};
|
||||
|
||||
typedef UInt64 FileSizeImpl;
|
||||
|
||||
FileImpl();
|
||||
@ -52,8 +57,8 @@ protected:
|
||||
void setSizeImpl(FileSizeImpl size);
|
||||
void setWriteableImpl(bool flag = true);
|
||||
void setExecutableImpl(bool flag = true);
|
||||
void copyToImpl(const std::string& path) const;
|
||||
void renameToImpl(const std::string& path);
|
||||
void copyToImpl(const std::string& path, int options = 0) const;
|
||||
void renameToImpl(const std::string& path, int options = 0);
|
||||
void linkToImpl(const std::string& path, int type) const;
|
||||
void removeImpl();
|
||||
bool createFileImpl();
|
||||
|
@ -208,7 +208,7 @@ File& File::setExecutable(bool flag)
|
||||
}
|
||||
|
||||
|
||||
void File::copyTo(const std::string& path) const
|
||||
void File::copyTo(const std::string& path, int options) const
|
||||
{
|
||||
Path src(getPathImpl());
|
||||
Path dest(path);
|
||||
@ -219,13 +219,13 @@ void File::copyTo(const std::string& path) const
|
||||
dest.setFileName(src.getFileName());
|
||||
}
|
||||
if (isDirectory())
|
||||
copyDirectory(dest.toString());
|
||||
copyDirectory(dest.toString(), options);
|
||||
else
|
||||
copyToImpl(dest.toString());
|
||||
copyToImpl(dest.toString(), options);
|
||||
}
|
||||
|
||||
|
||||
void File::copyDirectory(const std::string& path) const
|
||||
void File::copyDirectory(const std::string& path, int options) const
|
||||
{
|
||||
File target(path);
|
||||
target.createDirectories();
|
||||
@ -236,22 +236,22 @@ void File::copyDirectory(const std::string& path) const
|
||||
DirectoryIterator end;
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
it->copyTo(path);
|
||||
it->copyTo(path, options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void File::moveTo(const std::string& path)
|
||||
void File::moveTo(const std::string& path, int options)
|
||||
{
|
||||
copyTo(path);
|
||||
copyTo(path, options);
|
||||
remove(true);
|
||||
setPathImpl(path);
|
||||
}
|
||||
|
||||
|
||||
void File::renameTo(const std::string& path)
|
||||
void File::renameTo(const std::string& path, int options)
|
||||
{
|
||||
renameToImpl(path);
|
||||
renameToImpl(path, options);
|
||||
setPathImpl(path);
|
||||
}
|
||||
|
||||
|
@ -326,7 +326,7 @@ void FileImpl::setExecutableImpl(bool flag)
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::copyToImpl(const std::string& path) const
|
||||
void FileImpl::copyToImpl(const std::string& path, int options) const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
@ -340,8 +340,12 @@ void FileImpl::copyToImpl(const std::string& path) const
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
const long blockSize = st.st_blksize;
|
||||
|
||||
int dd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, st.st_mode);
|
||||
int dd;
|
||||
if (options & OPT_FAIL_ON_OVERWRITE_IMPL) {
|
||||
dd = open(path.c_str(), O_CREAT | O_TRUNC | O_EXCL | O_WRONLY, st.st_mode);
|
||||
} else {
|
||||
dd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, st.st_mode);
|
||||
}
|
||||
if (dd == -1)
|
||||
{
|
||||
close(sd);
|
||||
@ -376,10 +380,15 @@ void FileImpl::copyToImpl(const std::string& path) const
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::renameToImpl(const std::string& path)
|
||||
void FileImpl::renameToImpl(const std::string& path, int options)
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
struct stat st;
|
||||
|
||||
if (stat(path.c_str(), &st) == 0 && (options & OPT_FAIL_ON_OVERWRITE_IMPL))
|
||||
throw FileExistsException(path, EEXIST);
|
||||
|
||||
if (rename(_path.c_str(), path.c_str()) != 0)
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ void FileImpl::setExecutableImpl(bool flag)
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::copyToImpl(const std::string& path) const
|
||||
void FileImpl::copyToImpl(const std::string& path, int options) const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
@ -247,7 +247,13 @@ void FileImpl::copyToImpl(const std::string& path) const
|
||||
}
|
||||
const long blockSize = st.st_blksize;
|
||||
|
||||
int dd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, st.st_mode & S_IRWXU);
|
||||
int dd;
|
||||
if (options & OPT_FAIL_ON_OVERWRITE_IMPL) {
|
||||
dd = open(path.c_str(), O_CREAT | O_TRUNC | O_EXCL | O_WRONLY, st.st_mode & S_IRWXU);
|
||||
} else {
|
||||
dd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, st.st_mode & S_IRWXU);
|
||||
}
|
||||
|
||||
if (dd == -1)
|
||||
{
|
||||
close(sd);
|
||||
@ -276,10 +282,15 @@ void FileImpl::copyToImpl(const std::string& path) const
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::renameToImpl(const std::string& path)
|
||||
void FileImpl::renameToImpl(const std::string& path, int options)
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
struct stat st;
|
||||
|
||||
if (stat(path.c_str(), &st) == 0 && (options &OPT_FAIL_ON_OVERWRITE_IMPL))
|
||||
throw FileExistsException(path, EEXIST);
|
||||
|
||||
if (rename(_path.c_str(), path.c_str()) != 0)
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
|
@ -288,21 +288,27 @@ void FileImpl::setExecutableImpl(bool flag)
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::copyToImpl(const std::string& path) const
|
||||
void FileImpl::copyToImpl(const std::string& path, int options) const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
if (CopyFileA(_path.c_str(), path.c_str(), FALSE) == 0)
|
||||
if (CopyFileA(_path.c_str(), path.c_str(), (options & OPT_FAIL_ON_OVERWRITE_IMPL) != 0) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::renameToImpl(const std::string& path)
|
||||
void FileImpl::renameToImpl(const std::string& path, int options)
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
if (MoveFileExA(_path.c_str(), path.c_str(), MOVEFILE_REPLACE_EXISTING) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
if (options & OPT_FAIL_ON_OVERWRITE_IMPL) {
|
||||
if (MoveFileExA(_path.c_str(), path.c_str(), NULL) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
} else {
|
||||
if (MoveFileExA(_path.c_str(), path.c_str(), MOVEFILE_REPLACE_EXISTING) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -291,25 +291,30 @@ void FileImpl::setExecutableImpl(bool flag)
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::copyToImpl(const std::string& path) const
|
||||
void FileImpl::copyToImpl(const std::string& path, int options) const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
std::wstring upath;
|
||||
convertPath(path, upath);
|
||||
if (CopyFileW(_upath.c_str(), upath.c_str(), FALSE) == 0)
|
||||
if (CopyFileW(_upath.c_str(), upath.c_str(), (options & OPT_FAIL_ON_OVERWRITE_IMPL) != 0) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::renameToImpl(const std::string& path)
|
||||
void FileImpl::renameToImpl(const std::string& path, int options)
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
std::wstring upath;
|
||||
convertPath(path, upath);
|
||||
if (MoveFileExW(_upath.c_str(), upath.c_str(), MOVEFILE_REPLACE_EXISTING) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
if (options & OPT_FAIL_ON_OVERWRITE_IMPL) {
|
||||
if (MoveFileExW(_upath.c_str(), upath.c_str(), NULL) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
} else {
|
||||
if (MoveFileExW(_upath.c_str(), upath.c_str(), MOVEFILE_REPLACE_EXISTING) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -277,25 +277,31 @@ void FileImpl::setExecutableImpl(bool flag)
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::copyToImpl(const std::string& path) const
|
||||
void FileImpl::copyToImpl(const std::string& path, int options) const
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
std::wstring upath;
|
||||
convertPath(path, upath);
|
||||
if (CopyFileW(_upath.c_str(), upath.c_str(), FALSE) == 0)
|
||||
if (CopyFileW(_upath.c_str(), upath.c_str(), (options & OPT_FAIL_ON_OVERWRITE_IMPL) != 0) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
|
||||
|
||||
void FileImpl::renameToImpl(const std::string& path)
|
||||
void FileImpl::renameToImpl(const std::string& path, int options)
|
||||
{
|
||||
poco_assert (!_path.empty());
|
||||
|
||||
std::wstring upath;
|
||||
convertPath(path, upath);
|
||||
if (MoveFileW(_upath.c_str(), upath.c_str()) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
if (options & OPT_FAIL_ON_OVERWRITE_IMPL) {
|
||||
if (MoveFileW(_upath.c_str(), upath.c_str()) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
} else {
|
||||
if (MoveFileW(_upath.c_str(), upath.c_str(), MOVEFILE_REPLACE_EXISTING) == 0)
|
||||
handleLastErrorImpl(_path);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -380,6 +380,23 @@ void FileTest::testCopy()
|
||||
f1.setWriteable().remove();
|
||||
}
|
||||
|
||||
void FileTest::testCopyFailIfDestinationFileExists()
|
||||
{
|
||||
std::ofstream ostr("testfile.dat");
|
||||
ostr << "Hello, world!" << std::endl;
|
||||
ostr.close();
|
||||
|
||||
File f1("testfile.dat");
|
||||
TemporaryFile f2;
|
||||
f2.createFile();
|
||||
try {
|
||||
f1.setReadOnly().copyTo(f2.path(), File::OPT_FAIL_ON_OVERWRITE);
|
||||
failmsg("file exist - must throw exception");
|
||||
} catch (Exception&) {
|
||||
}
|
||||
f1.setWriteable().remove();
|
||||
}
|
||||
|
||||
|
||||
void FileTest::testMove()
|
||||
{
|
||||
@ -397,6 +414,21 @@ void FileTest::testMove()
|
||||
assertTrue (f1 == f2);
|
||||
}
|
||||
|
||||
void FileTest::testMoveFailIfDestinationFileExists() {
|
||||
std::ofstream ostr("testfile.dat");
|
||||
ostr << "Hello, world!" << std::endl;
|
||||
ostr.close();
|
||||
|
||||
File f1("testfile.dat");
|
||||
TemporaryFile f2;
|
||||
f2.createFile();
|
||||
try {
|
||||
f1.moveTo(f2.path(), File::OPT_FAIL_ON_OVERWRITE);
|
||||
failmsg("file exist - must throw exception");
|
||||
} catch (Exception&) {
|
||||
}
|
||||
f1.setWriteable().remove();
|
||||
}
|
||||
|
||||
void FileTest::testCopyDirectory()
|
||||
{
|
||||
@ -467,6 +499,44 @@ void FileTest::testCopyDirectory()
|
||||
fd3.remove(true);
|
||||
}
|
||||
|
||||
void FileTest::testCopyDirectoryFailIfExists()
|
||||
{
|
||||
Path pd1("testdir");
|
||||
File fd1(pd1);
|
||||
try {
|
||||
fd1.remove(true);
|
||||
} catch (...) {
|
||||
}
|
||||
fd1.createDirectories();
|
||||
Path pf1(pd1, "testfile1.dat");
|
||||
std::ofstream ostr1(pf1.toString().c_str());
|
||||
ostr1 << "Hello, world!" << std::endl;
|
||||
ostr1.close();
|
||||
Path pf2(pd1, "testfile2.dat");
|
||||
std::ofstream ostr2(pf2.toString().c_str());
|
||||
ostr2 << "Hello, world!" << std::endl;
|
||||
ostr2.close();
|
||||
|
||||
Path pd2("destination");
|
||||
File fd2(pd2);
|
||||
try {
|
||||
fd2.remove(true);
|
||||
} catch (...) {
|
||||
}
|
||||
fd2.createDirectories();
|
||||
Path pd3(pd2, "testdir");
|
||||
File fd3(pd3);
|
||||
fd3.createDirectories();
|
||||
|
||||
try {
|
||||
fd1.copyTo("testdir", File::OPT_FAIL_ON_OVERWRITE);
|
||||
failmsg("Destination Directory exists - must throw exception");
|
||||
} catch (Exception&) {
|
||||
}
|
||||
|
||||
fd1.remove(true);
|
||||
fd2.remove(true);
|
||||
}
|
||||
|
||||
void FileTest::testRename()
|
||||
{
|
||||
@ -485,6 +555,32 @@ void FileTest::testRename()
|
||||
f2.remove();
|
||||
}
|
||||
|
||||
void FileTest::testRenameFailIfExists() {
|
||||
std::ofstream ostr("testfile.dat");
|
||||
ostr << "Hello, world!" << std::endl;
|
||||
ostr.close();
|
||||
|
||||
File f1("testfile.dat");
|
||||
File f2("testfile2.dat");
|
||||
f2.createFile();
|
||||
|
||||
try {
|
||||
f1.renameTo(f2.path(), File::OPT_FAIL_ON_OVERWRITE);
|
||||
failmsg("file exists - must throw exception");
|
||||
} catch (Exception&) {
|
||||
}
|
||||
|
||||
f1.renameTo(f2.path());
|
||||
|
||||
assertTrue(f2.exists());
|
||||
assertTrue(f1.exists());
|
||||
assertTrue(f1 == f2);
|
||||
|
||||
f2.remove();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FileTest::testLongPath()
|
||||
{
|
||||
@ -549,9 +645,13 @@ CppUnit::Test* FileTest::suite()
|
||||
CppUnit_addTest(pSuite, FileTest, testSize);
|
||||
CppUnit_addTest(pSuite, FileTest, testDirectory);
|
||||
CppUnit_addTest(pSuite, FileTest, testCopy);
|
||||
CppUnit_addTest(pSuite, FileTest, testCopyFailIfDestinationFileExists);
|
||||
CppUnit_addTest(pSuite, FileTest, testMove);
|
||||
CppUnit_addTest(pSuite, FileTest, testMoveFailIfDestinationFileExists);
|
||||
CppUnit_addTest(pSuite, FileTest, testCopyDirectory);
|
||||
CppUnit_addTest(pSuite, FileTest, testCopyDirectoryFailIfExists);
|
||||
CppUnit_addTest(pSuite, FileTest, testRename);
|
||||
CppUnit_addTest(pSuite, FileTest, testRenameFailIfExists);
|
||||
CppUnit_addTest(pSuite, FileTest, testRootDir);
|
||||
CppUnit_addTest(pSuite, FileTest, testLongPath);
|
||||
|
||||
|
@ -33,9 +33,13 @@ public:
|
||||
void testSize();
|
||||
void testDirectory();
|
||||
void testCopy();
|
||||
void testCopyFailIfDestinationFileExists();
|
||||
void testMove();
|
||||
void testMoveFailIfDestinationFileExists();
|
||||
void testCopyDirectory();
|
||||
void testCopyDirectoryFailIfExists();
|
||||
void testRename();
|
||||
void testRenameFailIfExists();
|
||||
void testRootDir();
|
||||
void testLongPath();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user