KIOSlave
file_win.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright (C) 2000-2002 Stephan Kulow <coolo@kde.org> 00003 Copyright (C) 2000-2002 David Faure <faure@kde.org> 00004 Copyright (C) 2000-2002 Waldo Bastian <bastian@kde.org> 00005 Copyright (C) 2006 Allan Sandfeld Jensen <sandfeld@kde.org> 00006 Copyright (C) 2007 Thiago Macieira <thiago@kde.org> 00007 Copyright (C) 2007 Christian Ehrlicher <ch.ehrlicher@gmx.de> 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Library General Public 00011 License (LGPL) as published by the Free Software Foundation; 00012 either version 2 of the License, or (at your option) any later 00013 version. 00014 00015 This library is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 Library General Public License for more details. 00019 00020 You should have received a copy of the GNU Library General Public License 00021 along with this library; see the file COPYING.LIB. If not, write to 00022 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00023 Boston, MA 02110-1301, USA. 00024 */ 00025 00026 #include "file.h" 00027 00028 #include <windows.h> 00029 00030 #include <QtCore/QDir> 00031 #include <QtCore/QDirIterator> 00032 #include <QtCore/QFileInfo> 00033 00034 #include <config.h> 00035 00036 #include <kconfiggroup.h> 00037 #include <kdebug.h> 00038 00039 using namespace KIO; 00040 00041 static DWORD CALLBACK CopyProgressRoutine( 00042 LARGE_INTEGER TotalFileSize, 00043 LARGE_INTEGER TotalBytesTransferred, 00044 LARGE_INTEGER StreamSize, 00045 LARGE_INTEGER StreamBytesTransferred, 00046 DWORD dwStreamNumber, 00047 DWORD dwCallbackReason, 00048 HANDLE hSourceFile, 00049 HANDLE hDestinationFile, 00050 LPVOID lpData 00051 ) { 00052 FileProtocol *f = reinterpret_cast<FileProtocol*>(lpData); 00053 f->processedSize( TotalBytesTransferred.QuadPart ); 00054 return PROGRESS_CONTINUE; 00055 } 00056 00057 static UDSEntry createUDSEntryWin( const QFileInfo &fileInfo ) 00058 { 00059 UDSEntry entry; 00060 00061 entry.insert( KIO::UDSEntry::UDS_NAME, fileInfo.fileName() ); 00062 if( fileInfo.isSymLink() ) { 00063 entry.insert( KIO::UDSEntry::UDS_TARGET_URL, fileInfo.symLinkTarget() ); 00064 /* TODO - or not useful on windows? 00065 if ( details > 1 ) { 00066 // It is a link pointing to nowhere 00067 type = S_IFMT - 1; 00068 access = S_IRWXU | S_IRWXG | S_IRWXO; 00069 00070 entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, type ); 00071 entry.insert( KIO::UDSEntry::UDS_ACCESS, access ); 00072 entry.insert( KIO::UDSEntry::UDS_SIZE, 0LL ); 00073 goto notype; 00074 00075 } 00076 */ 00077 } 00078 int type = S_IFREG; 00079 int access = 0; 00080 if( fileInfo.isDir() ) 00081 type = S_IFDIR; 00082 else if( fileInfo.isSymLink() ) 00083 type = S_IFLNK; 00084 if( fileInfo.isReadable() ) 00085 access |= S_IRUSR; 00086 if( fileInfo.isWritable() ) 00087 access |= S_IWUSR; 00088 if( fileInfo.isExecutable() ) 00089 access |= S_IXUSR; 00090 00091 entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, type ); 00092 entry.insert( KIO::UDSEntry::UDS_ACCESS, access ); 00093 entry.insert( KIO::UDSEntry::UDS_SIZE, fileInfo.size() ); 00094 if( fileInfo.isHidden() ) 00095 entry.insert( KIO::UDSEntry::UDS_HIDDEN, true ); 00096 00097 entry.insert( KIO::UDSEntry::UDS_MODIFICATION_TIME, fileInfo.lastModified().toTime_t() ); 00098 entry.insert( KIO::UDSEntry::UDS_USER, fileInfo.owner() ); 00099 entry.insert( KIO::UDSEntry::UDS_GROUP, fileInfo.group() ); 00100 entry.insert( KIO::UDSEntry::UDS_ACCESS_TIME, fileInfo.lastRead().toTime_t() ); 00101 00102 return entry; 00103 } 00104 00105 void FileProtocol::copy( const KUrl &src, const KUrl &dest, 00106 int _mode, JobFlags _flags ) 00107 { 00108 kDebug(7101) << "copy(): " << src << " -> " << dest << ", mode=" << _mode; 00109 00110 QFileInfo _src(src.toLocalFile()); 00111 QFileInfo _dest(dest.toLocalFile()); 00112 DWORD dwFlags = COPY_FILE_FAIL_IF_EXISTS; 00113 00114 if( _src == _dest ) { 00115 error( KIO::ERR_IDENTICAL_FILES, _dest.filePath() ); 00116 return; 00117 } 00118 00119 if( !_src.exists() ) { 00120 error( KIO::ERR_DOES_NOT_EXIST, _src.filePath() ); 00121 return; 00122 } 00123 00124 if ( _src.isDir() ) { 00125 error( KIO::ERR_IS_DIRECTORY, _src.filePath() ); 00126 return; 00127 } 00128 00129 if( _dest.exists() ) { 00130 if( _dest.isDir() ) { 00131 error( KIO::ERR_DIR_ALREADY_EXIST, _dest.filePath() ); 00132 return; 00133 } 00134 00135 if (!(_flags & KIO::Overwrite)) 00136 { 00137 error( KIO::ERR_FILE_ALREADY_EXIST, _dest.filePath() ); 00138 return; 00139 } 00140 00141 dwFlags = 0; 00142 } 00143 00144 if( !QFileInfo(_dest.dir().absolutePath()).exists() ) 00145 { 00146 _dest.dir().mkdir(_dest.dir().absolutePath()); 00147 } 00148 00149 if ( CopyFileExW( ( LPCWSTR ) _src.filePath().utf16(), 00150 ( LPCWSTR ) _dest.filePath().utf16(), 00151 CopyProgressRoutine, 00152 ( LPVOID ) this, 00153 FALSE, 00154 dwFlags) == 0 ) 00155 { 00156 DWORD dwLastErr = GetLastError(); 00157 if ( dwLastErr == ERROR_FILE_NOT_FOUND ) 00158 error( KIO::ERR_DOES_NOT_EXIST, _src.filePath() ); 00159 else if ( dwLastErr == ERROR_ACCESS_DENIED ) 00160 error( KIO::ERR_ACCESS_DENIED, _dest.filePath() ); 00161 else { 00162 #if 0 00163 LPVOID lpMsgBuf; 00164 00165 FormatMessage( 00166 FORMAT_MESSAGE_ALLOCATE_BUFFER | 00167 FORMAT_MESSAGE_FROM_SYSTEM | 00168 FORMAT_MESSAGE_IGNORE_INSERTS, 00169 NULL, 00170 dwLastErr, 00171 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 00172 (LPTSTR) &lpMsgBuf, 00173 0, NULL ); 00174 OutputDebugString((WCHAR*)lpMsgBuf); 00175 #endif 00176 error( KIO::ERR_CANNOT_RENAME, _src.filePath() ); 00177 kDebug( 7101 ) << "Copying file " 00178 << _src.filePath() 00179 << " failed (" 00180 << dwLastErr << ")"; 00181 } 00182 return; 00183 } 00184 00185 finished(); 00186 } 00187 00188 void FileProtocol::listDir( const KUrl& url ) 00189 { 00190 kDebug(7101) << "========= LIST " << url.url() << " ========="; 00191 00192 if (!url.isLocalFile()) { 00193 KUrl redir(url); 00194 redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb")); 00195 redirection(redir); 00196 kDebug(7101) << "redirecting to " << redir.url(); 00197 finished(); 00198 return; 00199 } 00200 00201 QDir dir( url.toLocalFile() ); 00202 dir.setFilter( QDir::AllEntries|QDir::Hidden ); 00203 00204 if ( !dir.exists() ) { 00205 kDebug(7101) << "========= ERR_DOES_NOT_EXIST ========="; 00206 error( KIO::ERR_DOES_NOT_EXIST, url.toLocalFile() ); 00207 return; 00208 } 00209 00210 if ( !dir.isReadable() ) { 00211 kDebug(7101) << "========= ERR_CANNOT_ENTER_DIRECTORY ========="; 00212 error( KIO::ERR_CANNOT_ENTER_DIRECTORY, url.toLocalFile() ); 00213 return; 00214 } 00215 QDirIterator it( dir ); 00216 UDSEntry entry; 00217 while( it.hasNext() ) { 00218 it.next(); 00219 UDSEntry entry = createUDSEntryWin( it.fileInfo() ); 00220 00221 listEntry( entry, false ); 00222 entry.clear(); 00223 } 00224 00225 listEntry( entry, true ); // ready 00226 00227 kDebug(7101) << "============= COMPLETED LIST ============"; 00228 00229 finished(); 00230 } 00231 00232 void FileProtocol::rename( const KUrl &src, const KUrl &dest, 00233 KIO::JobFlags _flags ) 00234 { 00235 kDebug(7101) << "rename(): " << src << " -> " << dest; 00236 00237 QFileInfo _src(src.toLocalFile()); 00238 QFileInfo _dest(dest.toLocalFile()); 00239 DWORD dwFlags = 0; 00240 00241 if( _src == _dest ) { 00242 error( KIO::ERR_IDENTICAL_FILES, _dest.filePath() ); 00243 return; 00244 } 00245 00246 if( !_src.exists() ) { 00247 error( KIO::ERR_DOES_NOT_EXIST, _src.filePath() ); 00248 return; 00249 } 00250 00251 if( _dest.exists() ) { 00252 if( _dest.isDir() ) { 00253 error( KIO::ERR_DIR_ALREADY_EXIST, _dest.filePath() ); 00254 return; 00255 } 00256 00257 if (!(_flags & KIO::Overwrite)) 00258 { 00259 error( KIO::ERR_FILE_ALREADY_EXIST, _dest.filePath() ); 00260 return; 00261 } 00262 00263 #ifndef _WIN32_WCE 00264 dwFlags = MOVEFILE_REPLACE_EXISTING; 00265 #endif 00266 } 00267 // To avoid error 17 - The system cannot move the file to a different disk drive. 00268 #ifndef _WIN32_WCE 00269 dwFlags |= MOVEFILE_COPY_ALLOWED; 00270 00271 00272 if ( MoveFileExW( ( LPCWSTR ) _src.filePath().utf16(), 00273 ( LPCWSTR ) _dest.filePath().utf16(), dwFlags) == 0 ) 00274 #else 00275 if ( MoveFileW( ( LPCWSTR ) _src.filePath().utf16(), 00276 ( LPCWSTR ) _dest.filePath().utf16()) == 0 ) 00277 #endif 00278 { 00279 DWORD dwLastErr = GetLastError(); 00280 if ( dwLastErr == ERROR_FILE_NOT_FOUND ) 00281 error( KIO::ERR_DOES_NOT_EXIST, _src.filePath() ); 00282 else if ( dwLastErr == ERROR_ACCESS_DENIED ) 00283 error( KIO::ERR_ACCESS_DENIED, _dest.filePath() ); 00284 else { 00285 error( KIO::ERR_CANNOT_RENAME, _src.filePath() ); 00286 kDebug( 7101 ) << "Renaming file " 00287 << _src.filePath() 00288 << " failed (" 00289 << dwLastErr << ")"; 00290 } 00291 return; 00292 } 00293 00294 finished(); 00295 } 00296 00297 void FileProtocol::symlink( const QString &target, const KUrl &dest, KIO::JobFlags flags ) 00298 { 00299 // no symlink on windows for now 00300 // vista provides a CreateSymbolicLink() function. for now use ::copy 00301 FileProtocol::copy( target, dest, 0, flags ); 00302 } 00303 00304 void FileProtocol::del( const KUrl& url, bool isfile ) 00305 { 00306 QString _path( url.toLocalFile() ); 00307 /***** 00308 * Delete files 00309 *****/ 00310 00311 if (isfile) { 00312 kDebug( 7101 ) << "Deleting file " << _path; 00313 00314 if( DeleteFileW( ( LPCWSTR ) _path.utf16() ) == 0 ) { 00315 DWORD dwLastErr = GetLastError(); 00316 if ( dwLastErr == ERROR_PATH_NOT_FOUND ) 00317 error( KIO::ERR_DOES_NOT_EXIST, _path ); 00318 else if( dwLastErr == ERROR_ACCESS_DENIED ) 00319 error( KIO::ERR_ACCESS_DENIED, _path ); 00320 else { 00321 error( KIO::ERR_CANNOT_DELETE, _path ); 00322 kDebug( 7101 ) << "Deleting file " 00323 << _path 00324 << " failed (" 00325 << dwLastErr << ")"; 00326 } 00327 } 00328 } else { 00329 kDebug( 7101 ) << "Deleting directory " << _path; 00330 if (!deleteRecursive(_path)) 00331 return; 00332 if( RemoveDirectoryW( ( LPCWSTR ) _path.utf16() ) == 0 ) { 00333 DWORD dwLastErr = GetLastError(); 00334 if ( dwLastErr == ERROR_FILE_NOT_FOUND ) 00335 error( KIO::ERR_DOES_NOT_EXIST, _path ); 00336 else if( dwLastErr == ERROR_ACCESS_DENIED ) 00337 error( KIO::ERR_ACCESS_DENIED, _path ); 00338 else { 00339 error( KIO::ERR_CANNOT_DELETE, _path ); 00340 kDebug( 7101 ) << "Deleting directory " 00341 << _path 00342 << " failed (" 00343 << dwLastErr << ")"; 00344 } 00345 } 00346 } 00347 finished(); 00348 } 00349 00350 void FileProtocol::chown( const KUrl& url, const QString&, const QString& ) 00351 { 00352 error( KIO::ERR_CANNOT_CHOWN, url.toLocalFile() ); 00353 } 00354 00355 void FileProtocol::stat( const KUrl & url ) 00356 { 00357 if (!url.isLocalFile()) { 00358 KUrl redir(url); 00359 redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb")); 00360 redirection(redir); 00361 kDebug(7101) << "redirecting to " << redir.url(); 00362 finished(); 00363 return; 00364 } 00365 00366 const QString sDetails = metaData(QLatin1String("details")); 00367 int details = sDetails.isEmpty() ? 2 : sDetails.toInt(); 00368 kDebug(7101) << "FileProtocol::stat details=" << details; 00369 00370 UDSEntry entry = createUDSEntryWin( QFileInfo(url.toLocalFile()) ); 00371 00372 statEntry( entry ); 00373 00374 finished(); 00375 }
KDE 4.6 API Reference