26 #define QT_NO_CAST_FROM_ASCII
31 #include <config-kioslave-file.h>
33 #include <QtCore/QFile>
34 #include <QtCore/QDir>
49 #if defined(HAVE_LIMITS_H)
54 #if defined HAVE_SENDFILE && defined Q_OS_LINUX
55 #define USE_SENDFILE 1
59 #include <sys/sendfile.h>
64 #define MAX_IPC_SIZE (1024*32)
67 same_inode(
const KDE_struct_stat &src,
const KDE_struct_stat &dest)
69 if (src.st_ino == dest.st_ino &&
70 src.st_dev == dest.st_dev)
76 extern int write_all(
int fd,
const char *buf,
size_t len);
79 int _mode, JobFlags _flags )
81 kDebug(7101) <<
"copy(): " << srcUrl <<
" -> " << destUrl <<
", mode=" << _mode;
85 QByteArray _src( QFile::encodeName(src));
86 QByteArray _dest( QFile::encodeName(dest));
87 KDE_struct_stat buff_src;
92 if ( KDE_stat( _src.data(), &buff_src ) == -1 ) {
93 if ( errno == EACCES )
94 error(KIO::ERR_ACCESS_DENIED, src);
96 error(KIO::ERR_DOES_NOT_EXIST, src);
100 if ( S_ISDIR( buff_src.st_mode ) ) {
101 error(KIO::ERR_IS_DIRECTORY, src);
104 if ( S_ISFIFO( buff_src.st_mode ) || S_ISSOCK ( buff_src.st_mode ) ) {
105 error(KIO::ERR_CANNOT_OPEN_FOR_READING, src);
109 KDE_struct_stat buff_dest;
110 bool dest_exists = ( KDE_lstat( _dest.data(), &buff_dest ) != -1 );
113 if (S_ISDIR(buff_dest.st_mode))
115 error(KIO::ERR_DIR_ALREADY_EXIST, dest);
121 error(KIO::ERR_IDENTICAL_FILES, dest);
125 if (!(_flags & KIO::Overwrite))
127 error(KIO::ERR_FILE_ALREADY_EXIST, dest);
134 if ((_flags & KIO::Overwrite) && S_ISLNK(buff_dest.st_mode))
137 remove( _dest.data() );
141 int src_fd = KDE_open( _src.data(), O_RDONLY);
143 error(KIO::ERR_CANNOT_OPEN_FOR_READING, src);
148 posix_fadvise(src_fd,0,0,POSIX_FADV_SEQUENTIAL);
154 initialMode = _mode | S_IWUSR;
158 int dest_fd = KDE_open(_dest.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode);
160 kDebug(7101) <<
"###### COULD NOT WRITE " << dest;
161 if ( errno == EACCES ) {
162 error(KIO::ERR_WRITE_ACCESS_DENIED, dest);
164 error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest);
171 posix_fadvise(dest_fd,0,0,POSIX_FADV_SEQUENTIAL);
174 #ifdef HAVE_POSIX_ACL
175 acl = acl_get_fd(src_fd);
176 if ( acl && !isExtendedACL( acl ) ) {
177 kDebug(7101) << _dest.data() <<
" doesn't have extended ACL";
182 totalSize( buff_src.st_size );
184 KIO::filesize_t processed_size = 0;
188 bool use_sendfile=buff_src.st_size < 0x7FFFFFFF;
194 off_t sf = processed_size;
197 if ( n == -1 && ( errno == EINVAL || errno == ENOSYS ) ) {
198 kDebug(7101) <<
"sendfile() not supported, falling back ";
199 use_sendfile =
false;
211 if ( use_sendfile ) {
212 kDebug(7101) <<
"sendfile() error:" << strerror(errno);
213 if ( errno == ENOSPC )
215 error(KIO::ERR_DISK_FULL, dest);
216 remove( _dest.data() );
219 error(KIO::ERR_SLAVE_DEFINED,
220 i18n(
"Cannot copy file from %1 to %2. (Errno: %3)",
225 error(KIO::ERR_COULD_NOT_READ, src);
228 #ifdef HAVE_POSIX_ACL
229 if (acl) acl_free(acl);
236 if ( !use_sendfile ) {
243 if ( errno == ENOSPC )
245 error(KIO::ERR_DISK_FULL, dest);
246 remove( _dest.data() );
250 kWarning(7101) <<
"Couldn't write[2]. Error:" << strerror(errno);
251 error(KIO::ERR_COULD_NOT_WRITE, dest);
253 #ifdef HAVE_POSIX_ACL
254 if (acl) acl_free(acl);
262 processedSize( processed_size );
267 if (::
close( dest_fd))
269 kWarning(7101) <<
"Error when closing file descriptor[2]:" << strerror(errno);
270 error(KIO::ERR_COULD_NOT_WRITE, dest);
271 #ifdef HAVE_POSIX_ACL
272 if (acl) acl_free(acl);
280 if ( (::
chmod(_dest.data(), _mode) != 0)
281 #ifdef HAVE_POSIX_ACL
282 || (acl && acl_set_file(_dest.data(), ACL_TYPE_ACCESS, acl) != 0)
289 warning(
i18n(
"Could not change permissions for\n%1", dest));
292 #ifdef HAVE_POSIX_ACL
293 if (acl) acl_free(acl);
298 ut.actime = buff_src.st_atime;
299 ut.modtime = buff_src.st_mtime;
300 if ( ::
utime( _dest.data(), &ut ) != 0 )
302 kWarning() << QString::fromLatin1(
"Couldn't preserve access and modification time for\n%1").arg(dest);
305 processedSize( buff_src.st_size );
315 kDebug(7101) <<
"redirecting to " << redir.
url();
320 const QByteArray _path(QFile::encodeName(path));
321 DIR* dp = opendir(_path.data());
325 error(KIO::ERR_DOES_NOT_EXIST, path);
328 error(KIO::ERR_IS_FILE, path);
333 i18n(
"No media in device for %1", path));
337 error(KIO::ERR_CANNOT_ENTER_DIRECTORY, path);
350 const QString pathBuffer(QDir::currentPath());
351 if (!QDir::setCurrent(path)) {
357 const QString sDetails = metaData(QLatin1String(
"details"));
358 const int details = sDetails.isEmpty() ? 2 : sDetails.toInt();
362 #ifndef HAVE_DIRENT_D_TYPE
365 KDE_struct_dirent *ep;
366 while ((ep = KDE_readdir(dp)) != 0 ) {
369 const QString filename = QFile::decodeName(ep->d_name);
383 #ifdef HAVE_DIRENT_D_TYPE
385 (ep->d_type & DT_DIR) ? S_IFDIR : S_IFREG );
386 const bool isSymLink = (ep->d_type & DT_LNK);
389 if (KDE_lstat(ep->d_name, &st) == -1) {
393 (S_ISDIR(st.st_mode)) ? S_IFDIR : S_IFREG );
394 const bool isSymLink = S_ISLNK(st.st_mode);
401 listEntry(entry,
false);
404 if (createUDSEntry(filename, QByteArray(ep->d_name), entry, details,
true)) {
405 listEntry(entry,
false);
411 listEntry(entry,
true);
414 QDir::setCurrent(pathBuffer);
420 KIO::JobFlags _flags )
422 char off_t_should_be_64_bits[
sizeof(off_t) >= 8 ? 1 : -1]; (void) off_t_should_be_64_bits;
425 const QByteArray _src(QFile::encodeName(src));
426 const QByteArray _dest(QFile::encodeName(dest));
427 KDE_struct_stat buff_src;
428 if ( KDE_lstat( _src.data(), &buff_src ) == -1 ) {
429 if ( errno == EACCES )
430 error(KIO::ERR_ACCESS_DENIED, src);
432 error(KIO::ERR_DOES_NOT_EXIST, src);
436 KDE_struct_stat buff_dest;
439 bool dest_exists = ( KDE_lstat( _dest.data(), &buff_dest ) != -1 );
442 if (S_ISDIR(buff_dest.st_mode))
444 error(KIO::ERR_DIR_ALREADY_EXIST, dest);
450 error(KIO::ERR_IDENTICAL_FILES, dest);
454 if (!(_flags & KIO::Overwrite))
456 error(KIO::ERR_FILE_ALREADY_EXIST, dest);
461 if ( KDE_rename( _src.data(), _dest.data()))
463 if (( errno == EACCES ) || (errno == EPERM)) {
464 error(KIO::ERR_ACCESS_DENIED, dest);
466 else if (errno == EXDEV) {
467 error(KIO::ERR_UNSUPPORTED_ACTION, QLatin1String(
"rename"));
469 else if (errno == EROFS) {
470 error(KIO::ERR_CANNOT_DELETE, src);
473 error(KIO::ERR_CANNOT_RENAME, src);
485 if ( ::
symlink( QFile::encodeName(target), QFile::encodeName(dest) ) == -1 )
488 if ( errno == EEXIST )
490 if ( (flags & KIO::Overwrite) )
493 if ( unlink( QFile::encodeName(dest) ) != 0 )
495 error(KIO::ERR_CANNOT_DELETE, dest);
499 symlink( target, destUrl, flags );
503 KDE_struct_stat buff_dest;
504 if (KDE_lstat(QFile::encodeName(dest), &buff_dest) == 0 && S_ISDIR(buff_dest.st_mode))
505 error(KIO::ERR_DIR_ALREADY_EXIST, dest);
507 error(KIO::ERR_FILE_ALREADY_EXIST, dest);
514 error(KIO::ERR_CANNOT_SYMLINK, dest);
524 const QByteArray _path( QFile::encodeName(path));
530 kDebug(7101) <<
"Deleting file "<< url;
532 if ( unlink( _path.data() ) == -1 ) {
533 if ((errno == EACCES) || (errno == EPERM))
534 error(KIO::ERR_ACCESS_DENIED, path);
535 else if (errno == EISDIR)
536 error(KIO::ERR_IS_DIRECTORY, path);
538 error(KIO::ERR_CANNOT_DELETE, path);
547 kDebug( 7101 ) <<
"Deleting directory " << url.
url();
548 if (metaData(QLatin1String(
"recurse")) == QLatin1String(
"true")) {
549 if (!deleteRecursive(path))
552 if ( ::
rmdir( _path.data() ) == -1 ) {
553 if ((errno == EACCES) || (errno == EPERM))
554 error(KIO::ERR_ACCESS_DENIED, path);
557 error(KIO::ERR_COULD_NOT_RMDIR, path);
569 const QByteArray _path( QFile::encodeName(path) );
575 struct passwd *p = ::getpwnam(owner.toLatin1());
578 error( KIO::ERR_SLAVE_DEFINED,
579 i18n(
"Could not get user id for given user name %1", owner ) );
588 struct group *p = ::getgrnam(group.toLatin1());
591 error( KIO::ERR_SLAVE_DEFINED,
592 i18n(
"Could not get group id for given group name %1", group ) );
599 if ( ::
chown(_path, uid, gid) == -1 ) {
603 error(KIO::ERR_ACCESS_DENIED, path);
606 error(KIO::ERR_DISK_FULL, path);
609 error(KIO::ERR_CANNOT_CHOWN, path);
621 kDebug(7101) <<
"redirecting to " << redir.
url();
634 const QByteArray _path( QFile::encodeName(path));
635 const QString sDetails = metaData(QLatin1String(
"details"));
636 const int details = sDetails.isEmpty() ? 2 : sDetails.toInt();
639 if ( !createUDSEntry( url.
fileName(), _path, entry, details,
true ) )
641 error(KIO::ERR_DOES_NOT_EXIST, path);
646 MetaData::iterator it1 = mOutgoingMetaData.begin();
647 for ( ; it1 != mOutgoingMetaData.end(); it1++ ) {
648 kDebug(7101) << it1.key() <<
" = " << it1.data();