Changeset View
Changeset View
Standalone View
Standalone View
src/ioslaves/file/file.cpp
Show First 20 Lines • Show All 71 Lines • ▼ Show 20 Line(s) | |||||
72 | #if HAVE_VOLMGT | 72 | #if HAVE_VOLMGT | ||
73 | #include <volmgt.h> | 73 | #include <volmgt.h> | ||
74 | #include <sys/mnttab.h> | 74 | #include <sys/mnttab.h> | ||
75 | #endif | 75 | #endif | ||
76 | 76 | | |||
77 | #include <kdirnotify.h> | 77 | #include <kdirnotify.h> | ||
78 | #include <ioslave_defaults.h> | 78 | #include <ioslave_defaults.h> | ||
79 | 79 | | |||
80 | #include "sharefd.h" | ||||
81 | | ||||
80 | Q_LOGGING_CATEGORY(KIO_FILE, "kf5.kio.kio_file") | 82 | Q_LOGGING_CATEGORY(KIO_FILE, "kf5.kio.kio_file") | ||
81 | 83 | | |||
82 | // Pseudo plugin class to embed meta data | 84 | // Pseudo plugin class to embed meta data | ||
83 | class KIOPluginForMetaData : public QObject | 85 | class KIOPluginForMetaData : public QObject | ||
84 | { | 86 | { | ||
85 | Q_OBJECT | 87 | Q_OBJECT | ||
86 | Q_PLUGIN_METADATA(IID "org.kde.kio.slave.file" FILE "file.json") | 88 | Q_PLUGIN_METADATA(IID "org.kde.kio.slave.file" FILE "file.json") | ||
87 | }; | 89 | }; | ||
▲ Show 20 Lines • Show All 136 Lines • ▼ Show 20 Line(s) | |||||
224 | { | 226 | { | ||
225 | const QString path(url.toLocalFile()); | 227 | const QString path(url.toLocalFile()); | ||
226 | const QByteArray _path(QFile::encodeName(path)); | 228 | const QByteArray _path(QFile::encodeName(path)); | ||
227 | /* FIXME: Should be atomic */ | 229 | /* FIXME: Should be atomic */ | ||
228 | if (!QFile::setPermissions(path, modeToQFilePermissions(permissions)) || | 230 | if (!QFile::setPermissions(path, modeToQFilePermissions(permissions)) || | ||
229 | (setACL(_path.data(), permissions, false) == -1) || | 231 | (setACL(_path.data(), permissions, false) == -1) || | ||
230 | /* if not a directory, cannot set default ACLs */ | 232 | /* if not a directory, cannot set default ACLs */ | ||
231 | (setACL(_path.data(), permissions, true) == -1 && errno != ENOTDIR)) { | 233 | (setACL(_path.data(), permissions, true) == -1 && errno != ENOTDIR)) { | ||
232 | 234 | if (auto err = execWithElevatedPrivilege(CHMOD, _path, permissions)) { | |||
235 | if (!err.wasCanceled()) { | ||||
233 | switch (errno) { | 236 | switch (errno) { | ||
234 | case EPERM: | 237 | case EPERM: | ||
235 | case EACCES: | 238 | case EACCES: | ||
236 | error(KIO::ERR_ACCESS_DENIED, path); | 239 | error(KIO::ERR_ACCESS_DENIED, path); | ||
237 | break; | 240 | break; | ||
238 | #if defined(ENOTSUP) | 241 | #if defined(ENOTSUP) | ||
239 | case ENOTSUP: // from setACL since chmod can't return ENOTSUP | 242 | case ENOTSUP: // from setACL since chmod can't return ENOTSUP | ||
dfaure: the 'm' in "from" was actually good looking there :) | |||||
240 | error(KIO::ERR_UNSUPPORTED_ACTION, i18n("Setting ACL for %1", path)); | 243 | error(KIO::ERR_UNSUPPORTED_ACTION, i18n("Setting ACL for %1", path)); | ||
241 | break; | 244 | break; | ||
242 | #endif | 245 | #endif | ||
243 | case ENOSPC: | 246 | case ENOSPC: | ||
244 | error(KIO::ERR_DISK_FULL, path); | 247 | error(KIO::ERR_DISK_FULL, path); | ||
245 | break; | 248 | break; | ||
246 | default: | 249 | default: | ||
247 | error(KIO::ERR_CANNOT_CHMOD, path); | 250 | error(KIO::ERR_CANNOT_CHMOD, path); | ||
248 | } | 251 | } | ||
252 | } | ||||
253 | } | ||||
249 | } else { | 254 | } else { | ||
250 | finished(); | 255 | finished(); | ||
251 | } | 256 | } | ||
252 | } | 257 | } | ||
253 | 258 | | |||
254 | void FileProtocol::setModificationTime(const QUrl &url, const QDateTime &mtime) | 259 | void FileProtocol::setModificationTime(const QUrl &url, const QDateTime &mtime) | ||
255 | { | 260 | { | ||
256 | const QString path(url.toLocalFile()); | 261 | const QString path(url.toLocalFile()); | ||
257 | QT_STATBUF statbuf; | 262 | QT_STATBUF statbuf; | ||
258 | if (QT_LSTAT(QFile::encodeName(path).constData(), &statbuf) == 0) { | 263 | if (QT_LSTAT(QFile::encodeName(path).constData(), &statbuf) == 0) { | ||
259 | struct utimbuf utbuf; | 264 | struct utimbuf utbuf; | ||
260 | utbuf.actime = statbuf.st_atime; // access time, unchanged | 265 | utbuf.actime = statbuf.st_atime; // access time, unchanged | ||
261 | utbuf.modtime = mtime.toTime_t(); // modification time | 266 | utbuf.modtime = mtime.toTime_t(); // modification time | ||
262 | if (::utime(QFile::encodeName(path).constData(), &utbuf) != 0) { | 267 | if (::utime(QFile::encodeName(path).constData(), &utbuf) != 0) { | ||
268 | if (auto err = execWithElevatedPrivilege(UTIME, path, qint64(utbuf.actime), qint64(utbuf.modtime))) { | ||||
269 | if (!err.wasCanceled()) { | ||||
263 | // TODO: errno could be EACCES, EPERM, EROFS | 270 | // TODO: errno could be EACCES, EPERM, EROFS | ||
264 | error(KIO::ERR_CANNOT_SETTIME, path); | 271 | error(KIO::ERR_CANNOT_SETTIME, path); | ||
272 | } | ||||
273 | } | ||||
265 | } else { | 274 | } else { | ||
266 | finished(); | 275 | finished(); | ||
267 | } | 276 | } | ||
268 | } else { | 277 | } else { | ||
269 | error(KIO::ERR_DOES_NOT_EXIST, path); | 278 | error(KIO::ERR_DOES_NOT_EXIST, path); | ||
270 | } | 279 | } | ||
271 | } | 280 | } | ||
272 | 281 | | |||
273 | void FileProtocol::mkdir(const QUrl &url, int permissions) | 282 | void FileProtocol::mkdir(const QUrl &url, int permissions) | ||
274 | { | 283 | { | ||
275 | const QString path(url.toLocalFile()); | 284 | const QString path(url.toLocalFile()); | ||
276 | 285 | | |||
277 | // qDebug() << path << "permission=" << permissions; | 286 | // qDebug() << path << "permission=" << permissions; | ||
278 | 287 | | |||
279 | // Remove existing file or symlink, if requested (#151851) | 288 | // Remove existing file or symlink, if requested (#151851) | ||
280 | if (metaData(QStringLiteral("overwrite")) == QLatin1String("true")) { | 289 | if (metaData(QStringLiteral("overwrite")) == QLatin1String("true")) { | ||
281 | QFile::remove(path); | 290 | if (!QFile::remove(path)) { | ||
291 | if (auto err = execWithElevatedPrivilege(DEL, path)) { | ||||
292 | if (!err.wasCanceled()) { | ||||
293 | error(KIO::ERR_CANNOT_DELETE_ORIGINAL, path); | ||||
294 | } | ||||
295 | return; | ||||
296 | } | ||||
Picking this random one as an example:
dfaure: Picking this random one as an example:
- what happens if the user cancels the root-password… | |||||
297 | } | ||||
282 | } | 298 | } | ||
283 | 299 | | |||
284 | QT_STATBUF buff; | 300 | QT_STATBUF buff; | ||
285 | if (QT_LSTAT(QFile::encodeName(path).constData(), &buff) == -1) { | 301 | if (QT_LSTAT(QFile::encodeName(path).constData(), &buff) == -1) { | ||
286 | if (!QDir().mkdir(path)) { | 302 | bool dirCreated; | ||
303 | if (!(dirCreated = QDir().mkdir(path))) { | ||||
moving this to the line above would be simpler / more readable: bool dirCreated = QDir().mkdir(path); if (!dirCreated) { dfaure: moving this to the line above would be simpler / more readable:
bool dirCreated = QDir(). | |||||
304 | if (auto err = execWithElevatedPrivilege(MKDIR, path)) { | ||||
305 | if (!err.wasCanceled()) { | ||||
287 | //TODO: add access denied & disk full (or another reasons) handling (into Qt, possibly) | 306 | //TODO: add access denied & disk full (or another reasons) handling (into Qt, possibly) | ||
288 | error(KIO::ERR_CANNOT_MKDIR, path); | 307 | error(KIO::ERR_CANNOT_MKDIR, path); | ||
308 | } | ||||
289 | return; | 309 | return; | ||
290 | } else { | 310 | } | ||
311 | dirCreated = true; | ||||
312 | } | ||||
313 | | ||||
314 | if (dirCreated) { | ||||
291 | if (permissions != -1) { | 315 | if (permissions != -1) { | ||
292 | chmod(url, permissions); | 316 | chmod(url, permissions); | ||
293 | } else { | 317 | } else { | ||
294 | finished(); | 318 | finished(); | ||
295 | } | 319 | } | ||
296 | return; | 320 | return; | ||
297 | } | 321 | } | ||
298 | } | 322 | } | ||
Show All 34 Lines | 334 | { | |||
333 | } | 357 | } | ||
334 | if ((buff.st_mode & QT_STAT_MASK) != QT_STAT_REG) { | 358 | if ((buff.st_mode & QT_STAT_MASK) != QT_STAT_REG) { | ||
335 | error(KIO::ERR_CANNOT_OPEN_FOR_READING, path); | 359 | error(KIO::ERR_CANNOT_OPEN_FOR_READING, path); | ||
336 | return; | 360 | return; | ||
337 | } | 361 | } | ||
338 | 362 | | |||
339 | QFile f(path); | 363 | QFile f(path); | ||
340 | if (!f.open(QIODevice::ReadOnly)) { | 364 | if (!f.open(QIODevice::ReadOnly)) { | ||
365 | if (auto err = tryOpen(f, QFile::encodeName(path), O_RDONLY, S_IRUSR)) { | ||||
366 | if (!err.wasCanceled()) { | ||||
341 | error(KIO::ERR_CANNOT_OPEN_FOR_READING, path); | 367 | error(KIO::ERR_CANNOT_OPEN_FOR_READING, path); | ||
368 | } | ||||
342 | return; | 369 | return; | ||
343 | } | 370 | } | ||
371 | } | ||||
344 | 372 | | |||
345 | #if HAVE_FADVISE | 373 | #if HAVE_FADVISE | ||
346 | //TODO check return code | 374 | //TODO check return code | ||
347 | posix_fadvise(f.handle(), 0, 0, POSIX_FADV_SEQUENTIAL); | 375 | posix_fadvise(f.handle(), 0, 0, POSIX_FADV_SEQUENTIAL); | ||
348 | #endif | 376 | #endif | ||
349 | 377 | | |||
350 | // Determine the mimetype of the file to be retrieved, and emit it. | 378 | // Determine the mimetype of the file to be retrieved, and emit it. | ||
351 | // This is mandatory in all slaves (for KRun/BrowserRun to work) | 379 | // This is mandatory in all slaves (for KRun/BrowserRun to work) | ||
▲ Show 20 Lines • Show All 241 Lines • ▼ Show 20 Line(s) | 612 | if (dest.isEmpty()) { | |||
593 | } else { | 621 | } else { | ||
594 | dest = dest_orig; | 622 | dest = dest_orig; | ||
595 | if (bOrigExists && !(_flags & KIO::Resume)) { | 623 | if (bOrigExists && !(_flags & KIO::Resume)) { | ||
596 | // qDebug() << "Deleting destination file" << dest_orig; | 624 | // qDebug() << "Deleting destination file" << dest_orig; | ||
597 | QFile::remove(dest_orig); | 625 | QFile::remove(dest_orig); | ||
598 | // Catch errors when we try to open the file. | 626 | // Catch errors when we try to open the file. | ||
599 | } | 627 | } | ||
600 | } | 628 | } | ||
601 | 629 | | |||
dfaure: remove new empty line, there's already one | |||||
602 | f.setFileName(dest); | 630 | f.setFileName(dest); | ||
603 | 631 | | |||
604 | if ((_flags & KIO::Resume)) { | 632 | if ((_flags & KIO::Resume)) { | ||
605 | f.open(QIODevice::ReadWrite | QIODevice::Append); | 633 | f.open(QIODevice::ReadWrite | QIODevice::Append); | ||
606 | } else { | 634 | } else { | ||
607 | f.open(QIODevice::Truncate | QIODevice::WriteOnly); | 635 | f.open(QIODevice::Truncate | QIODevice::WriteOnly); | ||
608 | if (_mode != -1) { | 636 | if (_mode != -1) { | ||
609 | // WABA: Make sure that we keep writing permissions ourselves, | 637 | // WABA: Make sure that we keep writing permissions ourselves, | ||
610 | // otherwise we can be in for a surprise on NFS. | 638 | // otherwise we can be in for a surprise on NFS. | ||
611 | mode_t initialMode = _mode | S_IWUSR | S_IRUSR; | 639 | mode_t initialMode = _mode | S_IWUSR | S_IRUSR; | ||
612 | f.setPermissions(modeToQFilePermissions(initialMode)); | 640 | f.setPermissions(modeToQFilePermissions(initialMode)); | ||
613 | } | 641 | } | ||
614 | } | 642 | } | ||
615 | 643 | | |||
616 | if (!f.isOpen()) { | 644 | if (!f.isOpen()) { | ||
645 | int oflags = 0; | ||||
646 | int filemode = 0; | ||||
647 | QFile::OpenMode openMode; | ||||
648 | | ||||
649 | if (_flags & KIO::Resume) { | ||||
650 | oflags = O_RDWR | O_APPEND; | ||||
651 | openMode = QIODevice::ReadWrite | QIODevice::Append; | ||||
why not share this with lines 633/635? i.e. determine openMode once and for all, use it in both cases (as user, then as root) dfaure: why not share this with lines 633/635?
i.e. determine openMode once and for all, use it in… | |||||
652 | } else { | ||||
653 | oflags = O_WRONLY | O_TRUNC | O_CREAT; | ||||
654 | filemode = _mode | S_IWUSR | S_IRUSR; | ||||
655 | openMode = QIODevice::Truncate | QIODevice::WriteOnly; | ||||
656 | } | ||||
657 | | ||||
658 | if (auto err = tryOpen(f, QFile::encodeName(dest), oflags, filemode)) { | ||||
659 | if (!err.wasCanceled()) { | ||||
617 | // qDebug() << "####################### COULD NOT WRITE" << dest << "_mode=" << _mode; | 660 | // qDebug() << "####################### COULD NOT WRITE" << dest << "_mode=" << _mode; | ||
618 | // qDebug() << "QFile error==" << f.error() << "(" << f.errorString() << ")"; | 661 | // qDebug() << "QFile error==" << f.error() << "(" << f.errorString() << ")"; | ||
619 | 662 | | |||
620 | if (f.error() == QFileDevice::PermissionsError) { | 663 | if (f.error() == QFileDevice::PermissionsError) { | ||
621 | error(KIO::ERR_WRITE_ACCESS_DENIED, dest); | 664 | error(KIO::ERR_WRITE_ACCESS_DENIED, dest); | ||
622 | } else { | 665 | } else { | ||
623 | error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest); | 666 | error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest); | ||
624 | } | 667 | } | ||
668 | } | ||||
625 | return; | 669 | return; | ||
670 | } else { | ||||
671 | if (oflags & O_CREAT) { | ||||
672 | execWithElevatedPrivilege(CHOWN, dest, getuid(), getgid()); | ||||
673 | f.setPermissions(modeToQFilePermissions(filemode)); | ||||
674 | } | ||||
675 | } | ||||
626 | } | 676 | } | ||
627 | } | 677 | } | ||
628 | 678 | | |||
629 | if (f.write(buffer) == -1) { | 679 | if (f.write(buffer) == -1) { | ||
630 | if (f.error() == QFile::ResourceError) { // disk full | 680 | if (f.error() == QFile::ResourceError) { // disk full | ||
631 | error(KIO::ERR_DISK_FULL, dest_orig); | 681 | error(KIO::ERR_DISK_FULL, dest_orig); | ||
632 | result = -2; // means: remove dest file | 682 | result = -2; // means: remove dest file | ||
633 | } else { | 683 | } else { | ||
Show All 37 Lines | 718 | if (f.error() != QFile::NoError) { | |||
671 | return; | 721 | return; | ||
672 | } | 722 | } | ||
673 | 723 | | |||
674 | // after full download rename the file back to original name | 724 | // after full download rename the file back to original name | ||
675 | if (bMarkPartial) { | 725 | if (bMarkPartial) { | ||
676 | //QFile::rename() never overwrites the destination file unlike ::remove, | 726 | //QFile::rename() never overwrites the destination file unlike ::remove, | ||
677 | //so we must remove it manually first | 727 | //so we must remove it manually first | ||
678 | if (_flags & KIO::Overwrite) { | 728 | if (_flags & KIO::Overwrite) { | ||
679 | QFile::remove(dest_orig); | 729 | if (!QFile::remove(dest_orig)) { | ||
730 | execWithElevatedPrivilege(DEL, dest_orig); | ||||
731 | } | ||||
680 | } | 732 | } | ||
681 | 733 | | |||
682 | if (!QFile::rename(dest, dest_orig)) { | 734 | if (!QFile::rename(dest, dest_orig)) { | ||
735 | if (auto err = execWithElevatedPrivilege(RENAME, dest, dest_orig)) { | ||||
736 | if (!err.wasCanceled()) { | ||||
683 | qCWarning(KIO_FILE) << " Couldn't rename " << dest << " to " << dest_orig; | 737 | qCWarning(KIO_FILE) << " Couldn't rename " << dest << " to " << dest_orig; | ||
684 | error(KIO::ERR_CANNOT_RENAME_PARTIAL, dest_orig); | 738 | error(KIO::ERR_CANNOT_RENAME_PARTIAL, dest_orig); | ||
739 | } | ||||
685 | return; | 740 | return; | ||
686 | } | 741 | } | ||
742 | } | ||||
687 | org::kde::KDirNotify::emitFileRenamed(QUrl::fromLocalFile(dest), QUrl::fromLocalFile(dest_orig)); | 743 | org::kde::KDirNotify::emitFileRenamed(QUrl::fromLocalFile(dest), QUrl::fromLocalFile(dest_orig)); | ||
688 | } | 744 | } | ||
689 | 745 | | |||
690 | // set final permissions | 746 | // set final permissions | ||
691 | if (_mode != -1 && !(_flags & KIO::Resume)) { | 747 | if (_mode != -1 && !(_flags & KIO::Resume)) { | ||
692 | if (!QFile::setPermissions(dest_orig, modeToQFilePermissions(_mode))) { | 748 | if (!QFile::setPermissions(dest_orig, modeToQFilePermissions(_mode))) { | ||
693 | // couldn't chmod. Eat the error if the filesystem apparently doesn't support it. | 749 | // couldn't chmod. Eat the error if the filesystem apparently doesn't support it. | ||
694 | KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByPath(dest_orig); | 750 | if (auto err = execWithElevatedPrivilege(CHMOD, dest_orig, _mode)) { | ||
695 | if (mp && mp->testFileSystemFlag(KMountPoint::SupportsChmod)) { | 751 | if (!err.wasCanceled()) { | ||
696 | warning(i18n("Could not change permissions for\n%1", dest_orig)); | 752 | warning(i18n("Could not change permissions for\n%1", dest_orig)); | ||
697 | } | 753 | } | ||
698 | } | 754 | } | ||
699 | } | 755 | } | ||
756 | } | ||||
700 | 757 | | |||
701 | // set modification time | 758 | // set modification time | ||
702 | const QString mtimeStr = metaData(QStringLiteral("modified")); | 759 | const QString mtimeStr = metaData(QStringLiteral("modified")); | ||
703 | if (!mtimeStr.isEmpty()) { | 760 | if (!mtimeStr.isEmpty()) { | ||
704 | QDateTime dt = QDateTime::fromString(mtimeStr, Qt::ISODate); | 761 | QDateTime dt = QDateTime::fromString(mtimeStr, Qt::ISODate); | ||
705 | if (dt.isValid()) { | 762 | if (dt.isValid()) { | ||
706 | QT_STATBUF dest_statbuf; | 763 | QT_STATBUF dest_statbuf; | ||
707 | if (QT_STAT(QFile::encodeName(dest_orig).constData(), &dest_statbuf) == 0) { | 764 | if (QT_STAT(QFile::encodeName(dest_orig).constData(), &dest_statbuf) == 0) { | ||
708 | #ifndef Q_OS_WIN | 765 | #ifndef Q_OS_WIN | ||
709 | struct timeval utbuf[2]; | 766 | struct timeval utbuf[2]; | ||
710 | // access time | 767 | // access time | ||
711 | utbuf[0].tv_sec = dest_statbuf.st_atime; // access time, unchanged ## TODO preserve msec | 768 | utbuf[0].tv_sec = dest_statbuf.st_atime; // access time, unchanged ## TODO preserve msec | ||
712 | utbuf[0].tv_usec = 0; | 769 | utbuf[0].tv_usec = 0; | ||
713 | // modification time | 770 | // modification time | ||
714 | utbuf[1].tv_sec = dt.toTime_t(); | 771 | utbuf[1].tv_sec = dt.toTime_t(); | ||
715 | utbuf[1].tv_usec = dt.time().msec() * 1000; | 772 | utbuf[1].tv_usec = dt.time().msec() * 1000; | ||
716 | utimes(QFile::encodeName(dest_orig).constData(), utbuf); | 773 | utimes(QFile::encodeName(dest_orig).constData(), utbuf); | ||
717 | #else | 774 | #else | ||
718 | struct utimbuf utbuf; | 775 | struct utimbuf utbuf; | ||
719 | utbuf.actime = dest_statbuf.st_atime; | 776 | utbuf.actime = dest_statbuf.st_atime; | ||
720 | utbuf.modtime = dt.toTime_t(); | 777 | utbuf.modtime = dt.toTime_t(); | ||
721 | utime(QFile::encodeName(dest_orig).constData(), &utbuf); | 778 | if (utime(QFile::encodeName(dest_orig).constData(), &utbuf) != 0) { | ||
779 | execWithElevatedPrivilege(UTIME, dest_orig, qint64(utbuf.actime), qint64(utbuf.modtime)); | ||||
780 | } | ||||
722 | #endif | 781 | #endif | ||
723 | } | 782 | } | ||
724 | } | 783 | } | ||
725 | 784 | | |||
726 | } | 785 | } | ||
727 | 786 | | |||
728 | // We have done our job => finish | 787 | // We have done our job => finish | ||
729 | finished(); | 788 | finished(); | ||
▲ Show 20 Lines • Show All 595 Lines • ▼ Show 20 Line(s) | 1383 | while (it.hasNext()) { | |||
1325 | const QString itemPath = it.next(); | 1384 | const QString itemPath = it.next(); | ||
1326 | //qDebug() << "itemPath=" << itemPath; | 1385 | //qDebug() << "itemPath=" << itemPath; | ||
1327 | const QFileInfo info = it.fileInfo(); | 1386 | const QFileInfo info = it.fileInfo(); | ||
1328 | if (info.isDir() && !info.isSymLink()) { | 1387 | if (info.isDir() && !info.isSymLink()) { | ||
1329 | dirsToDelete.prepend(itemPath); | 1388 | dirsToDelete.prepend(itemPath); | ||
1330 | } else { | 1389 | } else { | ||
1331 | //qDebug() << "QFile::remove" << itemPath; | 1390 | //qDebug() << "QFile::remove" << itemPath; | ||
1332 | if (!QFile::remove(itemPath)) { | 1391 | if (!QFile::remove(itemPath)) { | ||
1392 | if (auto err = execWithElevatedPrivilege(DEL, itemPath)) { | ||||
1393 | if (!err.wasCanceled()) { | ||||
1333 | error(KIO::ERR_CANNOT_DELETE, itemPath); | 1394 | error(KIO::ERR_CANNOT_DELETE, itemPath); | ||
1395 | } | ||||
1334 | return false; | 1396 | return false; | ||
1335 | } | 1397 | } | ||
1336 | } | 1398 | } | ||
1337 | } | 1399 | } | ||
1400 | } | ||||
1338 | QDir dir; | 1401 | QDir dir; | ||
1339 | Q_FOREACH (const QString &itemPath, dirsToDelete) { | 1402 | Q_FOREACH (const QString &itemPath, dirsToDelete) { | ||
1340 | //qDebug() << "QDir::rmdir" << itemPath; | 1403 | //qDebug() << "QDir::rmdir" << itemPath; | ||
1341 | if (!dir.rmdir(itemPath)) { | 1404 | if (!dir.rmdir(itemPath)) { | ||
1405 | if (auto err = execWithElevatedPrivilege(RMDIR, itemPath)) { | ||||
1406 | if (!err.wasCanceled()) { | ||||
1342 | error(KIO::ERR_CANNOT_DELETE, itemPath); | 1407 | error(KIO::ERR_CANNOT_DELETE, itemPath); | ||
1408 | } | ||||
1343 | return false; | 1409 | return false; | ||
1344 | } | 1410 | } | ||
1345 | } | 1411 | } | ||
1412 | } | ||||
1346 | return true; | 1413 | return true; | ||
1347 | } | 1414 | } | ||
1348 | 1415 | | |||
1349 | void FileProtocol::fileSystemFreeSpace(const QUrl &url) | 1416 | void FileProtocol::fileSystemFreeSpace(const QUrl &url) | ||
1350 | { | 1417 | { | ||
1351 | if (url.isLocalFile()) { | 1418 | if (url.isLocalFile()) { | ||
1352 | const KDiskFreeSpaceInfo spaceInfo = KDiskFreeSpaceInfo::freeSpaceInfo(url.toLocalFile()); | 1419 | const KDiskFreeSpaceInfo spaceInfo = KDiskFreeSpaceInfo::freeSpaceInfo(url.toLocalFile()); | ||
1353 | if (spaceInfo.isValid()) { | 1420 | if (spaceInfo.isValid()) { | ||
Show All 27 Lines |
the 'm' in "from" was actually good looking there :)