* 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:
Ingo Weinhold
2009-11-17 22:04:46 +00:00
parent 37fca3d23f
commit 744a460c12
19 changed files with 476 additions and 69 deletions
@@ -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,