/qmake/library/ioutils.cpp
C++ | 168 lines | 98 code | 17 blank | 53 comment | 26 complexity | 6ba05077f154175c4f9b46574eb400ab MD5 | raw file
- /****************************************************************************
- **
- ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
- ** Contact: http://www.qt-project.org/legal
- **
- ** This file is part of the qmake application of the Qt Toolkit.
- **
- ** $QT_BEGIN_LICENSE:LGPL$
- ** Commercial License Usage
- ** Licensees holding valid commercial Qt licenses may use this file in
- ** accordance with the commercial license agreement provided with the
- ** Software or, alternatively, in accordance with the terms contained in
- ** a written agreement between you and Digia. For licensing terms and
- ** conditions see http://qt.digia.com/licensing. For further information
- ** use the contact form at http://qt.digia.com/contact-us.
- **
- ** GNU Lesser General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file. Please review the following information to
- ** ensure the GNU Lesser General Public License version 2.1 requirements
- ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
- **
- ** In addition, as a special exception, Digia gives you certain additional
- ** rights. These rights are described in the Digia Qt LGPL Exception
- ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
- **
- ** GNU General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU
- ** General Public License version 3.0 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.GPL included in the
- ** packaging of this file. Please review the following information to
- ** ensure the GNU General Public License version 3.0 requirements will be
- ** met: http://www.gnu.org/copyleft/gpl.html.
- **
- **
- ** $QT_END_LICENSE$
- **
- ****************************************************************************/
- #include "ioutils.h"
- #include <qdir.h>
- #include <qfile.h>
- #ifdef Q_OS_WIN
- # include <windows.h>
- #else
- # include <sys/types.h>
- # include <sys/stat.h>
- # include <unistd.h>
- #endif
- QT_BEGIN_NAMESPACE
- using namespace QMakeInternal;
- IoUtils::FileType IoUtils::fileType(const QString &fileName)
- {
- Q_ASSERT(fileName.isEmpty() || isAbsolutePath(fileName));
- #ifdef Q_OS_WIN
- DWORD attr = GetFileAttributesW((WCHAR*)fileName.utf16());
- if (attr == INVALID_FILE_ATTRIBUTES)
- return FileNotFound;
- return (attr & FILE_ATTRIBUTE_DIRECTORY) ? FileIsDir : FileIsRegular;
- #else
- struct ::stat st;
- if (::stat(fileName.toLocal8Bit().constData(), &st))
- return FileNotFound;
- return S_ISDIR(st.st_mode) ? FileIsDir : FileIsRegular;
- #endif
- }
- bool IoUtils::isRelativePath(const QString &path)
- {
- if (path.startsWith(QLatin1Char('/')))
- return false;
- #ifdef Q_OS_WIN
- if (path.startsWith(QLatin1Char('\\')))
- return false;
- // Unlike QFileInfo, this won't accept a relative path with a drive letter.
- // Such paths result in a royal mess anyway ...
- if (path.length() >= 3 && path.at(1) == QLatin1Char(':') && path.at(0).isLetter()
- && (path.at(2) == QLatin1Char('/') || path.at(2) == QLatin1Char('\\')))
- return false;
- #endif
- return true;
- }
- QStringRef IoUtils::fileName(const QString &fileName)
- {
- return fileName.midRef(fileName.lastIndexOf(QLatin1Char('/')) + 1);
- }
- QString IoUtils::resolvePath(const QString &baseDir, const QString &fileName)
- {
- if (fileName.isEmpty())
- return QString();
- if (isAbsolutePath(fileName))
- return QDir::cleanPath(fileName);
- return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName);
- }
- inline static
- bool hasSpecialChars(const QString &arg, const uchar (&iqm)[16])
- {
- for (int x = arg.length() - 1; x >= 0; --x) {
- ushort c = arg.unicode()[x].unicode();
- if ((c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))))
- return true;
- }
- return false;
- }
- QString IoUtils::shellQuoteUnix(const QString &arg)
- {
- // Chars that should be quoted (TM). This includes:
- static const uchar iqm[] = {
- 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8,
- 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78
- }; // 0-32 \'"$`<>|;&(){}*?#!~[]
- if (!arg.length())
- return QString::fromLatin1("\"\"");
- QString ret(arg);
- if (hasSpecialChars(ret, iqm)) {
- ret.replace(QLatin1Char('\''), QLatin1String("'\\''"));
- ret.prepend(QLatin1Char('\''));
- ret.append(QLatin1Char('\''));
- }
- return ret;
- }
- QString IoUtils::shellQuoteWin(const QString &arg)
- {
- // Chars that should be quoted (TM). This includes:
- // - control chars & space
- // - the shell meta chars "&()<>^|
- // - the potential separators ,;=
- static const uchar iqm[] = {
- 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10
- };
- if (!arg.length())
- return QString::fromLatin1("\"\"");
- QString ret(arg);
- if (hasSpecialChars(ret, iqm)) {
- // Quotes are escaped and their preceding backslashes are doubled.
- // It's impossible to escape anything inside a quoted string on cmd
- // level, so the outer quoting must be "suspended".
- ret.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\"\\1\\1\\^\"\""));
- // The argument must not end with a \ since this would be interpreted
- // as escaping the quote -- rather put the \ behind the quote: e.g.
- // rather use "foo"\ than "foo\"
- int i = ret.length();
- while (i > 0 && ret.at(i - 1) == QLatin1Char('\\'))
- --i;
- ret.insert(i, QLatin1Char('"'));
- ret.prepend(QLatin1Char('"'));
- }
- return ret;
- }
- QT_END_NAMESPACE