diff --git a/config/configure.ac b/config/configure.ac index 2dab6d35..a4d279f8 100644 --- a/config/configure.ac +++ b/config/configure.ac @@ -365,8 +365,9 @@ case "$host_os" in CPPFLAGS="$CPPFLAGS" # mingw doesn't link pthreads if you specify -std !! ;; *) - if [ $GCC_VERSION -le 5 ]; then CPPFLAGS="$CPPFLAGS -std=c++98" # // most others use c++98 - else CPPFLAGS="$CPPFLAGS -std=gnu++98" # // but not GCC 6 + CPPFLAGS="$CPPFLAGS -std=c++98" + if [[ ! -z "$GCC_VERSION" ]]; then + if [[ "$GCC_VERSION" -ge 6 ]]; then CPPFLAGS="$CPPFLAGS -std=gnu++98" ; fi # // not GCC 6 fi ;; esac diff --git a/include/exiv2/basicio.hpp b/include/exiv2/basicio.hpp index 39a14bc6..fb9ec04e 100644 --- a/include/exiv2/basicio.hpp +++ b/include/exiv2/basicio.hpp @@ -242,20 +242,6 @@ namespace Exiv2 { */ virtual std::wstring wpath() const =0; #endif - /*! - @brief Returns a temporary data storage location. This is often - needed to rewrite an IO source. - - For example, data may be read from the original IO source, modified - in some way, and then saved to the temporary instance. After the - operation is complete, the BasicIo::transfer method can be used to - replace the original IO source with the modified version. Subclasses - are free to return any class that derives from BasicIo. - - @return An instance of BasicIo on success - @throw Error In case of failure - */ - virtual BasicIo::AutoPtr temporary() const = 0; /*! @brief Mark all the bNone blocks to bKnow. This avoids allocating memory @@ -527,16 +513,6 @@ namespace Exiv2 { */ virtual std::wstring wpath() const; #endif - /*! - @brief Returns a temporary data storage location. The actual type - returned depends upon the size of the file represented a FileIo - object. For small files, a MemIo is returned while for large files - a FileIo is returned. Callers should not rely on this behavior, - however, since it may change. - @return An instance of BasicIo on success - @throw Error If opening the temporary file fails - */ - virtual BasicIo::AutoPtr temporary() const; /*! @brief Mark all the bNone blocks to bKnow. This avoids allocating memory @@ -548,15 +524,6 @@ namespace Exiv2 { virtual void populateFakeData(); //@} - /*! - @brief Returns the path to a temporary data storage location. - */ -#ifdef EXV_UNICODE_PATH - static std::wstring temporaryPath(); -#else - static std::string temporaryPath(); -#endif - private: // NOT IMPLEMENTED //! Copy constructor @@ -745,13 +712,6 @@ namespace Exiv2 { */ virtual std::wstring wpath() const; #endif - /*! - @brief Returns a temporary data storage location. Currently returns - an empty MemIo object, but callers should not rely on this - behavior since it may change. - @return An instance of BasicIo - */ - virtual BasicIo::AutoPtr temporary() const; /*! @brief Mark all the bNone blocks to bKnow. This avoids allocating memory @@ -1090,13 +1050,6 @@ namespace Exiv2 { */ virtual std::wstring wpath() const; #endif - /*! - @brief Returns a temporary data storage location. Currently returns - an empty MemIo object, but callers should not rely on this - behavior since it may change. - @return An instance of BasicIo - */ - virtual BasicIo::AutoPtr temporary() const; /*! @brief Mark all the bNone blocks to bKnow. This avoids allocating memory diff --git a/src/actions.cpp b/src/actions.cpp index c999dd76..4bf8cf50 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -2039,6 +2039,52 @@ namespace { return os.str(); } // tm2Str +// use static CS/MUTEX to make temporaryPath() thread safe +#if defined(_MSC_VER) || defined(__MINGW__) + static CRITICAL_SECTION cs; +#else + /* Unix/Linux/Cygwin/MacOSX */ + #include + #if defined(__APPLE__) + /* This is the critical section object (statically allocated). */ + static pthread_mutex_t cs = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; + #else + static pthread_mutex_t cs = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + #endif +#endif + + static std::string temporaryPath() + { + static int count = 0 ; + +#if defined(_MSC_VER) || defined(__MINGW__) + EnterCriticalSection(&cs); + char lpTempPathBuffer[MAX_PATH]; + GetTempPath(MAX_PATH,lpTempPathBuffer); + std::string tmp(lpTempPathBuffer); + tmp += "\\"; + HANDLE process=0; + DWORD pid = ::GetProcessId(process); +#else + pid_t pid = ::getpid(); + pthread_mutex_lock( &cs ); + std::string tmp = "/tmp/"; +#endif + char sCount[12]; + sprintf(sCount,"_%d",++count); + + std::string result = tmp + Exiv2::toString(pid) + sCount ; + if ( Exiv2::fileExists(result) ) std::remove(result.c_str()); + +#if defined(_MSC_VER) || defined(__MINGW__) + LeaveCriticalSection(&cs); +#else + pthread_mutex_unlock( &cs ); +#endif + + return result; + } + int metacopy(const std::string& source, const std::string& tgt, int targetType, @@ -2072,9 +2118,9 @@ namespace { // Open or create the target file #ifdef EXV_UNICODE_PATH - std::string target = bStdout ? Exiv2::ws2s(Exiv2::FileIo::temporaryPath()) : tgt; + std::string target = bStdout ? Exiv2::ws2s(temporaryPath()) : tgt; #else - std::string target = bStdout ? Exiv2::FileIo::temporaryPath() : tgt; + std::string target = bStdout ? temporaryPath() : tgt; #endif Exiv2::Image::AutoPtr targetImage; diff --git a/src/basicio.cpp b/src/basicio.cpp index d2fadec6..c13097d0 100644 --- a/src/basicio.cpp +++ b/src/basicio.cpp @@ -566,100 +566,6 @@ namespace Exiv2 { } #endif - BasicIo::AutoPtr FileIo::temporary() const - { - BasicIo::AutoPtr basicIo; - - Impl::StructStat buf; - int ret = p_->stat(buf); -#if defined WIN32 && !defined __CYGWIN__ - DWORD nlink = p_->winNumberOfLinks(); -#else - nlink_t nlink = buf.st_nlink; -#endif -#ifdef EXV_UNICODE_PATH - std::wstring tmpname; -#else - std::string tmpname; -#endif - // If file is > 1MB and doesn't have hard links then use a file, otherwise - // use a memory buffer. I.e., files with hard links always use a memory - // buffer, which is a workaround to ensure that the links don't get broken. - if (ret != 0 || (buf.st_size > 1048576 && nlink == 1)) - { - pid_t pid = ::getpid(); - std::auto_ptr fileIo; -#ifdef EXV_UNICODE_PATH - tmpname = temporaryPath() + s2ws(toString(pid)); - fileIo = std::auto_ptr(new FileIo(tmpname)); -#else - tmpname = temporaryPath() + toString(pid); - fileIo = std::auto_ptr(new FileIo(tmpname)); -#endif - if (fileIo->open("w+b") != 0) { -#ifdef EXV_UNICODE_PATH -#if defined(_MSC_VER) - if( !DeleteFileW( tmpname.c_str()) ) - { - perror("Error deleting file"); - throw WError(10, ws2s(tmpname).c_str(), "w+b", strError().c_str()); - } -#endif -#else -#if defined(_MSC_VER) || defined(__MINGW__) - if( !DeleteFile( tmpname.c_str() ) ) -#else - if( remove( tmpname.c_str() ) != 0 ) -#endif -#endif - { - perror("Error deleting file"); - } - throw Error(10, tmpname.c_str(), "w+b", strError()); - } - fileIo->p_->copyXattrFrom(*this); - basicIo = fileIo; - } else { - basicIo.reset(new MemIo); - } - - return basicIo; - } - - static std::string tempPath() - { - static int count = 0 ; - char sCount[12]; - sprintf(sCount,"_%d",count++); - -#if defined(_MSC_VER) || defined(__MINGW__) - char lpTempPathBuffer[MAX_PATH]; - GetTempPath(MAX_PATH,lpTempPathBuffer); - std::string tmp(lpTempPathBuffer); - tmp += "\\"; -#else - std::string tmp = "/tmp/"; -#endif - - pid_t pid = ::getpid(); - std::string result = tmp + toString(pid) + sCount ; - if ( Exiv2::fileExists(result) ) std::remove(result.c_str()); - - return result; - } - -#ifdef EXV_UNICODE_PATH - std::wstring FileIo::temporaryPath() - { - return s2ws(tempPath()); - } -#else - std::string FileIo::temporaryPath() - { - return tempPath(); - } -#endif - long FileIo::write(const byte* data, long wcount) { assert(p_->fp_ != 0); @@ -1218,11 +1124,6 @@ namespace Exiv2 { delete p_; } - BasicIo::AutoPtr MemIo::temporary() const - { - return BasicIo::AutoPtr(new MemIo); - } - long MemIo::write(const byte* data, long wcount) { p_->reserve(wcount); @@ -1991,11 +1892,6 @@ namespace Exiv2 { } #endif - BasicIo::AutoPtr RemoteIo::temporary() const - { - return BasicIo::AutoPtr(new MemIo); - } - void RemoteIo::populateFakeData() { assert(p_->isMalloced_); diff --git a/src/crwimage.cpp b/src/crwimage.cpp index dfee119c..285b3458 100644 --- a/src/crwimage.cpp +++ b/src/crwimage.cpp @@ -169,7 +169,7 @@ namespace Exiv2 { CrwParser::encode(blob, buf.pData_, buf.size_, this); // Write new buffer to file - BasicIo::AutoPtr tempIo(io_->temporary()); // may throw + MemIo::AutoPtr tempIo(new MemIo); assert(tempIo.get() != 0); tempIo->write((blob.size() > 0 ? &blob[0] : 0), static_cast(blob.size())); io_->close(); diff --git a/src/epsimage.cpp b/src/epsimage.cpp index 6e277e8b..4e7dde55 100644 --- a/src/epsimage.cpp +++ b/src/epsimage.cpp @@ -809,7 +809,7 @@ namespace { } // create temporary output file - BasicIo::AutoPtr tempIo(io.temporary()); + BasicIo::AutoPtr tempIo(new MemIo); assert (tempIo.get() != 0); if (!tempIo->isopen()) { #ifndef SUPPRESS_WARNINGS diff --git a/src/jp2image.cpp b/src/jp2image.cpp index 0b1ed498..01099d73 100644 --- a/src/jp2image.cpp +++ b/src/jp2image.cpp @@ -589,7 +589,7 @@ namespace Exiv2 throw Error(9, io_->path(), strError()); } IoCloser closer(*io_); - BasicIo::AutoPtr tempIo(io_->temporary()); // may throw + BasicIo::AutoPtr tempIo(new MemIo); assert (tempIo.get() != 0); doWriteMetadata(*tempIo); // may throw diff --git a/src/jpgimage.cpp b/src/jpgimage.cpp index cd07d172..82bd01d4 100644 --- a/src/jpgimage.cpp +++ b/src/jpgimage.cpp @@ -834,7 +834,7 @@ namespace Exiv2 { // exiv2 -pS E.jpg // binary copy io_ to a temporary file - BasicIo::AutoPtr tempIo(io_->temporary()); // may throw + BasicIo::AutoPtr tempIo(new MemIo); assert (tempIo.get() != 0); for ( uint64_t i = 0 ; i < (count/2)+1 ; i++ ) { @@ -866,7 +866,7 @@ namespace Exiv2 { throw Error(9, io_->path(), strError()); } IoCloser closer(*io_); - BasicIo::AutoPtr tempIo(io_->temporary()); // may throw + BasicIo::AutoPtr tempIo(new MemIo); assert (tempIo.get() != 0); doWriteMetadata(*tempIo); // may throw diff --git a/src/pgfimage.cpp b/src/pgfimage.cpp index 8b399d92..ab205a53 100644 --- a/src/pgfimage.cpp +++ b/src/pgfimage.cpp @@ -163,7 +163,7 @@ namespace Exiv2 { throw Error(9, io_->path(), strError()); } IoCloser closer(*io_); - BasicIo::AutoPtr tempIo(io_->temporary()); // may throw + BasicIo::AutoPtr tempIo(new MemIo); assert (tempIo.get() != 0); doWriteMetadata(*tempIo); // may throw diff --git a/src/pngimage.cpp b/src/pngimage.cpp index b0a288e3..33bed6c2 100644 --- a/src/pngimage.cpp +++ b/src/pngimage.cpp @@ -494,7 +494,7 @@ namespace Exiv2 { throw Error(9, io_->path(), strError()); } IoCloser closer(*io_); - BasicIo::AutoPtr tempIo(io_->temporary()); // may throw + BasicIo::AutoPtr tempIo(new MemIo); assert (tempIo.get() != 0); doWriteMetadata(*tempIo); // may throw diff --git a/src/psdimage.cpp b/src/psdimage.cpp index 9b361b9b..afa86441 100644 --- a/src/psdimage.cpp +++ b/src/psdimage.cpp @@ -348,7 +348,7 @@ namespace Exiv2 { throw Error(9, io_->path(), strError()); } IoCloser closer(*io_); - BasicIo::AutoPtr tempIo(io_->temporary()); // may throw + BasicIo::AutoPtr tempIo(new MemIo); assert (tempIo.get() != 0); doWriteMetadata(*tempIo); // may throw diff --git a/src/tiffimage.cpp b/src/tiffimage.cpp index 79c27ffc..abcecd47 100644 --- a/src/tiffimage.cpp +++ b/src/tiffimage.cpp @@ -1968,7 +1968,7 @@ namespace Exiv2 { encoder.add(createdTree.get(), parsedTree.get(), root); // Write binary representation from the composite tree DataBuf header = pHeader->write(); - BasicIo::AutoPtr tempIo(io.temporary()); // may throw + BasicIo::AutoPtr tempIo(new MemIo); assert(tempIo.get() != 0); IoWrapper ioWrapper(*tempIo, header.pData_, header.size_, pOffsetWriter); uint32_t imageIdx(uint32_t(-1)); diff --git a/src/webpimage.cpp b/src/webpimage.cpp index 86cc94ba..5e852bfe 100644 --- a/src/webpimage.cpp +++ b/src/webpimage.cpp @@ -120,7 +120,7 @@ namespace Exiv2 { throw Error(9, io_->path(), strError()); } IoCloser closer(*io_); - BasicIo::AutoPtr tempIo(io_->temporary()); // may throw + BasicIo::AutoPtr tempIo(new MemIo); assert (tempIo.get() != 0); doWriteMetadata(*tempIo); // may throw diff --git a/src/xmpsidecar.cpp b/src/xmpsidecar.cpp index a61370e4..00924224 100644 --- a/src/xmpsidecar.cpp +++ b/src/xmpsidecar.cpp @@ -159,7 +159,7 @@ namespace Exiv2 { if (xmpPacket_.substr(0, 5) != "temporary()); // may throw + BasicIo::AutoPtr tempIo(new MemIo); assert(tempIo.get() != 0); // Write XMP packet if ( tempIo->write(reinterpret_cast(xmpPacket_.data()), diff --git a/test/Makefile b/test/Makefile index eaaac42f..d9201a7d 100644 --- a/test/Makefile +++ b/test/Makefile @@ -76,7 +76,6 @@ TESTS = addmoddel.sh \ modify-test.sh \ path-test.sh \ preview-test.sh \ - stdin-test.sh \ stringto-test.sh \ tiff-test.sh \ webp-test.sh \