Modernize and unify filesystem code on Apple platforms.
Replace deprecated File Manager APIs with modern equivalents. Change some Q_OS_MACX to Q_OS_DARWIN in file system related code. All of these apply to iOS as well as OS X, and were ifdef'ed for OS X only primarily due to legacy reasons - carryovers from Qt 4 or Carbon APIs which have since been refactored into using CoreFoundation. This also makes the code consistent with the documentation. Change-Id: I414e9bdfffff731413ddf16171b1317027d87caf Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@theqtcompany.com>
This commit is contained in:
parent
827d0c0232
commit
46a372e1a1
@ -160,6 +160,7 @@ win32 {
|
|||||||
} else:ios {
|
} else:ios {
|
||||||
OBJECTIVE_SOURCES += io/qstandardpaths_ios.mm
|
OBJECTIVE_SOURCES += io/qstandardpaths_ios.mm
|
||||||
SOURCES += io/qstorageinfo_mac.cpp
|
SOURCES += io/qstorageinfo_mac.cpp
|
||||||
|
LIBS += -framework MobileCoreServices
|
||||||
} else {
|
} else {
|
||||||
SOURCES += io/qstandardpaths_unix.cpp
|
SOURCES += io/qstandardpaths_unix.cpp
|
||||||
}
|
}
|
||||||
|
@ -264,7 +264,7 @@ void QFileSystemMetaData::fillFromStatBuf(const QT_STATBUF &statBuffer)
|
|||||||
// Attributes
|
// Attributes
|
||||||
entryFlags |= QFileSystemMetaData::ExistsAttribute;
|
entryFlags |= QFileSystemMetaData::ExistsAttribute;
|
||||||
size_ = statBuffer.st_size;
|
size_ = statBuffer.st_size;
|
||||||
#if defined(Q_OS_MACX)
|
#if defined(Q_OS_DARWIN)
|
||||||
if (statBuffer.st_flags & UF_HIDDEN) {
|
if (statBuffer.st_flags & UF_HIDDEN) {
|
||||||
entryFlags |= QFileSystemMetaData::HiddenAttribute;
|
entryFlags |= QFileSystemMetaData::HiddenAttribute;
|
||||||
knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
|
knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
|
||||||
|
@ -76,7 +76,7 @@ public:
|
|||||||
static QString resolveGroupName(uint groupId);
|
static QString resolveGroupName(uint groupId);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_MACX)
|
#if defined(Q_OS_DARWIN)
|
||||||
static QString bundleName(const QFileSystemEntry &entry);
|
static QString bundleName(const QFileSystemEntry &entry);
|
||||||
#else
|
#else
|
||||||
static QString bundleName(const QFileSystemEntry &entry) { Q_UNUSED(entry) return QString(); }
|
static QString bundleName(const QFileSystemEntry &entry) { Q_UNUSED(entry) return QString(); }
|
||||||
|
@ -51,26 +51,38 @@
|
|||||||
# include <CoreFoundation/CFBundle.h>
|
# include <CoreFoundation/CFBundle.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_OSX
|
||||||
|
#include <CoreServices/CoreServices.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_IOS
|
||||||
|
#include <MobileCoreServices/MobileCoreServices.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
#if defined(Q_OS_MACX)
|
#if defined(Q_OS_DARWIN)
|
||||||
static inline bool _q_isMacHidden(const char *nativePath)
|
static inline bool hasResourcePropertyFlag(const QFileSystemMetaData &data,
|
||||||
|
const QFileSystemEntry &entry,
|
||||||
|
CFStringRef key)
|
||||||
{
|
{
|
||||||
OSErr err;
|
QCFString path = CFStringCreateWithFileSystemRepresentation(0,
|
||||||
|
entry.nativeFilePath().constData());
|
||||||
FSRef fsRef;
|
if (!path)
|
||||||
err = FSPathMakeRefWithOptions(reinterpret_cast<const UInt8 *>(nativePath),
|
|
||||||
kFSPathMakeRefDoNotFollowLeafSymlink, &fsRef, 0);
|
|
||||||
if (err != noErr)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
FSCatalogInfo catInfo;
|
QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle,
|
||||||
err = FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &catInfo, NULL, NULL, NULL);
|
data.hasFlags(QFileSystemMetaData::DirectoryType));
|
||||||
if (err != noErr)
|
if (!url)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
FileInfo * const fileInfo = reinterpret_cast<FileInfo*>(&catInfo.finderInfo);
|
CFBooleanRef value;
|
||||||
return (fileInfo->finderFlags & kIsInvisible);
|
if (CFURLCopyResourcePropertyForKey(url, key, &value, NULL)) {
|
||||||
|
if (value == kCFBooleanTrue)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &entry)
|
static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &entry)
|
||||||
@ -97,6 +109,7 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e
|
|||||||
if (CFBundleGetPackageInfoInDirectory(url, &type, &creator))
|
if (CFBundleGetPackageInfoInDirectory(url, &type, &creator))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
#ifdef Q_OS_OSX
|
||||||
// Find if an application other than Finder claims to know how to handle the package
|
// Find if an application other than Finder claims to know how to handle the package
|
||||||
QCFType<CFURLRef> application;
|
QCFType<CFURLRef> application;
|
||||||
LSGetApplicationForURL(url,
|
LSGetApplicationForURL(url,
|
||||||
@ -111,30 +124,11 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e
|
|||||||
if (applicationId != QLatin1String("com.apple.finder"))
|
if (applicationId != QLatin1String("com.apple.finder"))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Third step: check if the directory has the package bit set
|
// Third step: check if the directory has the package bit set
|
||||||
FSRef packageRef;
|
return hasResourcePropertyFlag(data, entry, kCFURLIsPackageKey);
|
||||||
FSPathMakeRef((UInt8 *)entry.nativeFilePath().constData(), &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
|
#endif
|
||||||
|
|
||||||
@ -194,22 +188,35 @@ QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link,
|
|||||||
ret.chop(1);
|
ret.chop(1);
|
||||||
return QFileSystemEntry(ret);
|
return QFileSystemEntry(ret);
|
||||||
}
|
}
|
||||||
#if defined(Q_OS_MACX)
|
#if defined(Q_OS_DARWIN)
|
||||||
{
|
{
|
||||||
FSRef fref;
|
QCFString path = CFStringCreateWithFileSystemRepresentation(0,
|
||||||
if (FSPathMakeRef((const UInt8 *)QFile::encodeName(QDir::cleanPath(link.filePath())).data(), &fref, 0) == noErr) {
|
QFile::encodeName(QDir::cleanPath(link.filePath())).data());
|
||||||
// TODO get the meta data info from the QFileSystemMetaData object
|
if (!path)
|
||||||
Boolean isAlias, isFolder;
|
return QFileSystemEntry();
|
||||||
if (FSResolveAliasFile(&fref, true, &isFolder, &isAlias) == noErr && isAlias) {
|
|
||||||
AliasHandle alias;
|
QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle,
|
||||||
if (FSNewAlias(0, &fref, &alias) == noErr && alias) {
|
data.hasFlags(QFileSystemMetaData::DirectoryType));
|
||||||
QCFString cfstr;
|
if (!url)
|
||||||
if (FSCopyAliasInfo(alias, 0, 0, &cfstr, 0, 0) == noErr)
|
return QFileSystemEntry();
|
||||||
|
|
||||||
|
QCFType<CFDataRef> bookmarkData = CFURLCreateBookmarkDataFromFile(0, url, NULL);
|
||||||
|
if (!bookmarkData)
|
||||||
|
return QFileSystemEntry();
|
||||||
|
|
||||||
|
QCFType<CFURLRef> resolvedUrl = CFURLCreateByResolvingBookmarkData(0,
|
||||||
|
bookmarkData,
|
||||||
|
(CFURLBookmarkResolutionOptions)(kCFBookmarkResolutionWithoutUIMask
|
||||||
|
| kCFBookmarkResolutionWithoutMountingMask), NULL, NULL, NULL, NULL);
|
||||||
|
if (!resolvedUrl)
|
||||||
|
return QFileSystemEntry();
|
||||||
|
|
||||||
|
QCFString cfstr(CFURLCopyFileSystemPath(resolvedUrl, kCFURLPOSIXPathStyle));
|
||||||
|
if (!cfstr)
|
||||||
|
return QFileSystemEntry();
|
||||||
|
|
||||||
return QFileSystemEntry(QCFString::toQString(cfstr));
|
return QFileSystemEntry(QCFString::toQString(cfstr));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
return QFileSystemEntry();
|
return QFileSystemEntry();
|
||||||
}
|
}
|
||||||
@ -226,10 +233,7 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry,
|
|||||||
return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath()));
|
return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath()));
|
||||||
#else
|
#else
|
||||||
char *ret = 0;
|
char *ret = 0;
|
||||||
# if defined(Q_OS_MACX)
|
# if defined(Q_OS_DARWIN)
|
||||||
// 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);
|
ret = (char*)malloc(PATH_MAX + 1);
|
||||||
if (ret && realpath(entry.nativeFilePath().constData(), (char*)ret) == 0) {
|
if (ret && realpath(entry.nativeFilePath().constData(), (char*)ret) == 0) {
|
||||||
const int savedErrno = errno; // errno is checked below, and free() might change it
|
const int savedErrno = errno; // errno is checked below, and free() might change it
|
||||||
@ -237,20 +241,6 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry,
|
|||||||
errno = savedErrno;
|
errno = savedErrno;
|
||||||
ret = 0;
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# elif defined(Q_OS_ANDROID)
|
# elif defined(Q_OS_ANDROID)
|
||||||
// On some Android versions, realpath() will return a path even if it does not exist
|
// On some Android versions, realpath() will return a path even if it does not exist
|
||||||
// To work around this, we check existence in advance.
|
// To work around this, we check existence in advance.
|
||||||
@ -406,7 +396,7 @@ QString QFileSystemEngine::resolveGroupName(uint groupId)
|
|||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_MACX)
|
#if defined(Q_OS_DARWIN)
|
||||||
//static
|
//static
|
||||||
QString QFileSystemEngine::bundleName(const QFileSystemEntry &entry)
|
QString QFileSystemEngine::bundleName(const QFileSystemEntry &entry)
|
||||||
{
|
{
|
||||||
@ -426,7 +416,7 @@ QString QFileSystemEngine::bundleName(const QFileSystemEntry &entry)
|
|||||||
bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data,
|
bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data,
|
||||||
QFileSystemMetaData::MetaDataFlags what)
|
QFileSystemMetaData::MetaDataFlags what)
|
||||||
{
|
{
|
||||||
#if defined(Q_OS_MACX)
|
#if defined(Q_OS_DARWIN)
|
||||||
if (what & QFileSystemMetaData::BundleType) {
|
if (what & QFileSystemMetaData::BundleType) {
|
||||||
if (!data.hasFlags(QFileSystemMetaData::DirectoryType))
|
if (!data.hasFlags(QFileSystemMetaData::DirectoryType))
|
||||||
what |= QFileSystemMetaData::DirectoryType;
|
what |= QFileSystemMetaData::DirectoryType;
|
||||||
@ -435,7 +425,7 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
|
|||||||
// OS X >= 10.5: st_flags & UF_HIDDEN
|
// OS X >= 10.5: st_flags & UF_HIDDEN
|
||||||
what |= QFileSystemMetaData::PosixStatFlags;
|
what |= QFileSystemMetaData::PosixStatFlags;
|
||||||
}
|
}
|
||||||
#endif // defined(Q_OS_MACX)
|
#endif // defined(Q_OS_DARWIN)
|
||||||
|
|
||||||
if (what & QFileSystemMetaData::PosixStatFlags)
|
if (what & QFileSystemMetaData::PosixStatFlags)
|
||||||
what |= QFileSystemMetaData::PosixStatFlags;
|
what |= QFileSystemMetaData::PosixStatFlags;
|
||||||
@ -496,19 +486,11 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
|
|||||||
| QFileSystemMetaData::ExistsAttribute;
|
| QFileSystemMetaData::ExistsAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_MACX)
|
#if defined(Q_OS_DARWIN)
|
||||||
if (what & QFileSystemMetaData::AliasType)
|
if (what & QFileSystemMetaData::AliasType)
|
||||||
{
|
{
|
||||||
if (entryExists) {
|
if (entryExists && hasResourcePropertyFlag(data, entry, kCFURLIsAliasFileKey))
|
||||||
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.entryFlags |= QFileSystemMetaData::AliasType;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data.knownFlagsMask |= QFileSystemMetaData::AliasType;
|
data.knownFlagsMask |= QFileSystemMetaData::AliasType;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -537,12 +519,15 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
|
|||||||
&& !data.isHidden()) {
|
&& !data.isHidden()) {
|
||||||
QString fileName = entry.fileName();
|
QString fileName = entry.fileName();
|
||||||
if ((fileName.size() > 0 && fileName.at(0) == QLatin1Char('.'))
|
if ((fileName.size() > 0 && fileName.at(0) == QLatin1Char('.'))
|
||||||
|| (entryExists && _q_isMacHidden(nativeFilePath)))
|
#if defined(Q_OS_DARWIN)
|
||||||
|
|| (entryExists && hasResourcePropertyFlag(data, entry, kCFURLIsHiddenKey))
|
||||||
|
#endif
|
||||||
|
)
|
||||||
data.entryFlags |= QFileSystemMetaData::HiddenAttribute;
|
data.entryFlags |= QFileSystemMetaData::HiddenAttribute;
|
||||||
data.knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
|
data.knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_MACX)
|
#if defined(Q_OS_DARWIN)
|
||||||
if (what & QFileSystemMetaData::BundleType) {
|
if (what & QFileSystemMetaData::BundleType) {
|
||||||
if (entryExists && isPackage(data, entry))
|
if (entryExists && isPackage(data, entry))
|
||||||
data.entryFlags |= QFileSystemMetaData::BundleType;
|
data.entryFlags |= QFileSystemMetaData::BundleType;
|
||||||
|
@ -93,7 +93,7 @@ public:
|
|||||||
LinkType = 0x00010000,
|
LinkType = 0x00010000,
|
||||||
FileType = 0x00020000,
|
FileType = 0x00020000,
|
||||||
DirectoryType = 0x00040000,
|
DirectoryType = 0x00040000,
|
||||||
#if defined(Q_OS_MACX)
|
#if defined(Q_OS_DARWIN)
|
||||||
BundleType = 0x00080000,
|
BundleType = 0x00080000,
|
||||||
AliasType = 0x08000000,
|
AliasType = 0x08000000,
|
||||||
#else
|
#else
|
||||||
@ -243,7 +243,7 @@ private:
|
|||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemMetaData::MetaDataFlags)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemMetaData::MetaDataFlags)
|
||||||
|
|
||||||
#if defined(Q_OS_MACX)
|
#if defined(Q_OS_DARWIN)
|
||||||
inline bool QFileSystemMetaData::isBundle() const { return (entryFlags & BundleType); }
|
inline bool QFileSystemMetaData::isBundle() const { return (entryFlags & BundleType); }
|
||||||
inline bool QFileSystemMetaData::isAlias() const { return (entryFlags & AliasType); }
|
inline bool QFileSystemMetaData::isAlias() const { return (entryFlags & AliasType); }
|
||||||
#else
|
#else
|
||||||
|
@ -147,32 +147,24 @@ void QStorageInfoPrivate::retrieveUrlProperties(bool initRootPath)
|
|||||||
|
|
||||||
void QStorageInfoPrivate::retrieveLabel()
|
void QStorageInfoPrivate::retrieveLabel()
|
||||||
{
|
{
|
||||||
#if !defined(Q_OS_IOS)
|
QCFString path = CFStringCreateWithFileSystemRepresentation(0,
|
||||||
// deprecated since 10.8
|
QFile::encodeName(rootPath).constData());
|
||||||
FSRef ref;
|
if (!path)
|
||||||
FSPathMakeRef(reinterpret_cast<const UInt8*>(QFile::encodeName(rootPath).constData()),
|
|
||||||
&ref,
|
|
||||||
Q_NULLPTR);
|
|
||||||
|
|
||||||
// deprecated since 10.8
|
|
||||||
FSCatalogInfo catalogInfo;
|
|
||||||
OSErr error;
|
|
||||||
error = FSGetCatalogInfo(&ref, kFSCatInfoVolume, &catalogInfo, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR);
|
|
||||||
if (error != noErr)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// deprecated (use CFURLCopyResourcePropertiesForKeys for 10.7 and higher)
|
QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle, true);
|
||||||
HFSUniStr255 volumeName;
|
if (!url)
|
||||||
error = FSGetVolumeInfo(catalogInfo.volume,
|
return;
|
||||||
0,
|
|
||||||
Q_NULLPTR,
|
QCFType<CFURLRef> volumeUrl;
|
||||||
kFSVolInfoFSInfo,
|
if (!CFURLCopyResourcePropertyForKey(url, kCFURLVolumeURLKey, &volumeUrl, NULL))
|
||||||
Q_NULLPTR,
|
return;
|
||||||
&volumeName,
|
|
||||||
Q_NULLPTR);
|
QCFString volumeName;
|
||||||
if (error == noErr)
|
if (!CFURLCopyResourcePropertyForKey(url, kCFURLNameKey, &volumeName, NULL))
|
||||||
name = QCFString(FSCreateStringFromHFSUniStr(Q_NULLPTR, &volumeName));
|
return;
|
||||||
#endif
|
|
||||||
|
name = volumeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
|
QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user