[haiku-commits] r34102 - haiku/trunk/src/add-ons/kernel/file_systems/packagefs

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 17 Nov 2009 23:04:47 +0100 (CET)

Author: bonefish
Date: 2009-11-17 23:04:46 +0100 (Tue, 17 Nov 2009)
New Revision: 34102
Changeset: http://dev.haiku-os.org/changeset/34102/haiku

Modified:
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Directory.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Directory.h
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/LeafNode.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/LeafNode.h
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Node.h
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Package.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Package.h
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageDirectory.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageDirectory.h
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageFile.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageFile.h
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageLeafNode.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageLeafNode.h
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageNode.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageNode.h
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageSymlink.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageSymlink.h
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Volume.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp
Log:
* 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.


Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Directory.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Directory.cpp 
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Directory.cpp 
2009-11-17 22:04:46 UTC (rev 34102)
@@ -38,6 +38,19 @@
 }
 
 
+status_t
+Directory::VFSInit(dev_t deviceID)
+{
+       return B_OK;
+}
+
+
+void
+Directory::VFSUninit()
+{
+}
+
+
 mode_t
 Directory::Mode() const
 {
@@ -98,6 +111,13 @@
 }
 
 
+status_t
+Directory::Read(off_t offset, void* buffer, size_t* bufferSize)
+{
+       return B_IS_A_DIRECTORY;
+}
+
+
 void
 Directory::AddChild(Node* node)
 {

Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Directory.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Directory.h   
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Directory.h   
2009-11-17 22:04:46 UTC (rev 34102)
@@ -31,6 +31,9 @@
 
        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 uid_t                           UserID() const;
        virtual gid_t                           GroupID() const;
@@ -39,6 +42,9 @@
 
        virtual status_t                        AddPackageNode(PackageNode* 
packageNode);
 
+       virtual status_t                        Read(off_t offset, void* buffer,
+                                                                       size_t* 
bufferSize);
+
                        void                            AddChild(Node* node);
                        void                            RemoveChild(Node* node);
                        Node*                           FindChild(const char* 
name);

Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/LeafNode.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/LeafNode.cpp  
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/LeafNode.cpp  
2009-11-17 22:04:46 UTC (rev 34102)
@@ -26,6 +26,23 @@
 }
 
 
+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
 LeafNode::Mode() const
 {
@@ -85,6 +102,15 @@
 }
 
 
+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*
 LeafNode::SymlinkPath() const
 {

Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/LeafNode.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/LeafNode.h    
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/LeafNode.h    
2009-11-17 22:04:46 UTC (rev 34102)
@@ -17,6 +17,9 @@
 
        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 uid_t                           UserID() const;
        virtual gid_t                           GroupID() const;
@@ -25,6 +28,9 @@
 
        virtual status_t                        AddPackageNode(PackageNode* 
packageNode);
 
+       virtual status_t                        Read(off_t offset, void* buffer,
+                                                                       size_t* 
bufferSize);
+
                        const char*                     SymlinkPath() const;
 
 private:

Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Node.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Node.h        
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Node.h        
2009-11-17 22:04:46 UTC (rev 34102)
@@ -42,6 +42,9 @@
 
        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 uid_t                           UserID() const = 0;
        virtual gid_t                           GroupID() const = 0;
@@ -50,6 +53,9 @@
 
        virtual status_t                        AddPackageNode(PackageNode* 
packageNode) = 0;
 
+       virtual status_t                        Read(off_t offset, void* buffer,
+                                                                       size_t* 
bufferSize) = 0;
+
 protected:
                        rw_lock                         fLock;
                        ino_t                           fID;

Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Package.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Package.cpp   
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Package.cpp   
2009-11-17 22:04:46 UTC (rev 34102)
@@ -6,19 +6,28 @@
 
 #include "Package.h"
 
+#include <errno.h>
+#include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
+#include <util/AutoLock.h>
+
 #include "DebugSupport.h"
+#include "PackageDomain.h"
 
 
 Package::Package(PackageDomain* domain, dev_t deviceID, ino_t nodeID)
        :
        fDomain(domain),
        fName(NULL),
+       fFD(-1),
+       fOpenCount(0),
        fNodeID(nodeID),
        fDeviceID(deviceID)
 {
+       mutex_init(&fLock, "packagefs package");
 }
 
 
@@ -28,6 +37,8 @@
                delete node;
 
        free(fName);
+
+       mutex_destroy(&fLock);
 }
 
 
@@ -47,3 +58,55 @@
 {
        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;
+       }
+}

Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Package.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Package.h     
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Package.h     
2009-11-17 22:04:46 UTC (rev 34102)
@@ -9,6 +9,8 @@
 #include <util/khash.h>
 #include <util/OpenHashTable.h>
 
+#include <lock.h>
+
 #include "PackageNode.h"
 
 
@@ -30,12 +32,18 @@
 
                        void                            AddNode(PackageNode* 
node);
 
+                       int                                     Open();
+                       void                            Close();
+
                        const PackageNodeList&  Nodes() const
                                                                        { 
return fNodes; }
 
 private:
+                       mutex                           fLock;
                        PackageDomain*          fDomain;
                        char*                           fName;
+                       int                                     fFD;
+                       uint32                          fOpenCount;
                        Package*                        fHashTableNext;
                        ino_t                           fNodeID;
                        dev_t                           fDeviceID;
@@ -43,6 +51,29 @@
 };
 
 
+struct PackageCloser {
+       PackageCloser(Package* package)
+               :
+               fPackage(package)
+       {
+       }
+
+       ~PackageCloser()
+       {
+               if (fPackage != NULL)
+                       fPackage->Close();
+       }
+
+       void Detach()
+       {
+               fPackage = NULL;
+       }
+
+private:
+       Package*        fPackage;
+};
+
+
 struct PackageHashDefinition {
        typedef const char*             KeyType;
        typedef Package                 ValueType;

Modified: 
haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageDirectory.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageDirectory.cpp  
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageDirectory.cpp  
2009-11-17 22:04:46 UTC (rev 34102)
@@ -7,9 +7,9 @@
 #include "PackageDirectory.h"
 
 
-PackageDirectory::PackageDirectory(mode_t mode)
+PackageDirectory::PackageDirectory(Package* package, mode_t mode)
        :
-       PackageNode(mode)
+       PackageNode(package, mode)
 {
 }
 

Modified: 
haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageDirectory.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageDirectory.h    
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageDirectory.h    
2009-11-17 22:04:46 UTC (rev 34102)
@@ -14,7 +14,7 @@
 class PackageDirectory : public PackageNode,
        public DoublyLinkedListLinkImpl<PackageDirectory> {
 public:
-                                                               
PackageDirectory(mode_t mode);
+                                                               
PackageDirectory(Package* package, mode_t mode);
        virtual                                         ~PackageDirectory();
 
                        void                            AddChild(PackageNode* 
node);

Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageFile.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageFile.cpp       
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageFile.cpp       
2009-11-17 22:04:46 UTC (rev 34102)
@@ -6,11 +6,99 @@
 
 #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),
-       fData(data)
+       PackageLeafNode(package, mode),
+       fData(data),
+       fDataAccessor(NULL)
 {
 }
 
@@ -20,8 +108,54 @@
 }
 
 
+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
 PackageFile::FileSize() const
 {
        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);
+}

Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageFile.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageFile.h 
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageFile.h 
2009-11-17 22:04:46 UTC (rev 34102)
@@ -13,14 +13,24 @@
 
 class PackageFile : public PackageLeafNode {
 public:
-                                                               
PackageFile(mode_t mode,
+                                                               
PackageFile(Package* package, mode_t mode,
                                                                        const 
PackageData& data);
        virtual                                         ~PackageFile();
 
+       virtual status_t                        VFSInit(dev_t deviceID, ino_t 
nodeID);
+       virtual void                            VFSUninit();
+
        virtual off_t                           FileSize() const;
 
+       virtual status_t                        Read(off_t offset, void* buffer,
+                                                                       size_t* 
bufferSize);
+
 private:
+                       struct DataAccessor;
+
+private:
                        PackageData                     fData;
+                       DataAccessor*           fDataAccessor;
 };
 
 

Modified: 
haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageLeafNode.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageLeafNode.cpp   
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageLeafNode.cpp   
2009-11-17 22:04:46 UTC (rev 34102)
@@ -7,9 +7,9 @@
 #include "PackageLeafNode.h"
 
 
-PackageLeafNode::PackageLeafNode(mode_t mode)
+PackageLeafNode::PackageLeafNode(Package* package, mode_t mode)
        :
-       PackageNode(mode)
+       PackageNode(package, mode)
 {
 }
 
@@ -24,3 +24,10 @@
 {
        return NULL;
 }
+
+
+status_t
+PackageLeafNode::Read(off_t offset, void* buffer, size_t* bufferSize)
+{
+       return EBADF;
+}

Modified: 
haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageLeafNode.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageLeafNode.h     
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageLeafNode.h     
2009-11-17 22:04:46 UTC (rev 34102)
@@ -14,11 +14,14 @@
 
 class PackageLeafNode : public PackageNode {
 public:
-                                                               
PackageLeafNode(mode_t mode);
+                                                               
PackageLeafNode(Package* package, mode_t mode);
        virtual                                         ~PackageLeafNode();
 
        virtual const char*                     SymlinkPath() const;
 
+       virtual status_t                        Read(off_t offset, void* buffer,
+                                                                       size_t* 
bufferSize);
+
 public:
                        SinglyLinkedListLink<PackageLeafNode> fListLink;
 };

Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageNode.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageNode.cpp       
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageNode.cpp       
2009-11-17 22:04:46 UTC (rev 34102)
@@ -12,8 +12,9 @@
 #include "DebugSupport.h"
 
 
-PackageNode::PackageNode(mode_t mode)
+PackageNode::PackageNode(Package* package, mode_t mode)
        :
+       fPackage(package),
        fParent(NULL),
        fName(NULL),
        fMode(mode),
@@ -41,6 +42,19 @@
 }
 
 
+status_t
+PackageNode::VFSInit(dev_t deviceID, ino_t nodeID)
+{
+       return B_OK;
+}
+
+
+void
+PackageNode::VFSUninit()
+{
+}
+
+
 off_t
 PackageNode::FileSize() const
 {

Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageNode.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageNode.h 
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageNode.h 
2009-11-17 22:04:46 UTC (rev 34102)
@@ -13,12 +13,13 @@
 #include <util/SinglyLinkedList.h>
 
 
+class Package;
 class PackageDirectory;
 
 
 class PackageNode : public SinglyLinkedListLinkImpl<PackageNode> {
 public:
-                                                               
PackageNode(mode_t mode);
+                                                               
PackageNode(Package* package, mode_t mode);
        virtual                                         ~PackageNode();
 
                        PackageDirectory*       Parent() const  { return 
fParent; }
@@ -27,6 +28,9 @@
        virtual status_t                        Init(PackageDirectory* parent,
                                                                        const 
char* name);
 
+       virtual status_t                        VFSInit(dev_t deviceID, ino_t 
nodeID);
+       virtual void                            VFSUninit();
+
                        mode_t                          Mode() const            
        { return fMode; }
 
                        uid_t                           UserID() const          
        { return fUserID; }
@@ -43,6 +47,7 @@
        virtual off_t                           FileSize() const;
 
 protected:
+                       Package*                        fPackage;
                        PackageDirectory*       fParent;
                        char*                           fName;
                        mode_t                          fMode;

Modified: 
haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageSymlink.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageSymlink.cpp    
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageSymlink.cpp    
2009-11-17 22:04:46 UTC (rev 34102)
@@ -10,9 +10,9 @@
 #include <string.h>
 
 
-PackageSymlink::PackageSymlink(mode_t mode)
+PackageSymlink::PackageSymlink(Package* package, mode_t mode)
        :
-       PackageLeafNode(mode),
+       PackageLeafNode(package, mode),
        fSymlinkPath(NULL)
 {
 }

Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageSymlink.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageSymlink.h      
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/PackageSymlink.h      
2009-11-17 22:04:46 UTC (rev 34102)
@@ -11,7 +11,7 @@
 
 class PackageSymlink : public PackageLeafNode {
 public:
-                                                               
PackageSymlink(mode_t mode);
+                                                               
PackageSymlink(Package* package, mode_t mode);
        virtual                                         ~PackageSymlink();
 
                        status_t                        SetSymlinkPath(const 
char* path);

Modified: haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Volume.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Volume.cpp    
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/Volume.cpp    
2009-11-17 22:04:46 UTC (rev 34102)
@@ -141,10 +141,11 @@
                PackageNode* node;
                if (S_ISREG(mode)) {
                        // file
-                       node = new(std::nothrow) PackageFile(mode, 
entry->Data());
+                       node = new(std::nothrow) PackageFile(fPackage, mode, 
entry->Data());
                } else if (S_ISLNK(mode)) {
                        // symlink
-                       PackageSymlink* symlink = new(std::nothrow) 
PackageSymlink(mode);
+                       PackageSymlink* symlink = new(std::nothrow) 
PackageSymlink(
+                               fPackage, mode);
                        if (symlink == NULL)
                                RETURN_ERROR(B_NO_MEMORY);
 
@@ -157,7 +158,7 @@
                        node = symlink;
                } else if (S_ISDIR(mode)) {
                        // directory
-                       node = new(std::nothrow) PackageDirectory(mode);
+                       node = new(std::nothrow) PackageDirectory(fPackage, 
mode);
                } else
                        RETURN_ERROR(B_BAD_DATA);
 
@@ -476,16 +477,12 @@
 Volume::_LoadPackage(Package* package)
 {
        // open package file
-       int fd = openat(package->Domain()->DirectoryFD(), package->Name(),
-               O_RDONLY);
-       if (fd < 0) {
-               ERROR("Failed to open package file \"%s\"\n", package->Name());
-               return errno;
-       }
-// TODO: Verify that it's still the same file.
-       FDCloser fdCloser(fd);
+       int fd = package->Open();
+       if (fd < 0)
+               RETURN_ERROR(fd);
+       PackageCloser packageCloser(package);
 
-       // open package
+       // initialize package reader
        PackageLoaderErrorOutput errorOutput(package);
        PackageReader packageReader(&errorOutput);
        status_t error = packageReader.Init(fd, false);

Modified: 
haiku/trunk/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp  
2009-11-17 21:50:48 UTC (rev 34101)
+++ haiku/trunk/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp  
2009-11-17 22:04:46 UTC (rev 34102)
@@ -58,6 +58,43 @@
 }
 
 
+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
 
 
@@ -171,9 +208,16 @@
        Node* node = volume->FindNode(vnid);
        if (node == NULL)
                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;
        *_type = node->Mode() & S_IFMT;
        *_flags = 0;
@@ -191,12 +235,28 @@
        FUNCTION("volume: %p, node: %p\n", volume, node);
        TOUCH(volume);
 
+       NodeWriteLocker nodeLocker(node);
+       node->VFSUninit();
+       nodeLocker.Unlock();
+
        node->ReleaseReference();
 
        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
 
 
@@ -238,39 +298,8 @@
        FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID());
        TOUCH(volume);
 
-       // write access requested?
-       if (mode & W_OK)
-               return B_READ_ONLY_DEVICE;
-
        NodeReadLocker nodeLocker(node);
-
-       // 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;
+       return check_access(node, mode);
 }
 
 
@@ -304,6 +333,17 @@
 // #pragma mark - Files
 
 
+struct FileCookie {
+       int     openMode;
+
+       FileCookie(int openMode)
+               :
+               openMode(openMode)
+       {
+       }
+};
+
+
 static status_t
 packagefs_open(fs_volume* fsVolume, fs_vnode* fsNode, int openMode,
        void** _cookie)
@@ -314,11 +354,27 @@
        FUNCTION("volume: %p, node: %p (%lld), openMode %#x\n", volume, node,
                node->ID(), openMode);
        TOUCH(volume);
-       TOUCH(node);
 
-// TODO: Implement it for real!
-       *_cookie = NULL;
+       NodeReadLocker nodeLocker(node);
 
+       // 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;
 }
 
@@ -331,17 +387,40 @@
 
 
 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;
 }
 
 
 static status_t
-packagefs_read(fs_volume* fs, fs_vnode* _node, void* cookie, off_t pos,
-       void* buffer, size_t* bufferSize)
+packagefs_read(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie,
+       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 @@
        NULL,   // read_pages,
        NULL,   // write_pages,
 
-       NULL,   // io()
+       NULL,   // &packagefs_io,
        NULL,   // cancel_io()
 
        NULL,   // get_file_map,


Other related posts:

  • » [haiku-commits] r34102 - haiku/trunk/src/add-ons/kernel/file_systems/packagefs - ingo_weinhold