25 #define QT_NO_CAST_FROM_ASCII
28 #include <QDirIterator>
31 #include <config-kioslave-file.h>
34 #include <sys/types.h>
37 #include <sys/socket.h>
38 #ifdef HAVE_SYS_TIME_H
58 #include <QtCore/QByteRef>
59 #include <QtCore/QDate>
60 #include <QtCore/QVarLengthArray>
61 #include <QtCore/QCoreApplication>
62 #include <QtCore/QRegExp>
63 #include <QtCore/QFile>
65 #include <QtCore/QDir>
66 #include <QtCore/QFileInfo>
83 #include <sys/mnttab.h>
94 #define MAX_IPC_SIZE (1024*32)
99 mode_t type,
bool withACL );
108 kDebug(7101) <<
"Starting" << getpid();
112 fprintf(stderr,
"Usage: kio_file protocol domain-socket1 domain-socket2\n");
117 slave.dispatchLoop();
124 :
SlaveBase(
"file", pool, app ), openFd(-1)
132 #ifdef HAVE_POSIX_ACL
133 static QString aclToText(acl_t acl) {
135 char* txt = acl_to_text(acl, &size);
142 int FileProtocol::setACL(
const char *path, mode_t perm,
bool directoryDefault )
145 #ifdef HAVE_POSIX_ACL
155 acl = acl_from_mode( perm );
157 acl = acl_from_text( ACLString.
toLatin1() );
158 if ( acl_valid( acl ) == 0 ) {
159 ret = acl_set_file( path, ACL_TYPE_ACCESS, acl );
160 kDebug(7101) <<
"Set ACL on:" << path <<
"to:" << aclToText(acl);
163 if ( ret != 0 )
return ret;
166 if ( directoryDefault && !defaultACLString.
isEmpty() ) {
169 ret += acl_delete_def_file( path );
171 acl_t acl = acl_from_text( defaultACLString.
toLatin1() );
172 if ( acl_valid( acl ) == 0 ) {
173 ret += acl_set_file( path, ACL_TYPE_DEFAULT, acl );
174 kDebug(7101) <<
"Set Default ACL on:" << path <<
"to:" << aclToText(acl);
182 Q_UNUSED(directoryDefault);
193 ( setACL( _path.data(), permissions, false ) == -1 ) ||
195 ( setACL( _path.data(), permissions, true ) == -1 && errno != ENOTDIR ) ) {
220 KDE_struct_stat statbuf;
222 struct utimbuf utbuf;
223 utbuf.actime = statbuf.st_atime;
240 kDebug(7101) << path <<
"permission=" << permissions;
246 KDE_struct_stat buff;
249 if ( errno == EACCES ) {
252 }
else if ( errno == ENOSPC ) {
260 if ( permissions != -1 )
261 chmod( url, permissions );
268 if ( S_ISDIR( buff.st_mode ) ) {
269 kDebug(7101) <<
"ERR_DIR_ALREADY_EXIST";
288 KDE_struct_stat buff;
290 if ( errno == EACCES )
297 if ( S_ISDIR( buff.st_mode ) ) {
301 if ( !S_ISREG( buff.st_mode ) ) {
313 posix_fadvise( fd, 0, 0, POSIX_FADV_SEQUENTIAL);
321 KMimeType::Ptr mt = KMimeType::findByUrl( url, buff.st_mode,
true );
322 emit mimeType( mt->name() );
324 totalSize( buff.st_size );
333 if (ok && (offset > 0) && (offset < buff.st_size))
335 if (KDE_lseek(fd, offset, SEEK_SET) == offset)
338 processed_size = offset;
366 processedSize( processed_size );
375 processedSize( buff.st_size );
383 ssize_t written = write(fd, buf, len);
401 KDE_struct_stat buff;
403 if ( errno == EACCES )
410 if ( S_ISDIR( buff.st_mode ) ) {
414 if ( !S_ISREG( buff.st_mode ) ) {
420 if (mode & QIODevice::ReadOnly) {
421 if (mode & QIODevice::WriteOnly) {
422 flags = O_RDWR | O_CREAT;
426 }
else if (mode & QIODevice::WriteOnly) {
427 flags = O_WRONLY | O_CREAT;
430 if (mode & QIODevice::Append) {
432 }
else if (mode & QIODevice::Truncate) {
437 if ( flags & O_CREAT)
449 if (mode & QIODevice::ReadOnly){
450 KMimeType::Ptr mt = KMimeType::findByUrl( url, buff.st_mode,
true );
451 emit mimeType( mt->name() );
454 totalSize( buff.st_size );
463 kDebug(7101) <<
"File::open -- read";
464 Q_ASSERT(openFd != -1);
471 }
while (res == -1 && errno == EINTR);
486 if (bytes <= 0)
break;
492 kDebug(7101) <<
"File::open -- write";
493 Q_ASSERT(openFd != -1);
496 if (errno == ENOSPC) {
500 kWarning(7101) <<
"Couldn't write. Error:" << strerror(errno);
505 written(data.
size());
511 kDebug(7101) <<
"File::open -- seek";
512 Q_ASSERT(openFd != -1);
514 int res = KDE_lseek(openFd, offset, SEEK_SET);
525 kDebug(7101) <<
"File::open -- close ";
526 Q_ASSERT(openFd != -1);
539 kDebug(7101) << dest_orig <<
"mode=" << _mode;
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);
550 KDE_struct_stat buff_part;
551 bPartExists = (
KDE::stat( dest_part, &buff_part ) != -1);
553 if (bPartExists && !(_flags &
KIO::Resume) && !(_flags &
KIO::Overwrite) && buff_part.st_size > 0 && S_ISREG(buff_part.st_mode))
568 if (S_ISDIR(buff_orig.st_mode))
586 result = readData( buffer );
594 kDebug(7101) <<
"Appending .part extension to" << dest_orig;
598 kDebug(7101) <<
"Deleting partial file" << dest_part;
608 kDebug(7101) <<
"Deleting destination file" << dest_orig;
618 KDE_lseek(fd, 0, SEEK_END);
627 initialMode = _mode | S_IWUSR | S_IRUSR;
631 fd =
KDE::open(dest, O_CREAT | O_TRUNC | O_WRONLY, initialMode);
636 kDebug(7101) <<
"####################### COULD NOT WRITE" << dest <<
"_mode=" << _mode;
637 kDebug(7101) <<
"errno==" << errno <<
"(" << strerror(errno) <<
")";
638 if ( errno == EACCES )
648 if ( errno == ENOSPC )
655 kWarning(7101) <<
"Couldn't write. Error:" << strerror(errno);
662 while ( result > 0 );
667 kDebug(7101) <<
"Error during 'put'. Aborting.";
673 KDE_struct_stat buff;
674 if (bMarkPartial &&
KDE::stat( dest, &buff ) == 0)
677 if (buff.st_size < size)
678 remove(_dest.
data());
693 kWarning(7101) <<
"Error when closing file descriptor:" << strerror(errno);
704 if( (_flags & KIO::Overwrite) && S_ISLNK( buff_orig.st_mode ) )
708 kWarning(7101) <<
" Couldn't rename " << _dest <<
" to " << dest_orig;
712 org::kde::KDirNotify::emitFileRenamed(
KUrl(dest).url(),
KUrl(dest_orig).url());
723 warning(
i18n(
"Could not change permissions for\n%1" , dest_orig ) );
732 KDE_struct_stat dest_statbuf;
733 if (
KDE::stat( dest_orig, &dest_statbuf ) == 0) {
734 struct timeval utbuf[2];
736 utbuf[0].tv_sec = dest_statbuf.st_atime;
737 utbuf[0].tv_usec = 0;
740 utbuf[1].tv_usec = dt.
time().
msec() * 1000;
751 QString FileProtocol::getUserName( uid_t uid )
const
753 if ( !mUsercache.
contains( uid ) ) {
754 struct passwd *user = getpwuid( uid );
761 return mUsercache[uid];
764 QString FileProtocol::getGroupName( gid_t gid )
const
766 if ( !mGroupcache.
contains( gid ) ) {
767 struct group *grp = getgrgid( gid );
774 return mGroupcache[gid];
778 short int details,
bool withACL )
780 #ifndef HAVE_POSIX_ACL
783 assert(entry.
count() == 0);
790 KDE_struct_stat buff;
792 if ( KDE_lstat( path.
data(), &buff ) == 0 ) {
799 if (S_ISLNK(buff.st_mode)) {
801 char buffer2[ 1000 ];
802 int n = readlink( path.
data(), buffer2, 999 );
810 if ( details > 1 && KDE_stat( path.
data(), &buff ) == -1 ) {
813 access = S_IRWXU | S_IRWXG | S_IRWXO;
827 type = buff.st_mode & S_IFMT;
828 access = buff.st_mode & 07777;
835 #ifdef HAVE_POSIX_ACL
840 appendACLAtoms( path, entry, type, withACL );
871 stream >> iRo >> fstype >> dev >> point;
873 bool ro = ( iRo != 0 );
875 kDebug(7101) <<
"MOUNTING fstype=" << fstype <<
" dev=" << dev <<
" point=" << point <<
" ro=" << ro;
903 kDebug(7101) <<
"fstype=" << _fstype;
913 if( volmgt_running() ) {
915 if( volmgt_check( devname.
data() ) == 0 ) {
916 kDebug(7101) <<
"VOLMGT: no media in "
918 err =
i18n(
"No Media inserted or Media not recognized.");
928 err =
i18n(
"\"vold\" is not running.");
929 kDebug(7101) <<
"VOLMGT: " << err;
954 bool fstype_empty = !_fstype || !*_fstype;
968 for (
int step = 0 ; step <= 1 ; step++ )
972 if ( !dev.isEmpty() && _point.
isEmpty() && fstype_empty )
976 if ( !_point.
isEmpty() && dev.isEmpty() && fstype_empty )
980 if ( !_point.
isEmpty() && !dev.isEmpty() && fstype_empty )
981 buffer += readonly +
' ' + dev +
' ' + point;
984 #if defined(__svr4__) && defined(Q_OS_SOLARIS) // MARCO for Solaris 8 and I
986 buffer +=
"-F " + fstype +
' ' + (_ro ?
"-oro" :
"") +
' ' + dev +
' ' + point;
988 buffer += readonly +
" -t " + fstype +
' ' + dev +
' ' + point;
990 buffer +=
" 2>" + tmpFileName;
993 int mount_ret = system( buffer.constData() );
996 if ( err.isEmpty() && mount_ret == 0)
1006 if ( mp && mount_ret == 0)
1008 kDebug(7101) <<
"mount got a warning:" << err;
1015 if ( (step == 0) && !_point.
isEmpty())
1018 kDebug(7101) <<
"Mounting with those options didn't work, trying with only mountpoint";
1020 fstype_empty =
true;
1042 err =
i18n(
"mounting is not supported by wince.");
1069 if( volmgt_running() ) {
1070 kDebug(7101) <<
"VOLMGT: looking for "
1073 if( (mnttab = KDE_fopen(
MNTTAB,
"r" )) == NULL ) {
1075 kDebug(7101) <<
"VOLMGT: " << err;
1088 while( getmntent( mnttab, &mnt ) == 0 ) {
1089 if( strcmp( _point.
toLocal8Bit(), mnt.mnt_mountp ) == 0 ){
1090 devname = mnt.mnt_special;
1096 if( devname == NULL ) {
1098 kDebug(7101) <<
"VOLMGT: "
1110 ptr = strrchr( devname,
'/' );
1113 buffer =
"/usr/bin/eject " + qdevname +
" 2>" + tmpFileName;
1114 kDebug(7101) <<
"VOLMGT: eject " << qdevname;
1120 if( WEXITSTATUS( system( buffer.
constData() )) == 4 ) {
1137 err =
i18n(
"\"vold\" is not running.");
1138 kDebug(7101) <<
"VOLMGT: " << err;
1158 if ( err.isEmpty() )
1164 err =
i18n(
"unmounting is not supported by wince.");
1204 QString dev = mp->realDeviceName();
1205 if (dev.
isEmpty())
return false;
1220 int res = system( buffer.
data() );
1238 if (file.
open(QIODevice::ReadOnly)) {
1250 #ifdef HAVE_POSIX_ACL
1252 bool FileProtocol::isExtendedACL( acl_t acl )
1254 return ( acl_equiv_mode( acl, 0 ) != 0 );
1257 static void appendACLAtoms(
const QByteArray & path,
UDSEntry& entry, mode_t type,
bool withACL )
1260 if ( acl_extended_file( path.
data() ) == 0 )
return;
1263 acl_t defaultAcl = 0;
1264 bool isDir = S_ISDIR( type );
1266 acl = acl_get_file( path.
data(), ACL_TYPE_ACCESS );
1271 if ( !FileProtocol::isExtendedACL( acl ) ) {
1276 defaultAcl = acl_get_file( path.
data(), ACL_TYPE_DEFAULT );
1278 if ( acl || defaultAcl ) {
1284 const QString str = aclToText(acl);
1289 const QString str = aclToText(defaultAcl);
1294 if ( acl ) acl_free( acl );
1295 if ( defaultAcl ) acl_free( defaultAcl );
1301 bool FileProtocol::deleteRecursive(
const QString& path)
1304 QDirIterator it(path, QDir::AllEntries | QDir::NoDotAndDotDot | QDir::System | QDir::Hidden,
1305 QDirIterator::Subdirectories);
1307 while ( it.hasNext() ) {
1308 const QString itemPath = it.next();
1312 dirsToDelete.
prepend(itemPath);
1322 Q_FOREACH(
const QString& itemPath, dirsToDelete) {
1324 if (!dir.
rmdir(itemPath)) {
void unmount(const QString &point)
QString i18n(const char *text)
KAutostart::StartPhase readEntry(const KConfigGroup &group, const char *key, const KAutostart::StartPhase &aDefault)
iterator insert(const Key &key, const T &value)
static List currentMountPoints(DetailsNeededFlags infoNeeded=BasicInfoNeeded)
int mkdir(const QString &pathname, mode_t)
void insert(uint field, const QString &value)
virtual void seek(KIO::filesize_t offset)
Ptr findByDevice(const QString &device) const
int stat(const QString &path, KDE_struct_stat *buf)
int rename(const QString &in, const QString &out)
virtual void special(const QByteArray &data)
Special commands supported by this slave: 1 - mount 2 - unmount.
int chmod(const QString &path, mode_t mode)
virtual void read(KIO::filesize_t size)
QByteArray fromRawData(const char *data, int size)
QString toLocalFile(AdjustPathOption trailing=LeaveTrailingSlash) const
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
void mount(bool _ro, const char *_fstype, const QString &dev, const QString &point)
KSharedConfigPtr config()
int kdemain(int argc, char **argv)
int open(const QString &pathname, int flags, mode_t mode)
FileProtocol(const QByteArray &pool, const QByteArray &app)
void setProtocol(const QString &proto)
QString number(int n, int base)
QString fromLocal8Bit(const char *str, int size)
virtual void setModificationTime(const KUrl &url, const QDateTime &mtime)
bool rmdir(const QString &dirName) const
static QString readLogFile(const QByteArray &_filename)
void setAutoRemove(bool b)
const char * constData() const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
QByteArray toLocal8Bit() const
QString quoteArg(const QString &arg)
#define DEFAULT_MINIMUM_KEEP_SIZE
QDateTime fromString(const QString &string, Qt::DateFormat format)
int lstat(const QString &path, KDE_struct_stat *buf)
virtual void write(const QByteArray &data)
bool pmount(const QString &dev)
QByteArray toLatin1() const
QString mid(int position, int n) const
QString dir(const QString &fileClass)
int access(const QString &path, int mode)
Ptr findByPath(const QString &path) const
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
virtual void get(const KUrl &url)
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
int write_all(int fd, const char *buf, size_t len)
QString fromLatin1(const char *str, int size)
virtual void chmod(const KUrl &url, int permissions)
void prepend(const T &value)
bool contains(const Key &key) const
bool pumount(const QString &point)
virtual void open(const KUrl &url, QIODevice::OpenMode mode)
virtual void mkdir(const KUrl &url, int permissions)
virtual void put(const KUrl &url, int _mode, KIO::JobFlags _flags)
int utime(const QString &filename, struct utimbuf *buf)
qlonglong toLongLong(bool *ok, int base) const
QByteArray encodeName(const QString &fileName)
QString decodeName(const QByteArray &localFileName)
QString number(KIO::filesize_t size)