diff --git a/src/ioslaves/file/file_win.cpp b/src/ioslaves/file/file_win.cpp index b0f59b6c..c185b89b 100644 --- a/src/ioslaves/file/file_win.cpp +++ b/src/ioslaves/file/file_win.cpp @@ -1,410 +1,411 @@ /* Copyright (C) 2000-2002 Stephan Kulow Copyright (C) 2000-2002 David Faure Copyright (C) 2000-2002 Waldo Bastian Copyright (C) 2006 Allan Sandfeld Jensen Copyright (C) 2007 Thiago Macieira Copyright (C) 2007 Christian Ehrlicher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License (LGPL) as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "file.h" #include #include #include #include #include #include #include "kioglobal_p.h" using namespace KIO; static DWORD CALLBACK CopyProgressRoutine( LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred, LARGE_INTEGER StreamSize, LARGE_INTEGER StreamBytesTransferred, DWORD dwStreamNumber, DWORD dwCallbackReason, HANDLE hSourceFile, HANDLE hDestinationFile, LPVOID lpData ) { FileProtocol *f = reinterpret_cast(lpData); f->processedSize(TotalBytesTransferred.QuadPart); return PROGRESS_CONTINUE; } static UDSEntry createUDSEntryWin(const QFileInfo &fileInfo) { UDSEntry entry; entry.insert(KIO::UDSEntry::UDS_NAME, fileInfo.fileName()); if (fileInfo.isSymLink()) { entry.insert(KIO::UDSEntry::UDS_TARGET_URL, fileInfo.symLinkTarget()); /* TODO - or not useful on windows? if ( details > 1 ) { // It is a link pointing to nowhere type = S_IFMT - 1; access = S_IRWXU | S_IRWXG | S_IRWXO; entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, type ); entry.insert( KIO::UDSEntry::UDS_ACCESS, access ); entry.insert( KIO::UDSEntry::UDS_SIZE, 0LL ); goto notype; } */ } int type = S_IFREG; int access = 0; if (fileInfo.isDir()) { type = S_IFDIR; } else if (fileInfo.isSymLink()) { type = QT_STAT_LNK; } if (fileInfo.isReadable()) { access |= S_IRUSR; } if (fileInfo.isWritable()) { access |= S_IWUSR; } if (fileInfo.isExecutable()) { access |= S_IXUSR; } entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, type); entry.insert(KIO::UDSEntry::UDS_ACCESS, access); entry.insert(KIO::UDSEntry::UDS_SIZE, fileInfo.size()); if (fileInfo.isHidden()) { entry.insert(KIO::UDSEntry::UDS_HIDDEN, true); } entry.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, fileInfo.lastModified().toSecsSinceEpoch()); entry.insert(KIO::UDSEntry::UDS_USER, fileInfo.owner()); entry.insert(KIO::UDSEntry::UDS_GROUP, fileInfo.group()); entry.insert(KIO::UDSEntry::UDS_ACCESS_TIME, fileInfo.lastRead().toSecsSinceEpoch()); + entry.insert(KIO::UDSEntry::UDS_CREATION_TIME, fileInfo.birthTime().toSecsSinceEpoch()); return entry; } void FileProtocol::copy(const QUrl &src, const QUrl &dest, int _mode, JobFlags _flags) { // qDebug() << "copy(): " << src << " -> " << dest << ", mode=" << _mode; QFileInfo _src(src.toLocalFile()); QFileInfo _dest(dest.toLocalFile()); DWORD dwFlags = COPY_FILE_FAIL_IF_EXISTS; if (_src == _dest) { error(KIO::ERR_IDENTICAL_FILES, _dest.filePath()); return; } if (!_src.exists()) { error(KIO::ERR_DOES_NOT_EXIST, _src.filePath()); return; } if (_src.isDir()) { error(KIO::ERR_IS_DIRECTORY, _src.filePath()); return; } if (_dest.exists()) { if (_dest.isDir()) { error(KIO::ERR_DIR_ALREADY_EXIST, _dest.filePath()); return; } if (!(_flags & KIO::Overwrite)) { error(KIO::ERR_FILE_ALREADY_EXIST, _dest.filePath()); return; } dwFlags = 0; } if (!QFileInfo(_dest.dir().absolutePath()).exists()) { _dest.dir().mkdir(_dest.dir().absolutePath()); } if (CopyFileExW((LPCWSTR) _src.filePath().utf16(), (LPCWSTR) _dest.filePath().utf16(), CopyProgressRoutine, (LPVOID) this, FALSE, dwFlags) == 0) { DWORD dwLastErr = GetLastError(); if (dwLastErr == ERROR_FILE_NOT_FOUND) { error(KIO::ERR_DOES_NOT_EXIST, _src.filePath()); } else if (dwLastErr == ERROR_ACCESS_DENIED) { error(KIO::ERR_ACCESS_DENIED, _dest.filePath()); } else { #if 0 LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwLastErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); OutputDebugString((WCHAR *)lpMsgBuf); #endif error(KIO::ERR_CANNOT_RENAME, _src.filePath()); // qDebug() << "Copying file " << _src.filePath() << " failed (" << dwLastErr << ")"; } return; } finished(); } void FileProtocol::listDir(const QUrl &url) { // qDebug() << "========= LIST " << url << " ========="; if (!url.isLocalFile()) { QUrl redir(url); redir.setScheme(configValue(QStringLiteral("DefaultRemoteProtocol"), QStringLiteral("smb"))); redirection(redir); // qDebug() << "redirecting to " << redir; finished(); return; } QString path = url.toLocalFile(); // C: means current directory, a concept which makes no sense in a GUI // KCoreDireLister strips trailing slashes, let's put it back again here for C:/ if (path.length() == 2 && path.at(1) == QLatin1Char(':')) path += QLatin1Char('/'); const QFileInfo info(path); if (info.isFile()) { error(KIO::ERR_IS_FILE, path); return; } QDir dir(path); dir.setFilter(QDir::AllEntries | QDir::Hidden); if (!dir.exists()) { // qDebug() << "========= ERR_DOES_NOT_EXIST ========="; error(KIO::ERR_DOES_NOT_EXIST, path); return; } if (!dir.isReadable()) { // qDebug() << "========= ERR_CANNOT_ENTER_DIRECTORY ========="; error(KIO::ERR_CANNOT_ENTER_DIRECTORY, path); return; } QDirIterator it(dir); UDSEntry entry; while (it.hasNext()) { it.next(); UDSEntry entry = createUDSEntryWin(it.fileInfo()); listEntry(entry); entry.clear(); } // qDebug() << "============= COMPLETED LIST ============"; finished(); } void FileProtocol::rename(const QUrl &src, const QUrl &dest, KIO::JobFlags _flags) { // qDebug() << "rename(): " << src << " -> " << dest; QFileInfo _src(src.toLocalFile()); QFileInfo _dest(dest.toLocalFile()); DWORD dwFlags = 0; if (_src == _dest) { error(KIO::ERR_IDENTICAL_FILES, _dest.filePath()); return; } if (!_src.exists()) { error(KIO::ERR_DOES_NOT_EXIST, _src.filePath()); return; } if (_dest.exists()) { if (_dest.isDir()) { error(KIO::ERR_DIR_ALREADY_EXIST, _dest.filePath()); return; } if (!(_flags & KIO::Overwrite)) { error(KIO::ERR_FILE_ALREADY_EXIST, _dest.filePath()); return; } #ifndef _WIN32_WCE dwFlags = MOVEFILE_REPLACE_EXISTING; #endif } // To avoid error 17 - The system cannot move the file to a different disk drive. #ifndef _WIN32_WCE dwFlags |= MOVEFILE_COPY_ALLOWED; if (MoveFileExW((LPCWSTR) _src.filePath().utf16(), (LPCWSTR) _dest.filePath().utf16(), dwFlags) == 0) #else if (MoveFileW((LPCWSTR) _src.filePath().utf16(), (LPCWSTR) _dest.filePath().utf16()) == 0) #endif { DWORD dwLastErr = GetLastError(); if (dwLastErr == ERROR_FILE_NOT_FOUND) { error(KIO::ERR_DOES_NOT_EXIST, _src.filePath()); } else if (dwLastErr == ERROR_ACCESS_DENIED) { error(KIO::ERR_ACCESS_DENIED, _dest.filePath()); } else { error(KIO::ERR_CANNOT_RENAME, _src.filePath()); qCDebug(KIO_FILE) << "Renaming file " << _src.filePath() << " failed (" << dwLastErr << ")"; } return; } finished(); } void FileProtocol::symlink(const QString &target, const QUrl &dest, KIO::JobFlags flags) { QString localDest = dest.toLocalFile(); //TODO handle overwrite, etc if (!KIOPrivate::createSymlink(target, localDest)) { error(KIO::ERR_UNKNOWN, localDest); } } void FileProtocol::del(const QUrl &url, bool isfile) { QString _path(url.toLocalFile()); /***** * Delete files *****/ if (isfile) { // qDebug() << "Deleting file " << _path; if (DeleteFileW((LPCWSTR) _path.utf16()) == 0) { DWORD dwLastErr = GetLastError(); if (dwLastErr == ERROR_PATH_NOT_FOUND) { error(KIO::ERR_DOES_NOT_EXIST, _path); } else if (dwLastErr == ERROR_ACCESS_DENIED) { error(KIO::ERR_ACCESS_DENIED, _path); } else { error(KIO::ERR_CANNOT_DELETE, _path); // qDebug() << "Deleting file " << _path << " failed (" << dwLastErr << ")"; } } } else { // qDebug() << "Deleting directory " << _path; if (!deleteRecursive(_path)) { return; } if (RemoveDirectoryW((LPCWSTR) _path.utf16()) == 0) { DWORD dwLastErr = GetLastError(); if (dwLastErr == ERROR_FILE_NOT_FOUND) { error(KIO::ERR_DOES_NOT_EXIST, _path); } else if (dwLastErr == ERROR_ACCESS_DENIED) { error(KIO::ERR_ACCESS_DENIED, _path); } else { error(KIO::ERR_CANNOT_DELETE, _path); // qDebug() << "Deleting directory " << _path << " failed (" << dwLastErr << ")"; } } } finished(); } void FileProtocol::chown(const QUrl &url, const QString &, const QString &) { error(KIO::ERR_CANNOT_CHOWN, url.toLocalFile()); } void FileProtocol::stat(const QUrl &url) { if (!url.isLocalFile()) { redirect(url); return; } const QString sDetails = metaData(QLatin1String("details")); int details = sDetails.isEmpty() ? 2 : sDetails.toInt(); // qDebug() << "FileProtocol::stat details=" << details; const QString localFile = url.toLocalFile(); QFileInfo fileInfo(localFile); if (!fileInfo.exists()) { error(KIO::ERR_DOES_NOT_EXIST, localFile); return; } UDSEntry entry = createUDSEntryWin(fileInfo); statEntry(entry); finished(); } bool FileProtocol::privilegeOperationUnitTestMode() { return false; } PrivilegeOperationReturnValue FileProtocol::execWithElevatedPrivilege(ActionType, const QVariantList &, int err) { return PrivilegeOperationReturnValue::failure(err); } PrivilegeOperationReturnValue FileProtocol::tryOpen(QFile &f, const QByteArray &, int , int, int err) { return PrivilegeOperationReturnValue::failure(err); } PrivilegeOperationReturnValue FileProtocol::tryChangeFileAttr(ActionType, const QVariantList &, int err) { return PrivilegeOperationReturnValue::failure(err); } int FileProtocol::setACL(const char *path, mode_t perm, bool directoryDefault) { Q_UNUSED(path); Q_UNUSED(perm); Q_UNUSED(directoryDefault); return 0; }