* Cleanup.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32281 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-08-12 14:39:37 +00:00
parent db341f3691
commit 30f4c392a4
@@ -1,6 +1,6 @@
/* /*
* Copyright 2005-2007, Ingo Weinhold, [email protected]. * Copyright 2005-2007, Ingo Weinhold, [email protected].
* Copyright 2005, Axel Dörfler, [email protected]. All rights reserved. * Copyright 2005-2009, Axel Dörfler, [email protected].
* *
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -33,13 +33,14 @@
#endif #endif
static const uint32 kFloppyArchiveOffset = BOOT_ARCHIVE_IMAGE_OFFSET * 1024; // initially at 192 kB, now defined at build time static const uint32 kFloppyArchiveOffset = BOOT_ARCHIVE_IMAGE_OFFSET * 1024;
// defined at build time, see build/jam/BuildSetup
static const size_t kTarRegionSize = 16 * 1024 * 1024; // 16 MB static const size_t kTarRegionSize = 16 * 1024 * 1024; // 16 MB
namespace TarFS { namespace TarFS {
struct RegionDelete { struct RegionDelete {
inline void operator()(void *memory) inline void operator()(void* memory)
{ {
if (memory != NULL) if (memory != NULL)
platform_free_region(memory, kTarRegionSize); platform_free_region(memory, kTarRegionSize);
@@ -47,24 +48,33 @@ struct RegionDelete {
}; };
struct RegionDeleter : BPrivate::AutoDeleter<void, RegionDelete> { struct RegionDeleter : BPrivate::AutoDeleter<void, RegionDelete> {
RegionDeleter() : BPrivate::AutoDeleter<void, RegionDelete>() {} RegionDeleter()
RegionDeleter(void *memory) : BPrivate::AutoDeleter<void, RegionDelete>(memory) {} :
BPrivate::AutoDeleter<void, RegionDelete>()
{
}
RegionDeleter(void* memory)
:
BPrivate::AutoDeleter<void, RegionDelete>(memory)
{
}
}; };
class Directory; class Directory;
class Entry : public DoublyLinkedListLinkImpl<Entry> { class Entry : public DoublyLinkedListLinkImpl<Entry> {
public: public:
Entry(const char *name); Entry(const char* name);
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;
int32 fID; int32 fID;
}; };
@@ -73,52 +83,58 @@ typedef EntryList::Iterator EntryIterator;
class File : public ::Node, public Entry { class File : public ::Node, public Entry {
public: public:
File(tar_header *header, const char *name); File(tar_header* header, const char* name);
virtual ~File(); virtual ~File();
virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize); virtual ssize_t ReadAt(void* cookie, off_t pos, void* buffer,
virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize); size_t bufferSize);
virtual ssize_t WriteAt(void* cookie, off_t pos,
const void* buffer, size_t bufferSize);
virtual status_t GetName(char *nameBuffer, size_t bufferSize) const; virtual status_t GetName(char* nameBuffer,
size_t bufferSize) const;
virtual int32 Type() const; virtual int32 Type() const;
virtual off_t Size() const; virtual off_t Size() const;
virtual ino_t Inode() const; virtual ino_t Inode() const;
virtual ::Node *ToNode() { return this; } virtual ::Node* ToNode() { return this; }
private: private:
tar_header *fHeader; tar_header* fHeader;
off_t fSize; off_t fSize;
}; };
class Directory : public ::Directory, public Entry { class Directory : public ::Directory, public Entry {
public: public:
Directory(const char *name); Directory(const char* name);
virtual ~Directory(); virtual ~Directory();
virtual status_t Open(void **_cookie, int mode); virtual status_t Open(void** _cookie, int mode);
virtual status_t Close(void *cookie); virtual status_t Close(void* cookie);
virtual status_t GetName(char *nameBuffer, size_t bufferSize) const; virtual status_t GetName(char* nameBuffer,
size_t bufferSize) const;
virtual TarFS::Entry *LookupEntry(const char *name); virtual TarFS::Entry* LookupEntry(const char* name);
virtual ::Node *Lookup(const char *name, bool traverseLinks); virtual ::Node* Lookup(const char* name, bool traverseLinks);
virtual status_t GetNextEntry(void *cookie, char *nameBuffer, size_t bufferSize); virtual status_t GetNextEntry(void* cookie, char* nameBuffer,
virtual status_t GetNextNode(void *cookie, Node **_node); size_t bufferSize);
virtual status_t Rewind(void *cookie); virtual status_t GetNextNode(void* cookie, Node** _node);
virtual bool IsEmpty(); virtual status_t Rewind(void* cookie);
virtual bool IsEmpty();
virtual ino_t Inode() const; virtual ino_t Inode() const;
virtual ::Node *ToNode() { return this; }; virtual ::Node* ToNode() { return this; };
virtual TarFS::Directory *ToTarDirectory() { return this; } virtual TarFS::Directory* ToTarDirectory() { return this; }
status_t AddDirectory(char *dirName, TarFS::Directory **_dir = NULL); status_t AddDirectory(char* dirName,
status_t AddFile(tar_header *header); TarFS::Directory** _dir = NULL);
status_t AddFile(tar_header* header);
private: private:
typedef ::Directory _inherited; typedef ::Directory _inherited;
@@ -128,44 +144,46 @@ class Directory : public ::Directory, public Entry {
class Symlink : public ::Node, public Entry { class Symlink : public ::Node, public Entry {
public: public:
Symlink(tar_header *header, const char *name); Symlink(tar_header* header, const char* name);
virtual ~Symlink(); virtual ~Symlink();
virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, virtual ssize_t ReadAt(void* cookie, off_t pos, void* buffer,
size_t bufferSize); size_t bufferSize);
virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, virtual ssize_t WriteAt(void* cookie, off_t pos,
size_t bufferSize); const void* buffer, size_t bufferSize);
virtual status_t GetName(char *nameBuffer, size_t bufferSize) const; virtual status_t GetName(char* nameBuffer,
size_t bufferSize) const;
virtual int32 Type() const; virtual int32 Type() const;
virtual off_t Size() const; virtual off_t Size() const;
virtual ino_t Inode() const; virtual ino_t Inode() const;
const char* LinkPath() const { return fHeader->linkname; } const char* LinkPath() const { return fHeader->linkname; }
virtual ::Node *ToNode() { return this; } virtual ::Node* ToNode() { return this; }
private: private:
tar_header *fHeader; tar_header* fHeader;
size_t fSize; size_t fSize;
}; };
class Volume : public TarFS::Directory { class Volume : public TarFS::Directory {
public: public:
Volume(); Volume();
~Volume(); ~Volume();
status_t Init(boot::Partition *partition); status_t Init(boot::Partition* partition);
TarFS::Directory *Root() { return this; } TarFS::Directory* Root() { return this; }
private: private:
status_t _Inflate(boot::Partition *partition, void* cookie, status_t _Inflate(boot::Partition* partition,
off_t offset, RegionDeleter& regionDeleter, void* cookie, off_t offset,
size_t* inflatedBytes); RegionDeleter& regionDeleter,
size_t* inflatedBytes);
}; };
} // namespace TarFS } // namespace TarFS
@@ -178,10 +196,10 @@ static int32 sNextID = 1;
bool bool
skip_gzip_header(z_stream *stream) skip_gzip_header(z_stream* stream)
{ {
uint8 *buffer = (uint8 *)stream->next_in; uint8* buffer = (uint8*)stream->next_in;
// check magic and skip method // check magic and skip method
if (buffer[0] != 0x1f || buffer[1] != 0x8b) if (buffer[0] != 0x1f || buffer[1] != 0x8b)
return false; return false;
@@ -224,7 +242,7 @@ skip_gzip_header(z_stream *stream)
// #pragma mark - // #pragma mark -
TarFS::Entry::Entry(const char *name) TarFS::Entry::Entry(const char* name)
: :
fName(name), fName(name),
fID(sNextID++) fID(sNextID++)
@@ -235,7 +253,7 @@ TarFS::Entry::Entry(const char *name)
// #pragma mark - // #pragma mark -
TarFS::File::File(tar_header *header, const char *name) TarFS::File::File(tar_header* header, const char* name)
: TarFS::Entry(name), : TarFS::Entry(name),
fHeader(header) fHeader(header)
{ {
@@ -249,9 +267,10 @@ TarFS::File::~File()
ssize_t ssize_t
TarFS::File::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize) TarFS::File::ReadAt(void* cookie, off_t pos, void* buffer, size_t bufferSize)
{ {
TRACE(("tarfs: read at %Ld, %lu bytes, fSize = %Ld\n", pos, bufferSize, fSize)); 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;
@@ -270,16 +289,18 @@ TarFS::File::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize)
ssize_t ssize_t
TarFS::File::WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize) TarFS::File::WriteAt(void* cookie, off_t pos, const void* buffer,
size_t bufferSize)
{ {
return B_NOT_ALLOWED; return B_NOT_ALLOWED;
} }
status_t status_t
TarFS::File::GetName(char *nameBuffer, size_t bufferSize) const TarFS::File::GetName(char* nameBuffer, size_t bufferSize) const
{ {
return strlcpy(nameBuffer, Name(), bufferSize) >= bufferSize ? B_BUFFER_OVERFLOW : B_OK; return strlcpy(nameBuffer, Name(), bufferSize) >= bufferSize
? B_BUFFER_OVERFLOW : B_OK;
} }
@@ -306,7 +327,7 @@ TarFS::File::Inode() const
// #pragma mark - // #pragma mark -
TarFS::Directory::Directory(const char *name) TarFS::Directory::Directory(const char* name)
: TarFS::Entry(name) : TarFS::Entry(name)
{ {
} }
@@ -314,19 +335,20 @@ TarFS::Directory::Directory(const char *name)
TarFS::Directory::~Directory() TarFS::Directory::~Directory()
{ {
while (TarFS::Entry *entry = fEntries.Head()) { while (TarFS::Entry* entry = fEntries.Head()) {
fEntries.Remove(entry); fEntries.Remove(entry);
delete entry; delete entry;
} }
} }
status_t status_t
TarFS::Directory::Open(void **_cookie, int mode) TarFS::Directory::Open(void** _cookie, int mode)
{ {
_inherited::Open(_cookie, mode); _inherited::Open(_cookie, mode);
EntryIterator *iterator = new(nothrow) EntryIterator(fEntries.GetIterator()); EntryIterator* iterator
= new(std::nothrow) EntryIterator(fEntries.GetIterator());
if (iterator == NULL) if (iterator == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -336,30 +358,31 @@ TarFS::Directory::Open(void **_cookie, int mode)
} }
status_t status_t
TarFS::Directory::Close(void *cookie) TarFS::Directory::Close(void* cookie)
{ {
_inherited::Close(cookie); _inherited::Close(cookie);
delete (EntryIterator *)cookie; delete (EntryIterator*)cookie;
return B_OK; return B_OK;
} }
status_t status_t
TarFS::Directory::GetName(char *nameBuffer, size_t bufferSize) const TarFS::Directory::GetName(char* nameBuffer, size_t bufferSize) const
{ {
return strlcpy(nameBuffer, Name(), bufferSize) >= bufferSize ? B_BUFFER_OVERFLOW : B_OK; return strlcpy(nameBuffer, Name(), bufferSize) >= bufferSize
? B_BUFFER_OVERFLOW : B_OK;
} }
TarFS::Entry * TarFS::Entry*
TarFS::Directory::LookupEntry(const char *name) TarFS::Directory::LookupEntry(const char* name)
{ {
EntryIterator iterator(fEntries.GetIterator()); EntryIterator iterator(fEntries.GetIterator());
while (iterator.HasNext()) { while (iterator.HasNext()) {
TarFS::Entry *entry = iterator.Next(); TarFS::Entry* entry = iterator.Next();
if (strcmp(name, entry->Name()) == 0) if (strcmp(name, entry->Name()) == 0)
return entry; return entry;
} }
@@ -368,10 +391,10 @@ TarFS::Directory::LookupEntry(const char *name)
} }
::Node * ::Node*
TarFS::Directory::Lookup(const char *name, bool traverseLinks) TarFS::Directory::Lookup(const char* name, bool traverseLinks)
{ {
TarFS::Entry *entry = LookupEntry(name); TarFS::Entry* entry = LookupEntry(name);
if (!entry) if (!entry)
return NULL; return NULL;
@@ -395,11 +418,11 @@ TarFS::Directory::Lookup(const char *name, bool traverseLinks)
} }
status_t status_t
TarFS::Directory::GetNextEntry(void *_cookie, char *name, size_t size) TarFS::Directory::GetNextEntry(void* _cookie, char* name, size_t size)
{ {
EntryIterator *iterator = (EntryIterator *)_cookie; EntryIterator* iterator = (EntryIterator*)_cookie;
TarFS::Entry *entry = iterator->Next(); TarFS::Entry* entry = iterator->Next();
if (entry != NULL) { if (entry != NULL) {
strlcpy(name, entry->Name(), size); strlcpy(name, entry->Name(), size);
@@ -410,11 +433,11 @@ TarFS::Directory::GetNextEntry(void *_cookie, char *name, size_t size)
} }
status_t status_t
TarFS::Directory::GetNextNode(void *_cookie, Node **_node) TarFS::Directory::GetNextNode(void* _cookie, Node** _node)
{ {
EntryIterator *iterator = (EntryIterator *)_cookie; EntryIterator* iterator = (EntryIterator*)_cookie;
TarFS::Entry *entry = iterator->Next(); TarFS::Entry* entry = iterator->Next();
if (entry != NULL) { if (entry != NULL) {
*_node = entry->ToNode(); *_node = entry->ToNode();
@@ -424,19 +447,19 @@ TarFS::Directory::GetNextNode(void *_cookie, Node **_node)
} }
status_t status_t
TarFS::Directory::Rewind(void *_cookie) TarFS::Directory::Rewind(void* _cookie)
{ {
EntryIterator *iterator = (EntryIterator *)_cookie; EntryIterator* iterator = (EntryIterator*)_cookie;
*iterator = fEntries.GetIterator(); *iterator = fEntries.GetIterator();
return B_OK; return B_OK;
} }
status_t status_t
TarFS::Directory::AddDirectory(char *dirName, TarFS::Directory **_dir) TarFS::Directory::AddDirectory(char* dirName, TarFS::Directory** _dir)
{ {
char *subDir = strchr(dirName, '/'); char* subDir = strchr(dirName, '/');
if (subDir) { if (subDir) {
// skip slashes // skip slashes
while (*subDir == '/') { while (*subDir == '/') {
@@ -451,8 +474,8 @@ TarFS::Directory::AddDirectory(char *dirName, TarFS::Directory **_dir)
} }
// check, whether the directory does already exist // check, whether the directory does already exist
Entry *entry = LookupEntry(dirName); Entry* entry = LookupEntry(dirName);
TarFS::Directory *dir = (entry ? entry->ToTarDirectory() : NULL); TarFS::Directory* dir = (entry ? entry->ToTarDirectory() : NULL);
if (entry) { if (entry) {
if (!dir) if (!dir)
return B_ERROR; return B_ERROR;
@@ -480,10 +503,10 @@ TarFS::Directory::AddDirectory(char *dirName, TarFS::Directory **_dir)
status_t status_t
TarFS::Directory::AddFile(tar_header *header) TarFS::Directory::AddFile(tar_header* header)
{ {
char *leaf = strrchr(header->name, '/'); char* leaf = strrchr(header->name, '/');
char *dirName = NULL; char* dirName = NULL;
if (leaf) { if (leaf) {
dirName = header->name; dirName = header->name;
*leaf = '\0'; *leaf = '\0';
@@ -492,7 +515,7 @@ TarFS::Directory::AddFile(tar_header *header)
leaf = header->name; leaf = header->name;
// create the parent directory // create the parent directory
TarFS::Directory *dir = this; TarFS::Directory* dir = this;
if (dirName) { if (dirName) {
status_t error = AddDirectory(dirName, &dir); status_t error = AddDirectory(dirName, &dir);
if (error != B_OK) if (error != B_OK)
@@ -500,7 +523,7 @@ TarFS::Directory::AddFile(tar_header *header)
} }
// create the entry // create the entry
TarFS::Entry *entry; TarFS::Entry* entry;
if (header->type == TAR_FILE || header->type == TAR_FILE2) if (header->type == TAR_FILE || header->type == TAR_FILE2)
entry = new(nothrow) TarFS::File(header, leaf); entry = new(nothrow) TarFS::File(header, leaf);
else if (header->type == TAR_SYMLINK) else if (header->type == TAR_SYMLINK)
@@ -517,7 +540,7 @@ TarFS::Directory::AddFile(tar_header *header)
} }
bool bool
TarFS::Directory::IsEmpty() TarFS::Directory::IsEmpty()
{ {
return fEntries.IsEmpty(); return fEntries.IsEmpty();
@@ -534,7 +557,7 @@ TarFS::Directory::Inode() const
// #pragma mark - // #pragma mark -
TarFS::Symlink::Symlink(tar_header *header, const char *name) TarFS::Symlink::Symlink(tar_header* header, const char* name)
: TarFS::Entry(name), : TarFS::Entry(name),
fHeader(header) fHeader(header)
{ {
@@ -550,14 +573,14 @@ TarFS::Symlink::~Symlink()
ssize_t ssize_t
TarFS::Symlink::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize) TarFS::Symlink::ReadAt(void* cookie, off_t pos, void* buffer, size_t bufferSize)
{ {
return B_NOT_ALLOWED; return B_NOT_ALLOWED;
} }
ssize_t ssize_t
TarFS::Symlink::WriteAt(void *cookie, off_t pos, const void *buffer, TarFS::Symlink::WriteAt(void* cookie, off_t pos, const void* buffer,
size_t bufferSize) size_t bufferSize)
{ {
return B_NOT_ALLOWED; return B_NOT_ALLOWED;
@@ -565,7 +588,7 @@ TarFS::Symlink::WriteAt(void *cookie, off_t pos, const void *buffer,
status_t status_t
TarFS::Symlink::GetName(char *nameBuffer, size_t bufferSize) const TarFS::Symlink::GetName(char* nameBuffer, size_t bufferSize) const
{ {
return strlcpy(nameBuffer, Name(), bufferSize) >= bufferSize return strlcpy(nameBuffer, Name(), bufferSize) >= bufferSize
? B_BUFFER_OVERFLOW : B_OK; ? B_BUFFER_OVERFLOW : B_OK;
@@ -608,9 +631,9 @@ TarFS::Volume::~Volume()
status_t status_t
TarFS::Volume::Init(boot::Partition *partition) TarFS::Volume::Init(boot::Partition* partition)
{ {
void *cookie; void* cookie;
status_t error = partition->Open(&cookie, O_RDONLY); status_t error = partition->Open(&cookie, O_RDONLY);
if (error != B_OK) if (error != B_OK)
return error; return error;
@@ -619,7 +642,7 @@ TarFS::Volume::Init(boot::Partition *partition)
boot::Partition *partition; boot::Partition *partition;
void *cookie; void *cookie;
PartitionCloser(boot::Partition *partition, void *cookie) PartitionCloser(boot::Partition* partition, void* cookie)
: partition(partition), : partition(partition),
cookie(cookie) cookie(cookie)
{ {
@@ -645,13 +668,13 @@ TarFS::Volume::Init(boot::Partition *partition)
return status; return status;
// parse the tar file // parse the tar file
char *block = (char*)regionDeleter.Get(); char* block = (char*)regionDeleter.Get();
int blockCount = inflatedBytes / BLOCK_SIZE; int blockCount = inflatedBytes / BLOCK_SIZE;
int blockIndex = 0; int blockIndex = 0;
while (blockIndex < blockCount) { while (blockIndex < blockCount) {
// check header // check header
tar_header *header = (tar_header*)(block + blockIndex * BLOCK_SIZE); tar_header* header = (tar_header*)(block + blockIndex * BLOCK_SIZE);
//dump_header(*header); //dump_header(*header);
if (header->magic[0] == '\0') if (header->magic[0] == '\0')
@@ -669,7 +692,8 @@ TarFS::Volume::Init(boot::Partition *partition)
TRACE(("tarfs: \"%s\", %Ld bytes\n", header->name, size)); 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:
case TAR_FILE2: case TAR_FILE2:
@@ -685,7 +709,8 @@ TarFS::Volume::Init(boot::Partition *partition)
// this is a long file name // this is a long file name
// TODO: read long name // TODO: read long name
default: default:
dprintf("tarfs: unsupported file type: %d ('%c')\n", header->type, header->type); dprintf("tarfs: unsupported file type: %d ('%c')\n",
header->type, header->type);
// unsupported type // unsupported type
status = B_ERROR; status = B_ERROR;
break; break;
@@ -707,7 +732,7 @@ TarFS::Volume::Init(boot::Partition *partition)
status_t status_t
TarFS::Volume::_Inflate(boot::Partition *partition, void* cookie, off_t offset, TarFS::Volume::_Inflate(boot::Partition* partition, void* cookie, off_t offset,
RegionDeleter& regionDeleter, size_t* inflatedBytes) RegionDeleter& regionDeleter, size_t* inflatedBytes)
{ {
char in[2048]; char in[2048];
@@ -742,7 +767,7 @@ TarFS::Volume::_Inflate(boot::Partition *partition, void* cookie, off_t offset,
} }
zStream.avail_in = bytesRead; zStream.avail_in = bytesRead;
zStream.next_in = (Bytef *)in; zStream.next_in = (Bytef*)in;
if (!headerRead) { if (!headerRead) {
// check and skip gzip header // check and skip gzip header
@@ -752,7 +777,7 @@ TarFS::Volume::_Inflate(boot::Partition *partition, void* cookie, off_t offset,
if (!out) { if (!out) {
// allocate memory for the uncompressed data // allocate memory for the uncompressed data
if (platform_allocate_region((void **)&out, kTarRegionSize, if (platform_allocate_region((void**)&out, kTarRegionSize,
B_READ_AREA | B_WRITE_AREA, false) != B_OK) { B_READ_AREA | B_WRITE_AREA, false) != B_OK) {
TRACE(("tarfs: allocating region failed!\n")); TRACE(("tarfs: allocating region failed!\n"));
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -761,7 +786,7 @@ TarFS::Volume::_Inflate(boot::Partition *partition, void* cookie, off_t offset,
} }
zStream.avail_out = kTarRegionSize; zStream.avail_out = kTarRegionSize;
zStream.next_out = (Bytef *)out; zStream.next_out = (Bytef*)out;
status = inflateInit2(&zStream, -15); status = inflateInit2(&zStream, -15);
if (status != Z_OK) if (status != Z_OK)
@@ -793,9 +818,9 @@ TarFS::Volume::_Inflate(boot::Partition *partition, void* cookie, off_t offset,
static status_t static status_t
tarfs_get_file_system(boot::Partition *partition, ::Directory **_root) tarfs_get_file_system(boot::Partition* partition, ::Directory** _root)
{ {
TarFS::Volume *volume = new(nothrow) TarFS::Volume; TarFS::Volume* volume = new(nothrow) TarFS::Volume;
if (volume == NULL) if (volume == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;