8#include <qregularexpression.h>
11# include <qt_windows.h>
13# include <sys/types.h>
21#define fL1S(s) QString::fromLatin1(s)
25using namespace Qt::Literals::StringLiterals;
33 }
else if (argv0.contains(u'/')
35 || argv0.contains(u'\\')
38 ret = QDir::current().absoluteFilePath(argv0);
40 QByteArray pEnv = qgetenv(
"PATH");
41 QDir currentDir = QDir::current();
42 QStringList paths = QString::fromLocal8Bit(pEnv).split(QDir::listSeparator());
44 paths.prepend(
"."_L1);
46 for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
49 QString candidate = currentDir.absoluteFilePath(*p + u'/' + argv0);
50 if (QFile::exists(candidate)) {
57 return QDir::cleanPath(ret);
64 DWORD attr = GetFileAttributesW((WCHAR*)fileName.utf16());
65 if (attr == INVALID_FILE_ATTRIBUTES)
67 return (attr & FILE_ATTRIBUTE_DIRECTORY) ? FileIsDir : FileIsRegular;
70 if (::stat(fileName.toLocal8Bit().constData(), &st))
78#ifdef QMAKE_BUILTIN_PRFS
79 if (path.startsWith(
":/"_L1))
85 if (path.length() >= 3 && path.at(1) == u':' && path.at(0).isLetter()
86 && (path.at(2) == u'/' || path.at(2) == u'\\')) {
90 if (path.length() >= 2
91 && (path.at(0).unicode() ==
'\\' || path.at(0).unicode() ==
'/')
92 && path.at(1) == path.at(0)) {
96 if (path.startsWith(u'/'))
102QStringView
IoUtils::pathName(
const QString &fileName)
104 return QStringView{ fileName }.left(fileName.lastIndexOf(u'/') + 1);
107QStringView
IoUtils::fileName(
const QString &fileName)
109 return QStringView(fileName).mid(fileName.lastIndexOf(u'/') + 1);
114 if (fileName.isEmpty())
116 if (isAbsolutePath(fileName))
117 return QDir::cleanPath(fileName);
119 if (fileName.at(0).unicode() ==
'/' || fileName.at(0).unicode() ==
'\\') {
120 Q_ASSERT_X(isAbsolutePath(baseDir),
"IoUtils::resolvePath", qUtf8Printable(baseDir));
121 return QDir::cleanPath(baseDir.left(2) + fileName);
124 return QDir::cleanPath(baseDir + u'/' + fileName);
130 if ((c <
sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))))
138 for (
int x = arg.size() - 1; x >= 0; --x) {
139 if (isSpecialChar(arg.unicode()[x].unicode(), iqm))
148 static const uchar iqm[] = {
149 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8,
150 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78
154 return QString::fromLatin1(
"''");
157 if (hasSpecialChars(ret, iqm)) {
158 ret.replace(QLatin1Char(
'\''),
"'\\''"_L1);
159 ret.prepend(QLatin1Char(
'\''));
160 ret.append(QLatin1Char(
'\''));
171 static const uchar iqm[] = {
172 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78,
173 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10
176 static const uchar ism[] = {
177 0x00, 0x00, 0x00, 0x00, 0x40, 0x03, 0x00, 0x50,
178 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10
182 return QString::fromLatin1(
"\"\"");
185 if (hasSpecialChars(ret, iqm)) {
189 ret.replace(QRegularExpression(QLatin1String(
"(\\\\*)\"")), QLatin1String(
"\\1\\1\\\""));
191 ret.replace(QRegularExpression(
"(\\\\+)$"_L1),
"\\1\\1"_L1);
197 for (
int i = 0; i < ret.size(); i++) {
198 QChar c = ret.unicode()[i];
199 if (c.unicode() ==
'"')
201 else if (!quoted && isSpecialChar(c.unicode(), ism))
202 ret.insert(i++, u'^');
212#if defined(PROEVALUATOR_FULL)
214# if defined(Q_OS_WIN)
215static QString windowsErrorCode()
217 wchar_t *string =
nullptr;
218 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
221 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
225 QString ret = QString::fromWCharArray(string);
226 LocalFree((HLOCAL)string);
227 return ret.trimmed();
231bool IoUtils::touchFile(
const QString &targetFileName,
const QString &referenceFileName, QString *errorString)
235 if (stat(referenceFileName.toLocal8Bit().constData(), &st)) {
236 *errorString = fL1S(
"Cannot stat() reference file %1: %2.").arg(referenceFileName, fL1S(strerror(errno)));
239# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L
240 const struct timespec times[2] = { { 0, UTIME_NOW }, st.st_mtim };
241 const bool utimeError = utimensat(AT_FDCWD, targetFileName.toLocal8Bit().constData(), times, 0) < 0;
244 utb.actime = time(0);
245 utb.modtime = st.st_mtime;
246 const bool utimeError= utime(targetFileName.toLocal8Bit().constData(), &utb) < 0;
249 *errorString = fL1S(
"Cannot touch %1: %2.").arg(targetFileName, fL1S(strerror(errno)));
253 HANDLE rHand = CreateFile((
wchar_t*)referenceFileName.utf16(),
254 GENERIC_READ, FILE_SHARE_READ,
255 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
256 if (rHand == INVALID_HANDLE_VALUE) {
257 *errorString = fL1S(
"Cannot open reference file %1: %2").arg(referenceFileName, windowsErrorCode());
261 GetFileTime(rHand, NULL, NULL, &ft);
263 HANDLE wHand = CreateFile((
wchar_t*)targetFileName.utf16(),
264 GENERIC_WRITE, FILE_SHARE_READ,
265 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
266 if (wHand == INVALID_HANDLE_VALUE) {
267 *errorString = fL1S(
"Cannot open %1: %2").arg(targetFileName, windowsErrorCode());
270 SetFileTime(wHand, NULL, NULL, &ft);
276#if defined(QT_BUILD_QMAKE) && defined(Q_OS_UNIX)
277bool IoUtils::readLinkTarget(
const QString &symlinkPath, QString *target)
279 const QByteArray localSymlinkPath = QFile::encodeName(symlinkPath);
280# if defined(__GLIBC__) && !defined(PATH_MAX)
281# define PATH_CHUNK_SIZE 256
284 int size = PATH_CHUNK_SIZE;
287 s = (
char *)::realloc(s, size);
288 len = ::readlink(localSymlinkPath.constData(), s, size);
299 int len = readlink(localSymlinkPath.constData(), s, PATH_MAX);
303 *target = QFile::decodeName(QByteArray(s, len));
304# if defined(__GLIBC__) && !defined(PATH_MAX)
This class provides replacement functionality for QFileInfo, QFile & QDir, as these are abysmally slo...
static FileType fileType(const QString &fileName)
static bool isRelativePath(const QString &fileName)
static QString binaryAbsLocation(const QString &argv0)
static bool isAbsolutePath(const QString &fileName)
static QString resolvePath(const QString &baseDir, const QString &fileName)
static QString shellQuoteWin(const QString &arg)
static QString shellQuoteUnix(const QString &arg)
static bool isSpecialChar(ushort c, const uchar(&iqm)[16])
static bool hasSpecialChars(const QString &arg, const uchar(&iqm)[16])