kdelibs/kdecore/kernel/kstandarddirs.cpp

1513 lines
46 KiB
C++
Raw Normal View History

2014-11-13 01:04:59 +02:00
/* This file is part of the KDE libraries
Copyright (C) 1999 Sirtaj Singh Kang <taj@kde.org>
Copyright (C) 1999,2007 Stephan Kulow <coolo@kde.org>
Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
Copyright (C) 2009 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 version 2 as published by the Free Software Foundation.
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
/*
* Author: Stephan Kulow <coolo@kde.org> and Sirtaj Singh Kang <taj@kde.org>
* Generated: Thu Mar 5 16:05:28 EST 1998
*/
#include <config.h>
#include <config-prefix.h>
#include <config-kstandarddirs.h>
2014-11-13 01:04:59 +02:00
#include "kstandarddirs.h"
#include "kconfig.h"
#include "kconfiggroup.h"
#include "kdebug.h"
#include "kcomponentdata.h"
#include "kshell.h"
#include "kuser.h"
#include "kde_file.h"
#include "klocale.h"
#include <QtCore/QRegExp>
#include <QtCore/QDir>
#include <QtCore/QCache>
#include <QtCore/QFileInfo>
#include <QtCore/QSettings>
#include <QtCore/QStandardPaths>
2014-11-13 01:04:59 +02:00
#include <stdlib.h>
#include <assert.h>
#include <string.h>
2014-11-13 01:04:59 +02:00
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/types.h>
#include <dirent.h>
#include <mutex>
#define case_sensitivity Qt::CaseSensitive
2014-11-13 01:04:59 +02:00
#ifndef PATH_MAX
# define PATH_MAX _POSIX_PATH_MAX
#endif
// same as KPATH_SEPARATOR
static const QString s_pathseparator = QString::fromLatin1(":");
static const QChar s_pathseparatorchar = QChar::fromLatin1(KPATH_SEPARATOR);
static QString readEnvPath(const char *env)
{
QByteArray c_path;
c_path = qgetenv(env);
if (c_path.isEmpty())
return QString();
return QDir::fromNativeSeparators(QFile::decodeName(c_path));
}
static inline QStringList splitPath(const QString &path)
{
const int len = path.length();
QString token;
QStringList tokens;
for(int index = 0; index < len; index++) {
if (path.at(index) == s_pathseparatorchar) {
tokens.append(token);
token.clear();
} else {
token += path.at(index);
}
}
if (!token.isEmpty()) {
tokens.append(token);
}
return tokens;
}
static void priorityAdd(QStringList &prefixes, const QString& dir, bool priority)
{
if (priority && !prefixes.isEmpty())
{
// Add in front but behind $KDEHOME
QStringList::iterator it = prefixes.begin();
++it;
prefixes.insert(it, dir);
}
else
{
prefixes.append(dir);
}
}
static QString checkExecutable( const QString& path, bool ignoreExecBit )
{
QFileInfo info( path );
QFileInfo orig = info;
if( info.exists() && info.isSymLink() )
info = QFileInfo( info.canonicalFilePath() );
if( info.exists() && ( ignoreExecBit || info.isExecutable() ) && info.isFile() ) {
// return absolute path, but without symlinks resolved in order to prevent
// problems with executables that work differently depending on name they are
// run as (for example gunzip)
orig.makeAbsolute();
return orig.filePath();
}
//kDebug(180) << "checkExecutable(): failed, returning empty string";
return QString();
}
static quint32 updateHash(const QString &file, quint32 hash)
{
KDE_struct_stat buff;
if ((KDE::access(file, R_OK) == 0) && (KDE::stat(file, &buff) == 0) && (S_ISREG(buff.st_mode))) {
hash = hash + static_cast<quint32>(buff.st_ctime);
}
return hash;
}
static void lookupDirectory(const QString& path, const QString &relPart,
const QRegExp &regexp,
QStringList& list,
QStringList& relList,
bool recursive, bool unique)
{
const QString pattern = regexp.pattern();
if (recursive || pattern.contains(QLatin1Char('?')) || pattern.contains(QLatin1Char('*')))
{
if (path.isEmpty()) //for sanity
return;
// We look for a set of files.
DIR *dp = opendir( QFile::encodeName(path));
if (!dp)
return;
assert(path.endsWith(QLatin1Char('/')));
struct dirent *ep;
while( ( ep = readdir( dp ) ) != 0L )
{
QString fn( QFile::decodeName(ep->d_name));
if (fn == QString::fromLatin1(".") || fn == QString::fromLatin1("..") || fn.at(fn.length() - 1) == QLatin1Char('~'))
continue;
if (!recursive && !regexp.exactMatch(fn))
continue; // No match
bool isDir;
bool isReg;
QString pathfn = path + fn;
#ifdef HAVE_DIRENT_D_TYPE
isDir = ep->d_type == DT_DIR;
isReg = ep->d_type == DT_REG;
if (ep->d_type == DT_UNKNOWN || ep->d_type == DT_LNK)
#endif
{
KDE_struct_stat buff;
if ( KDE::stat( pathfn, &buff ) != 0 ) {
kDebug(180) << "Error stat'ing " << pathfn << " : " << ::strerror(errno);
continue; // Couldn't stat (e.g. no read permissions)
}
isReg = S_ISREG (buff.st_mode);
isDir = S_ISDIR (buff.st_mode);
}
if ( recursive ) {
if ( isDir ) {
lookupDirectory(pathfn + QLatin1Char('/'), relPart + fn + QLatin1Char('/'), regexp, list, relList, recursive, unique);
}
if (!regexp.exactMatch(fn))
continue; // No match
}
if ( isReg )
{
if (!unique || !relList.contains(relPart + fn, case_sensitivity))
{
list.append( pathfn );
relList.append( relPart + fn );
}
}
}
closedir( dp );
}
else
{
// We look for a single file.
QString fn = pattern;
QString pathfn = path + fn;
KDE_struct_stat buff;
if ( KDE::stat( pathfn, &buff ) != 0 )
return; // File not found
if ( S_ISREG( buff.st_mode))
{
if (!unique || !relList.contains(relPart + fn, case_sensitivity))
{
list.append( pathfn );
relList.append( relPart + fn );
}
}
}
}
static void lookupPrefix(const QString& prefix, const QString& relpath,
const QString& relPart,
const QRegExp &regexp,
QStringList& list,
QStringList& relList,
bool recursive, bool unique)
{
if (relpath.isEmpty()) {
if (recursive)
Q_ASSERT(prefix != QLatin1String("/")); // we don't want to recursively list the whole disk!
lookupDirectory(prefix, relPart, regexp, list,
relList, recursive, unique);
return;
}
QString path;
QString rest;
int slash = relpath.indexOf(QLatin1Char('/'));
if (slash < 0)
rest = relpath.left(relpath.length() - 1);
else {
path = relpath.left(slash);
rest = relpath.mid(slash + 1);
}
if (prefix.isEmpty()) //for sanity
return;
// what does this assert check ?
assert(prefix.endsWith(QLatin1Char('/')));
if (path.contains(QLatin1Char('*')) || path.contains(QLatin1Char('?'))) {
QRegExp pathExp(path, Qt::CaseSensitive, QRegExp::Wildcard);
DIR *dp = opendir( QFile::encodeName(prefix) );
if (!dp) {
return;
}
struct dirent *ep;
while( ( ep = readdir( dp ) ) != 0L )
{
QString fn( QFile::decodeName(ep->d_name));
if (fn == QLatin1String(".") || fn == QLatin1String("..") || fn.at(fn.length() - 1) == QLatin1Char('~'))
continue;
if ( !pathExp.exactMatch(fn) )
continue; // No match
QString rfn = relPart+fn;
fn = prefix + fn;
bool isDir;
#ifdef HAVE_DIRENT_D_TYPE
isDir = ep->d_type == DT_DIR;
if (ep->d_type == DT_UNKNOWN || ep->d_type == DT_LNK)
#endif
{
QString pathfn = path + fn;
KDE_struct_stat buff;
if ( KDE::stat( fn, &buff ) != 0 ) {
kDebug(180) << "Error stat'ing " << fn << " : " << ::strerror(errno);
continue; // Couldn't stat (e.g. no read permissions)
}
isDir = S_ISDIR (buff.st_mode);
}
if ( isDir )
lookupPrefix(fn + QLatin1Char('/'), rest, rfn + QLatin1Char('/'), regexp, list, relList, recursive, unique);
}
closedir( dp );
} else {
// Don't stat, if the dir doesn't exist we will find out
// when we try to open it.
lookupPrefix(prefix + path + QLatin1Char('/'), rest,
relPart + path + QLatin1Char('/'), regexp, list,
relList, recursive, unique);
}
}
#ifdef Q_OS_LINUX
static QString executablePrefix()
{
char path_buffer[PATH_MAX + 1];
path_buffer[PATH_MAX] = 0;
int length = readlink ("/proc/self/exe", path_buffer, PATH_MAX);
if (length == -1)
return QString();
path_buffer[length] = '\0';
QString path = QFile::decodeName(path_buffer);
if(path.isEmpty())
return QString();
int pos = path.lastIndexOf(QLatin1Char('/')); // Skip filename
if(pos <= 0)
return QString();
pos = path.lastIndexOf(QLatin1Char('/'), pos - 1); // Skip last directory
if(pos <= 0)
return QString();
return path.left(pos);
}
#endif
2014-11-13 01:04:59 +02:00
class KStandardDirs::KStandardDirsPrivate
{
public:
KStandardDirsPrivate(KStandardDirs* qq)
: q(qq)
{ }
2014-11-13 01:04:59 +02:00
QStringList resourceDirs(const char* type, const QString& subdirForRestrictions);
void createSpecialResource(const char*);
bool exists(const QString &fullPath);
QString realPath(const QString &dirname);
2014-11-13 01:04:59 +02:00
QStringList xdgdata_prefixes;
QStringList xdgconf_prefixes;
QStringList m_prefixes;
// Directory dictionaries
QMap<QByteArray, QStringList> m_absolutes; // For each resource type, the list of absolute paths, from most local (most priority) to most global
QMap<QByteArray, QStringList> m_relatives; // Same with relative paths
// The search path is "all relative paths" < "all absolute paths", from most priority to least priority.
// Caches (protected by mutex in const methods, cf ctor docu)
QMap<QByteArray, QStringList> m_dircache;
QMap<QByteArray, QString> m_savelocations;
std::recursive_mutex m_cacheMutex; // resourceDirs is recursive
2014-11-13 01:04:59 +02:00
KStandardDirs* q;
};
/* If you add a new resource type here, make sure to
2015-05-20 23:32:01 +00:00
* 1) regenerate using "generate_string_table.pl types < tmpfile" with the data below in tmpfile.
2014-11-13 01:04:59 +02:00
* 2) update the KStandardDirs class documentation
* 3) update the list in kde-config.cpp
data
share/apps
html
share/doc/HTML
icon
share/icons
config
share/config
pixmap
share/pixmaps
sound
share/sounds
locale
share/locale
services
2015-06-14 18:49:20 +03:00
share/kde4/services
2014-11-13 01:04:59 +02:00
servicetypes
2015-06-14 18:49:20 +03:00
share/kde4/servicetypes
2014-11-13 01:04:59 +02:00
wallpaper
share/wallpapers
templates
share/templates
exe
bin
module
2015-06-14 18:49:20 +03:00
%lib/kde4
2014-11-13 01:04:59 +02:00
qtplugins
2015-06-14 18:49:20 +03:00
%lib/kde4/plugins
2014-11-13 01:04:59 +02:00
kcfg
share/config.kcfg
xdgdata-apps
applications
xdgdata-icon
icons
xdgdata-pixmap
pixmaps
xdgdata-dirs
desktop-directories
xdgdata-mime
mime
xdgconf-menu
menus
xdgconf-autostart
autostart
*/
static const char types_string[] =
"data\0"
"share/apps\0"
"html\0"
"share/doc/HTML\0"
"icon\0"
"share/icons\0"
"config\0"
"share/config\0"
"pixmap\0"
"share/pixmaps\0"
"sound\0"
"share/sounds\0"
"locale\0"
"share/locale\0"
"services\0"
2015-06-14 18:49:20 +03:00
"share/kde4/services\0"
2014-11-13 01:04:59 +02:00
"servicetypes\0"
2015-06-14 18:49:20 +03:00
"share/kde4/servicetypes\0"
2014-11-13 01:04:59 +02:00
"wallpaper\0"
"share/wallpapers\0"
"templates\0"
"share/templates\0"
"exe\0"
"bin\0"
"module\0"
2015-06-14 18:49:20 +03:00
"%lib/kde4\0"
2014-11-13 01:04:59 +02:00
"qtplugins\0"
2015-06-14 18:49:20 +03:00
"%lib/kde4/plugins\0"
2014-11-13 01:04:59 +02:00
"kcfg\0"
"share/config.kcfg\0"
"xdgdata-apps\0"
"applications\0"
"xdgdata-icon\0"
"icons\0"
"xdgdata-pixmap\0"
"pixmaps\0"
"xdgdata-dirs\0"
"desktop-directories\0"
"xdgdata-mime\0"
"mime\0"
2014-11-13 01:04:59 +02:00
"xdgconf-menu\0"
"menus\0"
"xdgconf-autostart\0"
"autostart\0"
"\0";
static const int types_indices[] = {
2015-05-20 23:32:01 +00:00
0, 5, 16, 21, 36, 41, 53, 60,
73, 80, 94, 100, 113, 120, 133, 142,
162, 175, 199, 209, 226, 236, 252, 256,
260, 267, 277, 287, 305, 310, 328, 341,
354, 367, 373, 388, 396, 409, 429, 442,
447, 460, 466, 484, -1
2014-11-13 01:04:59 +02:00
};
KStandardDirs::KStandardDirs()
: d(new KStandardDirsPrivate(this))
{
addKDEDefaults();
}
KStandardDirs::~KStandardDirs()
{
delete d;
}
QStringList KStandardDirs::allTypes() const
{
QStringList list;
for (int i = 0; types_indices[i] != -1; i += 2)
list.append(QLatin1String(types_string + types_indices[i]));
// Those are added manually by addKDEDefaults
list.append(QString::fromLatin1("lib"));
//list.append(QString::fromLatin1("home")); // undocumented on purpose, said Waldo in r113855.
// Those are handled by resourceDirs() itself
list.append(QString::fromLatin1("tmp"));
list.append(QString::fromLatin1("cache"));
// Those are handled by installPath()
list.append(QString::fromLatin1("include"));
// If you add anything here, make sure kde-config.cpp has a description for it.
return list;
}
void KStandardDirs::addPrefix( const QString& _dir )
{
addPrefix(_dir, false);
}
void KStandardDirs::addPrefix( const QString& _dir, bool priority )
{
if (_dir.isEmpty())
return;
QString dir = _dir;
if (dir.at(dir.length() - 1) != QLatin1Char('/'))
dir += QLatin1Char('/');
if (!d->m_prefixes.contains(dir, case_sensitivity)) {
2014-11-13 01:04:59 +02:00
priorityAdd(d->m_prefixes, dir, priority);
d->m_dircache.clear();
}
}
void KStandardDirs::addXdgConfigPrefix( const QString& _dir )
{
addXdgConfigPrefix(_dir, false);
}
void KStandardDirs::addXdgConfigPrefix( const QString& _dir, bool priority )
{
if (_dir.isEmpty())
return;
QString dir = _dir;
if (dir.at(dir.length() - 1) != QLatin1Char('/'))
dir += QLatin1Char('/');
if (!d->xdgconf_prefixes.contains(dir, case_sensitivity)) {
2014-11-13 01:04:59 +02:00
priorityAdd(d->xdgconf_prefixes, dir, priority);
d->m_dircache.clear();
}
}
void KStandardDirs::addXdgDataPrefix( const QString& _dir )
{
addXdgDataPrefix(_dir, false);
}
void KStandardDirs::addXdgDataPrefix( const QString& _dir, bool priority )
{
if (_dir.isEmpty())
return;
QString dir = _dir;
if (dir.at(dir.length() - 1) != QLatin1Char('/'))
dir += QLatin1Char('/');
if (!d->xdgdata_prefixes.contains(dir, case_sensitivity)) {
2014-11-13 01:04:59 +02:00
priorityAdd(d->xdgdata_prefixes, dir, priority);
d->m_dircache.clear();
}
}
QString KStandardDirs::kfsstnd_prefixes()
{
return d->m_prefixes.join(s_pathseparator);
2014-11-13 01:04:59 +02:00
}
QString KStandardDirs::kfsstnd_xdg_conf_prefixes()
{
return d->xdgconf_prefixes.join(s_pathseparator);
2014-11-13 01:04:59 +02:00
}
QString KStandardDirs::kfsstnd_xdg_data_prefixes()
{
return d->xdgdata_prefixes.join(s_pathseparator);
2014-11-13 01:04:59 +02:00
}
bool KStandardDirs::addResourceType( const char *type,
const char *basetype,
const QString& relativename,
bool priority )
{
if (relativename.isEmpty())
return false;
QString copy = relativename;
if (basetype)
copy = QLatin1Char('%') + QString::fromLatin1(basetype) + QLatin1Char('/') + relativename;
if (!copy.endsWith(QLatin1Char('/')))
copy += QLatin1Char('/');
QByteArray typeBa = type;
QStringList& rels = d->m_relatives[typeBa]; // find or insert
if (!rels.contains(copy, case_sensitivity)) {
2014-11-13 01:04:59 +02:00
if (priority)
rels.prepend(copy);
else
rels.append(copy);
// clean the caches
d->m_dircache.remove(typeBa);
d->m_savelocations.remove(typeBa);
return true;
}
return false;
}
bool KStandardDirs::addResourceDir( const char *type,
const QString& absdir,
bool priority)
{
if (absdir.isEmpty() || !type)
return false;
// find or insert entry in the map
QString copy = absdir;
if (copy.at(copy.length() - 1) != QLatin1Char('/'))
copy += QLatin1Char('/');
QByteArray typeBa = type;
QStringList &paths = d->m_absolutes[typeBa];
if (!paths.contains(copy, case_sensitivity)) {
2014-11-13 01:04:59 +02:00
if (priority)
paths.prepend(copy);
else
paths.append(copy);
// clean the caches
d->m_dircache.remove(typeBa);
d->m_savelocations.remove(typeBa);
return true;
}
return false;
}
QString KStandardDirs::findResource( const char *type,
const QString& filename ) const
2014-11-13 01:04:59 +02:00
{
if (!QDir::isRelativePath(filename))
return !KGlobal::hasLocale() ? filename // absolute dirs are absolute dirs, right? :-/
: KGlobal::locale()->localizedFilePath(filename); // -- almost.
2014-11-13 01:04:59 +02:00
#if 0
kDebug(180) << "Find resource: " << type;
foreach (const QString &it, d->m_prefixes) {
kDebug(180) << "Prefix: " << it;
2014-11-13 01:04:59 +02:00
}
#endif
const QString dir = findResourceDir(type, filename);
if (dir.isEmpty())
return dir;
return !KGlobal::hasLocale() ? dir + filename
: KGlobal::locale()->localizedFilePath(dir + filename);
}
2014-11-13 01:04:59 +02:00
quint32 KStandardDirs::calcResourceHash( const char *type,
const QString& filename,
SearchOptions options ) const
{
quint32 hash = 0;
2014-11-13 01:04:59 +02:00
if (!QDir::isRelativePath(filename))
{
// absolute dirs are absolute dirs, right? :-/
return updateHash(filename, hash);
}
foreach ( const QString & it, d->resourceDirs(type, filename) )
{
hash = updateHash(it + filename, hash);
if ( !( options & Recursive ) && hash ) {
return hash;
2014-11-13 01:04:59 +02:00
}
}
return hash;
}
2014-11-13 01:04:59 +02:00
QStringList KStandardDirs::findDirs( const char *type,
const QString& reldir ) const
{
QDir testdir;
QStringList list;
if (!QDir::isRelativePath(reldir))
{
testdir.setPath(reldir);
if (testdir.exists())
2014-11-13 01:04:59 +02:00
{
if (reldir.endsWith(QLatin1Char('/')))
list.append(reldir);
else
list.append(reldir+QLatin1Char('/'));
}
return list;
}
2014-11-13 01:04:59 +02:00
const QStringList candidates = d->resourceDirs(type, reldir);
2014-11-13 01:04:59 +02:00
for (QStringList::ConstIterator it = candidates.begin();
it != candidates.end(); ++it) {
testdir.setPath(*it + reldir);
if (testdir.exists())
list.append(testdir.absolutePath() + QLatin1Char('/'));
}
2014-11-13 01:04:59 +02:00
return list;
}
2014-11-13 01:04:59 +02:00
QString KStandardDirs::findResourceDir( const char *type,
const QString& filename) const
{
#ifndef NDEBUG
if (filename.isEmpty()) {
kWarning() << "filename for type " << type << " in KStandardDirs::findResourceDir is not supposed to be empty!!";
return QString();
}
2014-11-13 01:04:59 +02:00
#endif
const QStringList candidates = d->resourceDirs(type, filename);
for (QStringList::ConstIterator it = candidates.begin();
it != candidates.end(); ++it) {
if (exists(*it + filename)) {
return *it;
2014-11-13 01:04:59 +02:00
}
}
2014-11-13 01:04:59 +02:00
#ifndef NDEBUG
if(false && strcmp(type, "locale"))
kDebug(180) << "KStdDirs::findResDir(): can't find \"" << filename << "\" in type \"" << type << "\".";
#endif
return QString();
}
bool KStandardDirs::exists(const QString &fullPath) const
{
return d->exists(fullPath);
}
bool KStandardDirs::KStandardDirsPrivate::exists(const QString &fullPath)
{
QFileInfo fileinfo(fullPath);
if (!fileinfo.isReadable()) {
return false;
} else if (!fullPath.endsWith(QLatin1Char('/'))) {
return !fileinfo.isDir() && fileinfo.exists();
2014-11-13 01:04:59 +02:00
} else {
return fileinfo.isDir() && fileinfo.exists();
2014-11-13 01:04:59 +02:00
}
}
QStringList
KStandardDirs::findAllResources( const char *type,
const QString& filter,
SearchOptions options,
QStringList &relList) const
{
QString filterPath;
QString filterFile;
if ( !filter.isEmpty() )
{
int slash = filter.lastIndexOf(QLatin1Char('/'));
if (slash < 0) {
filterFile = filter;
} else {
filterPath = filter.left(slash + 1);
filterFile = filter.mid(slash + 1);
}
}
QStringList candidates;
if ( !QDir::isRelativePath(filter) ) // absolute path
{
candidates << QString::fromLatin1("/");
filterPath = filterPath.mid(1);
}
else
{
candidates = d->resourceDirs(type, filter);
}
if (filterFile.isEmpty()) {
filterFile = QString(QLatin1Char('*'));
}
QRegExp regExp(filterFile, Qt::CaseSensitive, QRegExp::Wildcard);
QStringList list;
foreach ( const QString& candidate, candidates )
{
lookupPrefix(candidate, filterPath, QString(), regExp, list,
relList, options & Recursive, options & NoDuplicates);
}
return list;
}
QStringList
KStandardDirs::findAllResources( const char *type,
const QString& filter,
SearchOptions options ) const
{
QStringList relList;
return findAllResources(type, filter, options, relList);
}
// ####### KDE4: should this be removed, in favor of QDir::canonicalPath()?
// aseigo: QDir::canonicalPath returns QString() if the dir doesn't exist
// and this method is often used with the expectation for it to work
// even if the directory doesn't exist. so ... no, we can't drop this
// yet
QString
KStandardDirs::KStandardDirsPrivate::realPath(const QString &dirname)
2014-11-13 01:04:59 +02:00
{
if (dirname.isEmpty() || (dirname.size() == 1 && dirname.at(0) == QLatin1Char('/')))
return dirname;
if (dirname.at(0) != QLatin1Char('/')) {
qWarning("realPath called with a relative path '%s', please fix", qPrintable(dirname));
return dirname;
}
char realpath_buffer[PATH_MAX + 1];
memset(realpath_buffer, 0, PATH_MAX + 1);
2014-11-13 01:04:59 +02:00
/* If the path contains symlinks, get the real name */
if (realpath( QFile::encodeName(dirname).constData(), realpath_buffer) != 0) {
// success, use result from realpath
int len = strlen(realpath_buffer);
realpath_buffer[len] = '/';
realpath_buffer[len+1] = 0;
return QFile::decodeName(realpath_buffer);
}
// Does not exist yet; resolve symlinks in parent dirs then.
// This ensures that once the directory exists, it will still be resolved
// the same way, so that the general rule that KStandardDirs always returns
// canonical paths stays true, and app code can compare paths more easily.
QString dir = dirname;
if (!dir.endsWith(QLatin1Char('/')))
dir += QLatin1Char('/');
QString relative;
while (!exists(dir)) {
2014-11-13 01:04:59 +02:00
//qDebug() << "does not exist:" << dir;
const int pos = dir.lastIndexOf(QLatin1Char('/'), -2);
Q_ASSERT(pos >= 0); // what? even "/" doesn't exist?
relative.prepend(dir.mid(pos+1)); // keep "subdir/"
dir = dir.left(pos+1);
Q_ASSERT(dir.endsWith(QLatin1Char('/')));
}
Q_ASSERT(!relative.isEmpty()); // infinite recursion ahead
if (!relative.isEmpty()) {
//qDebug() << "done, resolving" << dir << "and adding" << relative;
dir = realPath(dir) + relative;
}
return dir;
}
QString
KStandardDirs::realPath(const QString &dirname) const
{
return d->realPath(dirname);
}
2014-11-13 01:04:59 +02:00
// ####### KDE4: should this be removed, in favor of QDir::canonicalPath()?
// aseigo: QDir::canonicalPath returns QString() if the dir doesn't exist
// and this method is often used with the expectation for it to work
// even if the directory doesn't exist. so ... no, we can't drop this
// yet
QString
KStandardDirs::realFilePath(const QString &filename)
{
char realpath_buffer[PATH_MAX + 1];
memset(realpath_buffer, 0, PATH_MAX + 1);
2014-11-13 01:04:59 +02:00
/* If the path contains symlinks, get the real name */
if (realpath( QFile::encodeName(filename).constData(), realpath_buffer) != 0) {
// success, use result from realpath
return QFile::decodeName(realpath_buffer);
}
return filename;
}
void KStandardDirs::KStandardDirsPrivate::createSpecialResource(const char *type)
{
QString resourceDir;
if (qstrcmp(type, "cache") == 0) {
resourceDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
resourceDir.append(QDir::separator());
resourceDir.append(QLatin1String("katana"));
} else if (qstrcmp(type, "tmp") == 0) {
resourceDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
// if the base directory is /tmp not /run/user/<uid> make sure it is user specific
resourceDir.append(QDir::separator());
resourceDir.append(QLatin1String("katana-"));
resourceDir.append(QString::number(::getuid()));
} else {
Q_ASSERT(false);
}
// NOTE: QStandardPaths::writableLocation() should create the base directory
const QString cleanPath = QDir::cleanPath(resourceDir) + QLatin1Char('/');
KStandardDirs::makeDir(cleanPath, 0700);
q->addResourceDir(type, cleanPath, false);
2014-11-13 01:04:59 +02:00
}
QStringList KStandardDirs::resourceDirs(const char *type) const
{
return d->resourceDirs(type, QString());
}
QStringList KStandardDirs::KStandardDirsPrivate::resourceDirs(const char* type, const QString& subdirForRestrictions)
{
std::lock_guard<std::recursive_mutex> lock(m_cacheMutex);
2014-11-13 01:04:59 +02:00
QMap<QByteArray, QStringList>::const_iterator dirCacheIt = m_dircache.constFind(type);
QStringList candidates;
if (dirCacheIt != m_dircache.constEnd()) {
2014-11-13 01:04:59 +02:00
//qDebug() << this << "resourceDirs(" << type << "), in cache already";
candidates = *dirCacheIt;
}
else // filling cache
{
//qDebug() << this << "resourceDirs(" << type << "), not in cache";
if (strcmp(type, "tmp") == 0 || strcmp(type, "cache") == 0)
2014-11-13 01:04:59 +02:00
createSpecialResource(type);
QDir testdir;
const QStringList dirs = m_relatives.value(type);
const QString typeInstallPath = installPath(type); // could be empty
const QString installdir = typeInstallPath.isEmpty() ? QString() : realPath(typeInstallPath);
const QString installprefix = installPath("kdedir");
if (!dirs.isEmpty())
{
bool local = true;
for (QStringList::ConstIterator it = dirs.constBegin();
it != dirs.constEnd(); ++it)
{
if ((*it).startsWith(QLatin1Char('%'))) {
// grab the "data" from "%data/apps"
const int pos = (*it).indexOf(QLatin1Char('/'));
QByteArray rel = (*it).mid(1, pos - 1).toUtf8();
2014-11-13 01:04:59 +02:00
QString rest = (*it).mid(pos + 1);
const QStringList basedirs = resourceDirs(rel.constData(), subdirForRestrictions);
2014-11-13 01:04:59 +02:00
for (QStringList::ConstIterator it2 = basedirs.begin();
it2 != basedirs.end(); ++it2)
{
const QString path = realPath( *it2 + rest );
testdir.setPath(path);
if ((local || testdir.exists()) && !candidates.contains(path, case_sensitivity))
2014-11-13 01:04:59 +02:00
candidates.append(path);
local = false;
}
}
}
const QStringList *prefixList = 0;
if (strncmp(type, "xdgdata-", 8) == 0)
prefixList = &(xdgdata_prefixes);
else if (strncmp(type, "xdgconf-", 8) == 0)
prefixList = &(xdgconf_prefixes);
else
prefixList = &m_prefixes;
for (QStringList::ConstIterator pit = prefixList->begin();
pit != prefixList->end();
++pit)
{
if((*pit).compare(installprefix, case_sensitivity) != 0 || installdir.isEmpty())
2014-11-13 01:04:59 +02:00
{
for (QStringList::ConstIterator it = dirs.constBegin();
it != dirs.constEnd(); ++it)
{
if ((*it).startsWith(QLatin1Char('%')))
continue;
const QString path = realPath( *pit + *it );
testdir.setPath(path);
if ((local || testdir.exists()) && !candidates.contains(path, case_sensitivity))
2014-11-13 01:04:59 +02:00
candidates.append(path);
}
local = false;
}
else
{
// we have a custom install path, so use this instead of <installprefix>/<relative dir>
testdir.setPath(installdir);
if(testdir.exists() && ! candidates.contains(installdir, case_sensitivity))
2014-11-13 01:04:59 +02:00
candidates.append(installdir);
}
}
}
// make sure we find the path where it's installed
if (!installdir.isEmpty()) {
bool ok = true;
foreach (const QString &s, candidates) {
if (installdir.startsWith(s, case_sensitivity)) {
2014-11-13 01:04:59 +02:00
ok = false;
break;
}
}
if (ok)
candidates.append(installdir);
}
const QStringList absDirs = m_absolutes.value(type);
for (QStringList::ConstIterator it = absDirs.constBegin();
it != absDirs.constEnd(); ++it)
{
testdir.setPath(*it);
if (testdir.exists()) {
const QString filename = realPath( *it );
if (!candidates.contains(filename, case_sensitivity)) {
2014-11-13 01:04:59 +02:00
candidates.append(filename);
}
}
}
// Insert result into the cache for next time.
//kDebug() << this << "Inserting" << type << candidates << "into dircache";
m_dircache.insert(type, candidates);
2014-11-13 01:04:59 +02:00
}
#if 0
kDebug(180) << "found dirs for resource" << type << ":" << candidates;
#endif
return candidates;
}
QStringList KStandardDirs::systemPaths( const QString& pstr )
{
QStringList tokens;
if( pstr.isEmpty() ) {
tokens = splitPath( QString::fromLocal8Bit( qgetenv( "PATH" ) ) );
} else {
tokens = splitPath( pstr );
2014-11-13 01:04:59 +02:00
}
QStringList exePaths;
// split path using : as delimiters
2014-11-13 01:04:59 +02:00
for( int i = 0; i < tokens.count(); i++ )
{
exePaths << KShell::tildeExpand( tokens.at(i) );
2014-11-13 01:04:59 +02:00
}
return exePaths;
}
QString KStandardDirs::findExe( const QString& appname,
const QString& pstr,
SearchOptions options )
{
//kDebug(180) << "findExe(" << appname << ", pstr, " << ignoreExecBit << ") called";
QFileInfo info;
// absolute or relative path?
if (appname.contains(QDir::separator()))
{
//kDebug(180) << "findExe(): absolute path given";
return checkExecutable(appname, options & IgnoreExecBit);
2014-11-13 01:04:59 +02:00
}
//kDebug(180) << "findExe(): relative path given";
QString p = installPath("libexec") + appname;
QString result = checkExecutable(p, options & IgnoreExecBit);
if (!result.isEmpty()) {
//kDebug(180) << "findExe(): returning " << result;
return result;
}
//kDebug(180) << "findExe(): checking system paths";
foreach (const QString &it, systemPaths( pstr ))
2014-11-13 01:04:59 +02:00
{
p = it + QLatin1Char('/') + appname;
2014-11-13 01:04:59 +02:00
// Check for executable in this tokenized path
result = checkExecutable(p, options & IgnoreExecBit);
if (!result.isEmpty()) {
//kDebug(180) << "findExe(): returning " << result;
return result;
}
}
// Not found in PATH, look into the KDE-specific bin dir ("exe" resource)
p = installPath("exe") + appname;
2014-11-13 01:04:59 +02:00
result = checkExecutable(p, options & IgnoreExecBit);
if (!result.isEmpty()) {
//kDebug(180) << "findExe(): returning " << result;
return result;
}
// If we reach here, the executable wasn't found.
// So return empty string.
//kDebug(180) << "findExe(): failed, nothing matched";
return QString();
}
QString KStandardDirs::findRootExe( const QString& appname,
const QString& pstr,
SearchOptions options )
{
QStringList exePaths = systemPaths( pstr );
static const QStringList rootPaths = QStringList()
<< QLatin1String("/sbin")
<< QLatin1String("/usr/sbin")
<< QLatin1String("/usr/local/sbin")
<< QLatin1String(KDEDIR "/sbin");
foreach (const QString &rootPath, rootPaths) {
if (exePaths.contains(rootPath) || !QDir(rootPath).exists()) {
continue;
}
exePaths << rootPath;
}
return findExe(appname, exePaths.join(s_pathseparator), options);
}
2014-11-13 01:04:59 +02:00
int KStandardDirs::findAllExe( QStringList& list, const QString& appname,
const QString& pstr, SearchOptions options )
{
QFileInfo info;
QString p;
list.clear();
const QStringList exePaths = systemPaths( pstr );
for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
{
p = (*it) + QLatin1Char('/');
p += appname;
info.setFile( p );
if( info.exists() && ( ( options & IgnoreExecBit ) || info.isExecutable())
&& info.isFile() ) {
list.append( p );
}
}
return list.count();
}
QString KStandardDirs::saveLocation(const char *type,
const QString& suffix,
bool create) const
{
std::lock_guard<std::recursive_mutex> lock(d->m_cacheMutex);
2014-11-13 01:04:59 +02:00
QString path = d->m_savelocations.value(type);
if (path.isEmpty())
{
QStringList dirs = d->m_relatives.value(type);
if (dirs.isEmpty() && (strcmp(type, "tmp") == 0 || strcmp(type, "cache") == 0))
2014-11-13 01:04:59 +02:00
{
(void) resourceDirs(type); // Generate tmp|cache resource.
2014-11-13 01:04:59 +02:00
dirs = d->m_relatives.value(type); // Search again.
}
if (!dirs.isEmpty())
{
path = dirs.first();
if (path.startsWith(QLatin1Char('%'))) {
// grab the "data" from "%data/apps"
const int pos = path.indexOf(QLatin1Char('/'));
QByteArray rel = path.mid(1, pos - 1).toUtf8();
2014-11-13 01:04:59 +02:00
QString rest = path.mid(pos + 1);
QString basepath = saveLocation(rel.constData());
2014-11-13 01:04:59 +02:00
path = basepath + rest;
} else
// Check for existence of typed directory + suffix
if (strncmp(type, "xdgdata-", 8) == 0) {
path = realPath( localxdgdatadir() + path ) ;
} else if (strncmp(type, "xdgconf-", 8) == 0) {
path = realPath( localxdgconfdir() + path );
} else {
path = realPath( localkdedir() + path );
}
}
else {
dirs = d->m_absolutes.value(type);
if (dirs.isEmpty()) {
qFatal("KStandardDirs: The resource type %s is not registered", type);
} else {
path = realPath(dirs.first());
}
}
d->m_savelocations.insert(type, path.endsWith(QLatin1Char('/')) ? path : path + QLatin1Char('/'));
}
QString fullPath = path + suffix;
KDE_struct_stat st;
if (KDE::stat(fullPath, &st) != 0 || !(S_ISDIR(st.st_mode))) {
if(!create) {
#ifndef NDEBUG
// Too much noise from kbuildsycoca4 -- it's fine if this happens from KConfig
// when parsing global files without a local equivalent.
//kDebug(180) << QString("save location %1 doesn't exist").arg(fullPath);
#endif
return fullPath;
}
if(!KStandardDirs::makeDir(fullPath, 0700)) {
2014-11-13 01:04:59 +02:00
return fullPath;
}
d->m_dircache.remove(type);
}
if (!fullPath.endsWith(QLatin1Char('/')))
fullPath += QLatin1Char('/');
return fullPath;
}
QString KStandardDirs::relativeLocation(const char *type, const QString &absPath) const
2014-11-13 01:04:59 +02:00
{
QString fullPath = absPath;
int i = absPath.lastIndexOf(QLatin1Char('/'));
if (i != -1) {
fullPath = realFilePath(absPath); // Normalize
}
foreach (const QString &it, resourceDirs(type)) {
if (fullPath.startsWith(it, case_sensitivity)) {
return fullPath.mid(it.length());
2014-11-13 01:04:59 +02:00
}
}
return absPath;
}
bool KStandardDirs::makeDir(const QString& dir, int mode)
{
// we want an absolute path
if (QDir::isRelativePath(dir))
return false;
QString target = dir;
uint len = target.length();
// append trailing slash if missing
if (dir.at(len - 1) != QLatin1Char('/'))
target += QLatin1Char('/');
QString base;
uint i = 1;
while( i < len )
{
KDE_struct_stat st;
int pos = target.indexOf(QLatin1Char('/'), i);
base += target.mid(i - 1, pos - i + 1);
QByteArray baseEncoded = QFile::encodeName(base);
// bail out if we encountered a problem
if (KDE_stat(baseEncoded, &st) != 0)
{
// Directory does not exist....
// Or maybe a dangling symlink ?
if (KDE_lstat(baseEncoded, &st) == 0)
(void)unlink(baseEncoded); // try removing
if (KDE_mkdir(baseEncoded, static_cast<mode_t>(mode)) != 0) {
baseEncoded.prepend( "trying to create local folder " );
perror(baseEncoded.constData());
return false; // Couldn't create it :-(
}
}
i = pos + 1;
}
return true;
}
void KStandardDirs::addKDEDefaults()
{
QStringList kdedirList;
// begin KDEDIRS
QString kdedirs = readEnvPath("KDEDIRS");
if (!kdedirs.isEmpty())
{
kdedirList = splitPath(kdedirs);
2014-11-13 01:04:59 +02:00
}
kdedirList.append(installPath("kdedir"));
QString execPrefix(QFile::decodeName(EXEC_INSTALL_PREFIX));
if (!execPrefix.isEmpty() && !kdedirList.contains(execPrefix, case_sensitivity))
2014-11-13 01:04:59 +02:00
kdedirList.append(execPrefix);
#ifdef Q_OS_LINUX
2014-11-13 01:04:59 +02:00
const QString linuxExecPrefix = executablePrefix();
if ( !linuxExecPrefix.isEmpty() )
kdedirList.append( linuxExecPrefix );
#endif
// We treat root differently to prevent a "su" shell messing up the
// file permissions in the user's home directory.
QString localKdeDir = readEnvPath(getuid() ? "KDEHOME" : "KDEROOTHOME");
if (!localKdeDir.isEmpty()) {
if (!localKdeDir.endsWith(QLatin1Char('/')))
localKdeDir += QLatin1Char('/');
} else {
// TODO KDE5: make localKdeDir equal to localXdgDir (which is determined further below and
// defaults to ~/.config) + '/' + $KDECONFIG (which would default to e.g. "KDE")
// This would mean ~/.config/KDE/ by default, more xdg-compliant.
localKdeDir = QDir::homePath() + QLatin1Char('/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char('/');
}
if (localKdeDir != QLatin1String("-/")) {
2014-11-13 01:04:59 +02:00
localKdeDir = KShell::tildeExpand(localKdeDir);
addPrefix(localKdeDir);
}
foreach (const QString &it, kdedirList) {
addPrefix(KShell::tildeExpand(it));
2014-11-13 01:04:59 +02:00
}
// end KDEDIRS
// begin XDG_CONFIG_XXX
QStringList xdgdirList;
QString xdgdirs = readEnvPath("XDG_CONFIG_DIRS");
if (!xdgdirs.isEmpty())
{
xdgdirList = splitPath(xdgdirs);
2014-11-13 01:04:59 +02:00
}
else
{
xdgdirList.clear();
xdgdirList.append(QString::fromLatin1("/etc/xdg"));
xdgdirList.append(QFile::decodeName(SYSCONF_INSTALL_DIR "/xdg"));
2014-11-13 01:04:59 +02:00
}
QString localXdgDir = readEnvPath("XDG_CONFIG_HOME");
if (!localXdgDir.isEmpty()) {
if (!localXdgDir.endsWith(QLatin1Char('/')))
localXdgDir += QLatin1Char('/');
} else {
localXdgDir = QDir::homePath() + QString::fromLatin1("/.config/");
}
localXdgDir = KShell::tildeExpand(localXdgDir);
addXdgConfigPrefix(localXdgDir);
for (QStringList::ConstIterator it = xdgdirList.constBegin();
it != xdgdirList.constEnd(); ++it)
{
QString dir = KShell::tildeExpand(*it);
addXdgConfigPrefix(dir);
}
// end XDG_CONFIG_XXX
// begin XDG_DATA_XXX
QStringList kdedirDataDirs;
foreach (const QString &it, kdedirList) {
if (!it.endsWith(QLatin1Char('/'))) {
kdedirDataDirs.append(it + QLatin1String("/share/"));
} else {
kdedirDataDirs.append(it + QLatin1String("share/"));
}
2014-11-13 01:04:59 +02:00
}
xdgdirs = readEnvPath("XDG_DATA_DIRS");
if (!xdgdirs.isEmpty()) {
xdgdirList = splitPath(xdgdirs);
2014-11-13 01:04:59 +02:00
// Ensure the kdedirDataDirs are in there too,
2015-06-14 18:49:20 +03:00
// otherwise resourceDirs() will add kdedir/share/applications/kde4
2014-11-13 01:04:59 +02:00
// as returned by installPath(), and that's incorrect.
Q_FOREACH(const QString& dir, kdedirDataDirs) {
if (!xdgdirList.contains(dir, case_sensitivity))
2014-11-13 01:04:59 +02:00
xdgdirList.append(dir);
}
} else {
xdgdirList = kdedirDataDirs;
xdgdirList.append(QString::fromLatin1("/usr/local/share/"));
xdgdirList.append(QString::fromLatin1("/usr/share/"));
2015-05-20 23:32:01 +00:00
xdgdirList.append(QString::fromLatin1("/share/"));
2014-11-13 01:04:59 +02:00
}
localXdgDir = readEnvPath("XDG_DATA_HOME");
if (!localXdgDir.isEmpty())
{
if (localXdgDir[localXdgDir.length()-1] != QLatin1Char('/'))
localXdgDir += QLatin1Char('/');
}
else
{
localXdgDir = QDir::homePath() + QLatin1String("/.local/share/");
}
localXdgDir = KShell::tildeExpand(localXdgDir);
addXdgDataPrefix(localXdgDir);
for (QStringList::ConstIterator it = xdgdirList.constBegin();
it != xdgdirList.constEnd(); ++it)
{
QString dir = KShell::tildeExpand(*it);
addXdgDataPrefix(dir);
}
// end XDG_DATA_XXX
generic: replace installation paths with KDE4_ prefixed this is TODO from issue #9. CPack and CTest configs will not be supported. most of the changes done to other repisitories is automated via: find -type f -exec sed -i -e 's|${INSTALL_DIR}|${KDE4_INSTALL_DIR}|g' \ -e 's|${EXEC_INSTALL_PREFIX}|${KDE4_EXEC_INSTALL_PREFIX}|g' \ -e 's|${SHARE_INSTALL_PREFIX}|${KDE4_SHARE_INSTALL_PREFIX}|g' \ -e 's|${BIN_INSTALL_DIR}|${KDE4_BIN_INSTALL_DIR}|g' \ -e 's|${SBIN_INSTALL_DIR}|${KDE4_SBIN_INSTALL_DIR}|g' \ -e 's|${LIB_INSTALL_DIR}|${KDE4_LIB_INSTALL_DIR}|g' \ -e 's|${LIBEXEC_INSTALL_DIR}|${KDE4_LIBEXEC_INSTALL_DIR}|g' \ -e 's|${INCLUDE_INSTALL_DIR}|${KDE4_INCLUDE_INSTALL_DIR}|g' \ -e 's|${PLUGIN_INSTALL_DIR}|${KDE4_PLUGIN_INSTALL_DIR}|g' \ -e 's|${IMPORTS_INSTALL_DIR}|${KDE4_IMPORTS_INSTALL_DIR}|g' \ -e 's|${CONFIG_INSTALL_DIR}|${KDE4_CONFIG_INSTALL_DIR}|g' \ -e 's|${DATA_INSTALL_DIR}|${KDE4_DATA_INSTALL_DIR}|g' \ -e 's|${ICON_INSTALL_DIR}|${KDE4_ICON_INSTALL_DIR}|g' \ -e 's|${KCFG_INSTALL_DIR}|${KDE4_KCFG_INSTALL_DIR}|g' \ -e 's|${LOCALE_INSTALL_DIR}|${KDE4_LOCALE_INSTALL_DIR}|g' \ -e 's|${MIME_INSTALL_DIR}|${KDE4_MIME_INSTALL_DIR}|g' \ -e 's|${SERVICES_INSTALL_DIR}|${KDE4_SERVICES_INSTALL_DIR}|g' \ -e 's|${SERVICETYPES_INSTALL_DIR}|${KDE4_SERVICETYPES_INSTALL_DIR}|g' \ -e 's|${SOUND_INSTALL_DIR}|${KDE4_SOUND_INSTALL_DIR}|g' \ -e 's|${TEMPLATES_INSTALL_DIR}|${KDE4_TEMPLATES_INSTALL_DIR}|g' \ -e 's|${WALLPAPER_INSTALL_DIR}|${KDE4_WALLPAPER_INSTALL_DIR}|g' \ -e 's|${AUTOSTART_INSTALL_DIR}|${KDE4_AUTOSTART_INSTALL_DIR}|g' \ -e 's|${XDG_APPS_INSTALL_DIR}|${KDE4_XDG_APPS_INSTALL_DIR}|g' \ -e 's|${XDG_DIRECTORY_INSTALL_DIR}|${KDE4_XDG_DIRECTORY_INSTALL_DIR}|g' \ -e 's|${XDG_MIME_INSTALL_DIR}|${KDE4_XDG_MIME_INSTALL_DIR}|g' \ -e 's|${SYSCONF_INSTALL_DIR}|${KDE4_SYSCONF_INSTALL_DIR}|g' \ -e 's|${MAN_INSTALL_DIR}|${KDE4_MAN_INSTALL_DIR}|g' \ -e 's|${INFO_INSTALL_DIR}|${KDE4_INFO_INSTALL_DIR}|g' \ -e 's|${DBUS_INTERFACES_INSTALL_DIR}|${KDE4_DBUS_INTERFACES_INSTALL_DIR}|g' \ -e 's|${DBUS_SERVICES_INSTALL_DIR}|${KDE4_DBUS_SERVICES_INSTALL_DIR}|g' \ -e 's|${DBUS_SYSTEM_SERVICES_INSTALL_DIR}|${KDE4_DBUS_SYSTEM_SERVICES_INSTALL_DIR}|g' \ -e 's|${KAUTH_HELPER_PLUGIN_DIR}|${KDE4_KAUTH_HELPER_PLUGIN_DIR}|g' \ -e 's|${KAUTH_BACKEND_PLUGIN_DIR}|${KDE4_KAUTH_BACKEND_PLUGIN_DIR}|g' {} + note that if you execute this command you may corrupt the git repository files so move the .git directory out of the way. you can also verify that there are no other reference to the compatibility installation paths via: git grep \ -e INSTALL_DIR \ -e EXEC_INSTALL_PREFIX \ -e SHARE_INSTALL_PREFIX \ -e BIN_INSTALL_DIR \ -e SBIN_INSTALL_DIR \ -e LIB_INSTALL_DIR \ -e LIBEXEC_INSTALL_DIR \ -e INCLUDE_INSTALL_DIR \ -e PLUGIN_INSTALL_DIR \ -e IMPORTS_INSTALL_DIR \ -e CONFIG_INSTALL_DIR \ -e DATA_INSTALL_DIR \ -e ICON_INSTALL_DIR \ -e KCFG_INSTALL_DIR \ -e LOCALE_INSTALL_DIR \ -e MIME_INSTALL_DIR \ -e SERVICES_INSTALL_DIR \ -e SERVICETYPES_INSTALL_DIR \ -e SOUND_INSTALL_DIR \ -e TEMPLATES_INSTALL_DIR \ -e WALLPAPER_INSTALL_DIR \ -e AUTOSTART_INSTALL_DIR \ -e XDG_APPS_INSTALL_DIR \ -e XDG_DIRECTORY_INSTALL_DIR \ -e XDG_MIME_INSTALL_DIR \ -e SYSCONF_INSTALL_DIR \ -e MAN_INSTALL_DIR \ -e INFO_INSTALL_DIR \ -e DBUS_INTERFACES_INSTALL_DIR \ -e DBUS_SERVICES_INSTALL_DIR \ -e DBUS_SYSTEM_SERVICES_INSTALL_DIR \ -e KAUTH_HELPER_PLUGIN_DIR \ -e KAUTH_BACKEND_PLUGIN_DIR | grep -v KDE4_ this change should make default installation Filesystem Hierarchy Standard (FHS) compliant and packaging easier since library suffix (e.g. 64 for x86_64 hosts) will not have to be specified explicitly, it may solve possible conflicts with installation path variables from other projects which use custom installation paths aswell Signed-off-by: Ivailo Monev <xakepa10@laimg.moc>
2020-02-08 20:46:43 +00:00
addResourceDir("lib", QLatin1String(LIB_INSTALL_DIR "/"), true);
addResourceDir("exe", QLatin1String(LIBEXEC_INSTALL_DIR), true );
2014-11-13 01:04:59 +02:00
addResourceType("qtplugins", "lib", QLatin1String("plugins"));
2014-11-13 01:04:59 +02:00
uint index = 0;
while (types_indices[index] != -1) {
addResourceType(types_string + types_indices[index], 0,
QLatin1String(types_string + types_indices[index+1]), true);
2014-11-13 01:04:59 +02:00
index+=2;
}
addResourceDir("home", QDir::homePath(), false);
addResourceType("autostart", "xdgconf-autostart", QLatin1String("/")); // merge them, start with xdg autostart
addResourceType("autostart", NULL, QLatin1String("share/autostart")); // KDE ones are higher priority
2014-11-13 01:04:59 +02:00
}
QString KStandardDirs::localkdedir() const
{
// Return the prefix to use for saving
return d->m_prefixes.first();
}
QString KStandardDirs::localxdgdatadir() const
{
// Return the prefix to use for saving
return d->xdgdata_prefixes.first();
}
QString KStandardDirs::localxdgconfdir() const
{
// Return the prefix to use for saving
return d->xdgconf_prefixes.first();
}
// just to make code more readable without macros
QString KStandardDirs::locate( const char *type,
const QString& filename, const KComponentData &cData)
{
return cData.dirs()->findResource(type, filename);
}
QString KStandardDirs::locateLocal( const char *type,
const QString& filename, const KComponentData &cData)
{
return locateLocal(type, filename, true, cData);
}
QString KStandardDirs::locateLocal( const char *type,
const QString& filename, bool createDir,
const KComponentData &cData)
{
// try to find slashes. If there are some, we have to
// create the subdir first
int slash = filename.lastIndexOf(QLatin1Char('/')) + 1;
if (!slash) { // only one filename
return cData.dirs()->saveLocation(type, QString(), createDir) + filename;
}
// split path from filename
QString dir = filename.left(slash);
QString file = filename.mid(slash);
return cData.dirs()->saveLocation(type, dir, createDir) + file;
}
bool KStandardDirs::checkAccess(const QString& pathname, int mode)
{
int accessOK = KDE::access( pathname, mode );
if ( accessOK == 0 )
return true; // OK, I can really access the file
// else
// if we want to write the file would be created. Check, if the
// user may write to the directory to create the file.
if ( (mode & W_OK) == 0 )
return false; // Check for write access is not part of mode => bail out
if (!KDE::access( pathname, F_OK)) // if it already exists
return false;
//strip the filename (everything until '/' from the end
QString dirName(pathname);
int pos = dirName.lastIndexOf(QLatin1Char('/'));
if ( pos == -1 )
return false; // No path in argument. This is evil, we won't allow this
else if ( pos == 0 ) // don't turn e.g. /root into an empty string
pos = 1;
dirName.truncate(pos); // strip everything starting from the last '/'
accessOK = KDE::access( dirName, W_OK );
// -?- Can I write to the accessed diretory
if ( accessOK == 0 )
return true; // Yes
else
return false; // No
}