From 36c5179a74ff3080d2ebf72e7059e9eedb1f9a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 16 Sep 2003 00:58:04 +0000 Subject: [PATCH] Implemented file reading (only slightly tested, but it should be enough for our purposes [just copied some files in 1024 byte blocks to the Desktop]). git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4701 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../loader/file_systems/amiga_ffs/File.cpp | 183 +++++++++++++++++- .../boot/loader/file_systems/amiga_ffs/File.h | 4 + 2 files changed, 185 insertions(+), 2 deletions(-) diff --git a/src/kernel/boot/loader/file_systems/amiga_ffs/File.cpp b/src/kernel/boot/loader/file_systems/amiga_ffs/File.cpp index 3513d59cf7..f173516dbd 100644 --- a/src/kernel/boot/loader/file_systems/amiga_ffs/File.cpp +++ b/src/kernel/boot/loader/file_systems/amiga_ffs/File.cpp @@ -14,8 +14,156 @@ namespace FFS { -File::File(Volume &volume, int32 block) +class Stream { + public: + Stream(int device, FileBlock &node); + ~Stream(); + + status_t InitCheck(); + ssize_t ReadAt(off_t offset, uint8 *buffer, size_t size); + + private: + int32 BlockOffset(off_t offset) const; + int32 BlockIndex(off_t offset) const; + int32 ExtensionBlockOffset(off_t offset) const; + status_t ReadNextExtension(); + + int fDevice; + FileBlock &fNode; + FileBlock fBlock; + int32 fExtensionBlockOffset; +}; + + +Stream::Stream(int device, FileBlock &node) + : + fDevice(device), + fNode(node) { + void *buffer = malloc(fNode.BlockSize()); + if (buffer == NULL) + return; + + fExtensionBlockOffset = 0; + fBlock.SetTo(buffer, fNode.BlockSize()); +} + + +Stream::~Stream() +{ + free(fBlock.BlockData()); +} + + +status_t +Stream::InitCheck() +{ + return fBlock.BlockData() != NULL ? B_OK : B_NO_MEMORY; +} + + +int32 +Stream::BlockOffset(off_t offset) const +{ + return offset % fNode.BlockSize(); +} + + +int32 +Stream::BlockIndex(off_t offset) const +{ + return (offset % (fNode.BlockSize() * fNode.NumDataBlocks())) / fNode.BlockSize(); +} + + +int32 +Stream::ExtensionBlockOffset(off_t offset) const +{ + return offset / (fNode.BlockSize() * fNode.NumDataBlocks()); +} + + +status_t +Stream::ReadNextExtension() +{ + int32 next; + if (fExtensionBlockOffset == 0) + next = fNode.NextExtension(); + else + next = fBlock.NextExtension(); + + if (read_pos(fDevice, next * fNode.BlockSize(), fBlock.BlockData(), fNode.BlockSize()) < B_OK) + return B_ERROR; + + return fBlock.ValidateCheckSum(); +} + + +ssize_t +Stream::ReadAt(off_t offset, uint8 *buffer, size_t size) +{ + if (offset < 0) + return B_BAD_VALUE; + if (offset + size > fNode.Size()) + size = fNode.Size() - offset; + + ssize_t bytesLeft = (ssize_t)size; + + while (bytesLeft != 0) { + int32 extensionBlock = ExtensionBlockOffset(offset); + + // get the right extension block + + if (extensionBlock < fExtensionBlockOffset) + fExtensionBlockOffset = 1; + + while (fExtensionBlockOffset < extensionBlock) { + if (ReadNextExtension() != B_OK) + return B_ERROR; + + fExtensionBlockOffset++; + } + + // read the data block into memory + + int32 block; + if (extensionBlock == 0) + block = fNode.DataBlock(BlockIndex(offset)); + else + block = fBlock.DataBlock(BlockIndex(offset)); + + int32 blockOffset = BlockOffset(offset); + int32 toRead = fNode.BlockSize() - blockOffset; + if (toRead > bytesLeft) + toRead = bytesLeft; + + ssize_t bytesRead = read_pos(fDevice, block * fNode.BlockSize() + blockOffset, + buffer, toRead); + if (bytesRead < B_OK) + return bytesRead; + + bytesLeft -= bytesRead; + buffer += bytesRead; + offset += fNode.BlockSize() - blockOffset; + } + + return size; +} + + +// #pragma mark - + + +File::File(Volume &volume, int32 block) + : + fVolume(volume) +{ + void *data = malloc(volume.BlockSize()); + if (data == NULL) + return; + + if (read_pos(volume.Device(), block * volume.BlockSize(), data, volume.BlockSize()) == volume.BlockSize()) + fNode.SetTo(data, volume.BlockSize()); } @@ -34,10 +182,41 @@ File::InitCheck() } +status_t +File::Open(void **_cookie, int mode) +{ + Stream *stream = new Stream(fVolume.Device(), fNode); + if (stream == NULL) + return B_NO_MEMORY; + + if (stream->InitCheck() != B_OK) { + delete stream; + return B_NO_MEMORY; + } + + *_cookie = (void *)stream; + return B_OK; +} + + +status_t +File::Close(void *cookie) +{ + Stream *stream = (Stream *)cookie; + + delete stream; + return B_OK; +} + + ssize_t File::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize) { - return B_ERROR; + Stream *stream = (Stream *)cookie; + if (stream == NULL) + return B_BAD_VALUE; + + return stream->ReadAt(pos, (uint8 *)buffer, bufferSize); } diff --git a/src/kernel/boot/loader/file_systems/amiga_ffs/File.h b/src/kernel/boot/loader/file_systems/amiga_ffs/File.h index ac0fabe303..6edccab058 100644 --- a/src/kernel/boot/loader/file_systems/amiga_ffs/File.h +++ b/src/kernel/boot/loader/file_systems/amiga_ffs/File.h @@ -20,6 +20,9 @@ class File : public Node { status_t InitCheck(); + virtual status_t Open(void **_cookie, int mode); + virtual status_t Close(void *cookie); + virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize); virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize); @@ -28,6 +31,7 @@ class File : public Node { virtual off_t Size() const; private: + Volume &fVolume; FileBlock fNode; };