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());
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();
1158 if((*pit)!=installprefix||installdir.isEmpty()||!strcmp(
"exe", type))
1160 for (QStringList::ConstIterator it = dirs.constBegin();
1161 it != dirs.constEnd(); ++it)
1163 if ((*it).startsWith(QLatin1Char(
'%')))
1166 const QString path = realPath( *pit + *it ).toLower();
1168 const QString path = realPath( *pit + *it );
1170 testdir.setPath(path);
1171 if (local && restrictionActive)
1173 if ((local || testdir.exists()) && !candidates.contains(path))
1174 candidates.append(path);
1179 if (local && !strcmp(
"config", type))
1180 candidates.append(QLatin1String(
"/etc/kde/"));
1186 testdir.setPath(installdir);
1187 if(testdir.exists() && ! candidates.contains(installdir))
1188 candidates.append(installdir);
1194 if (!installdir.isEmpty()) {
1196 foreach (
const QString &s, candidates) {
1197 if (installdir.startsWith(s)) {
1203 candidates.append(installdir);
1206 const QStringList absDirs = m_absolutes.value(type);
1207 for (QStringList::ConstIterator it = absDirs.constBegin();
1208 it != absDirs.constEnd(); ++it)
1210 testdir.setPath(*it);
1211 if (testdir.exists()) {
1213 const QString filename = realPath( *it ).toLower();
1215 const QString filename = realPath( *it );
1217 if (!candidates.contains(filename)) {
1218 candidates.append(filename);
1225 if (!dataRestrictionActive) {
1227 m_dircache.insert(type, candidates);
1232 kDebug(180) <<
"found dirs for resource" << type <<
":" << candidates;
1241 QStringList ret = QString::fromLocal8Bit(qgetenv(
"PATHEXT")).split(QLatin1Char(
';'));
1242 if (!ret.contains(QLatin1String(
".exe"), Qt::CaseInsensitive)) {
1245 ret << QLatin1String(
".exe")
1246 << QLatin1String(
".com")
1247 << QLatin1String(
".bat")
1248 << QLatin1String(
".cmd");
1261 p = QString::fromLocal8Bit( qgetenv(
"PATH" ) );
1264 QString delimiters(QLatin1Char(KPATH_SEPARATOR));
1265 delimiters += QLatin1Char(
'\b');
1271 for(
int i = 0; i < tokens.count(); i++ )
1285 bundle += QLatin1String(
".app/Contents/MacOS/") + bundle.section(QLatin1Char(
'/'), -1);
1286 info.setFile( bundle );
1288 if (file =
fopen(info.absoluteFilePath().toUtf8().constData(),
"r")) {
1291 if ((
stat(info.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
1294 if ( ignore || (_stat.st_mode & S_IXUSR) ) {
1295 if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
1309 if ( !bundle.isEmpty() ) {
1314 QFileInfo info( path );
1315 QFileInfo orig = info;
1316 #if defined(Q_OS_DARWIN) || defined(Q_OS_MAC)
1318 if (file =
fopen(orig.absoluteFilePath().toUtf8().constData(),
"r")) {
1321 if ((
stat(orig.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
1324 if ( ignoreExecBit || (_stat.st_mode & S_IXUSR) ) {
1325 if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
1326 orig.makeAbsolute();
1327 return orig.filePath();
1333 if( info.exists() && info.isSymLink() )
1334 info = QFileInfo( info.canonicalFilePath() );
1335 if( info.exists() && ( ignoreExecBit || info.isExecutable() ) && info.isFile() ) {
1339 orig.makeAbsolute();
1340 return orig.filePath();
1349 SearchOptions options )
1355 if (!executable_extensions.contains(appname.section(QLatin1Char(
'.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
1357 foreach (
const QString& extension, executable_extensions) {
1358 found_exe =
findExe(appname + extension, pstr, options);
1359 if (!found_exe.isEmpty()) {
1369 if (appname.contains(QDir::separator()))
1380 if (!result.isEmpty()) {
1387 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
1389 p = (*it) + QLatin1Char(
'/');
1394 if (!result.isEmpty()) {
1404 if (!result.isEmpty()) {
1417 const QString& pstr, SearchOptions options )
1421 if (!executable_extensions.contains(appname.section(QLatin1Char(
'.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
1423 foreach (
const QString& extension, executable_extensions) {
1424 total +=
findAllExe (list, appname + extension, pstr, options);
1434 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
1436 p = (*it) + QLatin1Char(
'/');
1441 if ( !bundle.isEmpty() ) {
1443 list.append( bundle );
1449 if( info.exists() && ( ( options &
IgnoreExecBit ) || info.isExecutable())
1450 && info.isFile() ) {
1455 return list.count();
1465 return f.absoluteFilePath();
1474 const int len = str.length();
1477 for(
int index = 0; index < len; index++) {
1478 if (delim.contains(str[index])) {
1482 token += str[index];
1485 if (!token.isEmpty()) {
1490 #ifndef KDE_NO_DEPRECATED
1493 return QString(QLatin1Char(
'%')) + QString::fromLatin1(type) + QLatin1Char(
'/');
1501 QMutexLocker lock(&d->m_cacheMutex);
1502 QString path = d->m_savelocations.value(type);
1506 if (dirs.isEmpty() && (
1507 (strcmp(type,
"socket") == 0) ||
1508 (strcmp(type,
"tmp") == 0) ||
1509 (strcmp(type,
"cache") == 0) ))
1512 dirs = d->m_relatives.value(type);
1514 if (!dirs.isEmpty())
1516 path = dirs.first();
1518 if (path.startsWith(QLatin1Char(
'%'))) {
1520 const int pos = path.indexOf(QLatin1Char(
'/'));
1521 QString rel = path.mid(1, pos - 1);
1522 QString rest = path.mid(pos + 1);
1524 path = basepath + rest;
1528 if (strncmp(type,
"xdgdata-", 8) == 0) {
1530 }
else if (strncmp(type,
"xdgconf-", 8) == 0) {
1537 dirs = d->m_absolutes.value(type);
1538 if (dirs.isEmpty()) {
1539 qFatal(
"KStandardDirs: The resource type %s is not registered", type);
1545 d->m_savelocations.insert(type, path.endsWith(QLatin1Char(
'/')) ? path : path + QLatin1Char(
'/'));
1547 QString fullPath = path + suffix;
1550 if (
KDE::stat(fullPath, &st) != 0 || !(S_ISDIR(st.st_mode))) {
1559 if(!
makeDir(fullPath, 0700)) {
1562 d->m_dircache.remove(type);
1564 if (!fullPath.endsWith(QLatin1Char(
'/')))
1565 fullPath += QLatin1Char(
'/');
1573 int i = absPath.lastIndexOf(QLatin1Char(
'/'));
1580 for (QStringList::ConstIterator it = candidates.begin();
1581 it != candidates.end(); ++it) {
1582 if (fullPath.startsWith(*it)) {
1583 return fullPath.mid((*it).length());
1593 if (QDir::isRelativePath(dir))
1597 return QDir().mkpath(dir);
1600 uint len = target.length();
1603 if (dir.at(len - 1) != QLatin1Char(
'/'))
1604 target += QLatin1Char(
'/');
1612 int pos = target.indexOf(QLatin1Char(
'/'), i);
1613 base += target.mid(i - 1, pos - i + 1);
1614 QByteArray baseEncoded = QFile::encodeName(base);
1616 if (KDE_stat(baseEncoded, &st) != 0)
1620 if (KDE_lstat(baseEncoded, &st) == 0)
1621 (void)unlink(baseEncoded);
1623 if (KDE_mkdir(baseEncoded, static_cast<mode_t>(mode)) != 0) {
1624 baseEncoded.prepend(
"trying to create local folder " );
1625 perror(baseEncoded.constData());
1639 c_path = qgetenv(env);
1640 if (c_path.isEmpty())
1648 c_path = retval.toLatin1();
1651 return QDir::fromNativeSeparators(QFile::decodeName(c_path));
1655 static QString executablePrefix()
1657 char path_buffer[MAXPATHLEN + 1];
1658 path_buffer[MAXPATHLEN] = 0;
1659 int length = readlink (
"/proc/self/exe", path_buffer, MAXPATHLEN);
1663 path_buffer[length] =
'\0';
1665 QString path = QFile::decodeName(path_buffer);
1670 int pos = path.lastIndexOf(QLatin1Char(
'/'));
1673 pos = path.lastIndexOf(QLatin1Char(
'/'), pos - 1);
1677 return path.left(pos);
1681 void KStandardDirs::addResourcesFrom_krcdirs()
1683 QString localFile = QDir::currentPath() + QLatin1String(
"/.krcdirs");
1684 if (!QFile::exists(localFile))
1687 QSettings iniFile(localFile, QSettings::IniFormat);
1688 iniFile.beginGroup(QString::fromLatin1(
"KStandardDirs"));
1690 foreach(
const QString &key, resources)
1692 QDir path(iniFile.value(key).toString());
1696 if(path.makeAbsolute())
1701 void KStandardDirs::addKDEDefaults()
1703 addResourcesFrom_krcdirs();
1709 if (!kdedirs.isEmpty())
1715 QString execPrefix(QFile::decodeName(EXEC_INSTALL_PREFIX));
1716 if (!execPrefix.isEmpty() && !kdedirList.contains(execPrefix))
1717 kdedirList.append(execPrefix);
1719 const QString linuxExecPrefix = executablePrefix();
1720 if ( !linuxExecPrefix.isEmpty() )
1721 kdedirList.append( linuxExecPrefix );
1727 if (!localKdeDir.isEmpty()) {
1728 if (!localKdeDir.endsWith(QLatin1Char(
'/')))
1729 localKdeDir += QLatin1Char(
'/');
1735 #if defined(Q_WS_MACX)
1736 localKdeDir = QDir::homePath() + QLatin1String(
"/Library/Preferences/KDE/");
1737 #elif defined(Q_WS_WIN)
1739 WCHAR wPath[MAX_PATH+1];
1740 if ( SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wPath) == S_OK) {
1741 localKdeDir = QDir::fromNativeSeparators(QString::fromUtf16((
const ushort *) wPath)) + QLatin1Char(
'/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char(
'/');
1744 localKdeDir = QDir::homePath() + QLatin1Char(
'/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char(
'/');
1749 localKdeDir = QDir::homePath() + QLatin1Char(
'/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char(
'/');
1753 if (localKdeDir != QLatin1String(
"-/"))
1763 if (bundleDir.dirName() == QLatin1String(
"MacOS")) {
1771 QStringList::ConstIterator end(kdedirList.end());
1772 for (QStringList::ConstIterator it = kdedirList.constBegin();
1773 it != kdedirList.constEnd(); ++it)
1783 if (!xdgdirs.isEmpty())
1790 xdgdirList.append(QString::fromLatin1(
"/etc/xdg"));
1792 xdgdirList.append(
installPath(
"kdedir") + QString::fromLatin1(
"etc/xdg"));
1794 xdgdirList.append(QFile::decodeName(KDESYSCONFDIR
"/xdg"));
1799 if (!localXdgDir.isEmpty()) {
1800 if (!localXdgDir.endsWith(QLatin1Char(
'/')))
1801 localXdgDir += QLatin1Char(
'/');
1804 localXdgDir = QDir::homePath() + QString::fromLatin1(
"/Library/Preferences/XDG/");
1806 localXdgDir = QDir::homePath() + QString::fromLatin1(
"/.config/");
1813 for (QStringList::ConstIterator it = xdgdirList.constBegin();
1814 it != xdgdirList.constEnd(); ++it)
1823 for (QStringList::ConstIterator it = kdedirList.constBegin();
1824 it != kdedirList.constEnd(); ++it) {
1826 if (!dir.endsWith(QLatin1Char(
'/')))
1827 dir += QLatin1Char(
'/');
1828 kdedirDataDirs.append(dir + QLatin1String(
"share/"));
1832 if (!xdgdirs.isEmpty()) {
1837 Q_FOREACH(
const QString& dir, kdedirDataDirs) {
1838 if (!xdgdirList.contains(dir))
1839 xdgdirList.append(dir);
1842 xdgdirList = kdedirDataDirs;
1844 xdgdirList.append(QString::fromLatin1(
"/usr/local/share/"));
1845 xdgdirList.append(QString::fromLatin1(
"/usr/share/"));
1850 if (!localXdgDir.isEmpty())
1852 if (localXdgDir[localXdgDir.length()-1] != QLatin1Char(
'/'))
1853 localXdgDir += QLatin1Char(
'/');
1857 localXdgDir = QDir::homePath() + QLatin1String(
"/.local/share/");
1863 for (QStringList::ConstIterator it = xdgdirList.constBegin();
1864 it != xdgdirList.constEnd(); ++it)
1893 if (mapFile.isEmpty() || !QFile::exists(mapFile))
1895 profiles << QString::fromLatin1(
"default");
1899 struct passwd *pw = getpwuid(geteuid());
1902 profiles << QString::fromLatin1(
"default");
1906 QByteArray user = pw->pw_name;
1908 gid_t sup_gids[512];
1909 int sup_gids_nr = getgroups(512, sup_gids);
1913 if (mapCfg.
hasKey(user.constData()))
1924 for( QStringList::ConstIterator it = groups.begin();
1925 it != groups.end(); ++it )
1927 QByteArray grp = (*it).toUtf8();
1929 struct group *grp_ent = getgrnam(grp);
1930 if (!grp_ent)
continue;
1931 gid_t gid = grp_ent->gr_gid;
1932 if (pw->pw_gid == gid)
1939 for(
int i = 0; i < sup_gids_nr; i++)
1941 if (sup_gids[i] == gid)
1951 if (profiles.isEmpty())
1952 profiles << QString::fromLatin1(
"default");
1960 if (!d->m_checkRestrictions)
1976 int i = kioskAdmin.indexOf(QLatin1Char(
':'));
1977 QString user = kioskAdmin.left(i);
1978 QString host = kioskAdmin.mid(i+1);
1981 char hostname[ 256 ];
1982 hostname[ 0 ] =
'\0';
1983 if (!gethostname( hostname, 255 ))
1984 hostname[
sizeof(hostname)-1] =
'\0';
1987 (host.isEmpty() || (host == QLatin1String(hostname))))
1989 kde_kiosk_admin =
true;
1993 bool readProfiles =
true;
1995 if (kde_kiosk_admin && !qgetenv(
"KDE_KIOSK_NO_PROFILES").isEmpty())
1996 readProfiles =
false;
2000 if (!profileDirsPrefix.isEmpty() && !profileDirsPrefix.endsWith(QLatin1Char(
'/')))
2001 profileDirsPrefix.append(QLatin1Char(
'/'));
2008 bool priority =
false;
2013 for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
2021 if (list.isEmpty() && !profile.isEmpty() && !profileDirsPrefix.isEmpty())
2023 QString dir = profileDirsPrefix + profile;
2033 it2 != entries.end(); ++it2)
2035 const QString key = it2.key();
2036 if (key.startsWith(QLatin1String(
"dir_"))) {
2039 QStringList::ConstIterator sIt(dirs.begin());
2041 for (; sIt != dirs.end(); ++sIt)
2047 if (profiles.isEmpty())
2049 profile = profiles.back();
2050 group = QString::fromLatin1(
"Directories-%1").arg(profile);
2051 profiles.pop_back();
2057 if (!kde_kiosk_admin || qgetenv(
"KDE_KIOSK_NO_RESTRICTIONS").isEmpty())
2062 it2 != entries.end(); ++it2)
2064 const QString key = it2.key();
2067 d->m_restrictionsActive =
true;
2068 const QByteArray cKey = key.toLatin1();
2069 d->m_restrictions.insert(cKey,
true);
2070 d->m_dircache.remove(cKey);
2071 d->m_savelocations.remove(cKey);
2077 bool configDirsChanged = (
resourceDirs(
"config").count() != configdirs);
2079 d->m_checkRestrictions = configDirsChanged;
2081 return configDirsChanged;
2087 return d->m_prefixes.first();
2093 return d->xdgdata_prefixes.first();
2099 return d->xdgconf_prefixes.first();
2117 const QString& filename,
bool createDir,
2122 int slash = filename.lastIndexOf(QLatin1Char(
'/')) + 1;
2128 QString dir = filename.left(slash);
2129 QString file = filename.mid(slash);
2136 if ( accessOK == 0 )
2142 if ( (mode & W_OK) == 0 )
2151 int pos = dirName.lastIndexOf(QLatin1Char(
'/'));
2154 else if ( pos == 0 )
2157 dirName.truncate(pos);
2161 if ( accessOK == 0 )