[haiku-commits] r36148 - haiku/trunk/src/add-ons/kernel/file_systems/ext2

  • From: revol@xxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 11 Apr 2010 15:18:05 +0200 (CEST)

Author: mmu_man
Date: 2010-04-11 15:18:05 +0200 (Sun, 11 Apr 2010)
New Revision: 36148
Changeset: http://dev.haiku-os.org/changeset/36148/haiku

Modified:
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/Inode.cpp
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/Inode.h
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/Jamfile
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/ext2.h
   haiku/trunk/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp
Log:
Partial implementation for attribute support. Currently listattr successfully 
lists attributes on files.


Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/Inode.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/Inode.cpp  2010-04-11 
13:15:54 UTC (rev 36147)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/Inode.cpp  2010-04-11 
13:18:05 UTC (rev 36148)
@@ -7,11 +7,12 @@
 #include "Inode.h"
 
 #include <fs_cache.h>
+#include <string.h>
 
 #include "CachedBlock.h"
 
 
-//#define TRACE_EXT2
+#define TRACE_EXT2
 #ifdef TRACE_EXT2
 #      define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
 #else
@@ -25,7 +26,8 @@
        fID(id),
        fCache(NULL),
        fMap(NULL),
-       fNode(NULL)
+       fNode(NULL),
+       fAttributesBlock(NULL)
 {
        rw_lock_init(&fLock, "ext2 inode");
 
@@ -53,6 +55,11 @@
        file_cache_delete(FileCache());
        file_map_delete(Map());
 
+       if (fAttributesBlock) {
+               uint32 block = 
B_LENDIAN_TO_HOST_INT32(Node().file_access_control);
+               block_cache_put(fVolume->BlockCache(), block);
+       }
+
        if (fNode != NULL) {
                uint32 block;
                if (fVolume->GetInodeBlock(ID(), block) == B_OK)
@@ -206,3 +213,30 @@
        return file_cache_read(FileCache(), NULL, pos, buffer, _length);
 }
 
+
+status_t
+Inode::AttributeBlockReadAt(off_t pos, uint8* buffer, size_t* _length)
+{
+       size_t length = *_length;
+
+       if (!fAttributesBlock) {
+               uint32 block = 
B_LENDIAN_TO_HOST_INT32(Node().file_access_control);
+
+               if (block == 0)
+                       return B_ENTRY_NOT_FOUND;
+
+               TRACE("inode %Ld attributes at block %lu\n", ID(), block);
+               fAttributesBlock = (ext2_xattr_header*)block_cache_get(
+                       GetVolume()->BlockCache(), block);
+       }
+
+       if (!fAttributesBlock)
+               return B_ENTRY_NOT_FOUND;
+
+       if (pos < 0LL || ((uint32)pos + length) > GetVolume()->BlockSize())
+               return ERANGE;
+
+       memcpy(buffer, ((uint8 *)fAttributesBlock) + (uint32)pos, length);
+       *_length = length;
+       return B_NO_ERROR;
+}

Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/Inode.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/Inode.h    2010-04-11 
13:15:54 UTC (rev 36147)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/Inode.h    2010-04-11 
13:18:05 UTC (rev 36148)
@@ -49,6 +49,9 @@
                        status_t        FindBlock(off_t offset, uint32& block);
                        status_t        ReadAt(off_t pos, uint8 *buffer, size_t 
*length);
 
+                       status_t        AttributeBlockReadAt(off_t pos, uint8 
*buffer,
+                                                       size_t *length);
+
                        ext2_inode&     Node() { return *fNode; }
 
                        void*           FileCache() const { return fCache; }
@@ -66,6 +69,7 @@
        void*                           fCache;
        void*                           fMap;
        ext2_inode*                     fNode;
+       ext2_xattr_header*      fAttributesBlock;
 };
 
 #endif // INODE_H

Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/Jamfile
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/Jamfile    2010-04-11 
13:15:54 UTC (rev 36147)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/Jamfile    2010-04-11 
13:18:05 UTC (rev 36148)
@@ -13,6 +13,7 @@
 KernelAddon ext2 :
        Volume.cpp
        Inode.cpp
+       AttributeIterator.cpp
        DirectoryIterator.cpp
 
        kernel_interface.cpp

Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/ext2.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/ext2.h     2010-04-11 
13:15:54 UTC (rev 36147)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/ext2.h     2010-04-11 
13:18:05 UTC (rev 36148)
@@ -10,6 +10,7 @@
 
 #include <ByteOrder.h>
 #include <fs_interface.h>
+#include <KernelExport.h>
 
 
 #define EXT2_SUPER_BLOCK_OFFSET        1024
@@ -286,6 +287,78 @@
 #define EXT2_TYPE_SOCKET               6
 #define EXT2_TYPE_SYMLINK              7
 
+#define EXT2_XATTR_MAGIC               0xea020000
+#define EXT2_XATTR_ROUND               ((1 << 2) - 1)
+#define EXT2_XATTR_NAME_LENGTH 255
+
+#define EXT2_XATTR_INDEX_USER  1
+
+struct ext2_xattr_header {
+       uint32  magic;
+       uint32  refcount;
+       uint32  blocks;         // must be 1 for ext2
+       uint32  hash;
+       uint32  reserved[4];    // zero
+
+       bool IsValid() const
+       {
+               return B_LENDIAN_TO_HOST_INT32(magic) == EXT2_XATTR_MAGIC
+                       && B_LENDIAN_TO_HOST_INT32(blocks) == 1
+                       && refcount <= 1024;
+       }
+
+       void Dump() const {
+               for (int i = 0; i < Length(); i++)
+                       dprintf("%02x ", ((uint8 *)this)[i]);
+               dprintf("\n");
+       }
+
+       static size_t Length()
+       {
+               return sizeof(ext2_xattr_header);
+       }
+};
+
+struct ext2_xattr_entry {
+       uint8   name_length;
+       uint8   name_index;
+       uint16  value_offset;
+       uint32  value_block;    // must be zero for ext2
+       uint32  value_size;
+       uint32  hash;
+       char    name[EXT2_XATTR_NAME_LENGTH];
+
+       uint8 NameLength() const { return name_length; }
+       uint8 NameIndex() const { return name_index; }
+       uint16 ValueOffset() const { return
+                       B_LENDIAN_TO_HOST_INT16(value_offset); }
+       uint32 ValueSize() const { return
+                       B_LENDIAN_TO_HOST_INT32(value_size); }
+
+       // padded sizes
+       uint32 Length() const { return (MinimumSize() + NameLength()
+               + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND; }
+
+       bool IsValid() const
+       {
+               return NameLength() > 0 && value_block == 0;
+                       // There is no maximum size, as the last entry spans 
until the
+                       // end of the block
+       }
+
+       void Dump(bool full=false) const {
+               for (int i = 0; i < (full ? sizeof(this) : MinimumSize()); i++)
+                       dprintf("%02x ", ((uint8 *)this)[i]);
+               dprintf("\n");
+       }
+
+       static size_t MinimumSize()
+       {
+               return sizeof(ext2_xattr_entry) - EXT2_XATTR_NAME_LENGTH;
+       }
+} _PACKED;
+
+
 extern fs_volume_ops gExt2VolumeOps;
 extern fs_vnode_ops gExt2VnodeOps;
 

Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp       
2010-04-11 13:15:54 UTC (rev 36147)
+++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp       
2010-04-11 13:18:05 UTC (rev 36148)
@@ -11,11 +11,20 @@
 #include <fs_cache.h>
 #include <fs_info.h>
 
+#include "AttributeIterator.h"
 #include "DirectoryIterator.h"
 #include "ext2.h"
 #include "Inode.h"
 
 
+//#define TRACE_EXT2
+#ifdef TRACE_EXT2
+#      define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
+#else
+#      define TRACE(x...) ;
+#endif
+
+
 #define EXT2_IO_SIZE   65536
 
 
@@ -497,6 +506,198 @@
 }
 
 
+static status_t 
+ext2_open_attr_dir(fs_volume *_volume, fs_vnode *_node, void **_cookie)
+{
+       Inode* inode = (Inode*)_node->private_node;
+       Volume* volume = (Volume*)_volume->private_volume;
+       TRACE("%s()\n", __FUNCTION__);
+
+       if (!(volume->SuperBlock().CompatibleFeatures() & 
EXT2_FEATURE_EXT_ATTR))
+               return ENOSYS;
+
+       // on directories too ?
+       if (!inode->IsFile())
+               return EINVAL;
+
+       AttributeIterator* iterator = new(std::nothrow) 
AttributeIterator(inode);
+       if (iterator == NULL)
+               return B_NO_MEMORY;
+
+       *_cookie = iterator;
+       return B_OK;
+}
+
+static status_t
+ext2_close_attr_dir(fs_volume* _volume, fs_vnode* _node, void* cookie)
+{
+       TRACE("%s()\n", __FUNCTION__);
+       return B_OK;
+}
+
+
+static status_t
+ext2_free_attr_dir_cookie(fs_volume* _volume, fs_vnode* _node, void* _cookie)
+{
+       TRACE("%s()\n", __FUNCTION__);
+       delete (AttributeIterator *)_cookie;
+       return B_OK;
+}
+
+
+static status_t
+ext2_read_attr_dir(fs_volume* _volume, fs_vnode* _node,
+                               void* _cookie, struct dirent* dirent, size_t 
bufferSize,
+                               uint32* _num)
+{
+       Inode* inode = (Inode*)_node->private_node;
+       AttributeIterator *iterator = (AttributeIterator *)_cookie;
+       TRACE("%s()\n", __FUNCTION__);
+
+       size_t length = bufferSize;
+       status_t status = iterator->GetNext(dirent->d_name, &length);
+       if (status == B_ENTRY_NOT_FOUND) {
+               *_num = 0;
+               return B_OK;
+       } else if (status != B_OK)
+               return status;
+
+       Volume* volume = (Volume*)_volume->private_volume;
+
+       dirent->d_dev = volume->ID();
+       dirent->d_ino = inode->ID();
+       dirent->d_reclen = sizeof(struct dirent) + length;
+
+       *_num = 1;
+       return B_OK;
+}
+
+
+static status_t
+ext2_rewind_attr_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie)
+{
+       AttributeIterator *iterator = (AttributeIterator *)_cookie;
+       TRACE("%s()\n", __FUNCTION__);
+       return iterator->Rewind();
+}
+
+
+       /* attribute operations */
+static status_t
+ext2_create_attr(fs_volume* _volume, fs_vnode* _node,
+       const char* name, uint32 type, int openMode, void** _cookie)
+{
+       return EROFS;
+}
+
+
+static status_t
+ext2_open_attr(fs_volume* _volume, fs_vnode* _node, const char* name,
+       int openMode, void** _cookie)
+{
+       TRACE("%s()\n", __FUNCTION__);
+       if ((openMode & O_RWMASK) != O_RDONLY)
+               return EROFS;
+
+       Inode* inode = (Inode*)_node->private_node;
+       Volume* volume = (Volume*)_volume->private_volume;
+
+       if (!(volume->SuperBlock().CompatibleFeatures() & 
EXT2_FEATURE_EXT_ATTR))
+               return ENOSYS;
+
+       // on directories too ?
+       if (!inode->IsFile())
+               return EINVAL;
+
+       ext2_xattr_entry *entry = new ext2_xattr_entry;
+
+       AttributeIterator i(inode);
+       status_t status = i.Find(name, entry);
+       if (status == B_OK) {
+               entry->Dump();
+               *_cookie = entry;
+               return B_OK;
+       }
+       
+       delete entry;
+       return status;
+}
+
+
+static status_t
+ext2_close_attr(fs_volume* _volume, fs_vnode* _node,
+       void* cookie)
+{
+       return B_OK;
+}
+
+
+static status_t
+ext2_free_attr_cookie(fs_volume* _volume, fs_vnode* _node,
+       void* cookie)
+{
+       ext2_xattr_entry *entry = (ext2_xattr_entry *)cookie;
+
+       delete entry;
+       return B_OK;
+}
+
+
+static status_t
+ext2_read_attr(fs_volume* _volume, fs_vnode* _node, void* cookie,
+       off_t pos, void* buffer, size_t* length)
+{
+       return ENOSYS;
+}
+
+
+static status_t
+ext2_write_attr(fs_volume* _volume, fs_vnode* _node, void* cookie,
+       off_t pos, const void* buffer, size_t* length)
+{
+       return EROFS;
+}
+
+
+
+static status_t
+ext2_read_attr_stat(fs_volume* _volume, fs_vnode* _node,
+       void* cookie, struct stat* stat)
+{
+       ext2_xattr_entry *entry = (ext2_xattr_entry *)cookie;
+
+       stat->st_type = B_RAW_TYPE;
+       stat->st_size = entry->ValueSize();
+       TRACE("%s: st_size %d\n", __FUNCTION__, stat->st_size);
+
+       return B_OK;
+}
+
+
+static status_t
+ext2_write_attr_stat(fs_volume* _volume, fs_vnode* _node,
+       void* cookie, const struct stat* stat, int statMask)
+{
+       return EROFS;
+}
+
+
+static status_t
+ext2_rename_attr(fs_volume* _volume, fs_vnode* fromVnode,
+       const char* fromName, fs_vnode* toVnode, const char* toName)
+{
+       return ENOSYS;
+}
+
+
+static status_t
+ext2_remove_attr(fs_volume* _volume, fs_vnode* vnode,
+       const char* name)
+{
+       return ENOSYS;
+}
+
+
 fs_volume_ops gExt2VolumeOps = {
        &ext2_unmount,
        &ext2_read_fs_info,
@@ -556,7 +757,25 @@
        &ext2_read_dir,
        &ext2_rewind_dir,
 
-       NULL,
+       /* attribute directory operations */
+       &ext2_open_attr_dir,
+       &ext2_close_attr_dir,
+       &ext2_free_attr_dir_cookie,
+       &ext2_read_attr_dir,
+       &ext2_rewind_attr_dir,
+
+       /* attribute operations */
+       NULL, //&ext2_create_attr,
+       &ext2_open_attr,
+       &ext2_close_attr,
+       &ext2_free_attr_cookie,
+       NULL, //&ext2_read_attr,
+       NULL, //&ext2_write_attr,
+       &ext2_read_attr_stat,
+       NULL, //&ext2_write_attr_stat,
+       NULL, //&ext2_rename_attr,
+       NULL, //&ext2_remove_attr,
+       
 };
 
 static file_system_module_info sExt2FileSystem = {


Other related posts: