* Package: Added Open() (and matching Close()) method, which opens the package
file once, tracking an open count.
* Added VFSInit()/VFSUninit() methods to the Node and PackageNode class
hierarchies, called by the {get,put}_vnode() PackageFile implements them to
set up/tear down access to the file data. Also added a Read() reading the
data.
* Implemented the open(), free_cookie(), and read() FS hooks for real. Reading
files works now. Executing doesn't yet -- it requires working with
IORequests in a way not supported by the userlandfs.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34102 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -38,6 +38,19 @@ Directory::Init(Directory* parent, const char* name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Directory::VFSInit(dev_t deviceID)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Directory::VFSUninit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
mode_t
|
mode_t
|
||||||
Directory::Mode() const
|
Directory::Mode() const
|
||||||
{
|
{
|
||||||
@@ -98,6 +111,13 @@ Directory::AddPackageNode(PackageNode* packageNode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Directory::Read(off_t offset, void* buffer, size_t* bufferSize)
|
||||||
|
{
|
||||||
|
return B_IS_A_DIRECTORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Directory::AddChild(Node* node)
|
Directory::AddChild(Node* node)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ public:
|
|||||||
|
|
||||||
virtual status_t Init(Directory* parent, const char* name);
|
virtual status_t Init(Directory* parent, const char* name);
|
||||||
|
|
||||||
|
virtual status_t VFSInit(dev_t deviceID);
|
||||||
|
virtual void VFSUninit();
|
||||||
|
|
||||||
virtual mode_t Mode() const;
|
virtual mode_t Mode() const;
|
||||||
virtual uid_t UserID() const;
|
virtual uid_t UserID() const;
|
||||||
virtual gid_t GroupID() const;
|
virtual gid_t GroupID() const;
|
||||||
@@ -39,6 +42,9 @@ public:
|
|||||||
|
|
||||||
virtual status_t AddPackageNode(PackageNode* packageNode);
|
virtual status_t AddPackageNode(PackageNode* packageNode);
|
||||||
|
|
||||||
|
virtual status_t Read(off_t offset, void* buffer,
|
||||||
|
size_t* bufferSize);
|
||||||
|
|
||||||
void AddChild(Node* node);
|
void AddChild(Node* node);
|
||||||
void RemoveChild(Node* node);
|
void RemoveChild(Node* node);
|
||||||
Node* FindChild(const char* name);
|
Node* FindChild(const char* name);
|
||||||
|
|||||||
@@ -26,6 +26,23 @@ LeafNode::Init(Directory* parent, const char* name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
LeafNode::VFSInit(dev_t deviceID)
|
||||||
|
{
|
||||||
|
if (PackageLeafNode* packageNode = fPackageNodes.Head())
|
||||||
|
return packageNode->VFSInit(deviceID, fID);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LeafNode::VFSUninit()
|
||||||
|
{
|
||||||
|
if (PackageLeafNode* packageNode = fPackageNodes.Head())
|
||||||
|
packageNode->VFSUninit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
mode_t
|
mode_t
|
||||||
LeafNode::Mode() const
|
LeafNode::Mode() const
|
||||||
{
|
{
|
||||||
@@ -85,6 +102,15 @@ LeafNode::AddPackageNode(PackageNode* packageNode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
LeafNode::Read(off_t offset, void* buffer, size_t* bufferSize)
|
||||||
|
{
|
||||||
|
if (PackageLeafNode* packageNode = fPackageNodes.Head())
|
||||||
|
return packageNode->Read(offset, buffer, bufferSize);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
LeafNode::SymlinkPath() const
|
LeafNode::SymlinkPath() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ public:
|
|||||||
|
|
||||||
virtual status_t Init(Directory* parent, const char* name);
|
virtual status_t Init(Directory* parent, const char* name);
|
||||||
|
|
||||||
|
virtual status_t VFSInit(dev_t deviceID);
|
||||||
|
virtual void VFSUninit();
|
||||||
|
|
||||||
virtual mode_t Mode() const;
|
virtual mode_t Mode() const;
|
||||||
virtual uid_t UserID() const;
|
virtual uid_t UserID() const;
|
||||||
virtual gid_t GroupID() const;
|
virtual gid_t GroupID() const;
|
||||||
@@ -25,6 +28,9 @@ public:
|
|||||||
|
|
||||||
virtual status_t AddPackageNode(PackageNode* packageNode);
|
virtual status_t AddPackageNode(PackageNode* packageNode);
|
||||||
|
|
||||||
|
virtual status_t Read(off_t offset, void* buffer,
|
||||||
|
size_t* bufferSize);
|
||||||
|
|
||||||
const char* SymlinkPath() const;
|
const char* SymlinkPath() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ public:
|
|||||||
|
|
||||||
virtual status_t Init(Directory* parent, const char* name);
|
virtual status_t Init(Directory* parent, const char* name);
|
||||||
|
|
||||||
|
virtual status_t VFSInit(dev_t deviceID) = 0;
|
||||||
|
virtual void VFSUninit() = 0;
|
||||||
|
|
||||||
virtual mode_t Mode() const = 0;
|
virtual mode_t Mode() const = 0;
|
||||||
virtual uid_t UserID() const = 0;
|
virtual uid_t UserID() const = 0;
|
||||||
virtual gid_t GroupID() const = 0;
|
virtual gid_t GroupID() const = 0;
|
||||||
@@ -50,6 +53,9 @@ public:
|
|||||||
|
|
||||||
virtual status_t AddPackageNode(PackageNode* packageNode) = 0;
|
virtual status_t AddPackageNode(PackageNode* packageNode) = 0;
|
||||||
|
|
||||||
|
virtual status_t Read(off_t offset, void* buffer,
|
||||||
|
size_t* bufferSize) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
rw_lock fLock;
|
rw_lock fLock;
|
||||||
ino_t fID;
|
ino_t fID;
|
||||||
|
|||||||
@@ -6,19 +6,28 @@
|
|||||||
|
|
||||||
#include "Package.h"
|
#include "Package.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <util/AutoLock.h>
|
||||||
|
|
||||||
#include "DebugSupport.h"
|
#include "DebugSupport.h"
|
||||||
|
#include "PackageDomain.h"
|
||||||
|
|
||||||
|
|
||||||
Package::Package(PackageDomain* domain, dev_t deviceID, ino_t nodeID)
|
Package::Package(PackageDomain* domain, dev_t deviceID, ino_t nodeID)
|
||||||
:
|
:
|
||||||
fDomain(domain),
|
fDomain(domain),
|
||||||
fName(NULL),
|
fName(NULL),
|
||||||
|
fFD(-1),
|
||||||
|
fOpenCount(0),
|
||||||
fNodeID(nodeID),
|
fNodeID(nodeID),
|
||||||
fDeviceID(deviceID)
|
fDeviceID(deviceID)
|
||||||
{
|
{
|
||||||
|
mutex_init(&fLock, "packagefs package");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -28,6 +37,8 @@ Package::~Package()
|
|||||||
delete node;
|
delete node;
|
||||||
|
|
||||||
free(fName);
|
free(fName);
|
||||||
|
|
||||||
|
mutex_destroy(&fLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -47,3 +58,55 @@ Package::AddNode(PackageNode* node)
|
|||||||
{
|
{
|
||||||
fNodes.Add(node);
|
fNodes.Add(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Package::Open()
|
||||||
|
{
|
||||||
|
MutexLocker locker(fLock);
|
||||||
|
if (fOpenCount > 0) {
|
||||||
|
fOpenCount++;
|
||||||
|
return fFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open the file
|
||||||
|
fFD = openat(fDomain->DirectoryFD(), fName, O_RDONLY);
|
||||||
|
if (fFD < 0) {
|
||||||
|
ERROR("Failed to open package file \"%s\"\n", fName);
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stat it to verify that it's still the same file
|
||||||
|
struct stat st;
|
||||||
|
if (fstat(fFD, &st) < 0) {
|
||||||
|
ERROR("Failed to stat package file \"%s\"\n", fName);
|
||||||
|
close(fFD);
|
||||||
|
fFD = -1;
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st.st_dev != fDeviceID || st.st_ino != fNodeID) {
|
||||||
|
close(fFD);
|
||||||
|
fFD = -1;
|
||||||
|
RETURN_ERROR(B_ENTRY_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
fOpenCount = 1;
|
||||||
|
return fFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Package::Close()
|
||||||
|
{
|
||||||
|
MutexLocker locker(fLock);
|
||||||
|
if (fOpenCount == 0) {
|
||||||
|
ERROR("Package open count already 0!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (--fOpenCount == 0) {
|
||||||
|
close(fFD);
|
||||||
|
fFD = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#include <util/khash.h>
|
#include <util/khash.h>
|
||||||
#include <util/OpenHashTable.h>
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
|
#include <lock.h>
|
||||||
|
|
||||||
#include "PackageNode.h"
|
#include "PackageNode.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -30,12 +32,18 @@ public:
|
|||||||
|
|
||||||
void AddNode(PackageNode* node);
|
void AddNode(PackageNode* node);
|
||||||
|
|
||||||
|
int Open();
|
||||||
|
void Close();
|
||||||
|
|
||||||
const PackageNodeList& Nodes() const
|
const PackageNodeList& Nodes() const
|
||||||
{ return fNodes; }
|
{ return fNodes; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
mutex fLock;
|
||||||
PackageDomain* fDomain;
|
PackageDomain* fDomain;
|
||||||
char* fName;
|
char* fName;
|
||||||
|
int fFD;
|
||||||
|
uint32 fOpenCount;
|
||||||
Package* fHashTableNext;
|
Package* fHashTableNext;
|
||||||
ino_t fNodeID;
|
ino_t fNodeID;
|
||||||
dev_t fDeviceID;
|
dev_t fDeviceID;
|
||||||
@@ -43,6 +51,29 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct PackageCloser {
|
||||||
|
PackageCloser(Package* package)
|
||||||
|
:
|
||||||
|
fPackage(package)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~PackageCloser()
|
||||||
|
{
|
||||||
|
if (fPackage != NULL)
|
||||||
|
fPackage->Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Detach()
|
||||||
|
{
|
||||||
|
fPackage = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Package* fPackage;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct PackageHashDefinition {
|
struct PackageHashDefinition {
|
||||||
typedef const char* KeyType;
|
typedef const char* KeyType;
|
||||||
typedef Package ValueType;
|
typedef Package ValueType;
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
#include "PackageDirectory.h"
|
#include "PackageDirectory.h"
|
||||||
|
|
||||||
|
|
||||||
PackageDirectory::PackageDirectory(mode_t mode)
|
PackageDirectory::PackageDirectory(Package* package, mode_t mode)
|
||||||
:
|
:
|
||||||
PackageNode(mode)
|
PackageNode(package, mode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
class PackageDirectory : public PackageNode,
|
class PackageDirectory : public PackageNode,
|
||||||
public DoublyLinkedListLinkImpl<PackageDirectory> {
|
public DoublyLinkedListLinkImpl<PackageDirectory> {
|
||||||
public:
|
public:
|
||||||
PackageDirectory(mode_t mode);
|
PackageDirectory(Package* package, mode_t mode);
|
||||||
virtual ~PackageDirectory();
|
virtual ~PackageDirectory();
|
||||||
|
|
||||||
void AddChild(PackageNode* node);
|
void AddChild(PackageNode* node);
|
||||||
|
|||||||
@@ -6,11 +6,99 @@
|
|||||||
|
|
||||||
#include "PackageFile.h"
|
#include "PackageFile.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
PackageFile::PackageFile(mode_t mode, const PackageData& data)
|
#include <fs_cache.h>
|
||||||
|
|
||||||
|
#include "DataReader.h"
|
||||||
|
#include "PackageDataReader.h"
|
||||||
|
|
||||||
|
#include "DebugSupport.h"
|
||||||
|
#include "Package.h"
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - DataAccessor
|
||||||
|
|
||||||
|
|
||||||
|
struct PackageFile::DataAccessor {
|
||||||
|
DataAccessor(PackageData* data)
|
||||||
|
:
|
||||||
|
fData(data),
|
||||||
|
fDataReader(NULL),
|
||||||
|
fReader(NULL),
|
||||||
|
fFileCache(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~DataAccessor()
|
||||||
|
{
|
||||||
|
file_cache_delete(fFileCache);
|
||||||
|
delete fReader;
|
||||||
|
delete fDataReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t Init(dev_t deviceID, ino_t nodeID, int fd)
|
||||||
|
{
|
||||||
|
// create a DataReader for the compressed data
|
||||||
|
if (fData->IsEncodedInline()) {
|
||||||
|
fDataReader = new(std::nothrow) BufferDataReader(
|
||||||
|
fData->InlineData(), fData->CompressedSize());
|
||||||
|
} else
|
||||||
|
fDataReader = new(std::nothrow) FDDataReader(fd);
|
||||||
|
|
||||||
|
if (fDataReader == NULL)
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
|
||||||
|
// create a PackageDataReader
|
||||||
|
status_t error = PackageDataReaderFactory::CreatePackageDataReader(
|
||||||
|
fDataReader, *fData, fReader);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
// create a file cache
|
||||||
|
fFileCache = file_cache_create(deviceID, nodeID,
|
||||||
|
fData->UncompressedSize());
|
||||||
|
if (fFileCache == NULL)
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t ReadData(off_t offset, void* buffer, size_t* bufferSize)
|
||||||
|
{
|
||||||
|
if (offset < 0 || (uint64)offset > fData->UncompressedSize())
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
size_t toRead = std::min((uint64)*bufferSize,
|
||||||
|
fData->UncompressedSize() - offset);
|
||||||
|
|
||||||
|
if (toRead > 0) {
|
||||||
|
status_t error = fReader->ReadData(offset, buffer, toRead);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
*bufferSize = toRead;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PackageData* fData;
|
||||||
|
DataReader* fDataReader;
|
||||||
|
PackageDataReader* fReader;
|
||||||
|
void* fFileCache;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PackageFile
|
||||||
|
|
||||||
|
|
||||||
|
PackageFile::PackageFile(Package* package, mode_t mode, const PackageData& data)
|
||||||
:
|
:
|
||||||
PackageLeafNode(mode),
|
PackageLeafNode(package, mode),
|
||||||
fData(data)
|
fData(data),
|
||||||
|
fDataAccessor(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,8 +108,54 @@ PackageFile::~PackageFile()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageFile::VFSInit(dev_t deviceID, ino_t nodeID)
|
||||||
|
{
|
||||||
|
// open the package
|
||||||
|
int fd = fPackage->Open();
|
||||||
|
if (fd < 0)
|
||||||
|
RETURN_ERROR(fd);
|
||||||
|
PackageCloser packageCloser(fPackage);
|
||||||
|
|
||||||
|
// create the data accessor
|
||||||
|
fDataAccessor = new(std::nothrow) DataAccessor(&fData);
|
||||||
|
if (fDataAccessor == NULL)
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
|
||||||
|
status_t error = fDataAccessor->Init(deviceID, nodeID, fd);
|
||||||
|
if (error != B_OK) {
|
||||||
|
delete fDataAccessor;
|
||||||
|
fDataAccessor = NULL;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
packageCloser.Detach();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFile::VFSUninit()
|
||||||
|
{
|
||||||
|
if (fDataAccessor != NULL) {
|
||||||
|
fPackage->Close();
|
||||||
|
delete fDataAccessor;
|
||||||
|
fDataAccessor = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
off_t
|
off_t
|
||||||
PackageFile::FileSize() const
|
PackageFile::FileSize() const
|
||||||
{
|
{
|
||||||
return fData.UncompressedSize();
|
return fData.UncompressedSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageFile::Read(off_t offset, void* buffer, size_t* bufferSize)
|
||||||
|
{
|
||||||
|
if (fDataAccessor == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
return fDataAccessor->ReadData(offset, buffer, bufferSize);
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,14 +13,24 @@
|
|||||||
|
|
||||||
class PackageFile : public PackageLeafNode {
|
class PackageFile : public PackageLeafNode {
|
||||||
public:
|
public:
|
||||||
PackageFile(mode_t mode,
|
PackageFile(Package* package, mode_t mode,
|
||||||
const PackageData& data);
|
const PackageData& data);
|
||||||
virtual ~PackageFile();
|
virtual ~PackageFile();
|
||||||
|
|
||||||
|
virtual status_t VFSInit(dev_t deviceID, ino_t nodeID);
|
||||||
|
virtual void VFSUninit();
|
||||||
|
|
||||||
virtual off_t FileSize() const;
|
virtual off_t FileSize() const;
|
||||||
|
|
||||||
|
virtual status_t Read(off_t offset, void* buffer,
|
||||||
|
size_t* bufferSize);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct DataAccessor;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PackageData fData;
|
PackageData fData;
|
||||||
|
DataAccessor* fDataAccessor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
#include "PackageLeafNode.h"
|
#include "PackageLeafNode.h"
|
||||||
|
|
||||||
|
|
||||||
PackageLeafNode::PackageLeafNode(mode_t mode)
|
PackageLeafNode::PackageLeafNode(Package* package, mode_t mode)
|
||||||
:
|
:
|
||||||
PackageNode(mode)
|
PackageNode(package, mode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,3 +24,10 @@ PackageLeafNode::SymlinkPath() const
|
|||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageLeafNode::Read(off_t offset, void* buffer, size_t* bufferSize)
|
||||||
|
{
|
||||||
|
return EBADF;
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,11 +14,14 @@ class PackageData;
|
|||||||
|
|
||||||
class PackageLeafNode : public PackageNode {
|
class PackageLeafNode : public PackageNode {
|
||||||
public:
|
public:
|
||||||
PackageLeafNode(mode_t mode);
|
PackageLeafNode(Package* package, mode_t mode);
|
||||||
virtual ~PackageLeafNode();
|
virtual ~PackageLeafNode();
|
||||||
|
|
||||||
virtual const char* SymlinkPath() const;
|
virtual const char* SymlinkPath() const;
|
||||||
|
|
||||||
|
virtual status_t Read(off_t offset, void* buffer,
|
||||||
|
size_t* bufferSize);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SinglyLinkedListLink<PackageLeafNode> fListLink;
|
SinglyLinkedListLink<PackageLeafNode> fListLink;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,8 +12,9 @@
|
|||||||
#include "DebugSupport.h"
|
#include "DebugSupport.h"
|
||||||
|
|
||||||
|
|
||||||
PackageNode::PackageNode(mode_t mode)
|
PackageNode::PackageNode(Package* package, mode_t mode)
|
||||||
:
|
:
|
||||||
|
fPackage(package),
|
||||||
fParent(NULL),
|
fParent(NULL),
|
||||||
fName(NULL),
|
fName(NULL),
|
||||||
fMode(mode),
|
fMode(mode),
|
||||||
@@ -41,6 +42,19 @@ PackageNode::Init(PackageDirectory* parent, const char* name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageNode::VFSInit(dev_t deviceID, ino_t nodeID)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageNode::VFSUninit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
off_t
|
off_t
|
||||||
PackageNode::FileSize() const
|
PackageNode::FileSize() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,12 +13,13 @@
|
|||||||
#include <util/SinglyLinkedList.h>
|
#include <util/SinglyLinkedList.h>
|
||||||
|
|
||||||
|
|
||||||
|
class Package;
|
||||||
class PackageDirectory;
|
class PackageDirectory;
|
||||||
|
|
||||||
|
|
||||||
class PackageNode : public SinglyLinkedListLinkImpl<PackageNode> {
|
class PackageNode : public SinglyLinkedListLinkImpl<PackageNode> {
|
||||||
public:
|
public:
|
||||||
PackageNode(mode_t mode);
|
PackageNode(Package* package, mode_t mode);
|
||||||
virtual ~PackageNode();
|
virtual ~PackageNode();
|
||||||
|
|
||||||
PackageDirectory* Parent() const { return fParent; }
|
PackageDirectory* Parent() const { return fParent; }
|
||||||
@@ -27,6 +28,9 @@ public:
|
|||||||
virtual status_t Init(PackageDirectory* parent,
|
virtual status_t Init(PackageDirectory* parent,
|
||||||
const char* name);
|
const char* name);
|
||||||
|
|
||||||
|
virtual status_t VFSInit(dev_t deviceID, ino_t nodeID);
|
||||||
|
virtual void VFSUninit();
|
||||||
|
|
||||||
mode_t Mode() const { return fMode; }
|
mode_t Mode() const { return fMode; }
|
||||||
|
|
||||||
uid_t UserID() const { return fUserID; }
|
uid_t UserID() const { return fUserID; }
|
||||||
@@ -43,6 +47,7 @@ public:
|
|||||||
virtual off_t FileSize() const;
|
virtual off_t FileSize() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Package* fPackage;
|
||||||
PackageDirectory* fParent;
|
PackageDirectory* fParent;
|
||||||
char* fName;
|
char* fName;
|
||||||
mode_t fMode;
|
mode_t fMode;
|
||||||
|
|||||||
@@ -10,9 +10,9 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
PackageSymlink::PackageSymlink(mode_t mode)
|
PackageSymlink::PackageSymlink(Package* package, mode_t mode)
|
||||||
:
|
:
|
||||||
PackageLeafNode(mode),
|
PackageLeafNode(package, mode),
|
||||||
fSymlinkPath(NULL)
|
fSymlinkPath(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
class PackageSymlink : public PackageLeafNode {
|
class PackageSymlink : public PackageLeafNode {
|
||||||
public:
|
public:
|
||||||
PackageSymlink(mode_t mode);
|
PackageSymlink(Package* package, mode_t mode);
|
||||||
virtual ~PackageSymlink();
|
virtual ~PackageSymlink();
|
||||||
|
|
||||||
status_t SetSymlinkPath(const char* path);
|
status_t SetSymlinkPath(const char* path);
|
||||||
|
|||||||
@@ -141,10 +141,11 @@ struct Volume::PackageLoaderContentHandler : PackageContentHandler {
|
|||||||
PackageNode* node;
|
PackageNode* node;
|
||||||
if (S_ISREG(mode)) {
|
if (S_ISREG(mode)) {
|
||||||
// file
|
// file
|
||||||
node = new(std::nothrow) PackageFile(mode, entry->Data());
|
node = new(std::nothrow) PackageFile(fPackage, mode, entry->Data());
|
||||||
} else if (S_ISLNK(mode)) {
|
} else if (S_ISLNK(mode)) {
|
||||||
// symlink
|
// symlink
|
||||||
PackageSymlink* symlink = new(std::nothrow) PackageSymlink(mode);
|
PackageSymlink* symlink = new(std::nothrow) PackageSymlink(
|
||||||
|
fPackage, mode);
|
||||||
if (symlink == NULL)
|
if (symlink == NULL)
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
|
||||||
@@ -157,7 +158,7 @@ struct Volume::PackageLoaderContentHandler : PackageContentHandler {
|
|||||||
node = symlink;
|
node = symlink;
|
||||||
} else if (S_ISDIR(mode)) {
|
} else if (S_ISDIR(mode)) {
|
||||||
// directory
|
// directory
|
||||||
node = new(std::nothrow) PackageDirectory(mode);
|
node = new(std::nothrow) PackageDirectory(fPackage, mode);
|
||||||
} else
|
} else
|
||||||
RETURN_ERROR(B_BAD_DATA);
|
RETURN_ERROR(B_BAD_DATA);
|
||||||
|
|
||||||
@@ -476,16 +477,12 @@ status_t
|
|||||||
Volume::_LoadPackage(Package* package)
|
Volume::_LoadPackage(Package* package)
|
||||||
{
|
{
|
||||||
// open package file
|
// open package file
|
||||||
int fd = openat(package->Domain()->DirectoryFD(), package->Name(),
|
int fd = package->Open();
|
||||||
O_RDONLY);
|
if (fd < 0)
|
||||||
if (fd < 0) {
|
RETURN_ERROR(fd);
|
||||||
ERROR("Failed to open package file \"%s\"\n", package->Name());
|
PackageCloser packageCloser(package);
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
// TODO: Verify that it's still the same file.
|
|
||||||
FDCloser fdCloser(fd);
|
|
||||||
|
|
||||||
// open package
|
// initialize package reader
|
||||||
PackageLoaderErrorOutput errorOutput(package);
|
PackageLoaderErrorOutput errorOutput(package);
|
||||||
PackageReader packageReader(&errorOutput);
|
PackageReader packageReader(&errorOutput);
|
||||||
status_t error = packageReader.Init(fd, false);
|
status_t error = packageReader.Init(fd, false);
|
||||||
|
|||||||
@@ -58,6 +58,43 @@ set_dirent_name(struct dirent* buffer, size_t bufferSize, const char* name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
check_access(Node* node, int mode)
|
||||||
|
{
|
||||||
|
// write access requested?
|
||||||
|
if (mode & W_OK)
|
||||||
|
return B_READ_ONLY_DEVICE;
|
||||||
|
|
||||||
|
// get node permissions
|
||||||
|
int userPermissions = (node->Mode() & S_IRWXU) >> 6;
|
||||||
|
int groupPermissions = (node->Mode() & S_IRWXG) >> 3;
|
||||||
|
int otherPermissions = node->Mode() & S_IRWXO;
|
||||||
|
|
||||||
|
// get the permissions for this uid/gid
|
||||||
|
int permissions = 0;
|
||||||
|
uid_t uid = geteuid();
|
||||||
|
|
||||||
|
if (uid == 0) {
|
||||||
|
// user is root
|
||||||
|
// root has always read/write permission, but at least one of the
|
||||||
|
// X bits must be set for execute permission
|
||||||
|
permissions = userPermissions | groupPermissions | otherPermissions
|
||||||
|
| S_IROTH | S_IWOTH;
|
||||||
|
} else if (uid == node->UserID()) {
|
||||||
|
// user is node owner
|
||||||
|
permissions = userPermissions;
|
||||||
|
} else if (is_user_in_group(node->GroupID())) {
|
||||||
|
// user is in owning group
|
||||||
|
permissions = groupPermissions;
|
||||||
|
} else {
|
||||||
|
// user is one of the others
|
||||||
|
permissions = otherPermissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (mode & ~permissions) == 0 ? B_OK : B_NOT_ALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Volume
|
// #pragma mark - Volume
|
||||||
|
|
||||||
|
|
||||||
@@ -171,9 +208,16 @@ packagefs_get_vnode(fs_volume* fsVolume, ino_t vnid, fs_vnode* fsNode,
|
|||||||
Node* node = volume->FindNode(vnid);
|
Node* node = volume->FindNode(vnid);
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
node->AcquireReference();
|
BReference<Node> nodeReference(node);
|
||||||
|
volumeLocker.Unlock();
|
||||||
|
|
||||||
fsNode->private_node = node;
|
NodeWriteLocker nodeLocker(node);
|
||||||
|
status_t error = node->VFSInit(volume->ID());
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
nodeLocker.Unlock();
|
||||||
|
|
||||||
|
fsNode->private_node = nodeReference.Detach();
|
||||||
fsNode->ops = &gPackageFSVnodeOps;
|
fsNode->ops = &gPackageFSVnodeOps;
|
||||||
*_type = node->Mode() & S_IFMT;
|
*_type = node->Mode() & S_IFMT;
|
||||||
*_flags = 0;
|
*_flags = 0;
|
||||||
@@ -191,12 +235,28 @@ packagefs_put_vnode(fs_volume* fsVolume, fs_vnode* fsNode, bool reenter)
|
|||||||
FUNCTION("volume: %p, node: %p\n", volume, node);
|
FUNCTION("volume: %p, node: %p\n", volume, node);
|
||||||
TOUCH(volume);
|
TOUCH(volume);
|
||||||
|
|
||||||
|
NodeWriteLocker nodeLocker(node);
|
||||||
|
node->VFSUninit();
|
||||||
|
nodeLocker.Unlock();
|
||||||
|
|
||||||
node->ReleaseReference();
|
node->ReleaseReference();
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Request I/O
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static status_t
|
||||||
|
packagefs_io(fs_volume* volume, fs_vnode* vnode, void* cookie,
|
||||||
|
io_request* request)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Nodes
|
// #pragma mark - Nodes
|
||||||
|
|
||||||
|
|
||||||
@@ -238,39 +298,8 @@ packagefs_access(fs_volume* fsVolume, fs_vnode* fsNode, int mode)
|
|||||||
FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID());
|
FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID());
|
||||||
TOUCH(volume);
|
TOUCH(volume);
|
||||||
|
|
||||||
// write access requested?
|
|
||||||
if (mode & W_OK)
|
|
||||||
return B_READ_ONLY_DEVICE;
|
|
||||||
|
|
||||||
NodeReadLocker nodeLocker(node);
|
NodeReadLocker nodeLocker(node);
|
||||||
|
return check_access(node, mode);
|
||||||
// get node permissions
|
|
||||||
int userPermissions = (node->Mode() & S_IRWXU) >> 6;
|
|
||||||
int groupPermissions = (node->Mode() & S_IRWXG) >> 3;
|
|
||||||
int otherPermissions = node->Mode() & S_IRWXO;
|
|
||||||
|
|
||||||
// get the permissions for this uid/gid
|
|
||||||
int permissions = 0;
|
|
||||||
uid_t uid = geteuid();
|
|
||||||
|
|
||||||
if (uid == 0) {
|
|
||||||
// user is root
|
|
||||||
// root has always read/write permission, but at least one of the
|
|
||||||
// X bits must be set for execute permission
|
|
||||||
permissions = userPermissions | groupPermissions | otherPermissions
|
|
||||||
| S_IROTH | S_IWOTH;
|
|
||||||
} else if (uid == node->UserID()) {
|
|
||||||
// user is node owner
|
|
||||||
permissions = userPermissions;
|
|
||||||
} else if (is_user_in_group(node->GroupID())) {
|
|
||||||
// user is in owning group
|
|
||||||
permissions = groupPermissions;
|
|
||||||
} else {
|
|
||||||
// user is one of the others
|
|
||||||
permissions = otherPermissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (mode & ~permissions) ? B_NOT_ALLOWED : B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -304,6 +333,17 @@ packagefs_read_stat(fs_volume* fsVolume, fs_vnode* fsNode, struct stat* st)
|
|||||||
// #pragma mark - Files
|
// #pragma mark - Files
|
||||||
|
|
||||||
|
|
||||||
|
struct FileCookie {
|
||||||
|
int openMode;
|
||||||
|
|
||||||
|
FileCookie(int openMode)
|
||||||
|
:
|
||||||
|
openMode(openMode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
packagefs_open(fs_volume* fsVolume, fs_vnode* fsNode, int openMode,
|
packagefs_open(fs_volume* fsVolume, fs_vnode* fsNode, int openMode,
|
||||||
void** _cookie)
|
void** _cookie)
|
||||||
@@ -314,10 +354,26 @@ packagefs_open(fs_volume* fsVolume, fs_vnode* fsNode, int openMode,
|
|||||||
FUNCTION("volume: %p, node: %p (%lld), openMode %#x\n", volume, node,
|
FUNCTION("volume: %p, node: %p (%lld), openMode %#x\n", volume, node,
|
||||||
node->ID(), openMode);
|
node->ID(), openMode);
|
||||||
TOUCH(volume);
|
TOUCH(volume);
|
||||||
TOUCH(node);
|
|
||||||
|
|
||||||
// TODO: Implement it for real!
|
NodeReadLocker nodeLocker(node);
|
||||||
*_cookie = NULL;
|
|
||||||
|
// check the open mode and permissions
|
||||||
|
if (S_ISDIR(node->Mode()) && (openMode & O_RWMASK) != O_RDONLY)
|
||||||
|
return B_IS_A_DIRECTORY;
|
||||||
|
|
||||||
|
if ((openMode & O_RWMASK) != O_RDONLY)
|
||||||
|
return B_NOT_ALLOWED;
|
||||||
|
|
||||||
|
status_t error = check_access(node, R_OK);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// allocate the cookie
|
||||||
|
FileCookie* cookie = new(std::nothrow) FileCookie(openMode);
|
||||||
|
if (cookie == NULL)
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
|
||||||
|
*_cookie = cookie;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -331,17 +387,40 @@ packagefs_close(fs_volume* fs, fs_vnode* _node, void* cookie)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
packagefs_free_cookie(fs_volume* fs, fs_vnode* _node, void* cookie)
|
packagefs_free_cookie(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
|
||||||
{
|
{
|
||||||
|
Volume* volume = (Volume*)fsVolume->private_volume;
|
||||||
|
Node* node = (Node*)fsNode->private_node;
|
||||||
|
FileCookie* cookie = (FileCookie*)_cookie;
|
||||||
|
|
||||||
|
FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
|
||||||
|
node->ID(), cookie);
|
||||||
|
TOUCH(volume);
|
||||||
|
TOUCH(node);
|
||||||
|
|
||||||
|
delete cookie;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
packagefs_read(fs_volume* fs, fs_vnode* _node, void* cookie, off_t pos,
|
packagefs_read(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie,
|
||||||
void* buffer, size_t* bufferSize)
|
off_t offset, void* buffer, size_t* bufferSize)
|
||||||
{
|
{
|
||||||
return B_UNSUPPORTED;
|
Volume* volume = (Volume*)fsVolume->private_volume;
|
||||||
|
Node* node = (Node*)fsNode->private_node;
|
||||||
|
FileCookie* cookie = (FileCookie*)_cookie;
|
||||||
|
|
||||||
|
FUNCTION("volume: %p, node: %p (%lld), cookie: %p, offset: %lld, "
|
||||||
|
"buffer: %p, size: %lu\n", volume, node, node->ID(), cookie, offset,
|
||||||
|
buffer, *bufferSize);
|
||||||
|
TOUCH(volume);
|
||||||
|
|
||||||
|
if ((cookie->openMode & O_RWMASK) != O_RDONLY)
|
||||||
|
return EBADF;
|
||||||
|
|
||||||
|
return node->Read(offset, buffer, bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -635,7 +714,7 @@ fs_vnode_ops gPackageFSVnodeOps = {
|
|||||||
NULL, // read_pages,
|
NULL, // read_pages,
|
||||||
NULL, // write_pages,
|
NULL, // write_pages,
|
||||||
|
|
||||||
NULL, // io()
|
NULL, // &packagefs_io,
|
||||||
NULL, // cancel_io()
|
NULL, // cancel_io()
|
||||||
|
|
||||||
NULL, // get_file_map,
|
NULL, // get_file_map,
|
||||||
|
|||||||
Reference in New Issue
Block a user