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

KIOSlave

  • kioslave
  • file
file_unix.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  Copyright (C) 2007 Christian Ehrlicher <ch.ehrlicher@gmx.de>
8 
9  This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Library General Public
11  License (LGPL) as published by the Free Software Foundation;
12  either version 2 of the License, or (at your option) any later
13  version.
14 
15  This library is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  Library General Public License for more details.
19 
20  You should have received a copy of the GNU Library General Public License
21  along with this library; see the file COPYING.LIB. If not, write to
22  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  Boston, MA 02110-1301, USA.
24 */
25 
26 #define QT_NO_CAST_FROM_ASCII
27 
28 #include "file.h"
29 
30 #include <config.h>
31 #include <config-kioslave-file.h>
32 
33 #include <QtCore/QFile>
34 
35 #include <kde_file.h>
36 #include <kdebug.h>
37 #include <kconfiggroup.h>
38 #include <kmountpoint.h>
39 
40 #include <dirent.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <grp.h>
44 #include <utime.h>
45 #include <pwd.h>
46 #include <stdlib.h>
47 
48 #if defined(HAVE_LIMITS_H)
49 #include <limits.h> // PATH_MAX
50 #endif
51 
52 //sendfile has different semantics in different platforms
53 #if defined HAVE_SENDFILE && defined Q_OS_LINUX
54 #define USE_SENDFILE 1
55 #endif
56 
57 #ifdef USE_SENDFILE
58 #include <sys/sendfile.h>
59 #endif
60 
61 namespace KDEPrivate
62 {
63 
64 struct CharArrayDeleter
65 {
66  CharArrayDeleter(char *b) : buf(b) {}
67  ~CharArrayDeleter() { free(buf); }
68  char *buf;
69 };
70 
71 }
72 
73 using namespace KIO;
74 
75 #define MAX_IPC_SIZE (1024*32)
76 
77 static bool
78 same_inode(const KDE_struct_stat &src, const KDE_struct_stat &dest)
79 {
80  if (src.st_ino == dest.st_ino &&
81  src.st_dev == dest.st_dev)
82  return true;
83 
84  return false;
85 }
86 
87 extern int write_all(int fd, const char *buf, size_t len);
88 
89 void FileProtocol::copy( const KUrl &srcUrl, const KUrl &destUrl,
90  int _mode, JobFlags _flags )
91 {
92  kDebug(7101) << "copy(): " << srcUrl << " -> " << destUrl << ", mode=" << _mode;
93 
94  const QString src = srcUrl.toLocalFile();
95  const QString dest = destUrl.toLocalFile();
96  QByteArray _src( QFile::encodeName(src));
97  QByteArray _dest( QFile::encodeName(dest));
98  KDE_struct_stat buff_src;
99 #ifdef HAVE_POSIX_ACL
100  acl_t acl;
101 #endif
102 
103  if ( KDE_stat( _src.data(), &buff_src ) == -1 ) {
104  if ( errno == EACCES )
105  error(KIO::ERR_ACCESS_DENIED, src);
106  else
107  error(KIO::ERR_DOES_NOT_EXIST, src);
108  return;
109  }
110 
111  if ( S_ISDIR( buff_src.st_mode ) ) {
112  error(KIO::ERR_IS_DIRECTORY, src);
113  return;
114  }
115  if ( S_ISFIFO( buff_src.st_mode ) || S_ISSOCK ( buff_src.st_mode ) ) {
116  error(KIO::ERR_CANNOT_OPEN_FOR_READING, src);
117  return;
118  }
119 
120  KDE_struct_stat buff_dest;
121  bool dest_exists = ( KDE_lstat( _dest.data(), &buff_dest ) != -1 );
122  if ( dest_exists )
123  {
124  if (S_ISDIR(buff_dest.st_mode))
125  {
126  error(KIO::ERR_DIR_ALREADY_EXIST, dest);
127  return;
128  }
129 
130  if ( same_inode( buff_dest, buff_src) )
131  {
132  error(KIO::ERR_IDENTICAL_FILES, dest);
133  return;
134  }
135 
136  if (!(_flags & KIO::Overwrite))
137  {
138  error(KIO::ERR_FILE_ALREADY_EXIST, dest);
139  return;
140  }
141 
142  // If the destination is a symlink and overwrite is TRUE,
143  // remove the symlink first to prevent the scenario where
144  // the symlink actually points to current source!
145  if ((_flags & KIO::Overwrite) && S_ISLNK(buff_dest.st_mode))
146  {
147  //kDebug(7101) << "copy(): LINK DESTINATION";
148  remove( _dest.data() );
149  }
150  }
151 
152  int src_fd = KDE_open( _src.data(), O_RDONLY);
153  if ( src_fd < 0 ) {
154  error(KIO::ERR_CANNOT_OPEN_FOR_READING, src);
155  return;
156  }
157 
158 #if HAVE_FADVISE
159  posix_fadvise(src_fd,0,0,POSIX_FADV_SEQUENTIAL);
160 #endif
161  // WABA: Make sure that we keep writing permissions ourselves,
162  // otherwise we can be in for a surprise on NFS.
163  mode_t initialMode;
164  if (_mode != -1)
165  initialMode = _mode | S_IWUSR;
166  else
167  initialMode = 0666;
168 
169  int dest_fd = KDE_open(_dest.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode);
170  if ( dest_fd < 0 ) {
171  kDebug(7101) << "###### COULD NOT WRITE " << dest;
172  if ( errno == EACCES ) {
173  error(KIO::ERR_WRITE_ACCESS_DENIED, dest);
174  } else {
175  error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest);
176  }
177  ::close(src_fd);
178  return;
179  }
180 
181 #if HAVE_FADVISE
182  posix_fadvise(dest_fd,0,0,POSIX_FADV_SEQUENTIAL);
183 #endif
184 
185 #ifdef HAVE_POSIX_ACL
186  acl = acl_get_fd(src_fd);
187  if ( acl && !isExtendedACL( acl ) ) {
188  kDebug(7101) << _dest.data() << " doesn't have extended ACL";
189  acl_free( acl );
190  acl = NULL;
191  }
192 #endif
193  totalSize( buff_src.st_size );
194 
195  KIO::filesize_t processed_size = 0;
196  char buffer[ MAX_IPC_SIZE ];
197  int n;
198 #ifdef USE_SENDFILE
199  bool use_sendfile=buff_src.st_size < 0x7FFFFFFF;
200 #endif
201  while( 1 )
202  {
203 #ifdef USE_SENDFILE
204  if (use_sendfile) {
205  off_t sf = processed_size;
206  n = KDE_sendfile( dest_fd, src_fd, &sf, MAX_IPC_SIZE );
207  processed_size = sf;
208  if ( n == -1 && ( errno == EINVAL || errno == ENOSYS ) ) { //not all filesystems support sendfile()
209  kDebug(7101) << "sendfile() not supported, falling back ";
210  use_sendfile = false;
211  }
212  }
213  if (!use_sendfile)
214 #endif
215  n = ::read( src_fd, buffer, MAX_IPC_SIZE );
216 
217  if (n == -1)
218  {
219  if (errno == EINTR)
220  continue;
221 #ifdef USE_SENDFILE
222  if ( use_sendfile ) {
223  kDebug(7101) << "sendfile() error:" << strerror(errno);
224  if ( errno == ENOSPC ) // disk full
225  {
226  error(KIO::ERR_DISK_FULL, dest);
227  remove( _dest.data() );
228  }
229  else {
230  error(KIO::ERR_SLAVE_DEFINED,
231  i18n("Cannot copy file from %1 to %2. (Errno: %3)",
232  src, dest, errno));
233  }
234  } else
235 #endif
236  error(KIO::ERR_COULD_NOT_READ, src);
237  ::close(src_fd);
238  ::close(dest_fd);
239 #ifdef HAVE_POSIX_ACL
240  if (acl) acl_free(acl);
241 #endif
242  return;
243  }
244  if (n == 0)
245  break; // Finished
246 #ifdef USE_SENDFILE
247  if ( !use_sendfile ) {
248 #endif
249  if (write_all( dest_fd, buffer, n))
250  {
251  ::close(src_fd);
252  ::close(dest_fd);
253 
254  if ( errno == ENOSPC ) // disk full
255  {
256  error(KIO::ERR_DISK_FULL, dest);
257  remove( _dest.data() );
258  }
259  else
260  {
261  kWarning(7101) << "Couldn't write[2]. Error:" << strerror(errno);
262  error(KIO::ERR_COULD_NOT_WRITE, dest);
263  }
264 #ifdef HAVE_POSIX_ACL
265  if (acl) acl_free(acl);
266 #endif
267  return;
268  }
269  processed_size += n;
270 #ifdef USE_SENDFILE
271  }
272 #endif
273  processedSize( processed_size );
274  }
275 
276  ::close( src_fd );
277 
278  if (::close( dest_fd))
279  {
280  kWarning(7101) << "Error when closing file descriptor[2]:" << strerror(errno);
281  error(KIO::ERR_COULD_NOT_WRITE, dest);
282 #ifdef HAVE_POSIX_ACL
283  if (acl) acl_free(acl);
284 #endif
285  return;
286  }
287 
288  // set final permissions
289  if ( _mode != -1 )
290  {
291  if ( (::chmod(_dest.data(), _mode) != 0)
292 #ifdef HAVE_POSIX_ACL
293  || (acl && acl_set_file(_dest.data(), ACL_TYPE_ACCESS, acl) != 0)
294 #endif
295  )
296  {
297  KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByPath(dest);
298  // Eat the error if the filesystem apparently doesn't support chmod.
299  if ( mp && mp->testFileSystemFlag( KMountPoint::SupportsChmod ) )
300  warning(i18n("Could not change permissions for\n%1", dest));
301  }
302  }
303 #ifdef HAVE_POSIX_ACL
304  if (acl) acl_free(acl);
305 #endif
306 
307  // copy access and modification time
308  struct utimbuf ut;
309  ut.actime = buff_src.st_atime;
310  ut.modtime = buff_src.st_mtime;
311  if ( ::utime( _dest.data(), &ut ) != 0 )
312  {
313  kWarning() << QString::fromLatin1("Couldn't preserve access and modification time for\n%1").arg(dest);
314  }
315 
316  processedSize( buff_src.st_size );
317  finished();
318 }
319 
320 void FileProtocol::listDir( const KUrl& url)
321 {
322  if (!url.isLocalFile()) {
323  KUrl redir(url);
324  redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb"));
325  redirection(redir);
326  kDebug(7101) << "redirecting to " << redir.url();
327  finished();
328  return;
329  }
330  const QString path(url.toLocalFile());
331  const QByteArray _path(QFile::encodeName(path));
332  DIR* dp = opendir(_path.data());
333  if ( dp == 0 ) {
334  switch (errno) {
335  case ENOENT:
336  error(KIO::ERR_DOES_NOT_EXIST, path);
337  return;
338  case ENOTDIR:
339  error(KIO::ERR_IS_FILE, path);
340  break;
341 #ifdef ENOMEDIUM
342  case ENOMEDIUM:
343  error(ERR_SLAVE_DEFINED,
344  i18n("No media in device for %1", path));
345  break;
346 #endif
347  default:
348  error(KIO::ERR_CANNOT_ENTER_DIRECTORY, path);
349  break;
350  }
351  return;
352  }
353 
354  const QString sDetails = metaData(QLatin1String("details"));
355  const int details = sDetails.isEmpty() ? 2 : sDetails.toInt();
356  //kDebug(7101) << "========= LIST " << url << "details=" << details << " =========";
357  UDSEntry entry;
358 
359 #ifndef HAVE_DIRENT_D_TYPE
360  KDE_struct_stat st;
361 #endif
362  // Don't make this a QStringList. The locale file name we get here
363  // should be passed intact to createUDSEntry to avoid problems with
364  // files where QFile::encodeName(QFile::decodeName(a)) != a.
365  QList<QByteArray> entryNames;
366  KDE_struct_dirent *ep;
367  if (details == 0) {
368  // Fast path (for recursive deletion, mostly)
369  // Simply emit the name and file type, nothing else.
370  while ( ( ep = KDE_readdir( dp ) ) != 0 ) {
371  entry.clear();
372  entry.insert(KIO::UDSEntry::UDS_NAME, QFile::decodeName(ep->d_name));
373 #ifdef HAVE_DIRENT_D_TYPE
374  entry.insert(KIO::UDSEntry::UDS_FILE_TYPE,
375  (ep->d_type & DT_DIR) ? S_IFDIR : S_IFREG );
376  const bool isSymLink = (ep->d_type & DT_LNK);
377 #else
378  // oops, no fast way, we need to stat (e.g. on Solaris)
379  if (KDE_lstat(ep->d_name, &st) == -1) {
380  continue; // how can stat fail?
381  }
382  entry.insert(KIO::UDSEntry::UDS_FILE_TYPE,
383  (S_ISDIR(st.st_mode)) ? S_IFDIR : S_IFREG );
384  const bool isSymLink = S_ISLNK(st.st_mode);
385 #endif
386  if (isSymLink) {
387  // for symlinks obey the UDSEntry contract and provide UDS_LINK_DEST
388  // even if we don't know the link dest (and DeleteJob doesn't care...)
389  entry.insert(KIO::UDSEntry::UDS_LINK_DEST, QLatin1String("Dummy Link Target"));
390  }
391  listEntry(entry, false);
392  }
393  closedir( dp );
394  listEntry( entry, true ); // ready
395  } else {
396  while ( ( ep = KDE_readdir( dp ) ) != 0 ) {
397  entryNames.append( ep->d_name );
398  }
399 
400  closedir( dp );
401  totalSize( entryNames.count() );
402 
403  /* set the current dir to the path to speed up
404  in not having to pass an absolute path.
405  We restore the path later to get out of the
406  path - the kernel wouldn't unmount or delete
407  directories we keep as active directory. And
408  as the slave runs in the background, it's hard
409  to see for the user what the problem would be */
410 #if !defined(PATH_MAX) && defined(__GLIBC__)
411  char *path_buffer = ::get_current_dir_name();
412  const KDEPrivate::CharArrayDeleter path_buffer_deleter(path_buffer);
413 #else
414  char path_buffer[PATH_MAX];
415  path_buffer[0] = '\0';
416  (void) getcwd(path_buffer, PATH_MAX - 1);
417 #endif
418  if ( chdir( _path.data() ) ) {
419  if (errno == EACCES)
420  error(ERR_ACCESS_DENIED, path);
421  else
422  error(ERR_CANNOT_ENTER_DIRECTORY, path);
423  finished();
424  }
425 
426  QList<QByteArray>::ConstIterator it = entryNames.constBegin();
427  QList<QByteArray>::ConstIterator end = entryNames.constEnd();
428  for (; it != end; ++it) {
429  entry.clear();
430  if ( createUDSEntry( QFile::decodeName(*it),
431  *it /* we can use the filename as relative path*/,
432  entry, details, true ) )
433  listEntry( entry, false);
434  }
435 
436  listEntry( entry, true ); // ready
437 
438  //kDebug(7101) << "============= COMPLETED LIST ============";
439 
440 #if !defined(PATH_MAX) && defined(__GLIBC__)
441  if (path_buffer)
442 #else
443  if (*path_buffer)
444 #endif
445  {
446  chdir(path_buffer);
447  }
448  }
449  finished();
450 }
451 
452 void FileProtocol::rename( const KUrl &srcUrl, const KUrl &destUrl,
453  KIO::JobFlags _flags )
454 {
455  char off_t_should_be_64_bits[sizeof(off_t) >= 8 ? 1 : -1]; (void) off_t_should_be_64_bits;
456  const QString src = srcUrl.toLocalFile();
457  const QString dest = destUrl.toLocalFile();
458  const QByteArray _src(QFile::encodeName(src));
459  const QByteArray _dest(QFile::encodeName(dest));
460  KDE_struct_stat buff_src;
461  if ( KDE_lstat( _src.data(), &buff_src ) == -1 ) {
462  if ( errno == EACCES )
463  error(KIO::ERR_ACCESS_DENIED, src);
464  else
465  error(KIO::ERR_DOES_NOT_EXIST, src);
466  return;
467  }
468 
469  KDE_struct_stat buff_dest;
470  // stat symlinks here (lstat, not stat), to avoid ERR_IDENTICAL_FILES when replacing symlink
471  // with its target (#169547)
472  bool dest_exists = ( KDE_lstat( _dest.data(), &buff_dest ) != -1 );
473  if ( dest_exists )
474  {
475  if (S_ISDIR(buff_dest.st_mode))
476  {
477  error(KIO::ERR_DIR_ALREADY_EXIST, dest);
478  return;
479  }
480 
481  if ( same_inode( buff_dest, buff_src) )
482  {
483  error(KIO::ERR_IDENTICAL_FILES, dest);
484  return;
485  }
486 
487  if (!(_flags & KIO::Overwrite))
488  {
489  error(KIO::ERR_FILE_ALREADY_EXIST, dest);
490  return;
491  }
492  }
493 
494  if ( KDE_rename( _src.data(), _dest.data()))
495  {
496  if (( errno == EACCES ) || (errno == EPERM)) {
497  error(KIO::ERR_ACCESS_DENIED, dest);
498  }
499  else if (errno == EXDEV) {
500  error(KIO::ERR_UNSUPPORTED_ACTION, QLatin1String("rename"));
501  }
502  else if (errno == EROFS) { // The file is on a read-only filesystem
503  error(KIO::ERR_CANNOT_DELETE, src);
504  }
505  else {
506  error(KIO::ERR_CANNOT_RENAME, src);
507  }
508  return;
509  }
510 
511  finished();
512 }
513 
514 void FileProtocol::symlink( const QString &target, const KUrl &destUrl, KIO::JobFlags flags )
515 {
516  const QString dest = destUrl.toLocalFile();
517  // Assume dest is local too (wouldn't be here otherwise)
518  if ( ::symlink( QFile::encodeName(target), QFile::encodeName(dest) ) == -1 )
519  {
520  // Does the destination already exist ?
521  if ( errno == EEXIST )
522  {
523  if ( (flags & KIO::Overwrite) )
524  {
525  // Try to delete the destination
526  if ( unlink( QFile::encodeName(dest) ) != 0 )
527  {
528  error(KIO::ERR_CANNOT_DELETE, dest);
529  return;
530  }
531  // Try again - this won't loop forever since unlink succeeded
532  symlink( target, destUrl, flags );
533  }
534  else
535  {
536  KDE_struct_stat buff_dest;
537  KDE_lstat( QFile::encodeName(dest), &buff_dest );
538  if (S_ISDIR(buff_dest.st_mode))
539  error(KIO::ERR_DIR_ALREADY_EXIST, dest);
540  else
541  error(KIO::ERR_FILE_ALREADY_EXIST, dest);
542  return;
543  }
544  }
545  else
546  {
547  // Some error occurred while we tried to symlink
548  error(KIO::ERR_CANNOT_SYMLINK, dest);
549  return;
550  }
551  }
552  finished();
553 }
554 
555 void FileProtocol::del(const KUrl& url, bool isfile)
556 {
557  const QString path = url.toLocalFile();
558  const QByteArray _path( QFile::encodeName(path));
559  /*****
560  * Delete files
561  *****/
562 
563  if (isfile) {
564  kDebug(7101) << "Deleting file "<< url;
565 
566  if ( unlink( _path.data() ) == -1 ) {
567  if ((errno == EACCES) || (errno == EPERM))
568  error(KIO::ERR_ACCESS_DENIED, path);
569  else if (errno == EISDIR)
570  error(KIO::ERR_IS_DIRECTORY, path);
571  else
572  error(KIO::ERR_CANNOT_DELETE, path);
573  return;
574  }
575  } else {
576 
577  /*****
578  * Delete empty directory
579  *****/
580 
581  kDebug( 7101 ) << "Deleting directory " << url.url();
582  if (metaData(QLatin1String("recurse")) == QLatin1String("true")) {
583  if (!deleteRecursive(path))
584  return;
585  }
586  if ( ::rmdir( _path.data() ) == -1 ) {
587  if ((errno == EACCES) || (errno == EPERM))
588  error(KIO::ERR_ACCESS_DENIED, path);
589  else {
590  kDebug( 7101 ) << "could not rmdir " << perror;
591  error(KIO::ERR_COULD_NOT_RMDIR, path);
592  return;
593  }
594  }
595  }
596 
597  finished();
598 }
599 
600 void FileProtocol::chown( const KUrl& url, const QString& owner, const QString& group )
601 {
602  const QString path = url.toLocalFile();
603  const QByteArray _path( QFile::encodeName(path) );
604  uid_t uid;
605  gid_t gid;
606 
607  // get uid from given owner
608  {
609  struct passwd *p = ::getpwnam(owner.toAscii());
610 
611  if ( ! p ) {
612  error( KIO::ERR_SLAVE_DEFINED,
613  i18n( "Could not get user id for given user name %1", owner ) );
614  return;
615  }
616 
617  uid = p->pw_uid;
618  }
619 
620  // get gid from given group
621  {
622  struct group *p = ::getgrnam(group.toAscii());
623 
624  if ( ! p ) {
625  error( KIO::ERR_SLAVE_DEFINED,
626  i18n( "Could not get group id for given group name %1", group ) );
627  return;
628  }
629 
630  gid = p->gr_gid;
631  }
632 
633  if ( ::chown(_path, uid, gid) == -1 ) {
634  switch ( errno ) {
635  case EPERM:
636  case EACCES:
637  error(KIO::ERR_ACCESS_DENIED, path);
638  break;
639  case ENOSPC:
640  error(KIO::ERR_DISK_FULL, path);
641  break;
642  default:
643  error(KIO::ERR_CANNOT_CHOWN, path);
644  }
645  } else
646  finished();
647 }
648 
649 void FileProtocol::stat( const KUrl & url )
650 {
651  if (!url.isLocalFile()) {
652  KUrl redir(url);
653  redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb"));
654  redirection(redir);
655  kDebug(7101) << "redirecting to " << redir.url();
656  finished();
657  return;
658  }
659 
660  /* directories may not have a slash at the end if
661  * we want to stat() them; it requires that we
662  * change into it .. which may not be allowed
663  * stat("/is/unaccessible") -> rwx------
664  * stat("/is/unaccessible/") -> EPERM H.Z.
665  * This is the reason for the -1
666  */
667  const QString path(url.path(KUrl::RemoveTrailingSlash));
668  const QByteArray _path( QFile::encodeName(path));
669  const QString sDetails = metaData(QLatin1String("details"));
670  const int details = sDetails.isEmpty() ? 2 : sDetails.toInt();
671 
672  UDSEntry entry;
673  if ( !createUDSEntry( url.fileName(), _path, entry, details, true /*with acls*/ ) )
674  {
675  error(KIO::ERR_DOES_NOT_EXIST, path);
676  return;
677  }
678 #if 0
679 
680  MetaData::iterator it1 = mOutgoingMetaData.begin();
681  for ( ; it1 != mOutgoingMetaData.end(); it1++ ) {
682  kDebug(7101) << it1.key() << " = " << it1.data();
683  }
685 #endif
686  statEntry( entry );
687 
688  finished();
689 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Fri Nov 16 2012 15:17:54 by doxygen 1.8.1 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.8.5 API Reference

Skip menu "kdelibs-4.8.5 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