<table><tr><td style="">kdudka added a comment.
</td><a style="text-decoration: none; padding: 4px 8px; margin: 0 8px 8px; float: right; color: #464C5C; font-weight: bold; border-radius: 3px; background-color: #F7F7F9; background-image: linear-gradient(to bottom,#fff,#f1f0f1); display: inline-block; border: 1px solid rgba(71,87,120,.2);" href="https://phabricator.kde.org/D17816">View Revision</a></tr></table><br /><div><div><p>I was wondering why copying files in Krusader or Dolphin from a vfat-formatted memory card stopped working for me after update. After copying the first file, the transfer stopped progressing and the process ended up consuming 100% CPU forever. Later I discovered that the cause of the breakage was this patch: If fgetxattr() fails with ENOTSUP, the code loops indefinitely calling fgetxattr().</p>
<p>The following hotfix made copying of files in Krusader work again for me:</p>
<div class="remarkup-code-block" style="margin: 12px 0;" data-code-lang="diff" data-sigil="remarkup-code-block"><pre class="remarkup-code" style="font: 11px/15px "Menlo", "Consolas", "Monaco", monospace; padding: 12px; margin: 0; background: rgba(71, 87, 120, 0.08);"><span style="color: #a00000">--- a/src/ioslaves/file/file_unix.cpp</span>
<span style="color: #00a000">+++ b/src/ioslaves/file/file_unix.cpp</span>
<span style="color: #800080">@@ -642,35 +642,35 @@ bool FileProtocol::copyXattrs(const int src_fd, const int dest_fd)</span>
ssize_t valuelen = 0;
do {
value.resize(valuelen);
#if HAVE_SYS_XATTR_H && !defined(__stub_getxattr) && !defined(Q_OS_MAC)
valuelen = fgetxattr(src_fd, key.constData(), value.data(), valuelen);
#elif defined(Q_OS_MAC)
valuelen = fgetxattr(src_fd, key.constData(), value.data(), valuelen, 0, 0);
#elif HAVE_SYS_EXTATTR_H
valuelen = extattr_get_fd(src_fd, EXTATTR_NAMESPACE_USER, key.constData(), valuelen == 0 ? nullptr : value.data(), valuelen);
#endif
if (valuelen > 0 && value.size() == 0) {
continue;
}
if (valuelen > 0 && value.size() > 0) {
break;
}
<span style="color: #a00000">- if (valuelen == -1 && errno == ERANGE) {</span>
<span style="color: #00a000">+ if (valuelen == -1 && errno != ERANGE) {</span>
valuelen = 0;
<span style="color: #a00000">- continue;</span>
<span style="color: #00a000">+ break;</span>
}
// happens when attr value is an empty string
if (valuelen == 0) {
break;
}
} while (true);
// Write key:value pair on destination
#if HAVE_SYS_XATTR_H && !defined(__stub_getxattr) && !defined(Q_OS_MAC)
ssize_t destlen = fsetxattr(dest_fd, key.constData(), value.constData(), valuelen, 0);
#elif defined(Q_OS_MAC)
ssize_t destlen = fsetxattr(dest_fd, key.constData(), value.constData(), valuelen, 0, 0);
#elif HAVE_SYS_EXTATTR_H
ssize_t destlen = extattr_set_fd(dest_fd, EXTATTR_NAMESPACE_USER, key.constData(), value.constData(), valuelen);
#endif
if (destlen == -1 && errno == ENOTSUP) {</pre></div>
<p>However, the code might need bigger changes to cover all the cases. I do not fully understand the (IMO over-complicated) loops around flistxattr() and fgetxattr(). Note that the fact that one of them uses <tt style="background: #ebebeb; font-size: 13px;">while (true) { ... }</tt> whereas the other one uses <tt style="background: #ebebeb; font-size: 13px;">do { ... } while (true)</tt> does not improve code readability either.</p></div></div><br /><div><strong>REVISION DETAIL</strong><div><a href="https://phabricator.kde.org/D17816">https://phabricator.kde.org/D17816</a></div></div><br /><div><strong>To: </strong>arrowd, dfaure, chinmoyr, bruns, Frameworks, tmarshall, usta, cochise<br /><strong>Cc: </strong>kdudka, usta, scheirle, tmarshall, arrowd, cfeck, bruns, phidrho, dhaumann, funkybomber, abika, pino, davidedmundson, ngraham, atha.kane, spoorun, nicolasfella, kde-frameworks-devel, LeGast00n, cblack, michaelh<br /></div>