40 #include <config-prefix.h>
41 #include <config-kstandarddirs.h>
46 #ifdef HAVE_SYS_STAT_H
52 #include <sys/param.h>
53 #include <sys/types.h>
64 #define interface struct
67 #include <QtCore/QVarLengthArray>
70 #include <QtCore/QMutex>
71 #include <QtCore/QRegExp>
72 #include <QtCore/QDir>
73 #include <QtCore/QFileInfo>
74 #include <QtCore/QSettings>
76 class KStandardDirs::KStandardDirsPrivate
80 : m_restrictionsActive(false),
81 m_checkRestrictions(true),
86 bool hasDataRestrictions(
const QString &relPath)
const;
88 void createSpecialResource(
const char*);
90 bool m_restrictionsActive : 1;
91 bool m_checkRestrictions : 1;
188 "share/kde4/services\0"
190 "share/kde4/servicetypes\0"
204 "%lib/kde4/plugins\0"
206 "share/config.kcfg\0"
216 "desktop-directories\0"
220 "xdgconf-autostart\0"
225 0, 5, 16, 21, 36, 41, 53, 60,
226 73, 80, 94, 99, 112, 118, 131, 138,
227 151, 160, 180, 193, 217, 222, 236, 240,
228 248, 258, 275, 285, 301, 305, 309, 316,
229 326, 336, 354, 359, 377, 387, 403, 416,
230 429, 442, 448, 463, 471, 484, 504, 217,
231 517, 530, 536, 554, -1
238 : d(new KStandardDirsPrivate(this))
250 if (!d->m_restrictionsActive)
253 if (d->m_restrictions.value(type,
false))
256 if (strcmp(type,
"data")==0 && d->hasDataRestrictions(relPath))
262 bool KStandardDirs::KStandardDirsPrivate::hasDataRestrictions(
const QString &relPath)
const
265 const int i = relPath.indexOf(QLatin1Char(
'/'));
267 key = QString::fromLatin1(
"data_") + relPath.left(i);
269 key = QString::fromLatin1(
"data_") + relPath;
271 return m_restrictions.value(key.toLatin1(),
false);
281 list.append(QString::fromLatin1(
"lib"));
285 list.append(QString::fromLatin1(
"socket"));
286 list.append(QString::fromLatin1(
"tmp"));
287 list.append(QString::fromLatin1(
"cache"));
289 list.append(QString::fromLatin1(
"include"));
298 if (priority && !prefixes.isEmpty())
301 QStringList::iterator it = prefixes.begin();
303 prefixes.insert(it, dir);
307 prefixes.append(dir);
322 if (dir.at(dir.length() - 1) != QLatin1Char(
'/'))
323 dir += QLatin1Char(
'/');
325 if (!d->m_prefixes.contains(dir)) {
327 d->m_dircache.clear();
342 if (dir.at(dir.length() - 1) != QLatin1Char(
'/'))
343 dir += QLatin1Char(
'/');
345 if (!d->xdgconf_prefixes.contains(dir)) {
347 d->m_dircache.clear();
362 if (dir.at(dir.length() - 1) != QLatin1Char(
'/'))
363 dir += QLatin1Char(
'/');
365 if (!d->xdgdata_prefixes.contains(dir)) {
367 d->m_dircache.clear();
373 return d->m_prefixes.join(
QString(QLatin1Char(KPATH_SEPARATOR)));
378 return d->xdgconf_prefixes.join(
QString(QLatin1Char(KPATH_SEPARATOR)));
383 return d->xdgdata_prefixes.join(
QString(QLatin1Char(KPATH_SEPARATOR)));
386 #ifndef KDE_NO_DEPRECATED
396 const char *basetype,
400 if (relativename.isEmpty())
405 copy = QLatin1Char(
'%') + QString::fromLatin1(basetype) + QLatin1Char(
'/') + relativename;
407 if (!copy.endsWith(QLatin1Char(
'/')))
408 copy += QLatin1Char(
'/');
410 QByteArray typeBa = type;
413 if (!rels.contains(copy)) {
419 d->m_dircache.remove(typeBa);
420 d->m_savelocations.remove(typeBa);
430 if (absdir.isEmpty() || !type)
434 if (copy.at(copy.length() - 1) != QLatin1Char(
'/'))
435 copy += QLatin1Char(
'/');
437 QByteArray typeBa = type;
439 if (!paths.contains(copy)) {
445 d->m_dircache.remove(typeBa);
446 d->m_savelocations.remove(typeBa);
453 const QString& _filename )
const
455 if (!QDir::isRelativePath(_filename))
460 kDebug(180) <<
"Find resource: " << type;
461 for (QStringList::ConstIterator pit = m_prefixes.begin();
462 pit != m_prefixes.end();
465 kDebug(180) <<
"Prefix: " << *pit;
471 if(strcmp(type,
"exe") == 0) {
472 if(!filename.endsWith(QLatin1String(
".exe")))
473 filename += QLatin1String(
".exe");
486 KDE_struct_stat buff;
487 if ((
KDE::access(file, R_OK) == 0) && (
KDE::stat(file, &buff) == 0) && (S_ISREG(buff.st_mode))) {
488 hash = hash +
static_cast<quint32>(buff.st_ctime);
495 SearchOptions options )
const
499 if (!QDir::isRelativePath(filename))
504 QStringList candidates = d->resourceDirs(type, filename);
506 foreach (
const QString& candidate, candidates )
508 hash =
updateHash(candidate + filename, hash);
509 if ( !( options &
Recursive ) && hash ) {
522 if (!QDir::isRelativePath(reldir))
524 testdir.setPath(reldir);
525 if (testdir.exists())
527 if (reldir.endsWith(QLatin1Char(
'/')))
530 list.append(reldir+QLatin1Char(
'/'));
535 const QStringList candidates = d->resourceDirs(type, reldir);
537 for (QStringList::ConstIterator it = candidates.begin();
538 it != candidates.end(); ++it) {
539 testdir.setPath(*it + reldir);
540 if (testdir.exists())
541 list.append(testdir.absolutePath() + QLatin1Char(
'/'));
548 const QString& _filename)
const
551 if (_filename.isEmpty()) {
552 kWarning() <<
"filename for type " << type <<
" in KStandardDirs::findResourceDir is not supposed to be empty!!";
559 if(strcmp(type,
"exe") == 0) {
560 if(!filename.endsWith(QLatin1String(
".exe")))
561 filename += QLatin1String(
".exe");
564 const QStringList candidates = d->resourceDirs(type, filename);
566 for (QStringList::ConstIterator it = candidates.begin();
567 it != candidates.end(); ++it) {
568 if (
exists(*it + filename)) {
574 if(
false && strcmp(type,
"locale"))
575 kDebug(180) <<
"KStdDirs::findResDir(): can't find \"" << filename <<
"\" in type \"" << type <<
"\".";
587 if (fullPath.endsWith(QLatin1Char(
'/')))
588 return QDir(fullPath).exists();
589 return QFileInfo(fullPath).exists();
591 KDE_struct_stat buff;
592 QByteArray cFullPath = QFile::encodeName(fullPath);
593 if (
access(cFullPath, R_OK) == 0 && KDE_stat( cFullPath, &buff ) == 0) {
594 if (!fullPath.endsWith(QLatin1Char(
'/'))) {
595 if (S_ISREG( buff.st_mode ))
598 if (S_ISDIR( buff.st_mode ))
606 const QRegExp ®exp,
609 bool recursive,
bool unique)
611 const QString pattern = regexp.pattern();
612 if (recursive || pattern.contains(QLatin1Char(
'?')) || pattern.contains(QLatin1Char(
'*')))
617 QString path_ = path + QLatin1String(
"*.*" );
618 WIN32_FIND_DATA findData;
619 HANDLE hFile = FindFirstFile( (LPWSTR)path_.utf16(), &findData );
620 if( hFile == INVALID_HANDLE_VALUE )
623 const int len = wcslen( findData.cFileName );
624 if (!( findData.cFileName[0] ==
'.' &&
625 findData.cFileName[1] ==
'\0' ) &&
626 !( findData.cFileName[0] ==
'.' &&
627 findData.cFileName[1] ==
'.' &&
628 findData.cFileName[2] ==
'\0' ) &&
629 ( findData.cFileName[len-1] !=
'~' ) ) {
630 QString fn = QString::fromUtf16( (
const unsigned short*)findData.cFileName );
631 if (!recursive && !regexp.exactMatch(fn))
634 bool bIsDir = ( ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == FILE_ATTRIBUTE_DIRECTORY );
638 relPart + fn + QLatin1Char(
'/'),
639 regexp, list, relList, recursive, unique);
641 if (!regexp.exactMatch(fn))
646 if ( !unique || !relList.contains(relPart + fn) )
648 list.append( pathfn );
649 relList.append( relPart + fn );
653 }
while( FindNextFile( hFile, &findData ) != 0 );
657 DIR *dp = opendir( QFile::encodeName(path));
661 assert(path.endsWith(QLatin1Char(
'/')));
665 while( ( ep = readdir( dp ) ) != 0L )
667 QString fn( QFile::decodeName(ep->d_name));
668 if (fn == QString::fromLatin1(
".") || fn == QString::fromLatin1(
"..") || fn.at(fn.length() - 1) == QLatin1Char(
'~'))
671 if (!recursive && !regexp.exactMatch(fn))
678 #ifdef HAVE_DIRENT_D_TYPE
679 isDir = ep->d_type == DT_DIR;
680 isReg = ep->d_type == DT_REG;
682 if (ep->d_type == DT_UNKNOWN || ep->d_type == DT_LNK)
685 KDE_struct_stat buff;
687 kDebug(180) <<
"Error stat'ing " << pathfn <<
" : " <<
perror;
690 isReg = S_ISREG (buff.st_mode);
691 isDir = S_ISDIR (buff.st_mode);
696 lookupDirectory(pathfn + QLatin1Char(
'/'), relPart + fn + QLatin1Char(
'/'), regexp, list, relList, recursive, unique);
698 if (!regexp.exactMatch(fn))
703 if (!unique || !relList.contains(relPart + fn))
705 list.append( pathfn );
706 relList.append( relPart + fn );
718 KDE_struct_stat buff;
721 if ( S_ISREG( buff.st_mode))
723 if (!unique || !relList.contains(relPart + fn))
725 list.append( pathfn );
726 relList.append( relPart + fn );
734 const QRegExp ®exp,
737 bool recursive,
bool unique)
739 if (relpath.isEmpty()) {
741 Q_ASSERT(prefix != QLatin1String(
"/"));
743 relList, recursive, unique);
749 int slash = relpath.indexOf(QLatin1Char(
'/'));
751 rest = relpath.left(relpath.length() - 1);
753 path = relpath.left(slash);
754 rest = relpath.mid(slash + 1);
757 if (prefix.isEmpty())
761 assert(prefix.endsWith(QLatin1Char(
'/')));
763 if (path.contains(QLatin1Char(
'*')) || path.contains(QLatin1Char(
'?'))) {
765 QRegExp pathExp(path, Qt::CaseSensitive, QRegExp::Wildcard);
768 QString prefix_ = prefix + QLatin1String(
"*.*" );
769 WIN32_FIND_DATA findData;
770 HANDLE hFile = FindFirstFile( (LPWSTR)prefix_.utf16(), &findData );
771 if( hFile == INVALID_HANDLE_VALUE )
774 const int len = wcslen( findData.cFileName );
775 if (!( findData.cFileName[0] ==
'.' &&
776 findData.cFileName[1] ==
'\0' ) &&
777 !( findData.cFileName[0] ==
'.' &&
778 findData.cFileName[1] ==
'.' &&
779 findData.cFileName[2] ==
'\0' ) &&
780 ( findData.cFileName[len-1] !=
'~' ) ) {
781 const QString fn = QString::fromUtf16( (
const unsigned short*)findData.cFileName );
782 if ( !pathExp.exactMatch(fn) )
784 if ( ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == FILE_ATTRIBUTE_DIRECTORY )
786 rest, relPart + fn + QLatin1Char(
'/'),
787 regexp, list, relList, recursive, unique);
789 }
while( FindNextFile( hFile, &findData ) != 0 );
792 DIR *dp = opendir( QFile::encodeName(prefix) );
799 while( ( ep = readdir( dp ) ) != 0L )
801 QString fn( QFile::decodeName(ep->d_name));
802 if (fn == QLatin1String(
".") || fn == QLatin1String(
"..") || fn.at(fn.length() - 1) == QLatin1Char(
'~'))
805 if ( !pathExp.exactMatch(fn) )
812 #ifdef HAVE_DIRENT_D_TYPE
813 isDir = ep->d_type == DT_DIR;
815 if (ep->d_type == DT_UNKNOWN || ep->d_type == DT_LNK)
819 KDE_struct_stat buff;
821 kDebug(180) <<
"Error stat'ing " << fn <<
" : " <<
perror;
824 isDir = S_ISDIR (buff.st_mode);
827 lookupPrefix(fn + QLatin1Char(
'/'), rest, rfn + QLatin1Char(
'/'), regexp, list, relList, recursive, unique);
836 relPart + path + QLatin1Char(
'/'), regexp, list,
837 relList, recursive, unique);
844 SearchOptions options,
850 if ( !filter.isEmpty() )
852 int slash = filter.lastIndexOf(QLatin1Char(
'/'));
856 filterPath = filter.left(slash + 1);
857 filterFile = filter.mid(slash + 1);
862 if ( !QDir::isRelativePath(filter) )
865 candidates << filterPath.left(3);
866 filterPath = filterPath.mid(3);
868 candidates << QString::fromLatin1(
"/");
869 filterPath = filterPath.mid(1);
874 candidates = d->resourceDirs(type, filter);
877 if (filterFile.isEmpty()) {
878 filterFile =
QString(QLatin1Char(
'*'));
881 QRegExp regExp(filterFile, Qt::CaseSensitive, QRegExp::Wildcard);
884 foreach (
const QString& candidate, candidates )
896 SearchOptions options )
const
912 if (!strRet.endsWith(QLatin1Char(
'/')))
913 return strRet + QLatin1Char(
'/');
916 if (dirname.isEmpty() || (dirname.size() == 1 && dirname.at(0) == QLatin1Char(
'/')))
919 if (dirname.at(0) != QLatin1Char(
'/')) {
920 qWarning(
"realPath called with a relative path '%s', please fix", qPrintable(dirname));
924 char realpath_buffer[MAXPATHLEN + 1];
925 memset(realpath_buffer, 0, MAXPATHLEN + 1);
928 if (realpath( QFile::encodeName(dirname).constData(), realpath_buffer) != 0) {
930 int len = strlen(realpath_buffer);
931 realpath_buffer[len] =
'/';
932 realpath_buffer[len+1] = 0;
933 return QFile::decodeName(realpath_buffer);
941 if (!dir.endsWith(QLatin1Char(
'/')))
942 dir += QLatin1Char(
'/');
946 const int pos = dir.lastIndexOf(QLatin1Char(
'/'), -2);
948 relative.prepend(dir.mid(pos+1));
949 dir = dir.left(pos+1);
950 Q_ASSERT(dir.endsWith(QLatin1Char(
'/')));
952 Q_ASSERT(!relative.isEmpty());
953 if (!relative.isEmpty()) {
970 LPCWSTR lpIn = (LPCWSTR)filename.utf16();
971 QVarLengthArray<WCHAR, MAX_PATH> buf(MAX_PATH);
972 DWORD len = GetFullPathNameW(lpIn, buf.size(), buf.data(), NULL);
973 if (len > (DWORD)buf.size()) {
975 len = GetFullPathNameW(lpIn, buf.size(), buf.data(), NULL);
979 return QString::fromUtf16((
const unsigned short*)buf.data()).replace(QLatin1Char(
'\\'),QLatin1Char(
'/')).toLower();
981 char realpath_buffer[MAXPATHLEN + 1];
982 memset(realpath_buffer, 0, MAXPATHLEN + 1);
985 if (realpath( QFile::encodeName(filename).constData(), realpath_buffer) != 0) {
987 return QFile::decodeName(realpath_buffer);
995 void KStandardDirs::KStandardDirsPrivate::createSpecialResource(
const char *type)
999 gethostname(hostname, 255);
1000 const QString localkdedir = m_prefixes.first();
1001 QString dir = localkdedir + QString::fromLatin1(type) + QLatin1Char(
'-') + QString::fromLocal8Bit(hostname);
1004 int result = readlink(QFile::encodeName(dir).constData(), link, 1023);
1005 bool relink = (result == -1) && (errno == ENOENT);
1009 if (!QDir::isRelativePath(QFile::decodeName(link)))
1011 KDE_struct_stat stat_buf;
1012 int res =
KDE::lstat(QFile::decodeName(link), &stat_buf);
1013 if ((res == -1) && (errno == ENOENT))
1017 else if ((res == -1) || (!S_ISDIR(stat_buf.st_mode)))
1019 fprintf(stderr,
"Error: \"%s\" is not a directory.\n", link);
1022 else if (stat_buf.st_uid != getuid())
1024 fprintf(stderr,
"Error: \"%s\" is owned by uid %d instead of uid %d.\n", link, stat_buf.st_uid, getuid());
1032 if (!makeDir(dir, 0700))
1033 fprintf(stderr,
"failed to create \"%s\"", qPrintable(dir));
1035 result = readlink(QFile::encodeName(dir).constData(), link, 1023);
1040 QString srv = findExe(QLatin1String(
"lnusertemp"), installPath(
"libexec"));
1042 srv = findExe(QLatin1String(
"lnusertemp"));
1045 if (system(QByteArray(QFile::encodeName(srv) +
' ' + type)) == -1) {
1046 fprintf(stderr,
"Error: unable to launch lnusertemp command" );
1048 result = readlink(QFile::encodeName(dir).constData(), link, 1023);
1055 dir = QFile::decodeName(link);
1057 dir = QDir::cleanPath(dir + QFile::decodeName(link));
1060 q->addResourceDir(type, dir + QLatin1Char(
'/'),
false);
1065 return d->resourceDirs(type,
QString());
1068 QStringList KStandardDirs::KStandardDirsPrivate::resourceDirs(
const char* type,
const QString& subdirForRestrictions)
1070 QMutexLocker lock(&m_cacheMutex);
1071 const bool dataRestrictionActive = m_restrictionsActive
1072 && (strcmp(type,
"data") == 0)
1073 && hasDataRestrictions(subdirForRestrictions);
1079 if (dirCacheIt != m_dircache.constEnd() && !dataRestrictionActive) {
1081 candidates = *dirCacheIt;
1086 if (strcmp(type,
"socket") == 0)
1087 createSpecialResource(type);
1088 else if (strcmp(type,
"tmp") == 0)
1089 createSpecialResource(type);
1090 else if (strcmp(type,
"cache") == 0)
1091 createSpecialResource(type);
1095 bool restrictionActive =
false;
1096 if (m_restrictionsActive) {
1097 if (dataRestrictionActive)
1098 restrictionActive =
true;
1099 if (m_restrictions.value(
"all",
false))
1100 restrictionActive =
true;
1101 else if (m_restrictions.value(type,
false))
1102 restrictionActive =
true;
1106 const QString typeInstallPath = installPath(type);
1109 const QString installdir = typeInstallPath.isEmpty() ?
QString() : realPath(typeInstallPath).toLower();
1110 const QString installprefix = installPath(
"kdedir").toLower();
1112 const QString installdir = typeInstallPath.isEmpty() ?
QString() : realPath(typeInstallPath);
1113 const QString installprefix = installPath(
"kdedir");
1115 if (!dirs.isEmpty())
1119 for (QStringList::ConstIterator it = dirs.constBegin();
1120 it != dirs.constEnd(); ++it)
1122 if ((*it).startsWith(QLatin1Char(
'%'))) {
1124 const int pos = (*it).indexOf(QLatin1Char(
'/'));
1125 QString rel = (*it).mid(1, pos - 1);
1126 QString rest = (*it).mid(pos + 1);
1127 const QStringList basedirs = resourceDirs(rel.toUtf8().constData(), subdirForRestrictions);
1128 for (QStringList::ConstIterator it2 = basedirs.begin();
1129 it2 != basedirs.end(); ++it2)
1132 const QString path = realPath( *it2 + rest ).toLower();
1134 const QString path = realPath( *it2 + rest );
1136 testdir.setPath(path);
1137 if ((local || testdir.exists()) && !candidates.contains(path))
1138 candidates.append(path);
1145 if (strncmp(type,
"xdgdata-", 8) == 0)
1146 prefixList = &(xdgdata_prefixes);
1147 else if (strncmp(type,
"xdgconf-", 8) == 0)
1148 prefixList = &(xdgconf_prefixes);
1150 prefixList = &m_prefixes;
1152 for (QStringList::ConstIterator pit = prefixList->begin();
1153 pit != prefixList->end();
1156 if((*pit)!=installprefix||installdir.isEmpty())
1158 for (QStringList::ConstIterator it = dirs.constBegin();
1159 it != dirs.constEnd(); ++it)
1161 if ((*it).startsWith(QLatin1Char(
'%')))
1164 const QString path = realPath( *pit + *it ).toLower();
1166 const QString path = realPath( *pit + *it );
1168 testdir.setPath(path);
1169 if (local && restrictionActive)
1171 if ((local || testdir.exists()) && !candidates.contains(path))
1172 candidates.append(path);
1179 testdir.setPath(installdir);
1180 if(testdir.exists() && ! candidates.contains(installdir))
1181 candidates.append(installdir);
1187 if (!installdir.isEmpty()) {
1189 foreach (
const QString &s, candidates) {
1190 if (installdir.startsWith(s)) {
1196 candidates.append(installdir);
1199 const QStringList absDirs = m_absolutes.value(type);
1200 for (QStringList::ConstIterator it = absDirs.constBegin();
1201 it != absDirs.constEnd(); ++it)
1203 testdir.setPath(*it);
1204 if (testdir.exists()) {
1206 const QString filename = realPath( *it ).toLower();
1208 const QString filename = realPath( *it );
1210 if (!candidates.contains(filename)) {
1211 candidates.append(filename);
1218 if (!dataRestrictionActive) {
1220 m_dircache.insert(type, candidates);
1225 kDebug(180) <<
"found dirs for resource" << type <<
":" << candidates;
1234 QStringList ret = QString::fromLocal8Bit(qgetenv(
"PATHEXT")).split(QLatin1Char(
';'));
1235 if (!ret.contains(QLatin1String(
".exe"), Qt::CaseInsensitive)) {
1238 ret << QLatin1String(
".exe")
1239 << QLatin1String(
".com")
1240 << QLatin1String(
".bat")
1241 << QLatin1String(
".cmd");
1254 p = QString::fromLocal8Bit( qgetenv(
"PATH" ) );
1257 QString delimiters(QLatin1Char(KPATH_SEPARATOR));
1258 delimiters += QLatin1Char(
'\b');
1264 for(
int i = 0; i < tokens.count(); i++ )
1278 bundle += QLatin1String(
".app/Contents/MacOS/") + bundle.section(QLatin1Char(
'/'), -1);
1279 info.setFile( bundle );
1281 if (file =
fopen(info.absoluteFilePath().toUtf8().constData(),
"r")) {
1284 if ((
stat(info.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
1287 if ( ignore || (_stat.st_mode & S_IXUSR) ) {
1288 if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
1302 if ( !bundle.isEmpty() ) {
1307 QFileInfo info( path );
1308 QFileInfo orig = info;
1309 #if defined(Q_OS_DARWIN) || defined(Q_OS_MAC)
1311 if (file =
fopen(orig.absoluteFilePath().toUtf8().constData(),
"r")) {
1314 if ((
stat(orig.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
1317 if ( ignoreExecBit || (_stat.st_mode & S_IXUSR) ) {
1318 if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
1319 orig.makeAbsolute();
1320 return orig.filePath();
1326 if( info.exists() && info.isSymLink() )
1327 info = QFileInfo( info.canonicalFilePath() );
1328 if( info.exists() && ( ignoreExecBit || info.isExecutable() ) && info.isFile() ) {
1332 orig.makeAbsolute();
1333 return orig.filePath();
1342 SearchOptions options )
1348 if (!executable_extensions.contains(appname.section(QLatin1Char(
'.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
1350 foreach (
const QString& extension, executable_extensions) {
1351 found_exe =
findExe(appname + extension, pstr, options);
1352 if (!found_exe.isEmpty()) {
1362 if (appname.contains(QDir::separator()))
1373 if (!result.isEmpty()) {
1380 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
1382 p = (*it) + QLatin1Char(
'/');
1387 if (!result.isEmpty()) {
1397 if (!result.isEmpty()) {
1410 const QString& pstr, SearchOptions options )
1414 if (!executable_extensions.contains(appname.section(QLatin1Char(
'.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
1416 foreach (
const QString& extension, executable_extensions) {
1417 total +=
findAllExe (list, appname + extension, pstr, options);
1427 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
1429 p = (*it) + QLatin1Char(
'/');
1434 if ( !bundle.isEmpty() ) {
1436 list.append( bundle );
1442 if( info.exists() && ( ( options &
IgnoreExecBit ) || info.isExecutable())
1443 && info.isFile() ) {
1448 return list.count();
1458 return f.absoluteFilePath();
1467 const int len = str.length();
1470 for(
int index = 0; index < len; index++) {
1471 if (delim.contains(str[index])) {
1475 token += str[index];
1478 if (!token.isEmpty()) {
1483 #ifndef KDE_NO_DEPRECATED
1486 return QString(QLatin1Char(
'%')) + QString::fromLatin1(type) + QLatin1Char(
'/');
1494 QMutexLocker lock(&d->m_cacheMutex);
1495 QString path = d->m_savelocations.value(type);
1499 if (dirs.isEmpty() && (
1500 (strcmp(type,
"socket") == 0) ||
1501 (strcmp(type,
"tmp") == 0) ||
1502 (strcmp(type,
"cache") == 0) ))
1505 dirs = d->m_relatives.value(type);
1507 if (!dirs.isEmpty())
1509 path = dirs.first();
1511 if (path.startsWith(QLatin1Char(
'%'))) {
1513 const int pos = path.indexOf(QLatin1Char(
'/'));
1514 QString rel = path.mid(1, pos - 1);
1515 QString rest = path.mid(pos + 1);
1517 path = basepath + rest;
1521 if (strncmp(type,
"xdgdata-", 8) == 0) {
1523 }
else if (strncmp(type,
"xdgconf-", 8) == 0) {
1530 dirs = d->m_absolutes.value(type);
1531 if (dirs.isEmpty()) {
1532 qFatal(
"KStandardDirs: The resource type %s is not registered", type);
1538 d->m_savelocations.insert(type, path.endsWith(QLatin1Char(
'/')) ? path : path + QLatin1Char(
'/'));
1540 QString fullPath = path + suffix;
1543 if (
KDE::stat(fullPath, &st) != 0 || !(S_ISDIR(st.st_mode))) {
1552 if(!
makeDir(fullPath, 0700)) {
1555 d->m_dircache.remove(type);
1557 if (!fullPath.endsWith(QLatin1Char(
'/')))
1558 fullPath += QLatin1Char(
'/');
1566 int i = absPath.lastIndexOf(QLatin1Char(
'/'));
1573 for (QStringList::ConstIterator it = candidates.begin();
1574 it != candidates.end(); ++it) {
1575 if (fullPath.startsWith(*it)) {
1576 return fullPath.mid((*it).length());
1586 if (QDir::isRelativePath(dir))
1590 return QDir().mkpath(dir);
1593 uint len = target.length();
1596 if (dir.at(len - 1) != QLatin1Char(
'/'))
1597 target += QLatin1Char(
'/');
1605 int pos = target.indexOf(QLatin1Char(
'/'), i);
1606 base += target.mid(i - 1, pos - i + 1);
1607 QByteArray baseEncoded = QFile::encodeName(base);
1609 if (KDE_stat(baseEncoded, &st) != 0)
1613 if (KDE_lstat(baseEncoded, &st) == 0)
1614 (void)unlink(baseEncoded);
1616 if (KDE_mkdir(baseEncoded, static_cast<mode_t>(mode)) != 0) {
1617 baseEncoded.prepend(
"trying to create local folder " );
1618 perror(baseEncoded.constData());
1632 c_path = qgetenv(env);
1633 if (c_path.isEmpty())
1641 c_path = retval.toLatin1();
1644 return QDir::fromNativeSeparators(QFile::decodeName(c_path));
1648 static QString executablePrefix()
1650 char path_buffer[MAXPATHLEN + 1];
1651 path_buffer[MAXPATHLEN] = 0;
1652 int length = readlink (
"/proc/self/exe", path_buffer, MAXPATHLEN);
1656 path_buffer[length] =
'\0';
1658 QString path = QFile::decodeName(path_buffer);
1663 int pos = path.lastIndexOf(QLatin1Char(
'/'));
1666 pos = path.lastIndexOf(QLatin1Char(
'/'), pos - 1);
1670 return path.left(pos);
1674 void KStandardDirs::addResourcesFrom_krcdirs()
1676 QString localFile = QDir::currentPath() + QLatin1String(
"/.krcdirs");
1677 if (!QFile::exists(localFile))
1680 QSettings iniFile(localFile, QSettings::IniFormat);
1681 iniFile.beginGroup(QString::fromLatin1(
"KStandardDirs"));
1683 foreach(
const QString &key, resources)
1685 QDir path(iniFile.value(key).toString());
1689 if(path.makeAbsolute())
1694 void KStandardDirs::addKDEDefaults()
1696 addResourcesFrom_krcdirs();
1702 if (!kdedirs.isEmpty())
1708 QString execPrefix(QFile::decodeName(EXEC_INSTALL_PREFIX));
1709 if (!execPrefix.isEmpty() && !kdedirList.contains(execPrefix))
1710 kdedirList.append(execPrefix);
1712 const QString linuxExecPrefix = executablePrefix();
1713 if ( !linuxExecPrefix.isEmpty() )
1714 kdedirList.append( linuxExecPrefix );
1720 if (!localKdeDir.isEmpty()) {
1721 if (!localKdeDir.endsWith(QLatin1Char(
'/')))
1722 localKdeDir += QLatin1Char(
'/');
1728 #if defined(Q_WS_MACX)
1729 localKdeDir = QDir::homePath() + QLatin1String(
"/Library/Preferences/KDE/");
1730 #elif defined(Q_WS_WIN)
1732 WCHAR wPath[MAX_PATH+1];
1733 if ( SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wPath) == S_OK) {
1734 localKdeDir = QDir::fromNativeSeparators(QString::fromUtf16((
const ushort *) wPath)) + QLatin1Char(
'/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char(
'/');
1737 localKdeDir = QDir::homePath() + QLatin1Char(
'/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char(
'/');
1742 localKdeDir = QDir::homePath() + QLatin1Char(
'/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char(
'/');
1746 if (localKdeDir != QLatin1String(
"-/"))
1756 if (bundleDir.dirName() == QLatin1String(
"MacOS")) {
1764 QStringList::ConstIterator end(kdedirList.end());
1765 for (QStringList::ConstIterator it = kdedirList.constBegin();
1766 it != kdedirList.constEnd(); ++it)
1776 if (!xdgdirs.isEmpty())
1783 xdgdirList.append(QString::fromLatin1(
"/etc/xdg"));
1785 xdgdirList.append(
installPath(
"kdedir") + QString::fromLatin1(
"etc/xdg"));
1787 xdgdirList.append(QFile::decodeName(KDESYSCONFDIR
"/xdg"));
1792 if (!localXdgDir.isEmpty()) {
1793 if (!localXdgDir.endsWith(QLatin1Char(
'/')))
1794 localXdgDir += QLatin1Char(
'/');
1797 localXdgDir = QDir::homePath() + QString::fromLatin1(
"/Library/Preferences/XDG/");
1799 localXdgDir = QDir::homePath() + QString::fromLatin1(
"/.config/");
1806 for (QStringList::ConstIterator it = xdgdirList.constBegin();
1807 it != xdgdirList.constEnd(); ++it)
1816 for (QStringList::ConstIterator it = kdedirList.constBegin();
1817 it != kdedirList.constEnd(); ++it) {
1819 if (!dir.endsWith(QLatin1Char(
'/')))
1820 dir += QLatin1Char(
'/');
1821 kdedirDataDirs.append(dir + QLatin1String(
"share/"));
1825 if (!xdgdirs.isEmpty()) {
1830 Q_FOREACH(
const QString& dir, kdedirDataDirs) {
1831 if (!xdgdirList.contains(dir))
1832 xdgdirList.append(dir);
1835 xdgdirList = kdedirDataDirs;
1837 xdgdirList.append(QString::fromLatin1(
"/usr/local/share/"));
1838 xdgdirList.append(QString::fromLatin1(
"/usr/share/"));
1843 if (!localXdgDir.isEmpty())
1845 if (localXdgDir[localXdgDir.length()-1] != QLatin1Char(
'/'))
1846 localXdgDir += QLatin1Char(
'/');
1850 localXdgDir = QDir::homePath() + QLatin1String(
"/.local/share/");
1856 for (QStringList::ConstIterator it = xdgdirList.constBegin();
1857 it != xdgdirList.constEnd(); ++it)
1886 if (mapFile.isEmpty() || !QFile::exists(mapFile))
1888 profiles << QString::fromLatin1(
"default");
1892 struct passwd *pw = getpwuid(geteuid());
1895 profiles << QString::fromLatin1(
"default");
1899 QByteArray user = pw->pw_name;
1901 gid_t sup_gids[512];
1902 int sup_gids_nr = getgroups(512, sup_gids);
1906 if (mapCfg.
hasKey(user.constData()))
1917 for( QStringList::ConstIterator it = groups.begin();
1918 it != groups.end(); ++it )
1920 QByteArray grp = (*it).toUtf8();
1922 struct group *grp_ent = getgrnam(grp);
1923 if (!grp_ent)
continue;
1924 gid_t gid = grp_ent->gr_gid;
1925 if (pw->pw_gid == gid)
1932 for(
int i = 0; i < sup_gids_nr; i++)
1934 if (sup_gids[i] == gid)
1944 if (profiles.isEmpty())
1945 profiles << QString::fromLatin1(
"default");
1953 if (!d->m_checkRestrictions)
1969 int i = kioskAdmin.indexOf(QLatin1Char(
':'));
1970 QString user = kioskAdmin.left(i);
1971 QString host = kioskAdmin.mid(i+1);
1974 char hostname[ 256 ];
1975 hostname[ 0 ] =
'\0';
1976 if (!gethostname( hostname, 255 ))
1977 hostname[
sizeof(hostname)-1] =
'\0';
1980 (host.isEmpty() || (host == QLatin1String(hostname))))
1982 kde_kiosk_admin =
true;
1986 bool readProfiles =
true;
1988 if (kde_kiosk_admin && !qgetenv(
"KDE_KIOSK_NO_PROFILES").isEmpty())
1989 readProfiles =
false;
1993 if (!profileDirsPrefix.isEmpty() && !profileDirsPrefix.endsWith(QLatin1Char(
'/')))
1994 profileDirsPrefix.append(QLatin1Char(
'/'));
2001 bool priority =
false;
2006 for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
2014 if (list.isEmpty() && !profile.isEmpty() && !profileDirsPrefix.isEmpty())
2016 QString dir = profileDirsPrefix + profile;
2026 it2 != entries.end(); ++it2)
2028 const QString key = it2.key();
2029 if (key.startsWith(QLatin1String(
"dir_"))) {
2032 QStringList::ConstIterator sIt(dirs.begin());
2034 for (; sIt != dirs.end(); ++sIt)
2040 if (profiles.isEmpty())
2042 profile = profiles.back();
2043 group = QString::fromLatin1(
"Directories-%1").arg(profile);
2044 profiles.pop_back();
2050 if (!kde_kiosk_admin || qgetenv(
"KDE_KIOSK_NO_RESTRICTIONS").isEmpty())
2055 it2 != entries.end(); ++it2)
2057 const QString key = it2.key();
2060 d->m_restrictionsActive =
true;
2061 const QByteArray cKey = key.toLatin1();
2062 d->m_restrictions.insert(cKey,
true);
2063 d->m_dircache.remove(cKey);
2064 d->m_savelocations.remove(cKey);
2070 bool configDirsChanged = (
resourceDirs(
"config").count() != configdirs);
2072 d->m_checkRestrictions = configDirsChanged;
2074 return configDirsChanged;
2080 return d->m_prefixes.first();
2086 return d->xdgdata_prefixes.first();
2092 return d->xdgconf_prefixes.first();
2110 const QString& filename,
bool createDir,
2115 int slash = filename.lastIndexOf(QLatin1Char(
'/')) + 1;
2121 QString dir = filename.left(slash);
2122 QString file = filename.mid(slash);
2129 if ( accessOK == 0 )
2135 if ( (mode & W_OK) == 0 )
2144 int pos = dirName.lastIndexOf(QLatin1Char(
'/'));
2147 else if ( pos == 0 )
2150 dirName.truncate(pos);
2154 if ( accessOK == 0 )