Author: bonefish Date: 2009-11-19 17:31:16 +0100 (Thu, 19 Nov 2009) New Revision: 34138 Changeset: http://dev.haiku-os.org/changeset/34138/haiku Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Directory.cpp haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Directory.h haiku/trunk/src/add-ons/kernel/file_systems/packagefs/LeafNode.cpp haiku/trunk/src/add-ons/kernel/file_systems/packagefs/LeafNode.h haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Node.h haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageFile.cpp haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageFile.h haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageLeafNode.cpp haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageLeafNode.h haiku/trunk/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp haiku/trunk/src/bin/package/PackageDataReader.cpp haiku/trunk/src/bin/package/PackageDataReader.h Log: * Added method PackageDataReader::ReadDataToOutput(), which writes the read data to a DataOutput. * Implemented packagefs' io() hook and changed the read() hook implementation to use the file cache. It's now possible to mmap() files and thus execute programs. Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Directory.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Directory.cpp 2009-11-19 16:26:40 UTC (rev 34137) +++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Directory.cpp 2009-11-19 16:31:16 UTC (rev 34138) @@ -125,6 +125,13 @@ } +status_t +Directory::Read(io_request* request) +{ + return B_IS_A_DIRECTORY; +} + + void Directory::AddChild(Node* node) { Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Directory.h =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Directory.h 2009-11-19 16:26:40 UTC (rev 34137) +++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Directory.h 2009-11-19 16:31:16 UTC (rev 34138) @@ -46,6 +46,7 @@ virtual status_t Read(off_t offset, void* buffer, size_t* bufferSize); + virtual status_t Read(io_request* request); void AddChild(Node* node); void RemoveChild(Node* node); Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/LeafNode.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/LeafNode.cpp 2009-11-19 16:26:40 UTC (rev 34137) +++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/LeafNode.cpp 2009-11-19 16:31:16 UTC (rev 34138) @@ -118,6 +118,15 @@ } +status_t +LeafNode::Read(io_request* request) +{ + if (PackageLeafNode* packageNode = fPackageNodes.Head()) + return packageNode->Read(request); + return EBADF; +} + + const char* LeafNode::SymlinkPath() const { Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/LeafNode.h =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/LeafNode.h 2009-11-19 16:26:40 UTC (rev 34137) +++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/LeafNode.h 2009-11-19 16:31:16 UTC (rev 34138) @@ -32,6 +32,7 @@ virtual status_t Read(off_t offset, void* buffer, size_t* bufferSize); + virtual status_t Read(io_request* request); const char* SymlinkPath() const; Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Node.h =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Node.h 2009-11-19 16:26:40 UTC (rev 34137) +++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Node.h 2009-11-19 16:31:16 UTC (rev 34138) @@ -57,6 +57,7 @@ virtual status_t Read(off_t offset, void* buffer, size_t* bufferSize) = 0; + virtual status_t Read(io_request* request) = 0; protected: rw_lock fLock; Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageFile.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageFile.cpp 2009-11-19 16:26:40 UTC (rev 34137) +++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageFile.cpp 2009-11-19 16:31:16 UTC (rev 34138) @@ -11,6 +11,7 @@ #include <fs_cache.h> +#include "DataOutput.h" #include "DataReader.h" #include "PackageDataReader.h" @@ -22,6 +23,24 @@ // #pragma mark - DataAccessor +struct PackageFile::IORequestOutput : DataOutput { +public: + IORequestOutput(io_request* request) + : + fRequest(request) + { + } + + virtual status_t WriteData(const void* buffer, size_t size) + { + RETURN_ERROR(write_to_io_request(fRequest, buffer, size)); + } + +private: + io_request* fRequest; +}; + + struct PackageFile::DataAccessor { DataAccessor(PackageData* data) : @@ -73,17 +92,31 @@ if (offset < 0 || (uint64)offset > fData->UncompressedSize()) return B_BAD_VALUE; - size_t toRead = std::min((uint64)*bufferSize, + *bufferSize = std::min((uint64)*bufferSize, fData->UncompressedSize() - offset); + return file_cache_read(fFileCache, NULL, offset, buffer, bufferSize); + } + + status_t ReadData(io_request* request) + { + off_t offset = io_request_offset(request); + size_t size = io_request_length(request); + + if (offset < 0 || (uint64)offset > fData->UncompressedSize()) + RETURN_ERROR(B_BAD_VALUE); + + size_t toRead = std::min((uint64)size, + fData->UncompressedSize() - offset); + if (toRead > 0) { + IORequestOutput output(request); MutexLocker locker(fLock); - status_t error = fReader->ReadData(offset, buffer, toRead); + status_t error = fReader->ReadDataToOutput(offset, toRead, &output); if (error != B_OK) RETURN_ERROR(error); } - *bufferSize = toRead; return B_OK; } @@ -164,3 +197,12 @@ return B_BAD_VALUE; return fDataAccessor->ReadData(offset, buffer, bufferSize); } + + +status_t +PackageFile::Read(io_request* request) +{ + if (fDataAccessor == NULL) + return B_BAD_VALUE; + return fDataAccessor->ReadData(request); +} Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageFile.h =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageFile.h 2009-11-19 16:26:40 UTC (rev 34137) +++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageFile.h 2009-11-19 16:31:16 UTC (rev 34138) @@ -24,8 +24,10 @@ virtual status_t Read(off_t offset, void* buffer, size_t* bufferSize); + virtual status_t Read(io_request* request); private: + struct IORequestOutput; struct DataAccessor; private: Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageLeafNode.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageLeafNode.cpp 2009-11-19 16:26:40 UTC (rev 34137) +++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageLeafNode.cpp 2009-11-19 16:31:16 UTC (rev 34138) @@ -31,3 +31,10 @@ { return EBADF; } + + +status_t +PackageLeafNode::Read(io_request* request) +{ + return EBADF; +} Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageLeafNode.h =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageLeafNode.h 2009-11-19 16:26:40 UTC (rev 34137) +++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageLeafNode.h 2009-11-19 16:31:16 UTC (rev 34138) @@ -8,7 +8,9 @@ #include "PackageNode.h" +#include <io_requests.h> + class PackageData; @@ -21,6 +23,7 @@ virtual status_t Read(off_t offset, void* buffer, size_t* bufferSize); + virtual status_t Read(io_request* request); public: SinglyLinkedListLink<PackageLeafNode> fListLink; Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp 2009-11-19 16:26:40 UTC (rev 34137) +++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp 2009-11-19 16:31:16 UTC (rev 34138) @@ -14,6 +14,7 @@ #include <fs_info.h> #include <fs_interface.h> #include <KernelExport.h> +#include <io_requests.h> #include <AutoDeleter.h> @@ -249,13 +250,24 @@ // #pragma mark - Request I/O -#if 0 static status_t -packagefs_io(fs_volume* volume, fs_vnode* vnode, void* cookie, +packagefs_io(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, io_request* request) { + Volume* volume = (Volume*)fsVolume->private_volume; + Node* node = (Node*)fsNode->private_node; + + FUNCTION("volume: %p, node: %p (%lld), cookie: %p, request: %p\n", volume, + node, node->ID(), cookie, request); + TOUCH(volume); + + if (io_request_is_write(request)) + RETURN_ERROR(B_READ_ONLY_DEVICE); + + status_t error = node->Read(request); + notify_io_request(request, error); + return error; } -#endif // #pragma mark - Nodes @@ -517,6 +529,7 @@ Node* node = (Node*)fsNode->private_node; FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID()); + TOUCH(volume); if (!S_ISDIR(node->Mode())) return B_NOT_A_DIRECTORY; @@ -702,6 +715,7 @@ Node* node = (Node*)fsNode->private_node; FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID()); + TOUCH(volume); status_t error = check_access(node, R_OK); if (error != B_OK) @@ -1087,7 +1101,7 @@ NULL, // read_pages, NULL, // write_pages, - NULL, // &packagefs_io, + &packagefs_io, NULL, // cancel_io() NULL, // get_file_map, Modified: haiku/trunk/src/bin/package/PackageDataReader.cpp =================================================================== --- haiku/trunk/src/bin/package/PackageDataReader.cpp 2009-11-19 16:26:40 UTC (rev 34137) +++ haiku/trunk/src/bin/package/PackageDataReader.cpp 2009-11-19 16:31:16 UTC (rev 34138) @@ -14,6 +14,7 @@ #include <haiku_package.h> #include "BufferCache.h" +#include "DataOutput.h" #include "PackageData.h" #include "ZlibDecompressor.h" @@ -25,7 +26,10 @@ // maximum number of entries in the zlib offset table buffer static const uint32 kMaxZlibOffsetTableBufferSize = 512; +static const size_t kUncompressedReaderBufferSize + = B_HPKG_DEFAULT_DATA_CHUNK_SIZE_ZLIB; + // #pragma mark - PackageDataReader @@ -41,14 +45,24 @@ } +status_t +PackageDataReader::ReadData(off_t offset, void* buffer, size_t size) +{ + BufferDataOutput output(buffer, size); + return ReadDataToOutput(offset, size, &output); +} + + // #pragma mark - UncompressedPackageDataReader class UncompressedPackageDataReader : public PackageDataReader { public: - UncompressedPackageDataReader(DataReader* dataReader) + UncompressedPackageDataReader(DataReader* dataReader, + BufferCache* bufferCache) : - PackageDataReader(dataReader) + PackageDataReader(dataReader), + fBufferCache(bufferCache) { } @@ -84,9 +98,49 @@ return fDataReader->ReadData(fOffset + offset, buffer, size); } + virtual status_t ReadDataToOutput(off_t offset, size_t size, + DataOutput* output) + { + if (size == 0) + return B_OK; + + if (offset < 0) + return B_BAD_VALUE; + + if ((uint64)offset > fSize || size > fSize - offset) + return B_BAD_VALUE; + + // get a temporary buffer + CachedBuffer* buffer = fBufferCache->GetBuffer( + kUncompressedReaderBufferSize); + if (buffer == NULL) + return B_NO_MEMORY; + CachedBufferPutter bufferPutter(fBufferCache, &buffer); + + while (size > 0) { + // read into the buffer + size_t toRead = std::min(size, buffer->Size()); + status_t error = fDataReader->ReadData(fOffset + offset, + buffer->Buffer(), toRead); + if (error != B_OK) + return error; + + // write to the output + error = output->WriteData(buffer->Buffer(), toRead); + if (error != B_OK) + return error; + + offset += toRead; + size -= toRead; + } + + return B_OK; + } + private: - uint64 fOffset; - uint64 fSize; + BufferCache* fBufferCache; + uint64 fOffset; + uint64 fSize; }; @@ -161,10 +215,9 @@ return fChunkSize; } - virtual status_t ReadData(off_t offset, void* _buffer, size_t size) + virtual status_t ReadDataToOutput(off_t offset, size_t size, + DataOutput* output) { - uint8* buffer = (uint8*)_buffer; - // check offset and size if (size == 0) return B_OK; @@ -183,7 +236,8 @@ == NULL) { return B_NO_MEMORY; } - CachedBufferPutter uncompressBuffer(fBufferCache, &fUncompressBuffer); + CachedBufferPutter uncompressBufferPutter(fBufferCache, + &fUncompressBuffer); if (newBuffer) fUncompressedChunk = -1; @@ -199,12 +253,13 @@ if (error != B_OK) return error; - // copy data to buffer + // write data to output size_t toCopy = std::min(size, (size_t)fChunkSize - inChunkOffset); - memcpy(buffer, (uint8*)fUncompressBuffer->Buffer() + inChunkOffset, - toCopy); + error = output->WriteData( + (uint8*)fUncompressBuffer->Buffer() + inChunkOffset, toCopy); + if (error != B_OK) + return error; - buffer += toCopy; size -= toCopy; chunkIndex++; @@ -372,7 +427,7 @@ switch (data.Compression()) { case B_HPKG_COMPRESSION_NONE: reader = new(std::nothrow) UncompressedPackageDataReader( - dataReader); + dataReader, fBufferCache); break; case B_HPKG_COMPRESSION_ZLIB: reader = new(std::nothrow) ZlibPackageDataReader(dataReader, Modified: haiku/trunk/src/bin/package/PackageDataReader.h =================================================================== --- haiku/trunk/src/bin/package/PackageDataReader.h 2009-11-19 16:26:40 UTC (rev 34137) +++ haiku/trunk/src/bin/package/PackageDataReader.h 2009-11-19 16:31:16 UTC (rev 34138) @@ -10,6 +10,7 @@ class BufferCache; +class DataOutput; class PackageData; @@ -20,6 +21,11 @@ virtual status_t Init(const PackageData& data) = 0; + virtual status_t ReadData(off_t offset, void* buffer, + size_t size); + virtual status_t ReadDataToOutput(off_t offset, size_t size, + DataOutput* output) = 0; + virtual uint64 Size() const = 0; virtual size_t BlockSize() const = 0;