• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KIOSlave

  • kioslave
  • file
file.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2000-2002 Stephan Kulow <coolo@kde.org>
3 Copyright (C) 2000-2002 David Faure <faure@kde.org>
4 Copyright (C) 2000-2002 Waldo Bastian <bastian@kde.org>
5 Copyright (C) 2006 Allan Sandfeld Jensen <sandfeld@kde.org>
6 Copyright (C) 2007 Thiago Macieira <thiago@kde.org>
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License (LGPL) as published by the Free Software Foundation;
11 either version 2 of the License, or (at your option) any later
12 version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
18
19 You should have received a copy of the GNU Library General Public License
20 along with this library; see the file COPYING.LIB. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA.
23*/
24
25#define QT_NO_CAST_FROM_ASCII
26
27#include "file.h"
28#include <QDirIterator>
29
30#include <config.h>
31#include <config-kioslave-file.h>
32
33
34#include <sys/types.h>
35#include <sys/wait.h>
36#include <sys/stat.h>
37#include <sys/socket.h>
38#ifdef HAVE_SYS_TIME_H
39#include <sys/time.h>
40#endif
41
42#include <assert.h>
43#include <dirent.h>
44#include <errno.h>
45#include <fcntl.h>
46#include <grp.h>
47#include <pwd.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <signal.h>
51#include <time.h>
52#include <utime.h>
53#include <unistd.h>
54#ifdef HAVE_STRING_H
55#include <string.h>
56#endif
57
58#include <QtCore/QByteRef>
59#include <QtCore/QDate>
60#include <QtCore/QVarLengthArray>
61#include <QtCore/QCoreApplication>
62#include <QtCore/QRegExp>
63#include <QtCore/QFile>
64#ifdef Q_WS_WIN
65#include <QtCore/QDir>
66#include <QtCore/QFileInfo>
67#endif
68
69#include <kdebug.h>
70#include <kurl.h>
71#include <kcomponentdata.h>
72#include <kconfig.h>
73#include <kconfiggroup.h>
74#include <ktemporaryfile.h>
75#include <klocale.h>
76#include <limits.h>
77#include <kshell.h>
78#include <kmountpoint.h>
79#include <kstandarddirs.h>
80
81#ifdef HAVE_VOLMGT
82#include <volmgt.h>
83#include <sys/mnttab.h>
84#endif
85
86#include <kdirnotify.h>
87#include <kio/ioslave_defaults.h>
88#include <kde_file.h>
89#include <kglobal.h>
90#include <kmimetype.h>
91
92using namespace KIO;
93
94#define MAX_IPC_SIZE (1024*32)
95
96static QString readLogFile( const QByteArray&_filename );
97#ifdef HAVE_POSIX_ACL
98static void appendACLAtoms( const QByteArray & path, UDSEntry& entry,
99 mode_t type, bool withACL );
100#endif
101
102extern "C" int KDE_EXPORT kdemain( int argc, char **argv )
103{
104 QCoreApplication app( argc, argv ); // needed for QSocketNotifier
105 KComponentData componentData( "kio_file", "kdelibs4" );
106 ( void ) KGlobal::locale();
107
108 kDebug(7101) << "Starting" << getpid();
109
110 if (argc != 4)
111 {
112 fprintf(stderr, "Usage: kio_file protocol domain-socket1 domain-socket2\n");
113 exit(-1);
114 }
115
116 FileProtocol slave(argv[2], argv[3]);
117 slave.dispatchLoop();
118
119 kDebug(7101) << "Done";
120 return 0;
121}
122
123FileProtocol::FileProtocol( const QByteArray &pool, const QByteArray &app )
124 : SlaveBase( "file", pool, app ), openFd(-1)
125{
126}
127
128FileProtocol::~FileProtocol()
129{
130}
131
132#ifdef HAVE_POSIX_ACL
133static QString aclToText(acl_t acl) {
134 ssize_t size = 0;
135 char* txt = acl_to_text(acl, &size);
136 const QString ret = QString::fromLatin1(txt, size);
137 acl_free(txt);
138 return ret;
139}
140#endif
141
142int FileProtocol::setACL( const char *path, mode_t perm, bool directoryDefault )
143{
144 int ret = 0;
145#ifdef HAVE_POSIX_ACL
146
147 const QString ACLString = metaData(QLatin1String("ACL_STRING"));
148 const QString defaultACLString = metaData(QLatin1String("DEFAULT_ACL_STRING"));
149 // Empty strings mean leave as is
150 if ( !ACLString.isEmpty() ) {
151 acl_t acl = 0;
152 if (ACLString == QLatin1String("ACL_DELETE")) {
153 // user told us to delete the extended ACL, so let's write only
154 // the minimal (UNIX permission bits) part
155 acl = acl_from_mode( perm );
156 }
157 acl = acl_from_text( ACLString.toLatin1() );
158 if ( acl_valid( acl ) == 0 ) { // let's be safe
159 ret = acl_set_file( path, ACL_TYPE_ACCESS, acl );
160 kDebug(7101) << "Set ACL on:" << path << "to:" << aclToText(acl);
161 }
162 acl_free( acl );
163 if ( ret != 0 ) return ret; // better stop trying right away
164 }
165
166 if ( directoryDefault && !defaultACLString.isEmpty() ) {
167 if ( defaultACLString == QLatin1String("ACL_DELETE") ) {
168 // user told us to delete the default ACL, do so
169 ret += acl_delete_def_file( path );
170 } else {
171 acl_t acl = acl_from_text( defaultACLString.toLatin1() );
172 if ( acl_valid( acl ) == 0 ) { // let's be safe
173 ret += acl_set_file( path, ACL_TYPE_DEFAULT, acl );
174 kDebug(7101) << "Set Default ACL on:" << path << "to:" << aclToText(acl);
175 }
176 acl_free( acl );
177 }
178 }
179#else
180 Q_UNUSED(path);
181 Q_UNUSED(perm);
182 Q_UNUSED(directoryDefault);
183#endif
184 return ret;
185}
186
187void FileProtocol::chmod( const KUrl& url, int permissions )
188{
189 const QString path(url.toLocalFile());
190 const QByteArray _path( QFile::encodeName(path) );
191 /* FIXME: Should be atomic */
192 if ( KDE::chmod( path, permissions ) == -1 ||
193 ( setACL( _path.data(), permissions, false ) == -1 ) ||
194 /* if not a directory, cannot set default ACLs */
195 ( setACL( _path.data(), permissions, true ) == -1 && errno != ENOTDIR ) ) {
196
197 switch (errno) {
198 case EPERM:
199 case EACCES:
200 error(KIO::ERR_ACCESS_DENIED, path);
201 break;
202#if defined(ENOTSUP)
203 case ENOTSUP: // from setACL since chmod can't return ENOTSUP
204 error(KIO::ERR_UNSUPPORTED_ACTION, i18n("Setting ACL for %1", path));
205 break;
206#endif
207 case ENOSPC:
208 error(KIO::ERR_DISK_FULL, path);
209 break;
210 default:
211 error(KIO::ERR_CANNOT_CHMOD, path);
212 }
213 } else
214 finished();
215}
216
217void FileProtocol::setModificationTime( const KUrl& url, const QDateTime& mtime )
218{
219 const QString path(url.toLocalFile());
220 KDE_struct_stat statbuf;
221 if (KDE::lstat(path, &statbuf) == 0) {
222 struct utimbuf utbuf;
223 utbuf.actime = statbuf.st_atime; // access time, unchanged
224 utbuf.modtime = mtime.toTime_t(); // modification time
225 if (KDE::utime(path, &utbuf) != 0) {
226 // TODO: errno could be EACCES, EPERM, EROFS
227 error(KIO::ERR_CANNOT_SETTIME, path);
228 } else {
229 finished();
230 }
231 } else {
232 error(KIO::ERR_DOES_NOT_EXIST, path);
233 }
234}
235
236void FileProtocol::mkdir( const KUrl& url, int permissions )
237{
238 const QString path(url.toLocalFile());
239
240 kDebug(7101) << path << "permission=" << permissions;
241
242 // Remove existing file or symlink, if requested (#151851)
243 if (metaData(QLatin1String("overwrite")) == QLatin1String("true"))
244 QFile::remove(path);
245
246 KDE_struct_stat buff;
247 if ( KDE::lstat( path, &buff ) == -1 ) {
248 if ( KDE::mkdir( path, 0777 /*umask will be applied*/ ) != 0 ) {
249 if ( errno == EACCES ) {
250 error(KIO::ERR_ACCESS_DENIED, path);
251 return;
252 } else if ( errno == ENOSPC ) {
253 error(KIO::ERR_DISK_FULL, path);
254 return;
255 } else {
256 error(KIO::ERR_COULD_NOT_MKDIR, path);
257 return;
258 }
259 } else {
260 if ( permissions != -1 )
261 chmod( url, permissions );
262 else
263 finished();
264 return;
265 }
266 }
267
268 if ( S_ISDIR( buff.st_mode ) ) {
269 kDebug(7101) << "ERR_DIR_ALREADY_EXIST";
270 error(KIO::ERR_DIR_ALREADY_EXIST, path);
271 return;
272 }
273 error(KIO::ERR_FILE_ALREADY_EXIST, path);
274 return;
275}
276
277void FileProtocol::get( const KUrl& url )
278{
279 if (!url.isLocalFile()) {
280 KUrl redir(url);
281 redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb"));
282 redirection(redir);
283 finished();
284 return;
285 }
286
287 const QString path(url.toLocalFile());
288 KDE_struct_stat buff;
289 if ( KDE::stat( path, &buff ) == -1 ) {
290 if ( errno == EACCES )
291 error(KIO::ERR_ACCESS_DENIED, path);
292 else
293 error(KIO::ERR_DOES_NOT_EXIST, path);
294 return;
295 }
296
297 if ( S_ISDIR( buff.st_mode ) ) {
298 error(KIO::ERR_IS_DIRECTORY, path);
299 return;
300 }
301 if ( !S_ISREG( buff.st_mode ) ) {
302 error(KIO::ERR_CANNOT_OPEN_FOR_READING, path);
303 return;
304 }
305
306 int fd = KDE::open( path, O_RDONLY);
307 if ( fd < 0 ) {
308 error(KIO::ERR_CANNOT_OPEN_FOR_READING, path);
309 return;
310 }
311
312#if HAVE_FADVISE
313 posix_fadvise( fd, 0, 0, POSIX_FADV_SEQUENTIAL);
314#endif
315
316 // Determine the mimetype of the file to be retrieved, and emit it.
317 // This is mandatory in all slaves (for KRun/BrowserRun to work)
318 // In real "remote" slaves, this is usually done using findByNameAndContent
319 // after receiving some data. But we don't know how much data the mimemagic rules
320 // need, so for local files, better use findByUrl with localUrl=true.
321 KMimeType::Ptr mt = KMimeType::findByUrl( url, buff.st_mode, true /* local URL */ );
322 emit mimeType( mt->name() );
323 // Emit total size AFTER mimetype
324 totalSize( buff.st_size );
325
326 KIO::filesize_t processed_size = 0;
327
328 const QString resumeOffset = metaData(QLatin1String("resume"));
329 if ( !resumeOffset.isEmpty() )
330 {
331 bool ok;
332 KIO::fileoffset_t offset = resumeOffset.toLongLong(&ok);
333 if (ok && (offset > 0) && (offset < buff.st_size))
334 {
335 if (KDE_lseek(fd, offset, SEEK_SET) == offset)
336 {
337 canResume ();
338 processed_size = offset;
339 kDebug(7101) << "Resume offset:" << KIO::number(offset);
340 }
341 }
342 }
343
344 char buffer[ MAX_IPC_SIZE ];
345 QByteArray array;
346
347 while( 1 )
348 {
349 int n = ::read( fd, buffer, MAX_IPC_SIZE );
350 if (n == -1)
351 {
352 if (errno == EINTR)
353 continue;
354 error(KIO::ERR_COULD_NOT_READ, path);
355 ::close(fd);
356 return;
357 }
358 if (n == 0)
359 break; // Finished
360
361 array = QByteArray::fromRawData(buffer, n);
362 data( array );
363 array.clear();
364
365 processed_size += n;
366 processedSize( processed_size );
367
368 //kDebug(7101) << "Processed: " << KIO::number (processed_size);
369 }
370
371 data( QByteArray() );
372
373 ::close( fd );
374
375 processedSize( buff.st_size );
376 finished();
377}
378
379int write_all(int fd, const char *buf, size_t len)
380{
381 while (len > 0)
382 {
383 ssize_t written = write(fd, buf, len);
384 if (written < 0)
385 {
386 if (errno == EINTR)
387 continue;
388 return -1;
389 }
390 buf += written;
391 len -= written;
392 }
393 return 0;
394}
395
396void FileProtocol::open(const KUrl &url, QIODevice::OpenMode mode)
397{
398 kDebug(7101) << url;
399
400 openPath = url.toLocalFile();
401 KDE_struct_stat buff;
402 if (KDE::stat(openPath, &buff) == -1) {
403 if ( errno == EACCES )
404 error(KIO::ERR_ACCESS_DENIED, openPath);
405 else
406 error(KIO::ERR_DOES_NOT_EXIST, openPath);
407 return;
408 }
409
410 if ( S_ISDIR( buff.st_mode ) ) {
411 error(KIO::ERR_IS_DIRECTORY, openPath);
412 return;
413 }
414 if ( !S_ISREG( buff.st_mode ) ) {
415 error(KIO::ERR_CANNOT_OPEN_FOR_READING, openPath);
416 return;
417 }
418
419 int flags = 0;
420 if (mode & QIODevice::ReadOnly) {
421 if (mode & QIODevice::WriteOnly) {
422 flags = O_RDWR | O_CREAT;
423 } else {
424 flags = O_RDONLY;
425 }
426 } else if (mode & QIODevice::WriteOnly) {
427 flags = O_WRONLY | O_CREAT;
428 }
429
430 if (mode & QIODevice::Append) {
431 flags |= O_APPEND;
432 } else if (mode & QIODevice::Truncate) {
433 flags |= O_TRUNC;
434 }
435
436 int fd = -1;
437 if ( flags & O_CREAT)
438 fd = KDE::open( openPath, flags, 0666);
439 else
440 fd = KDE::open( openPath, flags);
441 if ( fd < 0 ) {
442 error(KIO::ERR_CANNOT_OPEN_FOR_READING, openPath);
443 return;
444 }
445 // Determine the mimetype of the file to be retrieved, and emit it.
446 // This is mandatory in all slaves (for KRun/BrowserRun to work).
447 // If we're not opening the file ReadOnly or ReadWrite, don't attempt to
448 // read the file and send the mimetype.
449 if (mode & QIODevice::ReadOnly){
450 KMimeType::Ptr mt = KMimeType::findByUrl( url, buff.st_mode, true /* local URL */ );
451 emit mimeType( mt->name() );
452 }
453
454 totalSize( buff.st_size );
455 position( 0 );
456
457 emit opened();
458 openFd = fd;
459}
460
461void FileProtocol::read(KIO::filesize_t bytes)
462{
463 kDebug(7101) << "File::open -- read";
464 Q_ASSERT(openFd != -1);
465
466 QVarLengthArray<char> buffer(bytes);
467 while (true) {
468 int res;
469 do {
470 res = ::read(openFd, buffer.data(), bytes);
471 } while (res == -1 && errno == EINTR);
472
473 if (res > 0) {
474 QByteArray array = QByteArray::fromRawData(buffer.data(), res);
475 data( array );
476 bytes -= res;
477 } else {
478 // empty array designates eof
479 data(QByteArray());
480 if (res != 0) {
481 error(KIO::ERR_COULD_NOT_READ, openPath);
482 close();
483 }
484 break;
485 }
486 if (bytes <= 0) break;
487 }
488}
489
490void FileProtocol::write(const QByteArray &data)
491{
492 kDebug(7101) << "File::open -- write";
493 Q_ASSERT(openFd != -1);
494
495 if (write_all(openFd, data.constData(), data.size())) {
496 if (errno == ENOSPC) { // disk full
497 error(KIO::ERR_DISK_FULL, openPath);
498 close();
499 } else {
500 kWarning(7101) << "Couldn't write. Error:" << strerror(errno);
501 error(KIO::ERR_COULD_NOT_WRITE, openPath);
502 close();
503 }
504 } else {
505 written(data.size());
506 }
507}
508
509void FileProtocol::seek(KIO::filesize_t offset)
510{
511 kDebug(7101) << "File::open -- seek";
512 Q_ASSERT(openFd != -1);
513
514 int res = KDE_lseek(openFd, offset, SEEK_SET);
515 if (res != -1) {
516 position( offset );
517 } else {
518 error(KIO::ERR_COULD_NOT_SEEK, openPath);
519 close();
520 }
521}
522
523void FileProtocol::close()
524{
525 kDebug(7101) << "File::open -- close ";
526 Q_ASSERT(openFd != -1);
527
528 ::close( openFd );
529 openFd = -1;
530 openPath.clear();
531
532 finished();
533}
534
535void FileProtocol::put( const KUrl& url, int _mode, KIO::JobFlags _flags )
536{
537 const QString dest_orig = url.toLocalFile();
538
539 kDebug(7101) << dest_orig << "mode=" << _mode;
540
541 QString dest_part(dest_orig + QLatin1String(".part"));
542
543 KDE_struct_stat buff_orig;
544 const bool bOrigExists = (KDE::lstat(dest_orig, &buff_orig) != -1);
545 bool bPartExists = false;
546 const bool bMarkPartial = config()->readEntry("MarkPartial", true);
547
548 if (bMarkPartial)
549 {
550 KDE_struct_stat buff_part;
551 bPartExists = (KDE::stat( dest_part, &buff_part ) != -1);
552
553 if (bPartExists && !(_flags & KIO::Resume) && !(_flags & KIO::Overwrite) && buff_part.st_size > 0 && S_ISREG(buff_part.st_mode))
554 {
555 kDebug(7101) << "calling canResume with" << KIO::number(buff_part.st_size);
556
557 // Maybe we can use this partial file for resuming
558 // Tell about the size we have, and the app will tell us
559 // if it's ok to resume or not.
560 _flags |= canResume( buff_part.st_size ) ? KIO::Resume : KIO::DefaultFlags;
561
562 kDebug(7101) << "got answer" << (_flags & KIO::Resume);
563 }
564 }
565
566 if ( bOrigExists && !(_flags & KIO::Overwrite) && !(_flags & KIO::Resume))
567 {
568 if (S_ISDIR(buff_orig.st_mode))
569 error( KIO::ERR_DIR_ALREADY_EXIST, dest_orig );
570 else
571 error( KIO::ERR_FILE_ALREADY_EXIST, dest_orig );
572 return;
573 }
574
575 int result;
576 QString dest;
577 QByteArray _dest;
578
579 int fd = -1;
580
581 // Loop until we got 0 (end of data)
582 do
583 {
584 QByteArray buffer;
585 dataReq(); // Request for data
586 result = readData( buffer );
587
588 if (result >= 0)
589 {
590 if (dest.isEmpty())
591 {
592 if (bMarkPartial)
593 {
594 kDebug(7101) << "Appending .part extension to" << dest_orig;
595 dest = dest_part;
596 if ( bPartExists && !(_flags & KIO::Resume) )
597 {
598 kDebug(7101) << "Deleting partial file" << dest_part;
599 QFile::remove( dest_part );
600 // Catch errors when we try to open the file.
601 }
602 }
603 else
604 {
605 dest = dest_orig;
606 if ( bOrigExists && !(_flags & KIO::Resume) )
607 {
608 kDebug(7101) << "Deleting destination file" << dest_orig;
609 QFile::remove( dest_orig );
610 // Catch errors when we try to open the file.
611 }
612 }
613
614 if ( (_flags & KIO::Resume) )
615 {
616 fd = KDE::open( dest, O_RDWR ); // append if resuming
617 if (fd != -1) {
618 KDE_lseek(fd, 0, SEEK_END); // Seek to end
619 }
620 }
621 else
622 {
623 // WABA: Make sure that we keep writing permissions ourselves,
624 // otherwise we can be in for a surprise on NFS.
625 mode_t initialMode;
626 if (_mode != -1)
627 initialMode = _mode | S_IWUSR | S_IRUSR;
628 else
629 initialMode = 0666;
630
631 fd = KDE::open(dest, O_CREAT | O_TRUNC | O_WRONLY, initialMode);
632 }
633
634 if ( fd < 0 )
635 {
636 kDebug(7101) << "####################### COULD NOT WRITE" << dest << "_mode=" << _mode;
637 kDebug(7101) << "errno==" << errno << "(" << strerror(errno) << ")";
638 if ( errno == EACCES )
639 error(KIO::ERR_WRITE_ACCESS_DENIED, dest);
640 else
641 error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest);
642 return;
643 }
644 }
645
646 if (write_all( fd, buffer.data(), buffer.size()))
647 {
648 if ( errno == ENOSPC ) // disk full
649 {
650 error(KIO::ERR_DISK_FULL, dest_orig);
651 result = -2; // means: remove dest file
652 }
653 else
654 {
655 kWarning(7101) << "Couldn't write. Error:" << strerror(errno);
656 error(KIO::ERR_COULD_NOT_WRITE, dest_orig);
657 result = -1;
658 }
659 }
660 }
661 }
662 while ( result > 0 );
663
664 // An error occurred deal with it.
665 if (result < 0)
666 {
667 kDebug(7101) << "Error during 'put'. Aborting.";
668
669 if (fd != -1)
670 {
671 ::close(fd);
672
673 KDE_struct_stat buff;
674 if (bMarkPartial && KDE::stat( dest, &buff ) == 0)
675 {
676 int size = config()->readEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE);
677 if (buff.st_size < size)
678 remove(_dest.data());
679 }
680 }
681
682 ::exit(255);
683 }
684
685 if ( fd == -1 ) // we got nothing to write out, so we never opened the file
686 {
687 finished();
688 return;
689 }
690
691 if ( ::close(fd) )
692 {
693 kWarning(7101) << "Error when closing file descriptor:" << strerror(errno);
694 error(KIO::ERR_COULD_NOT_WRITE, dest_orig);
695 return;
696 }
697
698 // after full download rename the file back to original name
699 if ( bMarkPartial )
700 {
701 // If the original URL is a symlink and we were asked to overwrite it,
702 // remove the symlink first. This ensures that we do not overwrite the
703 // current source if the symlink points to it.
704 if( (_flags & KIO::Overwrite) && S_ISLNK( buff_orig.st_mode ) )
705 QFile::remove( dest_orig );
706 if ( KDE::rename( dest, dest_orig ) )
707 {
708 kWarning(7101) << " Couldn't rename " << _dest << " to " << dest_orig;
709 error(KIO::ERR_CANNOT_RENAME_PARTIAL, dest_orig);
710 return;
711 }
712 org::kde::KDirNotify::emitFileRenamed(KUrl(dest).url(), KUrl(dest_orig).url());
713 }
714
715 // set final permissions
716 if ( _mode != -1 && !(_flags & KIO::Resume) )
717 {
718 if (KDE::chmod(dest_orig, _mode) != 0)
719 {
720 // couldn't chmod. Eat the error if the filesystem apparently doesn't support it.
721 KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByPath(dest_orig);
722 if (mp && mp->testFileSystemFlag(KMountPoint::SupportsChmod))
723 warning( i18n( "Could not change permissions for\n%1" , dest_orig ) );
724 }
725 }
726
727 // set modification time
728 const QString mtimeStr = metaData(QLatin1String("modified"));
729 if ( !mtimeStr.isEmpty() ) {
730 QDateTime dt = QDateTime::fromString( mtimeStr, Qt::ISODate );
731 if ( dt.isValid() ) {
732 KDE_struct_stat dest_statbuf;
733 if (KDE::stat( dest_orig, &dest_statbuf ) == 0) {
734 struct timeval utbuf[2];
735 // access time
736 utbuf[0].tv_sec = dest_statbuf.st_atime; // access time, unchanged ## TODO preserve msec
737 utbuf[0].tv_usec = 0;
738 // modification time
739 utbuf[1].tv_sec = dt.toTime_t();
740 utbuf[1].tv_usec = dt.time().msec() * 1000;
741 utimes( QFile::encodeName(dest_orig), utbuf );
742 }
743 }
744
745 }
746
747 // We have done our job => finish
748 finished();
749}
750
751QString FileProtocol::getUserName( uid_t uid ) const
752{
753 if ( !mUsercache.contains( uid ) ) {
754 struct passwd *user = getpwuid( uid );
755 if ( user ) {
756 mUsercache.insert( uid, QString::fromLatin1(user->pw_name) );
757 }
758 else
759 return QString::number( uid );
760 }
761 return mUsercache[uid];
762}
763
764QString FileProtocol::getGroupName( gid_t gid ) const
765{
766 if ( !mGroupcache.contains( gid ) ) {
767 struct group *grp = getgrgid( gid );
768 if ( grp ) {
769 mGroupcache.insert( gid, QString::fromLatin1(grp->gr_name) );
770 }
771 else
772 return QString::number( gid );
773 }
774 return mGroupcache[gid];
775}
776
777bool FileProtocol::createUDSEntry( const QString & filename, const QByteArray & path, UDSEntry & entry,
778 short int details, bool withACL )
779{
780#ifndef HAVE_POSIX_ACL
781 Q_UNUSED(withACL);
782#endif
783 assert(entry.count() == 0); // by contract :-)
784 // entry.reserve( 8 ); // speed up QHash insertion
785
786 entry.insert( KIO::UDSEntry::UDS_NAME, filename );
787
788 mode_t type;
789 mode_t access;
790 KDE_struct_stat buff;
791
792 if ( KDE_lstat( path.data(), &buff ) == 0 ) {
793
794 if (details > 2) {
795 entry.insert( KIO::UDSEntry::UDS_DEVICE_ID, buff.st_dev );
796 entry.insert( KIO::UDSEntry::UDS_INODE, buff.st_ino );
797 }
798
799 if (S_ISLNK(buff.st_mode)) {
800
801 char buffer2[ 1000 ];
802 int n = readlink( path.data(), buffer2, 999 );
803 if ( n != -1 ) {
804 buffer2[ n ] = 0;
805 }
806
807 entry.insert( KIO::UDSEntry::UDS_LINK_DEST, QFile::decodeName( buffer2 ) );
808
809 // A symlink -> follow it only if details>1
810 if ( details > 1 && KDE_stat( path.data(), &buff ) == -1 ) {
811 // It is a link pointing to nowhere
812 type = S_IFMT - 1;
813 access = S_IRWXU | S_IRWXG | S_IRWXO;
814
815 entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, type );
816 entry.insert( KIO::UDSEntry::UDS_ACCESS, access );
817 entry.insert( KIO::UDSEntry::UDS_SIZE, 0LL );
818 goto notype;
819
820 }
821 }
822 } else {
823 // kWarning() << "lstat didn't work on " << path.data();
824 return false;
825 }
826
827 type = buff.st_mode & S_IFMT; // extract file type
828 access = buff.st_mode & 07777; // extract permissions
829
830 entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, type );
831 entry.insert( KIO::UDSEntry::UDS_ACCESS, access );
832
833 entry.insert( KIO::UDSEntry::UDS_SIZE, buff.st_size );
834
835#ifdef HAVE_POSIX_ACL
836 if (details > 0) {
837 /* Append an atom indicating whether the file has extended acl information
838 * and if withACL is specified also one with the acl itself. If it's a directory
839 * and it has a default ACL, also append that. */
840 appendACLAtoms( path, entry, type, withACL );
841 }
842#endif
843
844 notype:
845 if (details > 0) {
846 entry.insert( KIO::UDSEntry::UDS_MODIFICATION_TIME, buff.st_mtime );
847 entry.insert( KIO::UDSEntry::UDS_USER, getUserName( buff.st_uid ) );
848 entry.insert( KIO::UDSEntry::UDS_GROUP, getGroupName( buff.st_gid ) );
849 entry.insert( KIO::UDSEntry::UDS_ACCESS_TIME, buff.st_atime );
850 }
851
852 // Note: buff.st_ctime isn't the creation time !
853 // We made that mistake for KDE 2.0, but it's in fact the
854 // "file status" change time, which we don't care about.
855
856 return true;
857}
858
859void FileProtocol::special( const QByteArray &data)
860{
861 int tmp;
862 QDataStream stream(data);
863
864 stream >> tmp;
865 switch (tmp) {
866 case 1:
867 {
868 QString fstype, dev, point;
869 qint8 iRo;
870
871 stream >> iRo >> fstype >> dev >> point;
872
873 bool ro = ( iRo != 0 );
874
875 kDebug(7101) << "MOUNTING fstype=" << fstype << " dev=" << dev << " point=" << point << " ro=" << ro;
876 bool ok = pmount( dev );
877 if (ok)
878 finished();
879 else
880 mount( ro, fstype.toLatin1(), dev, point );
881
882 }
883 break;
884 case 2:
885 {
886 QString point;
887 stream >> point;
888 bool ok = pumount( point );
889 if (ok)
890 finished();
891 else
892 unmount( point );
893 }
894 break;
895
896 default:
897 break;
898 }
899}
900
901void FileProtocol::mount( bool _ro, const char *_fstype, const QString& _dev, const QString& _point )
902{
903 kDebug(7101) << "fstype=" << _fstype;
904
905#ifndef _WIN32_WCE
906#ifdef HAVE_VOLMGT
907 /*
908 * support for Solaris volume management
909 */
910 QString err;
911 QByteArray devname = QFile::encodeName( _dev );
912
913 if( volmgt_running() ) {
914// kDebug(7101) << "VOLMGT: vold ok.";
915 if( volmgt_check( devname.data() ) == 0 ) {
916 kDebug(7101) << "VOLMGT: no media in "
917 << devname.data();
918 err = i18n("No Media inserted or Media not recognized.");
919 error( KIO::ERR_COULD_NOT_MOUNT, err );
920 return;
921 } else {
922 kDebug(7101) << "VOLMGT: " << devname.data()
923 << ": media ok";
924 finished();
925 return;
926 }
927 } else {
928 err = i18n("\"vold\" is not running.");
929 kDebug(7101) << "VOLMGT: " << err;
930 error( KIO::ERR_COULD_NOT_MOUNT, err );
931 return;
932 }
933#else
934
935
936 KTemporaryFile tmpFile;
937 tmpFile.setAutoRemove(false);
938 tmpFile.open();
939 QByteArray tmpFileName = QFile::encodeName(tmpFile.fileName());
940 QByteArray dev;
941 if (_dev.startsWith(QLatin1String("LABEL="))) { // turn LABEL=foo into -L foo (#71430)
942 QString labelName = _dev.mid( 6 );
943 dev = "-L ";
944 dev += QFile::encodeName( KShell::quoteArg( labelName ) ); // is it correct to assume same encoding as filesystem?
945 } else if (_dev.startsWith(QLatin1String("UUID="))) { // and UUID=bar into -U bar
946 QString uuidName = _dev.mid( 5 );
947 dev = "-U ";
948 dev += QFile::encodeName( KShell::quoteArg( uuidName ) );
949 }
950 else
951 dev = QFile::encodeName( KShell::quoteArg(_dev) ); // get those ready to be given to a shell
952
953 QByteArray point = QFile::encodeName( KShell::quoteArg(_point) );
954 bool fstype_empty = !_fstype || !*_fstype;
955 QByteArray fstype = KShell::quoteArg(QString::fromLatin1(_fstype)).toLatin1(); // good guess
956 QByteArray readonly = _ro ? "-r" : "";
957 QString epath = QString::fromLocal8Bit(qgetenv("PATH"));
958 QString path = QLatin1String("/sbin:/bin");
959 if(!epath.isEmpty())
960 path += QLatin1String(":") + epath;
961 QByteArray mountProg = KGlobal::dirs()->findExe(QLatin1String("mount"), path).toLocal8Bit();
962 if (mountProg.isEmpty()){
963 error( KIO::ERR_COULD_NOT_MOUNT, i18n("Could not find program \"mount\""));
964 return;
965 }
966
967 // Two steps, in case mount doesn't like it when we pass all options
968 for ( int step = 0 ; step <= 1 ; step++ )
969 {
970 QByteArray buffer = mountProg + ' ';
971 // Mount using device only if no fstype nor mountpoint (KDE-1.x like)
972 if ( !dev.isEmpty() && _point.isEmpty() && fstype_empty )
973 buffer += dev;
974 else
975 // Mount using the mountpoint, if no fstype nor device (impossible in first step)
976 if ( !_point.isEmpty() && dev.isEmpty() && fstype_empty )
977 buffer += point;
978 else
979 // mount giving device + mountpoint but no fstype
980 if ( !_point.isEmpty() && !dev.isEmpty() && fstype_empty )
981 buffer += readonly + ' ' + dev + ' ' + point;
982 else
983 // mount giving device + mountpoint + fstype
984#if defined(__svr4__) && defined(Q_OS_SOLARIS) // MARCO for Solaris 8 and I
985 // believe this is true for SVR4 in general
986 buffer += "-F " + fstype + ' ' + (_ro ? "-oro" : "") + ' ' + dev + ' ' + point;
987#else
988 buffer += readonly + " -t " + fstype + ' ' + dev + ' ' + point;
989#endif
990 buffer += " 2>" + tmpFileName;
991 kDebug(7101) << buffer;
992
993 int mount_ret = system( buffer.constData() );
994
995 QString err = readLogFile( tmpFileName );
996 if ( err.isEmpty() && mount_ret == 0)
997 {
998 finished();
999 return;
1000 }
1001 else
1002 {
1003 // Didn't work - or maybe we just got a warning
1004 KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByDevice( _dev );
1005 // Is the device mounted ?
1006 if ( mp && mount_ret == 0)
1007 {
1008 kDebug(7101) << "mount got a warning:" << err;
1009 warning( err );
1010 finished();
1011 return;
1012 }
1013 else
1014 {
1015 if ( (step == 0) && !_point.isEmpty())
1016 {
1017 kDebug(7101) << err;
1018 kDebug(7101) << "Mounting with those options didn't work, trying with only mountpoint";
1019 fstype = "";
1020 fstype_empty = true;
1021 dev = "";
1022 // The reason for trying with only mountpoint (instead of
1023 // only device) is that some people (hi Malte!) have the
1024 // same device associated with two mountpoints
1025 // for different fstypes, like /dev/fd0 /mnt/e2floppy and
1026 // /dev/fd0 /mnt/dosfloppy.
1027 // If the user has the same mountpoint associated with two
1028 // different devices, well they shouldn't specify the
1029 // mountpoint but just the device.
1030 }
1031 else
1032 {
1033 error( KIO::ERR_COULD_NOT_MOUNT, err );
1034 return;
1035 }
1036 }
1037 }
1038 }
1039#endif /* ! HAVE_VOLMGT */
1040#else
1041 QString err;
1042 err = i18n("mounting is not supported by wince.");
1043 error( KIO::ERR_COULD_NOT_MOUNT, err );
1044#endif
1045
1046}
1047
1048
1049void FileProtocol::unmount( const QString& _point )
1050{
1051#ifndef _WIN32_WCE
1052 QByteArray buffer;
1053
1054 KTemporaryFile tmpFile;
1055 tmpFile.setAutoRemove(false);
1056 tmpFile.open();
1057 QByteArray tmpFileName = QFile::encodeName(tmpFile.fileName());
1058 QString err;
1059
1060#ifdef HAVE_VOLMGT
1061 /*
1062 * support for Solaris volume management
1063 */
1064 char *devname;
1065 char *ptr;
1066 FILE *mnttab;
1067 struct mnttab mnt;
1068
1069 if( volmgt_running() ) {
1070 kDebug(7101) << "VOLMGT: looking for "
1071 << _point.toLocal8Bit();
1072
1073 if( (mnttab = KDE_fopen( MNTTAB, "r" )) == NULL ) {
1074 err = QLatin1String("could not open mnttab");
1075 kDebug(7101) << "VOLMGT: " << err;
1076 error( KIO::ERR_COULD_NOT_UNMOUNT, err );
1077 return;
1078 }
1079
1080 /*
1081 * since there's no way to derive the device name from
1082 * the mount point through the volmgt library (and
1083 * media_findname() won't work in this case), we have to
1084 * look ourselves...
1085 */
1086 devname = NULL;
1087 rewind( mnttab );
1088 while( getmntent( mnttab, &mnt ) == 0 ) {
1089 if( strcmp( _point.toLocal8Bit(), mnt.mnt_mountp ) == 0 ){
1090 devname = mnt.mnt_special;
1091 break;
1092 }
1093 }
1094 fclose( mnttab );
1095
1096 if( devname == NULL ) {
1097 err = QLatin1String("not in mnttab");
1098 kDebug(7101) << "VOLMGT: "
1099 << QFile::encodeName(_point).data()
1100 << ": " << err;
1101 error( KIO::ERR_COULD_NOT_UNMOUNT, err );
1102 return;
1103 }
1104
1105 /*
1106 * strip off the directory name (volume name)
1107 * the eject(1) command will handle unmounting and
1108 * physically eject the media (if possible)
1109 */
1110 ptr = strrchr( devname, '/' );
1111 *ptr = '\0';
1112 QByteArray qdevname(QFile::encodeName(KShell::quoteArg(QFile::decodeName(QByteArray(devname)))).data());
1113 buffer = "/usr/bin/eject " + qdevname + " 2>" + tmpFileName;
1114 kDebug(7101) << "VOLMGT: eject " << qdevname;
1115
1116 /*
1117 * from eject(1): exit status == 0 => need to manually eject
1118 * exit status == 4 => media was ejected
1119 */
1120 if( WEXITSTATUS( system( buffer.constData() )) == 4 ) {
1121 /*
1122 * this is not an error, so skip "readLogFile()"
1123 * to avoid wrong/confusing error popup. The
1124 * temporary file is removed by KTemporaryFile's
1125 * destructor, so don't do that manually.
1126 */
1127 finished();
1128 return;
1129 }
1130 } else {
1131 /*
1132 * eject(1) should do its job without vold(1M) running,
1133 * so we probably could call eject anyway, but since the
1134 * media is mounted now, vold must've died for some reason
1135 * during the user's session, so it should be restarted...
1136 */
1137 err = i18n("\"vold\" is not running.");
1138 kDebug(7101) << "VOLMGT: " << err;
1139 error( KIO::ERR_COULD_NOT_UNMOUNT, err );
1140 return;
1141 }
1142#else
1143 QString epath = QString::fromLocal8Bit(qgetenv("PATH"));
1144 QString path = QLatin1String("/sbin:/bin");
1145 if (!epath.isEmpty())
1146 path += QLatin1Char(':') + epath;
1147 QByteArray umountProg = KGlobal::dirs()->findExe(QLatin1String("umount"), path).toLocal8Bit();
1148
1149 if (umountProg.isEmpty()) {
1150 error( KIO::ERR_COULD_NOT_UNMOUNT, i18n("Could not find program \"umount\""));
1151 return;
1152 }
1153 buffer = umountProg + ' ' + QFile::encodeName(KShell::quoteArg(_point)) + " 2>" + tmpFileName;
1154 system( buffer.constData() );
1155#endif /* HAVE_VOLMGT */
1156
1157 err = readLogFile( tmpFileName );
1158 if ( err.isEmpty() )
1159 finished();
1160 else
1161 error( KIO::ERR_COULD_NOT_UNMOUNT, err );
1162#else
1163 QString err;
1164 err = i18n("unmounting is not supported by wince.");
1165 error( KIO::ERR_COULD_NOT_MOUNT, err );
1166#endif
1167}
1168
1169/*************************************
1170 *
1171 * pmount handling
1172 *
1173 *************************************/
1174
1175bool FileProtocol::pmount(const QString &dev)
1176{
1177#ifndef _WIN32_WCE
1178 QString epath = QString::fromLocal8Bit(qgetenv("PATH"));
1179 QString path = QLatin1String("/sbin:/bin");
1180 if (!epath.isEmpty())
1181 path += QLatin1Char(':') + epath;
1182 QString pmountProg = KGlobal::dirs()->findExe(QLatin1String("pmount"), path);
1183
1184 if (pmountProg.isEmpty())
1185 return false;
1186
1187 QByteArray buffer = QFile::encodeName(pmountProg) + ' ' +
1188 QFile::encodeName(KShell::quoteArg(dev));
1189
1190 int res = system( buffer.constData() );
1191
1192 return res==0;
1193#else
1194 return false;
1195#endif
1196}
1197
1198bool FileProtocol::pumount(const QString &point)
1199{
1200#ifndef _WIN32_WCE
1201 KMountPoint::Ptr mp = KMountPoint::currentMountPoints(KMountPoint::NeedRealDeviceName).findByPath(point);
1202 if (!mp)
1203 return false;
1204 QString dev = mp->realDeviceName();
1205 if (dev.isEmpty()) return false;
1206
1207 QString epath = QString::fromLocal8Bit(qgetenv("PATH"));
1208 QString path = QLatin1String("/sbin:/bin");
1209 if (!epath.isEmpty())
1210 path += QLatin1Char(':') + epath;
1211 QString pumountProg = KGlobal::dirs()->findExe(QLatin1String("pumount"), path);
1212
1213 if (pumountProg.isEmpty())
1214 return false;
1215
1216 QByteArray buffer = QFile::encodeName(pumountProg);
1217 buffer += ' ';
1218 buffer += QFile::encodeName(KShell::quoteArg(dev));
1219
1220 int res = system( buffer.data() );
1221
1222 return res==0;
1223#else
1224 return false;
1225#endif
1226}
1227
1228/*************************************
1229 *
1230 * Utilities
1231 *
1232 *************************************/
1233
1234static QString readLogFile( const QByteArray& _filename )
1235{
1236 QString result;
1237 QFile file(QFile::decodeName(_filename));
1238 if (file.open(QIODevice::ReadOnly)) {
1239 result = QString::fromLocal8Bit(file.readAll());
1240 }
1241 (void)file.remove();
1242 return result;
1243}
1244
1245/*************************************
1246 *
1247 * ACL handling helpers
1248 *
1249 *************************************/
1250#ifdef HAVE_POSIX_ACL
1251
1252bool FileProtocol::isExtendedACL( acl_t acl )
1253{
1254 return ( acl_equiv_mode( acl, 0 ) != 0 );
1255}
1256
1257static void appendACLAtoms( const QByteArray & path, UDSEntry& entry, mode_t type, bool withACL )
1258{
1259 // first check for a noop
1260 if ( acl_extended_file( path.data() ) == 0 ) return;
1261
1262 acl_t acl = 0;
1263 acl_t defaultAcl = 0;
1264 bool isDir = S_ISDIR( type );
1265 // do we have an acl for the file, and/or a default acl for the dir, if it is one?
1266 acl = acl_get_file( path.data(), ACL_TYPE_ACCESS );
1267 /* Sadly libacl does not provided a means of checking for extended ACL and default
1268 * ACL separately. Since a directory can have both, we need to check again. */
1269 if ( isDir ) {
1270 if ( acl ) {
1271 if ( !FileProtocol::isExtendedACL( acl ) ) {
1272 acl_free( acl );
1273 acl = 0;
1274 }
1275 }
1276 defaultAcl = acl_get_file( path.data(), ACL_TYPE_DEFAULT );
1277 }
1278 if ( acl || defaultAcl ) {
1279 kDebug(7101) << path.constData() << "has extended ACL entries";
1280 entry.insert( KIO::UDSEntry::UDS_EXTENDED_ACL, 1 );
1281 }
1282 if ( withACL ) {
1283 if ( acl ) {
1284 const QString str = aclToText(acl);
1285 entry.insert( KIO::UDSEntry::UDS_ACL_STRING, str );
1286 kDebug(7101) << path.constData() << "ACL:" << str;
1287 }
1288 if ( defaultAcl ) {
1289 const QString str = aclToText(defaultAcl);
1290 entry.insert( KIO::UDSEntry::UDS_DEFAULT_ACL_STRING, str );
1291 kDebug(7101) << path.constData() << "DEFAULT ACL:" << str;
1292 }
1293 }
1294 if ( acl ) acl_free( acl );
1295 if ( defaultAcl ) acl_free( defaultAcl );
1296}
1297#endif
1298
1299// We could port this to KTempDir::removeDir but then we wouldn't be able to tell the user
1300// where exactly the deletion failed, in case of errors.
1301bool FileProtocol::deleteRecursive(const QString& path)
1302{
1303 //kDebug() << path;
1304 QDirIterator it(path, QDir::AllEntries | QDir::NoDotAndDotDot | QDir::System | QDir::Hidden,
1305 QDirIterator::Subdirectories);
1306 QStringList dirsToDelete;
1307 while ( it.hasNext() ) {
1308 const QString itemPath = it.next();
1309 //kDebug() << "itemPath=" << itemPath;
1310 const QFileInfo info = it.fileInfo();
1311 if (info.isDir() && !info.isSymLink())
1312 dirsToDelete.prepend(itemPath);
1313 else {
1314 //kDebug() << "QFile::remove" << itemPath;
1315 if (!QFile::remove(itemPath)) {
1316 error(KIO::ERR_CANNOT_DELETE, itemPath);
1317 return false;
1318 }
1319 }
1320 }
1321 QDir dir;
1322 Q_FOREACH(const QString& itemPath, dirsToDelete) {
1323 //kDebug() << "QDir::rmdir" << itemPath;
1324 if (!dir.rmdir(itemPath)) {
1325 error(KIO::ERR_CANNOT_DELETE, itemPath);
1326 return false;
1327 }
1328 }
1329 return true;
1330}
1331
1332#include "file.moc"
FileProtocol
Definition: file.h:47
FileProtocol::mkdir
virtual void mkdir(const KUrl &url, int permissions)
Definition: file.cpp:236
FileProtocol::write
virtual void write(const QByteArray &data)
Definition: file.cpp:490
FileProtocol::put
virtual void put(const KUrl &url, int _mode, KIO::JobFlags _flags)
Definition: file.cpp:535
FileProtocol::special
virtual void special(const QByteArray &data)
Special commands supported by this slave: 1 - mount 2 - unmount.
Definition: file.cpp:859
FileProtocol::pumount
bool pumount(const QString &point)
Definition: file.cpp:1198
FileProtocol::close
virtual void close()
Definition: file.cpp:523
FileProtocol::get
virtual void get(const KUrl &url)
Definition: file.cpp:277
FileProtocol::seek
virtual void seek(KIO::filesize_t offset)
Definition: file.cpp:509
FileProtocol::~FileProtocol
virtual ~FileProtocol()
Definition: file.cpp:128
FileProtocol::mount
void mount(bool _ro, const char *_fstype, const QString &dev, const QString &point)
Definition: file.cpp:901
FileProtocol::pmount
bool pmount(const QString &dev)
Definition: file.cpp:1175
FileProtocol::setModificationTime
virtual void setModificationTime(const KUrl &url, const QDateTime &mtime)
Definition: file.cpp:217
FileProtocol::FileProtocol
FileProtocol(const QByteArray &pool, const QByteArray &app)
Definition: file.cpp:123
FileProtocol::chmod
virtual void chmod(const KUrl &url, int permissions)
Definition: file.cpp:187
FileProtocol::open
virtual void open(const KUrl &url, QIODevice::OpenMode mode)
Definition: file.cpp:396
FileProtocol::unmount
void unmount(const QString &point)
Definition: file.cpp:1049
FileProtocol::read
virtual void read(KIO::filesize_t size)
Definition: file.cpp:461
KComponentData
KConfigGroup::readEntry
QString readEntry(const char *key, const char *aDefault=0) const
KIO::SlaveBase
KIO::SlaveBase::mimeType
void mimeType(const QString &_type)
KIO::SlaveBase::metaData
QString metaData(const QString &key) const
KIO::SlaveBase::processedSize
void processedSize(KIO::filesize_t _bytes)
KIO::SlaveBase::warning
void warning(const QString &msg)
KIO::SlaveBase::finished
void finished()
KIO::SlaveBase::dataReq
void dataReq()
KIO::SlaveBase::written
void written(KIO::filesize_t _bytes)
KIO::SlaveBase::redirection
void redirection(const KUrl &_url)
KIO::SlaveBase::error
void error(int _errid, const QString &_text)
KIO::SlaveBase::position
void position(KIO::filesize_t _pos)
KIO::SlaveBase::dispatchLoop
void dispatchLoop()
KIO::SlaveBase::readData
int readData(QByteArray &buffer)
KIO::SlaveBase::data
void data(const QByteArray &data)
KIO::SlaveBase::totalSize
void totalSize(KIO::filesize_t _bytes)
KIO::SlaveBase::canResume
void canResume()
KIO::SlaveBase::config
KConfigGroup * config()
KIO::SlaveBase::opened
void opened()
KIO::SlaveBase::exit
void exit()
KIO::UDSEntry
KIO::UDSEntry::UDS_GROUP
UDS_GROUP
KIO::UDSEntry::UDS_LINK_DEST
UDS_LINK_DEST
KIO::UDSEntry::UDS_FILE_TYPE
UDS_FILE_TYPE
KIO::UDSEntry::UDS_MODIFICATION_TIME
UDS_MODIFICATION_TIME
KIO::UDSEntry::UDS_SIZE
UDS_SIZE
KIO::UDSEntry::UDS_DEVICE_ID
UDS_DEVICE_ID
KIO::UDSEntry::UDS_ACCESS_TIME
UDS_ACCESS_TIME
KIO::UDSEntry::UDS_DEFAULT_ACL_STRING
UDS_DEFAULT_ACL_STRING
KIO::UDSEntry::UDS_NAME
UDS_NAME
KIO::UDSEntry::UDS_ACL_STRING
UDS_ACL_STRING
KIO::UDSEntry::UDS_INODE
UDS_INODE
KIO::UDSEntry::UDS_USER
UDS_USER
KIO::UDSEntry::UDS_EXTENDED_ACL
UDS_EXTENDED_ACL
KIO::UDSEntry::UDS_ACCESS
UDS_ACCESS
KIO::UDSEntry::insert
void insert(uint field, const QString &value)
KIO::UDSEntry::count
int count() const
KMimeType::findByUrl
static Ptr findByUrl(const KUrl &url, mode_t mode=0, bool is_local_file=false, bool fast_mode=false, int *accuracy=0)
KMountPoint::List::findByPath
Ptr findByPath(const QString &path) const
KMountPoint::List::findByDevice
Ptr findByDevice(const QString &device) const
KMountPoint::SupportsChmod
SupportsChmod
KMountPoint::NeedRealDeviceName
NeedRealDeviceName
KMountPoint::currentMountPoints
static List currentMountPoints(DetailsNeededFlags infoNeeded=BasicInfoNeeded)
KSharedPtr
KStandardDirs::findExe
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
KTemporaryFile
KUrl
KUrl::setProtocol
void setProtocol(const QString &proto)
KUrl::isLocalFile
bool isLocalFile() const
KUrl::toLocalFile
QString toLocalFile(AdjustPathOption trailing=LeaveTrailingSlash) const
OrgKdeKDirNotifyInterface::emitFileRenamed
static void emitFileRenamed(const QString &src, const QString &dst)
write_all
int write_all(int fd, const char *buf, size_t len)
Definition: file.cpp:379
readLogFile
static QString readLogFile(const QByteArray &_filename)
Definition: file.cpp:1234
kdemain
int kdemain(int argc, char **argv)
Definition: file.cpp:102
MAX_IPC_SIZE
#define MAX_IPC_SIZE
Definition: file.cpp:94
file.h
kDebug
#define kDebug
kWarning
#define kWarning
ioslave_defaults.h
DEFAULT_MINIMUM_KEEP_SIZE
#define DEFAULT_MINIMUM_KEEP_SIZE
readEntry
KAutostart::StartPhase readEntry(const KConfigGroup &group, const char *key, const KAutostart::StartPhase &aDefault)
kcomponentdata.h
kconfig.h
kconfiggroup.h
kdebug.h
kdirnotify.h
kglobal.h
klocale.h
i18n
QString i18n(const char *text)
kmimetype.h
MNTTAB
#define MNTTAB
kmountpoint.h
kshell.h
kstandarddirs.h
ktemporaryfile.h
kurl.h
KDE::lstat
int lstat(const QString &path, KDE_struct_stat *buf)
KDE::utime
int utime(const QString &filename, struct utimbuf *buf)
KDE::chmod
int chmod(const QString &path, mode_t mode)
KDE::mkdir
int mkdir(const QString &pathname, mode_t)
KDE::open
int open(const QString &pathname, int flags, mode_t mode)
KDE::stat
int stat(const QString &path, KDE_struct_stat *buf)
KDE::rename
int rename(const QString &in, const QString &out)
access
int access(const QString &path, int mode)
KGlobal::dirs
KStandardDirs * dirs()
KGlobal::locale
KLocale * locale()
KIO
KIO::Resume
Resume
KIO::DefaultFlags
DefaultFlags
KIO::Overwrite
Overwrite
KIO::fileoffset_t
qlonglong fileoffset_t
KIO::filesize_t
qulonglong filesize_t
KIO::ERR_DOES_NOT_EXIST
ERR_DOES_NOT_EXIST
KIO::ERR_COULD_NOT_WRITE
ERR_COULD_NOT_WRITE
KIO::ERR_DIR_ALREADY_EXIST
ERR_DIR_ALREADY_EXIST
KIO::ERR_COULD_NOT_SEEK
ERR_COULD_NOT_SEEK
KIO::ERR_WRITE_ACCESS_DENIED
ERR_WRITE_ACCESS_DENIED
KIO::ERR_FILE_ALREADY_EXIST
ERR_FILE_ALREADY_EXIST
KIO::ERR_CANNOT_OPEN_FOR_READING
ERR_CANNOT_OPEN_FOR_READING
KIO::ERR_COULD_NOT_READ
ERR_COULD_NOT_READ
KIO::ERR_ACCESS_DENIED
ERR_ACCESS_DENIED
KIO::ERR_CANNOT_CHMOD
ERR_CANNOT_CHMOD
KIO::ERR_CANNOT_RENAME_PARTIAL
ERR_CANNOT_RENAME_PARTIAL
KIO::ERR_IS_DIRECTORY
ERR_IS_DIRECTORY
KIO::ERR_DISK_FULL
ERR_DISK_FULL
KIO::ERR_CANNOT_DELETE
ERR_CANNOT_DELETE
KIO::ERR_UNSUPPORTED_ACTION
ERR_UNSUPPORTED_ACTION
KIO::ERR_COULD_NOT_MKDIR
ERR_COULD_NOT_MKDIR
KIO::ERR_COULD_NOT_UNMOUNT
ERR_COULD_NOT_UNMOUNT
KIO::ERR_CANNOT_OPEN_FOR_WRITING
ERR_CANNOT_OPEN_FOR_WRITING
KIO::ERR_COULD_NOT_MOUNT
ERR_COULD_NOT_MOUNT
KIO::ERR_CANNOT_SETTIME
ERR_CANNOT_SETTIME
KIO::number
QString number(KIO::filesize_t size)
group
group
dir
QString dir(const QString &fileClass)
KShell::quoteArg
QString quoteArg(const QString &arg)
remove
KGuiItem remove()
ok
KGuiItem ok()
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KIOSlave

Skip menu "KIOSlave"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal