00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <config.h>
00026
00027 #include <qglobal.h>
00028 #include <sys/types.h>
00029 #include <sys/wait.h>
00030 #include <sys/stat.h>
00031 #ifdef HAVE_SYS_TIME_H
00032 #include <sys/time.h>
00033 #endif
00034
00035
00036 #if defined HAVE_SENDFILE && defined Q_OS_LINUX
00037 #define USE_SENDFILE 1
00038 #endif
00039
00040 #ifdef USE_SENDFILE
00041 #include <sys/sendfile.h>
00042 #endif
00043
00044 #ifdef USE_POSIX_ACL
00045 #include <sys/acl.h>
00046 #ifdef HAVE_NON_POSIX_ACL_EXTENSIONS
00047 #include <acl/libacl.h>
00048 #else
00049 #include <posixacladdons.h>
00050 #endif
00051 #endif
00052
00053 #include <assert.h>
00054 #include <dirent.h>
00055 #include <errno.h>
00056 #include <fcntl.h>
00057 #include <grp.h>
00058 #include <pwd.h>
00059 #include <stdio.h>
00060 #include <stdlib.h>
00061 #include <signal.h>
00062 #include <time.h>
00063 #include <utime.h>
00064 #include <unistd.h>
00065 #ifdef HAVE_STRING_H
00066 #include <string.h>
00067 #endif
00068
00069 #include <qvaluelist.h>
00070 #include <qregexp.h>
00071
00072 #include <kshred.h>
00073 #include <kdebug.h>
00074 #include <kurl.h>
00075 #include <kinstance.h>
00076 #include <ksimpleconfig.h>
00077 #include <ktempfile.h>
00078 #include <klocale.h>
00079 #include <qfile.h>
00080 #include <qstrlist.h>
00081 #include "file.h"
00082 #include <limits.h>
00083 #include <kprocess.h>
00084 #include <kmountpoint.h>
00085 #include <kstandarddirs.h>
00086
00087 #ifdef HAVE_VOLMGT
00088 #include <volmgt.h>
00089 #include <sys/mnttab.h>
00090 #endif
00091
00092 #include <kstandarddirs.h>
00093 #include <kio/ioslave_defaults.h>
00094 #include <klargefile.h>
00095 #include <kglobal.h>
00096 #include <kmimetype.h>
00097
00098 using namespace KIO;
00099
00100 #define MAX_IPC_SIZE (1024*32)
00101
00102 static QString testLogFile( const char *_filename );
00103 #ifdef USE_POSIX_ACL
00104 static QString aclAsString( acl_t p_acl );
00105 static bool isExtendedACL( acl_t p_acl );
00106 static void appendACLAtoms( const QCString & path, UDSEntry& entry,
00107 mode_t type, bool withACL );
00108 #endif
00109
00110 extern "C" { KDE_EXPORT int kdemain(int argc, char **argv); }
00111
00112 int kdemain( int argc, char **argv )
00113 {
00114 KLocale::setMainCatalogue("kdelibs");
00115 KInstance instance( "kio_file" );
00116 ( void ) KGlobal::locale();
00117
00118 kdDebug(7101) << "Starting " << getpid() << endl;
00119
00120 if (argc != 4)
00121 {
00122 fprintf(stderr, "Usage: kio_file protocol domain-socket1 domain-socket2\n");
00123 exit(-1);
00124 }
00125
00126 FileProtocol slave(argv[2], argv[3]);
00127 slave.dispatchLoop();
00128
00129 kdDebug(7101) << "Done" << endl;
00130 return 0;
00131 }
00132
00133
00134 FileProtocol::FileProtocol( const QCString &pool, const QCString &app ) : SlaveBase( "file", pool, app )
00135 {
00136 usercache.setAutoDelete( true );
00137 groupcache.setAutoDelete( true );
00138 }
00139
00140
00141 int FileProtocol::setACL( const char *path, mode_t perm, bool directoryDefault )
00142 {
00143 int ret = 0;
00144 #ifdef USE_POSIX_ACL
00145
00146 const QString ACLString = metaData( "ACL_STRING" );
00147 const QString defaultACLString = metaData( "DEFAULT_ACL_STRING" );
00148
00149 if ( !ACLString.isEmpty() ) {
00150 acl_t acl = 0;
00151 if ( ACLString == "ACL_DELETE" ) {
00152
00153
00154 acl = acl_from_mode( perm );
00155 }
00156 acl = acl_from_text( ACLString.latin1() );
00157 if ( acl_valid( acl ) == 0 ) {
00158 ret = acl_set_file( path, ACL_TYPE_ACCESS, acl );
00159 kdDebug(7101) << "Set ACL on: " << path << " to: " << aclAsString( acl ) << endl;
00160 }
00161 acl_free( acl );
00162 if ( ret != 0 ) return ret;
00163 }
00164
00165 if ( directoryDefault && !defaultACLString.isEmpty() ) {
00166 if ( defaultACLString == "ACL_DELETE" ) {
00167
00168 ret += acl_delete_def_file( path );
00169 } else {
00170 acl_t acl = acl_from_text( defaultACLString.latin1() );
00171 if ( acl_valid( acl ) == 0 ) {
00172 ret += acl_set_file( path, ACL_TYPE_DEFAULT, acl );
00173 kdDebug(7101) << "Set Default ACL on: " << path << " to: " << aclAsString( acl ) << endl;
00174 }
00175 acl_free( acl );
00176 }
00177 }
00178 #endif
00179 return ret;
00180 }
00181
00182 void FileProtocol::chmod( const KURL& url, int permissions )
00183 {
00184 QCString _path( QFile::encodeName(url.path()) );
00185
00186 if ( ::chmod( _path.data(), permissions ) == -1 ||
00187 ( setACL( _path.data(), permissions, false ) == -1 ) ||
00188
00189 ( setACL( _path.data(), permissions, true ) == -1 && errno != ENOTDIR ) ) {
00190
00191 switch (errno) {
00192 case EPERM:
00193 case EACCES:
00194 error( KIO::ERR_ACCESS_DENIED, url.path() );
00195 break;
00196 case ENOTSUP:
00197 error( KIO::ERR_UNSUPPORTED_ACTION, url.path() );
00198 break;
00199 case ENOSPC:
00200 error( KIO::ERR_DISK_FULL, url.path() );
00201 break;
00202 default:
00203 error( KIO::ERR_CANNOT_CHMOD, url.path() );
00204 }
00205 } else
00206 finished();
00207 }
00208
00209 void FileProtocol::mkdir( const KURL& url, int permissions )
00210 {
00211 QCString _path( QFile::encodeName(url.path()));
00212
00213 kdDebug(7101) << "mkdir(): " << _path << ", permission = " << permissions << endl;
00214
00215 KDE_struct_stat buff;
00216 if ( KDE_stat( _path.data(), &buff ) == -1 ) {
00217 if ( ::mkdir( _path.data(), 0777 ) != 0 ) {
00218 if ( errno == EACCES ) {
00219 error( KIO::ERR_ACCESS_DENIED, url.path() );
00220 return;
00221 } else if ( errno == ENOSPC ) {
00222 error( KIO::ERR_DISK_FULL, url.path() );
00223 return;
00224 } else {
00225 error( KIO::ERR_COULD_NOT_MKDIR, url.path() );
00226 return;
00227 }
00228 } else {
00229 if ( permissions != -1 )
00230 chmod( url, permissions );
00231 else
00232 finished();
00233 return;
00234 }
00235 }
00236
00237 if ( S_ISDIR( buff.st_mode ) ) {
00238 kdDebug(7101) << "ERR_DIR_ALREADY_EXIST" << endl;
00239 error( KIO::ERR_DIR_ALREADY_EXIST, url.path() );
00240 return;
00241 }
00242 error( KIO::ERR_FILE_ALREADY_EXIST, url.path() );
00243 return;
00244 }
00245
00246 void FileProtocol::get( const KURL& url )
00247 {
00248 if (!url.isLocalFile()) {
00249 KURL redir(url);
00250 redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb"));
00251 redirection(redir);
00252 finished();
00253 return;
00254 }
00255
00256 QCString _path( QFile::encodeName(url.path()));
00257 KDE_struct_stat buff;
00258 if ( KDE_stat( _path.data(), &buff ) == -1 ) {
00259 if ( errno == EACCES )
00260 error( KIO::ERR_ACCESS_DENIED, url.path() );
00261 else
00262 error( KIO::ERR_DOES_NOT_EXIST, url.path() );
00263 return;
00264 }
00265
00266 if ( S_ISDIR( buff.st_mode ) ) {
00267 error( KIO::ERR_IS_DIRECTORY, url.path() );
00268 return;
00269 }
00270 if ( !S_ISREG( buff.st_mode ) ) {
00271 error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
00272 return;
00273 }
00274
00275 int fd = KDE_open( _path.data(), O_RDONLY);
00276 if ( fd < 0 ) {
00277 error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
00278 return;
00279 }
00280
00281 #ifdef HAVE_FADVISE
00282 posix_fadvise( fd, 0, 0, POSIX_FADV_SEQUENTIAL);
00283 #endif
00284
00285
00286
00287 KMimeType::Ptr mt = KMimeType::findByURL( url, buff.st_mode, true );
00288 emit mimeType( mt->name() );
00289
00290 KIO::filesize_t processed_size = 0;
00291
00292 QString resumeOffset = metaData("resume");
00293 if ( !resumeOffset.isEmpty() )
00294 {
00295 bool ok;
00296 KIO::fileoffset_t offset = resumeOffset.toLongLong(&ok);
00297 if (ok && (offset > 0) && (offset < buff.st_size))
00298 {
00299 if (KDE_lseek(fd, offset, SEEK_SET) == offset)
00300 {
00301 canResume ();
00302 processed_size = offset;
00303 kdDebug( 7101 ) << "Resume offset: " << KIO::number(offset) << endl;
00304 }
00305 }
00306 }
00307
00308 totalSize( buff.st_size );
00309
00310 char buffer[ MAX_IPC_SIZE ];
00311 QByteArray array;
00312
00313 while( 1 )
00314 {
00315 int n = ::read( fd, buffer, MAX_IPC_SIZE );
00316 if (n == -1)
00317 {
00318 if (errno == EINTR)
00319 continue;
00320 error( KIO::ERR_COULD_NOT_READ, url.path());
00321 close(fd);
00322 return;
00323 }
00324 if (n == 0)
00325 break;
00326
00327 array.setRawData(buffer, n);
00328 data( array );
00329 array.resetRawData(buffer, n);
00330
00331 processed_size += n;
00332 processedSize( processed_size );
00333
00334
00335 }
00336
00337 data( QByteArray() );
00338
00339 close( fd );
00340
00341 processedSize( buff.st_size );
00342 finished();
00343 }
00344
00345 static int
00346 write_all(int fd, const char *buf, size_t len)
00347 {
00348 while (len > 0)
00349 {
00350 ssize_t written = write(fd, buf, len);
00351 if (written < 0)
00352 {
00353 if (errno == EINTR)
00354 continue;
00355 return -1;
00356 }
00357 buf += written;
00358 len -= written;
00359 }
00360 return 0;
00361 }
00362
00363 static bool
00364 same_inode(const KDE_struct_stat &src, const KDE_struct_stat &dest)
00365 {
00366 if (src.st_ino == dest.st_ino &&
00367 src.st_dev == dest.st_dev)
00368 return true;
00369
00370 return false;
00371 }
00372
00373 void FileProtocol::put( const KURL& url, int _mode, bool _overwrite, bool _resume )
00374 {
00375 QString dest_orig = url.path();
00376 QCString _dest_orig( QFile::encodeName(dest_orig));
00377
00378 kdDebug(7101) << "put(): " << dest_orig << ", mode=" << _mode << endl;
00379
00380 QString dest_part( dest_orig );
00381 dest_part += QString::fromLatin1(".part");
00382 QCString _dest_part( QFile::encodeName(dest_part));
00383
00384 KDE_struct_stat buff_orig;
00385 bool bOrigExists = (KDE_lstat( _dest_orig.data(), &buff_orig ) != -1);
00386 bool bPartExists = false;
00387 bool bMarkPartial = config()->readBoolEntry("MarkPartial", true);
00388
00389 if (bMarkPartial)
00390 {
00391 KDE_struct_stat buff_part;
00392 bPartExists = (KDE_stat( _dest_part.data(), &buff_part ) != -1);
00393
00394 if (bPartExists && !_resume && !_overwrite && buff_part.st_size > 0 && S_ISREG(buff_part.st_mode))
00395 {
00396 kdDebug(7101) << "FileProtocol::put : calling canResume with "
00397 << KIO::number(buff_part.st_size) << endl;
00398
00399
00400
00401
00402 _resume = canResume( buff_part.st_size );
00403
00404 kdDebug(7101) << "FileProtocol::put got answer " << _resume << endl;
00405 }
00406 }
00407
00408 if ( bOrigExists && !_overwrite && !_resume)
00409 {
00410 if (S_ISDIR(buff_orig.st_mode))
00411 error( KIO::ERR_DIR_ALREADY_EXIST, dest_orig );
00412 else
00413 error( KIO::ERR_FILE_ALREADY_EXIST, dest_orig );
00414 return;
00415 }
00416
00417 int result;
00418 QString dest;
00419 QCString _dest;
00420
00421 int fd = -1;
00422
00423
00424 do
00425 {
00426 QByteArray buffer;
00427 dataReq();
00428 result = readData( buffer );
00429
00430 if (result >= 0)
00431 {
00432 if (dest.isEmpty())
00433 {
00434 if (bMarkPartial)
00435 {
00436 kdDebug(7101) << "Appending .part extension to " << dest_orig << endl;
00437 dest = dest_part;
00438 if ( bPartExists && !_resume )
00439 {
00440 kdDebug(7101) << "Deleting partial file " << dest_part << endl;
00441 remove( _dest_part.data() );
00442
00443 }
00444 }
00445 else
00446 {
00447 dest = dest_orig;
00448 if ( bOrigExists && !_resume )
00449 {
00450 kdDebug(7101) << "Deleting destination file " << dest_orig << endl;
00451 remove( _dest_orig.data() );
00452
00453 }
00454 }
00455
00456 _dest = QFile::encodeName(dest);
00457
00458 if ( _resume )
00459 {
00460 fd = KDE_open( _dest.data(), O_RDWR );
00461 KDE_lseek(fd, 0, SEEK_END);
00462 }
00463 else
00464 {
00465
00466
00467 mode_t initialMode;
00468 if (_mode != -1)
00469 initialMode = _mode | S_IWUSR | S_IRUSR;
00470 else
00471 initialMode = 0666;
00472
00473 fd = KDE_open(_dest.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode);
00474 }
00475
00476 if ( fd < 0 )
00477 {
00478 kdDebug(7101) << "####################### COULD NOT WRITE " << dest << " _mode=" << _mode << endl;
00479 kdDebug(7101) << "errno==" << errno << "(" << strerror(errno) << ")" << endl;
00480 if ( errno == EACCES )
00481 error( KIO::ERR_WRITE_ACCESS_DENIED, dest );
00482 else
00483 error( KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest );
00484 return;
00485 }
00486 }
00487
00488 if (write_all( fd, buffer.data(), buffer.size()))
00489 {
00490 if ( errno == ENOSPC )
00491 {
00492 error( KIO::ERR_DISK_FULL, dest_orig);
00493 result = -2;
00494 }
00495 else
00496 {
00497 kdWarning(7101) << "Couldn't write. Error:" << strerror(errno) << endl;
00498 error( KIO::ERR_COULD_NOT_WRITE, dest_orig);
00499 result = -1;
00500 }
00501 }
00502 }
00503 }
00504 while ( result > 0 );
00505
00506
00507 if (result < 0)
00508 {
00509 kdDebug(7101) << "Error during 'put'. Aborting." << endl;
00510
00511 if (fd != -1)
00512 {
00513 close(fd);
00514
00515 KDE_struct_stat buff;
00516 if (bMarkPartial && KDE_stat( _dest.data(), &buff ) == 0)
00517 {
00518 int size = config()->readNumEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE);
00519 if (buff.st_size < size)
00520 remove(_dest.data());
00521 }
00522 }
00523
00524 ::exit(255);
00525 }
00526
00527 if ( fd == -1 )
00528 {
00529 finished();
00530 return;
00531 }
00532
00533 if ( close(fd) )
00534 {
00535 kdWarning(7101) << "Error when closing file descriptor:" << strerror(errno) << endl;
00536 error( KIO::ERR_COULD_NOT_WRITE, dest_orig);
00537 return;
00538 }
00539
00540
00541 if ( bMarkPartial )
00542 {
00543
00544
00545
00546 if( _overwrite && S_ISLNK( buff_orig.st_mode ) )
00547 remove( _dest_orig.data() );
00548
00549 if ( ::rename( _dest.data(), _dest_orig.data() ) )
00550 {
00551 kdWarning(7101) << " Couldn't rename " << _dest << " to " << _dest_orig << endl;
00552 error( KIO::ERR_CANNOT_RENAME_PARTIAL, dest_orig );
00553 return;
00554 }
00555 }
00556
00557
00558 if ( _mode != -1 && !_resume )
00559 {
00560 if (::chmod(_dest_orig.data(), _mode) != 0)
00561 {
00562
00563 if ( KIO::testFileSystemFlag( _dest_orig, KIO::SupportsChmod ) )
00564 warning( i18n( "Could not change permissions for\n%1" ).arg( dest_orig ) );
00565 }
00566 }
00567
00568
00569 const QString mtimeStr = metaData( "modified" );
00570 if ( !mtimeStr.isEmpty() ) {
00571 QDateTime dt = QDateTime::fromString( mtimeStr, Qt::ISODate );
00572 if ( dt.isValid() ) {
00573 KDE_struct_stat dest_statbuf;
00574 if (KDE_stat( _dest_orig.data(), &dest_statbuf ) == 0) {
00575 struct utimbuf utbuf;
00576 utbuf.actime = dest_statbuf.st_atime;
00577 utbuf.modtime = dt.toTime_t();
00578 kdDebug() << k_funcinfo << "setting modtime to " << utbuf.modtime << endl;
00579 utime( _dest_orig.data(), &utbuf );
00580 }
00581 }
00582
00583 }
00584
00585
00586 finished();
00587 }
00588
00589
00590 void FileProtocol::copy( const KURL &src, const KURL &dest,
00591 int _mode, bool _overwrite )
00592 {
00593 kdDebug(7101) << "copy(): " << src << " -> " << dest << ", mode=" << _mode << endl;
00594
00595 QCString _src( QFile::encodeName(src.path()));
00596 QCString _dest( QFile::encodeName(dest.path()));
00597 KDE_struct_stat buff_src;
00598 #ifdef USE_POSIX_ACL
00599 acl_t acl;
00600 #endif
00601
00602 if ( KDE_stat( _src.data(), &buff_src ) == -1 ) {
00603 if ( errno == EACCES )
00604 error( KIO::ERR_ACCESS_DENIED, src.path() );
00605 else
00606 error( KIO::ERR_DOES_NOT_EXIST, src.path() );
00607 return;
00608 }
00609
00610 if ( S_ISDIR( buff_src.st_mode ) ) {
00611 error( KIO::ERR_IS_DIRECTORY, src.path() );
00612 return;
00613 }
00614 if ( S_ISFIFO( buff_src.st_mode ) || S_ISSOCK ( buff_src.st_mode ) ) {
00615 error( KIO::ERR_CANNOT_OPEN_FOR_READING, src.path() );
00616 return;
00617 }
00618
00619 KDE_struct_stat buff_dest;
00620 bool dest_exists = ( KDE_lstat( _dest.data(), &buff_dest ) != -1 );
00621 if ( dest_exists )
00622 {
00623 if (S_ISDIR(buff_dest.st_mode))
00624 {
00625 error( KIO::ERR_DIR_ALREADY_EXIST, dest.path() );
00626 return;
00627 }
00628
00629 if ( same_inode( buff_dest, buff_src) )
00630 {
00631 error( KIO::ERR_IDENTICAL_FILES, dest.path() );
00632 return;
00633 }
00634
00635 if (!_overwrite)
00636 {
00637 error( KIO::ERR_FILE_ALREADY_EXIST, dest.path() );
00638 return;
00639 }
00640
00641
00642
00643
00644 if (_overwrite && S_ISLNK(buff_dest.st_mode))
00645 {
00646 kdDebug(7101) << "copy(): LINK DESTINATION" << endl;
00647 remove( _dest.data() );
00648 }
00649 }
00650
00651 int src_fd = KDE_open( _src.data(), O_RDONLY);
00652 if ( src_fd < 0 ) {
00653 error( KIO::ERR_CANNOT_OPEN_FOR_READING, src.path() );
00654 return;
00655 }
00656
00657 #ifdef HAVE_FADVISE
00658 posix_fadvise(src_fd,0,0,POSIX_FADV_SEQUENTIAL);
00659 #endif
00660
00661
00662 mode_t initialMode;
00663 if (_mode != -1)
00664 initialMode = _mode | S_IWUSR;
00665 else
00666 initialMode = 0666;
00667
00668 int dest_fd = KDE_open(_dest.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode);
00669 if ( dest_fd < 0 ) {
00670 kdDebug(7101) << "###### COULD NOT WRITE " << dest.url() << endl;
00671 if ( errno == EACCES ) {
00672 error( KIO::ERR_WRITE_ACCESS_DENIED, dest.path() );
00673 } else {
00674 error( KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest.path() );
00675 }
00676 close(src_fd);
00677 return;
00678 }
00679
00680 #ifdef HAVE_FADVISE
00681 posix_fadvise(dest_fd,0,0,POSIX_FADV_SEQUENTIAL);
00682 #endif
00683
00684 #ifdef USE_POSIX_ACL
00685 acl = acl_get_fd(src_fd);
00686 if ( acl && !isExtendedACL( acl ) ) {
00687 kdDebug(7101) << _dest.data() << " doesn't have extended ACL" << endl;
00688 acl_free( acl );
00689 acl = NULL;
00690 }
00691 #endif
00692 totalSize( buff_src.st_size );
00693
00694 KIO::filesize_t processed_size = 0;
00695 char buffer[ MAX_IPC_SIZE ];
00696 int n;
00697 #ifdef USE_SENDFILE
00698 bool use_sendfile=buff_src.st_size < 0x7FFFFFFF;
00699 #endif
00700 while( 1 )
00701 {
00702 #ifdef USE_SENDFILE
00703 if (use_sendfile) {
00704 off_t sf = processed_size;
00705 n = ::sendfile( dest_fd, src_fd, &sf, MAX_IPC_SIZE );
00706 processed_size = sf;
00707 if ( n == -1 && errno == EINVAL ) {
00708 kdDebug(7101) << "sendfile() not supported, falling back " << endl;
00709 use_sendfile = false;
00710 }
00711 }
00712 if (!use_sendfile)
00713 #endif
00714 n = ::read( src_fd, buffer, MAX_IPC_SIZE );
00715
00716 if (n == -1)
00717 {
00718 if (errno == EINTR)
00719 continue;
00720 #ifdef USE_SENDFILE
00721 if ( use_sendfile ) {
00722 kdDebug(7101) << "sendfile() error:" << strerror(errno) << endl;
00723 if ( errno == ENOSPC )
00724 {
00725 error( KIO::ERR_DISK_FULL, dest.path());
00726 remove( _dest.data() );
00727 }
00728 else {
00729 error( KIO::ERR_SLAVE_DEFINED,
00730 i18n("Cannot copy file from %1 to %2. (Errno: %3)")
00731 .arg( src.path() ).arg( dest.path() ).arg( errno ) );
00732 }
00733 } else
00734 #endif
00735 error( KIO::ERR_COULD_NOT_READ, src.path());
00736 close(src_fd);
00737 close(dest_fd);
00738 #ifdef USE_POSIX_ACL
00739 if (acl) acl_free(acl);
00740 #endif
00741 return;
00742 }
00743 if (n == 0)
00744 break;
00745 #ifdef USE_SENDFILE
00746 if ( !use_sendfile ) {
00747 #endif
00748 if (write_all( dest_fd, buffer, n))
00749 {
00750 close(src_fd);
00751 close(dest_fd);
00752
00753 if ( errno == ENOSPC )
00754 {
00755 error( KIO::ERR_DISK_FULL, dest.path());
00756 remove( _dest.data() );
00757 }
00758 else
00759 {
00760 kdWarning(7101) << "Couldn't write[2]. Error:" << strerror(errno) << endl;
00761 error( KIO::ERR_COULD_NOT_WRITE, dest.path());
00762 }
00763 #ifdef USE_POSIX_ACL
00764 if (acl) acl_free(acl);
00765 #endif
00766 return;
00767 }
00768 processed_size += n;
00769 #ifdef USE_SENDFILE
00770 }
00771 #endif
00772 processedSize( processed_size );
00773 }
00774
00775 close( src_fd );
00776
00777 if (close( dest_fd))
00778 {
00779 kdWarning(7101) << "Error when closing file descriptor[2]:" << strerror(errno) << endl;
00780 error( KIO::ERR_COULD_NOT_WRITE, dest.path());
00781 #ifdef USE_POSIX_ACL
00782 if (acl) acl_free(acl);
00783 #endif
00784 return;
00785 }
00786
00787
00788 if ( _mode != -1 )
00789 {
00790 if ( (::chmod(_dest.data(), _mode) != 0)
00791 #ifdef USE_POSIX_ACL
00792 || (acl && acl_set_file(_dest.data(), ACL_TYPE_ACCESS, acl) != 0)
00793 #endif
00794 )
00795 {
00796
00797 if ( KIO::testFileSystemFlag( _dest, KIO::SupportsChmod ) )
00798 warning( i18n( "Could not change permissions for\n%1" ).arg( dest.path() ) );
00799 }
00800 }
00801 #ifdef USE_POSIX_ACL
00802 if (acl) acl_free(acl);
00803 #endif
00804
00805
00806 struct utimbuf ut;
00807 ut.actime = buff_src.st_atime;
00808 ut.modtime = buff_src.st_mtime;
00809 if ( ::utime( _dest.data(), &ut ) != 0 )
00810 {
00811 kdWarning() << QString::fromLatin1("Couldn't preserve access and modification time for\n%1").arg( dest.path() ) << endl;
00812 }
00813
00814 processedSize( buff_src.st_size );
00815 finished();
00816 }
00817
00818 void FileProtocol::rename( const KURL &src, const KURL &dest,
00819 bool _overwrite )
00820 {
00821 QCString _src( QFile::encodeName(src.path()));
00822 QCString _dest( QFile::encodeName(dest.path()));
00823 KDE_struct_stat buff_src;
00824 if ( KDE_lstat( _src.data(), &buff_src ) == -1 ) {
00825 if ( errno == EACCES )
00826 error( KIO::ERR_ACCESS_DENIED, src.path() );
00827 else
00828 error( KIO::ERR_DOES_NOT_EXIST, src.path() );
00829 return;
00830 }
00831
00832 KDE_struct_stat buff_dest;
00833 bool dest_exists = ( KDE_stat( _dest.data(), &buff_dest ) != -1 );
00834 if ( dest_exists )
00835 {
00836 if (S_ISDIR(buff_dest.st_mode))
00837 {
00838 error( KIO::ERR_DIR_ALREADY_EXIST, dest.path() );
00839 return;
00840 }
00841
00842 if ( same_inode( buff_dest, buff_src) )
00843 {
00844 error( KIO::ERR_IDENTICAL_FILES, dest.path() );
00845 return;
00846 }
00847
00848 if (!_overwrite)
00849 {
00850 error( KIO::ERR_FILE_ALREADY_EXIST, dest.path() );
00851 return;
00852 }
00853 }
00854
00855 if ( ::rename( _src.data(), _dest.data()))
00856 {
00857 if (( errno == EACCES ) || (errno == EPERM)) {
00858 error( KIO::ERR_ACCESS_DENIED, dest.path() );
00859 }
00860 else if (errno == EXDEV) {
00861 error( KIO::ERR_UNSUPPORTED_ACTION, QString::fromLatin1("rename"));
00862 }
00863 else if (errno == EROFS) {
00864 error( KIO::ERR_CANNOT_DELETE, src.path() );
00865 }
00866 else {
00867 error( KIO::ERR_CANNOT_RENAME, src.path() );
00868 }
00869 return;
00870 }
00871
00872 finished();
00873 }
00874
00875 void FileProtocol::symlink( const QString &target, const KURL &dest, bool overwrite )
00876 {
00877
00878 if ( ::symlink( QFile::encodeName( target ), QFile::encodeName( dest.path() ) ) == -1 )
00879 {
00880
00881 if ( errno == EEXIST )
00882 {
00883 if ( overwrite )
00884 {
00885
00886 if ( unlink( QFile::encodeName( dest.path() ) ) != 0 )
00887 {
00888 error( KIO::ERR_CANNOT_DELETE, dest.path() );
00889 return;
00890 }
00891
00892 symlink( target, dest, overwrite );
00893 }
00894 else
00895 {
00896 KDE_struct_stat buff_dest;
00897 KDE_lstat( QFile::encodeName( dest.path() ), &buff_dest );
00898 if (S_ISDIR(buff_dest.st_mode))
00899 error( KIO::ERR_DIR_ALREADY_EXIST, dest.path() );
00900 else
00901 error( KIO::ERR_FILE_ALREADY_EXIST, dest.path() );
00902 return;
00903 }
00904 }
00905 else
00906 {
00907
00908 error( KIO::ERR_CANNOT_SYMLINK, dest.path() );
00909 return;
00910 }
00911 }
00912 finished();
00913 }
00914
00915 void FileProtocol::del( const KURL& url, bool isfile)
00916 {
00917 QCString _path( QFile::encodeName(url.path()));
00918
00919
00920
00921
00922 if (isfile) {
00923 kdDebug( 7101 ) << "Deleting file "<< url.url() << endl;
00924
00925
00926
00927 if ( unlink( _path.data() ) == -1 ) {
00928 if ((errno == EACCES) || (errno == EPERM))
00929 error( KIO::ERR_ACCESS_DENIED, url.path());
00930 else if (errno == EISDIR)
00931 error( KIO::ERR_IS_DIRECTORY, url.path());
00932 else
00933 error( KIO::ERR_CANNOT_DELETE, url.path() );
00934 return;
00935 }
00936 } else {
00937
00938
00939
00940
00941
00942 kdDebug( 7101 ) << "Deleting directory " << url.url() << endl;
00943
00944 if ( ::rmdir( _path.data() ) == -1 ) {
00945 if ((errno == EACCES) || (errno == EPERM))
00946 error( KIO::ERR_ACCESS_DENIED, url.path());
00947 else {
00948 kdDebug( 7101 ) << "could not rmdir " << perror << endl;
00949 error( KIO::ERR_COULD_NOT_RMDIR, url.path() );
00950 return;
00951 }
00952 }
00953 }
00954
00955 finished();
00956 }
00957
00958
00959 QString FileProtocol::getUserName( uid_t uid )
00960 {
00961 QString *temp;
00962 temp = usercache.find( uid );
00963 if ( !temp ) {
00964 struct passwd *user = getpwuid( uid );
00965 if ( user ) {
00966 usercache.insert( uid, new QString(QString::fromLatin1(user->pw_name)) );
00967 return QString::fromLatin1( user->pw_name );
00968 }
00969 else
00970 return QString::number( uid );
00971 }
00972 else
00973 return *temp;
00974 }
00975
00976 QString FileProtocol::getGroupName( gid_t gid )
00977 {
00978 QString *temp;
00979 temp = groupcache.find( gid );
00980 if ( !temp ) {
00981 struct group *grp = getgrgid( gid );
00982 if ( grp ) {
00983 groupcache.insert( gid, new QString(QString::fromLatin1(grp->gr_name)) );
00984 return QString::fromLatin1( grp->gr_name );
00985 }
00986 else
00987 return QString::number( gid );
00988 }
00989 else
00990 return *temp;
00991 }
00992
00993
00994
00995 bool FileProtocol::createUDSEntry( const QString & filename, const QCString & path, UDSEntry & entry,
00996 short int details, bool withACL )
00997 {
00998 assert(entry.count() == 0);
00999
01000
01001
01002 UDSAtom atom;
01003 atom.m_uds = KIO::UDS_NAME;
01004 atom.m_str = filename;
01005 entry.append( atom );
01006
01007 mode_t type;
01008 mode_t access;
01009 KDE_struct_stat buff;
01010
01011 if ( KDE_lstat( path.data(), &buff ) == 0 ) {
01012
01013 if (S_ISLNK(buff.st_mode)) {
01014
01015 char buffer2[ 1000 ];
01016 int n = readlink( path.data(), buffer2, 1000 );
01017 if ( n != -1 ) {
01018 buffer2[ n ] = 0;
01019 }
01020
01021 atom.m_uds = KIO::UDS_LINK_DEST;
01022 atom.m_str = QFile::decodeName( buffer2 );
01023 entry.append( atom );
01024
01025
01026 if ( details > 1 && KDE_stat( path.data(), &buff ) == -1 ) {
01027
01028 type = S_IFMT - 1;
01029 access = S_IRWXU | S_IRWXG | S_IRWXO;
01030
01031 atom.m_uds = KIO::UDS_FILE_TYPE;
01032 atom.m_long = type;
01033 entry.append( atom );
01034
01035 atom.m_uds = KIO::UDS_ACCESS;
01036 atom.m_long = access;
01037 entry.append( atom );
01038
01039 atom.m_uds = KIO::UDS_SIZE;
01040 atom.m_long = 0L;
01041 entry.append( atom );
01042
01043 goto notype;
01044
01045 }
01046 }
01047 } else {
01048
01049 return false;
01050 }
01051
01052 type = buff.st_mode & S_IFMT;
01053 access = buff.st_mode & 07777;
01054
01055 atom.m_uds = KIO::UDS_FILE_TYPE;
01056 atom.m_long = type;
01057 entry.append( atom );
01058
01059 atom.m_uds = KIO::UDS_ACCESS;
01060 atom.m_long = access;
01061 entry.append( atom );
01062
01063 atom.m_uds = KIO::UDS_SIZE;
01064 atom.m_long = buff.st_size;
01065 entry.append( atom );
01066
01067 #ifdef USE_POSIX_ACL
01068
01069
01070
01071 appendACLAtoms( path, entry, type, withACL );
01072 #endif
01073
01074 notype:
01075 atom.m_uds = KIO::UDS_MODIFICATION_TIME;
01076 atom.m_long = buff.st_mtime;
01077 entry.append( atom );
01078
01079 atom.m_uds = KIO::UDS_USER;
01080 atom.m_str = getUserName( buff.st_uid );
01081 entry.append( atom );
01082
01083 atom.m_uds = KIO::UDS_GROUP;
01084 atom.m_str = getGroupName( buff.st_gid );
01085 entry.append( atom );
01086
01087 atom.m_uds = KIO::UDS_ACCESS_TIME;
01088 atom.m_long = buff.st_atime;
01089 entry.append( atom );
01090
01091
01092
01093
01094
01095 return true;
01096 }
01097
01098 void FileProtocol::stat( const KURL & url )
01099 {
01100 if (!url.isLocalFile()) {
01101 KURL redir(url);
01102 redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb"));
01103 redirection(redir);
01104 kdDebug(7101) << "redirecting to " << redir.url() << endl;
01105 finished();
01106 return;
01107 }
01108
01109
01110
01111
01112
01113
01114
01115
01116 QCString _path( QFile::encodeName(url.path(-1)));
01117
01118 QString sDetails = metaData(QString::fromLatin1("details"));
01119 int details = sDetails.isEmpty() ? 2 : sDetails.toInt();
01120 kdDebug(7101) << "FileProtocol::stat details=" << details << endl;
01121
01122 UDSEntry entry;
01123 if ( !createUDSEntry( url.fileName(), _path, entry, details, true ) )
01124 {
01125 error( KIO::ERR_DOES_NOT_EXIST, url.path(-1) );
01126 return;
01127 }
01128 #if 0
01130 KIO::UDSEntry::ConstIterator it = entry.begin();
01131 for( ; it != entry.end(); it++ ) {
01132 switch ((*it).m_uds) {
01133 case KIO::UDS_FILE_TYPE:
01134 kdDebug(7101) << "File Type : " << (mode_t)((*it).m_long) << endl;
01135 break;
01136 case KIO::UDS_ACCESS:
01137 kdDebug(7101) << "Access permissions : " << (mode_t)((*it).m_long) << endl;
01138 break;
01139 case KIO::UDS_USER:
01140 kdDebug(7101) << "User : " << ((*it).m_str.ascii() ) << endl;
01141 break;
01142 case KIO::UDS_GROUP:
01143 kdDebug(7101) << "Group : " << ((*it).m_str.ascii() ) << endl;
01144 break;
01145 case KIO::UDS_NAME:
01146 kdDebug(7101) << "Name : " << ((*it).m_str.ascii() ) << endl;
01147
01148 break;
01149 case KIO::UDS_URL:
01150 kdDebug(7101) << "URL : " << ((*it).m_str.ascii() ) << endl;
01151 break;
01152 case KIO::UDS_MIME_TYPE:
01153 kdDebug(7101) << "MimeType : " << ((*it).m_str.ascii() ) << endl;
01154 break;
01155 case KIO::UDS_LINK_DEST:
01156 kdDebug(7101) << "LinkDest : " << ((*it).m_str.ascii() ) << endl;
01157 break;
01158 case KIO::UDS_EXTENDED_ACL:
01159 kdDebug(7101) << "Contains extended ACL " << endl;
01160 break;
01161 }
01162 }
01163 MetaData::iterator it1 = mOutgoingMetaData.begin();
01164 for ( ; it1 != mOutgoingMetaData.end(); it1++ ) {
01165 kdDebug(7101) << it1.key() << " = " << it1.data() << endl;
01166 }
01168 #endif
01169 statEntry( entry );
01170
01171 finished();
01172 }
01173
01174 void FileProtocol::listDir( const KURL& url)
01175 {
01176 kdDebug(7101) << "========= LIST " << url.url() << " =========" << endl;
01177 if (!url.isLocalFile()) {
01178 KURL redir(url);
01179 redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb"));
01180 redirection(redir);
01181 kdDebug(7101) << "redirecting to " << redir.url() << endl;
01182 finished();
01183 return;
01184 }
01185
01186 QCString _path( QFile::encodeName(url.path()));
01187
01188 KDE_struct_stat buff;
01189 if ( KDE_stat( _path.data(), &buff ) == -1 ) {
01190 error( KIO::ERR_DOES_NOT_EXIST, url.path() );
01191 return;
01192 }
01193
01194 if ( !S_ISDIR( buff.st_mode ) ) {
01195 error( KIO::ERR_IS_FILE, url.path() );
01196 return;
01197 }
01198
01199 DIR *dp = 0L;
01200 KDE_struct_dirent *ep;
01201
01202 dp = opendir( _path.data() );
01203 if ( dp == 0 ) {
01204 switch (errno)
01205 {
01206 #ifdef ENOMEDIUM
01207 case ENOMEDIUM:
01208 error( ERR_SLAVE_DEFINED,
01209 i18n( "No media in device for %1" ).arg( url.path() ) );
01210 break;
01211 #endif
01212 default:
01213 error( KIO::ERR_CANNOT_ENTER_DIRECTORY, url.path() );
01214 break;
01215 }
01216 return;
01217 }
01218
01219
01220
01221
01222 QStrList entryNames;
01223
01224 while ( ( ep = KDE_readdir( dp ) ) != 0L )
01225 entryNames.append( ep->d_name );
01226
01227 closedir( dp );
01228 totalSize( entryNames.count() );
01229
01230
01231
01232
01233
01234
01235
01236
01237 char path_buffer[PATH_MAX];
01238 (void) getcwd(path_buffer, PATH_MAX - 1);
01239 if ( chdir( _path.data() ) ) {
01240 if (errno == EACCES)
01241 error(ERR_ACCESS_DENIED, _path);
01242 else
01243 error(ERR_CANNOT_ENTER_DIRECTORY, _path);
01244 finished();
01245 }
01246
01247 UDSEntry entry;
01248 QStrListIterator it(entryNames);
01249 for (; it.current(); ++it) {
01250 entry.clear();
01251 if ( createUDSEntry( QFile::decodeName(*it),
01252 *it ,
01253 entry, 2, true ) )
01254 listEntry( entry, false);
01255
01256
01257 }
01258
01259 listEntry( entry, true );
01260
01261 kdDebug(7101) << "============= COMPLETED LIST ============" << endl;
01262
01263 chdir(path_buffer);
01264
01265 finished();
01266 }
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287 void FileProtocol::special( const QByteArray &data)
01288 {
01289 int tmp;
01290 QDataStream stream(data, IO_ReadOnly);
01291
01292 stream >> tmp;
01293 switch (tmp) {
01294 case 1:
01295 {
01296 QString fstype, dev, point;
01297 Q_INT8 iRo;
01298
01299 stream >> iRo >> fstype >> dev >> point;
01300
01301 bool ro = ( iRo != 0 );
01302
01303 kdDebug(7101) << "MOUNTING fstype=" << fstype << " dev=" << dev << " point=" << point << " ro=" << ro << endl;
01304 bool ok = pmount( dev );
01305 if (ok)
01306 finished();
01307 else
01308 mount( ro, fstype.ascii(), dev, point );
01309
01310 }
01311 break;
01312 case 2:
01313 {
01314 QString point;
01315 stream >> point;
01316 bool ok = pumount( point );
01317 if (ok)
01318 finished();
01319 else
01320 unmount( point );
01321 }
01322 break;
01323
01324 case 3:
01325 {
01326 QString filename;
01327 stream >> filename;
01328 KShred shred( filename );
01329 connect( &shred, SIGNAL( processedSize( KIO::filesize_t ) ),
01330 this, SLOT( slotProcessedSize( KIO::filesize_t ) ) );
01331 connect( &shred, SIGNAL( infoMessage( const QString & ) ),
01332 this, SLOT( slotInfoMessage( const QString & ) ) );
01333 if (!shred.shred())
01334 error( KIO::ERR_CANNOT_DELETE, filename );
01335 else
01336 finished();
01337 break;
01338 }
01339 default:
01340 break;
01341 }
01342 }
01343
01344
01345 void FileProtocol::slotProcessedSize( KIO::filesize_t bytes )
01346 {
01347 kdDebug(7101) << "FileProtocol::slotProcessedSize (" << (unsigned int) bytes << ")" << endl;
01348 processedSize( bytes );
01349 }
01350
01351
01352 void FileProtocol::slotInfoMessage( const QString & msg )
01353 {
01354 kdDebug(7101) << "FileProtocol::slotInfoMessage (" << msg << ")" << endl;
01355 infoMessage( msg );
01356 }
01357
01358 void FileProtocol::mount( bool _ro, const char *_fstype, const QString& _dev, const QString& _point )
01359 {
01360 kdDebug(7101) << "FileProtocol::mount _fstype=" << _fstype << endl;
01361 QCString buffer;
01362
01363 #ifdef HAVE_VOLMGT
01364
01365
01366
01367 QString err;
01368 QCString devname = QFile::encodeName( _dev );
01369
01370 if( volmgt_running() ) {
01371
01372 if( volmgt_check( devname.data() ) == 0 ) {
01373 kdDebug(7101) << "VOLMGT: no media in "
01374 << devname.data() << endl;
01375 err = i18n("No Media inserted or Media not recognized.");
01376 error( KIO::ERR_COULD_NOT_MOUNT, err );
01377 return;
01378 } else {
01379 kdDebug(7101) << "VOLMGT: " << devname.data()
01380 << ": media ok" << endl;
01381 finished();
01382 return;
01383 }
01384 } else {
01385 err = i18n("\"vold\" is not running.");
01386 kdDebug(7101) << "VOLMGT: " << err << endl;
01387 error( KIO::ERR_COULD_NOT_MOUNT, err );
01388 return;
01389 }
01390 #else
01391
01392
01393 KTempFile tmpFile;
01394 QCString tmpFileC = QFile::encodeName(tmpFile.name());
01395 const char *tmp = tmpFileC.data();
01396 QCString dev;
01397 if ( _dev.startsWith( "LABEL=" ) ) {
01398 QString labelName = _dev.mid( 6 );
01399 dev = "-L ";
01400 dev += QFile::encodeName( KProcess::quote( labelName ) );
01401 } else if ( _dev.startsWith( "UUID=" ) ) {
01402 QString uuidName = _dev.mid( 5 );
01403 dev = "-U ";
01404 dev += QFile::encodeName( KProcess::quote( uuidName ) );
01405 }
01406 else
01407 dev = QFile::encodeName( KProcess::quote(_dev) );
01408
01409 QCString point = QFile::encodeName( KProcess::quote(_point) );
01410 bool fstype_empty = !_fstype || !*_fstype;
01411 QCString fstype = KProcess::quote(_fstype).latin1();
01412 QCString readonly = _ro ? "-r" : "";
01413 QString epath = QString::fromLatin1(getenv("PATH"));
01414 QString path = QString::fromLatin1("/sbin:/bin");
01415 if(!epath.isEmpty())
01416 path += QString::fromLatin1(":") + epath;
01417 QString mountProg = KGlobal::dirs()->findExe("mount", path);
01418 if (mountProg.isEmpty()){
01419 error( KIO::ERR_COULD_NOT_MOUNT, i18n("Could not find program \"mount\""));
01420 return;
01421 }
01422
01423
01424 for ( int step = 0 ; step <= 1 ; step++ )
01425 {
01426
01427 if ( !_dev.isEmpty() && _point.isEmpty() && fstype_empty )
01428 buffer.sprintf( "%s %s 2>%s", mountProg.latin1(), dev.data(), tmp );
01429 else
01430
01431 if ( !_point.isEmpty() && _dev.isEmpty() && fstype_empty )
01432 buffer.sprintf( "%s %s 2>%s", mountProg.latin1(), point.data(), tmp );
01433 else
01434
01435 if ( !_point.isEmpty() && !_dev.isEmpty() && fstype_empty )
01436 buffer.sprintf( "%s %s %s %s 2>%s", mountProg.latin1(), readonly.data(), dev.data(), point.data(), tmp );
01437 else
01438
01439 #if defined(__svr4__) && defined(__sun__) // MARCO for Solaris 8 and I
01440
01441 buffer.sprintf( "%s -F %s %s %s %s 2>%s"
01442 mountProg.latin1()
01443 fstype.data()
01444 _ro ? "-oro" : ""
01445 dev.data()
01446 point.data()
01447 tmp );
01448 #else
01449 buffer.sprintf( "%s %s -t %s %s %s 2>%s", mountProg.latin1(), readonly.data(),
01450 fstype.data(), dev.data(), point.data(), tmp );
01451 #endif
01452
01453 kdDebug(7101) << buffer << endl;
01454
01455 int mount_ret = system( buffer.data() );
01456
01457 QString err = testLogFile( tmp );
01458 if ( err.isEmpty() && mount_ret == 0)
01459 {
01460 finished();
01461 return;
01462 }
01463 else
01464 {
01465
01466 QString mp = KIO::findDeviceMountPoint( _dev );
01467
01468 if ( !mp.isEmpty() && mount_ret == 0)
01469 {
01470 kdDebug(7101) << "mount got a warning: " << err << endl;
01471 warning( err );
01472 finished();
01473 return;
01474 }
01475 else
01476 {
01477 if ( (step == 0) && !_point.isEmpty())
01478 {
01479 kdDebug(7101) << err << endl;
01480 kdDebug(7101) << "Mounting with those options didn't work, trying with only mountpoint" << endl;
01481 fstype = "";
01482 fstype_empty = true;
01483 dev = "";
01484
01485
01486
01487
01488
01489
01490
01491
01492 }
01493 else
01494 {
01495 error( KIO::ERR_COULD_NOT_MOUNT, err );
01496 return;
01497 }
01498 }
01499 }
01500 }
01501 #endif
01502 }
01503
01504
01505 void FileProtocol::unmount( const QString& _point )
01506 {
01507 QCString buffer;
01508
01509 KTempFile tmpFile;
01510 QCString tmpFileC = QFile::encodeName(tmpFile.name());
01511 QString err;
01512 const char *tmp = tmpFileC.data();
01513
01514 #ifdef HAVE_VOLMGT
01515
01516
01517
01518 char *devname;
01519 char *ptr;
01520 FILE *mnttab;
01521 struct mnttab mnt;
01522
01523 if( volmgt_running() ) {
01524 kdDebug(7101) << "VOLMGT: looking for "
01525 << _point.local8Bit() << endl;
01526
01527 if( (mnttab = KDE_fopen( MNTTAB, "r" )) == NULL ) {
01528 err = "couldn't open mnttab";
01529 kdDebug(7101) << "VOLMGT: " << err << endl;
01530 error( KIO::ERR_COULD_NOT_UNMOUNT, err );
01531 return;
01532 }
01533
01534
01535
01536
01537
01538
01539
01540 devname = NULL;
01541 rewind( mnttab );
01542 while( getmntent( mnttab, &mnt ) == 0 ) {
01543 if( strcmp( _point.local8Bit(), mnt.mnt_mountp ) == 0 ){
01544 devname = mnt.mnt_special;
01545 break;
01546 }
01547 }
01548 fclose( mnttab );
01549
01550 if( devname == NULL ) {
01551 err = "not in mnttab";
01552 kdDebug(7101) << "VOLMGT: "
01553 << QFile::encodeName(_point).data()
01554 << ": " << err << endl;
01555 error( KIO::ERR_COULD_NOT_UNMOUNT, err );
01556 return;
01557 }
01558
01559
01560
01561
01562
01563
01564 ptr = strrchr( devname, '/' );
01565 *ptr = '\0';
01566 QCString qdevname(QFile::encodeName(KProcess::quote(QFile::decodeName(QCString(devname)))).data());
01567 buffer.sprintf( "/usr/bin/eject %s 2>%s", qdevname.data(), tmp );
01568 kdDebug(7101) << "VOLMGT: eject " << qdevname << endl;
01569
01570
01571
01572
01573
01574
01575 if( WEXITSTATUS( system( buffer.data() )) == 4 ) {
01576
01577
01578
01579
01580 unlink( tmp );
01581 finished();
01582 return;
01583 }
01584 } else {
01585
01586
01587
01588
01589
01590
01591 err = i18n("\"vold\" is not running.");
01592 kdDebug(7101) << "VOLMGT: " << err << endl;
01593 error( KIO::ERR_COULD_NOT_UNMOUNT, err );
01594 return;
01595 }
01596 #else
01597 QString epath = getenv("PATH");
01598 QString path = QString::fromLatin1("/sbin:/bin");
01599 if (!epath.isEmpty())
01600 path += ":" + epath;
01601 QString umountProg = KGlobal::dirs()->findExe("umount", path);
01602
01603 if (umountProg.isEmpty()) {
01604 error( KIO::ERR_COULD_NOT_UNMOUNT, i18n("Could not find program \"umount\""));
01605 return;
01606 }
01607 buffer.sprintf( "%s %s 2>%s", umountProg.latin1(), QFile::encodeName(KProcess::quote(_point)).data(), tmp );
01608 system( buffer.data() );
01609 #endif
01610
01611 err = testLogFile( tmp );
01612 if ( err.isEmpty() )
01613 finished();
01614 else
01615 error( KIO::ERR_COULD_NOT_UNMOUNT, err );
01616 }
01617
01618
01619
01620
01621
01622
01623
01624 bool FileProtocol::pmount(const QString &dev)
01625 {
01626 QString epath = getenv("PATH");
01627 QString path = QString::fromLatin1("/sbin:/bin");
01628 if (!epath.isEmpty())
01629 path += ":" + epath;
01630 QString pmountProg = KGlobal::dirs()->findExe("pmount", path);
01631
01632 if (pmountProg.isEmpty())
01633 return false;
01634
01635 QCString buffer;
01636 buffer.sprintf( "%s %s", QFile::encodeName(pmountProg).data(),
01637 QFile::encodeName(KProcess::quote(dev)).data() );
01638
01639 int res = system( buffer.data() );
01640
01641 return res==0;
01642 }
01643
01644 bool FileProtocol::pumount(const QString &point)
01645 {
01646 QString real_point = KStandardDirs::realPath(point);
01647
01648 KMountPoint::List mtab = KMountPoint::currentMountPoints();
01649
01650 KMountPoint::List::const_iterator it = mtab.begin();
01651 KMountPoint::List::const_iterator end = mtab.end();
01652
01653 QString dev;
01654
01655 for (; it!=end; ++it)
01656 {
01657 QString tmp = (*it)->mountedFrom();
01658 QString mp = (*it)->mountPoint();
01659 mp = KStandardDirs::realPath(mp);
01660
01661 if (mp==real_point)
01662 dev = KStandardDirs::realPath(tmp);
01663 }
01664
01665 if (dev.isEmpty()) return false;
01666 if (dev.endsWith("/")) dev.truncate(dev.length()-1);
01667
01668 QString epath = getenv("PATH");
01669 QString path = QString::fromLatin1("/sbin:/bin");
01670 if (!epath.isEmpty())
01671 path += ":" + epath;
01672 QString pumountProg = KGlobal::dirs()->findExe("pumount", path);
01673
01674 if (pumountProg.isEmpty())
01675 return false;
01676
01677 QCString buffer;
01678 buffer.sprintf( "%s %s", QFile::encodeName(pumountProg).data(),
01679 QFile::encodeName(KProcess::quote(dev)).data() );
01680
01681 int res = system( buffer.data() );
01682
01683 return res==0;
01684 }
01685
01686
01687
01688
01689
01690
01691
01692 static QString testLogFile( const char *_filename )
01693 {
01694 char buffer[ 1024 ];
01695 KDE_struct_stat buff;
01696
01697 QString result;
01698
01699 KDE_stat( _filename, &buff );
01700 int size = buff.st_size;
01701 if ( size == 0 ) {
01702 unlink( _filename );
01703 return result;
01704 }
01705
01706 FILE * f = KDE_fopen( _filename, "rb" );
01707 if ( f == 0L ) {
01708 unlink( _filename );
01709 result = i18n("Could not read %1").arg(QFile::decodeName(_filename));
01710 return result;
01711 }
01712
01713 result = "";
01714 const char *p = "";
01715 while ( p != 0L ) {
01716 p = fgets( buffer, sizeof(buffer)-1, f );
01717 if ( p != 0L )
01718 result += QString::fromLocal8Bit(buffer);
01719 }
01720
01721 fclose( f );
01722
01723 unlink( _filename );
01724
01725 return result;
01726 }
01727
01728
01729
01730
01731
01732
01733 #ifdef USE_POSIX_ACL
01734
01735 static bool isExtendedACL( acl_t acl )
01736 {
01737 return ( acl_equiv_mode( acl, 0 ) != 0 );
01738 }
01739
01740 static QString aclAsString( acl_t acl )
01741 {
01742 char *aclString = acl_to_text( acl, 0 );
01743 QString ret = QString::fromLatin1( aclString );
01744 acl_free( (void*)aclString );
01745 return ret;
01746 }
01747
01748 static void appendACLAtoms( const QCString & path, UDSEntry& entry, mode_t type, bool withACL )
01749 {
01750
01751 #ifdef HAVE_NON_POSIX_ACL_EXTENSIONS
01752 if ( acl_extended_file( path.data() ) == 0 ) return;
01753 #endif
01754
01755 acl_t acl = 0;
01756 acl_t defaultAcl = 0;
01757 UDSAtom atom;
01758 bool isDir = S_ISDIR( type );
01759
01760 if ( ( acl = acl_get_file( path.data(), ACL_TYPE_ACCESS ) ) ) {
01761 if ( !isExtendedACL( acl ) ) {
01762 acl_free( acl );
01763 acl = 0;
01764 }
01765 }
01766
01767
01768
01769 if ( isDir )
01770 defaultAcl = acl_get_file( path.data(), ACL_TYPE_DEFAULT );
01771
01772 if ( acl || defaultAcl ) {
01773 kdDebug(7101) << path.data() << " has extended ACL entries " << endl;
01774 atom.m_uds = KIO::UDS_EXTENDED_ACL;
01775 atom.m_long = 1;
01776 entry.append( atom );
01777 }
01778 if ( withACL ) {
01779 if ( acl ) {
01780 atom.m_uds = KIO::UDS_ACL_STRING;
01781 atom.m_str = aclAsString( acl );
01782 entry.append( atom );
01783 kdDebug(7101) << path.data() << "ACL: " << atom.m_str << endl;
01784 }
01785 if ( defaultAcl ) {
01786 atom.m_uds = KIO::UDS_DEFAULT_ACL_STRING;
01787 atom.m_str = aclAsString( defaultAcl );
01788 entry.append( atom );
01789 kdDebug(7101) << path.data() << "DEFAULT ACL: " << atom.m_str << endl;
01790 }
01791 }
01792 if ( acl ) acl_free( acl );
01793 if ( defaultAcl ) acl_free( defaultAcl );
01794 }
01795 #endif
01796
01797 #include "file.moc"