Example #1
0
//-----------------------------------------------------------------------------
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;
}
Example #2
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;
}
Example #4
0
//-----------------------------------------------------------------------------
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 );
}
Example #6
0
//-----------------------------------------------------------------------------
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;
}
Example #8
0
//-----------------------------------------------------------------------------
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;
}
Example #9
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;
}
Example #10
0
//-----------------------------------------------------------------------------
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;
}
Example #11
0
//-----------------------------------------------------------------------------
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;
}
Example #12
0
//-----------------------------------------------------------------------------
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;
}