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>
77 static Qt::CaseSensitivity
cs = Qt::CaseInsensitive;
79 static Qt::CaseSensitivity
cs = Qt::CaseSensitive;
82 class KStandardDirs::KStandardDirsPrivate
86 : m_restrictionsActive(
false),
87 m_checkRestrictions(
true),
88 m_cacheMutex(QMutex::Recursive),
92 bool hasDataRestrictions(
const QString &relPath)
const;
94 void createSpecialResource(
const char*);
96 bool m_restrictionsActive : 1;
97 bool m_checkRestrictions : 1;
194 "share/kde4/services\0"
196 "share/kde4/servicetypes\0"
210 "%lib/kde4/plugins\0"
212 "share/config.kcfg\0"
222 "desktop-directories\0"
226 "xdgconf-autostart\0"
231 0, 5, 16, 21, 36, 41, 53, 60,
232 73, 80, 94, 99, 112, 118, 131, 138,
233 151, 160, 180, 193, 217, 222, 236, 240,
234 248, 258, 275, 285, 301, 305, 309, 316,
235 326, 336, 354, 359, 377, 387, 403, 416,
236 429, 442, 448, 463, 471, 484, 504, 217,
237 517, 530, 536, 554, -1
244 : d(new KStandardDirsPrivate(this))
256 if (!d->m_restrictionsActive)
259 if (d->m_restrictions.value(type,
false))
262 if (strcmp(type,
"data")==0 && d->hasDataRestrictions(relPath))
268 bool KStandardDirs::KStandardDirsPrivate::hasDataRestrictions(
const QString &relPath)
const
271 const int i = relPath.indexOf(QLatin1Char(
'/'));
273 key = QString::fromLatin1(
"data_") + relPath.left(i);
275 key = QString::fromLatin1(
"data_") + relPath;
277 return m_restrictions.value(key.toLatin1(),
false);
287 list.append(QString::fromLatin1(
"lib"));
291 list.append(QString::fromLatin1(
"socket"));
292 list.append(QString::fromLatin1(
"tmp"));
293 list.append(QString::fromLatin1(
"cache"));
295 list.append(QString::fromLatin1(
"include"));
304 if (priority && !prefixes.isEmpty())
307 QStringList::iterator it = prefixes.begin();
309 prefixes.insert(it, dir);
313 prefixes.append(dir);
328 if (dir.at(dir.length() - 1) != QLatin1Char(
'/'))
329 dir += QLatin1Char(
'/');
331 if (!d->m_prefixes.contains(dir,
cs)) {
333 d->m_dircache.clear();
348 if (dir.at(dir.length() - 1) != QLatin1Char(
'/'))
349 dir += QLatin1Char(
'/');
351 if (!d->xdgconf_prefixes.contains(dir,
cs)) {
353 d->m_dircache.clear();
368 if (dir.at(dir.length() - 1) != QLatin1Char(
'/'))
369 dir += QLatin1Char(
'/');
371 if (!d->xdgdata_prefixes.contains(dir,
cs)) {
373 d->m_dircache.clear();
379 return d->m_prefixes.join(
QString(QLatin1Char(KPATH_SEPARATOR)));
384 return d->xdgconf_prefixes.join(
QString(QLatin1Char(KPATH_SEPARATOR)));
389 return d->xdgdata_prefixes.join(
QString(QLatin1Char(KPATH_SEPARATOR)));
392 #ifndef KDE_NO_DEPRECATED
402 const char *basetype,
406 if (relativename.isEmpty())
411 copy = QLatin1Char(
'%') + QString::fromLatin1(basetype) + QLatin1Char(
'/') + relativename;
413 if (!copy.endsWith(QLatin1Char(
'/')))
414 copy += QLatin1Char(
'/');
416 QByteArray typeBa = type;
419 if (!rels.contains(copy,
cs)) {
425 d->m_dircache.remove(typeBa);
426 d->m_savelocations.remove(typeBa);
436 if (absdir.isEmpty() || !type)
440 if (copy.at(copy.length() - 1) != QLatin1Char(
'/'))
441 copy += QLatin1Char(
'/');
443 QByteArray typeBa = type;
445 if (!paths.contains(copy,
cs)) {
451 d->m_dircache.remove(typeBa);
452 d->m_savelocations.remove(typeBa);
459 const QString& _filename )
const
461 if (!QDir::isRelativePath(_filename))
466 kDebug(180) <<
"Find resource: " << type;
467 for (QStringList::ConstIterator pit = m_prefixes.begin();
468 pit != m_prefixes.end();
471 kDebug(180) <<
"Prefix: " << *pit;
477 if(strcmp(type,
"exe") == 0) {
478 if(!filename.endsWith(QLatin1String(
".exe"), Qt::CaseInsensitive))
479 filename += QLatin1String(
".exe");
492 KDE_struct_stat buff;
493 if ((
KDE::access(file, R_OK) == 0) && (
KDE::stat(file, &buff) == 0) && (S_ISREG(buff.st_mode))) {
494 hash = hash +
static_cast<quint32>(buff.st_ctime);
501 SearchOptions options )
const
505 if (!QDir::isRelativePath(filename))
510 QStringList candidates = d->resourceDirs(type, filename);
512 foreach (
const QString& candidate, candidates )
514 hash =
updateHash(candidate + filename, hash);
515 if ( !( options &
Recursive ) && hash ) {
528 if (!QDir::isRelativePath(reldir))
530 testdir.setPath(reldir);
531 if (testdir.exists())
533 if (reldir.endsWith(QLatin1Char(
'/')))
536 list.append(reldir+QLatin1Char(
'/'));
541 const QStringList candidates = d->resourceDirs(type, reldir);
543 for (QStringList::ConstIterator it = candidates.begin();
544 it != candidates.end(); ++it) {
545 testdir.setPath(*it + reldir);
546 if (testdir.exists())
547 list.append(testdir.absolutePath() + QLatin1Char(
'/'));
554 const QString& _filename)
const
557 if (_filename.isEmpty()) {
558 kWarning() <<
"filename for type " << type <<
" in KStandardDirs::findResourceDir is not supposed to be empty!!";
565 if(strcmp(type,
"exe") == 0) {
566 if(!filename.endsWith(QLatin1String(
".exe"), Qt::CaseInsensitive))
567 filename += QLatin1String(
".exe");
570 const QStringList candidates = d->resourceDirs(type, filename);
572 for (QStringList::ConstIterator it = candidates.begin();
573 it != candidates.end(); ++it) {
574 if (
exists(*it + filename)) {
580 if(
false && strcmp(type,
"locale"))
581 kDebug(180) <<
"KStdDirs::findResDir(): can't find \"" << filename <<
"\" in type \"" << type <<
"\".";
593 if (fullPath.endsWith(QLatin1Char(
'/')))
594 return QDir(fullPath).exists();
595 return QFileInfo(fullPath).exists();
597 KDE_struct_stat buff;
598 QByteArray cFullPath = QFile::encodeName(fullPath);
599 if (
access(cFullPath, R_OK) == 0 && KDE_stat( cFullPath, &buff ) == 0) {
600 if (!fullPath.endsWith(QLatin1Char(
'/'))) {
601 if (S_ISREG( buff.st_mode ))
604 if (S_ISDIR( buff.st_mode ))
612 const QRegExp ®exp,
615 bool recursive,
bool unique)
617 const QString pattern = regexp.pattern();
618 if (recursive || pattern.contains(QLatin1Char(
'?')) || pattern.contains(QLatin1Char(
'*')))
623 QString path_ = path + QLatin1String(
"*.*" );
624 WIN32_FIND_DATA findData;
625 HANDLE hFile = FindFirstFile( (LPWSTR)path_.utf16(), &findData );
626 if( hFile == INVALID_HANDLE_VALUE )
629 const int len = wcslen( findData.cFileName );
630 if (!( findData.cFileName[0] ==
'.' &&
631 findData.cFileName[1] ==
'\0' ) &&
632 !( findData.cFileName[0] ==
'.' &&
633 findData.cFileName[1] ==
'.' &&
634 findData.cFileName[2] ==
'\0' ) &&
635 ( findData.cFileName[len-1] !=
'~' ) ) {
636 QString fn = QString::fromUtf16( (
const unsigned short*)findData.cFileName );
637 if (!recursive && !regexp.exactMatch(fn))
640 bool bIsDir = ( ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == FILE_ATTRIBUTE_DIRECTORY );
644 relPart + fn + QLatin1Char(
'/'),
645 regexp, list, relList, recursive, unique);
647 if (!regexp.exactMatch(fn))
652 if ( !unique || !relList.contains(relPart + fn,
cs) )
654 list.append( pathfn );
655 relList.append( relPart + fn );
659 }
while( FindNextFile( hFile, &findData ) != 0 );
663 DIR *dp = opendir( QFile::encodeName(path));
667 assert(path.endsWith(QLatin1Char(
'/')));
671 while( ( ep = readdir( dp ) ) != 0L )
673 QString fn( QFile::decodeName(ep->d_name));
674 if (fn == QString::fromLatin1(
".") || fn == QString::fromLatin1(
"..") || fn.at(fn.length() - 1) == QLatin1Char(
'~'))
677 if (!recursive && !regexp.exactMatch(fn))
684 #ifdef HAVE_DIRENT_D_TYPE
685 isDir = ep->d_type == DT_DIR;
686 isReg = ep->d_type == DT_REG;
688 if (ep->d_type == DT_UNKNOWN || ep->d_type == DT_LNK)
691 KDE_struct_stat buff;
693 kDebug(180) <<
"Error stat'ing " << pathfn <<
" : " <<
perror;
696 isReg = S_ISREG (buff.st_mode);
697 isDir = S_ISDIR (buff.st_mode);
702 lookupDirectory(pathfn + QLatin1Char(
'/'), relPart + fn + QLatin1Char(
'/'), regexp, list, relList, recursive, unique);
704 if (!regexp.exactMatch(fn))
709 if (!unique || !relList.contains(relPart + fn,
cs))
711 list.append( pathfn );
712 relList.append( relPart + fn );
724 KDE_struct_stat buff;
727 if ( S_ISREG( buff.st_mode))
729 if (!unique || !relList.contains(relPart + fn,
cs))
731 list.append( pathfn );
732 relList.append( relPart + fn );
740 const QRegExp ®exp,
743 bool recursive,
bool unique)
745 if (relpath.isEmpty()) {
747 Q_ASSERT(prefix != QLatin1String(
"/"));
749 relList, recursive, unique);
755 int slash = relpath.indexOf(QLatin1Char(
'/'));
757 rest = relpath.left(relpath.length() - 1);
759 path = relpath.left(slash);
760 rest = relpath.mid(slash + 1);
763 if (prefix.isEmpty())
767 assert(prefix.endsWith(QLatin1Char(
'/')));
769 if (path.contains(QLatin1Char(
'*')) || path.contains(QLatin1Char(
'?'))) {
771 QRegExp pathExp(path, Qt::CaseSensitive, QRegExp::Wildcard);
774 QString prefix_ = prefix + QLatin1String(
"*.*" );
775 WIN32_FIND_DATA findData;
776 HANDLE hFile = FindFirstFile( (LPWSTR)prefix_.utf16(), &findData );
777 if( hFile == INVALID_HANDLE_VALUE )
780 const int len = wcslen( findData.cFileName );
781 if (!( findData.cFileName[0] ==
'.' &&
782 findData.cFileName[1] ==
'\0' ) &&
783 !( findData.cFileName[0] ==
'.' &&
784 findData.cFileName[1] ==
'.' &&
785 findData.cFileName[2] ==
'\0' ) &&
786 ( findData.cFileName[len-1] !=
'~' ) ) {
787 const QString fn = QString::fromUtf16( (
const unsigned short*)findData.cFileName );
788 if ( !pathExp.exactMatch(fn) )
790 if ( ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == FILE_ATTRIBUTE_DIRECTORY )
792 rest, relPart + fn + QLatin1Char(
'/'),
793 regexp, list, relList, recursive, unique);
795 }
while( FindNextFile( hFile, &findData ) != 0 );
798 DIR *dp = opendir( QFile::encodeName(prefix) );
805 while( ( ep = readdir( dp ) ) != 0L )
807 QString fn( QFile::decodeName(ep->d_name));
808 if (fn == QLatin1String(
".") || fn == QLatin1String(
"..") || fn.at(fn.length() - 1) == QLatin1Char(
'~'))
811 if ( !pathExp.exactMatch(fn) )
818 #ifdef HAVE_DIRENT_D_TYPE
819 isDir = ep->d_type == DT_DIR;
821 if (ep->d_type == DT_UNKNOWN || ep->d_type == DT_LNK)
825 KDE_struct_stat buff;
827 kDebug(180) <<
"Error stat'ing " << fn <<
" : " <<
perror;
830 isDir = S_ISDIR (buff.st_mode);
833 lookupPrefix(fn + QLatin1Char(
'/'), rest, rfn + QLatin1Char(
'/'), regexp, list, relList, recursive, unique);
842 relPart + path + QLatin1Char(
'/'), regexp, list,
843 relList, recursive, unique);
850 SearchOptions options,
856 if ( !filter.isEmpty() )
858 int slash = filter.lastIndexOf(QLatin1Char(
'/'));
862 filterPath = filter.left(slash + 1);
863 filterFile = filter.mid(slash + 1);
868 if ( !QDir::isRelativePath(filter) )
871 candidates << filterPath.left(3);
872 filterPath = filterPath.mid(3);
874 candidates << QString::fromLatin1(
"/");
875 filterPath = filterPath.mid(1);
880 candidates = d->resourceDirs(type, filter);
883 if (filterFile.isEmpty()) {
884 filterFile =
QString(QLatin1Char(
'*'));
887 QRegExp regExp(filterFile, Qt::CaseSensitive, QRegExp::Wildcard);
890 foreach (
const QString& candidate, candidates )
902 SearchOptions options )
const
918 if (!strRet.endsWith(QLatin1Char(
'/')))
919 return strRet + QLatin1Char(
'/');
922 if (dirname.isEmpty() || (dirname.size() == 1 && dirname.at(0) == QLatin1Char(
'/')))
925 if (dirname.at(0) != QLatin1Char(
'/')) {
926 qWarning(
"realPath called with a relative path '%s', please fix", qPrintable(dirname));
930 char realpath_buffer[MAXPATHLEN + 1];
931 memset(realpath_buffer, 0, MAXPATHLEN + 1);
934 if (realpath( QFile::encodeName(dirname).constData(), realpath_buffer) != 0) {
936 int len = strlen(realpath_buffer);
937 realpath_buffer[len] =
'/';
938 realpath_buffer[len+1] = 0;
939 return QFile::decodeName(realpath_buffer);
947 if (!dir.endsWith(QLatin1Char(
'/')))
948 dir += QLatin1Char(
'/');
952 const int pos = dir.lastIndexOf(QLatin1Char(
'/'), -2);
954 relative.prepend(dir.mid(pos+1));
955 dir = dir.left(pos+1);
956 Q_ASSERT(dir.endsWith(QLatin1Char(
'/')));
958 Q_ASSERT(!relative.isEmpty());
959 if (!relative.isEmpty()) {
976 LPCWSTR lpIn = (LPCWSTR)filename.utf16();
977 QVarLengthArray<WCHAR, MAX_PATH> buf(MAX_PATH);
978 DWORD len = GetFullPathNameW(lpIn, buf.size(), buf.data(), NULL);
979 if (len > (DWORD)buf.size()) {
981 len = GetFullPathNameW(lpIn, buf.size(), buf.data(), NULL);
985 return QString::fromUtf16((
const unsigned short*)buf.data()).replace(QLatin1Char(
'\\'),QLatin1Char(
'/'));
987 char realpath_buffer[MAXPATHLEN + 1];
988 memset(realpath_buffer, 0, MAXPATHLEN + 1);
991 if (realpath( QFile::encodeName(filename).constData(), realpath_buffer) != 0) {
993 return QFile::decodeName(realpath_buffer);
1001 void KStandardDirs::KStandardDirsPrivate::createSpecialResource(
const char *type)
1005 gethostname(hostname, 255);
1006 const QString localkdedir = m_prefixes.first();
1007 QString dir = localkdedir + QString::fromLatin1(type) + QLatin1Char(
'-') + QString::fromLocal8Bit(hostname);
1010 int result = readlink(QFile::encodeName(dir).constData(), link, 1023);
1011 bool relink = (result == -1) && (errno == ENOENT);
1015 if (!QDir::isRelativePath(QFile::decodeName(link)))
1017 KDE_struct_stat stat_buf;
1018 int res =
KDE::lstat(QFile::decodeName(link), &stat_buf);
1019 if ((res == -1) && (errno == ENOENT))
1023 else if ((res == -1) || (!S_ISDIR(stat_buf.st_mode)))
1025 fprintf(stderr,
"Error: \"%s\" is not a directory.\n", link);
1028 else if (stat_buf.st_uid != getuid())
1030 fprintf(stderr,
"Error: \"%s\" is owned by uid %d instead of uid %d.\n", link, stat_buf.st_uid, getuid());
1038 if (!makeDir(dir, 0700))
1039 fprintf(stderr,
"failed to create \"%s\"", qPrintable(dir));
1041 result = readlink(QFile::encodeName(dir).constData(), link, 1023);
1046 QString srv = findExe(QLatin1String(
"lnusertemp"), installPath(
"libexec"));
1048 srv = findExe(QLatin1String(
"lnusertemp"));
1051 if (system(QByteArray(QFile::encodeName(srv) +
' ' + type)) == -1) {
1052 fprintf(stderr,
"Error: unable to launch lnusertemp command" );
1054 result = readlink(QFile::encodeName(dir).constData(), link, 1023);
1061 dir = QFile::decodeName(link);
1063 dir = QDir::cleanPath(dir + QFile::decodeName(link));
1066 q->addResourceDir(type, dir + QLatin1Char(
'/'),
false);
1071 return d->resourceDirs(type,
QString());
1074 QStringList KStandardDirs::KStandardDirsPrivate::resourceDirs(
const char* type,
const QString& subdirForRestrictions)
1076 QMutexLocker lock(&m_cacheMutex);
1077 const bool dataRestrictionActive = m_restrictionsActive
1078 && (strcmp(type,
"data") == 0)
1079 && hasDataRestrictions(subdirForRestrictions);
1085 if (dirCacheIt != m_dircache.constEnd() && !dataRestrictionActive) {
1087 candidates = *dirCacheIt;
1092 if (strcmp(type,
"socket") == 0)
1093 createSpecialResource(type);
1094 else if (strcmp(type,
"tmp") == 0)
1095 createSpecialResource(type);
1096 else if (strcmp(type,
"cache") == 0)
1097 createSpecialResource(type);
1101 bool restrictionActive =
false;
1102 if (m_restrictionsActive) {
1103 if (dataRestrictionActive)
1104 restrictionActive =
true;
1105 if (m_restrictions.value(
"all",
false))
1106 restrictionActive =
true;
1107 else if (m_restrictions.value(type,
false))
1108 restrictionActive =
true;
1112 const QString typeInstallPath = installPath(type);
1113 const QString installdir = typeInstallPath.isEmpty() ?
QString() : realPath(typeInstallPath);
1114 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)
1131 const QString path = realPath( *it2 + rest );
1132 testdir.setPath(path);
1133 if ((local || testdir.exists()) && !candidates.contains(path,
cs))
1134 candidates.append(path);
1141 if (strncmp(type,
"xdgdata-", 8) == 0)
1142 prefixList = &(xdgdata_prefixes);
1143 else if (strncmp(type,
"xdgconf-", 8) == 0)
1144 prefixList = &(xdgconf_prefixes);
1146 prefixList = &m_prefixes;
1148 for (QStringList::ConstIterator pit = prefixList->begin();
1149 pit != prefixList->end();
1154 if((*pit).compare(installprefix,
cs) != 0 || installdir.isEmpty() || !strcmp(
"exe", type))
1156 for (QStringList::ConstIterator it = dirs.constBegin();
1157 it != dirs.constEnd(); ++it)
1159 if ((*it).startsWith(QLatin1Char(
'%')))
1161 const QString path = realPath( *pit + *it );
1162 testdir.setPath(path);
1163 if (local && restrictionActive)
1165 if ((local || testdir.exists()) && !candidates.contains(path,
cs))
1166 candidates.append(path);
1171 if (local && !strcmp(
"config", type))
1172 candidates.append(QLatin1String(
"/etc/kde/"));
1178 testdir.setPath(installdir);
1179 if(testdir.exists() && ! candidates.contains(installdir,
cs))
1180 candidates.append(installdir);
1186 if (!installdir.isEmpty()) {
1188 foreach (
const QString &s, candidates) {
1189 if (installdir.startsWith(s,
cs)) {
1195 candidates.append(installdir);
1198 const QStringList absDirs = m_absolutes.value(type);
1199 for (QStringList::ConstIterator it = absDirs.constBegin();
1200 it != absDirs.constEnd(); ++it)
1202 testdir.setPath(*it);
1203 if (testdir.exists()) {
1204 const QString filename = realPath( *it );
1205 if (!candidates.contains(filename,
cs)) {
1206 candidates.append(filename);
1213 if (!dataRestrictionActive) {
1215 m_dircache.insert(type, candidates);
1220 kDebug(180) <<
"found dirs for resource" << type <<
":" << candidates;
1229 QStringList ret = QString::fromLocal8Bit(qgetenv(
"PATHEXT")).split(QLatin1Char(
';'));
1230 if (!ret.contains(QLatin1String(
".exe"), Qt::CaseInsensitive)) {
1233 ret << QLatin1String(
".exe")
1234 << QLatin1String(
".com")
1235 << QLatin1String(
".bat")
1236 << QLatin1String(
".cmd");
1249 p = QString::fromLocal8Bit( qgetenv(
"PATH" ) );
1252 QString delimiters(QLatin1Char(KPATH_SEPARATOR));
1253 delimiters += QLatin1Char(
'\b');
1259 for(
int i = 0; i < tokens.count(); i++ )
1273 bundle += QLatin1String(
".app/Contents/MacOS/") + bundle.section(QLatin1Char(
'/'), -1);
1274 info.setFile( bundle );
1276 if (file =
fopen(info.absoluteFilePath().toUtf8().constData(),
"r")) {
1279 if ((
stat(info.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
1282 if ( ignore || (_stat.st_mode & S_IXUSR) ) {
1283 if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
1297 if ( !bundle.isEmpty() ) {
1302 QFileInfo info( path );
1303 QFileInfo orig = info;
1304 #if defined(Q_OS_DARWIN) || defined(Q_OS_MAC)
1306 if (file =
fopen(orig.absoluteFilePath().toUtf8().constData(),
"r")) {
1309 if ((
stat(orig.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
1312 if ( ignoreExecBit || (_stat.st_mode & S_IXUSR) ) {
1313 if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
1314 orig.makeAbsolute();
1315 return orig.filePath();
1321 if( info.exists() && info.isSymLink() )
1322 info = QFileInfo( info.canonicalFilePath() );
1323 if( info.exists() && ( ignoreExecBit || info.isExecutable() ) && info.isFile() ) {
1327 orig.makeAbsolute();
1328 return orig.filePath();
1337 SearchOptions options )
1343 if (!executable_extensions.contains(appname.section(QLatin1Char(
'.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
1345 foreach (
const QString& extension, executable_extensions) {
1346 found_exe =
findExe(appname + extension, pstr, options);
1347 if (!found_exe.isEmpty()) {
1357 if (appname.contains(QDir::separator()))
1368 if (!result.isEmpty()) {
1375 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
1377 p = (*it) + QLatin1Char(
'/');
1382 if (!result.isEmpty()) {
1392 if (!result.isEmpty()) {
1405 const QString& pstr, SearchOptions options )
1409 if (!executable_extensions.contains(appname.section(QLatin1Char(
'.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
1411 foreach (
const QString& extension, executable_extensions) {
1412 total +=
findAllExe (list, appname + extension, pstr, options);
1422 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
1424 p = (*it) + QLatin1Char(
'/');
1429 if ( !bundle.isEmpty() ) {
1431 list.append( bundle );
1437 if( info.exists() && ( ( options &
IgnoreExecBit ) || info.isExecutable())
1438 && info.isFile() ) {
1443 return list.count();
1453 return f.absoluteFilePath();
1462 const int len = str.length();
1465 for(
int index = 0; index < len; index++) {
1466 if (delim.contains(str[index])) {
1470 token += str[index];
1473 if (!token.isEmpty()) {
1478 #ifndef KDE_NO_DEPRECATED
1481 return QString(QLatin1Char(
'%')) + QString::fromLatin1(type) + QLatin1Char(
'/');
1489 QMutexLocker lock(&d->m_cacheMutex);
1490 QString path = d->m_savelocations.value(type);
1494 if (dirs.isEmpty() && (
1495 (strcmp(type,
"socket") == 0) ||
1496 (strcmp(type,
"tmp") == 0) ||
1497 (strcmp(type,
"cache") == 0) ))
1500 dirs = d->m_relatives.value(type);
1502 if (!dirs.isEmpty())
1504 path = dirs.first();
1506 if (path.startsWith(QLatin1Char(
'%'))) {
1508 const int pos = path.indexOf(QLatin1Char(
'/'));
1509 QString rel = path.mid(1, pos - 1);
1510 QString rest = path.mid(pos + 1);
1512 path = basepath + rest;
1516 if (strncmp(type,
"xdgdata-", 8) == 0) {
1518 }
else if (strncmp(type,
"xdgconf-", 8) == 0) {
1525 dirs = d->m_absolutes.value(type);
1526 if (dirs.isEmpty()) {
1527 qFatal(
"KStandardDirs: The resource type %s is not registered", type);
1533 d->m_savelocations.insert(type, path.endsWith(QLatin1Char(
'/')) ? path : path + QLatin1Char(
'/'));
1535 QString fullPath = path + suffix;
1538 if (
KDE::stat(fullPath, &st) != 0 || !(S_ISDIR(st.st_mode))) {
1547 if(!
makeDir(fullPath, 0700)) {
1550 d->m_dircache.remove(type);
1552 if (!fullPath.endsWith(QLatin1Char(
'/')))
1553 fullPath += QLatin1Char(
'/');
1561 int i = absPath.lastIndexOf(QLatin1Char(
'/'));
1568 for (QStringList::ConstIterator it = candidates.begin();
1569 it != candidates.end(); ++it) {
1570 if (fullPath.startsWith(*it,
cs)) {
1571 return fullPath.mid((*it).length());
1581 if (QDir::isRelativePath(dir))
1585 return QDir().mkpath(dir);
1588 uint len = target.length();
1591 if (dir.at(len - 1) != QLatin1Char(
'/'))
1592 target += QLatin1Char(
'/');
1600 int pos = target.indexOf(QLatin1Char(
'/'), i);
1601 base += target.mid(i - 1, pos - i + 1);
1602 QByteArray baseEncoded = QFile::encodeName(base);
1604 if (KDE_stat(baseEncoded, &st) != 0)
1608 if (KDE_lstat(baseEncoded, &st) == 0)
1609 (void)unlink(baseEncoded);
1611 if (KDE_mkdir(baseEncoded, static_cast<mode_t>(mode)) != 0) {
1612 baseEncoded.prepend(
"trying to create local folder " );
1613 perror(baseEncoded.constData());
1627 c_path = qgetenv(env);
1628 if (c_path.isEmpty())
1636 c_path = retval.toLatin1();
1639 return QDir::fromNativeSeparators(QFile::decodeName(c_path));
1643 static QString executablePrefix()
1645 char path_buffer[MAXPATHLEN + 1];
1646 path_buffer[MAXPATHLEN] = 0;
1647 int length = readlink (
"/proc/self/exe", path_buffer, MAXPATHLEN);
1651 path_buffer[length] =
'\0';
1653 QString path = QFile::decodeName(path_buffer);
1658 int pos = path.lastIndexOf(QLatin1Char(
'/'));
1661 pos = path.lastIndexOf(QLatin1Char(
'/'), pos - 1);
1665 return path.left(pos);
1669 void KStandardDirs::addResourcesFrom_krcdirs()
1671 QString localFile = QDir::currentPath() + QLatin1String(
"/.krcdirs");
1672 if (!QFile::exists(localFile))
1675 QSettings iniFile(localFile, QSettings::IniFormat);
1676 iniFile.beginGroup(QString::fromLatin1(
"KStandardDirs"));
1678 foreach(
const QString &key, resources)
1680 QDir path(iniFile.value(key).toString());
1684 if(path.makeAbsolute())
1689 void KStandardDirs::addKDEDefaults()
1691 addResourcesFrom_krcdirs();
1697 if (!kdedirs.isEmpty())
1703 QString execPrefix(QFile::decodeName(EXEC_INSTALL_PREFIX));
1704 if (!execPrefix.isEmpty() && !kdedirList.contains(execPrefix,
cs))
1705 kdedirList.append(execPrefix);
1707 const QString linuxExecPrefix = executablePrefix();
1708 if ( !linuxExecPrefix.isEmpty() )
1709 kdedirList.append( linuxExecPrefix );
1715 if (!localKdeDir.isEmpty()) {
1716 if (!localKdeDir.endsWith(QLatin1Char(
'/')))
1717 localKdeDir += QLatin1Char(
'/');
1723 #if defined(Q_WS_MACX)
1724 localKdeDir = QDir::homePath() + QLatin1String(
"/Library/Preferences/KDE/");
1725 #elif defined(Q_WS_WIN)
1727 WCHAR wPath[MAX_PATH+1];
1728 if ( SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wPath) == S_OK) {
1729 localKdeDir = QDir::fromNativeSeparators(QString::fromUtf16((
const ushort *) wPath)) + QLatin1Char(
'/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char(
'/');
1732 localKdeDir = QDir::homePath() + QLatin1Char(
'/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char(
'/');
1737 localKdeDir = QDir::homePath() + QLatin1Char(
'/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char(
'/');
1741 if (localKdeDir != QLatin1String(
"-/"))
1751 if (bundleDir.dirName() == QLatin1String(
"MacOS")) {
1759 QStringList::ConstIterator end(kdedirList.end());
1760 for (QStringList::ConstIterator it = kdedirList.constBegin();
1761 it != kdedirList.constEnd(); ++it)
1771 if (!xdgdirs.isEmpty())
1778 xdgdirList.append(QString::fromLatin1(
"/etc/xdg"));
1780 xdgdirList.append(
installPath(
"kdedir") + QString::fromLatin1(
"etc/xdg"));
1782 xdgdirList.append(QFile::decodeName(KDESYSCONFDIR
"/xdg"));
1787 if (!localXdgDir.isEmpty()) {
1788 if (!localXdgDir.endsWith(QLatin1Char(
'/')))
1789 localXdgDir += QLatin1Char(
'/');
1792 localXdgDir = QDir::homePath() + QString::fromLatin1(
"/Library/Preferences/XDG/");
1794 localXdgDir = QDir::homePath() + QString::fromLatin1(
"/.config/");
1801 for (QStringList::ConstIterator it = xdgdirList.constBegin();
1802 it != xdgdirList.constEnd(); ++it)
1811 for (QStringList::ConstIterator it = kdedirList.constBegin();
1812 it != kdedirList.constEnd(); ++it) {
1814 if (!dir.endsWith(QLatin1Char(
'/')))
1815 dir += QLatin1Char(
'/');
1816 kdedirDataDirs.append(dir + QLatin1String(
"share/"));
1820 if (!xdgdirs.isEmpty()) {
1825 Q_FOREACH(
const QString& dir, kdedirDataDirs) {
1826 if (!xdgdirList.contains(dir,
cs))
1827 xdgdirList.append(dir);
1830 xdgdirList = kdedirDataDirs;
1832 xdgdirList.append(QString::fromLatin1(
"/usr/local/share/"));
1833 xdgdirList.append(QString::fromLatin1(
"/usr/share/"));
1838 if (!localXdgDir.isEmpty())
1840 if (localXdgDir[localXdgDir.length()-1] != QLatin1Char(
'/'))
1841 localXdgDir += QLatin1Char(
'/');
1845 localXdgDir = QDir::homePath() + QLatin1String(
"/.local/share/");
1851 for (QStringList::ConstIterator it = xdgdirList.constBegin();
1852 it != xdgdirList.constEnd(); ++it)
1881 if (mapFile.isEmpty() || !QFile::exists(mapFile))
1883 profiles << QString::fromLatin1(
"default");
1887 struct passwd *pw = getpwuid(geteuid());
1890 profiles << QString::fromLatin1(
"default");
1894 QByteArray user = pw->pw_name;
1896 gid_t sup_gids[512];
1897 int sup_gids_nr = getgroups(512, sup_gids);
1901 if (mapCfg.
hasKey(user.constData()))
1912 for( QStringList::ConstIterator it = groups.begin();
1913 it != groups.end(); ++it )
1915 QByteArray grp = (*it).toUtf8();
1917 struct group *grp_ent = getgrnam(grp);
1918 if (!grp_ent)
continue;
1919 gid_t gid = grp_ent->gr_gid;
1920 if (pw->pw_gid == gid)
1927 for(
int i = 0; i < sup_gids_nr; i++)
1929 if (sup_gids[i] == gid)
1939 if (profiles.isEmpty())
1940 profiles << QString::fromLatin1(
"default");
1948 if (!d->m_checkRestrictions)
1964 int i = kioskAdmin.indexOf(QLatin1Char(
':'));
1965 QString user = kioskAdmin.left(i);
1966 QString host = kioskAdmin.mid(i+1);
1969 char hostname[ 256 ];
1970 hostname[ 0 ] =
'\0';
1971 if (!gethostname( hostname, 255 ))
1972 hostname[
sizeof(hostname)-1] =
'\0';
1975 (host.isEmpty() || (host == QLatin1String(hostname))))
1977 kde_kiosk_admin =
true;
1981 bool readProfiles =
true;
1983 if (kde_kiosk_admin && !qgetenv(
"KDE_KIOSK_NO_PROFILES").isEmpty())
1984 readProfiles =
false;
1988 if (!profileDirsPrefix.isEmpty() && !profileDirsPrefix.endsWith(QLatin1Char(
'/')))
1989 profileDirsPrefix.append(QLatin1Char(
'/'));
1996 bool priority =
false;
2001 for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
2009 if (list.isEmpty() && !profile.isEmpty() && !profileDirsPrefix.isEmpty())
2011 QString dir = profileDirsPrefix + profile;
2021 it2 != entries.end(); ++it2)
2023 const QString key = it2.key();
2024 if (key.startsWith(QLatin1String(
"dir_"))) {
2027 QStringList::ConstIterator sIt(dirs.begin());
2029 for (; sIt != dirs.end(); ++sIt)
2035 if (profiles.isEmpty())
2037 profile = profiles.back();
2038 group = QString::fromLatin1(
"Directories-%1").arg(profile);
2039 profiles.pop_back();
2045 if (!kde_kiosk_admin || qgetenv(
"KDE_KIOSK_NO_RESTRICTIONS").isEmpty())
2050 it2 != entries.end(); ++it2)
2052 const QString key = it2.key();
2055 d->m_restrictionsActive =
true;
2056 const QByteArray cKey = key.toLatin1();
2057 d->m_restrictions.insert(cKey,
true);
2058 d->m_dircache.remove(cKey);
2059 d->m_savelocations.remove(cKey);
2065 bool configDirsChanged = (
resourceDirs(
"config").count() != configdirs);
2067 d->m_checkRestrictions = configDirsChanged;
2069 return configDirsChanged;
2075 return d->m_prefixes.first();
2081 return d->xdgdata_prefixes.first();
2087 return d->xdgconf_prefixes.first();
2105 const QString& filename,
bool createDir,
2110 int slash = filename.lastIndexOf(QLatin1Char(
'/')) + 1;
2116 QString dir = filename.left(slash);
2117 QString file = filename.mid(slash);
2124 if ( accessOK == 0 )
2130 if ( (mode & W_OK) == 0 )
2139 int pos = dirName.lastIndexOf(QLatin1Char(
'/'));
2142 else if ( pos == 0 )
2145 dirName.truncate(pos);
2149 if ( accessOK == 0 )
QString saveLocation(const char *type, const QString &suffix=QString(), bool create=true) const
Finds a location to save files into for the given type in the user's home directory.
QString kfsstnd_xdg_conf_prefixes()
static QStringList lookupProfiles(const QString &mapFile)
static const char types_string[]
static quint32 updateHash(const QString &file, quint32 hash)
static QString equalizePath(QString &str)
QDebug perror(QDebug s, KDebugTag)
QString localizedFilePath(const QString &filePath) const
static QString realFilePath(const QString &filename)
Expands all symbolic links and resolves references to '/.
bool addResourceType(const char *type, const QString &relativename, bool priority=true)
Adds suffixes for types.
void addPrefix(const QString &dir)
Adds another search dir to front of the fsstnd list.
KStandardDirs()
KStandardDirs' constructor.
QStringList findDirs(const char *type, const QString &reldir) const
Tries to find all directories whose names consist of the specified type and a relative path...
static QString locate(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
This function is just for convenience.
static QStringList executableExtensions()
KStandardDirs * dirs()
Returns the application standard dirs object.
static Qt::CaseSensitivity cs
int stat(const QString &path, KDE_struct_stat *buf)
static bool checkAccess(const QString &pathname, int mode)
Check, if a file may be accessed in a given mode.
static QString readEnvPath(const char *env)
static const int types_indices[]
static bool exists(const QString &fullPath)
Checks for existence and accessability of a file or directory.
virtual ~KStandardDirs()
KStandardDirs' destructor.
KSharedConfigPtr config()
Returns the general config object.
static bool makeDir(const QString &dir, int mode=0755)
Recursively creates still-missing directories in the given path.
Represents a user on your system.
QMap< QString, QString > entryMap(const QString &aGroup=QString()) const
Returns a map (tree) of entries in a particular group.
void addXdgDataPrefix(const QString &dir)
Adds another search dir to front of the XDG_DATA_XXX list of prefixes.
Site-independent access to standard KDE directories.
QString loginName() const
The login name of the user.
static QStringList systemPaths(const QString &pstr=QString())
Returns a QStringList list of pathnames in the system path.
QString relativeLocation(const char *type, const QString &absPath)
Converts an absolute path to a path relative to a certain resource.
QString kfsstnd_xdg_data_prefixes()
static int findAllExe(QStringList &list, const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
Finds all occurrences of an executable in the system path.
QString localxdgdatadir() const
static void lookupPrefix(const QString &prefix, const QString &relpath, const QString &relPart, const QRegExp ®exp, QStringList &list, QStringList &relList, bool recursive, bool unique)
quint32 calcResourceHash(const char *type, const QString &filename, SearchOptions options=NoSearchOptions) const
Returns a number that identifies this version of the resource.
QString mac_app_filename()
Get the application name.
QString kfsstnd_prefixes()
QString localxdgconfdir() const
static QString installPath(const char *type)
QString findResourceDir(const char *type, const QString &filename) const
Tries to find the directory the file is in.
QStringList resourceDirs(const char *type) const
This function is used internally by almost all other function as it serves and fills the directories ...
static QString getBundle(const QString &path, bool ignore)
int lstat(const QString &path, KDE_struct_stat *buf)
bool hasKey(const QString &key) const
Checks whether the key has an entry in this group.
KLocale * locale()
Returns the global locale object.
A class for one specific group in a KConfig object.
The central class of the KDE configuration data system.
static void tokenize(QStringList &token, const QString &str, const QString &delim)
static QString checkExecutable(const QString &path, bool ignoreExecBit)
static QString locateLocal(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
This function is much like locate.
int access(const QString &path, int mode)
static void lookupDirectory(const QString &path, const QString &relPart, const QRegExp ®exp, QStringList &list, QStringList &relList, bool recursive, bool unique)
bool isRestrictedResource(const char *type, const QString &relPath=QString()) const
Checks whether a resource is restricted as part of the KIOSK framework.
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
Finds the executable in the system path.
static void priorityAdd(QStringList &prefixes, const QString &dir, bool priority)
QString findResource(const char *type, const QString &filename) const
Tries to find a resource in the following order:
QString tildeExpand(const QString &path)
Performs tilde expansion on path.
QString localkdedir() const
Returns the toplevel directory in which KStandardDirs will store things.
FILE * fopen(const QString &pathname, const char *mode)
QStringList allTypes() const
This function will return a list of all the types that KStandardDirs supports.
bool addCustomized(KConfig *config)
Reads customized entries out of the given config object and add them via addResourceDirs().
QStringList findAllResources(const char *type, const QString &filter=QString(), SearchOptions options=NoSearchOptions) const
Tries to find all resources with the specified type.
void addXdgConfigPrefix(const QString &dir)
Adds another search dir to front of the XDG_CONFIG_XXX list of prefixes.
T readEntry(const QString &key, const T &aDefault) const
Reads the value of an entry specified by pKey in the current group.
static QString realPath(const QString &dirname)
Expands all symbolic links and resolves references to '/.
bool addResourceDir(const char *type, const QString &absdir, bool priority=true)
Adds absolute path at the beginning of the search path for particular types (for example in case of i...
QMap< QString, QString > entryMap() const
Returns a map (tree) of entries for all entries in this group.
QString getWin32RegistryValue(HKEY key, const QString &subKey, const QString &item, bool *ok)
static QString kde_default(const char *type)
This returns a default relative path for the standard KDE resource types.
KStandardDirs * dirs() const
Returns the application standard dirs object.