diff --git a/src/basicio.cpp b/src/basicio.cpp index a2ac7080..504b66be 100644 --- a/src/basicio.cpp +++ b/src/basicio.cpp @@ -44,12 +44,12 @@ EXIV2_RCSID("@(#) $Id$") // + standard includes #include #include -#include // for remove(), rename() -#include // for alloc(), realloc(), free() -#include // for stat() -#include // for stat() +#include // for remove, rename +#include // for alloc, realloc, free +#include // for stat, chmod +#include // for stat, chmod #ifdef EXV_HAVE_SYS_MMAN_H -# include // for mmap() and munmap() +# include // for mmap and munmap #endif #ifdef EXV_HAVE_PROCESS_H # include @@ -219,9 +219,17 @@ namespace Exiv2 { FileIo *fileIo = dynamic_cast(&src); if (fileIo) { - // Optimization if this is another instance of FileIo - close(); + // Optimization if src is another instance of FileIo fileIo->close(); + // Check if the file can be written to, if it already exists + if (open("w+b") != 0) { + throw Error(10, path_, "w+b", strError()); + } + close(); + struct stat buf; + if (stat(path_.c_str(), &buf) == -1) { + throw Error(2, path_, strError(), "stat"); + } // MSVCRT rename that does not overwrite existing files if (fileExists(path_) && std::remove(path_.c_str()) != 0) { throw Error(2, path_, strError(), "std::remove"); @@ -230,6 +238,10 @@ namespace Exiv2 { throw Error(17, fileIo->path_, path_, strError()); } std::remove(fileIo->path_.c_str()); + // Set original file permissions + if (chmod(path_.c_str(), buf.st_mode) == -1) { + throw Error(2, fileIo->path_, strError(), "chmod"); + } } else { // Generic handling, reopen both to reset to start @@ -443,7 +455,7 @@ namespace Exiv2 { { MemIo *memIo = dynamic_cast(&src); if (memIo) { - // Optimization if this is another instance of MemIo + // Optimization if src is another instance of MemIo if (true == isMalloced_) { std::free(data_); }