Example #1
0
bool KTar::doWriteDir(const QString &name, const QString &user,
                      const QString &group, mode_t perm,
                      const QDateTime & /*atime*/, const QDateTime &mtime, const QDateTime & /*ctime*/) {
    if ( !isOpen() )
    {
        //qWarning() << "You must open the tar file before writing to it\n";
        return false;
    }

    if ( !(mode() & QIODevice::WriteOnly) )
    {
        //qWarning() << "You must open the tar file for writing\n";
        return false;
    }

    // In some tar files we can find dir/./ => call cleanPath
    QString dirName ( QDir::cleanPath( name ) );

    // Need trailing '/'
    if ( !dirName.endsWith( QLatin1Char( '/' ) ) )
        dirName += QLatin1Char( '/' );

    if ( d->dirList.contains( dirName ) )
        return true; // already there

    char buffer[ 0x201 ];
    memset( buffer, 0, 0x200 );
    if ( ( mode() & QIODevice::ReadWrite ) == QIODevice::ReadWrite )
        device()->seek(d->tarEnd); // Go to end of archive as might have moved with a read

    // provide converted stuff we need lateron
    QByteArray encodedDirname = QFile::encodeName(dirName);
    QByteArray uname = user.toLocal8Bit();
    QByteArray gname = group.toLocal8Bit();

    // If more than 100 chars, we need to use the LongLink trick
    if ( dirName.length() > 99 )
        d->writeLonglink(buffer,encodedDirname,'L',uname.constData(),gname.constData());

    // Write (potentially truncated) name
    strncpy( buffer, encodedDirname.constData(), 99 );
    buffer[99] = 0;
    // zero out the rest (except for what gets filled anyways)
    memset(buffer+0x9d, 0, 0x200 - 0x9d);

    QByteArray permstr = QByteArray::number( (unsigned int)perm, 8 );
    permstr = permstr.rightJustified(6, ' ');
    d->fillBuffer( buffer, permstr.constData(), 0, mtime, 0x35, uname.constData(), gname.constData());

    // Write header
    device()->write( buffer, 0x200 );
    if ( ( mode() & QIODevice::ReadWrite ) == QIODevice::ReadWrite )
        d->tarEnd = device()->pos();

    d->dirList.append( dirName ); // contains trailing slash
    return true; // TODO if wanted, better error control
}
Example #2
0
bool KTar::doWriteSymLink(const QString &name, const QString &target,
                        const QString &user, const QString &group,
                        mode_t perm, const QDateTime & /*atime*/, const QDateTime &mtime, const QDateTime & /*ctime*/) {
    if ( !isOpen() )
    {
        //qWarning() << "You must open the tar file before writing to it\n";
        return false;
    }

    if ( !(mode() & QIODevice::WriteOnly) )
    {
        //qWarning() << "You must open the tar file for writing\n";
        return false;
    }

    // In some tar files we can find dir/./file => call cleanPath
    QString fileName ( QDir::cleanPath( name ) );

    char buffer[ 0x201 ];
    memset( buffer, 0, 0x200 );
    if ( ( mode() & QIODevice::ReadWrite ) == QIODevice::ReadWrite )
        device()->seek(d->tarEnd); // Go to end of archive as might have moved with a read

    // provide converted stuff we need lateron
    QByteArray encodedFileName = QFile::encodeName(fileName);
    QByteArray encodedTarget = QFile::encodeName(target);
    QByteArray uname = user.toLocal8Bit();
    QByteArray gname = group.toLocal8Bit();

    // If more than 100 chars, we need to use the LongLink trick
    if (target.length() > 99)
        d->writeLonglink(buffer,encodedTarget,'K',uname.constData(),gname.constData());
    if ( fileName.length() > 99 )
        d->writeLonglink(buffer,encodedFileName,'L',uname.constData(),gname.constData());

    // Write (potentially truncated) name
    strncpy( buffer, encodedFileName.constData(), 99 );
    buffer[99] = 0;
    // Write (potentially truncated) symlink target
    strncpy(buffer+0x9d, encodedTarget.constData(), 99);
    buffer[0x9d+99] = 0;
    // zero out the rest
    memset(buffer+0x9d+100, 0, 0x200 - 100 - 0x9d);

    QByteArray permstr = QByteArray::number( (unsigned int)perm, 8 );
    permstr = permstr.rightJustified(6, ' ');
    d->fillBuffer(buffer, permstr.constData(), 0, mtime, 0x32, uname.constData(), gname.constData());

    // Write header
    bool retval = device()->write( buffer, 0x200 ) == 0x200;
    if ( ( mode() & QIODevice::ReadWrite ) == QIODevice::ReadWrite )
        d->tarEnd = device()->pos();
    return retval;
}
Example #3
0
void tst_QByteArray::rightJustified()
{
    QByteArray a;
    a="ABC";
    QCOMPARE(a.rightJustified(5,'-'),QByteArray("--ABC"));
    QCOMPARE(a.rightJustified(4,'-'),QByteArray("-ABC"));
    QCOMPARE(a.rightJustified(4),QByteArray(" ABC"));
    QCOMPARE(a.rightJustified(3),QByteArray("ABC"));
    QCOMPARE(a.rightJustified(2),QByteArray("ABC"));
    QCOMPARE(a.rightJustified(1),QByteArray("ABC"));
    QCOMPARE(a.rightJustified(0),QByteArray("ABC"));

    QByteArray n;
    QVERIFY(!n.rightJustified(3).isNull());  // I expected true
    QCOMPARE(a.rightJustified(4,'-',true),QByteArray("-ABC"));
    QCOMPARE(a.rightJustified(4,' ',true),QByteArray(" ABC"));
    QCOMPARE(a.rightJustified(3,' ',true),QByteArray("ABC"));
    QCOMPARE(a.rightJustified(2,' ',true),QByteArray("AB"));
    QCOMPARE(a.rightJustified(1,' ',true),QByteArray("A"));
    QCOMPARE(a.rightJustified(0,' ',true),QByteArray(""));
    QCOMPARE(a,QByteArray("ABC"));
}
Example #4
0
bool KTar::doPrepareWriting(const QString &name, const QString &user,
                          const QString &group, qint64 size, mode_t perm,
                          const QDateTime & /*atime*/, const QDateTime &mtime, const QDateTime & /*ctime*/) {
    if ( !isOpen() )
    {
        //qWarning() << "You must open the tar file before writing to it\n";
        return false;
    }

    if ( !(mode() & QIODevice::WriteOnly) )
    {
        //qWarning() << "You must open the tar file for writing\n";
        return false;
    }

    // In some tar files we can find dir/./file => call cleanPath
    QString fileName ( QDir::cleanPath( name ) );

    /*
      // Create toplevel dirs
      // Commented out by David since it's not necessary, and if anybody thinks it is,
      // he needs to implement a findOrCreate equivalent in writeDir.
      // But as KTar and the "tar" program both handle tar files without
      // dir entries, there's really no need for that
      QString tmp ( fileName );
      int i = tmp.lastIndexOf( '/' );
      if ( i != -1 )
      {
      QString d = tmp.left( i + 1 ); // contains trailing slash
      if ( !m_dirList.contains( d ) )
      {
      tmp = tmp.mid( i + 1 );
      writeDir( d, user, group ); // WARNING : this one doesn't create its toplevel dirs
      }
      }
    */

    char buffer[ 0x201 ];
    memset( buffer, 0, 0x200 );
    if ( ( mode() & QIODevice::ReadWrite ) == QIODevice::ReadWrite )
        device()->seek(d->tarEnd); // Go to end of archive as might have moved with a read

    // provide converted stuff we need later on
    const QByteArray encodedFileName = QFile::encodeName(fileName);
    const QByteArray uname = user.toLocal8Bit();
    const QByteArray gname = group.toLocal8Bit();

    // If more than 100 chars, we need to use the LongLink trick
    if ( fileName.length() > 99 )
        d->writeLonglink(buffer,encodedFileName,'L',uname.constData(),gname.constData());

    // Write (potentially truncated) name
    strncpy( buffer, encodedFileName.constData(), 99 );
    buffer[99] = 0;
    // zero out the rest (except for what gets filled anyways)
    memset(buffer+0x9d, 0, 0x200 - 0x9d);

    QByteArray permstr = QByteArray::number( (unsigned int)perm, 8 );
    permstr = permstr.rightJustified(6, '0');
    d->fillBuffer(buffer, permstr.constData(), size, mtime, 0x30, uname.constData(), gname.constData());

    // Write header
    return device()->write( buffer, 0x200 ) == 0x200;
}
Example #5
0
void KTar::KTarPrivate::fillBuffer(char *buffer,
                                   const char *mode, qint64 size, const QDateTime &mtime, char typeflag,
                                   const char *uname, const char *gname) {
  // mode (as in stpos())
  assert( strlen(mode) == 6 );
  memcpy( buffer+0x64, mode, 6 );
  buffer[ 0x6a ] = ' ';
  buffer[ 0x6b ] = '\0';

  // dummy uid
  strcpy( buffer + 0x6c, "   765 "); // 501 in decimal
  // dummy gid
  strcpy( buffer + 0x74, "   144 "); // 100 in decimal

  // size
  QByteArray s = QByteArray::number( size, 8 ); // octal
  s = s.rightJustified( 11, '0' );
  memcpy( buffer + 0x7c, s.data(), 11 );
  buffer[ 0x87 ] = ' '; // space-terminate (no null after)

  // modification time
  const QDateTime modificationTime = mtime.isValid() ? mtime : QDateTime::currentDateTime();
  s = QByteArray::number( static_cast<qulonglong>(modificationTime.toMSecsSinceEpoch() / 1000), 8 ); // octal
  s = s.rightJustified( 11, '0' );
  memcpy( buffer + 0x88, s.data(), 11 );
  buffer[ 0x93 ] = ' '; // space-terminate (no null after) -- well current tar writes a null byte

  // spaces, replaced by the check sum later
  buffer[ 0x94 ] = 0x20;
  buffer[ 0x95 ] = 0x20;
  buffer[ 0x96 ] = 0x20;
  buffer[ 0x97 ] = 0x20;
  buffer[ 0x98 ] = 0x20;
  buffer[ 0x99 ] = 0x20;

  /* From the tar sources :
     Fill in the checksum field.  It's formatted differently from the
     other fields: it has [6] digits, a null, then a space -- rather than
     digits, a space, then a null. */

  buffer[ 0x9a ] = '\0';
  buffer[ 0x9b ] = ' ';

  // type flag (dir, file, link)
  buffer[ 0x9c ] = typeflag;

  // magic + version
  strcpy( buffer + 0x101, "ustar");
  strcpy( buffer + 0x107, "00" );

  // user
  strcpy( buffer + 0x109, uname );
  // group
  strcpy( buffer + 0x129, gname );

  // Header check sum
  int check = 32;
  for( uint j = 0; j < 0x200; ++j )
    check += buffer[j];
  s = QByteArray::number( check, 8 ); // octal
  s = s.rightJustified( 6, '0' );
  memcpy( buffer + 0x94, s.constData(), 6 );
}