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 dirs = m_relatives.value(type);
1107 const QString typeInstallPath = installPath(type);
1110 const QString installdir = typeInstallPath.isEmpty() ?
QString() : realPath(typeInstallPath).toLower();
1111 const QString installprefix = installPath(
"kdedir").toLower();
1113 const QString installdir = typeInstallPath.isEmpty() ?
QString() : realPath(typeInstallPath);
1114 const QString installprefix = installPath(
"kdedir");
1116 if (!dirs.isEmpty())
1120 for (QStringList::ConstIterator it = dirs.constBegin();
1121 it != dirs.constEnd(); ++it)
1123 if ((*it).startsWith(QLatin1Char(
'%'))) {
1125 const int pos = (*it).indexOf(QLatin1Char(
'/'));
1126 QString rel = (*it).mid(1, pos - 1);
1127 QString rest = (*it).mid(pos + 1);
1128 const QStringList basedirs = resourceDirs(rel.toUtf8().constData(), subdirForRestrictions);
1129 for (QStringList::ConstIterator it2 = basedirs.begin();
1130 it2 != basedirs.end(); ++it2)
1133 const QString path = realPath( *it2 + rest ).toLower();
1135 const QString path = realPath( *it2 + rest );
1137 testdir.setPath(path);
1138 if ((local || testdir.exists()) && !candidates.contains(path))
1139 candidates.append(path);
1146 if (strncmp(type,
"xdgdata-", 8) == 0)
1147 prefixList = &(xdgdata_prefixes);
1148 else if (strncmp(type,
"xdgconf-", 8) == 0)
1149 prefixList = &(xdgconf_prefixes);
1151 prefixList = &m_prefixes;
1153 for (QStringList::ConstIterator pit = prefixList->begin();
1154 pit != prefixList->end();
1157 if((*pit)!=installprefix||installdir.isEmpty())
1159 for (QStringList::ConstIterator it = dirs.constBegin();
1160 it != dirs.constEnd(); ++it)
1162 if ((*it).startsWith(QLatin1Char(
'%')))
1165 const QString path = realPath( *pit + *it ).toLower();
1167 const QString path = realPath( *pit + *it );
1169 testdir.setPath(path);
1170 if (local && restrictionActive)
1172 if ((local || testdir.exists()) && !candidates.contains(path))
1173 candidates.append(path);
1180 testdir.setPath(installdir);
1181 if(testdir.exists() && ! candidates.contains(installdir))
1182 candidates.append(installdir);
1188 if (!installdir.isEmpty()) {
1190 foreach (
const QString &s, candidates) {
1191 if (installdir.startsWith(s)) {
1197 candidates.append(installdir);
1200 dirs = m_absolutes.value(type);
1201 if (!dirs.isEmpty())
1202 for (QStringList::ConstIterator it = dirs.constBegin();
1203 it != dirs.constEnd(); ++it)
1205 testdir.setPath(*it);
1206 if (testdir.exists()) {
1208 const QString filename = realPath( *it ).toLower();
1210 const QString filename = realPath( *it );
1212 if (!candidates.contains(filename)) {
1213 candidates.append(filename);
1220 if (!dataRestrictionActive) {
1222 m_dircache.insert(type, candidates);
1227 kDebug(180) <<
"found dirs for resource" << type <<
":" << candidates;
1236 QStringList ret = QString::fromLocal8Bit(qgetenv(
"PATHEXT")).split(QLatin1Char(
';'));
1237 if (!ret.contains(QLatin1String(
".exe"), Qt::CaseInsensitive)) {
1240 ret << QLatin1String(
".exe")
1241 << QLatin1String(
".com")
1242 << QLatin1String(
".bat")
1243 << QLatin1String(
".cmd");
1256 p = QString::fromLocal8Bit( qgetenv(
"PATH" ) );
1259 QString delimiters(QLatin1Char(KPATH_SEPARATOR));
1260 delimiters += QLatin1Char(
'\b');
1266 for(
int i = 0; i < tokens.count(); i++ )
1280 bundle += QLatin1String(
".app/Contents/MacOS/") + bundle.section(QLatin1Char(
'/'), -1);
1281 info.setFile( bundle );
1283 if (file =
fopen(info.absoluteFilePath().toUtf8().constData(),
"r")) {
1286 if ((
stat(info.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
1289 if ( ignore || (_stat.st_mode & S_IXUSR) ) {
1290 if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
1304 if ( !bundle.isEmpty() ) {
1309 QFileInfo info( path );
1310 QFileInfo orig = info;
1311 #if defined(Q_OS_DARWIN) || defined(Q_OS_MAC)
1313 if (file =
fopen(orig.absoluteFilePath().toUtf8().constData(),
"r")) {
1316 if ((
stat(orig.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
1319 if ( ignoreExecBit || (_stat.st_mode & S_IXUSR) ) {
1320 if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
1321 orig.makeAbsolute();
1322 return orig.filePath();
1328 if( info.exists() && info.isSymLink() )
1329 info = QFileInfo( info.canonicalFilePath() );
1330 if( info.exists() && ( ignoreExecBit || info.isExecutable() ) && info.isFile() ) {
1334 orig.makeAbsolute();
1335 return orig.filePath();
1344 SearchOptions options )
1350 if (!executable_extensions.contains(appname.section(QLatin1Char(
'.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
1352 foreach (
const QString& extension, executable_extensions) {
1353 found_exe =
findExe(appname + extension, pstr, options);
1354 if (!found_exe.isEmpty()) {
1364 if (appname.contains(QDir::separator()))
1375 if (!result.isEmpty()) {
1382 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
1384 p = (*it) + QLatin1Char(
'/');
1389 if (!result.isEmpty()) {
1399 if (!result.isEmpty()) {
1412 const QString& pstr, SearchOptions options )
1416 if (!executable_extensions.contains(appname.section(QLatin1Char(
'.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
1418 foreach (
const QString& extension, executable_extensions) {
1419 total +=
findAllExe (list, appname + extension, pstr, options);
1429 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
1431 p = (*it) + QLatin1Char(
'/');
1436 if ( !bundle.isEmpty() ) {
1438 list.append( bundle );
1444 if( info.exists() && ( ( options &
IgnoreExecBit ) || info.isExecutable())
1445 && info.isFile() ) {
1450 return list.count();
1460 return f.absoluteFilePath();
1469 const int len = str.length();
1472 for(
int index = 0; index < len; index++) {
1473 if (delim.contains(str[index])) {
1477 token += str[index];
1480 if (!token.isEmpty()) {
1485 #ifndef KDE_NO_DEPRECATED
1488 return QString(QLatin1Char(
'%')) + QString::fromLatin1(type) + QLatin1Char(
'/');
1496 QMutexLocker lock(&d->m_cacheMutex);
1497 QString path = d->m_savelocations.value(type);
1501 if (dirs.isEmpty() && (
1502 (strcmp(type,
"socket") == 0) ||
1503 (strcmp(type,
"tmp") == 0) ||
1504 (strcmp(type,
"cache") == 0) ))
1507 dirs = d->m_relatives.value(type);
1509 if (!dirs.isEmpty())
1511 path = dirs.first();
1513 if (path.startsWith(QLatin1Char(
'%'))) {
1515 const int pos = path.indexOf(QLatin1Char(
'/'));
1516 QString rel = path.mid(1, pos - 1);
1517 QString rest = path.mid(pos + 1);
1519 path = basepath + rest;
1523 if (strncmp(type,
"xdgdata-", 8) == 0) {
1525 }
else if (strncmp(type,
"xdgconf-", 8) == 0) {
1532 dirs = d->m_absolutes.value(type);
1533 if (dirs.isEmpty()) {
1534 qFatal(
"KStandardDirs: The resource type %s is not registered", type);
1540 d->m_savelocations.insert(type, path.endsWith(QLatin1Char(
'/')) ? path : path + QLatin1Char(
'/'));
1542 QString fullPath = path + suffix;
1545 if (
KDE::stat(fullPath, &st) != 0 || !(S_ISDIR(st.st_mode))) {
1554 if(!
makeDir(fullPath, 0700)) {
1557 d->m_dircache.remove(type);
1559 if (!fullPath.endsWith(QLatin1Char(
'/')))
1560 fullPath += QLatin1Char(
'/');
1568 int i = absPath.lastIndexOf(QLatin1Char(
'/'));
1575 for (QStringList::ConstIterator it = candidates.begin();
1576 it != candidates.end(); ++it) {
1577 if (fullPath.startsWith(*it)) {
1578 return fullPath.mid((*it).length());
1588 if (QDir::isRelativePath(dir))
1592 return QDir().mkpath(dir);
1595 uint len = target.length();
1598 if (dir.at(len - 1) != QLatin1Char(
'/'))
1599 target += QLatin1Char(
'/');
1607 int pos = target.indexOf(QLatin1Char(
'/'), i);
1608 base += target.mid(i - 1, pos - i + 1);
1609 QByteArray baseEncoded = QFile::encodeName(base);
1611 if (KDE_stat(baseEncoded, &st) != 0)
1615 if (KDE_lstat(baseEncoded, &st) == 0)
1616 (void)unlink(baseEncoded);
1618 if (KDE_mkdir(baseEncoded, static_cast<mode_t>(mode)) != 0) {
1619 baseEncoded.prepend(
"trying to create local folder " );
1620 perror(baseEncoded.constData());
1634 c_path = qgetenv(env);
1635 if (c_path.isEmpty())
1643 c_path = retval.toAscii();
1646 return QDir::fromNativeSeparators(QFile::decodeName(c_path));
1650 static QString executablePrefix()
1652 char path_buffer[MAXPATHLEN + 1];
1653 path_buffer[MAXPATHLEN] = 0;
1654 int length = readlink (
"/proc/self/exe", path_buffer, MAXPATHLEN);
1658 path_buffer[length] =
'\0';
1660 QString path = QFile::decodeName(path_buffer);
1665 int pos = path.lastIndexOf(QLatin1Char(
'/'));
1668 pos = path.lastIndexOf(QLatin1Char(
'/'), pos - 1);
1672 return path.left(pos);
1676 void KStandardDirs::addResourcesFrom_krcdirs()
1678 QString localFile = QDir::currentPath() + QLatin1String(
"/.krcdirs");
1679 if (!QFile::exists(localFile))
1682 QSettings iniFile(localFile, QSettings::IniFormat);
1683 iniFile.beginGroup(QString::fromLatin1(
"KStandardDirs"));
1685 foreach(
const QString &key, resources)
1687 QDir path(iniFile.value(key).toString());
1691 if(path.makeAbsolute())
1696 void KStandardDirs::addKDEDefaults()
1698 addResourcesFrom_krcdirs();
1704 if (!kdedirs.isEmpty())
1710 QString execPrefix(QFile::decodeName(EXEC_INSTALL_PREFIX));
1711 if (!execPrefix.isEmpty() && !kdedirList.contains(execPrefix))
1712 kdedirList.append(execPrefix);
1714 const QString linuxExecPrefix = executablePrefix();
1715 if ( !linuxExecPrefix.isEmpty() )
1716 kdedirList.append( linuxExecPrefix );
1722 if (!localKdeDir.isEmpty()) {
1723 if (!localKdeDir.endsWith(QLatin1Char(
'/')))
1724 localKdeDir += QLatin1Char(
'/');
1730 #if defined(Q_WS_MACX)
1731 localKdeDir = QDir::homePath() + QLatin1String(
"/Library/Preferences/KDE/");
1732 #elif defined(Q_WS_WIN)
1734 WCHAR wPath[MAX_PATH+1];
1735 if ( SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wPath) == S_OK) {
1736 localKdeDir = QDir::fromNativeSeparators(QString::fromUtf16((
const ushort *) wPath)) + QLatin1Char(
'/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char(
'/');
1739 localKdeDir = QDir::homePath() + QLatin1Char(
'/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char(
'/');
1744 localKdeDir = QDir::homePath() + QLatin1Char(
'/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char(
'/');
1748 if (localKdeDir != QLatin1String(
"-/"))
1758 if (bundleDir.dirName() == QLatin1String(
"MacOS")) {
1766 QStringList::ConstIterator end(kdedirList.end());
1767 for (QStringList::ConstIterator it = kdedirList.constBegin();
1768 it != kdedirList.constEnd(); ++it)
1778 if (!xdgdirs.isEmpty())
1785 xdgdirList.append(QString::fromLatin1(
"/etc/xdg"));
1787 xdgdirList.append(
installPath(
"kdedir") + QString::fromLatin1(
"etc/xdg"));
1789 xdgdirList.append(QFile::decodeName(KDESYSCONFDIR
"/xdg"));
1794 if (!localXdgDir.isEmpty()) {
1795 if (!localXdgDir.endsWith(QLatin1Char(
'/')))
1796 localXdgDir += QLatin1Char(
'/');
1799 localXdgDir = QDir::homePath() + QString::fromLatin1(
"/Library/Preferences/XDG/");
1801 localXdgDir = QDir::homePath() + QString::fromLatin1(
"/.config/");
1808 for (QStringList::ConstIterator it = xdgdirList.constBegin();
1809 it != xdgdirList.constEnd(); ++it)
1818 for (QStringList::ConstIterator it = kdedirList.constBegin();
1819 it != kdedirList.constEnd(); ++it) {
1821 if (!dir.endsWith(QLatin1Char(
'/')))
1822 dir += QLatin1Char(
'/');
1823 kdedirDataDirs.append(dir + QLatin1String(
"share/"));
1827 if (!xdgdirs.isEmpty()) {
1832 Q_FOREACH(
const QString& dir, kdedirDataDirs) {
1833 if (!xdgdirList.contains(dir))
1834 xdgdirList.append(dir);
1837 xdgdirList = kdedirDataDirs;
1839 xdgdirList.append(QString::fromLatin1(
"/usr/local/share/"));
1840 xdgdirList.append(QString::fromLatin1(
"/usr/share/"));
1845 if (!localXdgDir.isEmpty())
1847 if (localXdgDir[localXdgDir.length()-1] != QLatin1Char(
'/'))
1848 localXdgDir += QLatin1Char(
'/');
1852 localXdgDir = QDir::homePath() + QLatin1String(
"/.local/share/");
1858 for (QStringList::ConstIterator it = xdgdirList.constBegin();
1859 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 )