26 #define QT_NO_CAST_FROM_ASCII
31 #include <config-kioslave-file.h>
33 #include <QtCore/QFile>
48 #if defined(HAVE_LIMITS_H)
53 #if defined HAVE_SENDFILE && defined Q_OS_LINUX
54 #define USE_SENDFILE 1
58 #include <sys/sendfile.h>
64 struct CharArrayDeleter
66 CharArrayDeleter(
char *b) : buf(b) {}
67 ~CharArrayDeleter() { free(buf); }
75 #define MAX_IPC_SIZE (1024*32)
78 same_inode(
const KDE_struct_stat &src,
const KDE_struct_stat &dest)
80 if (src.st_ino == dest.st_ino &&
81 src.st_dev == dest.st_dev)
87 extern int write_all(
int fd,
const char *buf,
size_t len);
90 int _mode, JobFlags _flags )
92 kDebug(7101) <<
"copy(): " << srcUrl <<
" -> " << destUrl <<
", mode=" << _mode;
96 QByteArray _src( QFile::encodeName(src));
97 QByteArray _dest( QFile::encodeName(dest));
98 KDE_struct_stat buff_src;
103 if ( KDE_stat( _src.data(), &buff_src ) == -1 ) {
104 if ( errno == EACCES )
111 if ( S_ISDIR( buff_src.st_mode ) ) {
115 if ( S_ISFIFO( buff_src.st_mode ) || S_ISSOCK ( buff_src.st_mode ) ) {
120 KDE_struct_stat buff_dest;
121 bool dest_exists = ( KDE_lstat( _dest.data(), &buff_dest ) != -1 );
124 if (S_ISDIR(buff_dest.st_mode))
145 if ((_flags & KIO::Overwrite) && S_ISLNK(buff_dest.st_mode))
148 remove( _dest.data() );
152 int src_fd = KDE_open( _src.data(), O_RDONLY);
159 posix_fadvise(src_fd,0,0,POSIX_FADV_SEQUENTIAL);
165 initialMode = _mode | S_IWUSR;
169 int dest_fd = KDE_open(_dest.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode);
171 kDebug(7101) <<
"###### COULD NOT WRITE " << dest;
172 if ( errno == EACCES ) {
182 posix_fadvise(dest_fd,0,0,POSIX_FADV_SEQUENTIAL);
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";
193 totalSize( buff_src.st_size );
199 bool use_sendfile=buff_src.st_size < 0x7FFFFFFF;
205 off_t sf = processed_size;
208 if ( n == -1 && ( errno == EINVAL || errno == ENOSYS ) ) {
209 kDebug(7101) <<
"sendfile() not supported, falling back ";
210 use_sendfile =
false;
222 if ( use_sendfile ) {
223 kDebug(7101) <<
"sendfile() error:" << strerror(errno);
224 if ( errno == ENOSPC )
227 remove( _dest.data() );
231 i18n(
"Cannot copy file from %1 to %2. (Errno: %3)",
239 #ifdef HAVE_POSIX_ACL
240 if (acl) acl_free(acl);
247 if ( !use_sendfile ) {
254 if ( errno == ENOSPC )
257 remove( _dest.data() );
261 kWarning(7101) <<
"Couldn't write[2]. Error:" << strerror(errno);
264 #ifdef HAVE_POSIX_ACL
265 if (acl) acl_free(acl);
273 processedSize( processed_size );
278 if (::
close( dest_fd))
280 kWarning(7101) <<
"Error when closing file descriptor[2]:" << strerror(errno);
282 #ifdef HAVE_POSIX_ACL
283 if (acl) acl_free(acl);
291 if ( (::
chmod(_dest.data(), _mode) != 0)
292 #ifdef HAVE_POSIX_ACL
293 || (acl && acl_set_file(_dest.data(), ACL_TYPE_ACCESS, acl) != 0)
300 warning(
i18n(
"Could not change permissions for\n%1", dest));
303 #ifdef HAVE_POSIX_ACL
304 if (acl) acl_free(acl);
309 ut.actime = buff_src.st_atime;
310 ut.modtime = buff_src.st_mtime;
311 if ( ::
utime( _dest.data(), &ut ) != 0 )
313 kWarning() << QString::fromLatin1(
"Couldn't preserve access and modification time for\n%1").arg(dest);
316 processedSize( buff_src.st_size );
326 kDebug(7101) <<
"redirecting to " << redir.
url();
331 const QByteArray _path(QFile::encodeName(path));
332 DIR* dp = opendir(_path.data());
344 i18n(
"No media in device for %1", path));
354 const QString sDetails = metaData(QLatin1String(
"details"));
355 const int details = sDetails.isEmpty() ? 2 : sDetails.toInt();
359 #ifndef HAVE_DIRENT_D_TYPE
365 QList<QByteArray> entryNames;
366 KDE_struct_dirent *ep;
370 while ( ( ep = KDE_readdir( dp ) ) != 0 ) {
373 #ifdef HAVE_DIRENT_D_TYPE
375 (ep->d_type & DT_DIR) ? S_IFDIR : S_IFREG );
376 const bool isSymLink = (ep->d_type & DT_LNK);
379 if (KDE_lstat(ep->d_name, &st) == -1) {
383 (S_ISDIR(st.st_mode)) ? S_IFDIR : S_IFREG );
384 const bool isSymLink = S_ISLNK(st.st_mode);
391 listEntry(entry,
false);
394 listEntry( entry,
true );
396 while ( ( ep = KDE_readdir( dp ) ) != 0 ) {
397 entryNames.append( ep->d_name );
401 totalSize( entryNames.count() );
410 #if !defined(PATH_MAX) && defined(__GLIBC__)
411 char *path_buffer = ::get_current_dir_name();
412 const KDEPrivate::CharArrayDeleter path_buffer_deleter(path_buffer);
414 char path_buffer[PATH_MAX];
415 path_buffer[0] =
'\0';
416 (void) getcwd(path_buffer, PATH_MAX - 1);
418 if ( chdir( _path.data() ) ) {
426 QList<QByteArray>::ConstIterator it = entryNames.constBegin();
427 QList<QByteArray>::ConstIterator
end = entryNames.constEnd();
428 for (; it != end; ++it) {
430 if ( createUDSEntry( QFile::decodeName(*it),
432 entry, details,
true ) )
433 listEntry( entry,
false);
436 listEntry( entry,
true );
440 #if !defined(PATH_MAX) && defined(__GLIBC__)
453 KIO::JobFlags _flags )
455 char off_t_should_be_64_bits[
sizeof(off_t) >= 8 ? 1 : -1]; (void) off_t_should_be_64_bits;
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 )
469 KDE_struct_stat buff_dest;
472 bool dest_exists = ( KDE_lstat( _dest.data(), &buff_dest ) != -1 );
475 if (S_ISDIR(buff_dest.st_mode))
494 if ( KDE_rename( _src.data(), _dest.data()))
496 if (( errno == EACCES ) || (errno == EPERM)) {
499 else if (errno == EXDEV) {
502 else if (errno == EROFS) {
518 if ( ::
symlink( QFile::encodeName(target), QFile::encodeName(dest) ) == -1 )
521 if ( errno == EEXIST )
526 if ( unlink( QFile::encodeName(dest) ) != 0 )
532 symlink( target, destUrl, flags );
536 KDE_struct_stat buff_dest;
537 KDE_lstat( QFile::encodeName(dest), &buff_dest );
538 if (S_ISDIR(buff_dest.st_mode))
558 const QByteArray _path( QFile::encodeName(path));
564 kDebug(7101) <<
"Deleting file "<< url;
566 if ( unlink( _path.data() ) == -1 ) {
567 if ((errno == EACCES) || (errno == EPERM))
569 else if (errno == EISDIR)
581 kDebug( 7101 ) <<
"Deleting directory " << url.
url();
582 if (metaData(QLatin1String(
"recurse")) == QLatin1String(
"true")) {
583 if (!deleteRecursive(path))
586 if ( ::
rmdir( _path.data() ) == -1 ) {
587 if ((errno == EACCES) || (errno == EPERM))
603 const QByteArray _path( QFile::encodeName(path) );
609 struct passwd *p = ::getpwnam(owner.toAscii());
613 i18n(
"Could not get user id for given user name %1", owner ) );
622 struct group *p = ::getgrnam(group.toAscii());
626 i18n(
"Could not get group id for given group name %1", group ) );
633 if ( ::
chown(_path, uid, gid) == -1 ) {
655 kDebug(7101) <<
"redirecting to " << redir.
url();
668 const QByteArray _path( QFile::encodeName(path));
669 const QString sDetails = metaData(QLatin1String(
"details"));
670 const int details = sDetails.isEmpty() ? 2 : sDetails.toInt();
673 if ( !createUDSEntry( url.
fileName(), _path, entry, details,
true ) )
680 MetaData::iterator it1 = mOutgoingMetaData.begin();
681 for ( ; it1 != mOutgoingMetaData.end(); it1++ ) {
682 kDebug(7101) << it1.key() <<
" = " << it1.data();