* Directory stores its parent directory (if any), now.

* Adjusted used files systems accordingly.
* BFS::Stream::GetName() was broken. It accessed the small data region
  which wasn't loaded, since BFS::Stream derived from bfs_inode, which
  is a variably-sized structure with the small data region at the end.
  Changed that to a ref-counted, shared member instead.
* Implemented RootFileSystem::GetName().
* Added Directory::GetPath() to get a full path of the directory or an
  entry.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27664 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2008-09-21 12:55:41 +00:00
parent b33ba0e92e
commit 6aa2c9ecf1
13 changed files with 275 additions and 111 deletions
+10 -1
View File
@@ -45,7 +45,13 @@ typedef NodeList::Iterator NodeIterator;
class Directory : public Node { class Directory : public Node {
public: public:
Directory(); Directory(Directory* parent);
~Directory();
Directory* Parent() const;
void SetParent(Directory* parent);
status_t GetPath(const char* entry, char* buffer, size_t bufferSize);
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, size_t bufferSize);
virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize); virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize);
@@ -58,6 +64,9 @@ class Directory : public Node {
virtual status_t GetNextNode(void *cookie, Node **_node) = 0; virtual status_t GetNextNode(void *cookie, Node **_node) = 0;
virtual status_t Rewind(void *cookie) = 0; virtual status_t Rewind(void *cookie) = 0;
virtual bool IsEmpty() = 0; virtual bool IsEmpty() = 0;
private:
Directory* fParent;
}; };
/** The console based nodes don't need cookies for I/O, they /** The console based nodes don't need cookies for I/O, they
+21 -9
View File
@@ -14,6 +14,8 @@
RootFileSystem::RootFileSystem() RootFileSystem::RootFileSystem()
:
Directory(NULL)
{ {
} }
@@ -29,7 +31,16 @@ RootFileSystem::~RootFileSystem()
} }
status_t status_t
RootFileSystem::GetName(char *nameBuffer, size_t bufferSize) const
{
if (strlcpy(nameBuffer, "/", bufferSize) >= bufferSize)
return B_BUFFER_OVERFLOW;
return B_OK;
}
status_t
RootFileSystem::Open(void **_cookie, int mode) RootFileSystem::Open(void **_cookie, int mode)
{ {
EntryIterator *iterator = new (std::nothrow) EntryIterator(&fList); EntryIterator *iterator = new (std::nothrow) EntryIterator(&fList);
@@ -42,7 +53,7 @@ RootFileSystem::Open(void **_cookie, int mode)
} }
status_t status_t
RootFileSystem::Close(void *cookie) RootFileSystem::Close(void *cookie)
{ {
delete (EntryIterator *)cookie; delete (EntryIterator *)cookie;
@@ -84,7 +95,7 @@ RootFileSystem::Lookup(const char *name, bool /*traverseLinks*/)
} }
status_t status_t
RootFileSystem::GetNextEntry(void *_cookie, char *name, size_t size) RootFileSystem::GetNextEntry(void *_cookie, char *name, size_t size)
{ {
EntryIterator *iterator = (EntryIterator *)_cookie; EntryIterator *iterator = (EntryIterator *)_cookie;
@@ -98,7 +109,7 @@ RootFileSystem::GetNextEntry(void *_cookie, char *name, size_t size)
} }
status_t status_t
RootFileSystem::GetNextNode(void *_cookie, Node **_node) RootFileSystem::GetNextNode(void *_cookie, Node **_node)
{ {
EntryIterator *iterator = (EntryIterator *)_cookie; EntryIterator *iterator = (EntryIterator *)_cookie;
@@ -113,24 +124,24 @@ RootFileSystem::GetNextNode(void *_cookie, Node **_node)
} }
status_t status_t
RootFileSystem::Rewind(void *_cookie) RootFileSystem::Rewind(void *_cookie)
{ {
EntryIterator *iterator = (EntryIterator *)_cookie; EntryIterator *iterator = (EntryIterator *)_cookie;
iterator->Rewind(); iterator->Rewind();
return B_OK; return B_OK;
} }
bool bool
RootFileSystem::IsEmpty() RootFileSystem::IsEmpty()
{ {
return fList.IsEmpty(); return fList.IsEmpty();
} }
status_t status_t
RootFileSystem::AddVolume(Directory *volume, Partition *partition) RootFileSystem::AddVolume(Directory *volume, Partition *partition)
{ {
struct entry *entry = new (std::nothrow) RootFileSystem::entry(); struct entry *entry = new (std::nothrow) RootFileSystem::entry();
@@ -138,6 +149,7 @@ RootFileSystem::AddVolume(Directory *volume, Partition *partition)
return B_NO_MEMORY; return B_NO_MEMORY;
volume->Acquire(); volume->Acquire();
volume->SetParent(this);
entry->name = NULL; entry->name = NULL;
entry->root = volume; entry->root = volume;
entry->partition = partition; entry->partition = partition;
@@ -165,7 +177,7 @@ RootFileSystem::AddLink(const char *name, Directory *target)
} }
status_t status_t
RootFileSystem::GetPartitionFor(Directory *volume, Partition **_partition) RootFileSystem::GetPartitionFor(Directory *volume, Partition **_partition)
{ {
EntryIterator iterator = fList.GetIterator(); EntryIterator iterator = fList.GetIterator();
+2
View File
@@ -17,6 +17,8 @@ class RootFileSystem : public Directory {
RootFileSystem(); RootFileSystem();
virtual ~RootFileSystem(); virtual ~RootFileSystem();
virtual status_t GetName(char *nameBuffer, size_t bufferSize) const;
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);
@@ -18,8 +18,9 @@
namespace FFS { namespace FFS {
Directory::Directory(Volume &volume, int32 block) Directory::Directory(Volume &volume, ::Directory* parent, int32 block)
: :
::Directory(parent),
fVolume(volume) fVolume(volume)
{ {
void *data = malloc(volume.BlockSize()); void *data = malloc(volume.BlockSize());
@@ -31,8 +32,9 @@ Directory::Directory(Volume &volume, int32 block)
} }
Directory::Directory(Volume &volume, RootBlock &root) Directory::Directory(Volume &volume, ::Directory* parent, RootBlock &root)
: :
::Directory(parent),
fVolume(volume) fVolume(volume)
{ {
fNode.SetTo(root.BlockData(), root.BlockSize()); fNode.SetTo(root.BlockData(), root.BlockSize());
@@ -45,14 +47,14 @@ Directory::~Directory()
} }
status_t status_t
Directory::InitCheck() Directory::InitCheck()
{ {
return fNode.ValidateCheckSum(); return fNode.ValidateCheckSum();
} }
status_t status_t
Directory::Open(void **_cookie, int mode) Directory::Open(void **_cookie, int mode)
{ {
_inherited::Open(_cookie, mode); _inherited::Open(_cookie, mode);
@@ -71,7 +73,7 @@ Directory::Open(void **_cookie, int mode)
} }
status_t status_t
Directory::Close(void *cookie) Directory::Close(void *cookie)
{ {
_inherited::Close(cookie); _inherited::Close(cookie);
@@ -104,7 +106,7 @@ Directory::Lookup(const char *name, bool traverseLinks)
if (node->IsFile()) if (node->IsFile())
return new(nothrow) File(fVolume, block); return new(nothrow) File(fVolume, block);
if (node->IsDirectory()) if (node->IsDirectory())
return new(nothrow) Directory(fVolume, block); return new(nothrow) Directory(fVolume, this, block);
return NULL; return NULL;
} }
@@ -113,7 +115,7 @@ Directory::Lookup(const char *name, bool traverseLinks)
} }
status_t status_t
Directory::GetNextEntry(void *cookie, char *name, size_t size) Directory::GetNextEntry(void *cookie, char *name, size_t size)
{ {
HashIterator *iterator = (HashIterator *)cookie; HashIterator *iterator = (HashIterator *)cookie;
@@ -127,7 +129,7 @@ Directory::GetNextEntry(void *cookie, char *name, size_t size)
} }
status_t status_t
Directory::GetNextNode(void *cookie, Node **_node) Directory::GetNextNode(void *cookie, Node **_node)
{ {
return B_ERROR; return B_ERROR;
@@ -17,9 +17,8 @@ class Volume;
class Directory : public ::Directory { class Directory : public ::Directory {
public: public:
Directory(); Directory(Volume &volume, ::Directory* parent, RootBlock &root);
Directory(Volume &volume, RootBlock &root); Directory(Volume &volume, ::Directory* parent, int32 block);
Directory(Volume &volume, int32 block);
virtual ~Directory(); virtual ~Directory();
status_t InitCheck(); status_t InitCheck();
@@ -75,7 +75,7 @@ Volume::Volume(boot::Partition *partition)
buffer = newBuffer; buffer = newBuffer;
fRootNode.SetTo(buffer, blockSize); fRootNode.SetTo(buffer, blockSize);
fRoot = new(nothrow) Directory(*this, fRootNode); fRoot = new(nothrow) Directory(*this, NULL, fRootNode);
// fRoot will free the buffer for us upon destruction // fRoot will free the buffer for us upon destruction
} }
@@ -87,7 +87,7 @@ Volume::~Volume()
} }
status_t status_t
Volume::InitCheck() Volume::InitCheck()
{ {
if (fRoot != NULL) if (fRoot != NULL)
@@ -22,24 +22,27 @@ extern Node *get_node_from(int fd);
namespace BFS { namespace BFS {
Directory::Directory(Volume &volume, block_run run) Directory::Directory(Volume &volume, ::Directory* parent, block_run run)
: :
::Directory(parent),
fStream(volume, run), fStream(volume, run),
fTree(&fStream) fTree(&fStream)
{ {
} }
Directory::Directory(Volume &volume, off_t id) Directory::Directory(Volume &volume, ::Directory* parent, off_t id)
: :
::Directory(parent),
fStream(volume, id), fStream(volume, id),
fTree(&fStream) fTree(&fStream)
{ {
} }
Directory::Directory(const Stream &stream) Directory::Directory(::Directory* parent, const Stream &stream)
: :
::Directory(parent),
fStream(stream), fStream(stream),
fTree(&fStream) fTree(&fStream)
{ {
@@ -51,14 +54,14 @@ Directory::~Directory()
} }
status_t status_t
Directory::InitCheck() Directory::InitCheck()
{ {
return fStream.InitCheck(); return fStream.InitCheck();
} }
status_t status_t
Directory::Open(void **_cookie, int mode) Directory::Open(void **_cookie, int mode)
{ {
_inherited::Open(_cookie, mode); _inherited::Open(_cookie, mode);
@@ -71,7 +74,7 @@ Directory::Open(void **_cookie, int mode)
} }
status_t status_t
Directory::Close(void *cookie) Directory::Close(void *cookie)
{ {
_inherited::Close(cookie); _inherited::Close(cookie);
@@ -88,7 +91,7 @@ Directory::Lookup(const char *name, bool traverseLinks)
if (fTree.Find((uint8 *)name, strlen(name), &id) < B_OK) if (fTree.Find((uint8 *)name, strlen(name), &id) < B_OK)
return NULL; return NULL;
Node *node = Stream::NodeFactory(fStream.GetVolume(), id); Node *node = Stream::NodeFactory(fStream.GetVolume(), this, id);
if (!node) if (!node)
return NULL; return NULL;
@@ -117,7 +120,7 @@ Directory::Lookup(const char *name, bool traverseLinks)
} }
status_t status_t
Directory::GetNextEntry(void *cookie, char *name, size_t size) Directory::GetNextEntry(void *cookie, char *name, size_t size)
{ {
TreeIterator *iterator = (TreeIterator *)cookie; TreeIterator *iterator = (TreeIterator *)cookie;
@@ -128,7 +131,7 @@ Directory::GetNextEntry(void *cookie, char *name, size_t size)
} }
status_t status_t
Directory::GetNextNode(void *cookie, Node **_node) Directory::GetNextNode(void *cookie, Node **_node)
{ {
TreeIterator *iterator = (TreeIterator *)cookie; TreeIterator *iterator = (TreeIterator *)cookie;
@@ -140,7 +143,7 @@ Directory::GetNextNode(void *cookie, Node **_node)
if (status != B_OK) if (status != B_OK)
return status; return status;
*_node = Stream::NodeFactory(fStream.GetVolume(), id); *_node = Stream::NodeFactory(fStream.GetVolume(), this, id);
if (*_node == NULL) if (*_node == NULL)
return B_ERROR; return B_ERROR;
@@ -148,7 +151,7 @@ Directory::GetNextNode(void *cookie, Node **_node)
} }
status_t status_t
Directory::Rewind(void *cookie) Directory::Rewind(void *cookie)
{ {
TreeIterator *iterator = (TreeIterator *)cookie; TreeIterator *iterator = (TreeIterator *)cookie;
@@ -157,7 +160,7 @@ Directory::Rewind(void *cookie)
} }
bool bool
Directory::IsEmpty() Directory::IsEmpty()
{ {
TreeIterator iterator(&fTree); TreeIterator iterator(&fTree);
@@ -184,7 +187,7 @@ Directory::IsEmpty()
status_t status_t
Directory::GetName(char *name, size_t size) const Directory::GetName(char *name, size_t size) const
{ {
if (fStream.inode_num == fStream.GetVolume().Root()) { if (fStream.InodeNum() == fStream.GetVolume().Root()) {
strlcpy(name, fStream.GetVolume().SuperBlock().name, size); strlcpy(name, fStream.GetVolume().SuperBlock().name, size);
return B_OK; return B_OK;
} }
@@ -17,9 +17,9 @@ namespace BFS {
class Directory : public ::Directory { class Directory : public ::Directory {
public: public:
Directory(Volume &volume, block_run run); Directory(Volume &volume, ::Directory* parent, block_run run);
Directory(Volume &volume, off_t id); Directory(Volume &volume, ::Directory* parent, off_t id);
Directory(const Stream &stream); Directory(::Directory* parent, const Stream &stream);
virtual ~Directory(); virtual ~Directory();
status_t InitCheck(); status_t InitCheck();
@@ -106,31 +106,47 @@ CachedBlock::SetTo(block_run run)
Stream::Stream(Volume &volume, block_run run) Stream::Stream(Volume &volume, block_run run)
: :
fVolume(volume) fVolume(volume),
fInode(NULL)
{ {
if (read_pos(volume.Device(), volume.ToOffset(run), this, sizeof(bfs_inode)) != sizeof(bfs_inode)) _LoadInode(volume.ToOffset(run));
return;
} }
Stream::Stream(Volume &volume, off_t id) Stream::Stream(Volume &volume, off_t id)
: :
fVolume(volume) fVolume(volume),
fInode(NULL)
{ {
if (read_pos(volume.Device(), volume.ToOffset(id), this, sizeof(bfs_inode)) != sizeof(bfs_inode)) _LoadInode(volume.ToOffset(id));
return; }
Stream::Stream(const Stream& other)
:
fVolume(other.fVolume),
fInode(NULL)
{
_UseInode(other.fInode);
} }
Stream::~Stream() Stream::~Stream()
{ {
if (fInode != NULL) {
if (--(((int32*)fInode)[-1]) == 0)
free((int32*)fInode - 1);
}
} }
status_t status_t
Stream::InitCheck() Stream::InitCheck()
{ {
return bfs_inode::InitCheck(&fVolume); if (fInode == NULL)
return B_NO_MEMORY;
return fInode->InitCheck(&fVolume);
} }
@@ -141,12 +157,12 @@ Stream::GetNextSmallData(const small_data **_smallData) const
// begin from the start? // begin from the start?
if (smallData == NULL) if (smallData == NULL)
smallData = small_data_start; smallData = fInode->small_data_start;
else else
smallData = smallData->Next(); smallData = smallData->Next();
// is already last item? // is already last item?
if (smallData->IsLast(this)) if (smallData->IsLast(fInode))
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
*_smallData = smallData; *_smallData = smallData;
@@ -155,7 +171,7 @@ Stream::GetNextSmallData(const small_data **_smallData) const
} }
status_t status_t
Stream::GetName(char *name, size_t size) const Stream::GetName(char *name, size_t size) const
{ {
const small_data *smallData = NULL; const small_data *smallData = NULL;
@@ -170,17 +186,17 @@ Stream::GetName(char *name, size_t size) const
} }
status_t status_t
Stream::ReadLink(char *buffer, size_t bufferSize) Stream::ReadLink(char *buffer, size_t bufferSize)
{ {
// link in the stream // link in the stream
if (Flags() & INODE_LONG_SYMLINK) if (fInode->Flags() & INODE_LONG_SYMLINK)
return ReadAt(0, (uint8 *)buffer, &bufferSize); return ReadAt(0, (uint8 *)buffer, &bufferSize);
// link in the inode // link in the inode
strlcpy(buffer, short_symlink, bufferSize); strlcpy(buffer, fInode->short_symlink, bufferSize);
return B_OK; return B_OK;
} }
@@ -190,21 +206,25 @@ Stream::FindBlockRun(off_t pos, block_run &run, off_t &offset)
{ {
// find matching block run // find matching block run
if (data.MaxDirectRange() > 0 && pos >= data.MaxDirectRange()) { if (fInode->data.MaxDirectRange() > 0
if (data.MaxDoubleIndirectRange() > 0 && pos >= data.MaxIndirectRange()) { && pos >= fInode->data.MaxDirectRange()) {
if (fInode->data.MaxDoubleIndirectRange() > 0
&& pos >= fInode->data.MaxIndirectRange()) {
// access to double indirect blocks // access to double indirect blocks
CachedBlock cached(fVolume); CachedBlock cached(fVolume);
off_t start = pos - data.MaxIndirectRange(); off_t start = pos - fInode->data.MaxIndirectRange();
int32 indirectSize = (1L << (INDIRECT_BLOCKS_SHIFT + cached.BlockShift())) int32 indirectSize
* (fVolume.BlockSize() / sizeof(block_run)); = (1L << (INDIRECT_BLOCKS_SHIFT + cached.BlockShift()))
* (fVolume.BlockSize() / sizeof(block_run));
int32 directSize = NUM_ARRAY_BLOCKS << cached.BlockShift(); int32 directSize = NUM_ARRAY_BLOCKS << cached.BlockShift();
int32 index = start / indirectSize; int32 index = start / indirectSize;
int32 runsPerBlock = cached.BlockSize() / sizeof(block_run); int32 runsPerBlock = cached.BlockSize() / sizeof(block_run);
block_run *indirect = (block_run *)cached.SetTo( block_run *indirect = (block_run*)cached.SetTo(
fVolume.ToBlock(data.double_indirect) + index / runsPerBlock); fVolume.ToBlock(fInode->data.double_indirect)
+ index / runsPerBlock);
if (indirect == NULL) if (indirect == NULL)
return B_ERROR; return B_ERROR;
@@ -213,24 +233,25 @@ Stream::FindBlockRun(off_t pos, block_run &run, off_t &offset)
int32 current = (start % indirectSize) / directSize; int32 current = (start % indirectSize) / directSize;
indirect = (block_run *)cached.SetTo( indirect = (block_run*)cached.SetTo(
fVolume.ToBlock(indirect[index % runsPerBlock]) + current / runsPerBlock); fVolume.ToBlock(indirect[index % runsPerBlock]) + current / runsPerBlock);
if (indirect == NULL) if (indirect == NULL)
return B_ERROR; return B_ERROR;
run = indirect[current % runsPerBlock]; run = indirect[current % runsPerBlock];
offset = data.MaxIndirectRange() + (index * indirectSize) + (current * directSize); offset = fInode->data.MaxIndirectRange() + (index * indirectSize)
+ (current * directSize);
//printf("\tfCurrent = %ld, fRunFileOffset = %Ld, fRunBlockEnd = %Ld, fRun = %ld,%d\n",fCurrent,fRunFileOffset,fRunBlockEnd,fRun.allocation_group,fRun.start); //printf("\tfCurrent = %ld, fRunFileOffset = %Ld, fRunBlockEnd = %Ld, fRun = %ld,%d\n",fCurrent,fRunFileOffset,fRunBlockEnd,fRun.allocation_group,fRun.start);
} else { } else {
// access to indirect blocks // access to indirect blocks
int32 runsPerBlock = fVolume.BlockSize() / sizeof(block_run); int32 runsPerBlock = fVolume.BlockSize() / sizeof(block_run);
off_t runBlockEnd = data.MaxDirectRange(); off_t runBlockEnd = fInode->data.MaxDirectRange();
CachedBlock cached(fVolume); CachedBlock cached(fVolume);
off_t block = fVolume.ToBlock(data.indirect); off_t block = fVolume.ToBlock(fInode->data.indirect);
for (int32 i = 0;i < data.indirect.Length();i++) { for (int32 i = 0;i < fInode->data.indirect.Length();i++) {
block_run *indirect = (block_run *)cached.SetTo(block + i); block_run *indirect = (block_run *)cached.SetTo(block + i);
if (indirect == NULL) if (indirect == NULL)
return B_IO_ERROR; return B_IO_ERROR;
@@ -259,12 +280,13 @@ Stream::FindBlockRun(off_t pos, block_run &run, off_t &offset)
int32 current = -1; int32 current = -1;
while (++current < NUM_DIRECT_BLOCKS) { while (++current < NUM_DIRECT_BLOCKS) {
if (data.direct[current].IsZero()) if (fInode->data.direct[current].IsZero())
break; break;
runBlockEnd += data.direct[current].Length() << fVolume.BlockShift(); runBlockEnd += fInode->data.direct[current].Length()
<< fVolume.BlockShift();
if (runBlockEnd > pos) { if (runBlockEnd > pos) {
run = data.direct[current]; run = fInode->data.direct[current];
offset = runBlockEnd - (run.Length() << fVolume.BlockShift()); offset = runBlockEnd - (run.Length() << fVolume.BlockShift());
//printf("### run[%ld] = (%ld,%d,%d), offset = %Ld\n",fCurrent,fRun.allocation_group,fRun.start,fRun.length,fRunFileOffset); //printf("### run[%ld] = (%ld,%d,%d), offset = %Ld\n",fCurrent,fRun.allocation_group,fRun.start,fRun.length,fRunFileOffset);
return fVolume.ValidateBlockRun(run); return fVolume.ValidateBlockRun(run);
@@ -284,15 +306,15 @@ Stream::ReadAt(off_t pos, uint8 *buffer, size_t *_length)
if (pos < 0) if (pos < 0)
return B_BAD_VALUE; return B_BAD_VALUE;
if (pos >= data.Size()) { if (pos >= fInode->data.Size()) {
*_length = 0; *_length = 0;
return B_NO_ERROR; return B_NO_ERROR;
} }
size_t length = *_length; size_t length = *_length;
if (pos + length > data.Size()) if (pos + length > fInode->data.Size())
length = data.Size() - pos; length = fInode->data.Size() - pos;
block_run run; block_run run;
off_t offset; off_t offset;
@@ -396,14 +418,14 @@ Stream::ReadAt(off_t pos, uint8 *buffer, size_t *_length)
Node * Node *
Stream::NodeFactory(Volume &volume, off_t id) Stream::NodeFactory(Volume &volume, ::Directory* parent, off_t id)
{ {
Stream stream(volume, id); Stream stream(volume, id);
if (stream.InitCheck() != B_OK) if (stream.InitCheck() != B_OK)
return NULL; return NULL;
if (stream.IsContainer()) if (stream.IsContainer())
return new(nothrow) Directory(stream); return new(nothrow) Directory(parent, stream);
if (stream.IsSymlink()) if (stream.IsSymlink())
return new(nothrow) Link(stream); return new(nothrow) Link(stream);
@@ -412,10 +434,41 @@ Stream::NodeFactory(Volume &volume, off_t id)
} }
status_t
Stream::_LoadInode(off_t offset)
{
int32* inodeRef = (int32*)malloc(fVolume.BlockSize() + 4);
if (inodeRef == NULL)
return B_NO_MEMORY;
fInode = (bfs_inode*)(inodeRef + 1);
*inodeRef = 1;
ssize_t bytesRead = read_pos(fVolume.Device(), offset, fInode,
fVolume.BlockSize());
if (bytesRead >= 0 && (size_t)bytesRead == fVolume.BlockSize())
return B_OK;
free(inodeRef);
fInode = NULL;
return bytesRead < 0 ? bytesRead : B_ERROR;
}
void
Stream::_UseInode(bfs_inode* inode)
{
fInode = inode;
if (fInode != NULL)
((int32*)fInode)[-1]++;
}
// #pragma mark - // #pragma mark -
status_t status_t
bfs_inode::InitCheck(Volume *volume) bfs_inode::InitCheck(Volume *volume)
{ {
if (Flags() & INODE_NOT_READY) { if (Flags() & INODE_NOT_READY) {
@@ -6,20 +6,23 @@
#ifndef STREAM_H #ifndef STREAM_H
#define STREAM_H #define STREAM_H
#include <sys/stat.h>
#include <boot/vfs.h>
#include "Volume.h" #include "Volume.h"
#include <sys/stat.h>
class Node; class Node;
namespace BFS { namespace BFS {
class Stream : public bfs_inode { class Stream {
public: public:
Stream(Volume &volume, block_run run); Stream(Volume &volume, block_run run);
Stream(Volume &volume, off_t id); Stream(Volume &volume, off_t id);
Stream(const Stream& other);
~Stream(); ~Stream();
status_t InitCheck(); status_t InitCheck();
@@ -29,19 +32,27 @@ class Stream : public bfs_inode {
status_t ReadAt(off_t pos, uint8 *buffer, size_t *length); status_t ReadAt(off_t pos, uint8 *buffer, size_t *length);
status_t GetName(char *name, size_t size) const; status_t GetName(char *name, size_t size) const;
off_t Size() const { return data.Size(); } off_t Size() const { return fInode->data.Size(); }
off_t ID() const { return fVolume.ToVnode(inode_num); } off_t ID() const { return fVolume.ToVnode(fInode->inode_num); }
inode_addr InodeNum() const { return fInode->inode_num; }
int32 Mode() const { return fInode->Mode(); }
status_t ReadLink(char *buffer, size_t bufferSize); status_t ReadLink(char *buffer, size_t bufferSize);
bool IsContainer() const { return Mode() & (S_IFDIR | S_INDEX_DIR | S_ATTR_DIR); } bool IsContainer() const { return Mode() & (S_IFDIR | S_INDEX_DIR | S_ATTR_DIR); }
bool IsSymlink() const { return S_ISLNK(Mode()); } bool IsSymlink() const { return S_ISLNK(Mode()); }
static Node *NodeFactory(Volume &volume, off_t id); static Node *NodeFactory(Volume &volume, ::Directory* parent, off_t id);
private: private:
Stream& operator=(const Stream& other);
status_t GetNextSmallData(const small_data **_smallData) const; status_t GetNextSmallData(const small_data **_smallData) const;
Volume &fVolume; status_t _LoadInode(off_t offset);
void _UseInode(bfs_inode* inode);
Volume& fVolume;
bfs_inode* fInode;
}; };
} // namespace BFS } // namespace BFS
@@ -45,7 +45,7 @@ Volume::Volume(boot::Partition *partition)
// try block 0 again (can only happen on the big endian BFS) // try block 0 again (can only happen on the big endian BFS)
if (read_pos(fDevice, 0, &fSuperBlock, sizeof(disk_super_block)) < B_OK) if (read_pos(fDevice, 0, &fSuperBlock, sizeof(disk_super_block)) < B_OK)
return; return;
if (!IsValidSuperBlock()) if (!IsValidSuperBlock())
return; return;
#else #else
@@ -55,7 +55,7 @@ Volume::Volume(boot::Partition *partition)
TRACE(("bfs: we do have a valid super block (name = %s)!\n", fSuperBlock.name)); TRACE(("bfs: we do have a valid super block (name = %s)!\n", fSuperBlock.name));
fRootNode = new(nothrow) BFS::Directory(*this, Root()); fRootNode = new(nothrow) BFS::Directory(*this, NULL, Root());
if (fRootNode == NULL) if (fRootNode == NULL)
return; return;
@@ -74,7 +74,7 @@ Volume::~Volume()
} }
status_t status_t
Volume::InitCheck() Volume::InitCheck()
{ {
if (fDevice < B_OK) if (fDevice < B_OK)
@@ -118,7 +118,7 @@ Volume::ValidateBlockRun(block_run run)
} }
block_run block_run
Volume::ToBlockRun(off_t block) const Volume::ToBlockRun(off_t block) const
{ {
block_run run; block_run run;
@@ -96,7 +96,7 @@ class File : public ::Node, public Entry {
class Directory : public ::Directory, public Entry { class Directory : public ::Directory, public Entry {
public: public:
Directory(const char *name); Directory(::Directory* parent, const char* name);
virtual ~Directory(); virtual ~Directory();
virtual status_t Open(void **_cookie, int mode); virtual status_t Open(void **_cookie, int mode);
@@ -181,7 +181,7 @@ 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;
@@ -306,8 +306,10 @@ TarFS::File::Inode() const
// #pragma mark - // #pragma mark -
TarFS::Directory::Directory(const char *name) TarFS::Directory::Directory(::Directory* parent, const char* name)
: TarFS::Entry(name) :
::Directory(parent),
TarFS::Entry(name)
{ {
} }
@@ -321,7 +323,7 @@ TarFS::Directory::~Directory()
} }
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);
@@ -336,7 +338,7 @@ 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);
@@ -395,7 +397,7 @@ 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;
@@ -410,7 +412,7 @@ 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;
@@ -424,12 +426,12 @@ 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;
} }
@@ -458,7 +460,7 @@ TarFS::Directory::AddDirectory(char *dirName, TarFS::Directory **_dir)
return B_ERROR; return B_ERROR;
} else { } else {
// doesn't exist yet -- create it // doesn't exist yet -- create it
dir = new(nothrow) TarFS::Directory(dirName); dir = new(nothrow) TarFS::Directory(this, dirName);
if (!dir) if (!dir)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -517,7 +519,7 @@ TarFS::Directory::AddFile(tar_header *header)
} }
bool bool
TarFS::Directory::IsEmpty() TarFS::Directory::IsEmpty()
{ {
return fEntries.IsEmpty(); return fEntries.IsEmpty();
@@ -597,7 +599,7 @@ TarFS::Symlink::Inode() const
TarFS::Volume::Volume() TarFS::Volume::Volume()
: TarFS::Directory("Boot from CD-ROM") : TarFS::Directory(NULL, "Boot from CD-ROM")
{ {
} }
+86 -15
View File
@@ -92,21 +92,21 @@ Node::Close(void *cookie)
} }
status_t status_t
Node::GetName(char *nameBuffer, size_t bufferSize) const Node::GetName(char *nameBuffer, size_t bufferSize) const
{ {
return B_ERROR; return B_ERROR;
} }
int32 int32
Node::Type() const Node::Type() const
{ {
return 0; return 0;
} }
off_t off_t
Node::Size() const Node::Size() const
{ {
return 0LL; return 0LL;
@@ -120,7 +120,7 @@ Node::Inode() const
} }
status_t status_t
Node::Acquire() Node::Acquire()
{ {
fRefCount++; fRefCount++;
@@ -128,7 +128,7 @@ Node::Acquire()
return B_OK; return B_OK;
} }
status_t status_t
Node::Release() Node::Release()
{ {
TRACE(("%p::Release(), fRefCount = %ld\n", this, fRefCount)); TRACE(("%p::Release(), fRefCount = %ld\n", this, fRefCount));
@@ -168,27 +168,98 @@ ConsoleNode::Write(const void *buffer, size_t bufferSize)
// #pragma mark - // #pragma mark -
Directory::Directory() Directory::Directory(Directory* parent)
: Node() :
Node(),
fParent(NULL)
{ {
SetParent(parent);
} }
ssize_t Directory::~Directory()
{
SetParent(NULL);
}
Directory*
Directory::Parent() const
{
return fParent;
}
void
Directory::SetParent(Directory* parent)
{
if (fParent != NULL)
fParent->Release();
fParent = parent;
if (fParent != NULL)
fParent->Acquire();
}
status_t
Directory::GetPath(const char* entry, char* buffer, size_t bufferSize)
{
// get parent path, if any
if (fParent != NULL) {
status_t error = fParent->GetPath(NULL, buffer, bufferSize);
if (error != B_OK)
return error;
size_t len = strlen(buffer);
if (len == 0)
return B_BAD_VALUE;
if (buffer[len - 1] != '/') {
if (len == bufferSize)
return B_BUFFER_OVERFLOW;
buffer[len++] = '/';
}
buffer += len;
bufferSize -= len;
}
// append directory name
status_t error = GetName(buffer, bufferSize);
if (error != B_OK)
return error;
if (entry == NULL)
return B_OK;
// append entry name
if (strlcat(buffer, "/", bufferSize) >= bufferSize
|| strlcat(buffer, entry, bufferSize) >= bufferSize) {
return B_BUFFER_OVERFLOW;
}
return B_OK;
}
ssize_t
Directory::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize) Directory::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize)
{ {
return B_ERROR; return B_ERROR;
} }
ssize_t ssize_t
Directory::WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize) Directory::WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize)
{ {
return B_ERROR; return B_ERROR;
} }
int32 int32
Directory::Type() const Directory::Type() const
{ {
return S_IFDIR; return S_IFDIR;
@@ -265,7 +336,7 @@ Descriptor::~Descriptor()
} }
ssize_t ssize_t
Descriptor::Read(void *buffer, size_t bufferSize) Descriptor::Read(void *buffer, size_t bufferSize)
{ {
ssize_t bytesRead = fNode->ReadAt(fCookie, fOffset, buffer, bufferSize); ssize_t bytesRead = fNode->ReadAt(fCookie, fOffset, buffer, bufferSize);
@@ -276,7 +347,7 @@ Descriptor::Read(void *buffer, size_t bufferSize)
} }
ssize_t ssize_t
Descriptor::ReadAt(off_t pos, void *buffer, size_t bufferSize) Descriptor::ReadAt(off_t pos, void *buffer, size_t bufferSize)
{ {
return fNode->ReadAt(fCookie, pos, buffer, bufferSize); return fNode->ReadAt(fCookie, pos, buffer, bufferSize);
@@ -351,7 +422,7 @@ status_t
register_boot_file_system(Directory *volume) register_boot_file_system(Directory *volume)
{ {
gRoot->AddLink("boot", volume); gRoot->AddLink("boot", volume);
Partition *partition; Partition *partition;
status_t status = gRoot->GetPartitionFor(volume, &partition); status_t status = gRoot->GetPartitionFor(volume, &partition);
if (status != B_OK) { if (status != B_OK) {
@@ -576,7 +647,7 @@ open_node(Node *node, int mode)
return B_ERROR; return B_ERROR;
// get free descriptor // get free descriptor
int fd = 0; int fd = 0;
for (; fd < MAX_VFS_DESCRIPTORS; fd++) { for (; fd < MAX_VFS_DESCRIPTORS; fd++) {
if (sDescriptors[fd] == NULL) if (sDescriptors[fd] == NULL)
@@ -588,7 +659,7 @@ open_node(Node *node, int mode)
TRACE(("got descriptor %d for node %p\n", fd, node)); TRACE(("got descriptor %d for node %p\n", fd, node));
// we got a free descriptor entry, now try to open the node // we got a free descriptor entry, now try to open the node
void *cookie; void *cookie;
status_t status = node->Open(&cookie, mode); status_t status = node->Open(&cookie, mode);
if (status < B_OK) if (status < B_OK)