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();
1152 if((*pit).compare(installprefix,
cs) != 0 || installdir.isEmpty())
1154 for (QStringList::ConstIterator it = dirs.constBegin();
1155 it != dirs.constEnd(); ++it)
1157 if ((*it).startsWith(QLatin1Char(
'%')))
1159 const QString path = realPath( *pit + *it );
1160 testdir.setPath(path);
1161 if (local && restrictionActive)
1163 if ((local || testdir.exists()) && !candidates.contains(path,
cs))
1164 candidates.append(path);
1171 testdir.setPath(installdir);
1172 if(testdir.exists() && ! candidates.contains(installdir,
cs))
1173 candidates.append(installdir);
1179 if (!installdir.isEmpty()) {
1181 foreach (
const QString &s, candidates) {
1182 if (installdir.startsWith(s,
cs)) {
1188 candidates.append(installdir);
1191 const QStringList absDirs = m_absolutes.value(type);
1192 for (QStringList::ConstIterator it = absDirs.constBegin();
1193 it != absDirs.constEnd(); ++it)
1195 testdir.setPath(*it);
1196 if (testdir.exists()) {
1197 const QString filename = realPath( *it );
1198 if (!candidates.contains(filename,
cs)) {
1199 candidates.append(filename);
1206 if (!dataRestrictionActive) {
1208 m_dircache.insert(type, candidates);
1213 kDebug(180) <<
"found dirs for resource" << type <<
":" << candidates;
1222 QStringList ret = QString::fromLocal8Bit(qgetenv(
"PATHEXT")).split(QLatin1Char(
';'));
1223 if (!ret.contains(QLatin1String(
".exe"), Qt::CaseInsensitive)) {
1226 ret << QLatin1String(
".exe")
1227 << QLatin1String(
".com")
1228 << QLatin1String(
".bat")
1229 << QLatin1String(
".cmd");
1242 p = QString::fromLocal8Bit( qgetenv(
"PATH" ) );
1245 QString delimiters(QLatin1Char(KPATH_SEPARATOR));
1246 delimiters += QLatin1Char(
'\b');
1252 for(
int i = 0; i < tokens.count(); i++ )
1266 bundle += QLatin1String(
".app/Contents/MacOS/") + bundle.section(QLatin1Char(
'/'), -1);
1267 info.setFile( bundle );
1269 if (file =
fopen(info.absoluteFilePath().toUtf8().constData(),
"r")) {
1272 if ((
stat(info.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
1275 if ( ignore || (_stat.st_mode & S_IXUSR) ) {
1276 if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
1290 if ( !bundle.isEmpty() ) {
1295 QFileInfo info( path );
1296 QFileInfo orig = info;
1297 #if defined(Q_OS_DARWIN) || defined(Q_OS_MAC)
1299 if (file =
fopen(orig.absoluteFilePath().toUtf8().constData(),
"r")) {
1302 if ((
stat(orig.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
1305 if ( ignoreExecBit || (_stat.st_mode & S_IXUSR) ) {
1306 if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
1307 orig.makeAbsolute();
1308 return orig.filePath();
1314 if( info.exists() && info.isSymLink() )
1315 info = QFileInfo( info.canonicalFilePath() );
1316 if( info.exists() && ( ignoreExecBit || info.isExecutable() ) && info.isFile() ) {
1320 orig.makeAbsolute();
1321 return orig.filePath();
1330 SearchOptions options )
1336 if (!executable_extensions.contains(appname.section(QLatin1Char(
'.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
1338 foreach (
const QString& extension, executable_extensions) {
1339 found_exe =
findExe(appname + extension, pstr, options);
1340 if (!found_exe.isEmpty()) {
1350 if (appname.contains(QDir::separator()))
1361 if (!result.isEmpty()) {
1368 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
1370 p = (*it) + QLatin1Char(
'/');
1375 if (!result.isEmpty()) {
1385 if (!result.isEmpty()) {
1398 const QString& pstr, SearchOptions options )
1402 if (!executable_extensions.contains(appname.section(QLatin1Char(
'.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
1404 foreach (
const QString& extension, executable_extensions) {
1405 total +=
findAllExe (list, appname + extension, pstr, options);
1415 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
1417 p = (*it) + QLatin1Char(
'/');
1422 if ( !bundle.isEmpty() ) {
1424 list.append( bundle );
1430 if( info.exists() && ( ( options &
IgnoreExecBit ) || info.isExecutable())
1431 && info.isFile() ) {
1436 return list.count();
1446 return f.absoluteFilePath();
1455 const int len = str.length();
1458 for(
int index = 0; index < len; index++) {
1459 if (delim.contains(str[index])) {
1463 token += str[index];
1466 if (!token.isEmpty()) {
1471 #ifndef KDE_NO_DEPRECATED
1474 return QString(QLatin1Char(
'%')) + QString::fromLatin1(type) + QLatin1Char(
'/');
1482 QMutexLocker lock(&d->m_cacheMutex);
1483 QString path = d->m_savelocations.value(type);
1487 if (dirs.isEmpty() && (
1488 (strcmp(type,
"socket") == 0) ||
1489 (strcmp(type,
"tmp") == 0) ||
1490 (strcmp(type,
"cache") == 0) ))
1493 dirs = d->m_relatives.value(type);
1495 if (!dirs.isEmpty())
1497 path = dirs.first();
1499 if (path.startsWith(QLatin1Char(
'%'))) {
1501 const int pos = path.indexOf(QLatin1Char(
'/'));
1502 QString rel = path.mid(1, pos - 1);
1503 QString rest = path.mid(pos + 1);
1505 path = basepath + rest;
1509 if (strncmp(type,
"xdgdata-", 8) == 0) {
1511 }
else if (strncmp(type,
"xdgconf-", 8) == 0) {
1518 dirs = d->m_absolutes.value(type);
1519 if (dirs.isEmpty()) {
1520 qFatal(
"KStandardDirs: The resource type %s is not registered", type);
1526 d->m_savelocations.insert(type, path.endsWith(QLatin1Char(
'/')) ? path : path + QLatin1Char(
'/'));
1528 QString fullPath = path + suffix;
1531 if (
KDE::stat(fullPath, &st) != 0 || !(S_ISDIR(st.st_mode))) {
1540 if(!
makeDir(fullPath, 0700)) {
1543 d->m_dircache.remove(type);
1545 if (!fullPath.endsWith(QLatin1Char(
'/')))
1546 fullPath += QLatin1Char(
'/');
1554 int i = absPath.lastIndexOf(QLatin1Char(
'/'));
1561 for (QStringList::ConstIterator it = candidates.begin();
1562 it != candidates.end(); ++it) {
1563 if (fullPath.startsWith(*it,
cs)) {
1564 return fullPath.mid((*it).length());
1574 if (QDir::isRelativePath(dir))
1578 return QDir().mkpath(dir);
1581 uint len = target.length();
1584 if (dir.at(len - 1) != QLatin1Char(
'/'))
1585 target += QLatin1Char(
'/');
1593 int pos = target.indexOf(QLatin1Char(
'/'), i);
1594 base += target.mid(i - 1, pos - i + 1);
1595 QByteArray baseEncoded = QFile::encodeName(base);
1597 if (KDE_stat(baseEncoded, &st) != 0)
1601 if (KDE_lstat(baseEncoded, &st) == 0)
1602 (void)unlink(baseEncoded);
1604 if (KDE_mkdir(baseEncoded, static_cast<mode_t>(mode)) != 0) {
1605 baseEncoded.prepend(
"trying to create local folder " );
1606 perror(baseEncoded.constData());
1620 c_path = qgetenv(env);
1621 if (c_path.isEmpty())
1629 c_path = retval.toLatin1();
1632 return QDir::fromNativeSeparators(QFile::decodeName(c_path));
1636 static QString executablePrefix()
1638 char path_buffer[MAXPATHLEN + 1];
1639 path_buffer[MAXPATHLEN] = 0;
1640 int length = readlink (
"/proc/self/exe", path_buffer, MAXPATHLEN);
1644 path_buffer[length] =
'\0';
1646 QString path = QFile::decodeName(path_buffer);
1651 int pos = path.lastIndexOf(QLatin1Char(
'/'));
1654 pos = path.lastIndexOf(QLatin1Char(
'/'), pos - 1);
1658 return path.left(pos);
1662 void KStandardDirs::addResourcesFrom_krcdirs()
1664 QString localFile = QDir::currentPath() + QLatin1String(
"/.krcdirs");
1665 if (!QFile::exists(localFile))
1668 QSettings iniFile(localFile, QSettings::IniFormat);
1669 iniFile.beginGroup(QString::fromLatin1(
"KStandardDirs"));
1671 foreach(
const QString &key, resources)
1673 QDir path(iniFile.value(key).toString());
1677 if(path.makeAbsolute())
1682 void KStandardDirs::addKDEDefaults()
1684 addResourcesFrom_krcdirs();
1690 if (!kdedirs.isEmpty())
1696 QString execPrefix(QFile::decodeName(EXEC_INSTALL_PREFIX));
1697 if (!execPrefix.isEmpty() && !kdedirList.contains(execPrefix,
cs))
1698 kdedirList.append(execPrefix);
1700 const QString linuxExecPrefix = executablePrefix();
1701 if ( !linuxExecPrefix.isEmpty() )
1702 kdedirList.append( linuxExecPrefix );
1708 if (!localKdeDir.isEmpty()) {
1709 if (!localKdeDir.endsWith(QLatin1Char(
'/')))
1710 localKdeDir += QLatin1Char(
'/');
1716 #if defined(Q_WS_MACX)
1717 localKdeDir = QDir::homePath() + QLatin1String(
"/Library/Preferences/KDE/");
1718 #elif defined(Q_WS_WIN)
1720 WCHAR wPath[MAX_PATH+1];
1721 if ( SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wPath) == S_OK) {
1722 localKdeDir = QDir::fromNativeSeparators(QString::fromUtf16((
const ushort *) wPath)) + QLatin1Char(
'/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char(
'/');
1725 localKdeDir = QDir::homePath() + QLatin1Char(
'/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char(
'/');
1730 localKdeDir = QDir::homePath() + QLatin1Char(
'/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char(
'/');
1734 if (localKdeDir != QLatin1String(
"-/"))
1744 if (bundleDir.dirName() == QLatin1String(
"MacOS")) {
1752 QStringList::ConstIterator end(kdedirList.end());
1753 for (QStringList::ConstIterator it = kdedirList.constBegin();
1754 it != kdedirList.constEnd(); ++it)
1764 if (!xdgdirs.isEmpty())
1771 xdgdirList.append(QString::fromLatin1(
"/etc/xdg"));
1773 xdgdirList.append(
installPath(
"kdedir") + QString::fromLatin1(
"etc/xdg"));
1775 xdgdirList.append(QFile::decodeName(KDESYSCONFDIR
"/xdg"));
1780 if (!localXdgDir.isEmpty()) {
1781 if (!localXdgDir.endsWith(QLatin1Char(
'/')))
1782 localXdgDir += QLatin1Char(
'/');
1785 localXdgDir = QDir::homePath() + QString::fromLatin1(
"/Library/Preferences/XDG/");
1787 localXdgDir = QDir::homePath() + QString::fromLatin1(
"/.config/");
1794 for (QStringList::ConstIterator it = xdgdirList.constBegin();
1795 it != xdgdirList.constEnd(); ++it)
1804 for (QStringList::ConstIterator it = kdedirList.constBegin();
1805 it != kdedirList.constEnd(); ++it) {
1807 if (!dir.endsWith(QLatin1Char(
'/')))
1808 dir += QLatin1Char(
'/');
1809 kdedirDataDirs.append(dir + QLatin1String(
"share/"));
1813 if (!xdgdirs.isEmpty()) {
1818 Q_FOREACH(
const QString& dir, kdedirDataDirs) {
1819 if (!xdgdirList.contains(dir,
cs))
1820 xdgdirList.append(dir);
1823 xdgdirList = kdedirDataDirs;
1825 xdgdirList.append(QString::fromLatin1(
"/usr/local/share/"));
1826 xdgdirList.append(QString::fromLatin1(
"/usr/share/"));
1831 if (!localXdgDir.isEmpty())
1833 if (localXdgDir[localXdgDir.length()-1] != QLatin1Char(
'/'))
1834 localXdgDir += QLatin1Char(
'/');
1838 localXdgDir = QDir::homePath() + QLatin1String(
"/.local/share/");
1844 for (QStringList::ConstIterator it = xdgdirList.constBegin();
1845 it != xdgdirList.constEnd(); ++it)
1874 if (mapFile.isEmpty() || !QFile::exists(mapFile))
1876 profiles << QString::fromLatin1(
"default");
1880 struct passwd *pw = getpwuid(geteuid());
1883 profiles << QString::fromLatin1(
"default");
1887 QByteArray user = pw->pw_name;
1889 gid_t sup_gids[512];
1890 int sup_gids_nr = getgroups(512, sup_gids);
1894 if (mapCfg.
hasKey(user.constData()))
1905 for( QStringList::ConstIterator it = groups.begin();
1906 it != groups.end(); ++it )
1908 QByteArray grp = (*it).toUtf8();
1910 struct group *grp_ent = getgrnam(grp);
1911 if (!grp_ent)
continue;
1912 gid_t gid = grp_ent->gr_gid;
1913 if (pw->pw_gid == gid)
1920 for(
int i = 0; i < sup_gids_nr; i++)
1922 if (sup_gids[i] == gid)
1932 if (profiles.isEmpty())
1933 profiles << QString::fromLatin1(
"default");
1941 if (!d->m_checkRestrictions)
1957 int i = kioskAdmin.indexOf(QLatin1Char(
':'));
1958 QString user = kioskAdmin.left(i);
1959 QString host = kioskAdmin.mid(i+1);
1962 char hostname[ 256 ];
1963 hostname[ 0 ] =
'\0';
1964 if (!gethostname( hostname, 255 ))
1965 hostname[
sizeof(hostname)-1] =
'\0';
1968 (host.isEmpty() || (host == QLatin1String(hostname))))
1970 kde_kiosk_admin =
true;
1974 bool readProfiles =
true;
1976 if (kde_kiosk_admin && !qgetenv(
"KDE_KIOSK_NO_PROFILES").isEmpty())
1977 readProfiles =
false;
1981 if (!profileDirsPrefix.isEmpty() && !profileDirsPrefix.endsWith(QLatin1Char(
'/')))
1982 profileDirsPrefix.append(QLatin1Char(
'/'));
1989 bool priority =
false;
1994 for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
2002 if (list.isEmpty() && !profile.isEmpty() && !profileDirsPrefix.isEmpty())
2004 QString dir = profileDirsPrefix + profile;
2014 it2 != entries.end(); ++it2)
2016 const QString key = it2.key();
2017 if (key.startsWith(QLatin1String(
"dir_"))) {
2020 QStringList::ConstIterator sIt(dirs.begin());
2022 for (; sIt != dirs.end(); ++sIt)
2028 if (profiles.isEmpty())
2030 profile = profiles.back();
2031 group = QString::fromLatin1(
"Directories-%1").arg(profile);
2032 profiles.pop_back();
2038 if (!kde_kiosk_admin || qgetenv(
"KDE_KIOSK_NO_RESTRICTIONS").isEmpty())
2043 it2 != entries.end(); ++it2)
2045 const QString key = it2.key();
2048 d->m_restrictionsActive =
true;
2049 const QByteArray cKey = key.toLatin1();
2050 d->m_restrictions.insert(cKey,
true);
2051 d->m_dircache.remove(cKey);
2052 d->m_savelocations.remove(cKey);
2058 bool configDirsChanged = (
resourceDirs(
"config").count() != configdirs);
2060 d->m_checkRestrictions = configDirsChanged;
2062 return configDirsChanged;
2068 return d->m_prefixes.first();
2074 return d->xdgdata_prefixes.first();
2080 return d->xdgconf_prefixes.first();
2098 const QString& filename,
bool createDir,
2103 int slash = filename.lastIndexOf(QLatin1Char(
'/')) + 1;
2109 QString dir = filename.left(slash);
2110 QString file = filename.mid(slash);
2117 if ( accessOK == 0 )
2123 if ( (mode & W_OK) == 0 )
2132 int pos = dirName.lastIndexOf(QLatin1Char(
'/'));
2135 else if ( pos == 0 )
2138 dirName.truncate(pos);
2142 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.