Backporting QlockFile. Successful build on Windows.
--HG-- branch : develop
This commit is contained in:
parent
94e2fe8c5a
commit
93eb3d692c
|
@ -430,6 +430,9 @@ DEPENDPATH += $$PWD/../libs/vlayout
|
||||||
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../libs/vlayout/$${DESTDIR}/vlayout.lib
|
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../libs/vlayout/$${DESTDIR}/vlayout.lib
|
||||||
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../libs/vlayout/$${DESTDIR}/libvlayout.a
|
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../libs/vlayout/$${DESTDIR}/libvlayout.a
|
||||||
|
|
||||||
|
# For build qt backport code
|
||||||
|
win32: LIBS+= libole32 libuuid
|
||||||
|
|
||||||
|
|
||||||
# Strip after you link all libaries.
|
# Strip after you link all libaries.
|
||||||
CONFIG(release, debug|release){
|
CONFIG(release, debug|release){
|
||||||
|
|
1251
src/app/core/backport/qabstractfileengine.cpp
Normal file
1251
src/app/core/backport/qabstractfileengine.cpp
Normal file
File diff suppressed because it is too large
Load Diff
251
src/app/core/backport/qabstractfileengine_p.h
Normal file
251
src/app/core/backport/qabstractfileengine_p.h
Normal file
|
@ -0,0 +1,251 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QABSTRACTFILEENGINE_P_H
|
||||||
|
#define QABSTRACTFILEENGINE_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists purely as an
|
||||||
|
// implementation detail. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#ifdef open
|
||||||
|
#error qabstractfileengine_p.h must be included before any header file that defines open
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class QVariant;
|
||||||
|
class QAbstractFileEngineIterator;
|
||||||
|
class QAbstractFileEnginePrivate;
|
||||||
|
|
||||||
|
class QAbstractFileEngine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum FileFlag {
|
||||||
|
//perms (overlaps the QFile::Permission)
|
||||||
|
ReadOwnerPerm = 0x4000, WriteOwnerPerm = 0x2000, ExeOwnerPerm = 0x1000,
|
||||||
|
ReadUserPerm = 0x0400, WriteUserPerm = 0x0200, ExeUserPerm = 0x0100,
|
||||||
|
ReadGroupPerm = 0x0040, WriteGroupPerm = 0x0020, ExeGroupPerm = 0x0010,
|
||||||
|
ReadOtherPerm = 0x0004, WriteOtherPerm = 0x0002, ExeOtherPerm = 0x0001,
|
||||||
|
|
||||||
|
//types
|
||||||
|
LinkType = 0x10000,
|
||||||
|
FileType = 0x20000,
|
||||||
|
DirectoryType = 0x40000,
|
||||||
|
BundleType = 0x80000,
|
||||||
|
|
||||||
|
//flags
|
||||||
|
HiddenFlag = 0x0100000,
|
||||||
|
LocalDiskFlag = 0x0200000,
|
||||||
|
ExistsFlag = 0x0400000,
|
||||||
|
RootFlag = 0x0800000,
|
||||||
|
Refresh = 0x1000000,
|
||||||
|
|
||||||
|
//masks
|
||||||
|
PermsMask = 0x0000FFFF,
|
||||||
|
TypesMask = 0x000F0000,
|
||||||
|
FlagsMask = 0x0FF00000,
|
||||||
|
FileInfoAll = FlagsMask | PermsMask | TypesMask
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(FileFlags, FileFlag)
|
||||||
|
|
||||||
|
enum FileName {
|
||||||
|
DefaultName,
|
||||||
|
BaseName,
|
||||||
|
PathName,
|
||||||
|
AbsoluteName,
|
||||||
|
AbsolutePathName,
|
||||||
|
LinkName,
|
||||||
|
CanonicalName,
|
||||||
|
CanonicalPathName,
|
||||||
|
BundleName,
|
||||||
|
NFileNames = 9
|
||||||
|
};
|
||||||
|
enum FileOwner {
|
||||||
|
OwnerUser,
|
||||||
|
OwnerGroup
|
||||||
|
};
|
||||||
|
enum FileTime {
|
||||||
|
CreationTime,
|
||||||
|
ModificationTime,
|
||||||
|
AccessTime
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~QAbstractFileEngine();
|
||||||
|
|
||||||
|
virtual bool open(QIODevice::OpenMode openMode);
|
||||||
|
virtual bool close();
|
||||||
|
virtual bool flush();
|
||||||
|
virtual bool syncToDisk();
|
||||||
|
virtual qint64 size() const;
|
||||||
|
virtual qint64 pos() const;
|
||||||
|
virtual bool seek(qint64 pos);
|
||||||
|
virtual bool isSequential() const;
|
||||||
|
virtual bool remove();
|
||||||
|
virtual bool copy(const QString &newName);
|
||||||
|
virtual bool rename(const QString &newName);
|
||||||
|
virtual bool renameOverwrite(const QString &newName);
|
||||||
|
virtual bool link(const QString &newName);
|
||||||
|
virtual bool mkdir(const QString &dirName, bool createParentDirectories) const;
|
||||||
|
virtual bool rmdir(const QString &dirName, bool recurseParentDirectories) const;
|
||||||
|
virtual bool setSize(qint64 size);
|
||||||
|
virtual bool caseSensitive() const;
|
||||||
|
virtual bool isRelativePath() const;
|
||||||
|
virtual QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const;
|
||||||
|
virtual FileFlags fileFlags(FileFlags type=FileInfoAll) const;
|
||||||
|
virtual bool setPermissions(uint perms);
|
||||||
|
virtual QString fileName(FileName file=DefaultName) const;
|
||||||
|
virtual uint ownerId(FileOwner) const;
|
||||||
|
virtual QString owner(FileOwner) const;
|
||||||
|
virtual QDateTime fileTime(FileTime time) const;
|
||||||
|
virtual void setFileName(const QString &file);
|
||||||
|
virtual int handle() const;
|
||||||
|
bool atEnd() const;
|
||||||
|
uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags);
|
||||||
|
bool unmap(uchar *ptr);
|
||||||
|
|
||||||
|
typedef QAbstractFileEngineIterator Iterator;
|
||||||
|
virtual Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames);
|
||||||
|
virtual Iterator *endEntryList();
|
||||||
|
|
||||||
|
virtual qint64 read(char *data, qint64 maxlen);
|
||||||
|
virtual qint64 readLine(char *data, qint64 maxlen);
|
||||||
|
virtual qint64 write(const char *data, qint64 len);
|
||||||
|
|
||||||
|
QFile::FileError error() const;
|
||||||
|
QString errorString() const;
|
||||||
|
|
||||||
|
enum Extension {
|
||||||
|
AtEndExtension,
|
||||||
|
FastReadLineExtension,
|
||||||
|
MapExtension,
|
||||||
|
UnMapExtension
|
||||||
|
};
|
||||||
|
class ExtensionOption
|
||||||
|
{};
|
||||||
|
class ExtensionReturn
|
||||||
|
{};
|
||||||
|
|
||||||
|
class MapExtensionOption : public ExtensionOption {
|
||||||
|
public:
|
||||||
|
qint64 offset;
|
||||||
|
qint64 size;
|
||||||
|
QFile::MemoryMapFlags flags;
|
||||||
|
};
|
||||||
|
class MapExtensionReturn : public ExtensionReturn {
|
||||||
|
public:
|
||||||
|
uchar *address;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UnMapExtensionOption : public ExtensionOption {
|
||||||
|
public:
|
||||||
|
uchar *address;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0);
|
||||||
|
virtual bool supportsExtension(Extension extension) const;
|
||||||
|
|
||||||
|
// Factory
|
||||||
|
static QAbstractFileEngine *create(const QString &fileName);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setError(QFile::FileError error, const QString &str);
|
||||||
|
|
||||||
|
QAbstractFileEngine();
|
||||||
|
QAbstractFileEngine(QAbstractFileEnginePrivate &);
|
||||||
|
|
||||||
|
QScopedPointer<QAbstractFileEnginePrivate> d_ptr;
|
||||||
|
private:
|
||||||
|
Q_DECLARE_PRIVATE(QAbstractFileEngine)
|
||||||
|
Q_DISABLE_COPY(QAbstractFileEngine)
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractFileEngine::FileFlags)
|
||||||
|
|
||||||
|
class QAbstractFileEngineHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QAbstractFileEngineHandler();
|
||||||
|
virtual ~QAbstractFileEngineHandler();
|
||||||
|
virtual QAbstractFileEngine *create(const QString &fileName) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QAbstractFileEngineIteratorPrivate;
|
||||||
|
class QAbstractFileEngineIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QAbstractFileEngineIterator(QDir::Filters filters, const QStringList &nameFilters);
|
||||||
|
virtual ~QAbstractFileEngineIterator();
|
||||||
|
|
||||||
|
virtual QString next() = 0;
|
||||||
|
virtual bool hasNext() const = 0;
|
||||||
|
|
||||||
|
QString path() const;
|
||||||
|
QStringList nameFilters() const;
|
||||||
|
QDir::Filters filters() const;
|
||||||
|
|
||||||
|
virtual QString currentFileName() const = 0;
|
||||||
|
virtual QFileInfo currentFileInfo() const;
|
||||||
|
QString currentFilePath() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum EntryInfoType {
|
||||||
|
};
|
||||||
|
virtual QVariant entryInfo(EntryInfoType type) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Q_DISABLE_COPY(QAbstractFileEngineIterator)
|
||||||
|
friend class QDirIterator;
|
||||||
|
friend class QDirIteratorPrivate;
|
||||||
|
void setPath(const QString &path);
|
||||||
|
QScopedPointer<QAbstractFileEngineIteratorPrivate> d;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QAbstractFileEnginePrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline QAbstractFileEnginePrivate()
|
||||||
|
: fileError(QFile::UnspecifiedError)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
inline virtual ~QAbstractFileEnginePrivate() { }
|
||||||
|
|
||||||
|
QFile::FileError fileError;
|
||||||
|
QString errorString;
|
||||||
|
|
||||||
|
QAbstractFileEngine *q_ptr;
|
||||||
|
Q_DECLARE_PUBLIC(QAbstractFileEngine)
|
||||||
|
};
|
||||||
|
|
||||||
|
QAbstractFileEngine *qt_custom_file_engine_handler_create(const QString &path);
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif // QABSTRACTFILEENGINE_P_H
|
61
src/app/core/backport/qcore_mac.cpp
Normal file
61
src/app/core/backport/qcore_mac.cpp
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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 "qcore_mac_p.h"
|
||||||
|
#include <new>
|
||||||
|
#include <QVarLengthArray>
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
QString QCFString::toQString(CFStringRef str)
|
||||||
|
{
|
||||||
|
if(!str)
|
||||||
|
return QString();
|
||||||
|
CFIndex length = CFStringGetLength(str);
|
||||||
|
const UniChar *chars = CFStringGetCharactersPtr(str);
|
||||||
|
if (chars)
|
||||||
|
return QString(reinterpret_cast<const QChar *>(chars), length);
|
||||||
|
|
||||||
|
QVarLengthArray<UniChar> buffer(length);
|
||||||
|
CFStringGetCharacters(str, CFRangeMake(0, length), buffer.data());
|
||||||
|
return QString(reinterpret_cast<const QChar *>(buffer.constData()), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
QCFString::operator QString() const
|
||||||
|
{
|
||||||
|
if (string.isEmpty() && type)
|
||||||
|
const_cast<QCFString*>(this)->string = toQString(type);
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFStringRef QCFString::toCFStringRef(const QString &string)
|
||||||
|
{
|
||||||
|
return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(string.unicode()),
|
||||||
|
string.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
QCFString::operator CFStringRef() const
|
||||||
|
{
|
||||||
|
if (!type)
|
||||||
|
const_cast<QCFString*>(this)->type = toCFStringRef(string);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
131
src/app/core/backport/qcore_mac_p.h
Normal file
131
src/app/core/backport/qcore_mac_p.h
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QCORE_MAC_P_H
|
||||||
|
#define QCORE_MAC_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists for the convenience
|
||||||
|
// of other Qt classes. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __IMAGECAPTURE__
|
||||||
|
# define __IMAGECAPTURE__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(QT_BOOTSTRAPPED)
|
||||||
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
|
#else
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
#ifdef Q_OS_MACX
|
||||||
|
#include <CoreServices/CoreServices.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __OBJC__
|
||||||
|
#include <Foundation/Foundation.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#if defined( __OBJC__) && defined(QT_NAMESPACE)
|
||||||
|
#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__) @compatibility_alias __KLASS__ QT_MANGLE_NAMESPACE(__KLASS__)
|
||||||
|
#else
|
||||||
|
#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
Helper class that automates refernce counting for CFtypes.
|
||||||
|
After constructing the QCFType object, it can be copied like a
|
||||||
|
value-based type.
|
||||||
|
|
||||||
|
Note that you must own the object you are wrapping.
|
||||||
|
This is typically the case if you get the object from a Core
|
||||||
|
Foundation function with the word "Create" or "Copy" in it. If
|
||||||
|
you got the object from a "Get" function, either retain it or use
|
||||||
|
constructFromGet(). One exception to this rule is the
|
||||||
|
HIThemeGet*Shape functions, which in reality are "Copy" functions.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class QCFType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline QCFType(const T &t = 0) : type(t) {}
|
||||||
|
inline QCFType(const QCFType &helper) : type(helper.type) { if (type) CFRetain(type); }
|
||||||
|
inline ~QCFType() { if (type) CFRelease(type); }
|
||||||
|
inline operator T() { return type; }
|
||||||
|
inline QCFType operator =(const QCFType &helper)
|
||||||
|
{
|
||||||
|
if (helper.type)
|
||||||
|
CFRetain(helper.type);
|
||||||
|
CFTypeRef type2 = type;
|
||||||
|
type = helper.type;
|
||||||
|
if (type2)
|
||||||
|
CFRelease(type2);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
inline T *operator&() { return &type; }
|
||||||
|
template <typename X> X as() const { return reinterpret_cast<X>(type); }
|
||||||
|
static QCFType constructFromGet(const T &t)
|
||||||
|
{
|
||||||
|
CFRetain(t);
|
||||||
|
return QCFType<T>(t);
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Q_CORE_EXPORT QCFString : public QCFType<CFStringRef>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline QCFString(const QString &str) : QCFType<CFStringRef>(0), string(str) {}
|
||||||
|
inline QCFString(const CFStringRef cfstr = 0) : QCFType<CFStringRef>(cfstr) {}
|
||||||
|
inline QCFString(const QCFType<CFStringRef> &other) : QCFType<CFStringRef>(other) {}
|
||||||
|
operator QString() const;
|
||||||
|
operator CFStringRef() const;
|
||||||
|
static QString toQString(CFStringRef cfstr);
|
||||||
|
static CFStringRef toCFStringRef(const QString &str);
|
||||||
|
#ifdef __OBJC__
|
||||||
|
static QString toQString(const NSString *nsstr);
|
||||||
|
static NSString *toNSString(const QString &string);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString string;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef Q_OS_IOS
|
||||||
|
QSysInfo::MacVersion qt_ios_version();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif // QCORE_MAC_P_H
|
109
src/app/core/backport/qcore_unix.cpp
Normal file
109
src/app/core/backport/qcore_unix.cpp
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the QtCore module 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 "qcore_unix_p.h"
|
||||||
|
#include "qelapsedtimer.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_NACL
|
||||||
|
#elif !defined (Q_OS_VXWORKS)
|
||||||
|
# if !defined(Q_OS_HPUX) || defined(__ia64)
|
||||||
|
# include <sys/select.h>
|
||||||
|
# endif
|
||||||
|
# include <sys/time.h>
|
||||||
|
#else
|
||||||
|
# include <selectLib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
#include <mach/mach_time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
static inline bool time_update(struct timespec *tv, const struct timespec &start,
|
||||||
|
const struct timespec &timeout)
|
||||||
|
{
|
||||||
|
// clock source is (hopefully) monotonic, so we can recalculate how much timeout is left;
|
||||||
|
// if it isn't monotonic, we'll simply hope that it hasn't jumped, because we have no alternative
|
||||||
|
struct timespec now = qt_gettime();
|
||||||
|
*tv = timeout + start - now;
|
||||||
|
return tv->tv_sec >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
|
||||||
|
const struct timespec *orig_timeout)
|
||||||
|
{
|
||||||
|
if (!orig_timeout) {
|
||||||
|
// no timeout -> block forever
|
||||||
|
int ret;
|
||||||
|
EINTR_LOOP(ret, select(nfds, fdread, fdwrite, fdexcept, 0));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
timespec start = qt_gettime();
|
||||||
|
timespec timeout = *orig_timeout;
|
||||||
|
|
||||||
|
// loop and recalculate the timeout as needed
|
||||||
|
int ret;
|
||||||
|
forever {
|
||||||
|
#ifndef Q_OS_QNX
|
||||||
|
ret = ::pselect(nfds, fdread, fdwrite, fdexcept, &timeout, 0);
|
||||||
|
#else
|
||||||
|
timeval timeoutVal;
|
||||||
|
timeoutVal.tv_sec = timeout.tv_sec;
|
||||||
|
timeoutVal.tv_usec = timeout.tv_nsec / 1000;
|
||||||
|
ret = ::select(nfds, fdread, fdwrite, fdexcept, &timeoutVal);
|
||||||
|
#endif
|
||||||
|
if (ret != -1 || errno != EINTR)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
// recalculate the timeout
|
||||||
|
if (!time_update(&timeout, start, *orig_timeout)) {
|
||||||
|
// timeout during update
|
||||||
|
// or clock reset, fake timeout error
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
335
src/app/core/backport/qcore_unix_p.h
Normal file
335
src/app/core/backport/qcore_unix_p.h
Normal file
|
@ -0,0 +1,335 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QCORE_UNIX_P_H
|
||||||
|
#define QCORE_UNIX_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists for the convenience
|
||||||
|
// of Qt code on Unix. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "qplatformdefs.h"
|
||||||
|
#include "qatomic.h"
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#ifndef Q_OS_UNIX
|
||||||
|
# error "qcore_unix_p.h included on a non-Unix system"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#if defined(Q_OS_VXWORKS)
|
||||||
|
# include <ioLib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct sockaddr;
|
||||||
|
|
||||||
|
#if defined(Q_OS_LINUX) && defined(O_CLOEXEC)
|
||||||
|
# define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 1
|
||||||
|
|
||||||
|
namespace QtLibcSupplement {
|
||||||
|
inline int accept4(int, sockaddr *, QT_SOCKLEN_T *, int)
|
||||||
|
{ errno = ENOSYS; return -1; }
|
||||||
|
inline int dup3(int, int, int)
|
||||||
|
{ errno = ENOSYS; return -1; }
|
||||||
|
inline int pipe2(int [], int )
|
||||||
|
{ errno = ENOSYS; return -1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace QT_PREPEND_NAMESPACE(QtLibcSupplement);
|
||||||
|
|
||||||
|
#else
|
||||||
|
# define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define EINTR_LOOP(var, cmd) \
|
||||||
|
do { \
|
||||||
|
var = cmd; \
|
||||||
|
} while (var == -1 && errno == EINTR)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Internal operator functions for timespecs
|
||||||
|
inline timespec &normalizedTimespec(timespec &t)
|
||||||
|
{
|
||||||
|
while (t.tv_nsec >= 1000000000) {
|
||||||
|
++t.tv_sec;
|
||||||
|
t.tv_nsec -= 1000000000;
|
||||||
|
}
|
||||||
|
while (t.tv_nsec < 0) {
|
||||||
|
--t.tv_sec;
|
||||||
|
t.tv_nsec += 1000000000;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
inline bool operator<(const timespec &t1, const timespec &t2)
|
||||||
|
{ return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec); }
|
||||||
|
inline bool operator==(const timespec &t1, const timespec &t2)
|
||||||
|
{ return t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec; }
|
||||||
|
inline timespec &operator+=(timespec &t1, const timespec &t2)
|
||||||
|
{
|
||||||
|
t1.tv_sec += t2.tv_sec;
|
||||||
|
t1.tv_nsec += t2.tv_nsec;
|
||||||
|
return normalizedTimespec(t1);
|
||||||
|
}
|
||||||
|
inline timespec operator+(const timespec &t1, const timespec &t2)
|
||||||
|
{
|
||||||
|
timespec tmp;
|
||||||
|
tmp.tv_sec = t1.tv_sec + t2.tv_sec;
|
||||||
|
tmp.tv_nsec = t1.tv_nsec + t2.tv_nsec;
|
||||||
|
return normalizedTimespec(tmp);
|
||||||
|
}
|
||||||
|
inline timespec operator-(const timespec &t1, const timespec &t2)
|
||||||
|
{
|
||||||
|
timespec tmp;
|
||||||
|
tmp.tv_sec = t1.tv_sec - (t2.tv_sec - 1);
|
||||||
|
tmp.tv_nsec = t1.tv_nsec - (t2.tv_nsec + 1000000000);
|
||||||
|
return normalizedTimespec(tmp);
|
||||||
|
}
|
||||||
|
inline timespec operator*(const timespec &t1, int mul)
|
||||||
|
{
|
||||||
|
timespec tmp;
|
||||||
|
tmp.tv_sec = t1.tv_sec * mul;
|
||||||
|
tmp.tv_nsec = t1.tv_nsec * mul;
|
||||||
|
return normalizedTimespec(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void qt_ignore_sigpipe()
|
||||||
|
{
|
||||||
|
// Set to ignore SIGPIPE once only.
|
||||||
|
static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0);
|
||||||
|
if (!atom.load()) {
|
||||||
|
// More than one thread could turn off SIGPIPE at the same time
|
||||||
|
// But that's acceptable because they all would be doing the same
|
||||||
|
// action
|
||||||
|
struct sigaction noaction;
|
||||||
|
memset(&noaction, 0, sizeof(noaction));
|
||||||
|
noaction.sa_handler = SIG_IGN;
|
||||||
|
::sigaction(SIGPIPE, &noaction, 0);
|
||||||
|
atom.store(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't call QT_OPEN or ::open
|
||||||
|
// call qt_safe_open
|
||||||
|
static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777)
|
||||||
|
{
|
||||||
|
#ifdef O_CLOEXEC
|
||||||
|
flags |= O_CLOEXEC;
|
||||||
|
#endif
|
||||||
|
int fd;
|
||||||
|
EINTR_LOOP(fd, QT_OPEN(pathname, flags, mode));
|
||||||
|
|
||||||
|
// unknown flags are ignored, so we have no way of verifying if
|
||||||
|
// O_CLOEXEC was accepted
|
||||||
|
if (fd != -1)
|
||||||
|
::fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
#undef QT_OPEN
|
||||||
|
#define QT_OPEN qt_safe_open
|
||||||
|
|
||||||
|
#ifndef Q_OS_VXWORKS // no POSIX pipes in VxWorks
|
||||||
|
// don't call ::pipe
|
||||||
|
// call qt_safe_pipe
|
||||||
|
static inline int qt_safe_pipe(int pipefd[2], int flags = 0)
|
||||||
|
{
|
||||||
|
#ifdef O_CLOEXEC
|
||||||
|
Q_ASSERT((flags & ~(O_CLOEXEC | O_NONBLOCK)) == 0);
|
||||||
|
#else
|
||||||
|
Q_ASSERT((flags & ~O_NONBLOCK) == 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(O_CLOEXEC)
|
||||||
|
// use pipe2
|
||||||
|
flags |= O_CLOEXEC;
|
||||||
|
ret = ::pipe2(pipefd, flags); // pipe2 is Linux-specific and is documented not to return EINTR
|
||||||
|
if (ret == 0 || errno != ENOSYS)
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = ::pipe(pipefd);
|
||||||
|
if (ret == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
::fcntl(pipefd[0], F_SETFD, FD_CLOEXEC);
|
||||||
|
::fcntl(pipefd[1], F_SETFD, FD_CLOEXEC);
|
||||||
|
|
||||||
|
// set non-block too?
|
||||||
|
if (flags & O_NONBLOCK) {
|
||||||
|
::fcntl(pipefd[0], F_SETFL, ::fcntl(pipefd[0], F_GETFL) | O_NONBLOCK);
|
||||||
|
::fcntl(pipefd[1], F_SETFL, ::fcntl(pipefd[1], F_GETFL) | O_NONBLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // Q_OS_VXWORKS
|
||||||
|
|
||||||
|
// don't call dup or fcntl(F_DUPFD)
|
||||||
|
static inline int qt_safe_dup(int oldfd, int atleast = 0, int flags = FD_CLOEXEC)
|
||||||
|
{
|
||||||
|
Q_ASSERT(flags == FD_CLOEXEC || flags == 0);
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
#ifdef F_DUPFD_CLOEXEC
|
||||||
|
// use this fcntl
|
||||||
|
if (flags & FD_CLOEXEC) {
|
||||||
|
ret = ::fcntl(oldfd, F_DUPFD_CLOEXEC, atleast);
|
||||||
|
if (ret != -1 || errno != EINVAL)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// use F_DUPFD
|
||||||
|
ret = ::fcntl(oldfd, F_DUPFD, atleast);
|
||||||
|
|
||||||
|
if (flags && ret != -1)
|
||||||
|
::fcntl(ret, F_SETFD, flags);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't call dup2
|
||||||
|
// call qt_safe_dup2
|
||||||
|
static inline int qt_safe_dup2(int oldfd, int newfd, int flags = FD_CLOEXEC)
|
||||||
|
{
|
||||||
|
Q_ASSERT(flags == FD_CLOEXEC || flags == 0);
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(O_CLOEXEC)
|
||||||
|
// use dup3
|
||||||
|
if (flags & FD_CLOEXEC) {
|
||||||
|
EINTR_LOOP(ret, ::dup3(oldfd, newfd, O_CLOEXEC));
|
||||||
|
if (ret == 0 || errno != ENOSYS)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
EINTR_LOOP(ret, ::dup2(oldfd, newfd));
|
||||||
|
if (ret == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (flags)
|
||||||
|
::fcntl(newfd, F_SETFD, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
|
||||||
|
{
|
||||||
|
qint64 ret = 0;
|
||||||
|
EINTR_LOOP(ret, QT_READ(fd, data, maxlen));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#undef QT_READ
|
||||||
|
#define QT_READ qt_safe_read
|
||||||
|
|
||||||
|
static inline qint64 qt_safe_write(int fd, const void *data, qint64 len)
|
||||||
|
{
|
||||||
|
qint64 ret = 0;
|
||||||
|
EINTR_LOOP(ret, QT_WRITE(fd, data, len));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#undef QT_WRITE
|
||||||
|
#define QT_WRITE qt_safe_write
|
||||||
|
|
||||||
|
static inline qint64 qt_safe_write_nosignal(int fd, const void *data, qint64 len)
|
||||||
|
{
|
||||||
|
qt_ignore_sigpipe();
|
||||||
|
return qt_safe_write(fd, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int qt_safe_close(int fd)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
EINTR_LOOP(ret, QT_CLOSE(fd));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#undef QT_CLOSE
|
||||||
|
#define QT_CLOSE qt_safe_close
|
||||||
|
|
||||||
|
// - VxWorks doesn't have processes
|
||||||
|
#if !defined(Q_OS_VXWORKS)
|
||||||
|
static inline int qt_safe_execve(const char *filename, char *const argv[],
|
||||||
|
char *const envp[])
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
EINTR_LOOP(ret, ::execve(filename, argv, envp));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int qt_safe_execv(const char *path, char *const argv[])
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
EINTR_LOOP(ret, ::execv(path, argv));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int qt_safe_execvp(const char *file, char *const argv[])
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
EINTR_LOOP(ret, ::execvp(file, argv));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
EINTR_LOOP(ret, ::waitpid(pid, status, options));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif // Q_OS_VXWORKS
|
||||||
|
|
||||||
|
#if !defined(_POSIX_MONOTONIC_CLOCK)
|
||||||
|
# define _POSIX_MONOTONIC_CLOCK -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// in qelapsedtimer_mac.cpp or qtimestamp_unix.cpp
|
||||||
|
timespec qt_gettime() Q_DECL_NOTHROW;
|
||||||
|
void qt_nanosleep(timespec amount);
|
||||||
|
|
||||||
|
int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, const struct timespec *tv);
|
||||||
|
|
||||||
|
// according to X/OPEN we have to define semun ourselves
|
||||||
|
// we use prefix as on some systems sem.h will have it
|
||||||
|
struct semid_ds;
|
||||||
|
union qt_semun {
|
||||||
|
int val; /* value for SETVAL */
|
||||||
|
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
|
||||||
|
unsigned short *array; /* array for GETALL, SETALL */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif
|
164
src/app/core/backport/qfileinfo_p.h
Normal file
164
src/app/core/backport/qfileinfo_p.h
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QFILEINFO_P_H
|
||||||
|
#define QFILEINFO_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists purely as an
|
||||||
|
// implementation detail. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include "qatomic.h"
|
||||||
|
#include <QSharedData>
|
||||||
|
#include "qfilesystemengine_p.h"
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
#include "qabstractfileengine_p.h"
|
||||||
|
#include "qfilesystementry_p.h"
|
||||||
|
#include "qfilesystemmetadata_p.h"
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
class QFileInfoPrivate : public QSharedData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum { CachedFileFlags=0x01, CachedLinkTypeFlag=0x02, CachedBundleTypeFlag=0x04,
|
||||||
|
CachedMTime=0x10, CachedCTime=0x20, CachedATime=0x40,
|
||||||
|
CachedSize =0x08, CachedPerms=0x80 };
|
||||||
|
|
||||||
|
inline QFileInfoPrivate()
|
||||||
|
: QSharedData(), fileEngine(0),
|
||||||
|
cachedFlags(0),
|
||||||
|
isDefaultConstructed(true),
|
||||||
|
cache_enabled(true), fileFlags(0), fileSize(0)
|
||||||
|
{}
|
||||||
|
inline QFileInfoPrivate(const QFileInfoPrivate ©)
|
||||||
|
: QSharedData(copy),
|
||||||
|
fileEntry(copy.fileEntry),
|
||||||
|
metaData(copy.metaData),
|
||||||
|
fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)),
|
||||||
|
cachedFlags(0),
|
||||||
|
#ifndef QT_NO_FSFILEENGINE
|
||||||
|
isDefaultConstructed(false),
|
||||||
|
#else
|
||||||
|
isDefaultConstructed(!fileEngine),
|
||||||
|
#endif
|
||||||
|
cache_enabled(copy.cache_enabled), fileFlags(0), fileSize(0)
|
||||||
|
{}
|
||||||
|
inline QFileInfoPrivate(const QString &file)
|
||||||
|
: fileEntry(QDir::fromNativeSeparators(file)),
|
||||||
|
fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)),
|
||||||
|
cachedFlags(0),
|
||||||
|
#ifndef QT_NO_FSFILEENGINE
|
||||||
|
isDefaultConstructed(false),
|
||||||
|
#else
|
||||||
|
isDefaultConstructed(!fileEngine),
|
||||||
|
#endif
|
||||||
|
cache_enabled(true), fileFlags(0), fileSize(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QFileInfoPrivate(const QFileSystemEntry &file, const QFileSystemMetaData &data)
|
||||||
|
: QSharedData(),
|
||||||
|
fileEntry(file),
|
||||||
|
metaData(data),
|
||||||
|
fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)),
|
||||||
|
cachedFlags(0),
|
||||||
|
isDefaultConstructed(false),
|
||||||
|
cache_enabled(true), fileFlags(0), fileSize(0)
|
||||||
|
{
|
||||||
|
//If the file engine is not null, this maybe a "mount point" for a custom file engine
|
||||||
|
//in which case we can't trust the metadata
|
||||||
|
if (fileEngine)
|
||||||
|
metaData = QFileSystemMetaData();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QFileInfoPrivate(const QFileSystemEntry &file, const QFileSystemMetaData &data, QAbstractFileEngine *engine)
|
||||||
|
: fileEntry(file),
|
||||||
|
metaData(data),
|
||||||
|
fileEngine(engine),
|
||||||
|
cachedFlags(0),
|
||||||
|
#ifndef QT_NO_FSFILEENGINE
|
||||||
|
isDefaultConstructed(false),
|
||||||
|
#else
|
||||||
|
isDefaultConstructed(!fileEngine),
|
||||||
|
#endif
|
||||||
|
cache_enabled(true), fileFlags(0), fileSize(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void clearFlags() const {
|
||||||
|
fileFlags = 0;
|
||||||
|
cachedFlags = 0;
|
||||||
|
if (fileEngine)
|
||||||
|
(void)fileEngine->fileFlags(QAbstractFileEngine::Refresh);
|
||||||
|
}
|
||||||
|
inline void clear() {
|
||||||
|
metaData.clear();
|
||||||
|
clearFlags();
|
||||||
|
for (int i = QAbstractFileEngine::NFileNames - 1 ; i >= 0 ; --i)
|
||||||
|
fileNames[i].clear();
|
||||||
|
fileOwners[1].clear();
|
||||||
|
fileOwners[0].clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint getFileFlags(QAbstractFileEngine::FileFlags) const;
|
||||||
|
QDateTime &getFileTime(QAbstractFileEngine::FileTime) const;
|
||||||
|
QString getFileName(QAbstractFileEngine::FileName) const;
|
||||||
|
QString getFileOwner(QAbstractFileEngine::FileOwner own) const;
|
||||||
|
|
||||||
|
QFileSystemEntry fileEntry;
|
||||||
|
mutable QFileSystemMetaData metaData;
|
||||||
|
|
||||||
|
QScopedPointer<QAbstractFileEngine> const fileEngine;
|
||||||
|
|
||||||
|
mutable QString fileNames[QAbstractFileEngine::NFileNames];
|
||||||
|
mutable QString fileOwners[2];
|
||||||
|
|
||||||
|
mutable uint cachedFlags : 30;
|
||||||
|
bool const isDefaultConstructed : 1; // QFileInfo is a default constructed instance
|
||||||
|
bool cache_enabled : 1;
|
||||||
|
mutable uint fileFlags;
|
||||||
|
mutable qint64 fileSize;
|
||||||
|
// ### Qt6: FIXME: This vector is essentially a plain array
|
||||||
|
// mutable QDateTime fileTimes[3], but the array is slower
|
||||||
|
// to initialize than the QVector as QDateTime has a pimpl.
|
||||||
|
// In Qt 6, QDateTime should inline its data members,
|
||||||
|
// and this here can be an array again.
|
||||||
|
mutable QVector<QDateTime> fileTimes;
|
||||||
|
inline bool getCachedFlag(uint c) const
|
||||||
|
{ return cache_enabled ? (cachedFlags & c) : 0; }
|
||||||
|
inline void setCachedFlag(uint c) const
|
||||||
|
{ if (cache_enabled) cachedFlags |= c; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif // QFILEINFO_P_H
|
403
src/app/core/backport/qfilesystemengine.cpp
Normal file
403
src/app/core/backport/qfilesystemengine.cpp
Normal file
|
@ -0,0 +1,403 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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 "qfilesystemengine_p.h"
|
||||||
|
#include <QDir>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QStringBuilder>
|
||||||
|
#include "qabstractfileengine_p.h"
|
||||||
|
#ifdef QT_BUILD_CORE_LIB
|
||||||
|
#include "qresource_p.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
|
||||||
|
Returns the canonicalized form of \a path (i.e., with all symlinks
|
||||||
|
resolved, and all redundant path elements removed.
|
||||||
|
*/
|
||||||
|
QString QFileSystemEngine::slowCanonicalized(const QString &path)
|
||||||
|
{
|
||||||
|
if (path.isEmpty())
|
||||||
|
return path;
|
||||||
|
|
||||||
|
QFileInfo fi;
|
||||||
|
const QChar slash(QLatin1Char('/'));
|
||||||
|
QString tmpPath = path;
|
||||||
|
int separatorPos = 0;
|
||||||
|
QSet<QString> nonSymlinks;
|
||||||
|
QSet<QString> known;
|
||||||
|
|
||||||
|
known.insert(path);
|
||||||
|
do {
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
if (separatorPos == 0) {
|
||||||
|
if (tmpPath.size() >= 2 && tmpPath.at(0) == slash && tmpPath.at(1) == slash) {
|
||||||
|
// UNC, skip past the first two elements
|
||||||
|
separatorPos = tmpPath.indexOf(slash, 2);
|
||||||
|
} else if (tmpPath.size() >= 3 && tmpPath.at(1) == QLatin1Char(':') && tmpPath.at(2) == slash) {
|
||||||
|
// volume root, skip since it can not be a symlink
|
||||||
|
separatorPos = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (separatorPos != -1)
|
||||||
|
#endif
|
||||||
|
separatorPos = tmpPath.indexOf(slash, separatorPos + 1);
|
||||||
|
QString prefix = separatorPos == -1 ? tmpPath : tmpPath.left(separatorPos);
|
||||||
|
if (!nonSymlinks.contains(prefix)) {
|
||||||
|
fi.setFile(prefix);
|
||||||
|
if (fi.isSymLink()) {
|
||||||
|
QString target = fi.symLinkTarget();
|
||||||
|
if(QFileInfo(target).isRelative())
|
||||||
|
target = fi.absolutePath() + slash + target;
|
||||||
|
if (separatorPos != -1) {
|
||||||
|
if (fi.isDir() && !target.endsWith(slash))
|
||||||
|
target.append(slash);
|
||||||
|
target.append(tmpPath.mid(separatorPos));
|
||||||
|
}
|
||||||
|
tmpPath = QDir::cleanPath(target);
|
||||||
|
separatorPos = 0;
|
||||||
|
|
||||||
|
if (known.contains(tmpPath))
|
||||||
|
return QString();
|
||||||
|
known.insert(tmpPath);
|
||||||
|
} else {
|
||||||
|
nonSymlinks.insert(prefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (separatorPos != -1);
|
||||||
|
|
||||||
|
return QDir::cleanPath(tmpPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool _q_checkEntry(QFileSystemEntry &entry, QFileSystemMetaData &data, bool resolvingEntry)
|
||||||
|
{
|
||||||
|
if (resolvingEntry) {
|
||||||
|
if (!QFileSystemEngine::fillMetaData(entry, data, QFileSystemMetaData::ExistsAttribute)
|
||||||
|
|| !data.exists()) {
|
||||||
|
data.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool _q_checkEntry(QAbstractFileEngine *&engine, bool resolvingEntry)
|
||||||
|
{
|
||||||
|
if (resolvingEntry) {
|
||||||
|
if (!(engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::ExistsFlag)) {
|
||||||
|
delete engine;
|
||||||
|
engine = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _q_resolveEntryAndCreateLegacyEngine_recursive(QFileSystemEntry &entry, QFileSystemMetaData &data,
|
||||||
|
QAbstractFileEngine *&engine, bool resolvingEntry = false)
|
||||||
|
{
|
||||||
|
QString const &filePath = entry.filePath();
|
||||||
|
if ((engine = qt_custom_file_engine_handler_create(filePath)))
|
||||||
|
return _q_checkEntry(engine, resolvingEntry);
|
||||||
|
|
||||||
|
#if defined(QT_BUILD_CORE_LIB)
|
||||||
|
for (int prefixSeparator = 0; prefixSeparator < filePath.size(); ++prefixSeparator) {
|
||||||
|
QChar const ch = filePath[prefixSeparator];
|
||||||
|
if (ch == QLatin1Char('/'))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (ch == QLatin1Char(':')) {
|
||||||
|
if (prefixSeparator == 0) {
|
||||||
|
engine = new QResourceFileEngine(filePath);
|
||||||
|
return _q_checkEntry(engine, resolvingEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefixSeparator == 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
const QStringList &paths = QDir::searchPaths(filePath.left(prefixSeparator));
|
||||||
|
for (int i = 0; i < paths.count(); i++) {
|
||||||
|
entry = QFileSystemEntry(QDir::cleanPath(paths.at(i) % QLatin1Char('/') % filePath.mid(prefixSeparator + 1)));
|
||||||
|
// Recurse!
|
||||||
|
if (_q_resolveEntryAndCreateLegacyEngine_recursive(entry, data, engine, true))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// entry may have been clobbered at this point.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There's no need to fully validate the prefix here. Consulting the
|
||||||
|
// unicode tables could be expensive and validation is already
|
||||||
|
// performed in QDir::setSearchPaths.
|
||||||
|
//
|
||||||
|
// if (!ch.isLetterOrNumber())
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
#endif // defined(QT_BUILD_CORE_LIB)
|
||||||
|
|
||||||
|
return _q_checkEntry(entry, data, resolvingEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
|
||||||
|
Resolves the \a entry (see QDir::searchPaths) and returns an engine for
|
||||||
|
it, but never a QFSFileEngine.
|
||||||
|
|
||||||
|
Returns a file engine that can be used to access the entry. Returns 0 if
|
||||||
|
QFileSystemEngine API should be used to query and interact with the file
|
||||||
|
system object.
|
||||||
|
*/
|
||||||
|
QAbstractFileEngine *QFileSystemEngine::resolveEntryAndCreateLegacyEngine(
|
||||||
|
QFileSystemEntry &entry, QFileSystemMetaData &data) {
|
||||||
|
QFileSystemEntry copy = entry;
|
||||||
|
QAbstractFileEngine *engine = 0;
|
||||||
|
|
||||||
|
if (_q_resolveEntryAndCreateLegacyEngine_recursive(copy, data, engine))
|
||||||
|
// Reset entry to resolved copy.
|
||||||
|
entry = copy;
|
||||||
|
else
|
||||||
|
data.clear();
|
||||||
|
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
//these unix functions are in this file, because they are shared by symbian port
|
||||||
|
//for open C file handles.
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
//static
|
||||||
|
bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data)
|
||||||
|
{
|
||||||
|
data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
|
||||||
|
data.knownFlagsMask |= QFileSystemMetaData::PosixStatFlags;
|
||||||
|
|
||||||
|
QT_STATBUF statBuffer;
|
||||||
|
if (QT_FSTAT(fd, &statBuffer) == 0) {
|
||||||
|
data.fillFromStatBuf(statBuffer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(Q_OS_QNX)
|
||||||
|
static void fillStat64fromStat32(struct stat64 *statBuf64, const struct stat &statBuf32)
|
||||||
|
{
|
||||||
|
statBuf64->st_mode = statBuf32.st_mode;
|
||||||
|
statBuf64->st_size = statBuf32.st_size;
|
||||||
|
statBuf64->st_ctime = statBuf32.st_ctime;
|
||||||
|
statBuf64->st_mtime = statBuf32.st_mtime;
|
||||||
|
statBuf64->st_atime = statBuf32.st_atime;
|
||||||
|
statBuf64->st_uid = statBuf32.st_uid;
|
||||||
|
statBuf64->st_gid = statBuf32.st_gid;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void QFileSystemMetaData::fillFromStatBuf(const QT_STATBUF &statBuffer)
|
||||||
|
{
|
||||||
|
// Permissions
|
||||||
|
if (statBuffer.st_mode & S_IRUSR)
|
||||||
|
entryFlags |= QFileSystemMetaData::OwnerReadPermission;
|
||||||
|
if (statBuffer.st_mode & S_IWUSR)
|
||||||
|
entryFlags |= QFileSystemMetaData::OwnerWritePermission;
|
||||||
|
if (statBuffer.st_mode & S_IXUSR)
|
||||||
|
entryFlags |= QFileSystemMetaData::OwnerExecutePermission;
|
||||||
|
|
||||||
|
if (statBuffer.st_mode & S_IRGRP)
|
||||||
|
entryFlags |= QFileSystemMetaData::GroupReadPermission;
|
||||||
|
if (statBuffer.st_mode & S_IWGRP)
|
||||||
|
entryFlags |= QFileSystemMetaData::GroupWritePermission;
|
||||||
|
if (statBuffer.st_mode & S_IXGRP)
|
||||||
|
entryFlags |= QFileSystemMetaData::GroupExecutePermission;
|
||||||
|
|
||||||
|
if (statBuffer.st_mode & S_IROTH)
|
||||||
|
entryFlags |= QFileSystemMetaData::OtherReadPermission;
|
||||||
|
if (statBuffer.st_mode & S_IWOTH)
|
||||||
|
entryFlags |= QFileSystemMetaData::OtherWritePermission;
|
||||||
|
if (statBuffer.st_mode & S_IXOTH)
|
||||||
|
entryFlags |= QFileSystemMetaData::OtherExecutePermission;
|
||||||
|
|
||||||
|
// Type
|
||||||
|
if ((statBuffer.st_mode & S_IFMT) == S_IFREG)
|
||||||
|
entryFlags |= QFileSystemMetaData::FileType;
|
||||||
|
else if ((statBuffer.st_mode & S_IFMT) == S_IFDIR)
|
||||||
|
entryFlags |= QFileSystemMetaData::DirectoryType;
|
||||||
|
else
|
||||||
|
entryFlags |= QFileSystemMetaData::SequentialType;
|
||||||
|
|
||||||
|
// Attributes
|
||||||
|
entryFlags |= QFileSystemMetaData::ExistsAttribute;
|
||||||
|
size_ = statBuffer.st_size;
|
||||||
|
#if defined(Q_OS_MACX)
|
||||||
|
if (statBuffer.st_flags & UF_HIDDEN) {
|
||||||
|
entryFlags |= QFileSystemMetaData::HiddenAttribute;
|
||||||
|
knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Times
|
||||||
|
creationTime_ = statBuffer.st_ctime ? statBuffer.st_ctime : statBuffer.st_mtime;
|
||||||
|
modificationTime_ = statBuffer.st_mtime;
|
||||||
|
accessTime_ = statBuffer.st_atime;
|
||||||
|
userId_ = statBuffer.st_uid;
|
||||||
|
groupId_ = statBuffer.st_gid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QFileSystemMetaData::fillFromDirEnt(const QT_DIRENT &entry)
|
||||||
|
{
|
||||||
|
#if defined(Q_OS_QNX)
|
||||||
|
knownFlagsMask = 0;
|
||||||
|
entryFlags = 0;
|
||||||
|
for (dirent_extra *extra = _DEXTRA_FIRST(&entry); _DEXTRA_VALID(extra, &entry);
|
||||||
|
extra = _DEXTRA_NEXT(extra)) {
|
||||||
|
if (extra->d_type == _DTYPE_STAT || extra->d_type == _DTYPE_LSTAT) {
|
||||||
|
|
||||||
|
const struct dirent_extra_stat * const extra_stat =
|
||||||
|
reinterpret_cast<struct dirent_extra_stat *>(extra);
|
||||||
|
|
||||||
|
// Remember whether this was a link or not, this saves an lstat() call later.
|
||||||
|
if (extra->d_type == _DTYPE_LSTAT) {
|
||||||
|
knownFlagsMask |= QFileSystemMetaData::LinkType;
|
||||||
|
if (S_ISLNK(extra_stat->d_stat.st_mode))
|
||||||
|
entryFlags |= QFileSystemMetaData::LinkType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For symlinks, the extra type _DTYPE_LSTAT doesn't work for filling out the meta data,
|
||||||
|
// as we need the stat() information there, not the lstat() information.
|
||||||
|
// In this case, don't use the extra information.
|
||||||
|
// Unfortunately, readdir() never seems to return extra info of type _DTYPE_STAT, so for
|
||||||
|
// symlinks, we always incur the cost of an extra stat() call later.
|
||||||
|
if (S_ISLNK(extra_stat->d_stat.st_mode) && extra->d_type == _DTYPE_LSTAT)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
#if defined(QT_USE_XOPEN_LFS_EXTENSIONS) && defined(QT_LARGEFILE_SUPPORT)
|
||||||
|
// Even with large file support, d_stat is always of type struct stat, not struct stat64,
|
||||||
|
// so it needs to be converted
|
||||||
|
struct stat64 statBuf;
|
||||||
|
fillStat64fromStat32(&statBuf, extra_stat->d_stat);
|
||||||
|
fillFromStatBuf(statBuf);
|
||||||
|
#else
|
||||||
|
fillFromStatBuf(extra_stat->d_stat);
|
||||||
|
#endif
|
||||||
|
knownFlagsMask |= QFileSystemMetaData::PosixStatFlags;
|
||||||
|
if (!S_ISLNK(extra_stat->d_stat.st_mode)) {
|
||||||
|
knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
|
||||||
|
entryFlags |= QFileSystemMetaData::ExistsAttribute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif defined(_DIRENT_HAVE_D_TYPE) || defined(Q_OS_BSD4)
|
||||||
|
// BSD4 includes Mac OS X
|
||||||
|
|
||||||
|
// ### This will clear all entry flags and knownFlagsMask
|
||||||
|
switch (entry.d_type)
|
||||||
|
{
|
||||||
|
case DT_DIR:
|
||||||
|
knownFlagsMask = QFileSystemMetaData::LinkType
|
||||||
|
| QFileSystemMetaData::FileType
|
||||||
|
| QFileSystemMetaData::DirectoryType
|
||||||
|
| QFileSystemMetaData::SequentialType
|
||||||
|
| QFileSystemMetaData::ExistsAttribute;
|
||||||
|
|
||||||
|
entryFlags = QFileSystemMetaData::DirectoryType
|
||||||
|
| QFileSystemMetaData::ExistsAttribute;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DT_BLK:
|
||||||
|
case DT_CHR:
|
||||||
|
case DT_FIFO:
|
||||||
|
case DT_SOCK:
|
||||||
|
// ### System attribute
|
||||||
|
knownFlagsMask = QFileSystemMetaData::LinkType
|
||||||
|
| QFileSystemMetaData::FileType
|
||||||
|
| QFileSystemMetaData::DirectoryType
|
||||||
|
| QFileSystemMetaData::BundleType
|
||||||
|
| QFileSystemMetaData::AliasType
|
||||||
|
| QFileSystemMetaData::SequentialType
|
||||||
|
| QFileSystemMetaData::ExistsAttribute;
|
||||||
|
|
||||||
|
entryFlags = QFileSystemMetaData::SequentialType
|
||||||
|
| QFileSystemMetaData::ExistsAttribute;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DT_LNK:
|
||||||
|
knownFlagsMask = QFileSystemMetaData::LinkType;
|
||||||
|
entryFlags = QFileSystemMetaData::LinkType;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DT_REG:
|
||||||
|
knownFlagsMask = QFileSystemMetaData::LinkType
|
||||||
|
| QFileSystemMetaData::FileType
|
||||||
|
| QFileSystemMetaData::DirectoryType
|
||||||
|
| QFileSystemMetaData::BundleType
|
||||||
|
| QFileSystemMetaData::SequentialType
|
||||||
|
| QFileSystemMetaData::ExistsAttribute;
|
||||||
|
|
||||||
|
entryFlags = QFileSystemMetaData::FileType
|
||||||
|
| QFileSystemMetaData::ExistsAttribute;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DT_UNKNOWN:
|
||||||
|
default:
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
Q_UNUSED(entry)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//static
|
||||||
|
QString QFileSystemEngine::resolveUserName(const QFileSystemEntry &entry, QFileSystemMetaData &metaData)
|
||||||
|
{
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
Q_UNUSED(metaData);
|
||||||
|
return QFileSystemEngine::owner(entry, QAbstractFileEngine::OwnerUser);
|
||||||
|
#else //(Q_OS_UNIX)
|
||||||
|
if (!metaData.hasFlags(QFileSystemMetaData::UserId))
|
||||||
|
QFileSystemEngine::fillMetaData(entry, metaData, QFileSystemMetaData::UserId);
|
||||||
|
return resolveUserName(metaData.userId());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
QString QFileSystemEngine::resolveGroupName(const QFileSystemEntry &entry, QFileSystemMetaData &metaData)
|
||||||
|
{
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
Q_UNUSED(metaData);
|
||||||
|
return QFileSystemEngine::owner(entry, QAbstractFileEngine::OwnerGroup);
|
||||||
|
#else //(Q_OS_UNIX)
|
||||||
|
if (!metaData.hasFlags(QFileSystemMetaData::GroupId))
|
||||||
|
QFileSystemEngine::fillMetaData(entry, metaData, QFileSystemMetaData::GroupId);
|
||||||
|
return resolveGroupName(metaData.groupId());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
120
src/app/core/backport/qfilesystemengine_p.h
Normal file
120
src/app/core/backport/qfilesystemengine_p.h
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QFILESYSTEMENGINE_P_H
|
||||||
|
#define QFILESYSTEMENGINE_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists purely as an
|
||||||
|
// implementation detail. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include "qfilesystementry_p.h"
|
||||||
|
#include "qfilesystemmetadata_p.h"
|
||||||
|
#include "qsystemerror_p.h"
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
class QFileSystemEngine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static bool isCaseSensitive()
|
||||||
|
{
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static QFileSystemEntry getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data);
|
||||||
|
static QFileSystemEntry canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data);
|
||||||
|
static QFileSystemEntry absoluteName(const QFileSystemEntry &entry);
|
||||||
|
static QByteArray id(const QFileSystemEntry &entry);
|
||||||
|
static QString resolveUserName(const QFileSystemEntry &entry, QFileSystemMetaData &data);
|
||||||
|
static QString resolveGroupName(const QFileSystemEntry &entry, QFileSystemMetaData &data);
|
||||||
|
|
||||||
|
#if defined(Q_OS_UNIX)
|
||||||
|
static QString resolveUserName(uint userId);
|
||||||
|
static QString resolveGroupName(uint groupId);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(Q_OS_MACX)
|
||||||
|
static QString bundleName(const QFileSystemEntry &entry);
|
||||||
|
#else
|
||||||
|
static QString bundleName(const QFileSystemEntry &entry) { Q_UNUSED(entry) return QString(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data,
|
||||||
|
QFileSystemMetaData::MetaDataFlags what);
|
||||||
|
#if defined(Q_OS_UNIX)
|
||||||
|
static bool fillMetaData(int fd, QFileSystemMetaData &data); // what = PosixStatFlags
|
||||||
|
#endif
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
|
||||||
|
static bool uncListSharesOnServer(const QString &server, QStringList *list); //Used also by QFSFileEngineIterator::hasNext()
|
||||||
|
static bool fillMetaData(int fd, QFileSystemMetaData &data,
|
||||||
|
QFileSystemMetaData::MetaDataFlags what);
|
||||||
|
static bool fillMetaData(HANDLE fHandle, QFileSystemMetaData &data,
|
||||||
|
QFileSystemMetaData::MetaDataFlags what);
|
||||||
|
static bool fillPermissions(const QFileSystemEntry &entry, QFileSystemMetaData &data,
|
||||||
|
QFileSystemMetaData::MetaDataFlags what);
|
||||||
|
static QString owner(const QFileSystemEntry &entry, QAbstractFileEngine::FileOwner own);
|
||||||
|
static QString nativeAbsoluteFilePath(const QString &path);
|
||||||
|
#endif
|
||||||
|
//homePath, rootPath and tempPath shall return clean paths
|
||||||
|
static QString homePath();
|
||||||
|
static QString rootPath();
|
||||||
|
static QString tempPath();
|
||||||
|
|
||||||
|
static bool createDirectory(const QFileSystemEntry &entry, bool createParents);
|
||||||
|
static bool removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents);
|
||||||
|
|
||||||
|
static bool createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
|
||||||
|
|
||||||
|
static bool copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
|
||||||
|
static bool renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
|
||||||
|
static bool removeFile(const QFileSystemEntry &entry, QSystemError &error);
|
||||||
|
|
||||||
|
static bool setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error,
|
||||||
|
QFileSystemMetaData *data = 0);
|
||||||
|
|
||||||
|
static bool setCurrentPath(const QFileSystemEntry &entry);
|
||||||
|
static QFileSystemEntry currentPath();
|
||||||
|
|
||||||
|
static QAbstractFileEngine *resolveEntryAndCreateLegacyEngine(QFileSystemEntry &entry,
|
||||||
|
QFileSystemMetaData &data);
|
||||||
|
private:
|
||||||
|
static QString slowCanonicalized(const QString &path);
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
static void clearWinStatData(QFileSystemMetaData &data);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif // include guard
|
756
src/app/core/backport/qfilesystemengine_unix.cpp
Normal file
756
src/app/core/backport/qfilesystemengine_unix.cpp
Normal file
|
@ -0,0 +1,756 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>>
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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 "qplatformdefs.h"
|
||||||
|
#include "qfilesystemengine_p.h"
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
|
#include <QVarLengthArray>
|
||||||
|
|
||||||
|
#include <stdlib.h> // for realpath()
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#if defined(Q_OS_MAC)
|
||||||
|
# include "qcore_mac_p.h"
|
||||||
|
# include <CoreFoundation/CFBundle.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#if defined(Q_OS_MACX)
|
||||||
|
static inline bool _q_isMacHidden(const char *nativePath)
|
||||||
|
{
|
||||||
|
OSErr err;
|
||||||
|
|
||||||
|
FSRef fsRef;
|
||||||
|
err = FSPathMakeRefWithOptions(reinterpret_cast<const UInt8 *>(nativePath),
|
||||||
|
kFSPathMakeRefDoNotFollowLeafSymlink, &fsRef, 0);
|
||||||
|
if (err != noErr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
FSCatalogInfo catInfo;
|
||||||
|
err = FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &catInfo, NULL, NULL, NULL);
|
||||||
|
if (err != noErr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
FileInfo * const fileInfo = reinterpret_cast<FileInfo*>(&catInfo.finderInfo);
|
||||||
|
return (fileInfo->finderFlags & kIsInvisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &entry)
|
||||||
|
{
|
||||||
|
if (!data.isDirectory())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QFileInfo info(entry.filePath());
|
||||||
|
QString suffix = info.suffix();
|
||||||
|
|
||||||
|
// First step: is the extenstion known ?
|
||||||
|
if (suffix == QLatin1String("app")
|
||||||
|
|| suffix == QLatin1String("debug")
|
||||||
|
|| suffix == QLatin1String("profile")
|
||||||
|
|| suffix == QLatin1String("bundle")
|
||||||
|
|| suffix == QLatin1String("pkg")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second step: check if an application knows the package type
|
||||||
|
const QByteArray &native = entry.nativeFilePath();
|
||||||
|
const char *nativeFilePath = native.constData();
|
||||||
|
int nativeFilePathLength = native.size();
|
||||||
|
|
||||||
|
QCFType<CFStringRef> path = CFStringCreateWithBytes(0,
|
||||||
|
reinterpret_cast<const UInt8*>(nativeFilePath),
|
||||||
|
nativeFilePathLength,
|
||||||
|
kCFStringEncodingUTF8,
|
||||||
|
false);
|
||||||
|
|
||||||
|
QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle, true);
|
||||||
|
|
||||||
|
UInt32 type, creator;
|
||||||
|
// Well created packages have the PkgInfo file
|
||||||
|
if (CFBundleGetPackageInfoInDirectory(url, &type, &creator))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Find if an application other than Finder claims to know how to handle the package
|
||||||
|
if (suffix.length() > 0) {
|
||||||
|
QCFType<CFURLRef> application;
|
||||||
|
LSGetApplicationForURL(url,
|
||||||
|
kLSRolesEditor|kLSRolesViewer|kLSRolesViewer,
|
||||||
|
NULL,
|
||||||
|
&application);
|
||||||
|
|
||||||
|
if (application) {
|
||||||
|
CFStringRef path = CFURLGetString(application);
|
||||||
|
QString applicationPath = QCFString::toQString(path);
|
||||||
|
if (applicationPath != QLatin1String("file://localhost/System/Library/CoreServices/Finder.app/"))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Third step: check if the directory has the package bit set
|
||||||
|
FSRef packageRef;
|
||||||
|
FSPathMakeRef((UInt8 *)nativeFilePath, &packageRef, NULL);
|
||||||
|
|
||||||
|
FSCatalogInfo catalogInfo;
|
||||||
|
FSGetCatalogInfo(&packageRef,
|
||||||
|
kFSCatInfoFinderInfo,
|
||||||
|
&catalogInfo,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
FolderInfo *folderInfo = reinterpret_cast<FolderInfo *>(catalogInfo.finderInfo);
|
||||||
|
return folderInfo->finderFlags & kHasBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
static inline bool _q_isMacHidden(const char *nativePath)
|
||||||
|
{
|
||||||
|
Q_UNUSED(nativePath);
|
||||||
|
// no-op
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//static
|
||||||
|
QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data)
|
||||||
|
{
|
||||||
|
#if defined(__GLIBC__) && !defined(PATH_MAX)
|
||||||
|
#define PATH_CHUNK_SIZE 256
|
||||||
|
char *s = 0;
|
||||||
|
int len = -1;
|
||||||
|
int size = PATH_CHUNK_SIZE;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
s = (char *) ::realloc(s, size);
|
||||||
|
Q_CHECK_PTR(s);
|
||||||
|
len = ::readlink(link.nativeFilePath().constData(), s, size);
|
||||||
|
if (len < 0) {
|
||||||
|
::free(s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (len < size) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size *= 2;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
char s[PATH_MAX+1];
|
||||||
|
int len = readlink(link.nativeFilePath().constData(), s, PATH_MAX);
|
||||||
|
#endif
|
||||||
|
if (len > 0) {
|
||||||
|
QString ret;
|
||||||
|
if (!data.hasFlags(QFileSystemMetaData::DirectoryType))
|
||||||
|
fillMetaData(link, data, QFileSystemMetaData::DirectoryType);
|
||||||
|
if (data.isDirectory() && s[0] != '/') {
|
||||||
|
QDir parent(link.filePath());
|
||||||
|
parent.cdUp();
|
||||||
|
ret = parent.path();
|
||||||
|
if (!ret.isEmpty() && !ret.endsWith(QLatin1Char('/')))
|
||||||
|
ret += QLatin1Char('/');
|
||||||
|
}
|
||||||
|
s[len] = '\0';
|
||||||
|
ret += QFile::decodeName(QByteArray(s));
|
||||||
|
#if defined(__GLIBC__) && !defined(PATH_MAX)
|
||||||
|
::free(s);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!ret.startsWith(QLatin1Char('/'))) {
|
||||||
|
if (link.filePath().startsWith(QLatin1Char('/'))) {
|
||||||
|
ret.prepend(link.filePath().left(link.filePath().lastIndexOf(QLatin1Char('/')))
|
||||||
|
+ QLatin1Char('/'));
|
||||||
|
} else {
|
||||||
|
ret.prepend(QDir::currentPath() + QLatin1Char('/'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = QDir::cleanPath(ret);
|
||||||
|
if (ret.size() > 1 && ret.endsWith(QLatin1Char('/')))
|
||||||
|
ret.chop(1);
|
||||||
|
return QFileSystemEntry(ret);
|
||||||
|
}
|
||||||
|
#if defined(Q_OS_MACX)
|
||||||
|
{
|
||||||
|
FSRef fref;
|
||||||
|
if (FSPathMakeRef((const UInt8 *)QFile::encodeName(QDir::cleanPath(link.filePath())).data(), &fref, 0) == noErr) {
|
||||||
|
// TODO get the meta data info from the QFileSystemMetaData object
|
||||||
|
Boolean isAlias, isFolder;
|
||||||
|
if (FSResolveAliasFile(&fref, true, &isFolder, &isAlias) == noErr && isAlias) {
|
||||||
|
AliasHandle alias;
|
||||||
|
if (FSNewAlias(0, &fref, &alias) == noErr && alias) {
|
||||||
|
QCFString cfstr;
|
||||||
|
if (FSCopyAliasInfo(alias, 0, 0, &cfstr, 0, 0) == noErr)
|
||||||
|
return QFileSystemEntry(QCFString::toQString(cfstr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return QFileSystemEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
|
||||||
|
{
|
||||||
|
if (entry.isEmpty() || entry.isRoot())
|
||||||
|
return entry;
|
||||||
|
|
||||||
|
#if !defined(Q_OS_MAC) && !defined(Q_OS_QNX) && !defined(Q_OS_ANDROID) && _POSIX_VERSION < 200809L
|
||||||
|
// realpath(X,0) is not supported
|
||||||
|
Q_UNUSED(data);
|
||||||
|
return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath()));
|
||||||
|
#else
|
||||||
|
char *ret = 0;
|
||||||
|
# if defined(Q_OS_MACX)
|
||||||
|
// When using -mmacosx-version-min=10.4, we get the legacy realpath implementation,
|
||||||
|
// which does not work properly with the realpath(X,0) form. See QTBUG-28282.
|
||||||
|
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) {
|
||||||
|
ret = (char*)malloc(PATH_MAX + 1);
|
||||||
|
if (ret && realpath(entry.nativeFilePath().constData(), (char*)ret) == 0) {
|
||||||
|
const int savedErrno = errno; // errno is checked below, and free() might change it
|
||||||
|
free(ret);
|
||||||
|
errno = savedErrno;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// on 10.5 we can use FSRef to resolve the file path.
|
||||||
|
QString path = QDir::cleanPath(entry.filePath());
|
||||||
|
FSRef fsref;
|
||||||
|
if (FSPathMakeRef((const UInt8 *)path.toUtf8().data(), &fsref, 0) == noErr) {
|
||||||
|
CFURLRef urlref = CFURLCreateFromFSRef(NULL, &fsref);
|
||||||
|
CFStringRef canonicalPath = CFURLCopyFileSystemPath(urlref, kCFURLPOSIXPathStyle);
|
||||||
|
QString ret = QCFString::toQString(canonicalPath);
|
||||||
|
CFRelease(canonicalPath);
|
||||||
|
CFRelease(urlref);
|
||||||
|
return QFileSystemEntry(ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
# if _POSIX_VERSION >= 200801L
|
||||||
|
ret = realpath(entry.nativeFilePath().constData(), (char*)0);
|
||||||
|
# else
|
||||||
|
ret = (char*)malloc(PATH_MAX + 1);
|
||||||
|
if (realpath(entry.nativeFilePath().constData(), (char*)ret) == 0) {
|
||||||
|
const int savedErrno = errno; // errno is checked below, and free() might change it
|
||||||
|
free(ret);
|
||||||
|
errno = savedErrno;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
if (ret) {
|
||||||
|
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
|
||||||
|
data.entryFlags |= QFileSystemMetaData::ExistsAttribute;
|
||||||
|
QString canonicalPath = QDir::cleanPath(QString::fromLocal8Bit(ret));
|
||||||
|
free(ret);
|
||||||
|
return QFileSystemEntry(canonicalPath);
|
||||||
|
} else if (errno == ENOENT) { // file doesn't exist
|
||||||
|
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
|
||||||
|
data.entryFlags &= ~(QFileSystemMetaData::ExistsAttribute);
|
||||||
|
return QFileSystemEntry();
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
|
||||||
|
{
|
||||||
|
if (entry.isAbsolute() && entry.isClean())
|
||||||
|
return entry;
|
||||||
|
|
||||||
|
QByteArray orig = entry.nativeFilePath();
|
||||||
|
QByteArray result;
|
||||||
|
if (orig.isEmpty() || !orig.startsWith('/')) {
|
||||||
|
QFileSystemEntry cur(currentPath());
|
||||||
|
result = cur.nativeFilePath();
|
||||||
|
}
|
||||||
|
if (!orig.isEmpty() && !(orig.length() == 1 && orig[0] == '.')) {
|
||||||
|
if (!result.isEmpty() && !result.endsWith('/'))
|
||||||
|
result.append('/');
|
||||||
|
result.append(orig);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.length() == 1 && result[0] == '/')
|
||||||
|
return QFileSystemEntry(result, QFileSystemEntry::FromNativePath());
|
||||||
|
const bool isDir = result.endsWith('/');
|
||||||
|
|
||||||
|
/* as long as QDir::cleanPath() operates on a QString we have to convert to a string here.
|
||||||
|
* ideally we never convert to a string since that loses information. Please fix after
|
||||||
|
* we get a QByteArray version of QDir::cleanPath()
|
||||||
|
*/
|
||||||
|
QFileSystemEntry resultingEntry(result, QFileSystemEntry::FromNativePath());
|
||||||
|
QString stringVersion = QDir::cleanPath(resultingEntry.filePath());
|
||||||
|
if (isDir)
|
||||||
|
stringVersion.append(QLatin1Char('/'));
|
||||||
|
return QFileSystemEntry(stringVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry)
|
||||||
|
{
|
||||||
|
struct stat statResult;
|
||||||
|
if (stat(entry.nativeFilePath().constData(), &statResult)) {
|
||||||
|
qErrnoWarning("stat() failed for '%s'", entry.nativeFilePath().constData());
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
|
QByteArray result = QByteArray::number(quint64(statResult.st_dev), 16);
|
||||||
|
result += ':';
|
||||||
|
result += QByteArray::number(quint64(statResult.st_ino));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
QString QFileSystemEngine::resolveUserName(uint userId)
|
||||||
|
{
|
||||||
|
#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
|
||||||
|
int size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
|
||||||
|
if (size_max == -1)
|
||||||
|
size_max = 1024;
|
||||||
|
QVarLengthArray<char, 1024> buf(size_max);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct passwd *pw = 0;
|
||||||
|
#if !defined(Q_OS_INTEGRITY)
|
||||||
|
#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS)
|
||||||
|
struct passwd entry;
|
||||||
|
getpwuid_r(userId, &entry, buf.data(), buf.size(), &pw);
|
||||||
|
#else
|
||||||
|
pw = getpwuid(userId);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
if (pw)
|
||||||
|
return QFile::decodeName(QByteArray(pw->pw_name));
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
QString QFileSystemEngine::resolveGroupName(uint groupId)
|
||||||
|
{
|
||||||
|
#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
|
||||||
|
int size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
|
||||||
|
if (size_max == -1)
|
||||||
|
size_max = 1024;
|
||||||
|
QVarLengthArray<char, 1024> buf(size_max);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct group *gr = 0;
|
||||||
|
#if !defined(Q_OS_INTEGRITY)
|
||||||
|
#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS)
|
||||||
|
size_max = sysconf(_SC_GETGR_R_SIZE_MAX);
|
||||||
|
if (size_max == -1)
|
||||||
|
size_max = 1024;
|
||||||
|
buf.resize(size_max);
|
||||||
|
struct group entry;
|
||||||
|
// Some large systems have more members than the POSIX max size
|
||||||
|
// Loop over by doubling the buffer size (upper limit 250k)
|
||||||
|
for (unsigned size = size_max; size < 256000; size += size)
|
||||||
|
{
|
||||||
|
buf.resize(size);
|
||||||
|
// ERANGE indicates that the buffer was too small
|
||||||
|
if (!getgrgid_r(groupId, &entry, buf.data(), buf.size(), &gr)
|
||||||
|
|| errno != ERANGE)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
gr = getgrgid(groupId);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
if (gr)
|
||||||
|
return QFile::decodeName(QByteArray(gr->gr_name));
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(Q_OS_MACX)
|
||||||
|
//static
|
||||||
|
QString QFileSystemEngine::bundleName(const QFileSystemEntry &entry)
|
||||||
|
{
|
||||||
|
QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, QCFString(entry.filePath()),
|
||||||
|
kCFURLPOSIXPathStyle, true);
|
||||||
|
if (QCFType<CFDictionaryRef> dict = CFBundleCopyInfoDictionaryForURL(url)) {
|
||||||
|
if (CFTypeRef name = (CFTypeRef)CFDictionaryGetValue(dict, kCFBundleNameKey)) {
|
||||||
|
if (CFGetTypeID(name) == CFStringGetTypeID())
|
||||||
|
return QCFString::toQString((CFStringRef)name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//static
|
||||||
|
bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data,
|
||||||
|
QFileSystemMetaData::MetaDataFlags what)
|
||||||
|
{
|
||||||
|
#if defined(Q_OS_MACX)
|
||||||
|
if (what & QFileSystemMetaData::BundleType) {
|
||||||
|
if (!data.hasFlags(QFileSystemMetaData::DirectoryType))
|
||||||
|
what |= QFileSystemMetaData::DirectoryType;
|
||||||
|
}
|
||||||
|
if (what & QFileSystemMetaData::HiddenAttribute) {
|
||||||
|
// Mac OS >= 10.5: st_flags & UF_HIDDEN
|
||||||
|
what |= QFileSystemMetaData::PosixStatFlags;
|
||||||
|
}
|
||||||
|
#endif // defined(Q_OS_MACX)
|
||||||
|
|
||||||
|
if (what & QFileSystemMetaData::PosixStatFlags)
|
||||||
|
what |= QFileSystemMetaData::PosixStatFlags;
|
||||||
|
|
||||||
|
if (what & QFileSystemMetaData::ExistsAttribute) {
|
||||||
|
// FIXME: Would other queries being performed provide this bit?
|
||||||
|
what |= QFileSystemMetaData::PosixStatFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.entryFlags &= ~what;
|
||||||
|
|
||||||
|
const char * nativeFilePath;
|
||||||
|
int nativeFilePathLength;
|
||||||
|
{
|
||||||
|
const QByteArray &path = entry.nativeFilePath();
|
||||||
|
nativeFilePath = path.constData();
|
||||||
|
nativeFilePathLength = path.size();
|
||||||
|
Q_UNUSED(nativeFilePathLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool entryExists = true; // innocent until proven otherwise
|
||||||
|
|
||||||
|
QT_STATBUF statBuffer;
|
||||||
|
bool statBufferValid = false;
|
||||||
|
if (what & QFileSystemMetaData::LinkType) {
|
||||||
|
if (QT_LSTAT(nativeFilePath, &statBuffer) == 0) {
|
||||||
|
if (S_ISLNK(statBuffer.st_mode)) {
|
||||||
|
data.entryFlags |= QFileSystemMetaData::LinkType;
|
||||||
|
} else {
|
||||||
|
statBufferValid = true;
|
||||||
|
data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entryExists = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.knownFlagsMask |= QFileSystemMetaData::LinkType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statBufferValid || (what & QFileSystemMetaData::PosixStatFlags)) {
|
||||||
|
if (entryExists && !statBufferValid)
|
||||||
|
statBufferValid = (QT_STAT(nativeFilePath, &statBuffer) == 0);
|
||||||
|
|
||||||
|
if (statBufferValid)
|
||||||
|
data.fillFromStatBuf(statBuffer);
|
||||||
|
else {
|
||||||
|
entryExists = false;
|
||||||
|
data.creationTime_ = 0;
|
||||||
|
data.modificationTime_ = 0;
|
||||||
|
data.accessTime_ = 0;
|
||||||
|
data.size_ = 0;
|
||||||
|
data.userId_ = (uint) -2;
|
||||||
|
data.groupId_ = (uint) -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset the mask
|
||||||
|
data.knownFlagsMask |= QFileSystemMetaData::PosixStatFlags
|
||||||
|
| QFileSystemMetaData::ExistsAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(Q_OS_MACX)
|
||||||
|
if (what & QFileSystemMetaData::AliasType)
|
||||||
|
{
|
||||||
|
if (entryExists) {
|
||||||
|
FSRef fref;
|
||||||
|
if (FSPathMakeRef((const UInt8 *)nativeFilePath, &fref, NULL) == noErr) {
|
||||||
|
Boolean isAlias, isFolder;
|
||||||
|
if (FSIsAliasFile(&fref, &isAlias, &isFolder) == noErr) {
|
||||||
|
if (isAlias)
|
||||||
|
data.entryFlags |= QFileSystemMetaData::AliasType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.knownFlagsMask |= QFileSystemMetaData::AliasType;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (what & QFileSystemMetaData::UserPermissions) {
|
||||||
|
// calculate user permissions
|
||||||
|
|
||||||
|
if (entryExists) {
|
||||||
|
if (what & QFileSystemMetaData::UserReadPermission) {
|
||||||
|
if (QT_ACCESS(nativeFilePath, R_OK) == 0)
|
||||||
|
data.entryFlags |= QFileSystemMetaData::UserReadPermission;
|
||||||
|
}
|
||||||
|
if (what & QFileSystemMetaData::UserWritePermission) {
|
||||||
|
if (QT_ACCESS(nativeFilePath, W_OK) == 0)
|
||||||
|
data.entryFlags |= QFileSystemMetaData::UserWritePermission;
|
||||||
|
}
|
||||||
|
if (what & QFileSystemMetaData::UserExecutePermission) {
|
||||||
|
if (QT_ACCESS(nativeFilePath, X_OK) == 0)
|
||||||
|
data.entryFlags |= QFileSystemMetaData::UserExecutePermission;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.knownFlagsMask |= (what & QFileSystemMetaData::UserPermissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (what & QFileSystemMetaData::HiddenAttribute
|
||||||
|
&& !data.isHidden()) {
|
||||||
|
QString fileName = entry.fileName();
|
||||||
|
if ((fileName.size() > 0 && fileName.at(0) == QLatin1Char('.'))
|
||||||
|
|| (entryExists && _q_isMacHidden(nativeFilePath)))
|
||||||
|
data.entryFlags |= QFileSystemMetaData::HiddenAttribute;
|
||||||
|
data.knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(Q_OS_MACX)
|
||||||
|
if (what & QFileSystemMetaData::BundleType) {
|
||||||
|
if (entryExists && isPackage(data, entry))
|
||||||
|
data.entryFlags |= QFileSystemMetaData::BundleType;
|
||||||
|
|
||||||
|
data.knownFlagsMask |= QFileSystemMetaData::BundleType;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!entryExists) {
|
||||||
|
data.clearFlags(what);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return data.hasFlags(what);
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents)
|
||||||
|
{
|
||||||
|
QString dirName = entry.filePath();
|
||||||
|
if (createParents) {
|
||||||
|
dirName = QDir::cleanPath(dirName);
|
||||||
|
for (int oldslash = -1, slash=0; slash != -1; oldslash = slash) {
|
||||||
|
slash = dirName.indexOf(QDir::separator(), oldslash+1);
|
||||||
|
if (slash == -1) {
|
||||||
|
if (oldslash == dirName.length())
|
||||||
|
break;
|
||||||
|
slash = dirName.length();
|
||||||
|
}
|
||||||
|
if (slash) {
|
||||||
|
const QByteArray chunk = QFile::encodeName(dirName.left(slash));
|
||||||
|
if (QT_MKDIR(chunk.constData(), 0777) != 0) {
|
||||||
|
if (errno == EEXIST
|
||||||
|
#if defined(Q_OS_QNX)
|
||||||
|
// On QNX the QNet (VFS paths of other hosts mounted under a directory
|
||||||
|
// such as /net) mountpoint returns ENOENT, despite existing. stat()
|
||||||
|
// on the QNet mountpoint returns successfully and reports S_IFDIR.
|
||||||
|
|| errno == ENOENT
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
|
QT_STATBUF st;
|
||||||
|
if (QT_STAT(chunk.constData(), &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#if defined(Q_OS_DARWIN) // Mac X doesn't support trailing /'s
|
||||||
|
if (dirName.endsWith(QLatin1Char('/')))
|
||||||
|
dirName.chop(1);
|
||||||
|
#endif
|
||||||
|
return (QT_MKDIR(QFile::encodeName(dirName).constData(), 0777) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents)
|
||||||
|
{
|
||||||
|
if (removeEmptyParents) {
|
||||||
|
QString dirName = QDir::cleanPath(entry.filePath());
|
||||||
|
for (int oldslash = 0, slash=dirName.length(); slash > 0; oldslash = slash) {
|
||||||
|
const QByteArray chunk = QFile::encodeName(dirName.left(slash));
|
||||||
|
QT_STATBUF st;
|
||||||
|
if (QT_STAT(chunk.constData(), &st) != -1) {
|
||||||
|
if ((st.st_mode & S_IFMT) != S_IFDIR)
|
||||||
|
return false;
|
||||||
|
if (::rmdir(chunk.constData()) != 0)
|
||||||
|
return oldslash != 0;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
slash = dirName.lastIndexOf(QDir::separator(), oldslash-1);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return rmdir(QFile::encodeName(entry.filePath()).constData()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
|
||||||
|
{
|
||||||
|
if (::symlink(source.nativeFilePath().constData(), target.nativeFilePath().constData()) == 0)
|
||||||
|
return true;
|
||||||
|
error = QSystemError(errno, QSystemError::StandardLibraryError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
|
||||||
|
{
|
||||||
|
Q_UNUSED(source);
|
||||||
|
Q_UNUSED(target);
|
||||||
|
error = QSystemError(ENOSYS, QSystemError::StandardLibraryError); //Function not implemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
|
||||||
|
{
|
||||||
|
if (::rename(source.nativeFilePath().constData(), target.nativeFilePath().constData()) == 0)
|
||||||
|
return true;
|
||||||
|
error = QSystemError(errno, QSystemError::StandardLibraryError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &error)
|
||||||
|
{
|
||||||
|
if (unlink(entry.nativeFilePath().constData()) == 0)
|
||||||
|
return true;
|
||||||
|
error = QSystemError(errno, QSystemError::StandardLibraryError);
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data)
|
||||||
|
{
|
||||||
|
mode_t mode = 0;
|
||||||
|
if (permissions & QFile::ReadOwner)
|
||||||
|
mode |= S_IRUSR;
|
||||||
|
if (permissions & QFile::WriteOwner)
|
||||||
|
mode |= S_IWUSR;
|
||||||
|
if (permissions & QFile::ExeOwner)
|
||||||
|
mode |= S_IXUSR;
|
||||||
|
if (permissions & QFile::ReadUser)
|
||||||
|
mode |= S_IRUSR;
|
||||||
|
if (permissions & QFile::WriteUser)
|
||||||
|
mode |= S_IWUSR;
|
||||||
|
if (permissions & QFile::ExeUser)
|
||||||
|
mode |= S_IXUSR;
|
||||||
|
if (permissions & QFile::ReadGroup)
|
||||||
|
mode |= S_IRGRP;
|
||||||
|
if (permissions & QFile::WriteGroup)
|
||||||
|
mode |= S_IWGRP;
|
||||||
|
if (permissions & QFile::ExeGroup)
|
||||||
|
mode |= S_IXGRP;
|
||||||
|
if (permissions & QFile::ReadOther)
|
||||||
|
mode |= S_IROTH;
|
||||||
|
if (permissions & QFile::WriteOther)
|
||||||
|
mode |= S_IWOTH;
|
||||||
|
if (permissions & QFile::ExeOther)
|
||||||
|
mode |= S_IXOTH;
|
||||||
|
|
||||||
|
bool success = ::chmod(entry.nativeFilePath().constData(), mode) == 0;
|
||||||
|
if (success && data) {
|
||||||
|
data->entryFlags &= ~QFileSystemMetaData::Permissions;
|
||||||
|
data->entryFlags |= QFileSystemMetaData::MetaDataFlag(uint(permissions));
|
||||||
|
data->knownFlagsMask |= QFileSystemMetaData::Permissions;
|
||||||
|
}
|
||||||
|
if (!success)
|
||||||
|
error = QSystemError(errno, QSystemError::StandardLibraryError);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFileSystemEngine::homePath()
|
||||||
|
{
|
||||||
|
QString home = QFile::decodeName(qgetenv("HOME"));
|
||||||
|
if (home.isEmpty())
|
||||||
|
home = rootPath();
|
||||||
|
return QDir::cleanPath(home);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFileSystemEngine::rootPath()
|
||||||
|
{
|
||||||
|
return QLatin1String("/");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFileSystemEngine::tempPath()
|
||||||
|
{
|
||||||
|
#ifdef QT_UNIX_TEMP_PATH_OVERRIDE
|
||||||
|
return QLatin1String(QT_UNIX_TEMP_PATH_OVERRIDE);
|
||||||
|
#elif defined(Q_OS_BLACKBERRY)
|
||||||
|
QString temp = QFile::decodeName(qgetenv("TEMP"));
|
||||||
|
if (temp.isEmpty())
|
||||||
|
temp = QFile::decodeName(qgetenv("TMPDIR"));
|
||||||
|
|
||||||
|
if (temp.isEmpty()) {
|
||||||
|
qWarning("Neither the TEMP nor the TMPDIR environment variable is set, falling back to /tmp.");
|
||||||
|
temp = QLatin1String("/tmp/");
|
||||||
|
}
|
||||||
|
return QDir::cleanPath(temp);
|
||||||
|
#else
|
||||||
|
QString temp = QFile::decodeName(qgetenv("TMPDIR"));
|
||||||
|
if (temp.isEmpty())
|
||||||
|
temp = QLatin1String("/tmp/");
|
||||||
|
return QDir::cleanPath(temp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &path)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
r = QT_CHDIR(path.nativeFilePath().constData());
|
||||||
|
return r >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileSystemEntry QFileSystemEngine::currentPath()
|
||||||
|
{
|
||||||
|
QFileSystemEntry result;
|
||||||
|
QT_STATBUF st;
|
||||||
|
if (QT_STAT(".", &st) == 0) {
|
||||||
|
#if defined(__GLIBC__) && !defined(PATH_MAX)
|
||||||
|
char *currentName = ::get_current_dir_name();
|
||||||
|
if (currentName) {
|
||||||
|
result = QFileSystemEntry(QByteArray(currentName), QFileSystemEntry::FromNativePath());
|
||||||
|
::free(currentName);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
char currentName[PATH_MAX+1];
|
||||||
|
if (::getcwd(currentName, PATH_MAX)) {
|
||||||
|
#if defined(Q_OS_VXWORKS) && defined(VXWORKS_VXSIM)
|
||||||
|
QByteArray dir(currentName);
|
||||||
|
if (dir.indexOf(':') < dir.indexOf('/'))
|
||||||
|
dir.remove(0, dir.indexOf(':')+1);
|
||||||
|
|
||||||
|
qstrncpy(currentName, dir.constData(), PATH_MAX);
|
||||||
|
#endif
|
||||||
|
result = QFileSystemEntry(QByteArray(currentName), QFileSystemEntry::FromNativePath());
|
||||||
|
}
|
||||||
|
# if defined(QT_DEBUG)
|
||||||
|
if (result.isEmpty())
|
||||||
|
qWarning("QFileSystemEngine::currentPath: getcwd() failed");
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
# if defined(QT_DEBUG)
|
||||||
|
qWarning("QFileSystemEngine::currentPath: stat(\".\") failed");
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
1324
src/app/core/backport/qfilesystemengine_win.cpp
Normal file
1324
src/app/core/backport/qfilesystemengine_win.cpp
Normal file
File diff suppressed because it is too large
Load Diff
388
src/app/core/backport/qfilesystementry.cpp
Normal file
388
src/app/core/backport/qfilesystementry.cpp
Normal file
|
@ -0,0 +1,388 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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 "qfilesystementry_p.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include "qfsfileengine_p.h"
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include <QStringBuilder>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
static bool isUncRoot(const QString &server)
|
||||||
|
{
|
||||||
|
QString localPath = QDir::toNativeSeparators(server);
|
||||||
|
if (!localPath.startsWith(QLatin1String("\\\\")))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int idx = localPath.indexOf(QLatin1Char('\\'), 2);
|
||||||
|
if (idx == -1 || idx + 1 == localPath.length())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
localPath = localPath.right(localPath.length() - idx - 1).trimmed();
|
||||||
|
return localPath.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline QString fixIfRelativeUncPath(const QString &path)
|
||||||
|
{
|
||||||
|
QString currentPath = QDir::currentPath();
|
||||||
|
if (currentPath.startsWith(QLatin1String("//")))
|
||||||
|
return currentPath % QChar(QLatin1Char('/')) % path;
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QFileSystemEntry::QFileSystemEntry()
|
||||||
|
: m_lastSeparator(-1),
|
||||||
|
m_firstDotInFileName(-1),
|
||||||
|
m_lastDotInFileName(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
Use this constructor when the path is supplied by user code, as it may contain a mix
|
||||||
|
of '/' and the native separator.
|
||||||
|
*/
|
||||||
|
QFileSystemEntry::QFileSystemEntry(const QString &filePath)
|
||||||
|
: m_filePath(QDir::fromNativeSeparators(filePath)),
|
||||||
|
m_lastSeparator(-2),
|
||||||
|
m_firstDotInFileName(-2),
|
||||||
|
m_lastDotInFileName(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
Use this constructor when the path is guaranteed to be in internal format, i.e. all
|
||||||
|
directory separators are '/' and not the native separator.
|
||||||
|
*/
|
||||||
|
QFileSystemEntry::QFileSystemEntry(const QString &filePath, FromInternalPath /* dummy */)
|
||||||
|
: m_filePath(filePath),
|
||||||
|
m_lastSeparator(-2),
|
||||||
|
m_firstDotInFileName(-2),
|
||||||
|
m_lastDotInFileName(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
Use this constructor when the path comes from a native API
|
||||||
|
*/
|
||||||
|
QFileSystemEntry::QFileSystemEntry(const NativePath &nativeFilePath, FromNativePath /* dummy */)
|
||||||
|
: m_nativeFilePath(nativeFilePath),
|
||||||
|
m_lastSeparator(-2),
|
||||||
|
m_firstDotInFileName(-2),
|
||||||
|
m_lastDotInFileName(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileSystemEntry::QFileSystemEntry(const QString &filePath, const NativePath &nativeFilePath)
|
||||||
|
: m_filePath(QDir::fromNativeSeparators(filePath)),
|
||||||
|
m_nativeFilePath(nativeFilePath),
|
||||||
|
m_lastSeparator(-2),
|
||||||
|
m_firstDotInFileName(-2),
|
||||||
|
m_lastDotInFileName(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFileSystemEntry::filePath() const
|
||||||
|
{
|
||||||
|
resolveFilePath();
|
||||||
|
return m_filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileSystemEntry::NativePath QFileSystemEntry::nativeFilePath() const
|
||||||
|
{
|
||||||
|
resolveNativeFilePath();
|
||||||
|
return m_nativeFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QFileSystemEntry::resolveFilePath() const
|
||||||
|
{
|
||||||
|
if (m_filePath.isEmpty() && !m_nativeFilePath.isEmpty()) {
|
||||||
|
#if defined(QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16)
|
||||||
|
m_filePath = QDir::fromNativeSeparators(m_nativeFilePath);
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
if (m_filePath.startsWith(QLatin1String("//?/UNC/")))
|
||||||
|
m_filePath = m_filePath.remove(2,6);
|
||||||
|
if (m_filePath.startsWith(QLatin1String("//?/")))
|
||||||
|
m_filePath = m_filePath.remove(0,4);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
m_filePath = QDir::fromNativeSeparators(QFile::decodeName(m_nativeFilePath));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QFileSystemEntry::resolveNativeFilePath() const
|
||||||
|
{
|
||||||
|
if (!m_filePath.isEmpty() && m_nativeFilePath.isEmpty()) {
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
QString filePath = m_filePath;
|
||||||
|
if (isRelative())
|
||||||
|
filePath = fixIfRelativeUncPath(m_filePath);
|
||||||
|
m_nativeFilePath = QFSFileEnginePrivate::longFileName(QDir::toNativeSeparators(filePath));
|
||||||
|
#elif defined(QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16)
|
||||||
|
m_nativeFilePath = QDir::toNativeSeparators(m_filePath);
|
||||||
|
#else
|
||||||
|
m_nativeFilePath = QFile::encodeName(QDir::toNativeSeparators(m_filePath));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFileSystemEntry::fileName() const
|
||||||
|
{
|
||||||
|
findLastSeparator();
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
|
||||||
|
return m_filePath.mid(2);
|
||||||
|
#endif
|
||||||
|
return m_filePath.mid(m_lastSeparator + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFileSystemEntry::path() const
|
||||||
|
{
|
||||||
|
findLastSeparator();
|
||||||
|
if (m_lastSeparator == -1) {
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
if (m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
|
||||||
|
return QFSFileEngine::currentPath(m_filePath.left(2));
|
||||||
|
#endif
|
||||||
|
return QString(QLatin1Char('.'));
|
||||||
|
}
|
||||||
|
if (m_lastSeparator == 0)
|
||||||
|
return QString(QLatin1Char('/'));
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
if (m_lastSeparator == 2 && m_filePath.at(1) == QLatin1Char(':'))
|
||||||
|
return m_filePath.left(m_lastSeparator + 1);
|
||||||
|
#endif
|
||||||
|
return m_filePath.left(m_lastSeparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFileSystemEntry::baseName() const
|
||||||
|
{
|
||||||
|
findFileNameSeparators();
|
||||||
|
int length = -1;
|
||||||
|
if (m_firstDotInFileName >= 0) {
|
||||||
|
length = m_firstDotInFileName;
|
||||||
|
if (m_lastSeparator != -1) // avoid off by one
|
||||||
|
length--;
|
||||||
|
}
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
|
||||||
|
return m_filePath.mid(2, length - 2);
|
||||||
|
#endif
|
||||||
|
return m_filePath.mid(m_lastSeparator + 1, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFileSystemEntry::completeBaseName() const
|
||||||
|
{
|
||||||
|
findFileNameSeparators();
|
||||||
|
int length = -1;
|
||||||
|
if (m_firstDotInFileName >= 0) {
|
||||||
|
length = m_firstDotInFileName + m_lastDotInFileName;
|
||||||
|
if (m_lastSeparator != -1) // avoid off by one
|
||||||
|
length--;
|
||||||
|
}
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
|
||||||
|
return m_filePath.mid(2, length - 2);
|
||||||
|
#endif
|
||||||
|
return m_filePath.mid(m_lastSeparator + 1, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFileSystemEntry::suffix() const
|
||||||
|
{
|
||||||
|
findFileNameSeparators();
|
||||||
|
|
||||||
|
if (m_lastDotInFileName == -1)
|
||||||
|
return QString();
|
||||||
|
|
||||||
|
return m_filePath.mid(qMax((qint16)0, m_lastSeparator) + m_firstDotInFileName + m_lastDotInFileName + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFileSystemEntry::completeSuffix() const
|
||||||
|
{
|
||||||
|
findFileNameSeparators();
|
||||||
|
if (m_firstDotInFileName == -1)
|
||||||
|
return QString();
|
||||||
|
|
||||||
|
return m_filePath.mid(qMax((qint16)0, m_lastSeparator) + m_firstDotInFileName + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
bool QFileSystemEntry::isRelative() const
|
||||||
|
{
|
||||||
|
resolveFilePath();
|
||||||
|
return (m_filePath.isEmpty() || (!m_filePath.isEmpty() && (m_filePath[0].unicode() != '/')
|
||||||
|
&& (!(m_filePath.length() >= 2 && m_filePath[1].unicode() == ':'))));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFileSystemEntry::isAbsolute() const
|
||||||
|
{
|
||||||
|
resolveFilePath();
|
||||||
|
return (!m_filePath.isEmpty() && ((m_filePath.length() >= 3
|
||||||
|
&& (m_filePath[0].isLetter() && m_filePath[1].unicode() == ':' && m_filePath[2].unicode() == '/'))
|
||||||
|
|| (m_filePath.length() >= 2 && (m_filePath.at(0) == QLatin1Char('/') && m_filePath.at(1) == QLatin1Char('/')))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
bool QFileSystemEntry::isRelative() const
|
||||||
|
{
|
||||||
|
return !isAbsolute();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFileSystemEntry::isAbsolute() const
|
||||||
|
{
|
||||||
|
resolveFilePath();
|
||||||
|
return (!m_filePath.isEmpty() && (m_filePath[0].unicode() == '/'));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
bool QFileSystemEntry::isDriveRoot() const
|
||||||
|
{
|
||||||
|
resolveFilePath();
|
||||||
|
return (m_filePath.length() == 3
|
||||||
|
&& m_filePath.at(0).isLetter() && m_filePath.at(1) == QLatin1Char(':')
|
||||||
|
&& m_filePath.at(2) == QLatin1Char('/'));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool QFileSystemEntry::isRoot() const
|
||||||
|
{
|
||||||
|
resolveFilePath();
|
||||||
|
if (m_filePath == QLatin1String("/")
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
|| isDriveRoot()
|
||||||
|
|| isUncRoot(m_filePath)
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFileSystemEntry::isEmpty() const
|
||||||
|
{
|
||||||
|
return m_filePath.isEmpty() && m_nativeFilePath.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// private methods
|
||||||
|
|
||||||
|
void QFileSystemEntry::findLastSeparator() const
|
||||||
|
{
|
||||||
|
if (m_lastSeparator == -2) {
|
||||||
|
resolveFilePath();
|
||||||
|
m_lastSeparator = -1;
|
||||||
|
for (int i = m_filePath.size() - 1; i >= 0; --i) {
|
||||||
|
if (m_filePath[i].unicode() == '/') {
|
||||||
|
m_lastSeparator = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QFileSystemEntry::findFileNameSeparators() const
|
||||||
|
{
|
||||||
|
if (m_firstDotInFileName == -2) {
|
||||||
|
resolveFilePath();
|
||||||
|
int firstDotInFileName = -1;
|
||||||
|
int lastDotInFileName = -1;
|
||||||
|
int lastSeparator = m_lastSeparator;
|
||||||
|
|
||||||
|
int stop;
|
||||||
|
if (lastSeparator < 0) {
|
||||||
|
lastSeparator = -1;
|
||||||
|
stop = 0;
|
||||||
|
} else {
|
||||||
|
stop = lastSeparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = m_filePath.size() - 1;
|
||||||
|
for (; i >= stop; --i) {
|
||||||
|
if (m_filePath[i].unicode() == '.') {
|
||||||
|
firstDotInFileName = lastDotInFileName = i;
|
||||||
|
break;
|
||||||
|
} else if (m_filePath[i].unicode() == '/') {
|
||||||
|
lastSeparator = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastSeparator != i) {
|
||||||
|
for (--i; i >= stop; --i) {
|
||||||
|
if (m_filePath[i].unicode() == '.')
|
||||||
|
firstDotInFileName = i;
|
||||||
|
else if (m_filePath[i].unicode() == '/') {
|
||||||
|
lastSeparator = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_lastSeparator = lastSeparator;
|
||||||
|
m_firstDotInFileName = firstDotInFileName == -1 ? -1 : firstDotInFileName - qMax(0, lastSeparator);
|
||||||
|
if (lastDotInFileName == -1)
|
||||||
|
m_lastDotInFileName = -1;
|
||||||
|
else if (firstDotInFileName == lastDotInFileName)
|
||||||
|
m_lastDotInFileName = 0;
|
||||||
|
else
|
||||||
|
m_lastDotInFileName = lastDotInFileName - firstDotInFileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFileSystemEntry::isClean() const
|
||||||
|
{
|
||||||
|
resolveFilePath();
|
||||||
|
int dots = 0;
|
||||||
|
bool dotok = true; // checking for ".." or "." starts to relative paths
|
||||||
|
bool slashok = true;
|
||||||
|
for (QString::const_iterator iter = m_filePath.constBegin(); iter != m_filePath.constEnd(); iter++) {
|
||||||
|
if (*iter == QLatin1Char('/')) {
|
||||||
|
if (dots == 1 || dots == 2)
|
||||||
|
return false; // path contains "./" or "../"
|
||||||
|
if (!slashok)
|
||||||
|
return false; // path contains "//"
|
||||||
|
dots = 0;
|
||||||
|
dotok = true;
|
||||||
|
slashok = false;
|
||||||
|
} else if (dotok) {
|
||||||
|
slashok = true;
|
||||||
|
if (*iter == QLatin1Char('.')) {
|
||||||
|
dots++;
|
||||||
|
if (dots > 2)
|
||||||
|
dotok = false;
|
||||||
|
} else {
|
||||||
|
//path element contains a character other than '.', it's clean
|
||||||
|
dots = 0;
|
||||||
|
dotok = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (dots != 1 && dots != 2); // clean if path doesn't end in . or ..
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
106
src/app/core/backport/qfilesystementry_p.h
Normal file
106
src/app/core/backport/qfilesystementry_p.h
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QFILESYSTEMENTRY_P_H
|
||||||
|
#define QFILESYSTEMENTRY_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists purely as an
|
||||||
|
// implementation detail. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QByteArray>
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
#define QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class QFileSystemEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
#ifndef QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16
|
||||||
|
typedef QByteArray NativePath;
|
||||||
|
#else
|
||||||
|
typedef QString NativePath;
|
||||||
|
#endif
|
||||||
|
struct FromNativePath{};
|
||||||
|
struct FromInternalPath{};
|
||||||
|
|
||||||
|
QFileSystemEntry();
|
||||||
|
explicit QFileSystemEntry(const QString &filePath);
|
||||||
|
|
||||||
|
QFileSystemEntry(const QString &filePath, FromInternalPath dummy);
|
||||||
|
QFileSystemEntry(const NativePath &nativeFilePath, FromNativePath dummy);
|
||||||
|
QFileSystemEntry(const QString &filePath, const NativePath &nativeFilePath);
|
||||||
|
|
||||||
|
QString filePath() const;
|
||||||
|
QString fileName() const;
|
||||||
|
QString path() const;
|
||||||
|
NativePath nativeFilePath() const;
|
||||||
|
QString baseName() const;
|
||||||
|
QString completeBaseName() const;
|
||||||
|
QString suffix() const;
|
||||||
|
QString completeSuffix() const;
|
||||||
|
bool isAbsolute() const;
|
||||||
|
bool isRelative() const;
|
||||||
|
bool isClean() const;
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
bool isDriveRoot() const;
|
||||||
|
#endif
|
||||||
|
bool isRoot() const;
|
||||||
|
|
||||||
|
bool isEmpty() const;
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
*this = QFileSystemEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// creates the QString version out of the bytearray version
|
||||||
|
void resolveFilePath() const;
|
||||||
|
// creates the bytearray version out of the QString version
|
||||||
|
void resolveNativeFilePath() const;
|
||||||
|
// resolves the separator
|
||||||
|
void findLastSeparator() const;
|
||||||
|
// resolves the dots and the separator
|
||||||
|
void findFileNameSeparators() const;
|
||||||
|
|
||||||
|
mutable QString m_filePath; // always has slashes as separator
|
||||||
|
mutable NativePath m_nativeFilePath; // native encoding and separators
|
||||||
|
|
||||||
|
mutable qint16 m_lastSeparator; // index in m_filePath of last separator
|
||||||
|
mutable qint16 m_firstDotInFileName; // index after m_filePath for first dot (.)
|
||||||
|
mutable qint16 m_lastDotInFileName; // index after m_firstDotInFileName for last dot (.)
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif // include guard
|
94
src/app/core/backport/qfilesystemiterator_p.h
Normal file
94
src/app/core/backport/qfilesystemiterator_p.h
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QFILESYSTEMITERATOR_P_H
|
||||||
|
#define QFILESYSTEMITERATOR_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists purely as an
|
||||||
|
// implementation detail. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#ifndef QT_NO_FILESYSTEMITERATOR
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QDirIterator>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include "qfilesystementry_p.h"
|
||||||
|
#include "qfilesystemmetadata_p.h"
|
||||||
|
|
||||||
|
// Platform-specific headers
|
||||||
|
#if !defined(Q_OS_WIN)
|
||||||
|
#include <QScopedPointer>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class QFileSystemIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters,
|
||||||
|
const QStringList &nameFilters, QDirIterator::IteratorFlags flags
|
||||||
|
= QDirIterator::FollowSymlinks | QDirIterator::Subdirectories);
|
||||||
|
~QFileSystemIterator();
|
||||||
|
|
||||||
|
bool advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QFileSystemEntry::NativePath nativePath;
|
||||||
|
|
||||||
|
// Platform-specific data
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
QString dirPath;
|
||||||
|
HANDLE findFileHandle;
|
||||||
|
QStringList uncShares;
|
||||||
|
bool uncFallback;
|
||||||
|
int uncShareIndex;
|
||||||
|
bool onlyDirs;
|
||||||
|
#else
|
||||||
|
QT_DIR *dir;
|
||||||
|
QT_DIRENT *dirEntry;
|
||||||
|
#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN)
|
||||||
|
// for readdir_r
|
||||||
|
QScopedPointer<QT_DIRENT, QScopedPointerPodDeleter> mt_file;
|
||||||
|
#if defined(Q_OS_QNX) && defined(__EXT_QNX__READDIR_R)
|
||||||
|
// for _readdir_r
|
||||||
|
size_t direntSize;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
int lastError;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Q_DISABLE_COPY(QFileSystemIterator)
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QT_NO_FILESYSTEMITERATOR
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif // include guard
|
112
src/app/core/backport/qfilesystemiterator_unix.cpp
Normal file
112
src/app/core/backport/qfilesystemiterator_unix.cpp
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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 "qplatformdefs.h"
|
||||||
|
#include "qfilesystemiterator_p.h"
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#ifndef QT_NO_FILESYSTEMITERATOR
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters,
|
||||||
|
const QStringList &nameFilters, QDirIterator::IteratorFlags flags)
|
||||||
|
: nativePath(entry.nativeFilePath())
|
||||||
|
, dir(0)
|
||||||
|
, dirEntry(0)
|
||||||
|
#if defined(Q_OS_QNX) && defined(__EXT_QNX__READDIR_R)
|
||||||
|
, direntSize(0)
|
||||||
|
#endif
|
||||||
|
, lastError(0)
|
||||||
|
{
|
||||||
|
Q_UNUSED(filters)
|
||||||
|
Q_UNUSED(nameFilters)
|
||||||
|
Q_UNUSED(flags)
|
||||||
|
|
||||||
|
if ((dir = QT_OPENDIR(nativePath.constData())) == 0) {
|
||||||
|
lastError = errno;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (!nativePath.endsWith('/'))
|
||||||
|
nativePath.append('/');
|
||||||
|
|
||||||
|
#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN)
|
||||||
|
// ### Race condition; we should use fpathconf and dirfd().
|
||||||
|
size_t maxPathName = ::pathconf(nativePath.constData(), _PC_NAME_MAX);
|
||||||
|
if (maxPathName == size_t(-1))
|
||||||
|
maxPathName = FILENAME_MAX;
|
||||||
|
maxPathName += sizeof(QT_DIRENT) + 1;
|
||||||
|
|
||||||
|
QT_DIRENT *p = reinterpret_cast<QT_DIRENT*>(::malloc(maxPathName));
|
||||||
|
Q_CHECK_PTR(p);
|
||||||
|
|
||||||
|
mt_file.reset(p);
|
||||||
|
#if defined(Q_OS_QNX) && defined(__EXT_QNX__READDIR_R)
|
||||||
|
direntSize = maxPathName;
|
||||||
|
|
||||||
|
// Include extra stat information in the readdir() call (d_stat member of dirent_extra_stat).
|
||||||
|
// This is used in QFileSystemMetaData::fillFromDirEnt() to avoid extra stat() calls when iterating
|
||||||
|
// over directories
|
||||||
|
if (dircntl(dir, D_SETFLAG, D_FLAG_STAT) == -1)
|
||||||
|
lastError = errno;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileSystemIterator::~QFileSystemIterator()
|
||||||
|
{
|
||||||
|
if (dir)
|
||||||
|
QT_CLOSEDIR(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData)
|
||||||
|
{
|
||||||
|
if (!dir)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#if defined(Q_OS_QNX) && defined(__EXT_QNX__READDIR_R)
|
||||||
|
lastError = _readdir_r(dir, mt_file.data(), &dirEntry, direntSize);
|
||||||
|
if (lastError)
|
||||||
|
return false;
|
||||||
|
#elif defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN)
|
||||||
|
lastError = QT_READDIR_R(dir, mt_file.data(), &dirEntry);
|
||||||
|
if (lastError)
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
// ### add local lock to prevent breaking reentrancy
|
||||||
|
dirEntry = QT_READDIR(dir);
|
||||||
|
#endif // _POSIX_THREAD_SAFE_FUNCTIONS
|
||||||
|
|
||||||
|
if (dirEntry) {
|
||||||
|
fileEntry = QFileSystemEntry(nativePath + QByteArray(dirEntry->d_name), QFileSystemEntry::FromNativePath());
|
||||||
|
metaData.fillFromDirEnt(*dirEntry);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastError = errno;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif // QT_NO_FILESYSTEMITERATOR
|
129
src/app/core/backport/qfilesystemiterator_win.cpp
Normal file
129
src/app/core/backport/qfilesystemiterator_win.cpp
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#if _WIN32_WINNT < 0x0500
|
||||||
|
#undef _WIN32_WINNT
|
||||||
|
#define _WIN32_WINNT 0x0500
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "qfilesystemiterator_p.h"
|
||||||
|
#include "qfilesystemengine_p.h"
|
||||||
|
#include "qplatformdefs.h"
|
||||||
|
|
||||||
|
#include <qt_windows.h>
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
bool done = true;
|
||||||
|
|
||||||
|
QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters,
|
||||||
|
const QStringList &nameFilters, QDirIterator::IteratorFlags flags)
|
||||||
|
: nativePath(entry.nativeFilePath())
|
||||||
|
, dirPath(entry.filePath())
|
||||||
|
, findFileHandle(INVALID_HANDLE_VALUE)
|
||||||
|
, uncFallback(false)
|
||||||
|
, uncShareIndex(0)
|
||||||
|
, onlyDirs(false)
|
||||||
|
{
|
||||||
|
Q_UNUSED(nameFilters)
|
||||||
|
Q_UNUSED(flags)
|
||||||
|
if (nativePath.endsWith(QLatin1String(".lnk"))) {
|
||||||
|
QFileSystemMetaData metaData;
|
||||||
|
QFileSystemEntry link = QFileSystemEngine::getLinkTarget(entry, metaData);
|
||||||
|
nativePath = link.nativeFilePath();
|
||||||
|
}
|
||||||
|
if (!nativePath.endsWith(QLatin1Char('\\')))
|
||||||
|
nativePath.append(QLatin1Char('\\'));
|
||||||
|
nativePath.append(QLatin1Char('*'));
|
||||||
|
if (!dirPath.endsWith(QLatin1Char('/')))
|
||||||
|
dirPath.append(QLatin1Char('/'));
|
||||||
|
if ((filters & (QDir::Dirs|QDir::Drives)) && (!(filters & (QDir::Files))))
|
||||||
|
onlyDirs = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileSystemIterator::~QFileSystemIterator()
|
||||||
|
{
|
||||||
|
if (findFileHandle != INVALID_HANDLE_VALUE)
|
||||||
|
FindClose(findFileHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData)
|
||||||
|
{
|
||||||
|
bool haveData = false;
|
||||||
|
WIN32_FIND_DATA findData;
|
||||||
|
|
||||||
|
if (findFileHandle == INVALID_HANDLE_VALUE && !uncFallback) {
|
||||||
|
haveData = true;
|
||||||
|
int infoLevel = 0 ; // FindExInfoStandard;
|
||||||
|
DWORD dwAdditionalFlags = 0;
|
||||||
|
#ifndef Q_OS_WINCE
|
||||||
|
if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) {
|
||||||
|
dwAdditionalFlags = 2; // FIND_FIRST_EX_LARGE_FETCH
|
||||||
|
infoLevel = 1 ; // FindExInfoBasic;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
int searchOps = 0; // FindExSearchNameMatch
|
||||||
|
if (onlyDirs)
|
||||||
|
searchOps = 1 ; // FindExSearchLimitToDirectories
|
||||||
|
findFileHandle = FindFirstFileEx((const wchar_t *)nativePath.utf16(), FINDEX_INFO_LEVELS(infoLevel), &findData,
|
||||||
|
FINDEX_SEARCH_OPS(searchOps), 0, dwAdditionalFlags);
|
||||||
|
if (findFileHandle == INVALID_HANDLE_VALUE) {
|
||||||
|
if (nativePath.startsWith(QLatin1String("\\\\?\\UNC\\"))) {
|
||||||
|
QStringList parts = nativePath.split(QLatin1Char('\\'), QString::SkipEmptyParts);
|
||||||
|
if (parts.count() == 4 && QFileSystemEngine::uncListSharesOnServer(
|
||||||
|
QLatin1String("\\\\") + parts.at(2), &uncShares)) {
|
||||||
|
if (uncShares.isEmpty())
|
||||||
|
return false; // No shares found in the server
|
||||||
|
else
|
||||||
|
uncFallback = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (findFileHandle == INVALID_HANDLE_VALUE && !uncFallback)
|
||||||
|
return false;
|
||||||
|
// Retrieve the new file information.
|
||||||
|
if (!haveData) {
|
||||||
|
if (uncFallback) {
|
||||||
|
if (++uncShareIndex >= uncShares.count())
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (!FindNextFile(findFileHandle, &findData))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Create the new file system entry & meta data.
|
||||||
|
if (uncFallback) {
|
||||||
|
fileEntry = QFileSystemEntry(dirPath + uncShares.at(uncShareIndex));
|
||||||
|
metaData.fillFromFileAttribute(FILE_ATTRIBUTE_DIRECTORY);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
QString fileName = QString::fromWCharArray(findData.cFileName);
|
||||||
|
fileEntry = QFileSystemEntry(dirPath + fileName);
|
||||||
|
metaData = QFileSystemMetaData();
|
||||||
|
if (!fileName.endsWith(QLatin1String(".lnk"))) {
|
||||||
|
metaData.fillFromFindData(findData, true);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
341
src/app/core/backport/qfilesystemmetadata_p.h
Normal file
341
src/app/core/backport/qfilesystemmetadata_p.h
Normal file
|
@ -0,0 +1,341 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QFILESYSTEMMETADATA_P_H
|
||||||
|
#define QFILESYSTEMMETADATA_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists purely as an
|
||||||
|
// implementation detail. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "qplatformdefs.h"
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include "qabstractfileengine_p.h"
|
||||||
|
|
||||||
|
// Platform-specific includes
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
# include <QtCore/qt_windows.h>
|
||||||
|
# ifndef IO_REPARSE_TAG_SYMLINK
|
||||||
|
# define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
class QFileSystemEngine;
|
||||||
|
|
||||||
|
class QFileSystemMetaData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QFileSystemMetaData()
|
||||||
|
: knownFlagsMask(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MetaDataFlag {
|
||||||
|
// Permissions, overlaps with QFile::Permissions
|
||||||
|
OtherReadPermission = 0x00000004, OtherWritePermission = 0x00000002, OtherExecutePermission = 0x00000001,
|
||||||
|
GroupReadPermission = 0x00000040, GroupWritePermission = 0x00000020, GroupExecutePermission = 0x00000010,
|
||||||
|
UserReadPermission = 0x00000400, UserWritePermission = 0x00000200, UserExecutePermission = 0x00000100,
|
||||||
|
OwnerReadPermission = 0x00004000, OwnerWritePermission = 0x00002000, OwnerExecutePermission = 0x00001000,
|
||||||
|
|
||||||
|
OtherPermissions = OtherReadPermission | OtherWritePermission | OtherExecutePermission,
|
||||||
|
GroupPermissions = GroupReadPermission | GroupWritePermission | GroupExecutePermission,
|
||||||
|
UserPermissions = UserReadPermission | UserWritePermission | UserExecutePermission,
|
||||||
|
OwnerPermissions = OwnerReadPermission | OwnerWritePermission | OwnerExecutePermission,
|
||||||
|
|
||||||
|
ReadPermissions = OtherReadPermission | GroupReadPermission | UserReadPermission | OwnerReadPermission,
|
||||||
|
WritePermissions = OtherWritePermission | GroupWritePermission | UserWritePermission | OwnerWritePermission,
|
||||||
|
ExecutePermissions = OtherExecutePermission | GroupExecutePermission | UserExecutePermission | OwnerExecutePermission,
|
||||||
|
|
||||||
|
Permissions = OtherPermissions | GroupPermissions | UserPermissions | OwnerPermissions,
|
||||||
|
|
||||||
|
// Type
|
||||||
|
LinkType = 0x00010000,
|
||||||
|
FileType = 0x00020000,
|
||||||
|
DirectoryType = 0x00040000,
|
||||||
|
#if defined(Q_OS_MACX)
|
||||||
|
BundleType = 0x00080000,
|
||||||
|
AliasType = 0x08000000,
|
||||||
|
#else
|
||||||
|
BundleType = 0x0,
|
||||||
|
AliasType = 0x0,
|
||||||
|
#endif
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
WinLnkType = 0x08000000, // Note: Uses the same position for AliasType on Mac
|
||||||
|
#else
|
||||||
|
WinLnkType = 0x0,
|
||||||
|
#endif
|
||||||
|
SequentialType = 0x00800000, // Note: overlaps with QAbstractFileEngine::RootFlag
|
||||||
|
|
||||||
|
LegacyLinkType = LinkType | AliasType | WinLnkType,
|
||||||
|
|
||||||
|
Type = LinkType | FileType | DirectoryType | BundleType | SequentialType | AliasType,
|
||||||
|
|
||||||
|
// Attributes
|
||||||
|
HiddenAttribute = 0x00100000,
|
||||||
|
SizeAttribute = 0x00200000, // Note: overlaps with QAbstractFileEngine::LocalDiskFlag
|
||||||
|
ExistsAttribute = 0x00400000,
|
||||||
|
|
||||||
|
Attributes = HiddenAttribute | SizeAttribute | ExistsAttribute,
|
||||||
|
|
||||||
|
// Times
|
||||||
|
CreationTime = 0x01000000, // Note: overlaps with QAbstractFileEngine::Refresh
|
||||||
|
ModificationTime = 0x02000000,
|
||||||
|
AccessTime = 0x04000000,
|
||||||
|
|
||||||
|
Times = CreationTime | ModificationTime | AccessTime,
|
||||||
|
|
||||||
|
// Owner IDs
|
||||||
|
UserId = 0x10000000,
|
||||||
|
GroupId = 0x20000000,
|
||||||
|
|
||||||
|
OwnerIds = UserId | GroupId,
|
||||||
|
|
||||||
|
PosixStatFlags = QFileSystemMetaData::OtherPermissions
|
||||||
|
| QFileSystemMetaData::GroupPermissions
|
||||||
|
| QFileSystemMetaData::OwnerPermissions
|
||||||
|
| QFileSystemMetaData::FileType
|
||||||
|
| QFileSystemMetaData::DirectoryType
|
||||||
|
| QFileSystemMetaData::SequentialType
|
||||||
|
| QFileSystemMetaData::SizeAttribute
|
||||||
|
| QFileSystemMetaData::Times
|
||||||
|
| QFileSystemMetaData::OwnerIds,
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
WinStatFlags = QFileSystemMetaData::FileType
|
||||||
|
| QFileSystemMetaData::DirectoryType
|
||||||
|
| QFileSystemMetaData::HiddenAttribute
|
||||||
|
| QFileSystemMetaData::ExistsAttribute
|
||||||
|
| QFileSystemMetaData::SizeAttribute
|
||||||
|
| QFileSystemMetaData::Times,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
AllMetaDataFlags = 0xFFFFFFFF
|
||||||
|
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(MetaDataFlags, MetaDataFlag)
|
||||||
|
|
||||||
|
bool hasFlags(MetaDataFlags flags) const
|
||||||
|
{
|
||||||
|
return ((knownFlagsMask & flags) == flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaDataFlags missingFlags(MetaDataFlags flags)
|
||||||
|
{
|
||||||
|
return flags & ~knownFlagsMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
knownFlagsMask = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearFlags(MetaDataFlags flags = AllMetaDataFlags)
|
||||||
|
{
|
||||||
|
knownFlagsMask &= ~flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool exists() const { return (entryFlags & ExistsAttribute); }
|
||||||
|
|
||||||
|
bool isLink() const { return (entryFlags & LinkType); }
|
||||||
|
bool isFile() const { return (entryFlags & FileType); }
|
||||||
|
bool isDirectory() const { return (entryFlags & DirectoryType); }
|
||||||
|
bool isBundle() const;
|
||||||
|
bool isAlias() const;
|
||||||
|
bool isLegacyLink() const { return (entryFlags & LegacyLinkType); }
|
||||||
|
bool isSequential() const { return (entryFlags & SequentialType); }
|
||||||
|
bool isHidden() const { return (entryFlags & HiddenAttribute); }
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
bool isLnkFile() const { return (entryFlags & WinLnkType); }
|
||||||
|
#else
|
||||||
|
bool isLnkFile() const { return false; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
qint64 size() const { return size_; }
|
||||||
|
|
||||||
|
QFile::Permissions permissions() const { return QFile::Permissions(Permissions & entryFlags); }
|
||||||
|
|
||||||
|
QDateTime creationTime() const;
|
||||||
|
QDateTime modificationTime() const;
|
||||||
|
QDateTime accessTime() const;
|
||||||
|
|
||||||
|
QDateTime fileTime(QAbstractFileEngine::FileTime time) const;
|
||||||
|
uint userId() const;
|
||||||
|
uint groupId() const;
|
||||||
|
uint ownerId(QAbstractFileEngine::FileOwner owner) const;
|
||||||
|
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
void fillFromStatBuf(const QT_STATBUF &statBuffer);
|
||||||
|
void fillFromDirEnt(const QT_DIRENT &statBuffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
inline void fillFromFileAttribute(DWORD fileAttribute, bool isDriveRoot = false);
|
||||||
|
inline void fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType = false, bool isDriveRoot = false);
|
||||||
|
inline void fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo);
|
||||||
|
#endif
|
||||||
|
private:
|
||||||
|
friend class QFileSystemEngine;
|
||||||
|
|
||||||
|
MetaDataFlags knownFlagsMask;
|
||||||
|
MetaDataFlags entryFlags;
|
||||||
|
|
||||||
|
qint64 size_;
|
||||||
|
|
||||||
|
// Platform-specific data goes here:
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
DWORD fileAttribute_;
|
||||||
|
FILETIME creationTime_;
|
||||||
|
FILETIME lastAccessTime_;
|
||||||
|
FILETIME lastWriteTime_;
|
||||||
|
#else
|
||||||
|
time_t creationTime_;
|
||||||
|
time_t modificationTime_;
|
||||||
|
time_t accessTime_;
|
||||||
|
|
||||||
|
uint userId_;
|
||||||
|
uint groupId_;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemMetaData::MetaDataFlags)
|
||||||
|
|
||||||
|
#if defined(Q_OS_MACX)
|
||||||
|
inline bool QFileSystemMetaData::isBundle() const { return (entryFlags & BundleType); }
|
||||||
|
inline bool QFileSystemMetaData::isAlias() const { return (entryFlags & AliasType); }
|
||||||
|
#else
|
||||||
|
inline bool QFileSystemMetaData::isBundle() const { return false; }
|
||||||
|
inline bool QFileSystemMetaData::isAlias() const { return false; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(Q_OS_UNIX) || defined (Q_OS_WIN)
|
||||||
|
inline QDateTime QFileSystemMetaData::fileTime(QAbstractFileEngine::FileTime time) const
|
||||||
|
{
|
||||||
|
switch (time) {
|
||||||
|
case QAbstractFileEngine::ModificationTime:
|
||||||
|
return modificationTime();
|
||||||
|
|
||||||
|
case QAbstractFileEngine::AccessTime:
|
||||||
|
return accessTime();
|
||||||
|
|
||||||
|
case QAbstractFileEngine::CreationTime:
|
||||||
|
return creationTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QDateTime();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(Q_OS_UNIX)
|
||||||
|
inline QDateTime QFileSystemMetaData::creationTime() const { return QDateTime::fromTime_t(creationTime_); }
|
||||||
|
inline QDateTime QFileSystemMetaData::modificationTime() const { return QDateTime::fromTime_t(modificationTime_); }
|
||||||
|
inline QDateTime QFileSystemMetaData::accessTime() const { return QDateTime::fromTime_t(accessTime_); }
|
||||||
|
|
||||||
|
inline uint QFileSystemMetaData::userId() const { return userId_; }
|
||||||
|
inline uint QFileSystemMetaData::groupId() const { return groupId_; }
|
||||||
|
|
||||||
|
inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const
|
||||||
|
{
|
||||||
|
if (owner == QAbstractFileEngine::OwnerUser)
|
||||||
|
return userId();
|
||||||
|
else
|
||||||
|
return groupId();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
inline uint QFileSystemMetaData::userId() const { return (uint) -2; }
|
||||||
|
inline uint QFileSystemMetaData::groupId() const { return (uint) -2; }
|
||||||
|
inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const
|
||||||
|
{
|
||||||
|
if (owner == QAbstractFileEngine::OwnerUser)
|
||||||
|
return userId();
|
||||||
|
else
|
||||||
|
return groupId();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void QFileSystemMetaData::fillFromFileAttribute(DWORD fileAttribute,bool isDriveRoot)
|
||||||
|
{
|
||||||
|
fileAttribute_ = fileAttribute;
|
||||||
|
// Ignore the hidden attribute for drives.
|
||||||
|
if (!isDriveRoot && (fileAttribute_ & FILE_ATTRIBUTE_HIDDEN))
|
||||||
|
entryFlags |= HiddenAttribute;
|
||||||
|
entryFlags |= ((fileAttribute & FILE_ATTRIBUTE_DIRECTORY) ? DirectoryType: FileType);
|
||||||
|
entryFlags |= ExistsAttribute;
|
||||||
|
knownFlagsMask |= FileType | DirectoryType | HiddenAttribute | ExistsAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType, bool isDriveRoot)
|
||||||
|
{
|
||||||
|
fillFromFileAttribute(findData.dwFileAttributes, isDriveRoot);
|
||||||
|
creationTime_ = findData.ftCreationTime;
|
||||||
|
lastAccessTime_ = findData.ftLastAccessTime;
|
||||||
|
lastWriteTime_ = findData.ftLastWriteTime;
|
||||||
|
if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
|
||||||
|
size_ = 0;
|
||||||
|
} else {
|
||||||
|
size_ = findData.nFileSizeHigh;
|
||||||
|
size_ <<= 32;
|
||||||
|
size_ += findData.nFileSizeLow;
|
||||||
|
}
|
||||||
|
knownFlagsMask |= Times | SizeAttribute;
|
||||||
|
if (setLinkType) {
|
||||||
|
knownFlagsMask |= LinkType;
|
||||||
|
entryFlags &= ~LinkType;
|
||||||
|
#if !defined(Q_OS_WINCE)
|
||||||
|
if ((fileAttribute_ & FILE_ATTRIBUTE_REPARSE_POINT)
|
||||||
|
&& (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
|
||||||
|
entryFlags |= LinkType;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void QFileSystemMetaData::fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo)
|
||||||
|
{
|
||||||
|
fillFromFileAttribute(fileInfo.dwFileAttributes);
|
||||||
|
creationTime_ = fileInfo.ftCreationTime;
|
||||||
|
lastAccessTime_ = fileInfo.ftLastAccessTime;
|
||||||
|
lastWriteTime_ = fileInfo.ftLastWriteTime;
|
||||||
|
if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
|
||||||
|
size_ = 0;
|
||||||
|
} else {
|
||||||
|
size_ = fileInfo.nFileSizeHigh;
|
||||||
|
size_ <<= 32;
|
||||||
|
size_ += fileInfo.nFileSizeLow;
|
||||||
|
}
|
||||||
|
knownFlagsMask |= Times | SizeAttribute;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif // include guard
|
942
src/app/core/backport/qfsfileengine.cpp
Normal file
942
src/app/core/backport/qfsfileengine.cpp
Normal file
|
@ -0,0 +1,942 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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 "qfsfileengine_p.h"
|
||||||
|
#include "qfsfileengine_iterator_p.h"
|
||||||
|
#include "qfilesystemengine_p.h"
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QDirIterator>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#ifndef QT_NO_FSFILEENGINE
|
||||||
|
|
||||||
|
#if !defined(Q_OS_WINCE)
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
#if defined(Q_OS_UNIX)
|
||||||
|
#include "qcore_unix_p.h"
|
||||||
|
#endif
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#if defined(Q_OS_MAC)
|
||||||
|
# include "qcore_mac_p.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
# ifndef S_ISREG
|
||||||
|
# define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
|
||||||
|
# endif
|
||||||
|
# ifndef S_ISCHR
|
||||||
|
# define S_ISCHR(x) (((x) & S_IFMT) == S_IFCHR)
|
||||||
|
# endif
|
||||||
|
# ifndef S_ISFIFO
|
||||||
|
# define S_ISFIFO(x) false
|
||||||
|
# endif
|
||||||
|
# ifndef S_ISSOCK
|
||||||
|
# define S_ISSOCK(x) false
|
||||||
|
# endif
|
||||||
|
# ifndef INVALID_FILE_ATTRIBUTES
|
||||||
|
# define INVALID_FILE_ATTRIBUTES (DWORD (-1))
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! \class QFSFileEngine
|
||||||
|
\inmodule QtCore
|
||||||
|
\brief The QFSFileEngine class implements Qt's default file engine.
|
||||||
|
\since 4.1
|
||||||
|
\internal
|
||||||
|
|
||||||
|
This class is part of the file engine framework in Qt. If you only want to
|
||||||
|
access files or directories, use QFile, QFileInfo or QDir instead.
|
||||||
|
|
||||||
|
QFSFileEngine is the default file engine for accessing regular files. It
|
||||||
|
is provided for convenience; by subclassing this class, you can alter its
|
||||||
|
behavior slightly, without having to write a complete QAbstractFileEngine
|
||||||
|
subclass. To install your custom file engine, you must also subclass
|
||||||
|
QAbstractFileEngineHandler and create an instance of your handler.
|
||||||
|
|
||||||
|
It can also be useful to create a QFSFileEngine object directly if you
|
||||||
|
need to use the local file system inside QAbstractFileEngine::create(), in
|
||||||
|
order to avoid recursion (as higher-level classes tend to call
|
||||||
|
QAbstractFileEngine::create()).
|
||||||
|
*/
|
||||||
|
|
||||||
|
//**************** QFSFileEnginePrivate
|
||||||
|
QFSFileEnginePrivate::QFSFileEnginePrivate() : QAbstractFileEnginePrivate()
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
void QFSFileEnginePrivate::init()
|
||||||
|
{
|
||||||
|
is_sequential = 0;
|
||||||
|
tried_stat = 0;
|
||||||
|
#if !defined(Q_OS_WINCE)
|
||||||
|
need_lstat = 1;
|
||||||
|
is_link = 0;
|
||||||
|
#endif
|
||||||
|
openMode = QIODevice::NotOpen;
|
||||||
|
fd = -1;
|
||||||
|
fh = 0;
|
||||||
|
lastIOCommand = IOFlushCommand;
|
||||||
|
lastFlushFailed = false;
|
||||||
|
closeFileHandle = false;
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
fileAttrib = INVALID_FILE_ATTRIBUTES;
|
||||||
|
fileHandle = INVALID_HANDLE_VALUE;
|
||||||
|
mapHandle = NULL;
|
||||||
|
#ifndef Q_OS_WINCE
|
||||||
|
cachedFd = -1;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs a QFSFileEngine for the file name \a file.
|
||||||
|
*/
|
||||||
|
QFSFileEngine::QFSFileEngine(const QString &file)
|
||||||
|
: QAbstractFileEngine(*new QFSFileEnginePrivate)
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
d->fileEntry = QFileSystemEntry(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs a QFSFileEngine.
|
||||||
|
*/
|
||||||
|
QFSFileEngine::QFSFileEngine() : QAbstractFileEngine(*new QFSFileEnginePrivate)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
QFSFileEngine::QFSFileEngine(QFSFileEnginePrivate &dd)
|
||||||
|
: QAbstractFileEngine(dd)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Destructs the QFSFileEngine.
|
||||||
|
*/
|
||||||
|
QFSFileEngine::~QFSFileEngine()
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
if (d->closeFileHandle) {
|
||||||
|
if (d->fh) {
|
||||||
|
int ret;
|
||||||
|
do {
|
||||||
|
ret = fclose(d->fh);
|
||||||
|
} while (ret == EOF && errno == EINTR);
|
||||||
|
} else if (d->fd != -1) {
|
||||||
|
int ret;
|
||||||
|
do {
|
||||||
|
ret = QT_CLOSE(d->fd);
|
||||||
|
} while (ret == -1 && errno == EINTR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QList<uchar*> keys = d->maps.keys();
|
||||||
|
for (int i = 0; i < keys.count(); ++i)
|
||||||
|
unmap(keys.at(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
void QFSFileEngine::setFileName(const QString &file)
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
d->init();
|
||||||
|
d->fileEntry = QFileSystemEntry(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
bool QFSFileEngine::open(QIODevice::OpenMode openMode)
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
if (d->fileEntry.isEmpty()) {
|
||||||
|
qWarning("QFSFileEngine::open: No file name specified");
|
||||||
|
setError(QFile::OpenError, QLatin1String("No file name specified"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append implies WriteOnly.
|
||||||
|
if (openMode & QFile::Append)
|
||||||
|
openMode |= QFile::WriteOnly;
|
||||||
|
|
||||||
|
// WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
|
||||||
|
if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
|
||||||
|
openMode |= QFile::Truncate;
|
||||||
|
|
||||||
|
d->openMode = openMode;
|
||||||
|
d->lastFlushFailed = false;
|
||||||
|
d->tried_stat = 0;
|
||||||
|
d->fh = 0;
|
||||||
|
d->fd = -1;
|
||||||
|
|
||||||
|
return d->nativeOpen(openMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Opens the file handle \a fh in \a openMode mode. Returns \c true on
|
||||||
|
success; otherwise returns \c false.
|
||||||
|
*/
|
||||||
|
bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh)
|
||||||
|
{
|
||||||
|
return open(openMode, fh, QFile::DontCloseHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh, QFile::FileHandleFlags handleFlags)
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
|
||||||
|
// Append implies WriteOnly.
|
||||||
|
if (openMode & QFile::Append)
|
||||||
|
openMode |= QFile::WriteOnly;
|
||||||
|
|
||||||
|
// WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
|
||||||
|
if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
|
||||||
|
openMode |= QFile::Truncate;
|
||||||
|
|
||||||
|
d->openMode = openMode;
|
||||||
|
d->lastFlushFailed = false;
|
||||||
|
d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle);
|
||||||
|
d->fileEntry.clear();
|
||||||
|
d->tried_stat = 0;
|
||||||
|
d->fd = -1;
|
||||||
|
|
||||||
|
return d->openFh(openMode, fh);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Opens the file handle \a fh using the open mode \a flags.
|
||||||
|
*/
|
||||||
|
bool QFSFileEnginePrivate::openFh(QIODevice::OpenMode openMode, FILE *fh)
|
||||||
|
{
|
||||||
|
Q_Q(QFSFileEngine);
|
||||||
|
this->fh = fh;
|
||||||
|
fd = -1;
|
||||||
|
|
||||||
|
// Seek to the end when in Append mode.
|
||||||
|
if (openMode & QIODevice::Append) {
|
||||||
|
int ret;
|
||||||
|
do {
|
||||||
|
ret = QT_FSEEK(fh, 0, SEEK_END);
|
||||||
|
} while (ret != 0 && errno == EINTR);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
|
||||||
|
qt_error_string(int(errno)));
|
||||||
|
|
||||||
|
this->openMode = QIODevice::NotOpen;
|
||||||
|
this->fh = 0;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Opens the file descriptor \a fd in \a openMode mode. Returns \c true
|
||||||
|
on success; otherwise returns \c false.
|
||||||
|
*/
|
||||||
|
bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd)
|
||||||
|
{
|
||||||
|
return open(openMode, fd, QFile::DontCloseHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd, QFile::FileHandleFlags handleFlags)
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
|
||||||
|
// Append implies WriteOnly.
|
||||||
|
if (openMode & QFile::Append)
|
||||||
|
openMode |= QFile::WriteOnly;
|
||||||
|
|
||||||
|
// WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
|
||||||
|
if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
|
||||||
|
openMode |= QFile::Truncate;
|
||||||
|
|
||||||
|
d->openMode = openMode;
|
||||||
|
d->lastFlushFailed = false;
|
||||||
|
d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle);
|
||||||
|
d->fileEntry.clear();
|
||||||
|
d->fh = 0;
|
||||||
|
d->fd = -1;
|
||||||
|
d->tried_stat = 0;
|
||||||
|
|
||||||
|
return d->openFd(openMode, fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Opens the file descriptor \a fd to the file engine, using the open mode \a
|
||||||
|
flags.
|
||||||
|
*/
|
||||||
|
bool QFSFileEnginePrivate::openFd(QIODevice::OpenMode openMode, int fd)
|
||||||
|
{
|
||||||
|
Q_Q(QFSFileEngine);
|
||||||
|
this->fd = fd;
|
||||||
|
fh = 0;
|
||||||
|
|
||||||
|
// Seek to the end when in Append mode.
|
||||||
|
if (openMode & QFile::Append) {
|
||||||
|
int ret;
|
||||||
|
do {
|
||||||
|
ret = QT_LSEEK(fd, 0, SEEK_END);
|
||||||
|
} while (ret == -1 && errno == EINTR);
|
||||||
|
|
||||||
|
if (ret == -1) {
|
||||||
|
q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
|
||||||
|
qt_error_string(int(errno)));
|
||||||
|
|
||||||
|
this->openMode = QIODevice::NotOpen;
|
||||||
|
this->fd = -1;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
bool QFSFileEngine::close()
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
d->openMode = QIODevice::NotOpen;
|
||||||
|
return d->nativeClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
bool QFSFileEnginePrivate::closeFdFh()
|
||||||
|
{
|
||||||
|
Q_Q(QFSFileEngine);
|
||||||
|
if (fd == -1 && !fh)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Flush the file if it's buffered, and if the last flush didn't fail.
|
||||||
|
bool flushed = !fh || (!lastFlushFailed && q->flush());
|
||||||
|
bool closed = true;
|
||||||
|
tried_stat = 0;
|
||||||
|
|
||||||
|
// Close the file if we created the handle.
|
||||||
|
if (closeFileHandle) {
|
||||||
|
int ret;
|
||||||
|
do {
|
||||||
|
if (fh) {
|
||||||
|
// Close buffered file.
|
||||||
|
ret = fclose(fh) != 0 ? -1 : 0;
|
||||||
|
} else {
|
||||||
|
// Close unbuffered file.
|
||||||
|
ret = QT_CLOSE(fd);
|
||||||
|
}
|
||||||
|
} while (ret == -1 && errno == EINTR);
|
||||||
|
|
||||||
|
// We must reset these guys regardless; calling close again after a
|
||||||
|
// failed close causes crashes on some systems.
|
||||||
|
fh = 0;
|
||||||
|
fd = -1;
|
||||||
|
closed = (ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report errors.
|
||||||
|
if (!flushed || !closed) {
|
||||||
|
if (flushed) {
|
||||||
|
// If not flushed, we want the flush error to fall through.
|
||||||
|
q->setError(QFile::UnspecifiedError, qt_error_string(errno));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
bool QFSFileEngine::flush()
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
if ((d->openMode & QIODevice::WriteOnly) == 0) {
|
||||||
|
// Nothing in the write buffers, so flush succeeds in doing
|
||||||
|
// nothing.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return d->nativeFlush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
bool QFSFileEngine::syncToDisk()
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
if ((d->openMode & QIODevice::WriteOnly) == 0)
|
||||||
|
return true;
|
||||||
|
return d->nativeSyncToDisk();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
bool QFSFileEnginePrivate::flushFh()
|
||||||
|
{
|
||||||
|
Q_Q(QFSFileEngine);
|
||||||
|
|
||||||
|
// Never try to flush again if the last flush failed. Otherwise you can
|
||||||
|
// get crashes on some systems (AIX).
|
||||||
|
if (lastFlushFailed)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int ret = fflush(fh);
|
||||||
|
|
||||||
|
lastFlushFailed = (ret != 0);
|
||||||
|
lastIOCommand = QFSFileEnginePrivate::IOFlushCommand;
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError,
|
||||||
|
qt_error_string(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
qint64 QFSFileEngine::size() const
|
||||||
|
{
|
||||||
|
Q_D(const QFSFileEngine);
|
||||||
|
return d->nativeSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
qint64 QFSFileEnginePrivate::sizeFdFh() const
|
||||||
|
{
|
||||||
|
Q_Q(const QFSFileEngine);
|
||||||
|
const_cast<QFSFileEngine *>(q)->flush();
|
||||||
|
|
||||||
|
tried_stat = 0;
|
||||||
|
metaData.clearFlags(QFileSystemMetaData::SizeAttribute);
|
||||||
|
if (!doStat(QFileSystemMetaData::SizeAttribute))
|
||||||
|
return 0;
|
||||||
|
return metaData.size();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
qint64 QFSFileEngine::pos() const
|
||||||
|
{
|
||||||
|
Q_D(const QFSFileEngine);
|
||||||
|
return d->nativePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
qint64 QFSFileEnginePrivate::posFdFh() const
|
||||||
|
{
|
||||||
|
if (fh)
|
||||||
|
return qint64(QT_FTELL(fh));
|
||||||
|
return QT_LSEEK(fd, 0, SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
bool QFSFileEngine::seek(qint64 pos)
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
return d->nativeSeek(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
bool QFSFileEnginePrivate::seekFdFh(qint64 pos)
|
||||||
|
{
|
||||||
|
Q_Q(QFSFileEngine);
|
||||||
|
|
||||||
|
// On Windows' stdlib implementation, the results of calling fread and
|
||||||
|
// fwrite are undefined if not called either in sequence, or if preceded
|
||||||
|
// with a call to fflush().
|
||||||
|
if (lastIOCommand != QFSFileEnginePrivate::IOFlushCommand && !q->flush())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (pos < 0 || pos != qint64(QT_OFF_T(pos)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (fh) {
|
||||||
|
// Buffered stdlib mode.
|
||||||
|
int ret;
|
||||||
|
do {
|
||||||
|
ret = QT_FSEEK(fh, QT_OFF_T(pos), SEEK_SET);
|
||||||
|
} while (ret != 0 && errno == EINTR);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
q->setError(QFile::ReadError, qt_error_string(int(errno)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Unbuffered stdio mode.
|
||||||
|
if (QT_LSEEK(fd, QT_OFF_T(pos), SEEK_SET) == -1) {
|
||||||
|
qWarning() << "QFile::at: Cannot set file position" << pos;
|
||||||
|
q->setError(QFile::PositionError, qt_error_string(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
int QFSFileEngine::handle() const
|
||||||
|
{
|
||||||
|
Q_D(const QFSFileEngine);
|
||||||
|
return d->nativeHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
qint64 QFSFileEngine::read(char *data, qint64 maxlen)
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
|
||||||
|
// On Windows' stdlib implementation, the results of calling fread and
|
||||||
|
// fwrite are undefined if not called either in sequence, or if preceded
|
||||||
|
// with a call to fflush().
|
||||||
|
if (d->lastIOCommand != QFSFileEnginePrivate::IOReadCommand) {
|
||||||
|
flush();
|
||||||
|
d->lastIOCommand = QFSFileEnginePrivate::IOReadCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
return d->nativeRead(data, maxlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len)
|
||||||
|
{
|
||||||
|
Q_Q(QFSFileEngine);
|
||||||
|
|
||||||
|
if (len < 0 || len != qint64(size_t(len))) {
|
||||||
|
q->setError(QFile::ReadError, qt_error_string(EINVAL));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 readBytes = 0;
|
||||||
|
bool eof = false;
|
||||||
|
|
||||||
|
if (fh) {
|
||||||
|
// Buffered stdlib mode.
|
||||||
|
|
||||||
|
size_t result;
|
||||||
|
bool retry = true;
|
||||||
|
do {
|
||||||
|
result = fread(data + readBytes, 1, size_t(len - readBytes), fh);
|
||||||
|
eof = feof(fh);
|
||||||
|
if (retry && eof && result == 0) {
|
||||||
|
// On Mac OS, this is needed, e.g., if a file was written to
|
||||||
|
// through another stream since our last read. See test
|
||||||
|
// tst_QFile::appendAndRead
|
||||||
|
QT_FSEEK(fh, QT_FTELL(fh), SEEK_SET); // re-sync stream.
|
||||||
|
retry = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
readBytes += result;
|
||||||
|
} while (!eof && (result == 0 ? errno == EINTR : readBytes < len));
|
||||||
|
|
||||||
|
} else if (fd != -1) {
|
||||||
|
// Unbuffered stdio mode.
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
int result;
|
||||||
|
#else
|
||||||
|
ssize_t result;
|
||||||
|
#endif
|
||||||
|
do {
|
||||||
|
result = QT_READ(fd, data + readBytes, size_t(len - readBytes));
|
||||||
|
} while ((result == -1 && errno == EINTR)
|
||||||
|
|| (result > 0 && (readBytes += result) < len));
|
||||||
|
|
||||||
|
eof = !(result == -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eof && readBytes == 0) {
|
||||||
|
readBytes = -1;
|
||||||
|
q->setError(QFile::ReadError, qt_error_string(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
return readBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
qint64 QFSFileEngine::readLine(char *data, qint64 maxlen)
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
|
||||||
|
// On Windows' stdlib implementation, the results of calling fread and
|
||||||
|
// fwrite are undefined if not called either in sequence, or if preceded
|
||||||
|
// with a call to fflush().
|
||||||
|
if (d->lastIOCommand != QFSFileEnginePrivate::IOReadCommand) {
|
||||||
|
flush();
|
||||||
|
d->lastIOCommand = QFSFileEnginePrivate::IOReadCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
return d->nativeReadLine(data, maxlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
qint64 QFSFileEnginePrivate::readLineFdFh(char *data, qint64 maxlen)
|
||||||
|
{
|
||||||
|
Q_Q(QFSFileEngine);
|
||||||
|
if (!fh)
|
||||||
|
return q->QAbstractFileEngine::readLine(data, maxlen);
|
||||||
|
|
||||||
|
QT_OFF_T oldPos = 0;
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
bool seq = q->isSequential();
|
||||||
|
if (!seq)
|
||||||
|
#endif
|
||||||
|
oldPos = QT_FTELL(fh);
|
||||||
|
|
||||||
|
// QIODevice::readLine() passes maxlen - 1 to QFile::readLineData()
|
||||||
|
// because it has made space for the '\0' at the end of data. But fgets
|
||||||
|
// does the same, so we'd get two '\0' at the end - passing maxlen + 1
|
||||||
|
// solves this.
|
||||||
|
if (!fgets(data, int(maxlen + 1), fh)) {
|
||||||
|
if (!feof(fh))
|
||||||
|
q->setError(QFile::ReadError, qt_error_string(int(errno)));
|
||||||
|
return -1; // error
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
if (seq)
|
||||||
|
return qstrlen(data);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
qint64 lineLength = QT_FTELL(fh) - oldPos;
|
||||||
|
return lineLength > 0 ? lineLength : qstrlen(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
qint64 QFSFileEngine::write(const char *data, qint64 len)
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
|
||||||
|
// On Windows' stdlib implementation, the results of calling fread and
|
||||||
|
// fwrite are undefined if not called either in sequence, or if preceded
|
||||||
|
// with a call to fflush().
|
||||||
|
if (d->lastIOCommand != QFSFileEnginePrivate::IOWriteCommand) {
|
||||||
|
flush();
|
||||||
|
d->lastIOCommand = QFSFileEnginePrivate::IOWriteCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
return d->nativeWrite(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len)
|
||||||
|
{
|
||||||
|
Q_Q(QFSFileEngine);
|
||||||
|
|
||||||
|
if (len < 0 || len != qint64(size_t(len))) {
|
||||||
|
q->setError(QFile::WriteError, qt_error_string(EINVAL));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 writtenBytes = 0;
|
||||||
|
|
||||||
|
if (fh) {
|
||||||
|
// Buffered stdlib mode.
|
||||||
|
|
||||||
|
size_t result;
|
||||||
|
do {
|
||||||
|
result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh);
|
||||||
|
writtenBytes += result;
|
||||||
|
} while (result == 0 ? errno == EINTR : writtenBytes < len);
|
||||||
|
|
||||||
|
} else if (fd != -1) {
|
||||||
|
// Unbuffered stdio mode.
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
int result;
|
||||||
|
#else
|
||||||
|
ssize_t result;
|
||||||
|
#endif
|
||||||
|
do {
|
||||||
|
result = QT_WRITE(fd, data + writtenBytes, size_t(len - writtenBytes));
|
||||||
|
} while ((result == -1 && errno == EINTR)
|
||||||
|
|| (result > 0 && (writtenBytes += result) < len));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len && writtenBytes == 0) {
|
||||||
|
writtenBytes = -1;
|
||||||
|
q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError, qt_error_string(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
return writtenBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef QT_NO_FILESYSTEMITERATOR
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
QAbstractFileEngine::Iterator *QFSFileEngine::beginEntryList(QDir::Filters filters, const QStringList &filterNames)
|
||||||
|
{
|
||||||
|
return new QFSFileEngineIterator(filters, filterNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
QAbstractFileEngine::Iterator *QFSFileEngine::endEntryList()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif // QT_NO_FILESYSTEMITERATOR
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
QStringList QFSFileEngine::entryList(QDir::Filters filters, const QStringList &filterNames) const
|
||||||
|
{
|
||||||
|
return QAbstractFileEngine::entryList(filters, filterNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
bool QFSFileEngine::isSequential() const
|
||||||
|
{
|
||||||
|
Q_D(const QFSFileEngine);
|
||||||
|
if (d->is_sequential == 0)
|
||||||
|
d->is_sequential = d->nativeIsSequential() ? 1 : 2;
|
||||||
|
return d->is_sequential == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
bool QFSFileEnginePrivate::isSequentialFdFh() const
|
||||||
|
{
|
||||||
|
if (doStat(QFileSystemMetaData::SequentialType))
|
||||||
|
return metaData.isSequential();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
bool QFSFileEngine::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
if (extension == AtEndExtension && d->fh && isSequential())
|
||||||
|
return feof(d->fh);
|
||||||
|
|
||||||
|
if (extension == MapExtension) {
|
||||||
|
const MapExtensionOption *options = (MapExtensionOption*)(option);
|
||||||
|
MapExtensionReturn *returnValue = static_cast<MapExtensionReturn*>(output);
|
||||||
|
returnValue->address = d->map(options->offset, options->size, options->flags);
|
||||||
|
return (returnValue->address != 0);
|
||||||
|
}
|
||||||
|
if (extension == UnMapExtension) {
|
||||||
|
UnMapExtensionOption *options = (UnMapExtensionOption*)option;
|
||||||
|
return d->unmap(options->address);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
bool QFSFileEngine::supportsExtension(Extension extension) const
|
||||||
|
{
|
||||||
|
Q_D(const QFSFileEngine);
|
||||||
|
if (extension == AtEndExtension && d->fh && isSequential())
|
||||||
|
return true;
|
||||||
|
if (extension == FastReadLineExtension && d->fh)
|
||||||
|
return true;
|
||||||
|
if (extension == FastReadLineExtension && d->fd != -1 && isSequential())
|
||||||
|
return true;
|
||||||
|
if (extension == UnMapExtension || extension == MapExtension)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \fn bool QFSFileEngine::caseSensitive() const
|
||||||
|
Returns \c true for Windows, false for Unix.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn bool QFSFileEngine::copy(const QString ©Name)
|
||||||
|
|
||||||
|
For windows, copy the file to file \a copyName.
|
||||||
|
|
||||||
|
Not implemented for Unix.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn QString QFSFileEngine::currentPath(const QString &fileName)
|
||||||
|
For Unix, returns the current working directory for the file
|
||||||
|
engine.
|
||||||
|
|
||||||
|
For Windows, returns the canonicalized form of the current path used
|
||||||
|
by the file engine for the drive specified by \a fileName. On
|
||||||
|
Windows, each drive has its own current directory, so a different
|
||||||
|
path is returned for file names that include different drive names
|
||||||
|
(e.g. A: or C:).
|
||||||
|
|
||||||
|
\sa setCurrentPath()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn QFileInfoList QFSFileEngine::drives()
|
||||||
|
For Windows, returns the list of drives in the file system as a list
|
||||||
|
of QFileInfo objects. On unix, Mac OS X and Windows CE, only the
|
||||||
|
root path is returned. On Windows, this function returns all drives
|
||||||
|
(A:\, C:\, D:\, etc.).
|
||||||
|
|
||||||
|
For Unix, the list contains just the root path "/".
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn QString QFSFileEngine::fileName(FileName file) const
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn QDateTime QFSFileEngine::fileTime(FileTime time) const
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn QString QFSFileEngine::homePath()
|
||||||
|
Returns the home path of the current user.
|
||||||
|
|
||||||
|
\sa rootPath()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn bool QFSFileEngine::isRelativePath() const
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn bool QFSFileEngine::link(const QString &newName)
|
||||||
|
|
||||||
|
Creates a link from the file currently specified by fileName() to
|
||||||
|
\a newName. What a link is depends on the underlying filesystem
|
||||||
|
(be it a shortcut on Windows or a symbolic link on Unix). Returns
|
||||||
|
true if successful; otherwise returns \c false.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn uint QFSFileEngine::ownerId(FileOwner own) const
|
||||||
|
In Unix, if stat() is successful, the \c uid is returned if
|
||||||
|
\a own is the owner. Otherwise the \c gid is returned. If stat()
|
||||||
|
is unsuccessful, -2 is reuturned.
|
||||||
|
|
||||||
|
For Windows, -2 is always returned.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn QString QFSFileEngine::owner(FileOwner own) const
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn bool QFSFileEngine::remove()
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn bool QFSFileEngine::rename(const QString &newName)
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*! \fn bool QFSFileEngine::renameOverwrite(const QString &newName)
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn QString QFSFileEngine::rootPath()
|
||||||
|
Returns the root path.
|
||||||
|
|
||||||
|
\sa homePath()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn bool QFSFileEngine::setCurrentPath(const QString &path)
|
||||||
|
Sets the current path (e.g., for QDir), to \a path. Returns \c true if the
|
||||||
|
new path exists; otherwise this function does nothing, and returns \c false.
|
||||||
|
|
||||||
|
\sa currentPath()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn bool QFSFileEngine::setPermissions(uint perms)
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn bool QFSFileEngine::setSize(qint64 size)
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn QString QFSFileEngine::tempPath()
|
||||||
|
Returns the temporary path (i.e., a path in which it is safe
|
||||||
|
to store temporary files).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions(QAbstractFileEngine::FileFlags type) const
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif // QT_NO_FSFILEENGINE
|
85
src/app/core/backport/qfsfileengine_iterator.cpp
Normal file
85
src/app/core/backport/qfsfileengine_iterator.cpp
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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 "qfsfileengine_iterator_p.h"
|
||||||
|
#include "qfileinfo_p.h"
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
#ifndef QT_NO_FILESYSTEMITERATOR
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
QFSFileEngineIterator::QFSFileEngineIterator(QDir::Filters filters, const QStringList &filterNames)
|
||||||
|
: QAbstractFileEngineIterator(filters, filterNames)
|
||||||
|
, done(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QFSFileEngineIterator::~QFSFileEngineIterator()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEngineIterator::hasNext() const
|
||||||
|
{
|
||||||
|
if (!done && !nativeIterator) {
|
||||||
|
nativeIterator.reset(new QFileSystemIterator(QFileSystemEntry(path()),
|
||||||
|
filters(), nameFilters()));
|
||||||
|
advance();
|
||||||
|
}
|
||||||
|
|
||||||
|
return !done;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFSFileEngineIterator::next()
|
||||||
|
{
|
||||||
|
if (!hasNext())
|
||||||
|
return QString();
|
||||||
|
|
||||||
|
advance();
|
||||||
|
return currentFilePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QFSFileEngineIterator::advance() const
|
||||||
|
{
|
||||||
|
currentInfo = nextInfo;
|
||||||
|
|
||||||
|
QFileSystemEntry entry;
|
||||||
|
QFileSystemMetaData data;
|
||||||
|
if (nativeIterator->advance(entry, data)) {
|
||||||
|
nextInfo = QFileInfo(new QFileInfoPrivate(entry, data));
|
||||||
|
} else {
|
||||||
|
done = true;
|
||||||
|
nativeIterator.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFSFileEngineIterator::currentFileName() const
|
||||||
|
{
|
||||||
|
return currentInfo.fileName();
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileInfo QFSFileEngineIterator::currentFileInfo() const
|
||||||
|
{
|
||||||
|
return currentInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif // QT_NO_FILESYSTEMITERATOR
|
70
src/app/core/backport/qfsfileengine_iterator_p.h
Normal file
70
src/app/core/backport/qfsfileengine_iterator_p.h
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QFSFILEENGINE_ITERATOR_P_H
|
||||||
|
#define QFSFILEENGINE_ITERATOR_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists purely as an
|
||||||
|
// implementation detail. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "qabstractfileengine_p.h"
|
||||||
|
#include "qfilesystemiterator_p.h"
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#ifndef QT_NO_FILESYSTEMITERATOR
|
||||||
|
|
||||||
|
class QFSFileEngineIteratorPrivate;
|
||||||
|
class QFSFileEngineIteratorPlatformSpecificData;
|
||||||
|
|
||||||
|
class QFSFileEngineIterator : public QAbstractFileEngineIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QFSFileEngineIterator(QDir::Filters filters, const QStringList &filterNames);
|
||||||
|
~QFSFileEngineIterator();
|
||||||
|
|
||||||
|
QString next();
|
||||||
|
bool hasNext() const;
|
||||||
|
|
||||||
|
QString currentFileName() const;
|
||||||
|
QFileInfo currentFileInfo() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void advance() const;
|
||||||
|
mutable QScopedPointer<QFileSystemIterator> nativeIterator;
|
||||||
|
mutable QFileInfo currentInfo;
|
||||||
|
mutable QFileInfo nextInfo;
|
||||||
|
mutable bool done;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QT_NO_FILESYSTEMITERATOR
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif // QFSFILEENGINE_ITERATOR_P_H
|
218
src/app/core/backport/qfsfileengine_p.h
Normal file
218
src/app/core/backport/qfsfileengine_p.h
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QFSFILEENGINE_P_H
|
||||||
|
#define QFSFILEENGINE_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists purely as an
|
||||||
|
// implementation detail. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "qplatformdefs.h"
|
||||||
|
#include "qabstractfileengine_p.h"
|
||||||
|
#include "qfilesystementry_p.h"
|
||||||
|
#include "qfilesystemmetadata_p.h"
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#ifndef QT_NO_FSFILEENGINE
|
||||||
|
|
||||||
|
#if defined(Q_OS_WINCE_STD) && _WIN32_WCE < 0x600
|
||||||
|
#define Q_USE_DEPRECATED_MAP_API 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class QFSFileEnginePrivate;
|
||||||
|
|
||||||
|
class QFSFileEngine : public QAbstractFileEngine
|
||||||
|
{
|
||||||
|
Q_DECLARE_PRIVATE(QFSFileEngine)
|
||||||
|
public:
|
||||||
|
QFSFileEngine();
|
||||||
|
explicit QFSFileEngine(const QString &file);
|
||||||
|
~QFSFileEngine();
|
||||||
|
|
||||||
|
bool open(QIODevice::OpenMode openMode);
|
||||||
|
bool open(QIODevice::OpenMode flags, FILE *fh);
|
||||||
|
bool close();
|
||||||
|
bool flush();
|
||||||
|
bool syncToDisk();
|
||||||
|
qint64 size() const;
|
||||||
|
qint64 pos() const;
|
||||||
|
bool seek(qint64);
|
||||||
|
bool isSequential() const;
|
||||||
|
bool remove();
|
||||||
|
bool copy(const QString &newName);
|
||||||
|
bool rename(const QString &newName);
|
||||||
|
bool renameOverwrite(const QString &newName);
|
||||||
|
bool link(const QString &newName);
|
||||||
|
bool mkdir(const QString &dirName, bool createParentDirectories) const;
|
||||||
|
bool rmdir(const QString &dirName, bool recurseParentDirectories) const;
|
||||||
|
bool setSize(qint64 size);
|
||||||
|
bool caseSensitive() const;
|
||||||
|
bool isRelativePath() const;
|
||||||
|
QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const;
|
||||||
|
FileFlags fileFlags(FileFlags type) const;
|
||||||
|
bool setPermissions(uint perms);
|
||||||
|
QString fileName(FileName file) const;
|
||||||
|
uint ownerId(FileOwner) const;
|
||||||
|
QString owner(FileOwner) const;
|
||||||
|
QDateTime fileTime(FileTime time) const;
|
||||||
|
void setFileName(const QString &file);
|
||||||
|
int handle() const;
|
||||||
|
|
||||||
|
#ifndef QT_NO_FILESYSTEMITERATOR
|
||||||
|
Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames);
|
||||||
|
Iterator *endEntryList();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
qint64 read(char *data, qint64 maxlen);
|
||||||
|
qint64 readLine(char *data, qint64 maxlen);
|
||||||
|
qint64 write(const char *data, qint64 len);
|
||||||
|
|
||||||
|
bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0);
|
||||||
|
bool supportsExtension(Extension extension) const;
|
||||||
|
|
||||||
|
//FS only!!
|
||||||
|
bool open(QIODevice::OpenMode flags, int fd);
|
||||||
|
bool open(QIODevice::OpenMode flags, int fd, QFile::FileHandleFlags handleFlags);
|
||||||
|
bool open(QIODevice::OpenMode flags, FILE *fh, QFile::FileHandleFlags handleFlags);
|
||||||
|
static bool setCurrentPath(const QString &path);
|
||||||
|
static QString currentPath(const QString &path = QString());
|
||||||
|
static QString homePath();
|
||||||
|
static QString rootPath();
|
||||||
|
static QString tempPath();
|
||||||
|
static QFileInfoList drives();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QFSFileEngine(QFSFileEnginePrivate &dd);
|
||||||
|
};
|
||||||
|
|
||||||
|
class QFSFileEnginePrivate : public QAbstractFileEnginePrivate
|
||||||
|
{
|
||||||
|
Q_DECLARE_PUBLIC(QFSFileEngine)
|
||||||
|
|
||||||
|
public:
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
static QString longFileName(const QString &path);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QFileSystemEntry fileEntry;
|
||||||
|
QIODevice::OpenMode openMode;
|
||||||
|
|
||||||
|
bool nativeOpen(QIODevice::OpenMode openMode);
|
||||||
|
bool openFh(QIODevice::OpenMode flags, FILE *fh);
|
||||||
|
bool openFd(QIODevice::OpenMode flags, int fd);
|
||||||
|
bool nativeClose();
|
||||||
|
bool closeFdFh();
|
||||||
|
bool nativeFlush();
|
||||||
|
bool nativeSyncToDisk();
|
||||||
|
bool flushFh();
|
||||||
|
qint64 nativeSize() const;
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
qint64 sizeFdFh() const;
|
||||||
|
#endif
|
||||||
|
qint64 nativePos() const;
|
||||||
|
qint64 posFdFh() const;
|
||||||
|
bool nativeSeek(qint64);
|
||||||
|
bool seekFdFh(qint64);
|
||||||
|
qint64 nativeRead(char *data, qint64 maxlen);
|
||||||
|
qint64 readFdFh(char *data, qint64 maxlen);
|
||||||
|
qint64 nativeReadLine(char *data, qint64 maxlen);
|
||||||
|
qint64 readLineFdFh(char *data, qint64 maxlen);
|
||||||
|
qint64 nativeWrite(const char *data, qint64 len);
|
||||||
|
qint64 writeFdFh(const char *data, qint64 len);
|
||||||
|
int nativeHandle() const;
|
||||||
|
bool nativeIsSequential() const;
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
bool isSequentialFdFh() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags);
|
||||||
|
bool unmap(uchar *ptr);
|
||||||
|
|
||||||
|
mutable QFileSystemMetaData metaData;
|
||||||
|
|
||||||
|
FILE *fh;
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
HANDLE fileHandle;
|
||||||
|
HANDLE mapHandle;
|
||||||
|
QHash<uchar *, DWORD /* offset % AllocationGranularity */> maps;
|
||||||
|
|
||||||
|
#ifndef Q_OS_WINCE
|
||||||
|
mutable int cachedFd;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mutable DWORD fileAttrib;
|
||||||
|
#else
|
||||||
|
QHash<uchar *, QPair<int /*offset % PageSize*/, size_t /*length + offset % PageSize*/> > maps;
|
||||||
|
#endif
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
enum LastIOCommand
|
||||||
|
{
|
||||||
|
IOFlushCommand,
|
||||||
|
IOReadCommand,
|
||||||
|
IOWriteCommand
|
||||||
|
};
|
||||||
|
LastIOCommand lastIOCommand;
|
||||||
|
bool lastFlushFailed;
|
||||||
|
bool closeFileHandle;
|
||||||
|
|
||||||
|
mutable uint is_sequential : 2;
|
||||||
|
mutable uint could_stat : 1;
|
||||||
|
mutable uint tried_stat : 1;
|
||||||
|
#if !defined(Q_OS_WINCE)
|
||||||
|
mutable uint need_lstat : 1;
|
||||||
|
mutable uint is_link : 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
bool doStat(QFileSystemMetaData::MetaDataFlags flags) const;
|
||||||
|
#else
|
||||||
|
bool doStat(QFileSystemMetaData::MetaDataFlags flags = QFileSystemMetaData::PosixStatFlags) const;
|
||||||
|
#endif
|
||||||
|
bool isSymlink() const;
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN32)
|
||||||
|
int sysOpen(const QString &, int flags);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QFSFileEnginePrivate();
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
QAbstractFileEngine::FileFlags getPermissions(QAbstractFileEngine::FileFlags type) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QT_NO_FSFILEENGINE
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif // QFSFILEENGINE_P_H
|
749
src/app/core/backport/qfsfileengine_unix.cpp
Normal file
749
src/app/core/backport/qfsfileengine_unix.cpp
Normal file
|
@ -0,0 +1,749 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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 "qplatformdefs.h"
|
||||||
|
#include "qabstractfileengine_p.h"
|
||||||
|
#include "qfsfileengine_p.h"
|
||||||
|
#include "qcore_unix_p.h"
|
||||||
|
#include "qfilesystementry_p.h"
|
||||||
|
#include "qfilesystemengine_p.h"
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#ifndef QT_NO_FSFILEENGINE
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QVarLengthArray>
|
||||||
|
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#if !defined(QWS) && defined(Q_OS_MAC)
|
||||||
|
# include "qcore_mac_p.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
|
||||||
|
Returns the stdlib open string corresponding to a QIODevice::OpenMode.
|
||||||
|
*/
|
||||||
|
static inline QByteArray openModeToFopenMode(QIODevice::OpenMode flags, const QFileSystemEntry &fileEntry,
|
||||||
|
QFileSystemMetaData &metaData)
|
||||||
|
{
|
||||||
|
QByteArray mode;
|
||||||
|
if ((flags & QIODevice::ReadOnly) && !(flags & QIODevice::Truncate)) {
|
||||||
|
mode = "rb";
|
||||||
|
if (flags & QIODevice::WriteOnly) {
|
||||||
|
metaData.clearFlags(QFileSystemMetaData::FileType);
|
||||||
|
if (!fileEntry.isEmpty()
|
||||||
|
&& QFileSystemEngine::fillMetaData(fileEntry, metaData, QFileSystemMetaData::FileType)
|
||||||
|
&& metaData.isFile()) {
|
||||||
|
mode += '+';
|
||||||
|
} else {
|
||||||
|
mode = "wb+";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (flags & QIODevice::WriteOnly) {
|
||||||
|
mode = "wb";
|
||||||
|
if (flags & QIODevice::ReadOnly)
|
||||||
|
mode += '+';
|
||||||
|
}
|
||||||
|
if (flags & QIODevice::Append) {
|
||||||
|
mode = "ab";
|
||||||
|
if (flags & QIODevice::ReadOnly)
|
||||||
|
mode += '+';
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0207
|
||||||
|
// must be glibc >= 2.7
|
||||||
|
mode += 'e';
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
|
||||||
|
Returns the stdio open flags corresponding to a QIODevice::OpenMode.
|
||||||
|
*/
|
||||||
|
static inline int openModeToOpenFlags(QIODevice::OpenMode mode)
|
||||||
|
{
|
||||||
|
int oflags = QT_OPEN_RDONLY;
|
||||||
|
#ifdef QT_LARGEFILE_SUPPORT
|
||||||
|
oflags |= QT_OPEN_LARGEFILE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((mode & QFile::ReadWrite) == QFile::ReadWrite) {
|
||||||
|
oflags = QT_OPEN_RDWR | QT_OPEN_CREAT;
|
||||||
|
} else if (mode & QFile::WriteOnly) {
|
||||||
|
oflags = QT_OPEN_WRONLY | QT_OPEN_CREAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode & QFile::Append) {
|
||||||
|
oflags |= QT_OPEN_APPEND;
|
||||||
|
} else if (mode & QFile::WriteOnly) {
|
||||||
|
if ((mode & QFile::Truncate) || !(mode & QFile::ReadOnly))
|
||||||
|
oflags |= QT_OPEN_TRUNC;
|
||||||
|
}
|
||||||
|
|
||||||
|
return oflags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
|
||||||
|
Sets the file descriptor to close on exec. That is, the file
|
||||||
|
descriptor is not inherited by child processes.
|
||||||
|
*/
|
||||||
|
static inline bool setCloseOnExec(int fd)
|
||||||
|
{
|
||||||
|
return fd != -1 && fcntl(fd, F_SETFD, FD_CLOEXEC) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
|
||||||
|
{
|
||||||
|
Q_Q(QFSFileEngine);
|
||||||
|
|
||||||
|
if (openMode & QIODevice::Unbuffered) {
|
||||||
|
int flags = openModeToOpenFlags(openMode);
|
||||||
|
|
||||||
|
// Try to open the file in unbuffered mode.
|
||||||
|
do {
|
||||||
|
fd = QT_OPEN(fileEntry.nativeFilePath().constData(), flags, 0666);
|
||||||
|
} while (fd == -1 && errno == EINTR);
|
||||||
|
|
||||||
|
// On failure, return and report the error.
|
||||||
|
if (fd == -1) {
|
||||||
|
q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
|
||||||
|
qt_error_string(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(openMode & QIODevice::WriteOnly)) {
|
||||||
|
// we don't need this check if we tried to open for writing because then
|
||||||
|
// we had received EISDIR anyway.
|
||||||
|
if (QFileSystemEngine::fillMetaData(fd, metaData)
|
||||||
|
&& metaData.isDirectory()) {
|
||||||
|
q->setError(QFile::OpenError, QLatin1String("file to open is a directory"));
|
||||||
|
QT_CLOSE(fd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seek to the end when in Append mode.
|
||||||
|
if (flags & QFile::Append) {
|
||||||
|
int ret;
|
||||||
|
do {
|
||||||
|
ret = QT_LSEEK(fd, 0, SEEK_END);
|
||||||
|
} while (ret == -1 && errno == EINTR);
|
||||||
|
|
||||||
|
if (ret == -1) {
|
||||||
|
q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
|
||||||
|
qt_error_string(int(errno)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fh = 0;
|
||||||
|
} else {
|
||||||
|
QByteArray fopenMode = openModeToFopenMode(openMode, fileEntry, metaData);
|
||||||
|
|
||||||
|
// Try to open the file in buffered mode.
|
||||||
|
do {
|
||||||
|
fh = QT_FOPEN(fileEntry.nativeFilePath().constData(), fopenMode.constData());
|
||||||
|
} while (!fh && errno == EINTR);
|
||||||
|
|
||||||
|
// On failure, return and report the error.
|
||||||
|
if (!fh) {
|
||||||
|
q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
|
||||||
|
qt_error_string(int(errno)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(openMode & QIODevice::WriteOnly)) {
|
||||||
|
// we don't need this check if we tried to open for writing because then
|
||||||
|
// we had received EISDIR anyway.
|
||||||
|
if (QFileSystemEngine::fillMetaData(QT_FILENO(fh), metaData)
|
||||||
|
&& metaData.isDirectory()) {
|
||||||
|
q->setError(QFile::OpenError, QLatin1String("file to open is a directory"));
|
||||||
|
fclose(fh);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setCloseOnExec(fileno(fh)); // ignore failure
|
||||||
|
|
||||||
|
// Seek to the end when in Append mode.
|
||||||
|
if (openMode & QIODevice::Append) {
|
||||||
|
int ret;
|
||||||
|
do {
|
||||||
|
ret = QT_FSEEK(fh, 0, SEEK_END);
|
||||||
|
} while (ret == -1 && errno == EINTR);
|
||||||
|
|
||||||
|
if (ret == -1) {
|
||||||
|
q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
|
||||||
|
qt_error_string(int(errno)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
closeFileHandle = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
bool QFSFileEnginePrivate::nativeClose()
|
||||||
|
{
|
||||||
|
return closeFdFh();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
|
||||||
|
*/
|
||||||
|
bool QFSFileEnginePrivate::nativeFlush()
|
||||||
|
{
|
||||||
|
return fh ? flushFh() : fd != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
\since 5.1
|
||||||
|
*/
|
||||||
|
bool QFSFileEnginePrivate::nativeSyncToDisk()
|
||||||
|
{
|
||||||
|
Q_Q(QFSFileEngine);
|
||||||
|
#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
|
||||||
|
const int ret = fdatasync(nativeHandle());
|
||||||
|
#else
|
||||||
|
const int ret = fsync(nativeHandle());
|
||||||
|
#endif
|
||||||
|
if (ret != 0)
|
||||||
|
q->setError(QFile::WriteError, qt_error_string(errno));
|
||||||
|
return ret == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
qint64 QFSFileEnginePrivate::nativeRead(char *data, qint64 len)
|
||||||
|
{
|
||||||
|
Q_Q(QFSFileEngine);
|
||||||
|
|
||||||
|
if (fh && nativeIsSequential()) {
|
||||||
|
size_t readBytes = 0;
|
||||||
|
int oldFlags = fcntl(QT_FILENO(fh), F_GETFL);
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
// Unix: Make the underlying file descriptor non-blocking
|
||||||
|
if ((oldFlags & O_NONBLOCK) == 0)
|
||||||
|
fcntl(QT_FILENO(fh), F_SETFL, oldFlags | O_NONBLOCK);
|
||||||
|
|
||||||
|
// Cross platform stdlib read
|
||||||
|
size_t read = 0;
|
||||||
|
do {
|
||||||
|
read = fread(data + readBytes, 1, size_t(len - readBytes), fh);
|
||||||
|
} while (read == 0 && !feof(fh) && errno == EINTR);
|
||||||
|
if (read > 0) {
|
||||||
|
readBytes += read;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (readBytes)
|
||||||
|
break;
|
||||||
|
readBytes = read;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unix: Restore the blocking state of the underlying socket
|
||||||
|
if ((oldFlags & O_NONBLOCK) == 0) {
|
||||||
|
fcntl(QT_FILENO(fh), F_SETFL, oldFlags);
|
||||||
|
if (readBytes == 0) {
|
||||||
|
int readByte = 0;
|
||||||
|
do {
|
||||||
|
readByte = fgetc(fh);
|
||||||
|
} while (readByte == -1 && errno == EINTR);
|
||||||
|
if (readByte != -1) {
|
||||||
|
*data = uchar(readByte);
|
||||||
|
readBytes += 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Unix: Restore the blocking state of the underlying socket
|
||||||
|
if ((oldFlags & O_NONBLOCK) == 0) {
|
||||||
|
fcntl(QT_FILENO(fh), F_SETFL, oldFlags);
|
||||||
|
}
|
||||||
|
if (readBytes == 0 && !feof(fh)) {
|
||||||
|
// if we didn't read anything and we're not at EOF, it must be an error
|
||||||
|
q->setError(QFile::ReadError, qt_error_string(int(errno)));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return readBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return readFdFh(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
qint64 QFSFileEnginePrivate::nativeReadLine(char *data, qint64 maxlen)
|
||||||
|
{
|
||||||
|
return readLineFdFh(data, maxlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
qint64 QFSFileEnginePrivate::nativeWrite(const char *data, qint64 len)
|
||||||
|
{
|
||||||
|
return writeFdFh(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
qint64 QFSFileEnginePrivate::nativePos() const
|
||||||
|
{
|
||||||
|
return posFdFh();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
bool QFSFileEnginePrivate::nativeSeek(qint64 pos)
|
||||||
|
{
|
||||||
|
return seekFdFh(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
int QFSFileEnginePrivate::nativeHandle() const
|
||||||
|
{
|
||||||
|
return fh ? fileno(fh) : fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
bool QFSFileEnginePrivate::nativeIsSequential() const
|
||||||
|
{
|
||||||
|
return isSequentialFdFh();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEngine::remove()
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
QSystemError error;
|
||||||
|
bool ret = QFileSystemEngine::removeFile(d->fileEntry, error);
|
||||||
|
d->metaData.clear();
|
||||||
|
if (!ret) {
|
||||||
|
setError(QFile::RemoveError, error.toString());
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEngine::copy(const QString &newName)
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
QSystemError error;
|
||||||
|
bool ret = QFileSystemEngine::copyFile(d->fileEntry, QFileSystemEntry(newName), error);
|
||||||
|
if (!ret) {
|
||||||
|
setError(QFile::CopyError, error.toString());
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEngine::renameOverwrite(const QString &newName)
|
||||||
|
{
|
||||||
|
// On Unix, rename() overwrites.
|
||||||
|
return rename(newName);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEngine::rename(const QString &newName)
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
QSystemError error;
|
||||||
|
bool ret = QFileSystemEngine::renameFile(d->fileEntry, QFileSystemEntry(newName), error);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
setError(QFile::RenameError, error.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEngine::link(const QString &newName)
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
QSystemError error;
|
||||||
|
bool ret = QFileSystemEngine::createLink(d->fileEntry, QFileSystemEntry(newName), error);
|
||||||
|
if (!ret) {
|
||||||
|
setError(QFile::RenameError, error.toString());
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 QFSFileEnginePrivate::nativeSize() const
|
||||||
|
{
|
||||||
|
return sizeFdFh();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const
|
||||||
|
{
|
||||||
|
return QFileSystemEngine::createDirectory(QFileSystemEntry(name), createParentDirectories);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const
|
||||||
|
{
|
||||||
|
return QFileSystemEngine::removeDirectory(QFileSystemEntry(name), recurseParentDirectories);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEngine::caseSensitive() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEngine::setCurrentPath(const QString &path)
|
||||||
|
{
|
||||||
|
return QFileSystemEngine::setCurrentPath(QFileSystemEntry(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFSFileEngine::currentPath(const QString &)
|
||||||
|
{
|
||||||
|
return QFileSystemEngine::currentPath().filePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFSFileEngine::homePath()
|
||||||
|
{
|
||||||
|
return QFileSystemEngine::homePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFSFileEngine::rootPath()
|
||||||
|
{
|
||||||
|
return QFileSystemEngine::rootPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFSFileEngine::tempPath()
|
||||||
|
{
|
||||||
|
return QFileSystemEngine::tempPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileInfoList QFSFileEngine::drives()
|
||||||
|
{
|
||||||
|
QFileInfoList ret;
|
||||||
|
ret.append(QFileInfo(rootPath()));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) const
|
||||||
|
{
|
||||||
|
if (!tried_stat || !metaData.hasFlags(flags)) {
|
||||||
|
tried_stat = 1;
|
||||||
|
|
||||||
|
int localFd = fd;
|
||||||
|
if (fh && fileEntry.isEmpty())
|
||||||
|
localFd = QT_FILENO(fh);
|
||||||
|
if (localFd != -1)
|
||||||
|
QFileSystemEngine::fillMetaData(localFd, metaData);
|
||||||
|
|
||||||
|
if (metaData.missingFlags(flags) && !fileEntry.isEmpty())
|
||||||
|
QFileSystemEngine::fillMetaData(fileEntry, metaData, metaData.missingFlags(flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
return metaData.exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEnginePrivate::isSymlink() const
|
||||||
|
{
|
||||||
|
if (!metaData.hasFlags(QFileSystemMetaData::LinkType))
|
||||||
|
QFileSystemEngine::fillMetaData(fileEntry, metaData, QFileSystemMetaData::LinkType);
|
||||||
|
|
||||||
|
return metaData.isLink();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const
|
||||||
|
{
|
||||||
|
Q_D(const QFSFileEngine);
|
||||||
|
|
||||||
|
if (type & Refresh)
|
||||||
|
d->metaData.clear();
|
||||||
|
|
||||||
|
QAbstractFileEngine::FileFlags ret = 0;
|
||||||
|
|
||||||
|
if (type & FlagsMask)
|
||||||
|
ret |= LocalDiskFlag;
|
||||||
|
|
||||||
|
bool exists;
|
||||||
|
{
|
||||||
|
QFileSystemMetaData::MetaDataFlags queryFlags = 0;
|
||||||
|
|
||||||
|
queryFlags |= QFileSystemMetaData::MetaDataFlags(uint(type))
|
||||||
|
& QFileSystemMetaData::Permissions;
|
||||||
|
|
||||||
|
if (type & TypesMask)
|
||||||
|
queryFlags |= QFileSystemMetaData::AliasType
|
||||||
|
| QFileSystemMetaData::LinkType
|
||||||
|
| QFileSystemMetaData::FileType
|
||||||
|
| QFileSystemMetaData::DirectoryType
|
||||||
|
| QFileSystemMetaData::BundleType;
|
||||||
|
|
||||||
|
if (type & FlagsMask)
|
||||||
|
queryFlags |= QFileSystemMetaData::HiddenAttribute
|
||||||
|
| QFileSystemMetaData::ExistsAttribute;
|
||||||
|
|
||||||
|
queryFlags |= QFileSystemMetaData::LinkType;
|
||||||
|
|
||||||
|
exists = d->doStat(queryFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exists && !d->metaData.isLink())
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (exists && (type & PermsMask))
|
||||||
|
ret |= FileFlags(uint(d->metaData.permissions()));
|
||||||
|
|
||||||
|
if (type & TypesMask) {
|
||||||
|
if (d->metaData.isAlias()) {
|
||||||
|
ret |= LinkType;
|
||||||
|
} else {
|
||||||
|
if ((type & LinkType) && d->metaData.isLink())
|
||||||
|
ret |= LinkType;
|
||||||
|
if (exists) {
|
||||||
|
if (d->metaData.isFile()) {
|
||||||
|
ret |= FileType;
|
||||||
|
} else if (d->metaData.isDirectory()) {
|
||||||
|
ret |= DirectoryType;
|
||||||
|
if ((type & BundleType) && d->metaData.isBundle())
|
||||||
|
ret |= BundleType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type & FlagsMask) {
|
||||||
|
if (exists)
|
||||||
|
ret |= ExistsFlag;
|
||||||
|
if (d->fileEntry.isRoot())
|
||||||
|
ret |= RootFlag;
|
||||||
|
else if (d->metaData.isHidden())
|
||||||
|
ret |= HiddenFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFSFileEngine::fileName(FileName file) const
|
||||||
|
{
|
||||||
|
Q_D(const QFSFileEngine);
|
||||||
|
if (file == BundleName) {
|
||||||
|
return QFileSystemEngine::bundleName(d->fileEntry);
|
||||||
|
} else if (file == BaseName) {
|
||||||
|
return d->fileEntry.fileName();
|
||||||
|
} else if (file == PathName) {
|
||||||
|
return d->fileEntry.path();
|
||||||
|
} else if (file == AbsoluteName || file == AbsolutePathName) {
|
||||||
|
QFileSystemEntry entry(QFileSystemEngine::absoluteName(d->fileEntry));
|
||||||
|
if (file == AbsolutePathName) {
|
||||||
|
return entry.path();
|
||||||
|
}
|
||||||
|
return entry.filePath();
|
||||||
|
} else if (file == CanonicalName || file == CanonicalPathName) {
|
||||||
|
QFileSystemEntry entry(QFileSystemEngine::canonicalName(d->fileEntry, d->metaData));
|
||||||
|
if (file == CanonicalPathName)
|
||||||
|
return entry.path();
|
||||||
|
return entry.filePath();
|
||||||
|
} else if (file == LinkName) {
|
||||||
|
if (d->isSymlink()) {
|
||||||
|
QFileSystemEntry entry = QFileSystemEngine::getLinkTarget(d->fileEntry, d->metaData);
|
||||||
|
return entry.filePath();
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
return d->fileEntry.filePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEngine::isRelativePath() const
|
||||||
|
{
|
||||||
|
Q_D(const QFSFileEngine);
|
||||||
|
return d->fileEntry.filePath().length() ? d->fileEntry.filePath()[0] != QLatin1Char('/') : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint QFSFileEngine::ownerId(FileOwner own) const
|
||||||
|
{
|
||||||
|
Q_D(const QFSFileEngine);
|
||||||
|
static const uint nobodyID = (uint) -2;
|
||||||
|
|
||||||
|
if (d->doStat(QFileSystemMetaData::OwnerIds))
|
||||||
|
return d->metaData.ownerId(own);
|
||||||
|
|
||||||
|
return nobodyID;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QFSFileEngine::owner(FileOwner own) const
|
||||||
|
{
|
||||||
|
if (own == OwnerUser)
|
||||||
|
return QFileSystemEngine::resolveUserName(ownerId(own));
|
||||||
|
return QFileSystemEngine::resolveGroupName(ownerId(own));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEngine::setPermissions(uint perms)
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
QSystemError error;
|
||||||
|
if (!QFileSystemEngine::setPermissions(d->fileEntry, QFile::Permissions(perms), error, 0)) {
|
||||||
|
setError(QFile::PermissionsError, error.toString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEngine::setSize(qint64 size)
|
||||||
|
{
|
||||||
|
Q_D(QFSFileEngine);
|
||||||
|
bool ret = false;
|
||||||
|
if (d->fd != -1)
|
||||||
|
ret = QT_FTRUNCATE(d->fd, size) == 0;
|
||||||
|
else if (d->fh)
|
||||||
|
ret = QT_FTRUNCATE(QT_FILENO(d->fh), size) == 0;
|
||||||
|
else
|
||||||
|
ret = QT_TRUNCATE(d->fileEntry.nativeFilePath().constData(), size) == 0;
|
||||||
|
if (!ret)
|
||||||
|
setError(QFile::ResizeError, qt_error_string(errno));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDateTime QFSFileEngine::fileTime(FileTime time) const
|
||||||
|
{
|
||||||
|
Q_D(const QFSFileEngine);
|
||||||
|
|
||||||
|
if (d->doStat(QFileSystemMetaData::Times))
|
||||||
|
return d->metaData.fileTime(time);
|
||||||
|
|
||||||
|
return QDateTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags)
|
||||||
|
{
|
||||||
|
Q_Q(QFSFileEngine);
|
||||||
|
Q_UNUSED(flags);
|
||||||
|
if (openMode == QIODevice::NotOpen) {
|
||||||
|
q->setError(QFile::PermissionsError, qt_error_string(int(EACCES)));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset < 0 || offset != qint64(QT_OFF_T(offset))
|
||||||
|
|| size < 0 || quint64(size) > quint64(size_t(-1))) {
|
||||||
|
q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL)));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we know the mapping will extend beyond EOF, fail early to avoid
|
||||||
|
// undefined behavior. Otherwise, let mmap have its say.
|
||||||
|
if (doStat(QFileSystemMetaData::SizeAttribute)
|
||||||
|
&& (QT_OFF_T(size) > metaData.size() - QT_OFF_T(offset)))
|
||||||
|
qWarning("QFSFileEngine::map: Mapping a file beyond its size is not portable");
|
||||||
|
|
||||||
|
int access = 0;
|
||||||
|
if (openMode & QIODevice::ReadOnly) access |= PROT_READ;
|
||||||
|
if (openMode & QIODevice::WriteOnly) access |= PROT_WRITE;
|
||||||
|
|
||||||
|
#if defined(Q_OS_INTEGRITY)
|
||||||
|
int pageSize = sysconf(_SC_PAGESIZE);
|
||||||
|
#else
|
||||||
|
int pageSize = getpagesize();
|
||||||
|
#endif
|
||||||
|
int extra = offset % pageSize;
|
||||||
|
|
||||||
|
if (quint64(size + extra) > quint64((size_t)-1)) {
|
||||||
|
q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL)));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t realSize = (size_t)size + extra;
|
||||||
|
QT_OFF_T realOffset = QT_OFF_T(offset);
|
||||||
|
realOffset &= ~(QT_OFF_T(pageSize - 1));
|
||||||
|
|
||||||
|
void *mapAddress = QT_MMAP((void*)0, realSize,
|
||||||
|
access, MAP_SHARED, nativeHandle(), realOffset);
|
||||||
|
if (MAP_FAILED != mapAddress) {
|
||||||
|
uchar *address = extra + static_cast<uchar*>(mapAddress);
|
||||||
|
maps[address] = QPair<int,size_t>(extra, realSize);
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(errno) {
|
||||||
|
case EBADF:
|
||||||
|
q->setError(QFile::PermissionsError, qt_error_string(int(EACCES)));
|
||||||
|
break;
|
||||||
|
case ENFILE:
|
||||||
|
case ENOMEM:
|
||||||
|
q->setError(QFile::ResourceError, qt_error_string(int(errno)));
|
||||||
|
break;
|
||||||
|
case EINVAL:
|
||||||
|
// size are out of bounds
|
||||||
|
default:
|
||||||
|
q->setError(QFile::UnspecifiedError, qt_error_string(int(errno)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QFSFileEnginePrivate::unmap(uchar *ptr)
|
||||||
|
{
|
||||||
|
#if !defined(Q_OS_INTEGRITY)
|
||||||
|
Q_Q(QFSFileEngine);
|
||||||
|
if (!maps.contains(ptr)) {
|
||||||
|
q->setError(QFile::PermissionsError, qt_error_string(EACCES));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uchar *start = ptr - maps[ptr].first;
|
||||||
|
size_t len = maps[ptr].second;
|
||||||
|
if (-1 == munmap(start, len)) {
|
||||||
|
q->setError(QFile::UnspecifiedError, qt_error_string(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
maps.remove(ptr);
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // QT_NO_FSFILEENGINE
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
1053
src/app/core/backport/qfsfileengine_win.cpp
Normal file
1053
src/app/core/backport/qfsfileengine_win.cpp
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -210,7 +210,7 @@ bool QLockFile::tryLock(int timeout)
|
||||||
if (!d->isLocked && d->isApparentlyStale()) {
|
if (!d->isLocked && d->isApparentlyStale()) {
|
||||||
// Stale lock from another thread/process
|
// Stale lock from another thread/process
|
||||||
// Ensure two processes don't remove it at the same time
|
// Ensure two processes don't remove it at the same time
|
||||||
QLockFile rmlock(d->fileName + QLatin1String(".rmlock"));
|
QLockFile rmlock(d->fileName + QStringLiteral(".rmlock"));
|
||||||
if (rmlock.tryLock()) {
|
if (rmlock.tryLock()) {
|
||||||
if (d->isApparentlyStale() && d->removeStaleLock())
|
if (d->isApparentlyStale() && d->removeStaleLock())
|
||||||
continue;
|
continue;
|
||||||
|
@ -220,7 +220,7 @@ bool QLockFile::tryLock(int timeout)
|
||||||
}
|
}
|
||||||
if (timeout == 0 || (timeout > 0 && timer.hasExpired(timeout)))
|
if (timeout == 0 || (timeout > 0 && timer.hasExpired(timeout)))
|
||||||
return false;
|
return false;
|
||||||
QLockFileThread::msleep(sleepTime);
|
QThread::msleep(sleepTime);
|
||||||
if (sleepTime < 5 * 1000)
|
if (sleepTime < 5 * 1000)
|
||||||
sleepTime *= 2;
|
sleepTime *= 2;
|
||||||
}
|
}
|
193
src/app/core/backport/qlockfile_unix.cpp
Normal file
193
src/app/core/backport/qlockfile_unix.cpp
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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 "qlockfile_p.h"
|
||||||
|
|
||||||
|
#include <QTemporaryFile>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
#include "qcore_unix_p.h" // qt_safe_open
|
||||||
|
#include "qabstractfileengine_p.h"
|
||||||
|
//#include "qtemporaryfile_p.h"
|
||||||
|
|
||||||
|
#include <sys/file.h> // flock
|
||||||
|
#include <sys/types.h> // kill
|
||||||
|
#include <signal.h> // kill
|
||||||
|
#include <unistd.h> // gethostname
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
static QByteArray localHostName() // from QHostInfo::localHostName(), modified to return a QByteArray
|
||||||
|
{
|
||||||
|
QByteArray hostName(512, Qt::Uninitialized);
|
||||||
|
if (gethostname(hostName.data(), hostName.size()) == -1)
|
||||||
|
return QByteArray();
|
||||||
|
hostName.truncate(strlen(hostName.data()));
|
||||||
|
return hostName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ### merge into qt_safe_write?
|
||||||
|
static qint64 qt_write_loop(int fd, const char *data, qint64 len)
|
||||||
|
{
|
||||||
|
qint64 pos = 0;
|
||||||
|
while (pos < len) {
|
||||||
|
const qint64 ret = qt_safe_write(fd, data + pos, len - pos);
|
||||||
|
if (ret == -1) // e.g. partition full
|
||||||
|
return pos;
|
||||||
|
pos += ret;
|
||||||
|
}
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QLockFilePrivate::checkFcntlWorksAfterFlock()
|
||||||
|
{
|
||||||
|
#ifndef QT_NO_TEMPORARYFILE
|
||||||
|
QTemporaryFile file;
|
||||||
|
if (!file.open())
|
||||||
|
return 0;
|
||||||
|
const int fd = file.d_func()->engine()->handle();
|
||||||
|
#if defined(LOCK_EX) && defined(LOCK_NB)
|
||||||
|
if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
struct flock flockData;
|
||||||
|
flockData.l_type = F_WRLCK;
|
||||||
|
flockData.l_whence = SEEK_SET;
|
||||||
|
flockData.l_start = 0;
|
||||||
|
flockData.l_len = 0; // 0 = entire file
|
||||||
|
flockData.l_pid = getpid();
|
||||||
|
if (fcntl(fd, F_SETLK, &flockData) == -1) // for networked filesystems
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static QBasicAtomicInt fcntlOK = Q_BASIC_ATOMIC_INITIALIZER(-1);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
Checks that the OS isn't using POSIX locks to emulate flock().
|
||||||
|
Mac OS X is one of those.
|
||||||
|
*/
|
||||||
|
static bool fcntlWorksAfterFlock()
|
||||||
|
{
|
||||||
|
int value = fcntlOK.load();
|
||||||
|
if (Q_UNLIKELY(value == -1)) {
|
||||||
|
value = QLockFilePrivate::checkFcntlWorksAfterFlock();
|
||||||
|
fcntlOK.store(value);
|
||||||
|
}
|
||||||
|
return value == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool setNativeLocks(int fd)
|
||||||
|
{
|
||||||
|
#if defined(LOCK_EX) && defined(LOCK_NB)
|
||||||
|
if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
struct flock flockData;
|
||||||
|
flockData.l_type = F_WRLCK;
|
||||||
|
flockData.l_whence = SEEK_SET;
|
||||||
|
flockData.l_start = 0;
|
||||||
|
flockData.l_len = 0; // 0 = entire file
|
||||||
|
flockData.l_pid = getpid();
|
||||||
|
if (fcntlWorksAfterFlock() && fcntl(fd, F_SETLK, &flockData) == -1) // for networked filesystems
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLockFile::LockError QLockFilePrivate::tryLock_sys()
|
||||||
|
{
|
||||||
|
// Assemble data, to write in a single call to write
|
||||||
|
// (otherwise we'd have to check every write call)
|
||||||
|
// Use operator% from the fast builder to avoid multiple memory allocations.
|
||||||
|
QByteArray fileData = QByteArray::number(QCoreApplication::applicationPid()) % '\n'
|
||||||
|
% qAppName().toUtf8() % '\n'
|
||||||
|
% localHostName() % '\n';
|
||||||
|
|
||||||
|
const QByteArray lockFileName = QFile::encodeName(fileName);
|
||||||
|
const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY | O_CREAT | O_EXCL, 0644);
|
||||||
|
if (fd < 0) {
|
||||||
|
switch (errno) {
|
||||||
|
case EEXIST:
|
||||||
|
return QLockFile::LockFailedError;
|
||||||
|
case EACCES:
|
||||||
|
case EROFS:
|
||||||
|
return QLockFile::PermissionError;
|
||||||
|
default:
|
||||||
|
return QLockFile::UnknownError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Ensure nobody else can delete the file while we have it
|
||||||
|
if (!setNativeLocks(fd))
|
||||||
|
qWarning() << "setNativeLocks failed:" << strerror(errno);
|
||||||
|
|
||||||
|
// We hold the lock, continue.
|
||||||
|
fileHandle = fd;
|
||||||
|
|
||||||
|
QLockFile::LockError error = QLockFile::NoError;
|
||||||
|
if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size())
|
||||||
|
error = QLockFile::UnknownError; // partition full
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QLockFilePrivate::removeStaleLock()
|
||||||
|
{
|
||||||
|
const QByteArray lockFileName = QFile::encodeName(fileName);
|
||||||
|
const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY, 0644);
|
||||||
|
if (fd < 0) // gone already?
|
||||||
|
return false;
|
||||||
|
bool success = setNativeLocks(fd) && (::unlink(lockFileName) == 0);
|
||||||
|
close(fd);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QLockFilePrivate::isApparentlyStale() const
|
||||||
|
{
|
||||||
|
qint64 pid;
|
||||||
|
QString hostname, appname;
|
||||||
|
if (!getLockInfo(&pid, &hostname, &appname))
|
||||||
|
return false;
|
||||||
|
if (hostname == QString::fromLocal8Bit(localHostName())) {
|
||||||
|
if (::kill(pid, 0) == -1 && errno == ESRCH)
|
||||||
|
return true; // PID doesn't exist anymore
|
||||||
|
}
|
||||||
|
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
|
||||||
|
return staleLockTime > 0 && age > staleLockTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QLockFile::unlock()
|
||||||
|
{
|
||||||
|
Q_D(QLockFile);
|
||||||
|
if (!d->isLocked)
|
||||||
|
return;
|
||||||
|
close(d->fileHandle);
|
||||||
|
d->fileHandle = -1;
|
||||||
|
QFile::remove(d->fileName);
|
||||||
|
d->lockError = QLockFile::NoError;
|
||||||
|
d->isLocked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
116
src/app/core/backport/qlockfile_win.cpp
Normal file
116
src/app/core/backport/qlockfile_win.cpp
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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 "qlockfile_p.h"
|
||||||
|
#include "qfilesystementry_p.h"
|
||||||
|
#include <qt_windows.h>
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
QLockFile::LockError QLockFilePrivate::tryLock_sys()
|
||||||
|
{
|
||||||
|
SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
|
||||||
|
const QFileSystemEntry fileEntry(fileName);
|
||||||
|
// When writing, allow others to read.
|
||||||
|
// When reading, QFile will allow others to read and write, all good.
|
||||||
|
// Adding FILE_SHARE_DELETE would allow forceful deletion of stale files,
|
||||||
|
// but Windows doesn't allow recreating it while this handle is open anyway,
|
||||||
|
// so this would only create confusion (can't lock, but no lock file to read from).
|
||||||
|
const DWORD dwShareMode = FILE_SHARE_READ;
|
||||||
|
HANDLE fh = CreateFile((const wchar_t*)fileEntry.nativeFilePath().utf16(),
|
||||||
|
GENERIC_WRITE,
|
||||||
|
dwShareMode,
|
||||||
|
&securityAtts,
|
||||||
|
CREATE_NEW, // error if already exists
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
NULL);
|
||||||
|
if (fh == INVALID_HANDLE_VALUE) {
|
||||||
|
const DWORD lastError = GetLastError();
|
||||||
|
switch (lastError) {
|
||||||
|
case ERROR_SHARING_VIOLATION:
|
||||||
|
case ERROR_ALREADY_EXISTS:
|
||||||
|
case ERROR_FILE_EXISTS:
|
||||||
|
case ERROR_ACCESS_DENIED: // readonly file, or file still in use by another process. Assume the latter, since we don't create it readonly.
|
||||||
|
return QLockFile::LockFailedError;
|
||||||
|
default:
|
||||||
|
qWarning() << "Got unexpected locking error" << lastError;
|
||||||
|
return QLockFile::UnknownError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We hold the lock, continue.
|
||||||
|
fileHandle = fh;
|
||||||
|
// Assemble data, to write in a single call to write
|
||||||
|
// (otherwise we'd have to check every write call)
|
||||||
|
QByteArray fileData;
|
||||||
|
fileData += QByteArray::number(QCoreApplication::applicationPid());
|
||||||
|
fileData += '\n';
|
||||||
|
fileData += qAppName().toUtf8();
|
||||||
|
fileData += '\n';
|
||||||
|
//fileData += localHostname(); // gethostname requires winsock init, see QHostInfo...
|
||||||
|
fileData += '\n';
|
||||||
|
DWORD bytesWritten = 0;
|
||||||
|
QLockFile::LockError error = QLockFile::NoError;
|
||||||
|
if (!WriteFile(fh, fileData.constData(), fileData.size(), &bytesWritten, NULL) || !FlushFileBuffers(fh))
|
||||||
|
error = QLockFile::UnknownError; // partition full
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QLockFilePrivate::removeStaleLock()
|
||||||
|
{
|
||||||
|
// QFile::remove fails on Windows if the other process is still using the file, so it's not stale.
|
||||||
|
return QFile::remove(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QLockFilePrivate::isApparentlyStale() const
|
||||||
|
{
|
||||||
|
qint64 pid;
|
||||||
|
QString hostname, appname;
|
||||||
|
if (!getLockInfo(&pid, &hostname, &appname))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
|
||||||
|
if (!procHandle)
|
||||||
|
return true;
|
||||||
|
// We got a handle but check if process is still alive
|
||||||
|
DWORD dwR = ::WaitForSingleObject(procHandle, 0);
|
||||||
|
::CloseHandle(procHandle);
|
||||||
|
if (dwR == WAIT_TIMEOUT)
|
||||||
|
return true;
|
||||||
|
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
|
||||||
|
return staleLockTime > 0 && age > staleLockTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QLockFile::unlock()
|
||||||
|
{
|
||||||
|
Q_D(QLockFile);
|
||||||
|
if (!d->isLocked)
|
||||||
|
return;
|
||||||
|
CloseHandle(d->fileHandle);
|
||||||
|
QFile::remove(d->fileName);
|
||||||
|
d->lockError = QLockFile::NoError;
|
||||||
|
d->isLocked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
133
src/app/core/backport/qmutexpool.cpp
Normal file
133
src/app/core/backport/qmutexpool.cpp
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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 "qatomic.h"
|
||||||
|
#include "qmutexpool_p.h"
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#ifndef QT_NO_THREAD
|
||||||
|
|
||||||
|
Q_GLOBAL_STATIC_WITH_ARGS(QMutexPool, globalMutexPool, (QMutex::Recursive))
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class QMutexPool
|
||||||
|
\inmodule QtCore
|
||||||
|
\brief The QMutexPool class provides a pool of QMutex objects.
|
||||||
|
|
||||||
|
\internal
|
||||||
|
|
||||||
|
\ingroup thread
|
||||||
|
|
||||||
|
QMutexPool is a convenience class that provides access to a fixed
|
||||||
|
number of QMutex objects.
|
||||||
|
|
||||||
|
Typical use of a QMutexPool is in situations where it is not
|
||||||
|
possible or feasible to use one QMutex for every protected object.
|
||||||
|
The mutex pool will return a mutex based on the address of the
|
||||||
|
object that needs protection.
|
||||||
|
|
||||||
|
For example, consider this simple class:
|
||||||
|
|
||||||
|
\snippet code/src_corelib_thread_qmutexpool.cpp 0
|
||||||
|
|
||||||
|
Adding a QMutex member to the Number class does not make sense,
|
||||||
|
because it is so small. However, in order to ensure that access to
|
||||||
|
each Number is protected, you need to use a mutex. In this case, a
|
||||||
|
QMutexPool would be ideal.
|
||||||
|
|
||||||
|
Code to calculate the square of a number would then look something
|
||||||
|
like this:
|
||||||
|
|
||||||
|
\snippet code/src_corelib_thread_qmutexpool.cpp 1
|
||||||
|
|
||||||
|
This function will safely calculate the square of a number, since
|
||||||
|
it uses a mutex from a QMutexPool. The mutex is locked and
|
||||||
|
unlocked automatically by the QMutexLocker class. See the
|
||||||
|
QMutexLocker documentation for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs a QMutexPool, reserving space for \a size QMutexes. All
|
||||||
|
mutexes in the pool are created with \a recursionMode. By default,
|
||||||
|
all mutexes are non-recursive.
|
||||||
|
|
||||||
|
The QMutexes are created when needed, and deleted when the
|
||||||
|
QMutexPool is destructed.
|
||||||
|
*/
|
||||||
|
QMutexPool::QMutexPool(QMutex::RecursionMode recursionMode, int size)
|
||||||
|
: mutexes(size), recursionMode(recursionMode)
|
||||||
|
{
|
||||||
|
for (int index = 0; index < mutexes.count(); ++index) {
|
||||||
|
mutexes[index].store(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Destructs a QMutexPool. All QMutexes that were created by the pool
|
||||||
|
are deleted.
|
||||||
|
*/
|
||||||
|
QMutexPool::~QMutexPool()
|
||||||
|
{
|
||||||
|
for (int index = 0; index < mutexes.count(); ++index)
|
||||||
|
delete mutexes[index].load();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the global QMutexPool instance.
|
||||||
|
*/
|
||||||
|
QMutexPool *QMutexPool::instance()
|
||||||
|
{
|
||||||
|
return globalMutexPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn QMutexPool::get(const void *address)
|
||||||
|
Returns a QMutex from the pool. QMutexPool uses the value \a address
|
||||||
|
to determine which mutex is returned from the pool.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
create the mutex for the given index
|
||||||
|
*/
|
||||||
|
QMutex *QMutexPool::createMutex(int index)
|
||||||
|
{
|
||||||
|
// mutex not created, create one
|
||||||
|
QMutex *newMutex = new QMutex(recursionMode);
|
||||||
|
if (!mutexes[index].testAndSetRelease(0, newMutex))
|
||||||
|
delete newMutex;
|
||||||
|
return mutexes[index].load();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns a QMutex from the global mutex pool.
|
||||||
|
*/
|
||||||
|
QMutex *QMutexPool::globalInstanceGet(const void *address)
|
||||||
|
{
|
||||||
|
QMutexPool * const globalInstance = globalMutexPool();
|
||||||
|
if (globalInstance == 0)
|
||||||
|
return 0;
|
||||||
|
return globalInstance->get(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // QT_NO_THREAD
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
70
src/app/core/backport/qmutexpool_p.h
Normal file
70
src/app/core/backport/qmutexpool_p.h
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QMUTEXPOOL_P_H
|
||||||
|
#define QMUTEXPOOL_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists for the convenience
|
||||||
|
// of QSettings. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "QtCore/qatomic.h"
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QVarLengthArray>
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#ifndef QT_NO_THREAD
|
||||||
|
|
||||||
|
class QMutexPool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit QMutexPool(QMutex::RecursionMode recursionMode = QMutex::NonRecursive, int size = 131);
|
||||||
|
~QMutexPool();
|
||||||
|
|
||||||
|
inline QMutex *get(const void *address) {
|
||||||
|
int index = uint(quintptr(address)) % mutexes.count();
|
||||||
|
QMutex *m = mutexes[index].load();
|
||||||
|
if (m)
|
||||||
|
return m;
|
||||||
|
else
|
||||||
|
return createMutex(index);
|
||||||
|
}
|
||||||
|
static QMutexPool *instance();
|
||||||
|
static QMutex *globalInstanceGet(const void *address);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMutex *createMutex(int index);
|
||||||
|
QVarLengthArray<QAtomicPointer<QMutex>, 131> mutexes;
|
||||||
|
QMutex::RecursionMode recursionMode;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QT_NO_THREAD
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif // QMUTEXPOOL_P_H
|
77
src/app/core/backport/qresource.h
Normal file
77
src/app/core/backport/qresource.h
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QRESOURCE_H
|
||||||
|
#define QRESOURCE_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QLocale>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
class QResourcePrivate;
|
||||||
|
|
||||||
|
class QResource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QResource(const QString &file=QString(), const QLocale &locale=QLocale());
|
||||||
|
~QResource();
|
||||||
|
|
||||||
|
void setFileName(const QString &file);
|
||||||
|
QString fileName() const;
|
||||||
|
QString absoluteFilePath() const;
|
||||||
|
|
||||||
|
void setLocale(const QLocale &locale);
|
||||||
|
QLocale locale() const;
|
||||||
|
|
||||||
|
bool isValid() const;
|
||||||
|
|
||||||
|
bool isCompressed() const;
|
||||||
|
qint64 size() const;
|
||||||
|
const uchar *data() const;
|
||||||
|
|
||||||
|
static void addSearchPath(const QString &path);
|
||||||
|
static QStringList searchPaths();
|
||||||
|
|
||||||
|
static bool registerResource(const QString &rccFilename, const QString &resourceRoot=QString());
|
||||||
|
static bool unregisterResource(const QString &rccFilename, const QString &resourceRoot=QString());
|
||||||
|
|
||||||
|
static bool registerResource(const uchar *rccData, const QString &resourceRoot=QString());
|
||||||
|
static bool unregisterResource(const uchar *rccData, const QString &resourceRoot=QString());
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class QResourceFileEngine;
|
||||||
|
friend class QResourceFileEngineIterator;
|
||||||
|
bool isDir() const;
|
||||||
|
inline bool isFile() const { return !isDir(); }
|
||||||
|
QStringList children() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QScopedPointer<QResourcePrivate> d_ptr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Q_DECLARE_PRIVATE(QResource)
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif // QRESOURCE_H
|
98
src/app/core/backport/qresource_p.h
Normal file
98
src/app/core/backport/qresource_p.h
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QRESOURCE_P_H
|
||||||
|
#define QRESOURCE_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists purely as an
|
||||||
|
// implementation detail. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "qabstractfileengine_p.h"
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
class QResourceFileEnginePrivate;
|
||||||
|
class QResourceFileEngine : public QAbstractFileEngine
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Q_DECLARE_PRIVATE(QResourceFileEngine)
|
||||||
|
public:
|
||||||
|
explicit QResourceFileEngine(const QString &path);
|
||||||
|
~QResourceFileEngine();
|
||||||
|
|
||||||
|
virtual void setFileName(const QString &file);
|
||||||
|
|
||||||
|
virtual bool open(QIODevice::OpenMode flags) ;
|
||||||
|
virtual bool close();
|
||||||
|
virtual bool flush();
|
||||||
|
virtual qint64 size() const;
|
||||||
|
virtual qint64 pos() const;
|
||||||
|
virtual bool atEnd() const;
|
||||||
|
virtual bool seek(qint64);
|
||||||
|
virtual qint64 read(char *data, qint64 maxlen);
|
||||||
|
virtual qint64 write(const char *data, qint64 len);
|
||||||
|
|
||||||
|
virtual bool remove();
|
||||||
|
virtual bool copy(const QString &newName);
|
||||||
|
virtual bool rename(const QString &newName);
|
||||||
|
virtual bool link(const QString &newName);
|
||||||
|
|
||||||
|
virtual bool isSequential() const;
|
||||||
|
|
||||||
|
virtual bool isRelativePath() const;
|
||||||
|
|
||||||
|
virtual bool mkdir(const QString &dirName, bool createParentDirectories) const;
|
||||||
|
virtual bool rmdir(const QString &dirName, bool recurseParentDirectories) const;
|
||||||
|
|
||||||
|
virtual bool setSize(qint64 size);
|
||||||
|
|
||||||
|
virtual QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const;
|
||||||
|
|
||||||
|
virtual bool caseSensitive() const;
|
||||||
|
|
||||||
|
virtual FileFlags fileFlags(FileFlags type) const;
|
||||||
|
|
||||||
|
virtual bool setPermissions(uint perms);
|
||||||
|
|
||||||
|
virtual QString fileName(QAbstractFileEngine::FileName file) const;
|
||||||
|
|
||||||
|
virtual uint ownerId(FileOwner) const;
|
||||||
|
virtual QString owner(FileOwner) const;
|
||||||
|
|
||||||
|
virtual QDateTime fileTime(FileTime time) const;
|
||||||
|
|
||||||
|
virtual Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames);
|
||||||
|
virtual Iterator *endEntryList();
|
||||||
|
|
||||||
|
bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0);
|
||||||
|
bool supportsExtension(Extension extension) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif // QRESOURCE_P_H
|
154
src/app/core/backport/qsystemerror.cpp
Normal file
154
src/app/core/backport/qsystemerror.cpp
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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 <QtGlobal>
|
||||||
|
#include "qsystemerror_p.h"
|
||||||
|
#if !defined(Q_OS_WINCE)
|
||||||
|
# include <errno.h>
|
||||||
|
# if defined(Q_CC_MSVC)
|
||||||
|
# include <crtdbg.h>
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# if (_WIN32_WCE >= 0x700)
|
||||||
|
# include <errno.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
# include <qt_windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#if !defined(Q_OS_WIN) && !defined(QT_NO_THREAD) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \
|
||||||
|
defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L
|
||||||
|
namespace {
|
||||||
|
// There are two incompatible versions of strerror_r:
|
||||||
|
// a) the XSI/POSIX.1 version, which returns an int,
|
||||||
|
// indicating success or not
|
||||||
|
// b) the GNU version, which returns a char*, which may or may not
|
||||||
|
// be the beginning of the buffer we used
|
||||||
|
// The GNU libc manpage for strerror_r says you should use the XSI
|
||||||
|
// version in portable code. However, it's impossible to do that if
|
||||||
|
// _GNU_SOURCE is defined so we use C++ overloading to decide what to do
|
||||||
|
// depending on the return type
|
||||||
|
static inline QString fromstrerror_helper(int, const QByteArray &buf)
|
||||||
|
{
|
||||||
|
return QString::fromLocal8Bit(buf);
|
||||||
|
}
|
||||||
|
static inline QString fromstrerror_helper(const char *str, const QByteArray &)
|
||||||
|
{
|
||||||
|
return QString::fromLocal8Bit(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
static QString windowsErrorString(int errorCode)
|
||||||
|
{
|
||||||
|
QString ret;
|
||||||
|
#ifndef Q_OS_WINRT
|
||||||
|
wchar_t *string = 0;
|
||||||
|
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
|
||||||
|
NULL,
|
||||||
|
errorCode,
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
(LPWSTR)&string,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
ret = QString::fromWCharArray(string);
|
||||||
|
LocalFree((HLOCAL)string);
|
||||||
|
#else
|
||||||
|
wchar_t errorString[1024];
|
||||||
|
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
|
||||||
|
NULL,
|
||||||
|
errorCode,
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
(LPWSTR)&errorString,
|
||||||
|
sizeof(errorString)/sizeof(wchar_t),
|
||||||
|
NULL);
|
||||||
|
ret = QString::fromWCharArray(errorString);
|
||||||
|
#endif // Q_OS_WINRT
|
||||||
|
|
||||||
|
if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND)
|
||||||
|
ret = QString::fromLatin1("The specified module could not be found.");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static QString standardLibraryErrorString(int errorCode)
|
||||||
|
{
|
||||||
|
const char *s = 0;
|
||||||
|
QString ret;
|
||||||
|
switch (errorCode) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case EACCES:
|
||||||
|
s = QT_TRANSLATE_NOOP("QIODevice", "Permission denied");
|
||||||
|
break;
|
||||||
|
case EMFILE:
|
||||||
|
s = QT_TRANSLATE_NOOP("QIODevice", "Too many open files");
|
||||||
|
break;
|
||||||
|
case ENOENT:
|
||||||
|
s = QT_TRANSLATE_NOOP("QIODevice", "No such file or directory");
|
||||||
|
break;
|
||||||
|
case ENOSPC:
|
||||||
|
s = QT_TRANSLATE_NOOP("QIODevice", "No space left on device");
|
||||||
|
break;
|
||||||
|
default: {
|
||||||
|
#ifdef Q_OS_WINCE
|
||||||
|
ret = windowsErrorString(errorCode);
|
||||||
|
#else
|
||||||
|
#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX)
|
||||||
|
QByteArray buf(1024, '\0');
|
||||||
|
ret = fromstrerror_helper(strerror_r(errorCode, buf.data(), buf.size()), buf);
|
||||||
|
#else
|
||||||
|
ret = QString::fromLocal8Bit(strerror(errorCode));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
break; }
|
||||||
|
}
|
||||||
|
if (s) {
|
||||||
|
// ######## this breaks moc build currently
|
||||||
|
// ret = QCoreApplication::translate("QIODevice", s);
|
||||||
|
ret = QString::fromLatin1(s);
|
||||||
|
}
|
||||||
|
return ret.trimmed();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QSystemError::toString()
|
||||||
|
{
|
||||||
|
switch(errorScope) {
|
||||||
|
case NativeError:
|
||||||
|
#if defined (Q_OS_WIN)
|
||||||
|
return windowsErrorString(errorCode);
|
||||||
|
#else
|
||||||
|
//unix: fall through as native and standard library are the same
|
||||||
|
#endif
|
||||||
|
case StandardLibraryError:
|
||||||
|
return standardLibraryErrorString(errorCode);
|
||||||
|
default:
|
||||||
|
qWarning("invalid error scope");
|
||||||
|
//fall through
|
||||||
|
case NoError:
|
||||||
|
return QLatin1String("No error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
85
src/app/core/backport/qsystemerror_p.h
Normal file
85
src/app/core/backport/qsystemerror_p.h
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QSYSTEMERROR_P_H
|
||||||
|
#define QSYSTEMERROR_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists purely as an
|
||||||
|
// implementation detail. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
class QSystemError
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum ErrorScope
|
||||||
|
{
|
||||||
|
NoError,
|
||||||
|
StandardLibraryError,
|
||||||
|
NativeError
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QSystemError(int error, ErrorScope scope);
|
||||||
|
inline QSystemError();
|
||||||
|
|
||||||
|
QString toString();
|
||||||
|
inline ErrorScope scope();
|
||||||
|
inline int error();
|
||||||
|
|
||||||
|
//data members
|
||||||
|
int errorCode;
|
||||||
|
ErrorScope errorScope;
|
||||||
|
};
|
||||||
|
|
||||||
|
QSystemError::QSystemError(int error, QSystemError::ErrorScope scope)
|
||||||
|
: errorCode(error), errorScope(scope)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QSystemError::QSystemError()
|
||||||
|
: errorCode(0), errorScope(NoError)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QSystemError::ErrorScope QSystemError::scope()
|
||||||
|
{
|
||||||
|
return errorScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QSystemError::error()
|
||||||
|
{
|
||||||
|
return errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif // QSYSTEMERROR_P_H
|
90
src/app/core/backport/qsystemlibrary_p.h
Normal file
90
src/app/core/backport/qsystemlibrary_p.h
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL$
|
||||||
|
**
|
||||||
|
** 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$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QSYSTEMLIBRARY_P_H
|
||||||
|
#define QSYSTEMLIBRARY_P_H
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
# include <QString>
|
||||||
|
# include <qt_windows.h>
|
||||||
|
|
||||||
|
class QSystemLibrary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit QSystemLibrary(const QString &libraryName)
|
||||||
|
{
|
||||||
|
m_libraryName = libraryName;
|
||||||
|
m_handle = 0;
|
||||||
|
m_didLoad = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit QSystemLibrary(const wchar_t *libraryName)
|
||||||
|
{
|
||||||
|
m_libraryName = QString::fromWCharArray(libraryName);
|
||||||
|
m_handle = 0;
|
||||||
|
m_didLoad = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load(bool onlySystemDirectory = true)
|
||||||
|
{
|
||||||
|
m_handle = load((const wchar_t *)m_libraryName.utf16(), onlySystemDirectory);
|
||||||
|
m_didLoad = true;
|
||||||
|
return (m_handle != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isLoaded()
|
||||||
|
{
|
||||||
|
return (m_handle != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
QFunctionPointer resolve(const char *symbol)
|
||||||
|
{
|
||||||
|
if (!m_didLoad)
|
||||||
|
load();
|
||||||
|
if (!m_handle)
|
||||||
|
return 0;
|
||||||
|
#ifdef Q_OS_WINCE
|
||||||
|
return QFunctionPointer(GetProcAddress(m_handle, (const wchar_t*)QString::fromLatin1(symbol).utf16()));
|
||||||
|
#else
|
||||||
|
return QFunctionPointer(GetProcAddress(m_handle, symbol));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static QFunctionPointer resolve(const QString &libraryName, const char *symbol)
|
||||||
|
{
|
||||||
|
return QSystemLibrary(libraryName).resolve(symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Q_CORE_EXPORT HINSTANCE load(const wchar_t *lpFileName, bool onlySystemDirectory = true);
|
||||||
|
private:
|
||||||
|
HINSTANCE m_handle;
|
||||||
|
QString m_libraryName;
|
||||||
|
bool m_didLoad;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //Q_OS_WIN
|
||||||
|
|
||||||
|
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
|
#endif //QSYSTEMLIBRARY_P_H
|
|
@ -5,15 +5,67 @@ HEADERS += \
|
||||||
$$PWD/vapplication.h \
|
$$PWD/vapplication.h \
|
||||||
$$PWD/undoevent.h \
|
$$PWD/undoevent.h \
|
||||||
$$PWD/vsettings.h \
|
$$PWD/vsettings.h \
|
||||||
$$PWD/qcommandlineoption.h \
|
$$PWD/backport/qcommandlineoption.h \
|
||||||
$$PWD/qcommandlineparser.h \
|
$$PWD/backport/qcommandlineparser.h \
|
||||||
$$PWD/qlockfile.h \
|
$$PWD/backport/qlockfile.h \
|
||||||
$$PWD/qlockfile_p.h
|
$$PWD/backport/qlockfile_p.h \
|
||||||
|
$$PWD/backport/qfilesystementry_p.h \
|
||||||
|
$$PWD/backport/qfsfileengine_p.h \
|
||||||
|
$$PWD/backport/qabstractfileengine_p.h \
|
||||||
|
$$PWD/backport/qresource_p.h \
|
||||||
|
$$PWD/backport/qresource.h \
|
||||||
|
$$PWD/backport/qfilesystemmetadata_p.h \
|
||||||
|
$$PWD/backport/qfilesystemengine_p.h \
|
||||||
|
$$PWD/backport/qsystemerror_p.h \
|
||||||
|
$$PWD/backport/qfsfileengine_iterator_p.h \
|
||||||
|
$$PWD/backport/qfilesystemiterator_p.h \
|
||||||
|
$$PWD/backport/qfileinfo_p.h \
|
||||||
|
$$PWD/backport/qmutexpool_p.h \
|
||||||
|
$$PWD/backport/qsystemlibrary_p.h \
|
||||||
|
|
||||||
|
unix:!macx {
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/backport/qcore_unix_p.h
|
||||||
|
}
|
||||||
|
|
||||||
|
unix:macx {
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/backport/qcore_mac_p.h
|
||||||
|
}
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/vapplication.cpp \
|
$$PWD/vapplication.cpp \
|
||||||
$$PWD/undoevent.cpp \
|
$$PWD/undoevent.cpp \
|
||||||
$$PWD/vsettings.cpp \
|
$$PWD/vsettings.cpp \
|
||||||
$$PWD/qcommandlineoption.cpp \
|
$$PWD/backport/qcommandlineoption.cpp \
|
||||||
$$PWD/qcommandlineparser.cpp \
|
$$PWD/backport/qcommandlineparser.cpp \
|
||||||
$$PWD/qlockfile.cpp
|
$$PWD/backport/qlockfile.cpp \
|
||||||
|
$$PWD/backport/qfilesystementry.cpp \
|
||||||
|
$$PWD/backport/qfsfileengine.cpp \
|
||||||
|
$$PWD/backport/qabstractfileengine.cpp \
|
||||||
|
$$PWD/backport/qfilesystemengine.cpp \
|
||||||
|
$$PWD/backport/qsystemerror.cpp \
|
||||||
|
$$PWD/backport/qfsfileengine_iterator.cpp \
|
||||||
|
$$PWD/backport/qmutexpool.cpp
|
||||||
|
|
||||||
|
unix:!macx {
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/backport/qlockfile_unix.cpp \
|
||||||
|
$$PWD/backport/qfilesystemiterator_unix.cpp \
|
||||||
|
$$PWD/backport/qfsfileengine_unix.cpp \
|
||||||
|
$$PWD/backport/qfilesystemengine_unix.cpp \
|
||||||
|
$$PWD/backport/qcore_unix.cpp
|
||||||
|
}
|
||||||
|
|
||||||
|
unix:macx {
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/backport/qcore_mac.cpp
|
||||||
|
}
|
||||||
|
|
||||||
|
win32 {
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/backport/qlockfile_win.cpp \
|
||||||
|
$$PWD/backport/qfilesystemiterator_win.cpp \
|
||||||
|
$$PWD/backport/qfsfileengine_win.cpp \
|
||||||
|
$$PWD/backport/qfilesystemengine_win.cpp
|
||||||
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
# include "qlockfile.h"
|
# include "backport/qlockfile.h"
|
||||||
#else
|
#else
|
||||||
# include <QLockFile>
|
# include <QLockFile>
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
|
#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
|
||||||
# include "../core/qcommandlineparser.h"
|
# include "../core/backport/qcommandlineparser.h"
|
||||||
#else
|
#else
|
||||||
# include <QCommandLineParser>
|
# include <QCommandLineParser>
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
# include "core/qlockfile.h"
|
# include "core/backport/qlockfile.h"
|
||||||
#else
|
#else
|
||||||
# include <QLockFile>
|
# include <QLockFile>
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user