Blame qtools/qfileinfo_unix.cpp

Packit 1c1d7e
/****************************************************************************
Packit 1c1d7e
** 
Packit 1c1d7e
**
Packit 1c1d7e
** Implementation of QFileInfo class
Packit 1c1d7e
**
Packit 1c1d7e
** Created : 950628
Packit 1c1d7e
**
Packit 1c1d7e
** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
Packit 1c1d7e
**
Packit 1c1d7e
** This file is part of the tools module of the Qt GUI Toolkit.
Packit 1c1d7e
**
Packit 1c1d7e
** This file may be distributed under the terms of the Q Public License
Packit 1c1d7e
** as defined by Trolltech AS of Norway and appearing in the file
Packit 1c1d7e
** LICENSE.QPL included in the packaging of this file.
Packit 1c1d7e
**
Packit 1c1d7e
** This file may be distributed and/or modified under the terms of the
Packit 1c1d7e
** GNU General Public License version 2 as published by the Free Software
Packit 1c1d7e
** Foundation and appearing in the file LICENSE.GPL included in the
Packit 1c1d7e
** packaging of this file.
Packit 1c1d7e
**
Packit 1c1d7e
** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
Packit 1c1d7e
** licenses for Unix/X11 or for Qt/Embedded may use this file in accordance
Packit 1c1d7e
** with the Qt Commercial License Agreement provided with the Software.
Packit 1c1d7e
**
Packit 1c1d7e
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
Packit 1c1d7e
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
Packit 1c1d7e
**
Packit 1c1d7e
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
Packit 1c1d7e
**   information about Qt Commercial License Agreements.
Packit 1c1d7e
** See http://www.trolltech.com/qpl/ for QPL licensing information.
Packit 1c1d7e
** See http://www.trolltech.com/gpl/ for GPL licensing information.
Packit 1c1d7e
**
Packit 1c1d7e
** Contact info@trolltech.com if any conditions of this licensing are
Packit 1c1d7e
** not clear to you.
Packit 1c1d7e
**
Packit 1c1d7e
**********************************************************************/
Packit 1c1d7e
Packit 1c1d7e
#include "qglobal.h"
Packit 1c1d7e
Packit 1c1d7e
#if defined(_OS_SUN_)
Packit 1c1d7e
#define readlink _qt_hide_readlink
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
#include <pwd.h>
Packit 1c1d7e
#include <grp.h>
Packit 1c1d7e
Packit 1c1d7e
#include "qfileinfo.h"
Packit 1c1d7e
#include "qfiledefs_p.h"
Packit 1c1d7e
#include "qdatetime.h"
Packit 1c1d7e
#include "qdir.h"
Packit 1c1d7e
Packit 1c1d7e
#if defined(_OS_SUN_)
Packit 1c1d7e
#undef readlink
Packit 1c1d7e
extern "C" int readlink( const char *, void *, uint );
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
void QFileInfo::slashify( QString& )
Packit 1c1d7e
{
Packit 1c1d7e
    return;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
void QFileInfo::makeAbs( QString & )
Packit 1c1d7e
{
Packit 1c1d7e
    return;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
extern bool qt_file_access( const QString& fn, int t );
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  Returns TRUE if we are pointing to a real file.
Packit 1c1d7e
  \sa isDir(), isSymLink()
Packit 1c1d7e
*/
Packit 1c1d7e
bool QFileInfo::isFile() const
Packit 1c1d7e
{
Packit 1c1d7e
    if ( !fic || !cache )
Packit 1c1d7e
	doStat();
Packit 1c1d7e
    return fic ? (fic->st.st_mode & STAT_MASK) == STAT_REG : FALSE;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  Returns TRUE if we are pointing to a directory or a symbolic link to
Packit 1c1d7e
  a directory.
Packit 1c1d7e
  \sa isFile(), isSymLink()
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
bool QFileInfo::isDir() const
Packit 1c1d7e
{
Packit 1c1d7e
    if ( !fic || !cache )
Packit 1c1d7e
	doStat();
Packit 1c1d7e
    return fic ? (fic->st.st_mode & STAT_MASK) == STAT_DIR : FALSE;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  Returns TRUE if we are pointing to a symbolic link.
Packit 1c1d7e
  \sa isFile(), isDir(), readLink()
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
bool QFileInfo::isSymLink() const
Packit 1c1d7e
{
Packit 1c1d7e
    if ( !fic || !cache )
Packit 1c1d7e
	doStat();
Packit 1c1d7e
    return fic ? fic->isSymLink : FALSE;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  Returns the name a symlink points to, or a null QString if the
Packit 1c1d7e
  object does not refer to a symbolic link.
Packit 1c1d7e
Packit 1c1d7e
  This name may not represent an existing file; it is only a string.
Packit 1c1d7e
  QFileInfo::exists() returns TRUE if the symlink points to an
Packit 1c1d7e
  existing file.
Packit 1c1d7e
Packit 1c1d7e
  \sa exists(), isSymLink(), isDir(), isFile()
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QString QFileInfo::readLink() const
Packit 1c1d7e
{
Packit 1c1d7e
    QString r;
Packit 1c1d7e
Packit 1c1d7e
#if defined(_OS_UNIX_) && !defined(_OS_OS2EMX_)
Packit 1c1d7e
    char s[PATH_MAX+1];
Packit 1c1d7e
    if ( !isSymLink() )
Packit 1c1d7e
	return QString();
Packit 1c1d7e
    int len = (int)readlink( QFile::encodeName(fn).data(), s, PATH_MAX );
Packit 1c1d7e
    if ( len >= 0 ) {
Packit 1c1d7e
	s[len] = '\0';
Packit 1c1d7e
	r = QFile::decodeName(s);
Packit 1c1d7e
    }
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
    return r;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static const uint nobodyID = (uint) -2;
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  Returns the owner of the file.
Packit 1c1d7e
Packit 1c1d7e
  On systems where files do not have owners this function returns 0.
Packit 1c1d7e
Packit 1c1d7e
  Note that this function can be time-consuming under UNIX. (in the order
Packit 1c1d7e
  of milliseconds on a 486 DX2/66 running Linux).
Packit 1c1d7e
Packit 1c1d7e
  \sa ownerId(), group(), groupId()
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QString QFileInfo::owner() const
Packit 1c1d7e
{
Packit 1c1d7e
    passwd *pw = getpwuid( ownerId() );
Packit 1c1d7e
    if ( pw )
Packit 1c1d7e
	return QFile::decodeName( pw->pw_name );
Packit 1c1d7e
    return QString::null;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  Returns the id of the owner of the file.
Packit 1c1d7e
Packit 1c1d7e
  On systems where files do not have owners this function returns ((uint) -2).
Packit 1c1d7e
Packit 1c1d7e
  \sa owner(), group(), groupId()
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
uint QFileInfo::ownerId() const
Packit 1c1d7e
{
Packit 1c1d7e
    if ( !fic || !cache )
Packit 1c1d7e
	doStat();
Packit 1c1d7e
    if ( fic )
Packit 1c1d7e
	return fic->st.st_uid;
Packit 1c1d7e
    return nobodyID;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  Returns the group the file belongs to.
Packit 1c1d7e
Packit 1c1d7e
  On systems where files do not have groups this function always
Packit 1c1d7e
  returns 0.
Packit 1c1d7e
Packit 1c1d7e
  Note that this function can be time-consuming under UNIX (in the order of
Packit 1c1d7e
  milliseconds on a 486 DX2/66 running Linux).
Packit 1c1d7e
Packit 1c1d7e
  \sa groupId(), owner(), ownerId()
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QString QFileInfo::group() const
Packit 1c1d7e
{
Packit 1c1d7e
    struct group *gr = getgrgid( groupId() );
Packit 1c1d7e
    if ( gr )
Packit 1c1d7e
	return QFile::decodeName( gr->gr_name );
Packit 1c1d7e
    return QString::null;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  Returns the id of the group the file belongs to.
Packit 1c1d7e
Packit 1c1d7e
  On systems where files do not have groups this function always
Packit 1c1d7e
  returns ((uind) -2).
Packit 1c1d7e
Packit 1c1d7e
  \sa group(), owner(), ownerId()
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
uint QFileInfo::groupId() const
Packit 1c1d7e
{
Packit 1c1d7e
    if ( !fic || !cache )
Packit 1c1d7e
	doStat();
Packit 1c1d7e
    if ( fic )
Packit 1c1d7e
	return fic->st.st_gid;
Packit 1c1d7e
    return nobodyID;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \fn bool QFileInfo::permission( int permissionSpec ) const
Packit 1c1d7e
Packit 1c1d7e
  Tests for file permissions.  The \e permissionSpec argument can be several
Packit 1c1d7e
  flags of type PermissionSpec or'ed together to check for permission
Packit 1c1d7e
  combinations.
Packit 1c1d7e
Packit 1c1d7e
  On systems where files do not have permissions this function always
Packit 1c1d7e
  returns TRUE.
Packit 1c1d7e
Packit 1c1d7e
  Example:
Packit 1c1d7e
  \code
Packit 1c1d7e
    QFileInfo fi( "/tmp/tonsils" );
Packit 1c1d7e
    if ( fi.permission( QFileInfo::WriteUser | QFileInfo::ReadGroup ) )
Packit 1c1d7e
	qWarning( "Tonsils can be changed by me, and the group can read them.");
Packit 1c1d7e
    if ( fi.permission( QFileInfo::WriteGroup | QFileInfo::WriteOther ) )
Packit 1c1d7e
	qWarning( "Danger! Tonsils can be changed by the group or others!" );
Packit 1c1d7e
  \endcode
Packit 1c1d7e
Packit 1c1d7e
  \sa isReadable(), isWritable(), isExecutable()
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
bool QFileInfo::permission( int permissionSpec ) const
Packit 1c1d7e
{
Packit 1c1d7e
    if ( !fic || !cache )
Packit 1c1d7e
	doStat();
Packit 1c1d7e
    if ( fic ) {
Packit 1c1d7e
	uint mask = 0;
Packit 1c1d7e
	if ( permissionSpec & ReadUser)
Packit 1c1d7e
	    mask |= S_IRUSR;
Packit 1c1d7e
	if ( permissionSpec & WriteUser)
Packit 1c1d7e
	    mask |= S_IWUSR;
Packit 1c1d7e
	if ( permissionSpec & ExeUser)
Packit 1c1d7e
	    mask |= S_IXUSR;
Packit 1c1d7e
	if ( permissionSpec & ReadGroup)
Packit 1c1d7e
	    mask |= S_IRGRP;
Packit 1c1d7e
	if ( permissionSpec & WriteGroup)
Packit 1c1d7e
	    mask |= S_IWGRP;
Packit 1c1d7e
	if ( permissionSpec & ExeGroup)
Packit 1c1d7e
	    mask |= S_IXGRP;
Packit 1c1d7e
	if ( permissionSpec & ReadOther)
Packit 1c1d7e
	    mask |= S_IROTH;
Packit 1c1d7e
	if ( permissionSpec & WriteOther)
Packit 1c1d7e
	    mask |= S_IWOTH;
Packit 1c1d7e
	if ( permissionSpec & ExeOther)
Packit 1c1d7e
	    mask |= S_IXOTH;
Packit 1c1d7e
	if ( mask ) {
Packit 1c1d7e
	   return (fic->st.st_mode & mask) == mask;
Packit 1c1d7e
	} else {
Packit 1c1d7e
#if defined(CHECK_NULL)
Packit 1c1d7e
	   qWarning( "QFileInfo::permission: permissionSpec is 0" );
Packit 1c1d7e
#endif
Packit 1c1d7e
	   return TRUE;
Packit 1c1d7e
	}
Packit 1c1d7e
    } else {
Packit 1c1d7e
	return FALSE;
Packit 1c1d7e
    }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  Returns the file size in bytes, or 0 if the file does not exist if the size
Packit 1c1d7e
  cannot be fetched.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
uint QFileInfo::size() const
Packit 1c1d7e
{
Packit 1c1d7e
    if ( !fic || !cache )
Packit 1c1d7e
	doStat();
Packit 1c1d7e
    if ( fic )
Packit 1c1d7e
	return (uint)fic->st.st_size;
Packit 1c1d7e
    else
Packit 1c1d7e
	return 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  Returns the date and time when the file was last modified.
Packit 1c1d7e
  \sa lastRead()
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QDateTime QFileInfo::lastModified() const
Packit 1c1d7e
{
Packit 1c1d7e
    QDateTime dt;
Packit 1c1d7e
    if ( !fic || !cache )
Packit 1c1d7e
	doStat();
Packit 1c1d7e
    if ( fic )
Packit 1c1d7e
	dt.setTime_t( (uint)fic->st.st_mtime );
Packit 1c1d7e
    return dt;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  Returns the date and time when the file was last read (accessed).
Packit 1c1d7e
Packit 1c1d7e
  On systems that do not support last read times, the modification time is
Packit 1c1d7e
  returned.
Packit 1c1d7e
Packit 1c1d7e
  \sa lastModified()
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QDateTime QFileInfo::lastRead() const
Packit 1c1d7e
{
Packit 1c1d7e
    QDateTime dt;
Packit 1c1d7e
    if ( !fic || !cache )
Packit 1c1d7e
	doStat();
Packit 1c1d7e
    if ( fic )
Packit 1c1d7e
	dt.setTime_t( (uint)fic->st.st_atime );
Packit 1c1d7e
    return dt;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
void QFileInfo::doStat() const
Packit 1c1d7e
{
Packit 1c1d7e
    QFileInfo *that = ((QFileInfo*)this);	// mutable function
Packit 1c1d7e
    if ( !that->fic )
Packit 1c1d7e
	that->fic = new QFileInfoCache;
Packit 1c1d7e
    STATBUF *b = &that->fic->st;
Packit 1c1d7e
    that->fic->isSymLink = FALSE;
Packit 1c1d7e
Packit 1c1d7e
#if defined(_OS_UNIX_) && defined(S_IFLNK)
Packit 1c1d7e
    if ( ::lstat(QFile::encodeName(fn),b) == 0 ) {
Packit 1c1d7e
	if ( S_ISLNK( b->st_mode ) )
Packit 1c1d7e
	    that->fic->isSymLink = TRUE;
Packit 1c1d7e
	else
Packit 1c1d7e
	    return;
Packit 1c1d7e
    }
Packit 1c1d7e
#endif
Packit 1c1d7e
    int r;
Packit 1c1d7e
Packit 1c1d7e
    r = STAT( QFile::encodeName(fn), b );
Packit 1c1d7e
Packit 1c1d7e
    if ( r != 0 ) {
Packit 1c1d7e
	delete that->fic;
Packit 1c1d7e
	that->fic = 0;
Packit 1c1d7e
    }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  Returns the directory path of the file.
Packit 1c1d7e
Packit 1c1d7e
  If \e absPath is TRUE an absolute path is always returned.
Packit 1c1d7e
Packit 1c1d7e
  \sa dir(), filePath(), fileName(), isRelative()
Packit 1c1d7e
*/
Packit 1c1d7e
#ifndef QT_NO_DIR
Packit 1c1d7e
QString QFileInfo::dirPath( bool absPath ) const
Packit 1c1d7e
{
Packit 1c1d7e
    QString s;
Packit 1c1d7e
    if ( absPath )
Packit 1c1d7e
	s = absFilePath();
Packit 1c1d7e
    else
Packit 1c1d7e
	s = fn;
Packit 1c1d7e
    int pos = s.findRev( '/' );
Packit 1c1d7e
    if ( pos == -1 ) {
Packit 1c1d7e
	return QString::fromLatin1(".");
Packit 1c1d7e
    } else {
Packit 1c1d7e
	if ( pos == 0 )
Packit 1c1d7e
	    return QString::fromLatin1( "/" );
Packit 1c1d7e
	return s.left( pos );
Packit 1c1d7e
    }
Packit 1c1d7e
}
Packit 1c1d7e
#endif
Packit 1c1d7e
/*!
Packit 1c1d7e
  Returns the name of the file, the file path is not included.
Packit 1c1d7e
Packit 1c1d7e
  Example:
Packit 1c1d7e
  \code
Packit 1c1d7e
     QFileInfo fi( "/tmp/abdomen.lower" );
Packit 1c1d7e
     QString name = fi.fileName();		// name = "abdomen.lower"
Packit 1c1d7e
  \endcode
Packit 1c1d7e
Packit 1c1d7e
  \sa isRelative(), filePath(), baseName(), extension()
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QString QFileInfo::fileName() const
Packit 1c1d7e
{
Packit 1c1d7e
    int p = fn.findRev( '/' );
Packit 1c1d7e
    if ( p == -1 ) {
Packit 1c1d7e
	return fn;
Packit 1c1d7e
    } else {
Packit 1c1d7e
	return fn.mid(p+1);
Packit 1c1d7e
    }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  Returns the absolute path name.
Packit 1c1d7e
Packit 1c1d7e
  The absolute path name is the file name including the absolute path. If
Packit 1c1d7e
  the QFileInfo is absolute (i.e. not relative) this function will return
Packit 1c1d7e
  the same string as filePath().
Packit 1c1d7e
Packit 1c1d7e
  Note that this function can be time-consuming under UNIX. (in the order
Packit 1c1d7e
  of milliseconds on a 486 DX2/66 running Linux).
Packit 1c1d7e
Packit 1c1d7e
  \sa isRelative(), filePath()
Packit 1c1d7e
*/
Packit 1c1d7e
#ifndef QT_NO_DIR
Packit 1c1d7e
QString QFileInfo::absFilePath() const
Packit 1c1d7e
{
Packit 1c1d7e
    if ( QDir::isRelativePath(fn) ) {
Packit 1c1d7e
	QString tmp = QDir::currentDirPath();
Packit 1c1d7e
	tmp += '/';
Packit 1c1d7e
	tmp += fn;
Packit 1c1d7e
	makeAbs( tmp );
Packit 1c1d7e
	return QDir::cleanDirPath( tmp );
Packit 1c1d7e
    } else {
Packit 1c1d7e
	QString tmp = fn;
Packit 1c1d7e
	makeAbs( tmp );
Packit 1c1d7e
	return QDir::cleanDirPath( tmp );
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
}
Packit 1c1d7e
#endif