예제 #1
0
KArchiveDirectory *KArchive::findOrCreate(const QString &path)
{
    //qCDebug(KArchiveLog) << path;
    if (path.isEmpty() || path == QLatin1String("/") || path == QLatin1String(".")) { // root dir => found
        //qCDebug(KArchiveLog) << "returning rootdir";
        return rootDir();
    }
    // Important note : for tar files containing absolute paths
    // (i.e. beginning with "/"), this means the leading "/" will
    // be removed (no KDirectory for it), which is exactly the way
    // the "tar" program works (though it displays a warning about it)
    // See also KArchiveDirectory::entry().

    // Already created ? => found
    const KArchiveEntry *ent = rootDir()->entry(path);
    if (ent) {
        if (ent->isDirectory())
            //qCDebug(KArchiveLog) << "found it";
        {
            const KArchiveDirectory *dir = static_cast<const KArchiveDirectory *>(ent);
            return const_cast<KArchiveDirectory *>(dir);
        } else {
            const KArchiveFile *file = static_cast<const KArchiveFile *>(ent);
            if (file->size() > 0) {
                qCWarning(KArchiveLog) << path << "is normal file, but there are file paths in the archive assuming it is a directory, bailing out";
                return nullptr;
            }

            qCDebug(KArchiveLog) << path << " is an empty file, assuming it is actually a directory and replacing";
            KArchiveEntry *myEntry = const_cast<KArchiveEntry*>(ent);
            rootDir()->removeEntry(myEntry);
            delete myEntry;
        }
    }

    // Otherwise go up and try again
    int pos = path.lastIndexOf(QLatin1Char('/'));
    KArchiveDirectory *parent;
    QString dirname;
    if (pos == -1) { // no more slash => create in root dir
        parent =  rootDir();
        dirname = path;
    } else {
        QString left = path.left(pos);
        dirname = path.mid(pos + 1);
        parent = findOrCreate(left);   // recursive call... until we find an existing dir.
    }

    //qCDebug(KArchiveLog) << "found parent " << parent->name() << " adding " << dirname << " to ensure " << path;
    // Found -> add the missing piece
    KArchiveDirectory *e = new KArchiveDirectory(this, dirname, d->rootDir->permissions(),
                                                 d->rootDir->date(), d->rootDir->user(),
                                                 d->rootDir->group(), QString());
    parent->addEntry(e);
    return e; // now a directory to <path> exists
}
예제 #2
0
*/ std::shared_ptr<FileNode> DirNode::openNode(const char *plainName,
                                               const char *requestor, int flags,
                                               int *result) {
  (void)requestor;
  rAssert(result != NULL);
  Lock _lock(mutex);

  std::shared_ptr<FileNode> node = findOrCreate(plainName);

  if (node && (*result = node->open(flags)) >= 0)
    return node;
  else
    return std::shared_ptr<FileNode>();
}
예제 #3
0
KArchiveDirectory * KArchiveHandler::findOrCreate( const QString & path )
{
    //qDebug() << path;
    if ( path.isEmpty() || path == QLatin1String("/") || path == QLatin1String(".") ) // root dir => found
    {
        //qDebug() << "returning rootdir";
        return rootDir();
    }
    // Important note : for tar files containing absolute paths
    // (i.e. beginning with "/"), this means the leading "/" will
    // be removed (no KDirectory for it), which is exactly the way
    // the "tar" program works (though it displays a warning about it)
    // See also KArchiveDirectory::entry().

    // Already created ? => found
    const KArchiveEntry* ent = rootDir()->entry( path );
    if ( ent )
    {
        if ( ent->isDirectory() )
            //qDebug() << "found it";
            return (KArchiveDirectory *) ent;
        else {
            //qWarning() << "Found" << path << "but it's not a directory";
        }
    }

    // Otherwise go up and try again
    int pos = path.lastIndexOf( QLatin1Char('/') );
    KArchiveDirectory * parent;
    QString dirname;
    if ( pos == -1 ) // no more slash => create in root dir
    {
        parent =  rootDir();
        dirname = path;
    }
    else
    {
        QString left = path.left( pos );
        dirname = path.mid( pos + 1 );
        parent = findOrCreate( left ); // recursive call... until we find an existing dir.
    }

    //qDebug() << "found parent " << parent->name() << " adding " << dirname << " to ensure " << path;
    // Found -> add the missing piece
    KArchiveDirectory * e = new KArchiveDirectory( d->archive, dirname, d->rootDir->permissions(),
                                                   d->rootDir->date(), d->rootDir->user(),
                                                   d->rootDir->group(), QString() );
    parent->addEntry( e );
    return e; // now a directory to <path> exists
}
예제 #4
0
파일: kPak.cpp 프로젝트: Uiomae/kio_pak
bool KPak::openArchive(int mode) {
	kdDebug(7000) << "openArchiving!";
	if ( mode == IO_WriteOnly )
		return true;
	if ( mode != IO_ReadOnly && mode != IO_ReadWrite )
	{
		kdWarning(7000) << "Unsupported mode " << mode << endl;
		return false;
	}
	
	QIODevice *dev = device();

	if (!dev)
		return false;

	_pakFile = new libPak(dev);
	if (!_pakFile->isValidPak()) {
		kdWarning(7000) << "Invalid file magic" << endl;
		return false;
	}

	QValueList<libPak::PakFile> files(_pakFile->getAllFiles());
	
	for ( QValueList<libPak::PakFile>::Iterator it = files.begin(); it != files.end(); ++it ) {
		QString temp((*it).filename.mid(1));
		temp.replace("\\", "/");
		int pos = temp.findRev("/");
		QString file;
		file = temp.mid(pos + 1);
		// TODO: Add position and size
		KArchiveEntry *e = new KArchiveFile(this, file, 0444, 0, /*uid*/0, /*gid*/0, /*symlink*/0, (int)(*it).offset, (*it).size);
		if (pos == -1) {
			rootDir()->addEntry(e);
		} else {
			QString path = QDir::cleanDirPath( (*it).filename.mid(1).replace("\\", "/").left(pos) );
			KArchiveDirectory *d = findOrCreate(path);
			d->addEntry(e);
		}
	}
	return true;
}
예제 #5
0
std::shared_ptr<FileNode> DirNode::renameNode(const char *from, const char *to,
                                              bool forwardMode) {
  std::shared_ptr<FileNode> node = findOrCreate(from);

  if (node) {
    uint64_t newIV = 0;
    string cname = rootDir + naming->encodePath(to, &newIV);

    VLOG(1) << "renaming internal node " << node->cipherName() << " -> "
            << cname;

    if (node->setName(to, cname.c_str(), newIV, forwardMode)) {
      if (ctx) ctx->renameNode(from, to);
    } else {
      // rename error! - put it back
      RLOG(ERROR) << "renameNode failed";
      throw Error("Internal node name change failed!");
    }
  }

  return node;
}
예제 #6
0
TerrainMaterial* TerrainMaterial::getWarningMaterial()
{ 
   return findOrCreate( NULL );
}
예제 #7
0
bool KTar::openArchive( QIODevice::OpenMode mode ) {

    if ( !(mode & QIODevice::ReadOnly) )
        return true;

    if ( !d->fillTempFile( fileName() ) )
        return false;

    // We'll use the permission and user/group of d->rootDir
    // for any directory we emulate (see findOrCreate)
    //struct stat buf;
    //stat( fileName(), &buf );

    d->dirList.clear();
    QIODevice* dev = device();

    if ( !dev )
        return false;

    // read dir information
    char buffer[ 0x200 ];
    bool ende = false;
    do
    {
        QString name;
        QString symlink;

        // Read header
        qint64 n = d->readHeader( buffer, name, symlink );
        if (n < 0) return false;
        if (n == 0x200)
        {
            bool isdir = false;

            if ( name.endsWith( QLatin1Char( '/' ) ) )
            {
                isdir = true;
                name.truncate( name.length() - 1 );
            }

            QByteArray prefix = QByteArray(buffer + 0x159, 155);
            if (prefix[0] != '\0') {
                name = (QString::fromLatin1(prefix.constData()) + QLatin1Char('/') +  name);
            }

            int pos = name.lastIndexOf( QLatin1Char('/') );
            QString nm = ( pos == -1 ) ? name : name.mid( pos + 1 );

            // read access
            buffer[ 0x6b ] = 0;
            char *dummy;
            const char* p = buffer + 0x64;
            while( *p == ' ' ) ++p;
            int access = (int)strtol( p, &dummy, 8 );

            // read user and group
            QString user = QString::fromLocal8Bit( buffer + 0x109 );
            QString group = QString::fromLocal8Bit( buffer + 0x129 );

            // read time
            buffer[ 0x93 ] = 0;
            p = buffer + 0x88;
            while( *p == ' ' ) ++p;
            uint time = (int)strtol( p, &dummy, 8 );

            // read type flag
            char typeflag = buffer[ 0x9c ];
            // '0' for files, '1' hard link, '2' symlink, '5' for directory
            // (and 'L' for longlink fileNames, 'K' for longlink symlink targets)
            // 'D' for GNU tar extension DUMPDIR, 'x' for Extended header referring
            // to the next file in the archive and 'g' for Global extended header

            if ( typeflag == '5' )
                isdir = true;

            bool isDumpDir = false;
            if ( typeflag == 'D' )
            {
                isdir = false;
                isDumpDir = true;
            }
            //qDebug() << nm << "isdir=" << isdir << "pos=" << dev->pos() << "typeflag=" << typeflag << " islink=" << ( typeflag == '1' || typeflag == '2' );

            if (typeflag == 'x' || typeflag == 'g') { // pax extended header, or pax global extended header
                // Skip it for now. TODO: implement reading of extended header, as per http://pubs.opengroup.org/onlinepubs/009695399/utilities/pax.html
                (void)dev->read( buffer, 0x200 );
                continue;
            }

            if (isdir)
                access |= S_IFDIR; // f*cking broken tar files

            KArchiveEntry* e;
            if ( isdir )
            {
                //qDebug() << "directory" << nm;
                e = new KArchiveDirectory( this, nm, access, KArchivePrivate::time_tToDateTime(time), user, group, symlink );
            }
            else
            {
                // read size
                QByteArray sizeBuffer( buffer + 0x7c, 12 );
                qint64 size = sizeBuffer.trimmed().toLongLong( 0, 8 /*octal*/ );
                //qDebug() << "sizeBuffer='" << sizeBuffer << "' -> size=" << size;

                // for isDumpDir we will skip the additional info about that dirs contents
                if ( isDumpDir )
                {
                    //qDebug() << nm << "isDumpDir";
                    e = new KArchiveDirectory( this, nm, access, KArchivePrivate::time_tToDateTime(time), user, group, symlink );
                }
                else
                {

                    // Let's hack around hard links. Our classes don't support that, so make them symlinks
                    if ( typeflag == '1' )
                    {
                        //qDebug() << "Hard link, setting size to 0 instead of" << size;
                        size = 0; // no contents
                    }

                    //qDebug() << "file" << nm << "size=" << size;
                    e = new KArchiveFile( this, nm, access, KArchivePrivate::time_tToDateTime(time), user, group, symlink,
                                          dev->pos(), size );
                }

                // Skip contents + align bytes
                qint64 rest = size % 0x200;
                qint64 skip = size + (rest ? 0x200 - rest : 0);
                //qDebug() << "pos()=" << dev->pos() << "rest=" << rest << "skipping" << skip;
                if (! dev->seek( dev->pos() + skip ) ) {
                    //qWarning() << "skipping" << skip << "failed";
                }
            }

            if ( pos == -1 )
            {
                if (nm == QLatin1String(".")) { // special case
                    Q_ASSERT( isdir );
                    if (isdir) {
                        setRootDir( static_cast<KArchiveDirectory *>( e ) );
                    }
                } else {
                    rootDir()->addEntry( e );
                }
            }
            else
            {
                // In some tar files we can find dir/./file => call cleanPath
                QString path = QDir::cleanPath( name.left( pos ) );
                // Ensure container directory exists, create otherwise
                KArchiveDirectory * d = findOrCreate( path );
                d->addEntry( e );
            }
        }
        else
        {
            //qDebug("Terminating. Read %d bytes, first one is %d", n, buffer[0]);
            d->tarEnd = dev->pos() - n; // Remember end of archive
            ende = true;
        }
    } while( !ende );
    return true;
}
예제 #8
0
shared_ptr<FileNode> DirNode::lookupNode(const char *plainName,
                                         const char * /* requestor */) {
  Lock _lock(mutex);
  return findOrCreate(plainName);
}
예제 #9
0
int DirNode::rename(const char *fromPlaintext, const char *toPlaintext) {
  Lock _lock(mutex);

  string fromCName = rootDir + naming->encodePath(fromPlaintext);
  string toCName = rootDir + naming->encodePath(toPlaintext);
  rAssert(!fromCName.empty());
  rAssert(!toCName.empty());

  VLOG(1) << "rename " << fromCName << " -> " << toCName;

  std::shared_ptr<FileNode> toNode = findOrCreate(toPlaintext);

  std::shared_ptr<RenameOp> renameOp;
  if (hasDirectoryNameDependency() && isDirectory(fromCName.c_str())) {
    VLOG(1) << "recursive rename begin";
    renameOp = newRenameOp(fromPlaintext, toPlaintext);

    if (!renameOp || !renameOp->apply()) {
      if (renameOp) renameOp->undo();

      RLOG(WARNING) << "rename aborted";
      return -EACCES;
    }
    VLOG(1) << "recursive rename end";
  }

  int res = 0;
  try {
	struct stat_st st;
    bool preserve_mtime = unix::stat(fromCName.c_str(), &st) == 0;

    renameNode(fromPlaintext, toPlaintext);
    res = unix::rename(fromCName.c_str(), toCName.c_str());

    if (res == -1) {
      // undo
      res = -errno;
      renameNode(toPlaintext, fromPlaintext, false);

      if (renameOp) renameOp->undo();
    } else if (preserve_mtime) {
      struct utimbuf ut;

#ifdef USE_LEGACY_DOKAN
	  ut.actime = st.st_atime;
	  ut.modtime = st.st_mtime;
#else
	  ut.actime = st.st_atim.tv_sec;
	  ut.modtime = st.st_mtim.tv_sec;
#endif

      unix::utime(toCName.c_str(), &ut);
    }
  } catch (encfs::Error &err) {
    // exception from renameNode, just show the error and continue..
    RLOG(WARNING) << err.what();
    res = -EIO;
  }

  if (res != 0) {
    VLOG(1) << "rename failed: " << strerror(errno);
    res = -errno;
  }

  return res;
}
예제 #10
0
/// \fn NetConnection::receive()
/// \brief Receive data from the socket
void NetConnection::receive()
{
   NetAddress address;
   while ( mSocket.select(true, false) )
   {
      PackageHandle package(mAllocator);

      try
      {
         int bytes = mSocket.receive(address, *package);
         ASSERT(package.hasObject());

         NetAddress& client = findOrCreate(address); 
         client.lastTimeRecv = Timer::getInstance().getTick();

         if ( client.pstatistics )
         {
            client.pstatistics->received(bytes);
         }

         switch ( package->getType() )
         {
            case NetPackage::eAck:
               {
                  client.removeAcknowledged(package->getNumber());
                  break;
               }
            case NetPackage::eAlive:
               {
                  // don't do anything with the I'm alive message
                  break;
               }
            case NetPackage::eRequest:
               {
                  // add the requested message at the front of the queue,
                  // so it gets checked first
                  client.mOrderQueue.insert(package);
                  break;
               }
            case NetPackage::eEvent:
               {
                  NetPackage::Reliability reliability = package->getReliability();
                  if ( reliability == NetPackage::eReliableSequenced )
                  {
                     // the older packages are no longer valid, can be removed
                     //client.mOrderQueue.removeOldPackages(package->getNumber());
                     for (auto it = client.mOrderQueue.begin(); it != client.mOrderQueue.end(); )
                     {
                        const auto& p = *it;
                        if (p->getNumber() < package->getNumber())
                        {
                           it = client.mOrderQueue.erase(it);
                        }
                        else
                        {
                           break;
                        }
                     }
                     client.nextPackageNumber = package->getNumber();
                  }

                  client.mOrderQueue.insert(package);
                  break;
               }
            case NetPackage::eInvalid:
            default:
               UNREACHABLE("Invalid package type.");
               break;
         }
      }
      catch ( NetSocketException* pexception )
      {
         switch ( pexception->getError() )
         {
            case NetSocketException::eConnReset:
               {
                  NetAddress *pclient = mClients.find(address); 
                  if ( pclient != NULL )
                  {
                     mClients.remove(pclient->index);
                  }
                  // else nothing to close
                  break;
               }
         }
      }
   }
}