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 (execWithElevatedPrivilege(CHMOD, path, permissions)) { | |||
235 | finished(); | ||||
236 | } else { | ||||
233 | switch (errno) { | 237 | switch (errno) { | ||
234 | case EPERM: | 238 | case EPERM: | ||
235 | case EACCES: | 239 | case EACCES: | ||
236 | error(KIO::ERR_ACCESS_DENIED, path); | 240 | error(KIO::ERR_ACCESS_DENIED, path); | ||
237 | break; | 241 | break; | ||
238 | #if defined(ENOTSUP) | 242 | #if defined(ENOTSUP) | ||
dfaure: the 'm' in "from" was actually good looking there :) | |||||
239 | case ENOTSUP: // from setACL since chmod can't return ENOTSUP | 243 | case ENOTSUP: // from setACL since chmod can't return ENOTSUP | ||
240 | error(KIO::ERR_UNSUPPORTED_ACTION, i18n("Setting ACL for %1", path)); | 244 | error(KIO::ERR_UNSUPPORTED_ACTION, i18n("Setting ACL for %1", path)); | ||
241 | break; | 245 | break; | ||
242 | #endif | 246 | #endif | ||
243 | case ENOSPC: | 247 | case ENOSPC: | ||
244 | error(KIO::ERR_DISK_FULL, path); | 248 | error(KIO::ERR_DISK_FULL, path); | ||
245 | break; | 249 | break; | ||
246 | default: | 250 | default: | ||
247 | error(KIO::ERR_CANNOT_CHMOD, path); | 251 | error(KIO::ERR_CANNOT_CHMOD, path); | ||
248 | } | 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 (!execWithElevatedPrivilege(UTIME, path, qint64(utbuf.actime), qint64(utbuf.modtime))) { | ||||
263 | // TODO: errno could be EACCES, EPERM, EROFS | 269 | // TODO: errno could be EACCES, EPERM, EROFS | ||
264 | error(KIO::ERR_CANNOT_SETTIME, path); | 270 | error(KIO::ERR_CANNOT_SETTIME, path); | ||
265 | } else { | 271 | return; | ||
266 | finished(); | | |||
267 | } | 272 | } | ||
273 | } | ||||
274 | finished(); | ||||
268 | } else { | 275 | } else { | ||
269 | error(KIO::ERR_DOES_NOT_EXIST, path); | 276 | error(KIO::ERR_DOES_NOT_EXIST, path); | ||
270 | } | 277 | } | ||
271 | } | 278 | } | ||
272 | 279 | | |||
273 | void FileProtocol::mkdir(const QUrl &url, int permissions) | 280 | void FileProtocol::mkdir(const QUrl &url, int permissions) | ||
274 | { | 281 | { | ||
275 | const QString path(url.toLocalFile()); | 282 | const QString path(url.toLocalFile()); | ||
276 | 283 | | |||
277 | // qDebug() << path << "permission=" << permissions; | 284 | // qDebug() << path << "permission=" << permissions; | ||
278 | 285 | | |||
279 | // Remove existing file or symlink, if requested (#151851) | 286 | // Remove existing file or symlink, if requested (#151851) | ||
280 | if (metaData(QStringLiteral("overwrite")) == QLatin1String("true")) { | 287 | if (metaData(QStringLiteral("overwrite")) == QLatin1String("true")) { | ||
281 | QFile::remove(path); | 288 | if (!QFile::remove(path)) { | ||
289 | execWithElevatedPrivilege(DEL, path); | ||||
290 | } | ||||
282 | } | 291 | } | ||
283 | 292 | | |||
284 | QT_STATBUF buff; | 293 | QT_STATBUF buff; | ||
285 | if (QT_LSTAT(QFile::encodeName(path).constData(), &buff) == -1) { | 294 | if (QT_LSTAT(QFile::encodeName(path).constData(), &buff) == -1) { | ||
286 | if (!QDir().mkdir(path)) { | 295 | bool dirCreated = QDir().mkdir(path); | ||
296 | if (!dirCreated) | ||||
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 | dirCreated = execWithElevatedPrivilege(MKDIR, path); | ||||
298 | | ||||
299 | if (!dirCreated) { | ||||
287 | //TODO: add access denied & disk full (or another reasons) handling (into Qt, possibly) | 300 | //TODO: add access denied & disk full (or another reasons) handling (into Qt, possibly) | ||
288 | error(KIO::ERR_CANNOT_MKDIR, path); | 301 | error(KIO::ERR_CANNOT_MKDIR, path); | ||
289 | return; | 302 | return; | ||
290 | } else { | 303 | } else { | ||
291 | if (permissions != -1) { | 304 | if (permissions != -1) { | ||
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(). | |||||
292 | chmod(url, permissions); | 305 | chmod(url, permissions); | ||
293 | } else { | 306 | } else { | ||
294 | finished(); | 307 | finished(); | ||
295 | } | 308 | } | ||
296 | return; | 309 | return; | ||
297 | } | 310 | } | ||
298 | } | 311 | } | ||
299 | 312 | | |||
Show All 33 Lines | 323 | { | |||
333 | } | 346 | } | ||
334 | if ((buff.st_mode & QT_STAT_MASK) != QT_STAT_REG) { | 347 | if ((buff.st_mode & QT_STAT_MASK) != QT_STAT_REG) { | ||
335 | error(KIO::ERR_CANNOT_OPEN_FOR_READING, path); | 348 | error(KIO::ERR_CANNOT_OPEN_FOR_READING, path); | ||
336 | return; | 349 | return; | ||
337 | } | 350 | } | ||
338 | 351 | | |||
339 | QFile f(path); | 352 | QFile f(path); | ||
340 | if (!f.open(QIODevice::ReadOnly)) { | 353 | if (!f.open(QIODevice::ReadOnly)) { | ||
354 | int src_fd = -1; | ||||
355 | FdReceiver fdRecv; | ||||
356 | bool _continue = ( fdRecv.startListening(QStringLiteral("org_kde_kio_file_helper_socket")) | ||||
357 | && execWithElevatedPrivilege(OPEN, path, O_RDONLY, S_IRUSR) | ||||
358 | && (src_fd = fdRecv.fileDescriptor()) != -1 | ||||
359 | && f.open(src_fd, QIODevice::ReadOnly, QFileDevice::AutoCloseHandle)); | ||||
360 | | ||||
361 | if (!_continue) { | ||||
341 | error(KIO::ERR_CANNOT_OPEN_FOR_READING, path); | 362 | error(KIO::ERR_CANNOT_OPEN_FOR_READING, path); | ||
342 | return; | 363 | return; | ||
343 | } | 364 | } | ||
365 | } | ||||
344 | 366 | | |||
345 | #if HAVE_FADVISE | 367 | #if HAVE_FADVISE | ||
346 | //TODO check return code | 368 | //TODO check return code | ||
347 | posix_fadvise(f.handle(), 0, 0, POSIX_FADV_SEQUENTIAL); | 369 | posix_fadvise(f.handle(), 0, 0, POSIX_FADV_SEQUENTIAL); | ||
348 | #endif | 370 | #endif | ||
349 | 371 | | |||
350 | // Determine the mimetype of the file to be retrieved, and emit it. | 372 | // Determine the mimetype of the file to be retrieved, and emit it. | ||
351 | // This is mandatory in all slaves (for KRun/BrowserRun to work) | 373 | // This is mandatory in all slaves (for KRun/BrowserRun to work) | ||
▲ Show 20 Lines • Show All 230 Lines • ▼ Show 20 Line(s) | 600 | do { | |||
582 | 604 | | |||
583 | if (result >= 0) { | 605 | if (result >= 0) { | ||
584 | if (dest.isEmpty()) { | 606 | if (dest.isEmpty()) { | ||
585 | if (bMarkPartial) { | 607 | if (bMarkPartial) { | ||
586 | // qDebug() << "Appending .part extension to" << dest_orig; | 608 | // qDebug() << "Appending .part extension to" << dest_orig; | ||
587 | dest = dest_part; | 609 | dest = dest_part; | ||
588 | if (bPartExists && !(_flags & KIO::Resume)) { | 610 | if (bPartExists && !(_flags & KIO::Resume)) { | ||
589 | // qDebug() << "Deleting partial file" << dest_part; | 611 | // qDebug() << "Deleting partial file" << dest_part; | ||
590 | QFile::remove(dest_part); | 612 | if (!QFile::remove(dest_part)) { | ||
613 | execWithElevatedPrivilege(DEL, dest_part); | ||||
614 | } | ||||
591 | // Catch errors when we try to open the file. | 615 | // Catch errors when we try to open the file. | ||
592 | } | 616 | } | ||
593 | } else { | 617 | } else { | ||
594 | dest = dest_orig; | 618 | dest = dest_orig; | ||
595 | if (bOrigExists && !(_flags & KIO::Resume)) { | 619 | if (bOrigExists && !(_flags & KIO::Resume)) { | ||
596 | // qDebug() << "Deleting destination file" << dest_orig; | 620 | // qDebug() << "Deleting destination file" << dest_orig; | ||
597 | QFile::remove(dest_orig); | 621 | if (!QFile::remove(dest_orig)) { | ||
622 | execWithElevatedPrivilege(DEL, dest_orig); | ||||
623 | } | ||||
598 | // Catch errors when we try to open the file. | 624 | // Catch errors when we try to open the file. | ||
599 | } | 625 | } | ||
600 | } | 626 | } | ||
601 | 627 | | |||
602 | f.setFileName(dest); | 628 | f.setFileName(dest); | ||
603 | 629 | | |||
dfaure: remove new empty line, there's already one | |||||
604 | if ((_flags & KIO::Resume)) { | 630 | if ((_flags & KIO::Resume)) { | ||
605 | f.open(QIODevice::ReadWrite | QIODevice::Append); | 631 | f.open(QIODevice::ReadWrite | QIODevice::Append); | ||
606 | } else { | 632 | } else { | ||
607 | f.open(QIODevice::Truncate | QIODevice::WriteOnly); | 633 | f.open(QIODevice::Truncate | QIODevice::WriteOnly); | ||
608 | if (_mode != -1) { | 634 | if (_mode != -1) { | ||
609 | // WABA: Make sure that we keep writing permissions ourselves, | 635 | // WABA: Make sure that we keep writing permissions ourselves, | ||
610 | // otherwise we can be in for a surprise on NFS. | 636 | // otherwise we can be in for a surprise on NFS. | ||
611 | mode_t initialMode = _mode | S_IWUSR | S_IRUSR; | 637 | mode_t initialMode = _mode | S_IWUSR | S_IRUSR; | ||
612 | f.setPermissions(modeToQFilePermissions(initialMode)); | 638 | f.setPermissions(modeToQFilePermissions(initialMode)); | ||
613 | } | 639 | } | ||
614 | } | 640 | } | ||
615 | 641 | | |||
616 | if (!f.isOpen()) { | 642 | if (!f.isOpen()) { | ||
643 | int dest_fd = -1; | ||||
644 | int oflags = -1; | ||||
645 | int filemode = -1; | ||||
646 | QFile::OpenMode openMode; | ||||
647 | | ||||
648 | if (_flags & KIO::Resume) { | ||||
649 | oflags = O_RDWR | O_APPEND; | ||||
650 | openMode = QIODevice::ReadWrite | QIODevice::Append; | ||||
651 | } else { | ||||
652 | oflags = O_WRONLY | O_TRUNC | O_CREAT; | ||||
653 | filemode = _mode | S_IWUSR | S_IRUSR; | ||||
654 | openMode = QIODevice::Truncate | QIODevice::WriteOnly; | ||||
655 | } | ||||
656 | FdReceiver fdRecv; | ||||
657 | bool _continue = ( fdRecv.startListening(QStringLiteral("org_kde_kio_file_helper_socket")) | ||||
658 | && execWithElevatedPrivilege(OPEN, dest, oflags, filemode) | ||||
659 | && (dest_fd = fdRecv.fileDescriptor()) != -1 | ||||
660 | && f.open(dest_fd, openMode, QFileDevice::AutoCloseHandle)); | ||||
661 | if (_continue) { | ||||
662 | // change ownership as file was created by root. | ||||
663 | if (oflags & O_CREAT) { | ||||
664 | execWithElevatedPrivilege(CHOWN, dest, getuid(), -1); | ||||
665 | } | ||||
666 | } | ||||
667 | | ||||
668 | } | ||||
669 | | ||||
670 | if (!f.isOpen()) { | ||||
617 | // qDebug() << "####################### COULD NOT WRITE" << dest << "_mode=" << _mode; | 671 | // qDebug() << "####################### COULD NOT WRITE" << dest << "_mode=" << _mode; | ||
618 | // qDebug() << "QFile error==" << f.error() << "(" << f.errorString() << ")"; | 672 | // qDebug() << "QFile error==" << f.error() << "(" << f.errorString() << ")"; | ||
619 | 673 | | |||
620 | if (f.error() == QFileDevice::PermissionsError) { | 674 | if (f.error() == QFileDevice::PermissionsError) { | ||
621 | error(KIO::ERR_WRITE_ACCESS_DENIED, dest); | 675 | error(KIO::ERR_WRITE_ACCESS_DENIED, dest); | ||
622 | } else { | 676 | } else { | ||
623 | error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest); | 677 | error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest); | ||
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… | |||||
624 | } | 678 | } | ||
625 | return; | 679 | return; | ||
626 | } | 680 | } | ||
627 | } | 681 | } | ||
628 | 682 | | |||
629 | if (f.write(buffer) == -1) { | 683 | if (f.write(buffer) == -1) { | ||
630 | if (f.error() == QFile::ResourceError) { // disk full | 684 | if (f.error() == QFile::ResourceError) { // disk full | ||
631 | error(KIO::ERR_DISK_FULL, dest_orig); | 685 | error(KIO::ERR_DISK_FULL, dest_orig); | ||
Show All 13 Lines | 697 | if (result < 0) { | |||
645 | 699 | | |||
646 | if (f.isOpen()) { | 700 | if (f.isOpen()) { | ||
647 | f.close(); | 701 | f.close(); | ||
648 | 702 | | |||
649 | QT_STATBUF buff; | 703 | QT_STATBUF buff; | ||
650 | if (QT_STAT(QFile::encodeName(dest).constData(), &buff) == 0) { | 704 | if (QT_STAT(QFile::encodeName(dest).constData(), &buff) == 0) { | ||
651 | int size = config()->readEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE); | 705 | int size = config()->readEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE); | ||
652 | if (buff.st_size < size) { | 706 | if (buff.st_size < size) { | ||
653 | QFile::remove(dest); | 707 | if (!QFile::remove(dest)) { | ||
708 | execWithElevatedPrivilege(DEL, dest); | ||||
709 | } | ||||
654 | } | 710 | } | ||
655 | } | 711 | } | ||
656 | } | 712 | } | ||
657 | 713 | | |||
658 | ::exit(255); | 714 | ::exit(255); | ||
659 | } | 715 | } | ||
660 | 716 | | |||
661 | if (!f.isOpen()) { // we got nothing to write out, so we never opened the file | 717 | if (!f.isOpen()) { // we got nothing to write out, so we never opened the file | ||
Show All 9 Lines | 724 | if (f.error() != QFile::NoError) { | |||
671 | return; | 727 | return; | ||
672 | } | 728 | } | ||
673 | 729 | | |||
674 | // after full download rename the file back to original name | 730 | // after full download rename the file back to original name | ||
675 | if (bMarkPartial) { | 731 | if (bMarkPartial) { | ||
676 | //QFile::rename() never overwrites the destination file unlike ::remove, | 732 | //QFile::rename() never overwrites the destination file unlike ::remove, | ||
677 | //so we must remove it manually first | 733 | //so we must remove it manually first | ||
678 | if (_flags & KIO::Overwrite) { | 734 | if (_flags & KIO::Overwrite) { | ||
679 | QFile::remove(dest_orig); | 735 | if (!QFile::remove(dest_orig)) { | ||
736 | execWithElevatedPrivilege(DEL, dest_orig); | ||||
737 | } | ||||
680 | } | 738 | } | ||
681 | 739 | | |||
682 | if (!QFile::rename(dest, dest_orig)) { | 740 | if (!QFile::rename(dest, dest_orig)) { | ||
741 | if (!execWithElevatedPrivilege(RENAME, dest, dest_orig)) { | ||||
683 | qCWarning(KIO_FILE) << " Couldn't rename " << dest << " to " << dest_orig; | 742 | qCWarning(KIO_FILE) << " Couldn't rename " << dest << " to " << dest_orig; | ||
684 | error(KIO::ERR_CANNOT_RENAME_PARTIAL, dest_orig); | 743 | error(KIO::ERR_CANNOT_RENAME_PARTIAL, dest_orig); | ||
685 | return; | 744 | return; | ||
686 | } | 745 | } | ||
746 | } | ||||
687 | org::kde::KDirNotify::emitFileRenamed(QUrl::fromLocalFile(dest), QUrl::fromLocalFile(dest_orig)); | 747 | org::kde::KDirNotify::emitFileRenamed(QUrl::fromLocalFile(dest), QUrl::fromLocalFile(dest_orig)); | ||
688 | } | 748 | } | ||
689 | 749 | | |||
690 | // set final permissions | 750 | // set final permissions | ||
691 | if (_mode != -1 && !(_flags & KIO::Resume)) { | 751 | if (_mode != -1 && !(_flags & KIO::Resume)) { | ||
692 | if (!QFile::setPermissions(dest_orig, modeToQFilePermissions(_mode))) { | 752 | if (!QFile::setPermissions(dest_orig, modeToQFilePermissions(_mode))) { | ||
753 | if (!execWithElevatedPrivilege(CHMOD, dest_orig, _mode)) { | ||||
693 | // couldn't chmod. Eat the error if the filesystem apparently doesn't support it. | 754 | // couldn't chmod. Eat the error if the filesystem apparently doesn't support it. | ||
694 | KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByPath(dest_orig); | 755 | KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByPath(dest_orig); | ||
695 | if (mp && mp->testFileSystemFlag(KMountPoint::SupportsChmod)) { | 756 | if (mp && mp->testFileSystemFlag(KMountPoint::SupportsChmod)) { | ||
696 | warning(i18n("Could not change permissions for\n%1", dest_orig)); | 757 | warning(i18n("Could not change permissions for\n%1", dest_orig)); | ||
697 | } | 758 | } | ||
698 | } | 759 | } | ||
699 | } | 760 | } | ||
761 | } | ||||
700 | 762 | | |||
701 | // set modification time | 763 | // set modification time | ||
702 | const QString mtimeStr = metaData(QStringLiteral("modified")); | 764 | const QString mtimeStr = metaData(QStringLiteral("modified")); | ||
703 | if (!mtimeStr.isEmpty()) { | 765 | if (!mtimeStr.isEmpty()) { | ||
704 | QDateTime dt = QDateTime::fromString(mtimeStr, Qt::ISODate); | 766 | QDateTime dt = QDateTime::fromString(mtimeStr, Qt::ISODate); | ||
705 | if (dt.isValid()) { | 767 | if (dt.isValid()) { | ||
706 | QT_STATBUF dest_statbuf; | 768 | QT_STATBUF dest_statbuf; | ||
707 | if (QT_STAT(QFile::encodeName(dest_orig).constData(), &dest_statbuf) == 0) { | 769 | if (QT_STAT(QFile::encodeName(dest_orig).constData(), &dest_statbuf) == 0) { | ||
708 | #ifndef Q_OS_WIN | 770 | #ifndef Q_OS_WIN | ||
709 | struct timeval utbuf[2]; | 771 | struct timeval utbuf[2]; | ||
710 | // access time | 772 | // access time | ||
711 | utbuf[0].tv_sec = dest_statbuf.st_atime; // access time, unchanged ## TODO preserve msec | 773 | utbuf[0].tv_sec = dest_statbuf.st_atime; // access time, unchanged ## TODO preserve msec | ||
712 | utbuf[0].tv_usec = 0; | 774 | utbuf[0].tv_usec = 0; | ||
713 | // modification time | 775 | // modification time | ||
714 | utbuf[1].tv_sec = dt.toTime_t(); | 776 | utbuf[1].tv_sec = dt.toTime_t(); | ||
715 | utbuf[1].tv_usec = dt.time().msec() * 1000; | 777 | utbuf[1].tv_usec = dt.time().msec() * 1000; | ||
716 | utimes(QFile::encodeName(dest_orig).constData(), utbuf); | 778 | utimes(QFile::encodeName(dest_orig).constData(), utbuf); | ||
717 | #else | 779 | #else | ||
718 | struct utimbuf utbuf; | 780 | struct utimbuf utbuf; | ||
719 | utbuf.actime = dest_statbuf.st_atime; | 781 | utbuf.actime = dest_statbuf.st_atime; | ||
720 | utbuf.modtime = dt.toTime_t(); | 782 | utbuf.modtime = dt.toTime_t(); | ||
721 | utime(QFile::encodeName(dest_orig).constData(), &utbuf); | 783 | if (utime(QFile::encodeName(dest_orig).constData(), &utbuf) != 0) { | ||
784 | execWithElevatedPrivilege(UTIME, dest_orig, qint64(utbuf.actime), qint64(utbuf.modtime)); | ||||
785 | } | ||||
722 | #endif | 786 | #endif | ||
723 | } | 787 | } | ||
724 | } | 788 | } | ||
725 | 789 | | |||
726 | } | 790 | } | ||
727 | 791 | | |||
728 | // We have done our job => finish | 792 | // We have done our job => finish | ||
729 | finished(); | 793 | finished(); | ||
▲ Show 20 Lines • Show All 595 Lines • ▼ Show 20 Line(s) | 1388 | while (it.hasNext()) { | |||
1325 | const QString itemPath = it.next(); | 1389 | const QString itemPath = it.next(); | ||
1326 | //qDebug() << "itemPath=" << itemPath; | 1390 | //qDebug() << "itemPath=" << itemPath; | ||
1327 | const QFileInfo info = it.fileInfo(); | 1391 | const QFileInfo info = it.fileInfo(); | ||
1328 | if (info.isDir() && !info.isSymLink()) { | 1392 | if (info.isDir() && !info.isSymLink()) { | ||
1329 | dirsToDelete.prepend(itemPath); | 1393 | dirsToDelete.prepend(itemPath); | ||
1330 | } else { | 1394 | } else { | ||
1331 | //qDebug() << "QFile::remove" << itemPath; | 1395 | //qDebug() << "QFile::remove" << itemPath; | ||
1332 | if (!QFile::remove(itemPath)) { | 1396 | if (!QFile::remove(itemPath)) { | ||
1397 | if (!execWithElevatedPrivilege(DEL, itemPath)) { | ||||
1333 | error(KIO::ERR_CANNOT_DELETE, itemPath); | 1398 | error(KIO::ERR_CANNOT_DELETE, itemPath); | ||
1334 | return false; | 1399 | return false; | ||
1335 | } | 1400 | } | ||
1336 | } | 1401 | } | ||
1337 | } | 1402 | } | ||
1403 | } | ||||
1338 | QDir dir; | 1404 | QDir dir; | ||
1339 | Q_FOREACH (const QString &itemPath, dirsToDelete) { | 1405 | Q_FOREACH (const QString &itemPath, dirsToDelete) { | ||
1340 | //qDebug() << "QDir::rmdir" << itemPath; | 1406 | //qDebug() << "QDir::rmdir" << itemPath; | ||
1341 | if (!dir.rmdir(itemPath)) { | 1407 | if (!dir.rmdir(itemPath)) { | ||
1408 | if (!execWithElevatedPrivilege(RMDIR, itemPath)) { | ||||
1342 | error(KIO::ERR_CANNOT_DELETE, itemPath); | 1409 | error(KIO::ERR_CANNOT_DELETE, itemPath); | ||
1343 | return false; | 1410 | return false; | ||
1344 | } | 1411 | } | ||
1345 | } | 1412 | } | ||
1413 | } | ||||
1346 | return true; | 1414 | return true; | ||
1347 | } | 1415 | } | ||
1348 | 1416 | | |||
1349 | void FileProtocol::fileSystemFreeSpace(const QUrl &url) | 1417 | void FileProtocol::fileSystemFreeSpace(const QUrl &url) | ||
1350 | { | 1418 | { | ||
1351 | if (url.isLocalFile()) { | 1419 | if (url.isLocalFile()) { | ||
1352 | const KDiskFreeSpaceInfo spaceInfo = KDiskFreeSpaceInfo::freeSpaceInfo(url.toLocalFile()); | 1420 | const KDiskFreeSpaceInfo spaceInfo = KDiskFreeSpaceInfo::freeSpaceInfo(url.toLocalFile()); | ||
1353 | if (spaceInfo.isValid()) { | 1421 | if (spaceInfo.isValid()) { | ||
Show All 27 Lines |
the 'm' in "from" was actually good looking there :)