KIOSlave
file_unix.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 #define QT_NO_CAST_FROM_ASCII 00027 00028 #include "file.h" 00029 00030 #include <config.h> 00031 00032 #include <QtCore/QFile> 00033 00034 #include <kde_file.h> 00035 #include <kdebug.h> 00036 #include <kconfiggroup.h> 00037 #include <kmountpoint.h> 00038 00039 #include <dirent.h> 00040 #include <errno.h> 00041 #include <fcntl.h> 00042 #include <grp.h> 00043 #include <utime.h> 00044 #include <pwd.h> 00045 #include <stdlib.h> 00046 00047 #if defined(HAVE_LIMITS_H) 00048 #include <limits.h> // PATH_MAX 00049 #endif 00050 00051 //sendfile has different semantics in different platforms 00052 #if defined HAVE_SENDFILE && defined Q_OS_LINUX 00053 #define USE_SENDFILE 1 00054 #endif 00055 00056 #ifdef USE_SENDFILE 00057 #include <sys/sendfile.h> 00058 #endif 00059 00060 namespace KDEPrivate 00061 { 00062 00063 struct CharArrayDeleter 00064 { 00065 CharArrayDeleter(char *b) : buf(b) {} 00066 ~CharArrayDeleter() { free(buf); } 00067 char *buf; 00068 }; 00069 00070 } 00071 00072 using namespace KIO; 00073 00074 #define MAX_IPC_SIZE (1024*32) 00075 00076 static bool 00077 same_inode(const KDE_struct_stat &src, const KDE_struct_stat &dest) 00078 { 00079 if (src.st_ino == dest.st_ino && 00080 src.st_dev == dest.st_dev) 00081 return true; 00082 00083 return false; 00084 } 00085 00086 extern int write_all(int fd, const char *buf, size_t len); 00087 00088 void FileProtocol::copy( const KUrl &srcUrl, const KUrl &destUrl, 00089 int _mode, JobFlags _flags ) 00090 { 00091 kDebug(7101) << "copy(): " << srcUrl << " -> " << destUrl << ", mode=" << _mode; 00092 00093 const QString src = srcUrl.toLocalFile(); 00094 const QString dest = destUrl.toLocalFile(); 00095 QByteArray _src( QFile::encodeName(src)); 00096 QByteArray _dest( QFile::encodeName(dest)); 00097 KDE_struct_stat buff_src; 00098 #ifdef HAVE_POSIX_ACL 00099 acl_t acl; 00100 #endif 00101 00102 if ( KDE_stat( _src.data(), &buff_src ) == -1 ) { 00103 if ( errno == EACCES ) 00104 error(KIO::ERR_ACCESS_DENIED, src); 00105 else 00106 error(KIO::ERR_DOES_NOT_EXIST, src); 00107 return; 00108 } 00109 00110 if ( S_ISDIR( buff_src.st_mode ) ) { 00111 error(KIO::ERR_IS_DIRECTORY, src); 00112 return; 00113 } 00114 if ( S_ISFIFO( buff_src.st_mode ) || S_ISSOCK ( buff_src.st_mode ) ) { 00115 error(KIO::ERR_CANNOT_OPEN_FOR_READING, src); 00116 return; 00117 } 00118 00119 KDE_struct_stat buff_dest; 00120 bool dest_exists = ( KDE_lstat( _dest.data(), &buff_dest ) != -1 ); 00121 if ( dest_exists ) 00122 { 00123 if (S_ISDIR(buff_dest.st_mode)) 00124 { 00125 error(KIO::ERR_DIR_ALREADY_EXIST, dest); 00126 return; 00127 } 00128 00129 if ( same_inode( buff_dest, buff_src) ) 00130 { 00131 error(KIO::ERR_IDENTICAL_FILES, dest); 00132 return; 00133 } 00134 00135 if (!(_flags & KIO::Overwrite)) 00136 { 00137 error(KIO::ERR_FILE_ALREADY_EXIST, dest); 00138 return; 00139 } 00140 00141 // If the destination is a symlink and overwrite is TRUE, 00142 // remove the symlink first to prevent the scenario where 00143 // the symlink actually points to current source! 00144 if ((_flags & KIO::Overwrite) && S_ISLNK(buff_dest.st_mode)) 00145 { 00146 //kDebug(7101) << "copy(): LINK DESTINATION"; 00147 remove( _dest.data() ); 00148 } 00149 } 00150 00151 int src_fd = KDE_open( _src.data(), O_RDONLY); 00152 if ( src_fd < 0 ) { 00153 error(KIO::ERR_CANNOT_OPEN_FOR_READING, src); 00154 return; 00155 } 00156 00157 #ifdef HAVE_FADVISE 00158 posix_fadvise(src_fd,0,0,POSIX_FADV_SEQUENTIAL); 00159 #endif 00160 // WABA: Make sure that we keep writing permissions ourselves, 00161 // otherwise we can be in for a surprise on NFS. 00162 mode_t initialMode; 00163 if (_mode != -1) 00164 initialMode = _mode | S_IWUSR; 00165 else 00166 initialMode = 0666; 00167 00168 int dest_fd = KDE_open(_dest.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode); 00169 if ( dest_fd < 0 ) { 00170 kDebug(7101) << "###### COULD NOT WRITE " << dest; 00171 if ( errno == EACCES ) { 00172 error(KIO::ERR_WRITE_ACCESS_DENIED, dest); 00173 } else { 00174 error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest); 00175 } 00176 ::close(src_fd); 00177 return; 00178 } 00179 00180 #ifdef HAVE_FADVISE 00181 posix_fadvise(dest_fd,0,0,POSIX_FADV_SEQUENTIAL); 00182 #endif 00183 00184 #ifdef HAVE_POSIX_ACL 00185 acl = acl_get_fd(src_fd); 00186 if ( acl && !isExtendedACL( acl ) ) { 00187 kDebug(7101) << _dest.data() << " doesn't have extended ACL"; 00188 acl_free( acl ); 00189 acl = NULL; 00190 } 00191 #endif 00192 totalSize( buff_src.st_size ); 00193 00194 KIO::filesize_t processed_size = 0; 00195 char buffer[ MAX_IPC_SIZE ]; 00196 int n; 00197 #ifdef USE_SENDFILE 00198 bool use_sendfile=buff_src.st_size < 0x7FFFFFFF; 00199 #endif 00200 while( 1 ) 00201 { 00202 #ifdef USE_SENDFILE 00203 if (use_sendfile) { 00204 off_t sf = processed_size; 00205 n = KDE_sendfile( dest_fd, src_fd, &sf, MAX_IPC_SIZE ); 00206 processed_size = sf; 00207 if ( n == -1 && ( errno == EINVAL || errno == ENOSYS ) ) { //not all filesystems support sendfile() 00208 kDebug(7101) << "sendfile() not supported, falling back "; 00209 use_sendfile = false; 00210 } 00211 } 00212 if (!use_sendfile) 00213 #endif 00214 n = ::read( src_fd, buffer, MAX_IPC_SIZE ); 00215 00216 if (n == -1) 00217 { 00218 if (errno == EINTR) 00219 continue; 00220 #ifdef USE_SENDFILE 00221 if ( use_sendfile ) { 00222 kDebug(7101) << "sendfile() error:" << strerror(errno); 00223 if ( errno == ENOSPC ) // disk full 00224 { 00225 error(KIO::ERR_DISK_FULL, dest); 00226 remove( _dest.data() ); 00227 } 00228 else { 00229 error(KIO::ERR_SLAVE_DEFINED, 00230 i18n("Cannot copy file from %1 to %2. (Errno: %3)", 00231 src, dest, errno)); 00232 } 00233 } else 00234 #endif 00235 error(KIO::ERR_COULD_NOT_READ, src); 00236 ::close(src_fd); 00237 ::close(dest_fd); 00238 #ifdef HAVE_POSIX_ACL 00239 if (acl) acl_free(acl); 00240 #endif 00241 return; 00242 } 00243 if (n == 0) 00244 break; // Finished 00245 #ifdef USE_SENDFILE 00246 if ( !use_sendfile ) { 00247 #endif 00248 if (write_all( dest_fd, buffer, n)) 00249 { 00250 ::close(src_fd); 00251 ::close(dest_fd); 00252 00253 if ( errno == ENOSPC ) // disk full 00254 { 00255 error(KIO::ERR_DISK_FULL, dest); 00256 remove( _dest.data() ); 00257 } 00258 else 00259 { 00260 kWarning(7101) << "Couldn't write[2]. Error:" << strerror(errno); 00261 error(KIO::ERR_COULD_NOT_WRITE, dest); 00262 } 00263 #ifdef HAVE_POSIX_ACL 00264 if (acl) acl_free(acl); 00265 #endif 00266 return; 00267 } 00268 processed_size += n; 00269 #ifdef USE_SENDFILE 00270 } 00271 #endif 00272 processedSize( processed_size ); 00273 } 00274 00275 ::close( src_fd ); 00276 00277 if (::close( dest_fd)) 00278 { 00279 kWarning(7101) << "Error when closing file descriptor[2]:" << strerror(errno); 00280 error(KIO::ERR_COULD_NOT_WRITE, dest); 00281 #ifdef HAVE_POSIX_ACL 00282 if (acl) acl_free(acl); 00283 #endif 00284 return; 00285 } 00286 00287 // set final permissions 00288 if ( _mode != -1 ) 00289 { 00290 if ( (::chmod(_dest.data(), _mode) != 0) 00291 #ifdef HAVE_POSIX_ACL 00292 || (acl && acl_set_file(_dest.data(), ACL_TYPE_ACCESS, acl) != 0) 00293 #endif 00294 ) 00295 { 00296 KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByPath(dest); 00297 // Eat the error if the filesystem apparently doesn't support chmod. 00298 if ( mp && mp->testFileSystemFlag( KMountPoint::SupportsChmod ) ) 00299 warning(i18n("Could not change permissions for\n%1", dest)); 00300 } 00301 } 00302 #ifdef HAVE_POSIX_ACL 00303 if (acl) acl_free(acl); 00304 #endif 00305 00306 // copy access and modification time 00307 struct utimbuf ut; 00308 ut.actime = buff_src.st_atime; 00309 ut.modtime = buff_src.st_mtime; 00310 if ( ::utime( _dest.data(), &ut ) != 0 ) 00311 { 00312 kWarning() << QString::fromLatin1("Couldn't preserve access and modification time for\n%1").arg(dest); 00313 } 00314 00315 processedSize( buff_src.st_size ); 00316 finished(); 00317 } 00318 00319 void FileProtocol::listDir( const KUrl& url) 00320 { 00321 if (!url.isLocalFile()) { 00322 KUrl redir(url); 00323 redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb")); 00324 redirection(redir); 00325 kDebug(7101) << "redirecting to " << redir.url(); 00326 finished(); 00327 return; 00328 } 00329 const QString path(url.toLocalFile()); 00330 const QByteArray _path(QFile::encodeName(path)); 00331 DIR* dp = opendir(_path.data()); 00332 if ( dp == 0 ) { 00333 switch (errno) { 00334 case ENOENT: 00335 error(KIO::ERR_DOES_NOT_EXIST, path); 00336 return; 00337 case ENOTDIR: 00338 error(KIO::ERR_IS_FILE, path); 00339 break; 00340 #ifdef ENOMEDIUM 00341 case ENOMEDIUM: 00342 error(ERR_SLAVE_DEFINED, 00343 i18n("No media in device for %1", path)); 00344 break; 00345 #endif 00346 default: 00347 error(KIO::ERR_CANNOT_ENTER_DIRECTORY, path); 00348 break; 00349 } 00350 return; 00351 } 00352 00353 const QString sDetails = metaData(QLatin1String("details")); 00354 const int details = sDetails.isEmpty() ? 2 : sDetails.toInt(); 00355 //kDebug(7101) << "========= LIST " << url << "details=" << details << " ========="; 00356 UDSEntry entry; 00357 00358 #ifndef HAVE_DIRENT_D_TYPE 00359 KDE_struct_stat st; 00360 #endif 00361 // Don't make this a QStringList. The locale file name we get here 00362 // should be passed intact to createUDSEntry to avoid problems with 00363 // files where QFile::encodeName(QFile::decodeName(a)) != a. 00364 QList<QByteArray> entryNames; 00365 KDE_struct_dirent *ep; 00366 if (details == 0) { 00367 // Fast path (for recursive deletion, mostly) 00368 // Simply emit the name and file type, nothing else. 00369 while ( ( ep = KDE_readdir( dp ) ) != 0 ) { 00370 entry.clear(); 00371 entry.insert(KIO::UDSEntry::UDS_NAME, QFile::decodeName(ep->d_name)); 00372 #ifdef HAVE_DIRENT_D_TYPE 00373 entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, 00374 (ep->d_type & DT_DIR) ? S_IFDIR : S_IFREG ); 00375 const bool isSymLink = (ep->d_type & DT_LNK); 00376 #else 00377 // oops, no fast way, we need to stat (e.g. on Solaris) 00378 if (KDE_lstat(ep->d_name, &st) == -1) { 00379 continue; // how can stat fail? 00380 } 00381 entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, 00382 (S_ISDIR(st.st_mode)) ? S_IFDIR : S_IFREG ); 00383 const bool isSymLink = S_ISLNK(st.st_mode); 00384 #endif 00385 if (isSymLink) { 00386 // for symlinks obey the UDSEntry contract and provide UDS_LINK_DEST 00387 // even if we don't know the link dest (and DeleteJob doesn't care...) 00388 entry.insert(KIO::UDSEntry::UDS_LINK_DEST, QLatin1String("Dummy Link Target")); 00389 } 00390 listEntry(entry, false); 00391 } 00392 closedir( dp ); 00393 listEntry( entry, true ); // ready 00394 } else { 00395 while ( ( ep = KDE_readdir( dp ) ) != 0 ) { 00396 entryNames.append( ep->d_name ); 00397 } 00398 00399 closedir( dp ); 00400 totalSize( entryNames.count() ); 00401 00402 /* set the current dir to the path to speed up 00403 in not having to pass an absolute path. 00404 We restore the path later to get out of the 00405 path - the kernel wouldn't unmount or delete 00406 directories we keep as active directory. And 00407 as the slave runs in the background, it's hard 00408 to see for the user what the problem would be */ 00409 #if !defined(PATH_MAX) && defined(__GLIBC__) 00410 char *path_buffer = ::get_current_dir_name(); 00411 const KDEPrivate::CharArrayDeleter path_buffer_deleter(path_buffer); 00412 #else 00413 char path_buffer[PATH_MAX]; 00414 path_buffer[0] = '\0'; 00415 (void) getcwd(path_buffer, PATH_MAX - 1); 00416 #endif 00417 if ( chdir( _path.data() ) ) { 00418 if (errno == EACCES) 00419 error(ERR_ACCESS_DENIED, path); 00420 else 00421 error(ERR_CANNOT_ENTER_DIRECTORY, path); 00422 finished(); 00423 } 00424 00425 QList<QByteArray>::ConstIterator it = entryNames.constBegin(); 00426 QList<QByteArray>::ConstIterator end = entryNames.constEnd(); 00427 for (; it != end; ++it) { 00428 entry.clear(); 00429 if ( createUDSEntry( QFile::decodeName(*it), 00430 *it /* we can use the filename as relative path*/, 00431 entry, details, true ) ) 00432 listEntry( entry, false); 00433 } 00434 00435 listEntry( entry, true ); // ready 00436 00437 //kDebug(7101) << "============= COMPLETED LIST ============"; 00438 00439 #if !defined(PATH_MAX) && defined(__GLIBC__) 00440 if (path_buffer) 00441 #else 00442 if (*path_buffer) 00443 #endif 00444 { 00445 chdir(path_buffer); 00446 } 00447 } 00448 finished(); 00449 } 00450 00451 void FileProtocol::rename( const KUrl &srcUrl, const KUrl &destUrl, 00452 KIO::JobFlags _flags ) 00453 { 00454 char off_t_should_be_64_bits[sizeof(off_t) >= 8 ? 1 : -1]; (void) off_t_should_be_64_bits; 00455 const QString src = srcUrl.toLocalFile(); 00456 const QString dest = destUrl.toLocalFile(); 00457 const QByteArray _src(QFile::encodeName(src)); 00458 const QByteArray _dest(QFile::encodeName(dest)); 00459 KDE_struct_stat buff_src; 00460 if ( KDE_lstat( _src.data(), &buff_src ) == -1 ) { 00461 if ( errno == EACCES ) 00462 error(KIO::ERR_ACCESS_DENIED, src); 00463 else 00464 error(KIO::ERR_DOES_NOT_EXIST, src); 00465 return; 00466 } 00467 00468 KDE_struct_stat buff_dest; 00469 // stat symlinks here (lstat, not stat), to avoid ERR_IDENTICAL_FILES when replacing symlink 00470 // with its target (#169547) 00471 bool dest_exists = ( KDE_lstat( _dest.data(), &buff_dest ) != -1 ); 00472 if ( dest_exists ) 00473 { 00474 if (S_ISDIR(buff_dest.st_mode)) 00475 { 00476 error(KIO::ERR_DIR_ALREADY_EXIST, dest); 00477 return; 00478 } 00479 00480 if ( same_inode( buff_dest, buff_src) ) 00481 { 00482 error(KIO::ERR_IDENTICAL_FILES, dest); 00483 return; 00484 } 00485 00486 if (!(_flags & KIO::Overwrite)) 00487 { 00488 error(KIO::ERR_FILE_ALREADY_EXIST, dest); 00489 return; 00490 } 00491 } 00492 00493 if ( KDE_rename( _src.data(), _dest.data())) 00494 { 00495 if (( errno == EACCES ) || (errno == EPERM)) { 00496 error(KIO::ERR_ACCESS_DENIED, dest); 00497 } 00498 else if (errno == EXDEV) { 00499 error(KIO::ERR_UNSUPPORTED_ACTION, QLatin1String("rename")); 00500 } 00501 else if (errno == EROFS) { // The file is on a read-only filesystem 00502 error(KIO::ERR_CANNOT_DELETE, src); 00503 } 00504 else { 00505 error(KIO::ERR_CANNOT_RENAME, src); 00506 } 00507 return; 00508 } 00509 00510 finished(); 00511 } 00512 00513 void FileProtocol::symlink( const QString &target, const KUrl &destUrl, KIO::JobFlags flags ) 00514 { 00515 const QString dest = destUrl.toLocalFile(); 00516 // Assume dest is local too (wouldn't be here otherwise) 00517 if ( ::symlink( QFile::encodeName(target), QFile::encodeName(dest) ) == -1 ) 00518 { 00519 // Does the destination already exist ? 00520 if ( errno == EEXIST ) 00521 { 00522 if ( (flags & KIO::Overwrite) ) 00523 { 00524 // Try to delete the destination 00525 if ( unlink( QFile::encodeName(dest) ) != 0 ) 00526 { 00527 error(KIO::ERR_CANNOT_DELETE, dest); 00528 return; 00529 } 00530 // Try again - this won't loop forever since unlink succeeded 00531 symlink( target, destUrl, flags ); 00532 } 00533 else 00534 { 00535 KDE_struct_stat buff_dest; 00536 KDE_lstat( QFile::encodeName(dest), &buff_dest ); 00537 if (S_ISDIR(buff_dest.st_mode)) 00538 error(KIO::ERR_DIR_ALREADY_EXIST, dest); 00539 else 00540 error(KIO::ERR_FILE_ALREADY_EXIST, dest); 00541 return; 00542 } 00543 } 00544 else 00545 { 00546 // Some error occurred while we tried to symlink 00547 error(KIO::ERR_CANNOT_SYMLINK, dest); 00548 return; 00549 } 00550 } 00551 finished(); 00552 } 00553 00554 void FileProtocol::del(const KUrl& url, bool isfile) 00555 { 00556 const QString path = url.toLocalFile(); 00557 const QByteArray _path( QFile::encodeName(path)); 00558 /***** 00559 * Delete files 00560 *****/ 00561 00562 if (isfile) { 00563 kDebug(7101) << "Deleting file "<< url; 00564 00565 if ( unlink( _path.data() ) == -1 ) { 00566 if ((errno == EACCES) || (errno == EPERM)) 00567 error(KIO::ERR_ACCESS_DENIED, path); 00568 else if (errno == EISDIR) 00569 error(KIO::ERR_IS_DIRECTORY, path); 00570 else 00571 error(KIO::ERR_CANNOT_DELETE, path); 00572 return; 00573 } 00574 } else { 00575 00576 /***** 00577 * Delete empty directory 00578 *****/ 00579 00580 kDebug( 7101 ) << "Deleting directory " << url.url(); 00581 if (metaData(QLatin1String("recurse")) == QLatin1String("true")) { 00582 if (!deleteRecursive(path)) 00583 return; 00584 } 00585 if ( ::rmdir( _path.data() ) == -1 ) { 00586 if ((errno == EACCES) || (errno == EPERM)) 00587 error(KIO::ERR_ACCESS_DENIED, path); 00588 else { 00589 kDebug( 7101 ) << "could not rmdir " << perror; 00590 error(KIO::ERR_COULD_NOT_RMDIR, path); 00591 return; 00592 } 00593 } 00594 } 00595 00596 finished(); 00597 } 00598 00599 void FileProtocol::chown( const KUrl& url, const QString& owner, const QString& group ) 00600 { 00601 const QString path = url.toLocalFile(); 00602 const QByteArray _path( QFile::encodeName(path) ); 00603 uid_t uid; 00604 gid_t gid; 00605 00606 // get uid from given owner 00607 { 00608 struct passwd *p = ::getpwnam(owner.toAscii()); 00609 00610 if ( ! p ) { 00611 error( KIO::ERR_SLAVE_DEFINED, 00612 i18n( "Could not get user id for given user name %1", owner ) ); 00613 return; 00614 } 00615 00616 uid = p->pw_uid; 00617 } 00618 00619 // get gid from given group 00620 { 00621 struct group *p = ::getgrnam(group.toAscii()); 00622 00623 if ( ! p ) { 00624 error( KIO::ERR_SLAVE_DEFINED, 00625 i18n( "Could not get group id for given group name %1", group ) ); 00626 return; 00627 } 00628 00629 gid = p->gr_gid; 00630 } 00631 00632 if ( ::chown(_path, uid, gid) == -1 ) { 00633 switch ( errno ) { 00634 case EPERM: 00635 case EACCES: 00636 error(KIO::ERR_ACCESS_DENIED, path); 00637 break; 00638 case ENOSPC: 00639 error(KIO::ERR_DISK_FULL, path); 00640 break; 00641 default: 00642 error(KIO::ERR_CANNOT_CHOWN, path); 00643 } 00644 } else 00645 finished(); 00646 } 00647 00648 void FileProtocol::stat( const KUrl & url ) 00649 { 00650 if (!url.isLocalFile()) { 00651 KUrl redir(url); 00652 redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb")); 00653 redirection(redir); 00654 kDebug(7101) << "redirecting to " << redir.url(); 00655 finished(); 00656 return; 00657 } 00658 00659 /* directories may not have a slash at the end if 00660 * we want to stat() them; it requires that we 00661 * change into it .. which may not be allowed 00662 * stat("/is/unaccessible") -> rwx------ 00663 * stat("/is/unaccessible/") -> EPERM H.Z. 00664 * This is the reason for the -1 00665 */ 00666 const QString path(url.path(KUrl::RemoveTrailingSlash)); 00667 const QByteArray _path( QFile::encodeName(path)); 00668 const QString sDetails = metaData(QLatin1String("details")); 00669 const int details = sDetails.isEmpty() ? 2 : sDetails.toInt(); 00670 00671 UDSEntry entry; 00672 if ( !createUDSEntry( url.fileName(), _path, entry, details, true /*with acls*/ ) ) 00673 { 00674 error(KIO::ERR_DOES_NOT_EXIST, path); 00675 return; 00676 } 00677 #if 0 00678 00679 MetaData::iterator it1 = mOutgoingMetaData.begin(); 00680 for ( ; it1 != mOutgoingMetaData.end(); it1++ ) { 00681 kDebug(7101) << it1.key() << " = " << it1.data(); 00682 } 00684 #endif 00685 statEntry( entry ); 00686 00687 finished(); 00688 }
KDE 4.6 API Reference