Bug 346081 - Exiv2 cannot open file on NTFS within non-english directory
Summary: Exiv2 cannot open file on NTFS within non-english directory
Status: RESOLVED FIXED
Alias: None
Product: digikam
Classification: Applications
Component: Metadata-Engine (show other bugs)
Version: 4.9.0
Platform: openSUSE Linux
: NOR major
Target Milestone: ---
Assignee: Digikam Developers
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-04-11 17:22 UTC by Konstantin
Modified: 2021-04-25 02:50 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In: 7.3.0


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Konstantin 2015-04-11 17:22:24 UTC
I have NTFS partition which mounted in Linux.
And there I have Album with russian name.
And all of it would lead me to error: Digikam cannot save any modified file. He created file with zero size, but then Exiv generates throw and operations aborted.
I cannot redact anything with digikam now.

That convert to std:string in libkexiv2/kexiv2.cpp:308
image = Exiv2::ImageFactory::open((const char*)(QFile::encodeName(filePath)));
is really alright?

Reproducible: Always

Steps to Reproduce:
1. Create Album on NTFS with non-english name
2. Try to modifity some photos within this album

Actual Results:  
Files created, but they have zero size or just stuck with temp names.

Expected Results:  
Files should be created normally.

log from gdb about bug:
Catchpoint 1 (exception thrown), __cxxabiv1::__cxa_throw (obj=0x7fff700272a0, tinfo=0x7ffff65dd090 <typeinfo for Exiv2::BasicError<char>>, dest=0x7fffee55c500 <Exiv2::BasicError<char>::~BasicError()>) at ../../../../libstdc++-v3/libsupc++/eh_throw.cc:62                  
62      {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
#0  0x00007ffff0f5f540 in __cxxabiv1::__cxa_throw(void*, std::type_info*, void (*)(void*)) (obj=0x7fff700272a0, tinfo=0x7ffff65dd090 <typeinfo for Exiv2::BasicError<char>>, dest=0x7fffee55c500 <Exiv2::BasicError<char>::~BasicError()>)                                     
    at ../../../../libstdc++-v3/libsupc++/eh_throw.cc:62                                                                                                                                                                                                                       
#1  0x00007fffee5a2b46 in Exiv2::ImageFactory::open(std::string const&) (path="/mount/Media/Фото и видео/2015/Свадьба Максима/фото/DSC_1383_1.JPG") at image.cpp:423                                                                                                           
#2  0x00007ffff636716b in KExiv2Iface::KExiv2::load(QString const&) const (this=this@entry=0x7fff70024890, filePath=...) at /usr/src/debug/libkexiv2-14.12.3/libkexiv2/kexiv2.cpp:308                                                                                          
#3  0x00007ffff5c825e6 in Digikam::DMetadata::load(QString const&) const (this=this@entry=0x7fff70024890, filePath=...) at /usr/src/debug/digikam-4.9.0/core/libs/dmetadata/dmetadata.cpp:110                                                                                  
#4  0x00007ffff56d435f in Digikam::ImageScanner::loadFromDisk() (this=this@entry=0x7fff8e7fb330) at /usr/src/debug/digikam-4.9.0/core/libs/database/imagescanner.cpp:1525                                                                                                      
#5  0x00007ffff56d4550 in Digikam::ImageScanner::newFile(int) (this=this@entry=0x7fff8e7fb330, albumId=albumId@entry=183) at /usr/src/debug/digikam-4.9.0/core/libs/database/imagescanner.cpp:285                                                                              
#6  0x00007ffff566d056 in Digikam::CollectionScanner::scanNewFile(QFileInfo const&, int) (this=this@entry=0x7fff8e7fb620, info=..., albumId=albumId@entry=183) at /usr/src/debug/digikam-4.9.0/core/libs/database/collectionscanner.cpp:1255                                   
#7  0x00007ffff566df3e in Digikam::CollectionScanner::scanFile(QFileInfo const&, int, long long, Digikam::CollectionScanner::FileScanMode) (this=this@entry=0x7fff8e7fb620, fi=..., albumId=albumId@entry=183, imageId=imageId@entry=-1, mode=mode@entry=Digikam::CollectionScanner::NormalScan) at /usr/src/debug/digikam-4.9.0/core/libs/database/collectionscanner.cpp:776                                                                                                                                                                                 
#8  0x00007ffff5671e8d in Digikam::CollectionScanner::scanFile(QString const&, QString const&, QString const&, Digikam::CollectionScanner::FileScanMode) (this=this@entry=0x7fff8e7fb620, albumRoot=..., album=..., fileName=..., mode=mode@entry=Digikam::CollectionScanner::NormalScan) at /usr/src/debug/digikam-4.9.0/core/libs/database/collectionscanner.cpp:750                                                                                                                                                                                        
#9  0x00007ffff567234b in Digikam::CollectionScanner::scanFile(QString const&, Digikam::CollectionScanner::FileScanMode) (this=this@entry=0x7fff8e7fb620, filePath=..., mode=mode@entry=Digikam::CollectionScanner::NormalScan)                                                
    at /usr/src/debug/digikam-4.9.0/core/libs/database/collectionscanner.cpp:719                                                                                                                                                                                               
#10 0x00000000005e3537 in Digikam::ScanController::scannedInfo(QString const&) (this=0xe6db80, filePath=...) at /usr/src/debug/digikam-4.9.0/core/app/database/scancontroller.cpp:555                                                                                          
#11 0x000000000062c9bf in Digikam::FileActionMngrDatabaseWorker::copyAttributes(Digikam::FileActionImageInfoList, QStringList const&) (this=<optimized out>, infos=..., derivedPaths=...) at /usr/src/debug/digikam-4.9.0/core/app/fileaction/databaseworkeriface.cpp:308      
#12 0x000000000062cf9d in Digikam::DatabaseWorkerInterface::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (_o=0x1c19740, _c=4133343376, _id=-296368896, _a=0x7ffff11f17a0 <std::string::_Rep::_S_empty_rep_storage>)                                            
    at /usr/src/debug/digikam-4.9.0/build/core/app/databaseworkeriface.moc:85                                                                                                                                                                                                  
#13 0x00007ffff160a59e in QObject::event(QEvent*) (this=0x1c19740, e=<optimized out>) at kernel/qobject.cpp:1231                                                                                                                                                               
#14 0x00007ffff200076c in QApplicationPrivate::notify_helper(QObject*, QEvent*) (this=this@entry=0xcf1380, receiver=receiver@entry=0x1c19740, e=e@entry=0x7fffa80c1ba0) at kernel/qapplication.cpp:4565                                                                        
#15 0x00007ffff2006cad in QApplication::notify(QObject*, QEvent*) (this=this@entry=0x7fffffffdc20, receiver=receiver@entry=0x1c19740, e=e@entry=0x7fffa80c1ba0) at kernel/qapplication.cpp:4351
#16 0x00007ffff2d18cea in KApplication::notify(QObject*, QEvent*) (this=0x7fffffffdc20, receiver=0x1c19740, event=0x7fffa80c1ba0) at /usr/src/debug/kdelibs-4.14.6/kdeui/kernel/kapplication.cpp:311
#17 0x00007ffff15f22ad in QCoreApplication::notifyInternal(QObject*, QEvent*) (this=0x7fffffffdc20, receiver=receiver@entry=0x1c19740, event=event@entry=0x7fffa80c1ba0) at kernel/qcoreapplication.cpp:953
#18 0x00007ffff15f557d in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (event=0x7fffa80c1ba0, receiver=0x1c19740) at kernel/qcoreapplication.h:231
#19 0x00007ffff15f557d in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (receiver=receiver@entry=0x0, event_type=event_type@entry=0, data=0x2fe0bc0) at kernel/qcoreapplication.cpp:1577
#20 0x00007ffff15f5a23 in QCoreApplication::sendPostedEvents(QObject*, int) (receiver=receiver@entry=0x0, event_type=event_type@entry=0) at kernel/qcoreapplication.cpp:1470
#21 0x00007ffff161f8fe in postEventSourceDispatch(GSource*, GSourceFunc, gpointer) () at kernel/qcoreapplication.h:236
#22 0x00007ffff161f8fe in postEventSourceDispatch(GSource*, GSourceFunc, gpointer) (s=0x7fff70013ca0) at kernel/qeventdispatcher_glib.cpp:300
#23 0x00007fffe8c08a04 in g_main_context_dispatch (context=0x7fff700250d0) at gmain.c:3111
#24 0x00007fffe8c08a04 in g_main_context_dispatch (context=context@entry=0x7fff700250d0) at gmain.c:3710
#25 0x00007fffe8c08c48 in g_main_context_iterate (context=context@entry=0x7fff700250d0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3781
#26 0x00007fffe8c08cec in g_main_context_iteration (context=0x7fff700250d0, may_block=1) at gmain.c:3842
#27 0x00007ffff161f0be in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (this=0x7fff70013990, flags=...) at kernel/qeventdispatcher_glib.cpp:450
#28 0x00007ffff15f0e6f in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (this=this@entry=0x7fff8e7fbce0, flags=...) at kernel/qeventloop.cpp:149
#29 0x00007ffff15f1165 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (this=this@entry=0x7fff8e7fbce0, flags=...) at kernel/qeventloop.cpp:204
#30 0x00007ffff5ced213 in Digikam::WorkerObjectRunnable::run() (this=0x7fffa80bcc00) at /usr/src/debug/digikam-4.9.0/core/libs/threads/threadmanager.cpp:196
#31 0x00007ffff14e46ae in QThreadPoolThread::run() (this=0x2fe0a20) at concurrent/qthreadpool.cpp:108
#32 0x00007ffff14f079f in QThreadPrivate::start(void*) (arg=0x2fe0a20) at thread/qthread_unix.cpp:349
#33 0x00007fffee96e0a4 in start_thread (arg=0x7fff8e7fc700) at pthread_create.c:309
#34 0x00007ffff0a2306d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
Comment 1 caulier.gilles 2015-04-11 19:14:57 UTC
From the backtrace, the crash pass to libkexiv2 and down to Exiv2 shared lib.

I recommend to forward this file to Exiv2 bugzilla. Sound like the problem is relevant of this library.

See http://www.exiv2 .org

Gilles Caulier
Comment 2 Konstantin 2015-04-12 08:31:02 UTC
(In reply to Gilles Caulier from comment #1)
> From the backtrace, the crash pass to libkexiv2 and down to Exiv2 shared lib.
> I recommend to forward this file to Exiv2 bugzilla. Sound like the problem
> is relevant of this library.
> Gilles Caulier

Well. I don't think that this is so simple to think that this is just EXIV2 bug(if it even was).
I tested it more and there a full log with my coomments:
https://drive.google.com/file/d/0B0HrM03esTe-V0NpTUliWlRJN2c/view?usp=sharing

You see there a 4 step when Exiv2 is called when output set to XFS Linux. (3 call from toolOperations, after first one call file size changed from 0 MB to 2,7 MB)
And only two steps when Exiv2 is called when you output set to NTFS(only one call(and this call doesn't throw any exceptions!) from tool operations! After this call file size is unchanded and = 0 MB).

I can't just create bug on EXIV2 bugtracker if I don't know that this is EXIV2 fault for sure. And I don't know inner structure of digikam and cannot understand where and what does wrong in digilkam so I can track problem. Can you give me some hints what can go wrong after first step when output set to NTFS so file size remains zero?
Comment 3 Konstantin 2015-04-12 08:55:07 UTC
Ugh. Doesn't pay attention to fact that in log names of temfiles in calls and names of tempfiles in my comments may differ. It kind of my fault. I append them from my other gdb session and forget to change them.
Comment 4 caulier.gilles 2015-04-12 08:57:47 UTC
In digiKam we handle metadata through libkexiv2, which is a Qt wrapper around Exiv2 library.

libkexiv2 use Qt. File paths are stored in QString which use UTF8.

Exiv2 is pure C++ lib. I don't know how UTF-8 is managed and if all way respected this encoding.

To be sure just try to use Exiv2 CLI tool to change a metadata to a file stored in NTFS with non ASCII char as file path.

If problem is reproducible with Exiv2 CLI tool, it's clear problem is located in this lib.

Note : your backtrace indicate that crash down to Exiv2. This must never happen. Exiv2 use C++ exception to handle problem. Exception are catch by libkexiv2 in top level.

So, outside the char encoding problem, the crash from Exiv2 is abnormal and must be reported to Exiv2 bugzilla. This cannot be fixed in libkexiv2.

Gilles Caulier
Comment 5 Konstantin 2015-04-17 19:56:42 UTC
(In reply to Gilles Caulier from comment #4)

Sorry, you are right. I just messed up with mount options - writed fmask=113,dmask=022 instead of fmask=113,dmask=002.
So file can be creared and readed, but cannot be writed. >_<

But! It would be really good to add
to function JPEGLoader::load in digikam/core/libs/dimg/loaders/jpegloader.cpp:111
string kDebug() << "Failed to open file \"" << filePath << "\" with flags 'rb'";
and to function JPEGLoader::save in digikam/core/libs/dimg/loaders/jpegloader.cpp:641
string kDebug() << "Failed to open file \"" << filePath << "\" with flags 'wb'";
Comment 6 caulier.gilles 2021-04-07 16:21:37 UTC
Maik, 

Since you have implmented UNC support for Windows, perhaps this file can be turned as Resolved/Fixed ?

Gilles
Comment 7 Maik Qualmann 2021-04-07 16:31:24 UTC
Well, under Windows we now use UTF16 for Windows throughout. This is about NTFS on Linux. We use UTF8 under Linux, even when QFile::encodeName() was used back then. The problem is more on the side of mounting NTFS on Linux, I mean knowing that you can specify the code page. So from our side we can't do anything anymore, we fully support UTF8/16. We should close ...

Maik