[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-core-devel
Subject: Fwd: Re: 64 bit file support
From: Waldo Bastian <bastian () kde ! org>
Date: 2001-08-10 18:53:56
[Download RAW message or body]
Hiya,
One of the things todo for KDE 3.0 is to get 64-bit file support working. You
might want to read the following URL in order to understand the problem.
http://ftp.sas.com/standards/large.file/x_open.20Mar96.html
It seems that since we can't control the way in which either Qt, other libs
or applications are being compiled we will need to use the "Transitional
Extensions".
I haven't tried it yet but I hope that we can circumvent this define mess
that Jeff talks about. I'm sure that after all the problems with X-headers
the glibc-developers wouldn't be that stupid.
As far as KDE's internal interfaces goes, I think that we should start to use
"long long" in the interfaces that need it. Maybe we can add a
KIO::filesize_t typedef so that we have a central place to change it to
something else.
Cheers,
Waldo
---------- Forwarded Message ----------
Subject: Re: 64 bit file support
Date: Mon, 6 Aug 2001 14:53:46 -0400
From: Jeff Woods <Jeff.Woods@ChoicePointPRG.net>
To: Waldo Bastian <bastian@kde.org>
On Wednesday 25 July 2001 02:56 pm, you wrote:
> There are various problems with 64 bit file-sizes, one of them being that
> our APIs don't support 64 bits. We hope to fix that in KDE 3.0. Your
> experiences will be usefull in that regard so that we know what needs
> fixing.
We finally got 64 files partially supported. Basically, we replaced the
stat's and lstat's in kio/kfileitem.cpp and kio/file/file.cc with stat64 and
lstat64. This allows files with sizes greater than 4 GB to be displayed in
the file browser (which was our greatest concern). The application we've
been working with already used 64 bit access routines where necessary.
This solution won't work under Linux, though. Linux headers define "struct
stat" based on the value of _FILE_OFFSET_BITS. If you place the line
"#define _FILE_OFFSET_BITS 64" prior to any #include's in your source, you
get the 64 bit version, otherwise you get the 32 bit version. An unfortunate
side effect of this is that all system calls, such as open and truncate, get
a #define like this:
#define open open64
#define truncate truncate64
This caused problems with some QT member functions which had the same name as
a system call. For example, QString::truncate() was renamed
QString::truncate64(), which did not resolve against the QT dynamic library.
We were able to get away with this since Solaris defines a seperate "struct
stat64" for use with stat64 and lstat64. We just surrounded our changes with
#ifdef sun ... #endif statements to keep the builds clean.
As you're aware, there are many more changes which are necessary. Even
though we are able to list the file, we do not get the correct file size.
This would require a number of internal changes.
I've attached the changed files (my reason for not posting to the developer
list).
Jeff Woods
-------------------------------------------------------
--
KDE 2.2: We deliver.
["kfileitem.cpp" (text/x-c++)]
/* This file is part of the KDE project
Copyright (C) 1999 David Faure <faure@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
// $Id: kfileitem.cpp,v 1.89 2001/02/10 12:58:21 hausmann Exp $
#include <sys/time.h>
#include <pwd.h>
#include <grp.h>
#include <sys/types.h>
#include <assert.h>
#include <unistd.h>
#include "kfileitem.h"
#include <qdir.h>
#include <qfile.h>
#include <kglobal.h>
#include <kdebug.h>
#include <klocale.h>
#include <kmimetype.h>
#include <krun.h>
#include <errno.h>
extern int errno;
class KFileItem::KFileItemPrivate
{
public:
KFileItemPrivate() { bMimeTypeKnown = false; }
// For special case like link to dirs over FTP
QString m_guessedMimeType;
bool bMimeTypeKnown;
};
KFileItem::KFileItem( const KIO::UDSEntry& _entry, const KURL& _url,
bool _determineMimeTypeOnDemand, bool _urlIsDirectory ) :
m_entry( _entry ),
m_url( _url ),
m_bIsLocalURL( _url.isLocalFile() ),
m_fileMode( (mode_t)-1 ),
m_permissions( (mode_t)-1 ),
m_bLink( false ),
m_pMimeType( 0 ),
m_bMarked( false ),
d(new KFileItemPrivate)
{
bool UDS_URL_seen = false;
// extract the mode and the filename from the KIO::UDS Entry
KIO::UDSEntry::ConstIterator it = m_entry.begin();
for( ; it != m_entry.end(); it++ ) {
switch ((*it).m_uds) {
case KIO::UDS_FILE_TYPE:
m_fileMode = (mode_t)((*it).m_long);
break;
case KIO::UDS_ACCESS:
m_permissions = (mode_t)((*it).m_long);
break;
case KIO::UDS_USER:
m_user = ((*it).m_str);
break;
case KIO::UDS_GROUP:
m_group = ((*it).m_str);
break;
case KIO::UDS_NAME:
m_strName = (*it).m_str;
m_strText = KIO::decodeFileName( m_strName );
break;
case KIO::UDS_URL:
UDS_URL_seen = true;
m_url = KURL((*it).m_str);
break;
case KIO::UDS_MIME_TYPE:
m_pMimeType = KMimeType::mimeType((*it).m_str);
break;
case KIO::UDS_GUESSED_MIME_TYPE:
d->m_guessedMimeType = (*it).m_str;
break;
case KIO::UDS_LINK_DEST:
m_bLink = !(*it).m_str.isEmpty(); // we don't store the link dest
break;
}
}
// avoid creating these QStrings again and again
static const QString& dot = KGlobal::staticQString(".");
if ( _urlIsDirectory && !UDS_URL_seen && !m_strName.isEmpty() && m_strName != dot )
m_url.addPath( m_strName );
init( _determineMimeTypeOnDemand );
}
KFileItem::KFileItem( mode_t _mode, mode_t _permissions, const KURL& _url, bool \
_determineMimeTypeOnDemand ) : m_entry(), // warning !
m_url( _url ),
m_bIsLocalURL( _url.isLocalFile() ),
m_strName( _url.fileName() ),
m_strText( KIO::decodeFileName( m_strName ) ),
m_fileMode ( _mode ),
m_permissions( _permissions ),
m_bLink( false ),
m_bMarked( false ),
d(new KFileItemPrivate)
{
init( _determineMimeTypeOnDemand );
}
KFileItem::KFileItem( const KURL &url, const QString &mimeType, mode_t mode )
> m_url( url ),
m_bIsLocalURL( url.isLocalFile() ),
m_strName( url.fileName() ),
m_strText( KIO::decodeFileName( m_strName ) ),
m_fileMode( mode ),
m_permissions( 0 ),
m_bLink( false ),
m_bMarked( false ),
d(new KFileItemPrivate)
{
m_pMimeType = KMimeType::mimeType( mimeType );
init( false );
}
KFileItem::KFileItem( const KFileItem & item ) :
d(new KFileItemPrivate)
{
assign( item );
}
KFileItem::~KFileItem()
{
delete d;
}
void KFileItem::init( bool _determineMimeTypeOnDemand )
{
// determine mode and/or permissions if unknown
if ( m_fileMode == (mode_t) -1 || m_permissions == (mode_t) -1 )
{
mode_t mode = 0;
if ( m_url.isLocalFile() )
{
/* directories may not have a slash at the end if
* we want to stat() them; it requires that we
* change into it .. which may not be allowed
* stat("/is/unaccessible") -> rwx------
* stat("/is/unaccessible/") -> EPERM H.Z.
* This is the reason for the -1
*/
QCString path = QFile::encodeName(m_url.path( -1 ));
#ifdef sun
struct stat64 buf;
if ( lstat64( path.data(), &buf ) == 0 )
#else
struct stat buf;
if ( lstat( path.data(), &buf ) == 0 )
#endif
{
mode = buf.st_mode;
if ( S_ISLNK( mode ) )
{
m_bLink = true;
#ifdef sun
if ( stat64(path.data(), &buf) == 0 )
#else
if ( stat( path.data(), &buf) == 0 )
#endif
mode = buf.st_mode;
else // link pointing to nowhere (see kio/file/file.cc)
mode = (S_IFMT-1) | S_IRWXU | S_IRWXG | S_IRWXO;
}
}
}
if ( m_fileMode == (mode_t) -1 )
m_fileMode = mode & S_IFMT; // extract file type
if ( m_permissions == (mode_t) -1 )
m_permissions = mode & 07777; // extract permissions
}
// determine the mimetype
if (!m_pMimeType )
{
m_pMimeType = KMimeType::findByURL( m_url, m_fileMode, m_bIsLocalURL,
// use fast mode if not mimetype on demand
_determineMimeTypeOnDemand );
// if we didn't use fast mode, or if we got a result, then this is the mimetype
// otherwise, determineMimeType will be able to do better.
d->bMimeTypeKnown = (!_determineMimeTypeOnDemand) || (m_pMimeType->name() != \
KMimeType::defaultMimeType()); }
}
void KFileItem::refresh()
{
m_fileMode = (mode_t)-1;
m_permissions = (mode_t)-1;
m_user = QString::null;
m_group = QString::null;
// Basically, we can't trust any information we got while listing.
// Everything could have changed...
// Clearing m_entry makes it possible to detect changes in the size of the file,
// the time information, etc.
m_entry = KIO::UDSEntry();
init( false );
}
void KFileItem::refreshMimeType()
{
m_pMimeType = 0L;
init( false ); // Will determine the mimetype
}
void KFileItem::setURL( const KURL &url )
{
m_url = url;
m_strName = url.fileName();
m_strText = KIO::decodeFileName( m_strName );
}
QString KFileItem::linkDest() const
{
// Extract it from the KIO::UDSEntry
KIO::UDSEntry::ConstIterator it = m_entry.begin();
for( ; it != m_entry.end(); it++ )
if ( (*it).m_uds == KIO::UDS_LINK_DEST )
return (*it).m_str;
// If not in the KIO::UDSEntry, or if UDSEntry empty, use readlink() [if local URL]
if ( m_bIsLocalURL )
{
char buf[1000];
int n = readlink( QFile::encodeName(m_url.path( -1 )), buf, 1000 );
if ( n != -1 )
{
buf[ n ] = 0;
return QString::fromLocal8Bit( buf );
}
}
return QString::null;
}
long KFileItem::size() const
{
// Extract it from the KIO::UDSEntry
KIO::UDSEntry::ConstIterator it = m_entry.begin();
for( ; it != m_entry.end(); it++ )
if ( (*it).m_uds == KIO::UDS_SIZE )
return (*it).m_long;
// If not in the KIO::UDSEntry, or if UDSEntry empty, use stat() [if local URL]
if ( m_bIsLocalURL )
{
#ifdef sun
struct stat64 buf;
stat64( QFile::encodeName(m_url.path( -1 )), &buf );
#else
struct stat buf;
stat( QFile::encodeName(m_url.path( -1 )), &buf );
#endif
return buf.st_size;
}
return 0L;
}
time_t KFileItem::time( unsigned int which ) const
{
// Extract it from the KIO::UDSEntry
KIO::UDSEntry::ConstIterator it = m_entry.begin();
for( ; it != m_entry.end(); it++ )
if ( (*it).m_uds == which )
return static_cast<time_t>((*it).m_long);
// If not in the KIO::UDSEntry, or if UDSEntry empty, use stat() [if local URL]
if ( m_bIsLocalURL )
{
#ifdef sun
struct stat64 buf;
stat64( QFile::encodeName(m_url.path( -1 )), &buf );
#else
struct stat buf;
stat( QFile::encodeName(m_url.path( -1 )), &buf );
#endif
return (which == KIO::UDS_MODIFICATION_TIME) ? buf.st_mtime :
(which == KIO::UDS_ACCESS_TIME) ? buf.st_atime :
static_cast<time_t>(0); // We can't determine creation time for local files
}
return static_cast<time_t>(0);
}
QString KFileItem::user() const
{
if ( m_user.isEmpty() && m_bIsLocalURL )
{
#ifdef sun
struct stat64 buff;
if ( lstat64( QFile::encodeName(m_url.path( -1 )), &buff ) == 0) // get uid/gid \
of the link, if it's a link #else
struct stat buff;
if ( lstat( QFile::encodeName(m_url.path( -1 )), &buff ) == 0) // get uid/gid of \
the link, if it's a link #endif
{
struct passwd *user = getpwuid( buff.st_uid );
if ( user != 0L )
m_user = QString::fromLocal8Bit(user->pw_name);
}
}
return m_user;
}
QString KFileItem::group() const
{
if (m_group.isEmpty() && m_bIsLocalURL )
{
#ifdef sun
struct stat64 buff;
if ( lstat64( QFile::encodeName(m_url.path( -1 )), &buff ) == 0) // get uid/gid \
of the link, if it's a link #else
struct stat buff;
if ( lstat( QFile::encodeName(m_url.path( -1 )), &buff ) == 0) // get uid/gid of \
the link, if it's a link #endif
{
struct group *ge = getgrgid( buff.st_gid );
if ( ge != 0L ) {
m_group = QString::fromLocal8Bit(ge->gr_name);
if (m_group.isEmpty())
m_group.sprintf("%d",ge->gr_gid);
} else
m_group.sprintf("%d",buff.st_gid);
}
else if (errno == EOVERFLOW)
{
m_group = (char *) NULL;
}
}
return m_group;
}
QString KFileItem::mimetype() const
{
KFileItem * that = const_cast<KFileItem *>(this);
return that->determineMimeType()->name();
}
KMimeType::Ptr KFileItem::determineMimeType()
{
if ( !m_pMimeType || !d->bMimeTypeKnown )
{
//kdDebug(1203) << "finding mimetype for " << m_url.url() << endl;
m_pMimeType = KMimeType::findByURL( m_url, m_fileMode, m_bIsLocalURL );
d->bMimeTypeKnown = true;
}
return m_pMimeType;
}
bool KFileItem::isMimeTypeKnown() const
{
return d->bMimeTypeKnown;
}
QString KFileItem::mimeComment()
{
KMimeType::Ptr mType = determineMimeType();
QString comment = mType->comment( m_url, false );
if (!comment.isEmpty())
return comment;
else
return mType->name();
}
QString KFileItem::iconName()
{
return determineMimeType()->icon(m_url, false);
}
QPixmap KFileItem::pixmap( int _size, int _state ) const
{
if ( !m_pMimeType )
{
static const QString & defaultFolderIcon =
KGlobal::staticQString(KMimeType::mimeType( "inode/directory" \
)->KServiceType::icon()); if ( S_ISDIR( m_fileMode ) )
return DesktopIcon( defaultFolderIcon, _size, _state );
return DesktopIcon( "unknown", _size, _state );
}
if ( m_bLink )
_state |= KIcon::LinkOverlay;
if ( !S_ISDIR( m_fileMode ) // Locked dirs have a special icon
&& !isReadable())
_state |= KIcon::LockOverlay;
KMimeType::Ptr mime;
// Use guessed mimetype if the main one is clueless
if ( m_pMimeType->name() == KMimeType::defaultMimeType()
&& !d->m_guessedMimeType.isEmpty() )
mime = KMimeType::mimeType( d->m_guessedMimeType );
else
mime = m_pMimeType;
// Support for gzipped files
if ( mime->name() == "application/x-gzip" && m_url.fileName().right(3) == ".gz" )
{
QString subFileName = m_url.path().left( m_url.path().length() - 3 );
//kdDebug() << "KFileItem::pixmap subFileName=" << subFileName << endl;
mime = KMimeType::findByURL( subFileName, 0, m_bIsLocalURL );
_state |= KIcon::ZipOverlay;
}
QPixmap p = mime->pixmap( m_url, KIcon::Desktop, _size, _state );
if (p.isNull())
kdWarning() << "Pixmap not found for mimetype " << m_pMimeType->name() << endl;
return p;
}
bool KFileItem::isReadable() const
{
/*
struct passwd * user = getpwuid( geteuid() );
bool isMyFile = (QString::fromLocal8Bit(user->pw_name) == m_user);
// This gets ugly for the group....
// Maybe we want a static QString for the user and a static QStringList
// for the groups... then we need to handle the deletion properly...
*/
// No read permission at all
if ( !(S_IRUSR & m_permissions) && !(S_IRGRP & m_permissions) && !(S_IROTH & \
m_permissions) ) return false;
// Or if we can't read it [using access()] - not network transparent
else if ( m_bIsLocalURL && access( QFile::encodeName(m_url.path()), R_OK ) == -1 )
return false;
return true;
}
bool KFileItem::acceptsDrops()
{
// A directory ?
if ( S_ISDIR( mode() ) )
{
if ( m_bIsLocalURL ) // local -> check if we can enter it
return (access( QFile::encodeName(m_url.path()), X_OK ) == 0);
else
return true; // assume ok for remote urls
}
// But only local .desktop files and executables
if ( !m_bIsLocalURL )
return false;
if ( mimetype() == "application/x-desktop")
return true;
// Executable, shell script ... ?
if ( access( QFile::encodeName(m_url.path()), X_OK ) == 0 )
return true;
return false;
}
QString KFileItem::getStatusBarInfo()
{
QString comment = determineMimeType()->comment( m_url, false );
QString text = m_strText;
// Extract from the KIO::UDSEntry the additional info we didn't get previously
QString myLinkDest = linkDest();
long mySize = size();
QString text2 = text.copy();
if ( m_bLink )
{
QString tmp;
if ( comment.isEmpty() )
tmp = i18n ( "Symbolic Link" );
else
tmp = i18n("%1 (Link)").arg(comment);
text += "->";
text += myLinkDest;
text += " ";
text += tmp;
}
else if ( S_ISREG( m_fileMode ) )
{
text = QString("%1 (%2)").arg(text2).arg( KIO::convertSize( mySize ) );
text += " ";
text += comment;
}
else if ( S_ISDIR ( m_fileMode ) )
{
text += "/ ";
text += comment;
}
else
{
text += " ";
text += comment;
}
return text;
}
void KFileItem::run()
{
KURL url( m_url );
if ( m_bLink )
url = KURL( m_url, linkDest() );
(void) new KRun( url, m_fileMode, m_bIsLocalURL );
}
bool KFileItem::cmp( const KFileItem & item )
{
return ( m_strName == item.m_strName
&& m_bIsLocalURL == item.m_bIsLocalURL
&& m_fileMode == item.m_fileMode
&& m_permissions == item.m_permissions
&& m_user == item.m_user
&& m_group == item.m_group
&& m_bLink == item.m_bLink
&& size() == item.size()
&& time(KIO::UDS_MODIFICATION_TIME) == \
item.time(KIO::UDS_MODIFICATION_TIME) ); }
void KFileItem::assign( const KFileItem & item )
{
m_entry = item.m_entry;
m_url = item.m_url;
m_bIsLocalURL = item.m_bIsLocalURL;
m_strName = item.m_strName;
m_strText = item.m_strText;
m_fileMode = item.m_fileMode;
m_permissions = item.m_permissions;
m_user = item.m_user;
m_group = item.m_group;
m_bLink = item.m_bLink;
m_pMimeType = item.m_pMimeType;
m_strLowerCaseName = item.m_strLowerCaseName;
*d = *item.d;
// We had a mimetype previously (probably), so we need to re-determine it
determineMimeType();
}
["file.cc" (text/x-c++)]
// $Id: file.cc,v 1.103.2.1 2001/03/12 12:10:54 faure Exp $
#include <config.h>
#ifdef __linux__
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
#include <features.h>
#endif
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <assert.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <qvaluelist.h>
#include <kshred.h>
#include <kdebug.h>
#include <kurl.h>
#include <kprotocolmanager.h>
#include <kinstance.h>
#include <ksimpleconfig.h>
#include <ktempfile.h>
#include <klocale.h>
#include <qfile.h>
#include <qstrlist.h>
#include "file.h"
#include <limits.h>
using namespace KIO;
#define MAX_IPC_SIZE (1024*32)
QString testLogFile( const char *_filename );
extern "C" { int kdemain(int argc, char **argv); }
int kdemain( int argc, char **argv )
{
KInstance instance( "kio_file" );
kdDebug(7101) << "Starting " << getpid() << endl;
if (argc != 4)
{
fprintf(stderr, "Usage: kio_file protocol domain-socket1 domain-socket2\n");
exit(-1);
}
FileProtocol slave(argv[2], argv[3]);
slave.dispatchLoop();
kdDebug(7101) << "Done" << endl;
return 0;
}
FileProtocol::FileProtocol( const QCString &pool, const QCString &app ) : SlaveBase( \
"file", pool, app ) {
usercache.setAutoDelete( TRUE );
groupcache.setAutoDelete( TRUE );
}
void FileProtocol::chmod( const KURL& url, int permissions )
{
QCString _path( QFile::encodeName(url.path()));
if ( ::chmod( _path.data(), permissions ) == -1 )
error( KIO::ERR_CANNOT_CHMOD, url.path() );
else
finished();
}
void FileProtocol::mkdir( const KURL& url, int permissions )
{
QCString _path( QFile::encodeName(url.path()));
#ifdef sun
struct stat64 buff;
if ( stat64( _path.data(), &buff ) == -1 ) {
#else
struct stat buff;
if ( ::stat( _path.data(), &buff ) == -1 ) {
#endif
if ( ::mkdir( _path.data(), 0777 /*umask will be applied*/ ) != 0 ) {
if ( errno == EACCES ) {
error( KIO::ERR_ACCESS_DENIED, url.path() );
return;
} else {
error( KIO::ERR_COULD_NOT_MKDIR, url.path() );
return;
}
} else {
if ( permissions != -1 )
chmod( url, permissions );
else
finished();
return;
}
}
if ( S_ISDIR( buff.st_mode ) ) {
kdDebug() << "ERR_DIR_ALREADY_EXIST" << endl;
error( KIO::ERR_DIR_ALREADY_EXIST, url.path() );
return;
}
error( KIO::ERR_FILE_ALREADY_EXIST, url.path() );
return;
}
void FileProtocol::get( const KURL& url )
{
QCString _path( QFile::encodeName(url.path()));
#ifdef sun
struct stat64 buff;
if ( stat64( _path.data(), &buff ) == -1 ) {
#else
struct stat buff;
if ( ::stat( _path.data(), &buff ) == -1 ) {
#endif
if ( errno == EACCES )
error( KIO::ERR_ACCESS_DENIED, url.path() );
else
error( KIO::ERR_DOES_NOT_EXIST, url.path() );
return;
}
if ( S_ISDIR( buff.st_mode ) ) {
error( KIO::ERR_IS_DIRECTORY, url.path() );
return;
}
if ( S_ISFIFO( buff.st_mode ) || S_ISSOCK ( buff.st_mode ) ) {
error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
return;
}
int fd = open( _path.data(), O_RDONLY);
if ( fd < 0 ) {
error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
return;
}
totalSize( buff.st_size );
int processed_size = 0;
time_t t_start = time( 0L );
time_t t_last = t_start;
char buffer[ MAX_IPC_SIZE ];
QByteArray array;
while( 1 )
{
int n = ::read( fd, buffer, MAX_IPC_SIZE );
if (n == -1)
{
if (errno == EINTR)
continue;
error( KIO::ERR_COULD_NOT_READ, url.path());
close(fd);
return;
}
if (n == 0)
break; // Finished
array.setRawData(buffer, n);
data( array );
array.resetRawData(buffer, n);
processed_size += n;
time_t t = time( 0L );
if ( t - t_last >= 1 )
{
processedSize( processed_size );
speed( processed_size / ( t - t_start ) );
t_last = t;
}
}
data( QByteArray() );
close( fd );
processedSize( buff.st_size );
time_t t = time( 0L );
if ( t - t_start >= 1 )
speed( processed_size / ( t - t_start ) );
finished();
}
static int
write_all(int fd, const char *buf, size_t len)
{
while (len > 0)
{
int written = write(fd, buf, len);
if (written < 0)
{
if (errno == EINTR)
continue;
return -1;
}
buf += written;
len -= written;
}
return 0;
}
void FileProtocol::put( const KURL& url, int _mode, bool _overwrite, bool _resume )
{
QString dest_orig = url.path();
QCString _dest_orig( QFile::encodeName(dest_orig));
kdDebug( 7101 ) << "Put " << dest_orig << endl;
QString dest_part( dest_orig );
dest_part += QString::fromLatin1(".part");
QCString _dest_part( QFile::encodeName(dest_part));
bool bMarkPartial = KProtocolManager::markPartial();
#ifdef sun
struct stat64 buff_orig;
bool orig_exists = ( stat64( _dest_orig.data(), &buff_orig ) != -1 );
#else
struct stat buff_orig;
bool orig_exists = ( ::stat( _dest_orig.data(), &buff_orig ) != -1 );
#endif
if ( orig_exists && !_overwrite && !_resume)
{
if (S_ISDIR(buff_orig.st_mode))
error( KIO::ERR_DIR_ALREADY_EXIST, dest_orig );
else
error( KIO::ERR_FILE_ALREADY_EXIST, dest_orig );
return;
}
QString dest;
if (bMarkPartial)
{
kdDebug(7101) << "Appending .part extension to " << dest_orig << endl;
dest = dest_part;
#ifdef sun
struct stat64 buff_part;
bool part_exists = ( stat64( _dest_part.data(), &buff_part ) != -1 );
#else
struct stat buff_part;
bool part_exists = ( ::stat( _dest_part.data(), &buff_part ) != -1 );
#endif
if ( part_exists && !_resume && buff_part.st_size > 0 )
{
kdDebug() << "FileProtocol::put : calling canResume with " << (unsigned \
long)buff_part.st_size << endl; // Maybe we can use this partial file for resuming
// Tell about the size we have, and the app will tell us
// if it's ok to resume or not.
_resume = canResume( buff_part.st_size );
kdDebug() << "FileProtocol::put got answer " << _resume << endl;
if (!_resume)
{
kdDebug(7101) << "Deleting partial file " << dest_part << endl;
if ( ! remove( _dest_part.data() ) ) {
part_exists = false;
} else {
error( KIO::ERR_CANNOT_DELETE_PARTIAL, dest_part );
return;
}
}
}
}
else
{
dest = dest_orig;
if ( orig_exists && !_resume )
{
kdDebug(7101) << "Deleting destination file " << dest_part << endl;
remove( _dest_orig.data() );
// Catch errors when we try to open the file.
}
}
QCString _dest( QFile::encodeName(dest));
int fd;
if ( _resume ) {
fd = open( _dest.data(), O_RDWR ); // append if resuming
lseek(fd, 0, SEEK_END); // Seek to end
} else {
// WABA: Make sure that we keep writing permissions ourselves,
// otherwise we can be in for a surprise on NFS.
mode_t initialMode;
if (_mode != -1)
initialMode = _mode | S_IWUSR | S_IRUSR;
else
initialMode = 0666;
fd = open(_dest.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode);
}
if ( fd < 0 ) {
kdDebug(7101) << "####################### COULD NOT WRITE " << dest << _mode << \
endl; kdDebug(7101) << "errno==" << errno << "(" << strerror(errno) << ")" << endl;
if ( errno == EACCES ) {
error( KIO::ERR_WRITE_ACCESS_DENIED, dest );
} else {
error( KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest );
}
return;
}
int result;
// Loop until we got 0 (end of data)
do
{
QByteArray buffer;
dataReq(); // Request for data
result = readData( buffer );
if (result > 0)
{
if (write_all( fd, buffer.data(), buffer.size()))
{
if ( errno == ENOSPC ) // disk full
{
error( KIO::ERR_DISK_FULL, dest_orig);
result = -2; // means: remove dest file
}
else
{
error( KIO::ERR_COULD_NOT_WRITE, dest_orig);
result = -1;
}
}
}
}
while ( result > 0 );
if (result != 0)
{
close(fd);
kdDebug(7101) << "Error during 'put'. Aborting." << endl;
if (result == -2)
{
remove(_dest.data());
} else if (bMarkPartial)
{
#ifdef sun
struct stat64 buff;
if (( stat64( _dest.data(), &buff ) == -1 ) ||
( buff.st_size < KProtocolManager::minimumKeepSize() ))
#else
struct stat buff;
if (( ::stat( _dest.data(), &buff ) == -1 ) ||
( buff.st_size < KProtocolManager::minimumKeepSize() ))
#endif
{
remove(_dest.data());
}
}
::exit(255);
}
if ( close(fd) )
{
error( KIO::ERR_COULD_NOT_WRITE, dest_orig);
return;
}
// after full download rename the file back to original name
if ( bMarkPartial )
{
if ( ::rename( _dest.data(), _dest_orig.data() ) )
{
kdWarning(7101) << " Couldn't rename " << _dest << " to " << _dest_orig << \
endl; error( KIO::ERR_CANNOT_RENAME_PARTIAL, dest_orig );
return;
}
}
// set final permissions, if the file was just created
if ( _mode != -1 && !orig_exists )
{
if (::chmod(_dest_orig.data(), _mode) != 0)
{
warning( i18n( "Could not change permissions for\n%1" ).arg( dest_orig ) \
); }
}
// We have done our job => finish
finished();
}
void FileProtocol::copy( const KURL &src, const KURL &dest,
int _mode, bool _overwrite )
{
QCString _src( QFile::encodeName(src.path()));
QCString _dest( QFile::encodeName(dest.path()));
#ifdef sun
struct stat64 buff_src;
if ( stat64( _src.data(), &buff_src ) == -1 ) {
#else
struct stat buff_src;
if ( ::stat( _src.data(), &buff_src ) == -1 ) {
#endif
if ( errno == EACCES )
error( KIO::ERR_ACCESS_DENIED, src.path() );
else
error( KIO::ERR_DOES_NOT_EXIST, src.path() );
return;
}
if ( S_ISDIR( buff_src.st_mode ) ) {
error( KIO::ERR_IS_DIRECTORY, src.path() );
return;
}
if ( S_ISFIFO( buff_src.st_mode ) || S_ISSOCK ( buff_src.st_mode ) ) {
error( KIO::ERR_CANNOT_OPEN_FOR_READING, src.path() );
return;
}
#ifdef sun
struct stat64 buff_dest;
bool dest_exists = ( stat64( _dest.data(), &buff_dest ) != -1 );
#else
struct stat buff_dest;
bool dest_exists = ( ::stat( _dest.data(), &buff_dest ) != -1 );
#endif
if ( dest_exists )
{
if (S_ISDIR(buff_dest.st_mode))
{
error( KIO::ERR_DIR_ALREADY_EXIST, dest.path() );
return;
}
if (!_overwrite)
{
error( KIO::ERR_FILE_ALREADY_EXIST, dest.path() );
return;
}
}
int src_fd = open( _src.data(), O_RDONLY);
if ( src_fd < 0 ) {
error( KIO::ERR_CANNOT_OPEN_FOR_READING, src.path() );
return;
}
// WABA: Make sure that we keep writing permissions ourselves,
// otherwise we can be in for a surprise on NFS.
mode_t initialMode;
if (_mode != -1)
initialMode = _mode | S_IWUSR;
else
initialMode = 0666;
int dest_fd = open(_dest.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode);
if ( dest_fd < 0 ) {
kdDebug(7101) << "###### COULD NOT WRITE " << dest.url() << endl;
if ( errno == EACCES ) {
error( KIO::ERR_WRITE_ACCESS_DENIED, dest.path() );
} else {
error( KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest.path() );
}
close(src_fd);
return;
}
totalSize( buff_src.st_size );
int processed_size = 0;
time_t t_start = time( 0L );
time_t t_last = t_start;
char buffer[ MAX_IPC_SIZE ];
QByteArray array;
while( 1 )
{
int n = ::read( src_fd, buffer, MAX_IPC_SIZE );
if (n == -1)
{
if (errno == EINTR)
continue;
error( KIO::ERR_COULD_NOT_READ, src.path());
close(src_fd);
close(dest_fd);
return;
}
if (n == 0)
break; // Finished
if (write_all( dest_fd, buffer, n))
{
close(src_fd);
close(dest_fd);
if ( errno == ENOSPC ) // disk full
{
error( KIO::ERR_DISK_FULL, dest.path());
remove( _dest.data() );
}
else
{
error( KIO::ERR_COULD_NOT_WRITE, dest.path());
}
return;
}
processed_size += n;
time_t t = time( 0L );
if ( t - t_last >= 1 )
{
processedSize( processed_size );
speed( processed_size / ( t - t_start ) );
t_last = t;
}
}
close( src_fd );
if (close( dest_fd))
{
error( KIO::ERR_COULD_NOT_WRITE, dest.path());
return;
}
// set final permissions
if ( _mode != -1 )
{
if (::chmod(_dest.data(), _mode) != 0)
{
warning( i18n( "Could not change permissions for\n%1" ).arg( dest.path() ) \
); }
}
processedSize( buff_src.st_size );
time_t t = time( 0L );
if ( t - t_start >= 1 )
speed( processed_size / ( t - t_start ) );
finished();
}
void FileProtocol::rename( const KURL &src, const KURL &dest,
bool _overwrite )
{
QCString _src( QFile::encodeName(src.path()));
QCString _dest( QFile::encodeName(dest.path()));
#ifdef sun
struct stat64 buff_src;
if ( stat64( _src.data(), &buff_src ) == -1 ) {
#else
struct stat buff_src;
if ( ::stat( _src.data(), &buff_src ) == -1 ) {
#endif
if ( errno == EACCES )
error( KIO::ERR_ACCESS_DENIED, src.path() );
else
error( KIO::ERR_DOES_NOT_EXIST, src.path() );
return;
}
#ifdef sun
struct stat64 buff_dest;
bool dest_exists = ( stat64( _dest.data(), &buff_dest ) != -1 );
#else
struct stat buff_dest;
bool dest_exists = ( ::stat( _dest.data(), &buff_dest ) != -1 );
#endif
if ( dest_exists )
{
if (S_ISDIR(buff_dest.st_mode))
{
error( KIO::ERR_DIR_ALREADY_EXIST, dest.path() );
return;
}
if (!_overwrite)
{
error( KIO::ERR_FILE_ALREADY_EXIST, dest.path() );
return;
}
}
if ( ::rename( _src.data(), _dest.data()))
{
if (( errno == EACCES ) || (errno == EPERM)) {
error( KIO::ERR_ACCESS_DENIED, dest.path() );
}
else if (errno == EXDEV) {
error( KIO::ERR_UNSUPPORTED_ACTION, QString::fromLatin1("rename"));
}
else if (errno == EROFS) { // The file is on a read-only filesystem
error( KIO::ERR_CANNOT_DELETE, src.path() );
}
else {
error( KIO::ERR_CANNOT_RENAME, src.path() );
}
return;
}
finished();
}
void FileProtocol::symlink( const QString &target, const KURL &dest, bool overwrite )
{
// Assume dest is local too (wouldn't be here otherwise)
if ( ::symlink( QFile::encodeName( target ), QFile::encodeName( dest.path() ) ) \
== -1 ) {
// Does the destination already exist ?
if ( errno == EEXIST )
{
if ( overwrite )
{
// Try to delete the destination
if ( unlink( QFile::encodeName( dest.path() ) ) != 0 )
{
error( KIO::ERR_CANNOT_DELETE, dest.path() );
return;
}
// Try again - this won't loop forever since unlink succeeded
symlink( target, dest, overwrite );
}
else
{
#ifdef sun
struct stat64 buff_dest;
lstat64( QFile::encodeName( dest.path() ), &buff_dest );
#else
struct stat buff_dest;
::lstat( QFile::encodeName( dest.path() ), &buff_dest );
#endif
if (S_ISDIR(buff_dest.st_mode))
error( KIO::ERR_DIR_ALREADY_EXIST, dest.path() );
else
error( KIO::ERR_FILE_ALREADY_EXIST, dest.path() );
return;
}
}
else
{
// Some error occured while we tried to symlink
error( KIO::ERR_CANNOT_SYMLINK, dest.path() );
return;
}
}
finished();
}
void FileProtocol::del( const KURL& url, bool isfile)
{
QCString _path( QFile::encodeName(url.path()));
/*****
* Delete files
*****/
if (isfile) {
kdDebug( 7101 ) << "Deleting file "<< url.url() << endl;
// TODO deletingFile( source );
if ( unlink( _path.data() ) == -1 ) {
if ((errno == EACCES) || (errno == EPERM))
error( KIO::ERR_ACCESS_DENIED, url.path());
else if (errno == EISDIR)
error( KIO::ERR_IS_DIRECTORY, url.path());
else
error( KIO::ERR_CANNOT_DELETE, url.path() );
return;
}
} else {
/*****
* Delete empty directory
*****/
kdDebug( 7101 ) << "Deleting directory " << url.url() << endl;
if ( ::rmdir( _path.data() ) == -1 ) {
if ((errno == EACCES) || (errno == EPERM))
error( KIO::ERR_ACCESS_DENIED, url.path());
else {
kdDebug( 7101 ) << "could not rmdir " << perror << endl;
error( KIO::ERR_COULD_NOT_RMDIR, url.path() );
return;
}
}
}
finished();
}
bool FileProtocol::createUDSEntry( const QString & filename, const QCString & path, \
UDSEntry & entry ) {
assert(entry.count() == 0); // by contract :-)
UDSAtom atom;
atom.m_uds = KIO::UDS_NAME;
atom.m_str = filename;
entry.append( atom );
mode_t type;
mode_t access;
#ifdef sun
struct stat64 buff;
if ( lstat64( path.data(), &buff ) == 0 ) {
#else
struct stat buff;
if ( lstat( path.data(), &buff ) == 0 ) {
#endif
if (S_ISLNK(buff.st_mode)) {
char buffer2[ 1000 ];
int n = readlink( path.data(), buffer2, 1000 );
if ( n != -1 ) {
buffer2[ n ] = 0;
}
atom.m_uds = KIO::UDS_LINK_DEST;
atom.m_str = QString::fromLocal8Bit( buffer2 );
entry.append( atom );
// A link poiting to nowhere ?
#ifdef sun
kdWarning() << "using 64 bit stat" << endl;
if ( stat64( path.data(), &buff ) == -1 ) {
#else
kdWarning() << "using 32 bit stat" << endl;
if ( ::stat( path.data(), &buff ) == -1 ) {
#endif
// It is a link pointing to nowhere
type = S_IFMT - 1;
access = S_IRWXU | S_IRWXG | S_IRWXO;
atom.m_uds = KIO::UDS_FILE_TYPE;
atom.m_long = type;
entry.append( atom );
atom.m_uds = KIO::UDS_ACCESS;
atom.m_long = access;
entry.append( atom );
atom.m_uds = KIO::UDS_SIZE;
atom.m_long = 0L;
entry.append( atom );
goto notype;
}
}
} else {
kdWarning() << "lstat didn't work on " << path.data() << endl;
return false;
}
type = buff.st_mode & S_IFMT; // extract file type
access = buff.st_mode & 07777; // extract permissions
atom.m_uds = KIO::UDS_FILE_TYPE;
atom.m_long = type;
entry.append( atom );
atom.m_uds = KIO::UDS_ACCESS;
atom.m_long = access;
entry.append( atom );
atom.m_uds = KIO::UDS_SIZE;
atom.m_long = buff.st_size;
entry.append( atom );
notype:
atom.m_uds = KIO::UDS_MODIFICATION_TIME;
atom.m_long = buff.st_mtime;
entry.append( atom );
atom.m_uds = KIO::UDS_USER;
uid_t uid = buff.st_uid;
QString *temp = usercache.find( uid );
if ( !temp ) {
struct passwd *user = getpwuid( uid );
if ( user ) {
usercache.insert( uid, new QString(QString::fromLatin1(user->pw_name)) );
atom.m_str = user->pw_name;
}
else
atom.m_str = QString::number( uid );
}
else
atom.m_str = *temp;
entry.append( atom );
atom.m_uds = KIO::UDS_GROUP;
gid_t gid = buff.st_gid;
temp = groupcache.find( gid );
if ( !temp ) {
struct group *grp = getgrgid( gid );
if ( grp ) {
groupcache.insert( gid, new QString(QString::fromLatin1(grp->gr_name)) );
atom.m_str = grp->gr_name;
}
else
atom.m_str = QString::number( gid );
}
else
atom.m_str = *temp;
entry.append( atom );
atom.m_uds = KIO::UDS_ACCESS_TIME;
atom.m_long = buff.st_atime;
entry.append( atom );
// Note: buff.st_ctime isn't the creation time !
// We made that mistake for KDE 2.0, but it's in fact the
// "file status" change time, which we don't care about.
return true;
}
void FileProtocol::stat( const KURL & url )
{
/* directories may not have a slash at the end if
* we want to stat() them; it requires that we
* change into it .. which may not be allowed
* stat("/is/unaccessible") -> rwx------
* stat("/is/unaccessible/") -> EPERM H.Z.
* This is the reason for the -1
*/
QCString _path( QFile::encodeName(url.path(-1)));
#ifdef sun
struct stat64 buff;
if ( lstat64( _path.data(), &buff ) == -1 ) {
#else
struct stat buff;
if ( ::lstat( _path.data(), &buff ) == -1 ) {
#endif
error( KIO::ERR_DOES_NOT_EXIST, url.path(-1) );
return;
}
UDSEntry entry;
if ( !createUDSEntry( url.fileName(), _path, entry ) )
{
// Should never happen
error( KIO::ERR_DOES_NOT_EXIST, url.path(-1) );
return;
}
#if 0
///////// debug code
KIO::UDSEntry::ConstIterator it = entry.begin();
for( ; it != entry.end(); it++ ) {
switch ((*it).m_uds) {
case KIO::UDS_FILE_TYPE:
kdDebug(7101) << "File Type : " << (mode_t)((*it).m_long) << endl;
break;
case KIO::UDS_ACCESS:
kdDebug(7101) << "Access permissions : " << (mode_t)((*it).m_long) << \
endl; break;
case KIO::UDS_USER:
kdDebug(7101) << "User : " << ((*it).m_str.ascii() ) << endl;
break;
case KIO::UDS_GROUP:
kdDebug(7101) << "Group : " << ((*it).m_str.ascii() ) << endl;
break;
case KIO::UDS_NAME:
kdDebug(7101) << "Name : " << ((*it).m_str.ascii() ) << endl;
//m_strText = decodeFileName( (*it).m_str );
break;
case KIO::UDS_URL:
kdDebug(7101) << "URL : " << ((*it).m_str.ascii() ) << endl;
break;
case KIO::UDS_MIME_TYPE:
kdDebug(7101) << "MimeType : " << ((*it).m_str.ascii() ) << endl;
break;
case KIO::UDS_LINK_DEST:
kdDebug(7101) << "LinkDest : " << ((*it).m_str.ascii() ) << endl;
break;
}
}
/////////
#endif
statEntry( entry );
finished();
}
void FileProtocol::listDir( const KURL& url)
{
QCString _path( QFile::encodeName(url.path()));
kdDebug(7101) << "========= LIST " << url.url() << " =========" << endl;
#ifdef sun
struct stat64 buff;
if ( stat64( _path.data(), &buff ) == -1 ) {
#else
struct stat buff;
if ( ::stat( _path.data(), &buff ) == -1 ) {
#endif
error( KIO::ERR_DOES_NOT_EXIST, url.path() );
return;
}
if ( !S_ISDIR( buff.st_mode ) ) {
error( KIO::ERR_IS_FILE, url.path() );
return;
}
DIR *dp = 0L;
#if defined( __DECCXX) && defined(__linux__)
struct dirent64 *ep; // XXX struct dirent *ep;
#else
struct dirent *ep;
#endif
dp = opendir( _path.data() );
if ( dp == 0 ) {
error( KIO::ERR_CANNOT_ENTER_DIRECTORY, url.path() );
return;
}
// Don't make this a QStringList. The locale file name we get here
// should be passed intact to createUDSEntry to avoid problems with
// files where QFile::encodeName(QFile::decodeName(a)) != a.
QStrList entryNames;
while ( ( ep = readdir( dp ) ) != 0L )
entryNames.append( ep->d_name );
closedir( dp );
totalSize( entryNames.count() );
/* set the current dir to the path to speed up
in not having to pass an absolute path.
We restore the path later to get out of the
path - the kernel wouldn't unmount or delete
directories we keep as active directory. And
as the slave runs in the background, it's hard
to see for the user what the problem would be */
char path_buffer[PATH_MAX];
getcwd(path_buffer, PATH_MAX - 1);
chdir( _path.data() );
UDSEntry entry;
QStrListIterator it(entryNames);
for (; it.current(); ++it) {
entry.clear();
if ( createUDSEntry( QFile::decodeName(*it), *it /* we can use the filename \
as relative path*/, entry ) ) listEntry( entry, false);
else
;//Well, this should never happen... but with wrong encoding names
}
listEntry( entry, true ); // ready
kdDebug(7101) << "============= COMPLETED LIST ============" << endl;
chdir(path_buffer);
finished();
kdDebug(7101) << "=============== BYE ===========" << endl;
}
/*
void FileProtocol::testDir( const QString& path )
{
QCString _path( QFile::encodeName(path));
struct stat buff;
if ( ::stat( _path.data(), &buff ) == -1 ) {
error( KIO::ERR_DOES_NOT_EXIST, path );
return;
}
if ( S_ISDIR( buff.st_mode ) )
isDirectory();
else
isFile();
finished();
}
*/
void FileProtocol::special( const QByteArray &data)
{
int tmp;
QDataStream stream(data, IO_ReadOnly);
stream >> tmp;
switch (tmp) {
case 1:
{
QString fstype, dev, point;
Q_INT8 iRo;
stream >> iRo >> fstype >> dev >> point;
bool ro = ( iRo != 0 );
kdDebug(7101) << "MOUNTING fstype=" << fstype << " dev=" << dev << " point=" << \
point << " ro=" << ro << endl; mount( ro, fstype.ascii(), dev, point );
}
break;
case 2:
{
QString point;
stream >> point;
unmount( point );
}
break;
case 3:
{
QString filename;
stream >> filename;
KShred shred( filename );
connect( &shred, SIGNAL( processedSize( unsigned long ) ),
this, SLOT( slotProcessedSize( unsigned long ) ) );
connect( &shred, SIGNAL( infoMessage( const QString & ) ),
this, SLOT( slotInfoMessage( const QString & ) ) );
if (!shred.shred())
error( KIO::ERR_CANNOT_DELETE, filename );
else
finished();
break;
}
default:
assert(0);
}
}
// Connected to KShred
void FileProtocol::slotProcessedSize( unsigned long bytes )
{
kdDebug(7101) << "FileProtocol::slotProcessedSize (" << (unsigned int) bytes << ")" \
<< endl; processedSize( bytes );
}
// Connected to KShred
void FileProtocol::slotInfoMessage( const QString & msg )
{
kdDebug(7101) << "FileProtocol::slotInfoMessage (" << msg << ")" << endl;
infoMessage( msg );
}
static QString shellQuote( const QString &_str )
{
// Credits to Walter, says Bernd G. :)
QString str(_str);
str.replace(QRegExp(QString::fromLatin1("'")), QString::fromLatin1("'\"'\"'"));
return QString::fromLatin1("'")+str+'\'';
}
void FileProtocol::mount( bool _ro, const char *_fstype, const QString& _dev, const \
QString& _point ) {
kdDebug(7101) << "FileProtocol::mount _fstype=" << _fstype << endl;
QString buffer;
KTempFile tmpFile;
QCString tmpFileC = QFile::encodeName(tmpFile.name());
const char *tmp = tmpFileC.data();
QCString dev = QFile::encodeName( shellQuote(_dev) ); // get those ready to be \
given to a shell QCString point = QFile::encodeName( shellQuote(_point) );
QCString fstype = _fstype;
QCString readonly = _ro ? "-r" : "";
// Two steps, in case mount doesn't like it when we pass all options
for ( int step = 0 ; step <= 1 ; step++ )
{
// Mount using device only if no fstype nor mountpoint (KDE-1.x like)
if ( !_dev.isEmpty() && _point.isEmpty() && fstype.isEmpty() )
buffer.sprintf( "mount %s 2>%s", dev.data(), tmp );
else
// Mount using the mountpoint, if no fstype nor device (impossible in first \
step) if ( !_point.isEmpty() && _dev.isEmpty() && fstype.isEmpty() )
buffer.sprintf( "mount %s 2>%s", point.data(), tmp );
else
// mount giving device + mountpoint but no fstype
if ( !_point.isEmpty() && !_dev.isEmpty() && fstype.isEmpty() )
buffer.sprintf( "mount %s %s %s 2>%s", readonly.data(), dev.data(), \
point.data(), tmp ); else
// mount giving device + mountpoint + fstype
buffer.sprintf( "mount %s -t %s %s %s 2>%s", readonly.data(),
fstype.data(), dev.data(), point.data(), tmp );
kdDebug(7101) << buffer << endl;
system( buffer.ascii() );
QString err = testLogFile( tmp );
if ( err.isEmpty() )
{
finished();
return;
}
else
{
// Didn't work - or maybe we just got a warning
QString mp = KIO::findDeviceMountPoint( _dev );
// Is the device mounted ?
if ( !mp.isNull() )
{
kdDebug(7101) << "mount got a warning: " << err << endl;
warning( err );
finished();
return;
}
else
{
if ( step == 0 )
{
kdDebug(7101) << err << endl;
kdDebug(7101) << "Mounting with those options didn't work, trying \
with only mountpoint" << endl; fstype = "";
dev = "";
// The reason for trying with only mountpoint (instead of
// only device) is that some people (hi Malte!) have the
// same device associated with two mountpoints
// for different fstypes, like /dev/fd0 /mnt/e2floppy and
// /dev/fd0 /mnt/dosfloppy.
// If the user has the same mountpoint associated with two
// different devices, well they shouldn't specify the
// mountpoint but just the device.
}
else
{
error( KIO::ERR_COULD_NOT_MOUNT, err );
return;
}
}
}
}
}
void FileProtocol::unmount( const QString& _point )
{
QString buffer;
KTempFile tmpFile;
QCString tmpFileC = QFile::encodeName(tmpFile.name());
const char *tmp = tmpFileC.data();
buffer.sprintf( "umount %s 2>%s", QFile::encodeName(_point).data(), tmp );
system( buffer.ascii() );
QString err = testLogFile( tmp );
if ( err.isEmpty() )
finished();
else
error( KIO::ERR_COULD_NOT_UNMOUNT, err );
}
/*************************************
*
* Utilities
*
*************************************/
QString testLogFile( const char *_filename )
{
char buffer[ 1024 ];
QString result;
#ifdef sun
struct stat64 buff;
stat64( _filename, &buff );
#else
struct stat buff;
stat( _filename, &buff );
#endif
int size = buff.st_size;
if ( size == 0 ) {
unlink( _filename );
return result;
}
FILE * f = fopen( _filename, "rb" );
if ( f == 0L ) {
unlink( _filename );
result = i18n("Could not read %1").arg(QFile::decodeName(_filename));
return result;
}
result = "";
const char *p = "";
while ( p != 0L ) {
p = fgets( buffer, sizeof(buffer)-1, f );
if ( p != 0L )
result += QString::fromLocal8Bit(buffer);
}
fclose( f );
unlink( _filename );
return result;
}
#include "file.moc"
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic