//----------------------------------------------------------------------------- int KMFolder::expunge(void) { int openCount = mOpenCount; assert(name() != ""); close(TRUE); if (mAutoCreateIndex) truncate(indexLocation(), mHeaderOffset); else unlink(indexLocation()); if (truncate(location(), 0)) return errno; mDirty = FALSE; mMsgList.reset(INIT_MSGS); needsCompact = false; //we're cleared and truncated no need to compact if (openCount > 0) { open(); mOpenCount = openCount; } unreadMsgs = 0; emit numUnreadMsgsChanged( this ); if (!mQuiet) emit changed(); return 0; }
//----------------------------------------------------------------------------- int KMFolder::rename(const QString aName) { QString oldLoc, oldIndexLoc, newLoc, newIndexLoc, oldName; int rc=0, openCount=mOpenCount; assert(!aName.isEmpty()); oldLoc = location().copy(); oldIndexLoc = indexLocation().copy(); close(TRUE); oldName = name(); setName(aName); newLoc = location(); newIndexLoc = indexLocation(); if (_rename(oldLoc, newLoc)) { setName(oldName); rc = errno; } else if (!oldIndexLoc.isEmpty()) _rename(oldIndexLoc, newIndexLoc); if (openCount > 0) { open(); mOpenCount = openCount; } return rc; }
bool KMFolderIndex::updateIndexStreamPtr(bool just_close) { #ifndef HAVE_MMAP Q_UNUSED( just_close ); #endif // We touch the folder, otherwise the index is regenerated, if KMail is // running, while the clock switches from daylight savings time to normal time if ( 0 != utime( QFile::encodeName( QDir::toNativeSeparators( location() ) ), 0 ) ) { kWarning() << "utime(" << QDir::toNativeSeparators( location() ) << ", 0) failed (location())"; } if ( 0 != utime( QFile::encodeName( QDir::toNativeSeparators( indexLocation() ) ), 0 ) ) { kWarning() << "utime(" << QDir::toNativeSeparators( indexLocation() ) << ", 0) failed (indexLocation())"; } if ( 0 != utime( QFile::encodeName( QDir::toNativeSeparators( KMMsgDict::getFolderIdsLocation( *this ) ) ), 0 ) ) { kWarning() << "utime(" << QDir::toNativeSeparators( KMMsgDict::getFolderIdsLocation( *this ) ) << ", 0) failed (KMMsgDict::getFolderIdsLocation( *this ))"; } mIndexSwapByteOrder = false; #ifdef HAVE_MMAP if ( just_close ) { bool munmapResult = true; if( mIndexStreamPtr ) munmapResult = 0 == munmap( reinterpret_cast<char *>( mIndexStreamPtr ), mIndexStreamPtrLength ); mIndexStreamPtr = 0; mIndexStreamPtrLength = 0; return munmapResult; } assert( mIndexStream ); KDE_struct_stat stat_buf; if ( KDE_fstat( fileno( mIndexStream ), &stat_buf ) == -1 ) { if( mIndexStreamPtr ) munmap( reinterpret_cast<char *>( mIndexStreamPtr ), mIndexStreamPtrLength ); mIndexStreamPtr = 0; mIndexStreamPtrLength = 0; return false; } if ( mIndexStreamPtr ) if ( 0 != munmap( reinterpret_cast<char *>( mIndexStreamPtr ), mIndexStreamPtrLength ) ) return false; mIndexStreamPtrLength = stat_buf.st_size; mIndexStreamPtr = static_cast<uchar *>( mmap( 0, mIndexStreamPtrLength, PROT_READ, MAP_SHARED, fileno( mIndexStream ), 0 ) ); if ( mIndexStreamPtr == MAP_FAILED ) { mIndexStreamPtr = 0; mIndexStreamPtrLength = 0; return false; } #endif return true; }
//----------------------------------------------------------------------------- int KMFolder::writeIndex(void) { KMMsgBase* msgBase; int old_umask; int i=0; if (mIndexStream) fclose(mIndexStream); old_umask = umask(077); mIndexStream = fopen(indexLocation(), "w"); umask(old_umask); if (!mIndexStream) return errno; fprintf(mIndexStream, "# KMail-Index V%d\n", INDEX_VERSION); mHeaderOffset = ftell(mIndexStream); for (i=0; i<mMsgList.high(); i++) { if (!(msgBase = mMsgList[i])) continue; fprintf(mIndexStream, "%s\n", (const char*)msgBase->asIndexString()); } fflush(mIndexStream); mDirty = FALSE; return 0; }
void KMFolderIndex::truncateIndex() { if ( mHeaderOffset ) truncate(QFile::encodeName(indexLocation()), mHeaderOffset); else // The index file wasn't opened, so we don't know the header offset. // So let's just create a new empty index. writeIndex( true ); }
//----------------------------------------------------------------------------- bool KMFolder::isIndexOutdated(void) { QFileInfo contInfo(location()); QFileInfo indInfo(indexLocation()); if (!contInfo.exists()) return FALSE; if (!indInfo.exists()) return TRUE; return (contInfo.lastModified() > indInfo.lastModified()); }
KMFolderIndex::IndexStatus KMFolderIndex::indexStatus() { QFileInfo contInfo(location()); QFileInfo indInfo(indexLocation()); if (!contInfo.exists()) return KMFolderIndex::IndexOk; if (!indInfo.exists()) return KMFolderIndex::IndexMissing; return ( contInfo.lastModified() > indInfo.lastModified() ) ? KMFolderIndex::IndexTooOld : KMFolderIndex::IndexOk; }
//----------------------------------------------------------------------------- int KMFolder::remove(void) { int rc; assert(name() != ""); close(TRUE); unlink(indexLocation()); rc = unlink(location()); if (rc) return rc; mMsgList.reset(INIT_MSGS); needsCompact = false; //we are dead - no need to compact us return 0; }
//----------------------------------------------------------------------------- int KMFolder::open(void) { int rc = 0; mOpenCount++; if (mOpenCount > 1) return 0; // already open assert(name() != ""); mFilesLocked = FALSE; mStream = fopen(location(), "r+"); // messages file if (!mStream) { debug("Cannot open folder `%s': %s", (const char*)location(), strerror(errno)); mOpenCount = 0; return errno; } if (!path().isEmpty()) { if (isIndexOutdated()) // test if contents file has changed { QString str; mIndexStream = NULL; str.sprintf(i18n("Folder `%s' changed. Recreating index."), (const char*)name()); emit statusMsg(str); } else mIndexStream = fopen(indexLocation(), "r+"); // index file if (!mIndexStream) rc = createIndexFromContents(); else readIndex(); } else { //debug("No path specified for folder `" + name() + // "' -- Turning autoCreateIndex off"); mAutoCreateIndex = FALSE; rc = createIndexFromContents(); } if (!rc) lock(); mQuiet = 0; return rc; }
//----------------------------------------------------------------------------- bool KMFolder::readIndexHeader(void) { int indexVersion; assert(mIndexStream != NULL); fscanf(mIndexStream, "# KMail-Index V%d\n", &indexVersion); if (indexVersion < INDEX_VERSION) { debug("Index file %s is out of date. Re-creating it.", (const char*)indexLocation()); createIndexFromContents(); return FALSE; } return TRUE; }
//----------------------------------------------------------------------------- int KMFolder::create(void) { int rc; int old_umask; assert(name() != ""); assert(mOpenCount == 0); if (access(location(), F_OK) == 0) return EEXIST; old_umask = umask(077); mStream = fopen(location(), "w+"); //sven; open RW umask(old_umask); if (!mStream) return errno; if (!path().isEmpty()) { old_umask = umask(077); mIndexStream = fopen(indexLocation(), "w+"); //sven; open RW umask(old_umask); if (!mIndexStream) return errno; } else { //debug("Folder `" + name() + // "' has no path specified -- turning autoCreateIndex off"); mAutoCreateIndex = FALSE; } mOpenCount++; mQuiet = 0; rc = writeIndex(); if (!rc) lock(); return rc; }
//----------------------------------------------------------------------------- int KMFolder::compact(void) { KMFolder* tempFolder; KMMessage* msg; QString tempName, msgStr; int openCount = mOpenCount; int num, numStatus; if (!needsCompact) { //debug ("Not compacting %s; it's clean", name().data()); return 0; } debug ("Compacting %s ", name().data()); tempName = "." + name(); tempName.detach(); tempName += ".compacted"; unlink(tempName); //tempFolder = parent()->createFolder(tempName); //sven: shouldn't be in list tempFolder = new KMFolder(parent(), tempName); //sven: we create it if(tempFolder->create()) { debug("KMFolder::compact() Creating tempFolder failed!\n"); delete tempFolder; //sven: and we delete it return 0; } quiet(TRUE); tempFolder->open(); open(); for(num=1,numStatus=9; count() > 0; num++, numStatus--) { if (numStatus <= 0) { msgStr.sprintf(i18n("Compacting folder: %d messages done"), num); emit statusMsg(msgStr); numStatus = 10; } msg = getMsg(0); if(msg) tempFolder->moveMsg(msg); } tempName = tempFolder->location(); tempFolder->close(TRUE); close(TRUE); mMsgList.clear(TRUE); _rename(tempName, location()); _rename(tempFolder->indexLocation(), indexLocation()); // Now really free all memory delete tempFolder; //sven: we delete it, not the manager if (openCount > 0) { open(); mOpenCount = openCount; } quiet(FALSE); if (!mQuiet) emit changed(); needsCompact = false; // We are clean now return 0; }
void RenderMathMLRoot::layoutBlock(bool relayoutChildren, LayoutUnit) { ASSERT(needsLayout()); if (!relayoutChildren && simplifiedLayout()) return; updateStyle(); m_radicalOperatorTop = 0; m_baseWidth = 0; if (!isValid()) { setLogicalWidth(0); setLogicalHeight(0); clearNeedsLayout(); return; } // We layout the children, determine the vertical metrics of the base and set the logical width. // Note: Per the MathML specification, the children of <msqrt> are wrapped in an inferred <mrow>, which is the desired base. LayoutUnit baseAscent, baseDescent; recomputeLogicalWidth(); if (m_kind == SquareRoot) { baseAscent = baseDescent; RenderMathMLRow::computeLineVerticalStretch(baseAscent, baseDescent); RenderMathMLRow::layoutRowItems(baseAscent, baseDescent); m_baseWidth = logicalWidth(); } else { getBase().layoutIfNeeded(); m_baseWidth = getBase().logicalWidth(); baseAscent = ascentForChild(getBase()); baseDescent = getBase().logicalHeight() - baseAscent; getIndex().layoutIfNeeded(); } // Stretch the radical operator to cover the base height. // We can then determine the metrics of the radical operator + the base. m_radicalOperator.stretchTo(style(), baseAscent + baseDescent); LayoutUnit radicalOperatorHeight = m_radicalOperator.ascent() + m_radicalOperator.descent(); LayoutUnit indexBottomRaise = m_degreeBottomRaisePercent * radicalOperatorHeight; LayoutUnit radicalAscent = baseAscent + m_verticalGap + m_ruleThickness + m_extraAscender; LayoutUnit radicalDescent = std::max<LayoutUnit>(baseDescent, radicalOperatorHeight + m_extraAscender - radicalAscent); LayoutUnit descent = radicalDescent; LayoutUnit ascent = radicalAscent; // We set the logical width. if (m_kind == SquareRoot) setLogicalWidth(m_radicalOperator.width() + m_baseWidth); else { ASSERT(m_kind == RootWithIndex); setLogicalWidth(m_kernBeforeDegree + getIndex().logicalWidth() + m_kernAfterDegree + m_radicalOperator.width() + m_baseWidth); } // For <mroot>, we update the metrics to take into account the index. LayoutUnit indexAscent, indexDescent; if (m_kind == RootWithIndex) { indexAscent = ascentForChild(getIndex()); indexDescent = getIndex().logicalHeight() - indexAscent; ascent = std::max<LayoutUnit>(radicalAscent, indexBottomRaise + indexDescent + indexAscent - descent); } // We set the final position of children. m_radicalOperatorTop = ascent - radicalAscent + m_extraAscender; LayoutUnit horizontalOffset = m_radicalOperator.width(); if (m_kind == RootWithIndex) horizontalOffset += m_kernBeforeDegree + getIndex().logicalWidth() + m_kernAfterDegree; LayoutPoint baseLocation(mirrorIfNeeded(horizontalOffset, m_baseWidth), ascent - baseAscent); if (m_kind == SquareRoot) { for (auto* child = firstChildBox(); child; child = child->nextSiblingBox()) child->setLocation(child->location() + baseLocation); } else { ASSERT(m_kind == RootWithIndex); getBase().setLocation(baseLocation); LayoutPoint indexLocation(mirrorIfNeeded(m_kernBeforeDegree, getIndex()), ascent + descent - indexBottomRaise - indexDescent - indexAscent); getIndex().setLocation(indexLocation); } setLogicalHeight(ascent + descent); clearNeedsLayout(); }
int KMFolderIndex::writeIndex( bool createEmptyIndex ) { QString tempName; QString indexName; mode_t old_umask; indexName = indexLocation(); tempName = indexName + ".temp"; { int result = unlink( QFile::encodeName( tempName ) ); if ( ! ( result == 0 || (result == -1 && errno == ENOENT ) ) ) return errno; } // We touch the folder, otherwise the index is regenerated, if KMail is // running, while the clock switches from daylight savings time to normal time utime( QFile::encodeName( QDir::toNativeSeparators(location()) ), 0 ); old_umask = umask( 077 ); FILE *tmpIndexStream = KDE_fopen( QFile::encodeName( tempName ), "w" ); //kDebug( KMKernel::storageDebug() ) << "KDE_fopen(tempName=" << tempName << ", \"w\") == tmpIndexStream == " << tmpIndexStream; umask( old_umask ); if ( !tmpIndexStream ) { return errno; } fprintf(tmpIndexStream, "# KMail-Index V%d\n", INDEX_VERSION); // Header quint32 byteOrder = 0x12345678; quint32 sizeOfLong = sizeof(long); quint32 header_length = sizeof(byteOrder)+sizeof(sizeOfLong); char pad_char = '\0'; fwrite(&pad_char, sizeof(pad_char), 1, tmpIndexStream); fwrite(&header_length, sizeof(header_length), 1, tmpIndexStream); // Write header fwrite(&byteOrder, sizeof(byteOrder), 1, tmpIndexStream); fwrite(&sizeOfLong, sizeof(sizeOfLong), 1, tmpIndexStream); off_t nho = KDE_ftell(tmpIndexStream); int fError = 0; if ( !createEmptyIndex ) { fError = writeMessages( 0/*all*/, false /* !flush */, tmpIndexStream ); /* moved to writeMessages() KMMsgBase* msgBase; int len; const uchar *buffer = 0; for (unsigned int i=0; i<mMsgList.high(); i++) { if (!(msgBase = mMsgList.at(i))) continue; buffer = msgBase->asIndexString(len); fwrite(&len,sizeof(len), 1, tmpIndexStream); off_t tmp = KDE_ftell(tmpIndexStream); msgBase->setIndexOffset(tmp); msgBase->setIndexLength(len); if(fwrite(buffer, len, 1, tmpIndexStream) != 1) kDebug() << "Whoa!"; }*/ } fError |= ferror( tmpIndexStream ); if( fError != 0 ) { fclose( tmpIndexStream ); //kDebug( KMKernel::storageDebug() ) << "fclose(tmpIndexStream = " << tmpIndexStream << ")"; return fError; } if( ( fflush( tmpIndexStream ) != 0 ) || ( fsync( fileno( tmpIndexStream ) ) != 0 ) ) { int errNo = errno; fclose( tmpIndexStream ); kWarning() << "fflush() or fsync() failed; fclose(tmpIndexStream = " << tmpIndexStream << ")"; return errNo; } //kDebug( KMKernel::storageDebug() ) << "fclose(tmpIndexStream = " << tmpIndexStream << ")"; if( fclose( tmpIndexStream ) != 0 ) { kWarning() << "fclose() failed"; return errno; } #ifdef Q_WS_WIN if (mIndexStream) { // close before renaming // neither this fixes windows port: // if ( !updateIndexStreamPtr() ) // return 1; bool ok = fclose( mIndexStream ) == 0; //kDebug( KMKernel::storageDebug() ) << "fclose(mIndexStream = " << mIndexStream << ")"; mIndexStream = 0; if ( !ok ) { kWarning() << "fclose() failed"; return errno; } } #endif if ( KDE_rename(QFile::encodeName(tempName), QFile::encodeName(indexName)) != 0 ) return errno; mHeaderOffset = nho; #ifndef Q_WS_WIN if (mIndexStream) { fclose(mIndexStream); //kDebug( KMKernel::storageDebug() ) << "fclose(mIndexStream = " << mIndexStream << ")"; } #endif if ( createEmptyIndex ) return 0; mIndexStream = KDE_fopen(QFile::encodeName(indexName), "r+"); // index file //kDebug( KMKernel::storageDebug() ) << "KDE_fopen(indexName=" << indexName << ", \"r+\") == mIndexStream == " << mIndexStream; assert( mIndexStream ); #ifndef Q_WS_WIN fcntl(fileno(mIndexStream), F_SETFD, FD_CLOEXEC); #endif if ( !updateIndexStreamPtr() ) return 1; if ( 0 != writeFolderIdsFile() ) return 1; setDirty( false ); return 0; }
bool KMFolderIndex::readIndexHeader(int *gv) { int indexVersion; assert(mIndexStream != 0); mIndexSwapByteOrder = false; mIndexSizeOfLong = sizeof(long); int ret = fscanf(mIndexStream, "# KMail-Index V%d\n", &indexVersion); if ( ret == EOF || ret == 0 ) return false; // index file has invalid header if(gv) *gv = indexVersion; if (indexVersion < 1505 ) { if(indexVersion == 1503) { kDebug() << "Converting old index file" << indexLocation() << "to utf-8"; mConvertToUtf8 = true; } return true; } else if (indexVersion == 1505) { } else if (indexVersion < INDEX_VERSION) { kDebug() << "Index file" << indexLocation() << "is out of date. Re-creating it."; createIndexFromContents(); return false; } else if(indexVersion > INDEX_VERSION) { QApplication::setOverrideCursor( QCursor( Qt::ArrowCursor ) ); int r = KMessageBox::questionYesNo(0, i18n( "The mail index for '%1' is from an unknown version of KMail (%2).\n" "This index can be regenerated from your mail folder, but some " "information, including status flags, may be lost. Do you wish " "to downgrade your index file?" , objectName() , indexVersion), QString(), KGuiItem(i18n("Downgrade")), KGuiItem(i18n("Do Not Downgrade")) ); QApplication::restoreOverrideCursor(); if (r == KMessageBox::Yes) createIndexFromContents(); return false; } else { // Header quint32 byteOrder = 0; quint32 sizeOfLong = sizeof(long); // default quint32 header_length = 0; KDE_fseek(mIndexStream, sizeof(char), SEEK_CUR ); fread(&header_length, sizeof(header_length), 1, mIndexStream); if (header_length > 0xFFFF) header_length = kmail_swap_32(header_length); off_t endOfHeader = KDE_ftell(mIndexStream) + header_length; bool needs_update = true; // Process available header parts if (header_length >= sizeof(byteOrder)) { fread(&byteOrder, sizeof(byteOrder), 1, mIndexStream); mIndexSwapByteOrder = (byteOrder == 0x78563412); header_length -= sizeof(byteOrder); if (header_length >= sizeof(sizeOfLong)) { fread(&sizeOfLong, sizeof(sizeOfLong), 1, mIndexStream); if (mIndexSwapByteOrder) sizeOfLong = kmail_swap_32(sizeOfLong); mIndexSizeOfLong = sizeOfLong; header_length -= sizeof(sizeOfLong); needs_update = false; } } if (needs_update || mIndexSwapByteOrder || (mIndexSizeOfLong != sizeof(long))) setDirty( true ); // Seek to end of header KDE_fseek(mIndexStream, endOfHeader, SEEK_SET ); if ( mIndexSwapByteOrder ) { kDebug() << "Index File has byte order swapped!"; } if ( mIndexSizeOfLong != sizeof( long ) ) { kDebug() << "Index File sizeOfLong is" << mIndexSizeOfLong << "while sizeof(long) is" << sizeof(long) << "!"; } } return true; }