TAR fs is now also working correctly in the real boot loader.

Some more cleanup and better error output.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14370 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2005-10-13 14:06:11 +00:00
parent 8d156f1c5e
commit 0ecc530bf0

View File

@ -5,6 +5,7 @@
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "tarfs.h" #include "tarfs.h"
#include <fcntl.h> #include <fcntl.h>
@ -24,6 +25,14 @@
#include <util/DoublyLinkedList.h> #include <util/DoublyLinkedList.h>
//#define TRACE_TARFS
#ifdef TRACE_TARFS
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
static const uint32 kCompressedArchiveOffset = 192 * 1024; // at 192 kB static const uint32 kCompressedArchiveOffset = 192 * 1024; // at 192 kB
static const size_t kTarRegionSize = 4 * 1024 * 1024; // 4 MB static const size_t kTarRegionSize = 4 * 1024 * 1024; // 4 MB
@ -32,7 +41,8 @@ namespace TarFS {
struct RegionDelete { struct RegionDelete {
inline void operator()(void *memory) inline void operator()(void *memory)
{ {
platform_free_region(memory, kTarRegionSize); if (memory != NULL)
platform_free_region(memory, kTarRegionSize);
} }
}; };
@ -45,14 +55,12 @@ class Directory;
class Entry : public DoublyLinkedListLinkImpl<Entry> { class Entry : public DoublyLinkedListLinkImpl<Entry> {
public: public:
Entry(const char *name) : fName(name) { Entry(const char *name) : fName(name) {}
printf("created Entry %p: %s\n", this, fName);
}
virtual ~Entry() {} virtual ~Entry() {}
const char *Name() const { return fName; } const char *Name() const { return fName; }
virtual ::Node *ToNode() = 0; virtual ::Node *ToNode() = 0;
virtual TarFS::Directory *ToTarDirectory() { return NULL; } virtual TarFS::Directory *ToTarDirectory() { return NULL; }
protected: protected:
const char *fName; const char *fName;
@ -195,6 +203,8 @@ TarFS::Node::~Node()
ssize_t ssize_t
TarFS::Node::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize) TarFS::Node::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize)
{ {
TRACE(("tarfs: read at %Ld, %lu bytes, fSize = %Ld\n", pos, bufferSize, fSize));
if (pos < 0 || !buffer) if (pos < 0 || !buffer)
return B_BAD_VALUE; return B_BAD_VALUE;
@ -205,7 +215,7 @@ TarFS::Node::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize)
if (toRead > bufferSize) if (toRead > bufferSize)
toRead = bufferSize; toRead = bufferSize;
memcpy(buffer, (char*)fHeader + 512 + pos, toRead); memcpy(buffer, (char*)fHeader + BLOCK_SIZE + pos, toRead);
return toRead; return toRead;
} }
@ -455,7 +465,7 @@ TarFS::Volume::Init(boot::Partition *partition)
cookie(cookie) cookie(cookie)
{ {
} }
~PartitionCloser() ~PartitionCloser()
{ {
partition->Close(cookie); partition->Close(cookie);
@ -502,8 +512,10 @@ TarFS::Volume::Init(boot::Partition *partition)
return B_BAD_DATA; return B_BAD_DATA;
if (platform_allocate_region((void **)&out, kTarRegionSize, if (platform_allocate_region((void **)&out, kTarRegionSize,
B_READ_AREA | B_WRITE_AREA) != B_OK) B_READ_AREA | B_WRITE_AREA) != B_OK) {
TRACE(("tarfs: allocating region failed!\n"));
return B_NO_MEMORY; return B_NO_MEMORY;
}
regionDeleter.SetTo(out); regionDeleter.SetTo(out);
zStream.avail_out = kTarRegionSize; zStream.avail_out = kTarRegionSize;
@ -518,13 +530,15 @@ TarFS::Volume::Init(boot::Partition *partition)
offset += sizeof(in); offset += sizeof(in);
if (zStream.avail_in != 0 && status != Z_STREAM_END) if (zStream.avail_in != 0 && status != Z_STREAM_END)
printf("buhuuu"); dprintf("tarfs: didn't read whole block!\n");
} while (status == Z_OK); } while (status == Z_OK);
inflateEnd(&zStream); inflateEnd(&zStream);
if (status != Z_STREAM_END) if (status != Z_STREAM_END) {
TRACE(("tarfs: inflating failed: %d!\n", status));
return B_BAD_DATA; return B_BAD_DATA;
}
status = B_OK; status = B_OK;
@ -543,8 +557,7 @@ TarFS::Volume::Init(boot::Partition *partition)
if (strcmp(header->magic, kTarHeaderMagic) != 0) { if (strcmp(header->magic, kTarHeaderMagic) != 0) {
if (strcmp(header->magic, kOldTarHeaderMagic) != 0) { if (strcmp(header->magic, kOldTarHeaderMagic) != 0) {
fprintf(stderr, "Bad tar header magic in block %d.\n", dprintf("Bad tar header magic in block %d.\n", blockIndex);
blockIndex);
status = B_BAD_DATA; status = B_BAD_DATA;
break; break;
} }
@ -552,6 +565,8 @@ TarFS::Volume::Init(boot::Partition *partition)
off_t size = strtol(header->size, NULL, 8); off_t size = strtol(header->size, NULL, 8);
TRACE(("tarfs: \"%s\", %Ld bytes\n", header->name, size));
// TODO: this is old-style GNU tar which probably won't work with newer ones... // TODO: this is old-style GNU tar which probably won't work with newer ones...
switch (header->type) { switch (header->type) {
case TAR_FILE: case TAR_FILE:
@ -593,12 +608,12 @@ TarFS::Volume::Init(boot::Partition *partition)
static status_t static status_t
tarfs_get_file_system(boot::Partition *partition, ::Directory **_root) tarfs_get_file_system(boot::Partition *partition, ::Directory **_root)
{ {
// TODO: Who owns the Volume object created here?
TarFS::Volume *volume = new TarFS::Volume; TarFS::Volume *volume = new TarFS::Volume;
if (volume == NULL) if (volume == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
if (volume->Init(partition) < B_OK) { if (volume->Init(partition) < B_OK) {
TRACE(("Initializing tarfs failed\n"));
delete volume; delete volume;
return B_ERROR; return B_ERROR;
} }