Beispiel #1
0
/*
 * Add support for resolving Mac native alias files (not the same as unix alias files)
 * (what are "unix alias files"?)
 * returns 0 on success.
 */
int macxp_resolveAlias(char *path, int buflen)
{
#if HAVE_FEATURE_MACOSX_SANDBOX
    /* Avoid unnecessary messages in the system.log:
     *
     * soffice(57342) deny file-read-data /Users/tml/Documents/b.odt/..namedfork/rsrc
     * etc.
     *
     * Just don't bother with resolving aliases. I doubt its usefulness anyway.
     */
    (void) path;
    (void) buflen;
    return 0;
#else
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
    FSRef aFSRef;
    OSStatus nErr;
    Boolean bFolder;
    Boolean bAliased;
#else
    CFStringRef cfpath;
    CFURLRef cfurl;
    CFErrorRef cferror;
    CFDataRef cfbookmark;
#endif

    char *unprocessedPath = path;

    if ( *unprocessedPath == '/' )
        unprocessedPath++;

    int nRet = 0;
    while ( !nRet && unprocessedPath && *unprocessedPath )
    {
        unprocessedPath = strchr( unprocessedPath, '/' );
        if ( unprocessedPath )
            *unprocessedPath = '\0';

#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
        nErr = noErr;
        bFolder = FALSE;
        bAliased = FALSE;

        if ( FSPathMakeRef( (const UInt8 *)path, &aFSRef, 0 ) == noErr )
        {
            nErr = FSResolveAliasFileWithMountFlags( &aFSRef, TRUE, &bFolder, &bAliased, kResolveAliasFileNoUI );
            if ( nErr == nsvErr )
            {
                errno = ENOENT;
                nRet = -1;
            }
            else if ( nErr == noErr && bAliased )
            {
                char tmpPath[ PATH_MAX ];
                if ( FSRefMakePath( &aFSRef, (UInt8 *)tmpPath, PATH_MAX ) == noErr )
                {
                    int nLen = strlen( tmpPath ) + ( unprocessedPath ? strlen( unprocessedPath + 1 ) + 1 : 0 );
                    if ( nLen < buflen && nLen < PATH_MAX )
                    {
                        if ( unprocessedPath )
                        {
                            int nTmpPathLen = strlen( tmpPath );
                            strcat( tmpPath, "/" );
                            strcat( tmpPath, unprocessedPath + 1 );
                            strcpy( path, tmpPath);
                            unprocessedPath = path + nTmpPathLen;
                        }
                        else if ( !unprocessedPath )
                        {
                            strcpy( path, tmpPath);
                        }
                    }
                    else
                    {
                        errno = ENAMETOOLONG;
                        nRet = -1;
                    }
                }
            }
        }
#else
        cfpath = CFStringCreateWithCString( NULL, path, kCFStringEncodingUTF8 );
        cfurl = CFURLCreateWithFileSystemPath( NULL, cfpath, kCFURLPOSIXPathStyle, false );
        CFRelease( cfpath );
        cferror = NULL;
        cfbookmark = CFURLCreateBookmarkDataFromFile( NULL, cfurl, &cferror );
        CFRelease( cfurl );

        if ( cfbookmark == NULL )
        {
            if(cferror)
            {
                CFRelease( cferror );
            }
        }
        else
        {
            Boolean isStale;
            cfurl = CFURLCreateByResolvingBookmarkData( NULL, cfbookmark, kCFBookmarkResolutionWithoutUIMask,
                    NULL, NULL, &isStale, &cferror );
            CFRelease( cfbookmark );
            if ( cfurl == NULL )
            {
                CFRelease( cferror );
            }
            else
            {
                cfpath = CFURLCopyFileSystemPath( cfurl, kCFURLPOSIXPathStyle );
                CFRelease( cfurl );
                if ( cfpath != NULL )
                {
                    char tmpPath[ PATH_MAX ];
                    if ( CFStringGetCString( cfpath, tmpPath, PATH_MAX, kCFStringEncodingUTF8 ) )
                    {
                        int nLen = strlen( tmpPath ) + ( unprocessedPath ? strlen( unprocessedPath + 1 ) + 1 : 0 );
                        if ( nLen < buflen && nLen < PATH_MAX )
                        {
                            if ( unprocessedPath )
                            {
                                int nTmpPathLen = strlen( tmpPath );
                                strcat( tmpPath, "/" );
                                strcat( tmpPath, unprocessedPath + 1 );
                                strcpy( path, tmpPath);
                                unprocessedPath = path + nTmpPathLen;
                            }
                            else if ( !unprocessedPath )
                            {
                                strcpy( path, tmpPath );
                            }
                        }
                        else
                        {
                            errno = ENAMETOOLONG;
                            nRet = -1;
                        }
                    }
                    CFRelease( cfpath );
                }
            }
        }
#endif

        if ( unprocessedPath )
            *unprocessedPath++ = '/';
    }

    return nRet;
#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();
}