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

KIOSlave

  • sources
  • kde-4.12
  • kdelibs
  • 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 
92 using namespace KIO;
93 
94 #define MAX_IPC_SIZE (1024*32)
95 
96 static QString readLogFile( const QByteArray&_filename );
97 #ifdef HAVE_POSIX_ACL
98 static void appendACLAtoms( const QByteArray & path, UDSEntry& entry,
99  mode_t type, bool withACL );
100 #endif
101 
102 extern "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 
123 FileProtocol::FileProtocol( const QByteArray &pool, const QByteArray &app )
124  : SlaveBase( "file", pool, app ), openFd(-1)
125 {
126 }
127 
128 FileProtocol::~FileProtocol()
129 {
130 }
131 
132 #ifdef HAVE_POSIX_ACL
133 static 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 
142 int 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 
187 void 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 
217 void 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 
236 void 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 
277 void 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 
379 int 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 
396 void 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 
461 void 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 
490 void 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 
509 void 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 
523 void 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 
535 void 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(dest, dest_orig);
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 
751 QString 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 
764 QString 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 
777 bool 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 
859 void 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 
901 void 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 
1049 void 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 
1175 bool 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 
1198 bool 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 
1234 static 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 
1252 bool FileProtocol::isExtendedACL( acl_t acl )
1253 {
1254  return ( acl_equiv_mode( acl, 0 ) != 0 );
1255 }
1256 
1257 static 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.
1301 bool 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::unmount
void unmount(const QString &point)
Definition: file.cpp:1049
i18n
QString i18n(const char *text)
KIO::Overwrite
KSharedPtr
KIO::filesize_t
qulonglong filesize_t
readEntry
KAutostart::StartPhase readEntry(const KConfigGroup &group, const char *key, const KAutostart::StartPhase &aDefault)
KIO::ERR_DISK_FULL
kdebug.h
ioslave_defaults.h
kmimetype.h
kurl.h
KIO::UDSEntry::UDS_DEVICE_ID
KIO::UDSEntry
group
KIO::ERR_COULD_NOT_SEEK
KIO::UDSEntry::UDS_ACL_STRING
kmountpoint.h
KMountPoint::currentMountPoints
static List currentMountPoints(DetailsNeededFlags infoNeeded=BasicInfoNeeded)
KDE::mkdir
int mkdir(const QString &pathname, mode_t)
KIO::UDSEntry::insert
void insert(uint field, const QString &value)
FileProtocol::seek
virtual void seek(KIO::filesize_t offset)
Definition: file.cpp:509
kdirnotify.h
kconfig.h
KIO::ERR_CANNOT_DELETE
KIO::UDSEntry::UDS_DEFAULT_ACL_STRING
kshell.h
KIO::ERR_COULD_NOT_MKDIR
KIO::UDSEntry::UDS_FILE_TYPE
KIO::ERR_FILE_ALREADY_EXIST
KMountPoint::List::findByDevice
Ptr findByDevice(const QString &device) const
KGlobal::dirs
KStandardDirs * dirs()
KDE::stat
int stat(const QString &path, KDE_struct_stat *buf)
KDE::rename
int rename(const QString &in, const QString &out)
FileProtocol::special
virtual void special(const QByteArray &data)
Special commands supported by this slave: 1 - mount 2 - unmount.
Definition: file.cpp:859
KDE::chmod
int chmod(const QString &path, mode_t mode)
FileProtocol::read
virtual void read(KIO::filesize_t size)
Definition: file.cpp:461
KUrl::toLocalFile
QString toLocalFile(AdjustPathOption trailing=LeaveTrailingSlash) const
KIO::ERR_CANNOT_RENAME_PARTIAL
QString
KTemporaryFile
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
klocale.h
file.h
KIO::ERR_WRITE_ACCESS_DENIED
FileProtocol::mount
void mount(bool _ro, const char *_fstype, const QString &dev, const QString &point)
Definition: file.cpp:901
KUrl
config
KSharedConfigPtr config()
FileProtocol
Definition: file.h:46
kdemain
int kdemain(int argc, char **argv)
Definition: file.cpp:102
KDE::open
int open(const QString &pathname, int flags, mode_t mode)
KIO::DefaultFlags
kglobal.h
KIO::UDSEntry::UDS_USER
FileProtocol::FileProtocol
FileProtocol(const QByteArray &pool, const QByteArray &app)
Definition: file.cpp:123
KUrl::setProtocol
void setProtocol(const QString &proto)
KIO::UDSEntry::count
int count() const
FileProtocol::setModificationTime
virtual void setModificationTime(const KUrl &url, const QDateTime &mtime)
Definition: file.cpp:217
KIO::ERR_COULD_NOT_UNMOUNT
readLogFile
static QString readLogFile(const QByteArray &_filename)
Definition: file.cpp:1234
KIO::ERR_CANNOT_OPEN_FOR_WRITING
KIO::ERR_COULD_NOT_READ
KIO::SlaveBase
KIO::Resume
QStringList
KIO::ERR_IS_DIRECTORY
KIO::UDSEntry::UDS_ACCESS_TIME
KMountPoint::NeedRealDeviceName
FileProtocol::~FileProtocol
virtual ~FileProtocol()
Definition: file.cpp:128
KIO::ERR_DIR_ALREADY_EXIST
KIO::UDSEntry::UDS_INODE
KIO::UDSEntry::UDS_MODIFICATION_TIME
KIO::fileoffset_t
qlonglong fileoffset_t
KShell::quoteArg
QString quoteArg(const QString &arg)
DEFAULT_MINIMUM_KEEP_SIZE
#define DEFAULT_MINIMUM_KEEP_SIZE
ok
KGuiItem ok()
KDE::lstat
int lstat(const QString &path, KDE_struct_stat *buf)
KIO::ERR_ACCESS_DENIED
KGlobal::locale
KLocale * locale()
QDateTime
FileProtocol::write
virtual void write(const QByteArray &data)
Definition: file.cpp:490
ktemporaryfile.h
FileProtocol::pmount
bool pmount(const QString &dev)
Definition: file.cpp:1175
dir
QString dir(const QString &fileClass)
KIO::UDSEntry::UDS_ACCESS
access
int access(const QString &path, int mode)
kstandarddirs.h
KMountPoint::List::findByPath
Ptr findByPath(const QString &path) const
KIO::UDSEntry::UDS_NAME
KIO::UDSEntry::UDS_LINK_DEST
KIO::ERR_UNSUPPORTED_ACTION
KStandardDirs::findExe
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
FileProtocol::get
virtual void get(const KUrl &url)
Definition: file.cpp:277
MAX_IPC_SIZE
#define MAX_IPC_SIZE
Definition: file.cpp:94
KIO::UDSEntry::UDS_GROUP
kWarning
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
write_all
int write_all(int fd, const char *buf, size_t len)
Definition: file.cpp:379
KIO::ERR_CANNOT_OPEN_FOR_READING
FileProtocol::chmod
virtual void chmod(const KUrl &url, int permissions)
Definition: file.cpp:187
KIO::UDSEntry::UDS_EXTENDED_ACL
MNTTAB
#define MNTTAB
KIO::ERR_CANNOT_SETTIME
FileProtocol::pumount
bool pumount(const QString &point)
Definition: file.cpp:1198
FileProtocol::open
virtual void open(const KUrl &url, QIODevice::OpenMode mode)
Definition: file.cpp:396
KIO::ERR_DOES_NOT_EXIST
KIO::ERR_COULD_NOT_MOUNT
kcomponentdata.h
KUrl::isLocalFile
bool isLocalFile() const
FileProtocol::mkdir
virtual void mkdir(const KUrl &url, int permissions)
Definition: file.cpp:236
FileProtocol::put
virtual void put(const KUrl &url, int _mode, KIO::JobFlags _flags)
Definition: file.cpp:535
KDE::utime
int utime(const QString &filename, struct utimbuf *buf)
KIO::UDSEntry::UDS_SIZE
FileProtocol::close
virtual void close()
Definition: file.cpp:523
KMountPoint::SupportsChmod
KComponentData
KIO::ERR_COULD_NOT_WRITE
KIO::ERR_CANNOT_CHMOD
kconfiggroup.h
KIO::number
QString number(KIO::filesize_t size)
KDE_EXPORT
#define KDE_EXPORT
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:50:58 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



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