Project

General

Profile

Dateikonflikt Exiv2 Library unter Windows

Added by LaserSoft Imaging over 7 years ago

Sehr geehrter Herr Huggel, liebe Mitleser,

if it is necessary, we could also translate our question to english.

Bei der Verwendung der Exiv2 Bibliothek sind wir vereinzelt auf Dateikonflikte unter Windows gestoßen. Es scheint als würde beim Schreiben von Metadaten in ein Image-Objekt die Datei einen temporären Namen "Dateiname + Prozess ID" erhalten. Hier ein Beispiel, wie wir die Metadaten derzeit schreiben:

Exiv2::XmpData exiv2IptcData;
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(filename.toStdString());
// ...fill exiv2IptcData...
image->readMetadata(); // Read meta data
// Get exif- and xmp-data and set it again to the image
Exiv2::ExifData exiv2ExifData = image->exifData();
image->setExifData(exiv2ExifData);
Exiv2::XmpData exiv2XmpData = image->xmpData();
image->setXmpData(exiv2XmpData);
// Set the freshly created IPTC data
image->setIptcData(exiv2IptcData);
// Write the meta data to the file.
image->writeMetadata();

Abhängig von der jeweiligen Dateigröße erscheint im Windows Datei-Explorer die temporäre Datei mit der zusätzlich Endung, die die Prozess ID unserer Programmsitzung darstellt. Interagiert man mit dieser, also markiert sie beispielsweise mit der Maus, erzwingt man einen Fehler mit dem Errorcode 17:

catch(Exiv2::AnyError& error)
{
    int errCode(error.code());
    // Write error message to log-file:
    sfDebug("CsfIptc::applyIptcToFile() Exiv2 Error " + QString::number(errCode) + " while storing IPTC data: " + QString(error.what()));
}

...ergibt die Fehlermeldung:
CsfIptc::applyIptcToFile() Exiv2 Error 17 while storing IPTC data: C:/Users/tester/Pictures/iptcTest/iptc2/OF120_0516.tif1884: Failed to rename file to C:/Users/tester/Pictures/iptcTest/iptc2/OF120_0516.tif: File exists (errno = 17)

Unsere Frage ist, ob es bestimmte Gründe gibt, warum die Datei von der Exiv2-Bibliothek zwischenzeitlich umbenannt wird, beziehungsweise ob man diese Umbenennung auch komplett verhindern kann?


Replies (7)

RE: Dateikonflikt Exiv2 Library unter Windows - Added by Robin Mills over 7 years ago

I've been on vacation and left this for Andreas to handle as he's a native German speaker. May I ask you to translate this to English and I will reply.

RE: Dateikonflikt Exiv2 Library unter Windows - Added by LaserSoft Imaging over 7 years ago

Yes, of course. We met the behavior that obviously exiv2-library renames the file it is working with to a temporary name. This name should be its original name extended by the process-id of the application which is using exiv2-library. The first code fragment above shows how we use the exiv2-library for writing the meta-data to a file.
Depending on the size of the (temporary-named) file and a possible user-interaction with it while exiv2-library tries to write the meta-data, it appears that the library throws error no 17. It tells that while storing the IPTC data the renaming failed.
We are now using some kind of a work-around which renames the file by our application since we at least know the temporary name and the target name.
We ask ourself if this renaming to "name + process-id" is even necessary or if it could be prevented somehow? By the way, we only experienced this behavior on Windows so far.

RE: Dateikonflikt Exiv2 Library unter Windows - Added by Robin Mills over 7 years ago

Thanks. Before I asked you to translate, I used Google Translate. Now I know what you're talking about! Human translators don't need to worry (yet) about machines taking over their job!

I suspect that 'name+process-id' has been used for process safety. Two applications can operate on the same file with some independence. However without a mutex, or some other system wide exclusion lock, the rename operation is vulnerable. This code does not seems to be thread safe. Two threads could easily collide.

Windows "rename" is different from Unix "mv" and fails when the target already exists. There's a comment in the code concerning this at src/basicio.cpp+710.

            // MSVCRT rename that does not overwrite existing files
#ifdef EXV_UNICODE_PATH
            if (p_->wpMode_ == Impl::wpUnicode) {
                if (fileExists(wpf) && ::_wremove(wpf) != 0) {
                    throw WError(2, wpf, strError().c_str(), "::_wremove");
                }
                if (::_wrename(fileIo->wpath().c_str(), wpf) == -1) {
                    throw WError(17, fileIo->wpath(), wpf, strError().c_str());
                }
                ::_wremove(fileIo->wpath().c_str());
                // Check permissions of new file
                struct _stat buf2;
                if (statOk && ::_wstat(wpf, &buf2) == -1) {
                    statOk = false;
#ifndef SUPPRESS_WARNINGS
                    EXV_WARNING << Error(2, wpf, strError(), "::_wstat") << "\n";
#endif
                }
                if (statOk && origStMode != buf2.st_mode) {
                    // Set original file permissions
                    if (::_wchmod(wpf, origStMode) == -1) {
#ifndef SUPPRESS_WARNINGS
                        EXV_WARNING << Error(2, wpf, strError(), "::_wchmod") << "\n";
#endif
                    }
                }
            } // if (p_->wpMode_ == Impl::wpUnicode)

You'll notice that the '17' appears to come from here.

The bracketing of the #ifdef EXV_UNICODE_PATH code looks suspicious to me. I think the code is running both the EXV_UNICODE_PATH and ASCII branches. Our normal build does not set EXV_UNICODE_PATH, so this code doesn't get exercised by our test suite. I'll rebuild and test with EXV_UNICODE_PATH and see what happens.

May I ask a couple of questions:
1) Do you set EXV_UNICODE_PATH for your build in MSVC and/or LINUX?
2) Are you using multi-processing and/or multi-threading?

Robin

RE: Dateikonflikt Exiv2 Library unter Windows - Added by LaserSoft Imaging over 7 years ago

Thanks for your reply, Robin!

Robin Mills wrote:

May I ask a couple of questions:
1) Do you set EXV_UNICODE_PATH for your build in MSVC and/or LINUX?

From what we remember, we haven't set this in purpose for building the library.

Robin Mills wrote:

2) Are you using multi-processing and/or multi-threading?

No, not for writing the metadata. We would rather expect Windows to be the second "thread" accessing the file.

RE: Dateikonflikt Exiv2 Library unter Windows - Added by Robin Mills over 7 years ago

I've built and run our test suite on the trunk with/without EXV_UNICODE_PATH defined. Incidentally, EXV_UNICODE_PATH is defined by default in exv_msvc.h

I think we're going on Safari to hunt down this beast. I'm fairly sure this issue arrives from the code in src/basicio.cpp line#710+. I can only think of three ways to get closer:
1) You debug it from your application (with Visual Studio, or std::cout statements).
2) You find a way (with a sample images) to isolate the issue with the exiv2(.exe) command.
3) I (or you) have a new idea in the next day or two.

If I don't update this topic for the next couple of days, can you start a new Issue (bug) report and reference this topic (t1789)? It will not be forgotten when tracked as an Issue.

Robin

RE: Dateikonflikt Exiv2 Library unter Windows - Added by Robin Mills over 7 years ago

I've opened an issue (bug) report about this. http://dev.exiv2.org/issues/979

RE: Dateikonflikt Exiv2 Library unter Windows - Added by Robin Mills about 7 years ago

We believe the Virus checker make be the bandit here. See discussion: http://dev.exiv2.org/boards/3/topics/1816

    (1-7/7)