[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: