//static QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data) { if (entry.isEmpty() || entry.isRoot()) return entry; QFileSystemEntry result = absoluteName(entry); if (!data.hasFlags(QFileSystemMetaData::ExistsAttribute)) fillMetaData(result, data, QFileSystemMetaData::ExistsAttribute); if (!data.exists()) { // file doesn't exist return QFileSystemEntry(); } else { return result; } }
//static bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data, QFileSystemMetaData::MetaDataFlags what) { if (what & QFileSystemMetaData::SymbianTEntryFlags) { RFs& fs(qt_s60GetRFs()); TInt err; QFileSystemEntry absentry(absoluteName(entry)); if (entry.isEmpty()) { err = KErrNotFound; } else if (absentry.isRoot()) { //Root directories don't have an entry, and Entry() returns KErrBadName. //Therefore get information about the volume instead. TInt drive; err = RFs::CharToDrive(TChar(absentry.nativeFilePath().at(0).unicode()), drive); if (!err) { TVolumeInfo info; err = fs.Volume(info, drive); if (!err) data.fillFromVolumeInfo(info); } } else { TEntry ent; err = fs.Entry(qt_QString2TPtrC(absentry.nativeFilePath()), ent); if (!err) data.fillFromTEntry(ent); } if (err) { data.size_ = 0; data.modificationTime_ = TTime(0); data.entryFlags &= ~(QFileSystemMetaData::SymbianTEntryFlags); } //files in /sys/bin on any drive are executable, even though we don't normally have permission to check whether they exist or not if(absentry.filePath().midRef(1,10).compare(QLatin1String(":/sys/bin/"), Qt::CaseInsensitive) == 0) data.entryFlags |= QFileSystemMetaData::ExecutePermissions; } return data.hasFlags(what); }
//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(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) { 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 bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data, QFileSystemMetaData::MetaDataFlags what) { #if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) if (what & QFileSystemMetaData::BundleType) { if (!data.hasFlags(QFileSystemMetaData::DirectoryType)) what |= QFileSystemMetaData::DirectoryType; } #endif #if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) \ && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 if (what & QFileSystemMetaData::HiddenAttribute) { // Mac OS >= 10.5: st_flags & UF_HIDDEN what |= QFileSystemMetaData::PosixStatFlags; } #endif 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(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) 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(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) if (what & QFileSystemMetaData::BundleType) { if (entryExists && data.isDirectory()) { QCFType<CFStringRef> path = CFStringCreateWithBytes(0, (const UInt8*)nativeFilePath, nativeFilePathLength, kCFStringEncodingUTF8, false); QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle, true); UInt32 type, creator; if (CFBundleGetPackageInfoInDirectory(url, &type, &creator)) data.entryFlags |= QFileSystemMetaData::BundleType; } data.knownFlagsMask |= QFileSystemMetaData::BundleType; } #endif return data.hasFlags(what); }
//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 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) && !defined(Q_OS_HAIKU) && _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_DARWIN) 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; } # elif defined(Q_OS_ANDROID) // On some Android versions, realpath() will return a path even if it does not exist // To work around this, we check existence in advance. if (!data.hasFlags(QFileSystemMetaData::ExistsAttribute)) fillMetaData(entry, data, QFileSystemMetaData::ExistsAttribute); if (!data.exists()) { ret = 0; errno = ENOENT; } 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; } } # 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::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_DARWIN) { QCFString path = CFStringCreateWithFileSystemRepresentation(0, QFile::encodeName(QDir::cleanPath(link.filePath())).data()); if (!path) return QFileSystemEntry(); QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle, data.hasFlags(QFileSystemMetaData::DirectoryType)); if (!url) 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)); } #endif return QFileSystemEntry(); }