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; }
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); } } }