Пример #1
0
FcBool FcAtomicLock(FcAtomic *atomic) {
    int ret;
    struct stat lck_stat;

#ifdef HAVE_LINK
    int fd = -1;
    FILE *f = 0;
    FcBool no_link = FcFalse;

    strcpy((char *)atomic->tmp, (char *)atomic->file);
    strcat((char *)atomic->tmp, TMP_NAME);
    fd = FcMakeTempfile((char *)atomic->tmp);
    if (fd < 0) return FcFalse;
    f = fdopen(fd, "w");
    if (!f) {
        close(fd);
        unlink((char *)atomic->tmp);
        return FcFalse;
    }
    ret = fprintf(f, "%ld\n", (long)getpid());
    if (ret <= 0) {
        fclose(f);
        unlink((char *)atomic->tmp);
        return FcFalse;
    }
    if (fclose(f) == EOF) {
        unlink((char *)atomic->tmp);
        return FcFalse;
    }
    ret = link((char *)atomic->tmp, (char *)atomic->lck);
    if (ret < 0 && errno == EPERM) {
        /* the filesystem where atomic->lck points to may not supports
         * the hard link. so better try to fallback
         */
        ret = mkdir((char *)atomic->lck, 0600);
        no_link = FcTrue;
    }
    (void)unlink((char *)atomic->tmp);
#else
    ret = mkdir((char *)atomic->lck, 0600);
#endif
    if (ret < 0) {
        /*
         * If the file is around and old (> 10 minutes),
         * assume the lock is stale.  This assumes that any
         * machines sharing the same filesystem will have clocks
         * reasonably close to each other.
         */
        if (FcStat(atomic->lck, &lck_stat) >= 0) {
            time_t now = time(0);
            if ((long int)(now - lck_stat.st_mtime) > 10 * 60) {
#ifdef HAVE_LINK
                if (no_link) {
                    if (rmdir((char *)atomic->lck) == 0)
                        return FcAtomicLock(atomic);
                } else {
                    if (unlink((char *)atomic->lck) == 0)
                        return FcAtomicLock(atomic);
                }
#else
                if (rmdir((char *)atomic->lck) == 0)
                    return FcAtomicLock(atomic);
#endif
            }
        }
        return FcFalse;
    }
    (void)unlink((char *)atomic->new_file);
    return FcTrue;
}
Пример #2
0
void addDir(const QString &dir, bool system)
{
    QDomDocument doc("fontconfig");
    QString      fileName=getConfigFile(system);
    QFile        f(fileName);
    bool         hasDir(false);

    KFI_DBUG << "Using fontconfig file:" << fileName;

    // Load existing file - and check to see whether it has the dir...
    if(f.open(QIODevice::ReadOnly))
    {
        doc.clear();

        if(doc.setContent(&f))
        {
            QDomNode n = doc.documentElement().firstChild();

            while(!n.isNull() && !hasDir)
            {
                QDomElement e = n.toElement();

                if(!e.isNull() && "dir"==e.tagName())
                    if(0==Misc::expandHome(Misc::dirSyntax(e.text())).indexOf(dir))
                        hasDir=true;
                n=n.nextSibling();
            }
        }
        f.close();
    }

    // Add dir, and save, if config does not already have this dir.
    if(!hasDir)
    {
        if(doc.documentElement().isNull())
            doc.appendChild(doc.createElement("fontconfig"));

        QDomElement newNode = doc.createElement("dir");
        QDomText    text    = doc.createTextNode(Misc::contractHome(xDirSyntax(dir)));

        newNode.appendChild(text);
        doc.documentElement().appendChild(newNode);

        FcAtomic *atomic=FcAtomicCreate((const unsigned char *)(QFile::encodeName(fileName).data()));

        if(atomic)
        {
            if(FcAtomicLock(atomic))
            {
                FILE *f=fopen((char *)FcAtomicNewFile(atomic), "w");

                if(f)
                {
                    //
                    // Check document syntax...
                    static const char qtXmlHeader[]   = "<?xml version = '1.0'?>";
                    static const char xmlHeader[]     = "<?xml version=\"1.0\"?>";
                    static const char qtDocTypeLine[] = "<!DOCTYPE fontconfig>";
                    static const char docTypeLine[]   = "<!DOCTYPE fontconfig SYSTEM "
                                                        "\"fonts.dtd\">";

                    QString str(doc.toString());
                    int     idx;

                    if(0!=str.indexOf("<?xml"))
                        str.insert(0, xmlHeader);
                    else if(0==str.indexOf(qtXmlHeader))
                        str.replace(0, strlen(qtXmlHeader), xmlHeader);

                    if(-1!=(idx=str.indexOf(qtDocTypeLine)))
                        str.replace(idx, strlen(qtDocTypeLine), docTypeLine);

                    //
                    // Write to file...
                    fputs(str.toUtf8(), f);
                    fclose(f);

                    if(!FcAtomicReplaceOrig(atomic))
                        FcAtomicDeleteNew(atomic);
                }
                FcAtomicUnlock(atomic);
            }
            FcAtomicDestroy(atomic);
        }
    }
}