diff --git a/src/add-ons/kernel/file_systems/ext2/Attribute.cpp b/src/add-ons/kernel/file_systems/ext2/Attribute.cpp new file mode 100644 index 0000000000..036d68954d --- /dev/null +++ b/src/add-ons/kernel/file_systems/ext2/Attribute.cpp @@ -0,0 +1,364 @@ +/* + * Copyright 2010, Jérôme Duval, korli@users.berlios.de. + * Copyright 2010, François Revol, . + * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. + * This file may be used under the terms of the MIT License. + */ + +//! connection between pure inode and kernel_interface attributes + + +#include "Attribute.h" +#include "Utility.h" + +#include + + +//#define TRACE_EXT2 +#ifdef TRACE_EXT2 +# define TRACE(x...) dprintf("\33[34mext2:\33[0m " x) +#else +# define TRACE(x...) ; +#endif + + +Attribute::Attribute(Inode* inode) + : + fVolume(inode->GetVolume()), + fBlock(fVolume), + fInode(inode), + fBodyEntry(NULL), + fBlockEntry(NULL), + fName(NULL) +{ + +} + + +Attribute::Attribute(Inode* inode, attr_cookie* cookie) + : + fVolume(inode->GetVolume()), + fBlock(fVolume), + fInode(inode), + fBodyEntry(NULL), + fBlockEntry(NULL), + fName(NULL) +{ + Find(cookie->name); +} + + +Attribute::~Attribute() +{ + Put(); +} + + +status_t +Attribute::InitCheck() +{ + return (fBodyEntry != NULL || fBlockEntry != NULL) ? B_OK : B_NO_INIT; +} + + +status_t +Attribute::CheckAccess(const char* name, int openMode) +{ + return fInode->CheckPermissions(open_mode_to_access(openMode) + | (openMode & O_TRUNC ? W_OK : 0)); +} + + +status_t +Attribute::Find(const char* name) +{ + return _Find(name, -1); +} + + +status_t +Attribute::Find(int32 index) +{ + return _Find(NULL, index); +} + + +status_t +Attribute::GetName(char* name, size_t* _nameLength) +{ + if (fBodyEntry == NULL && fBlockEntry == NULL) + return B_NO_INIT; + if (fBodyEntry != NULL) + return _PrefixedName(fBodyEntry, name, _nameLength); + else + return _PrefixedName(fBlockEntry, name, _nameLength); +} + + +void +Attribute::Put() +{ + if (fBodyEntry != NULL) { + recursive_lock_unlock(&fInode->SmallDataLock()); + fBlock.Unset(); + fBodyEntry = NULL; + } + + if (fBlockEntry != NULL) { + fBlock.Unset(); + fBlockEntry = NULL; + } +} + + +status_t +Attribute::Create(const char* name, type_code type, int openMode, + attr_cookie** _cookie) +{ + status_t status = CheckAccess(name, openMode); + if (status < B_OK) + return status; + + attr_cookie* cookie = new(std::nothrow) attr_cookie; + if (cookie == NULL) + return B_NO_MEMORY; + + fName = name; + + // initialize the cookie + strlcpy(cookie->name, fName, B_ATTR_NAME_LENGTH); + cookie->type = type; + cookie->open_mode = openMode; + cookie->create = true; + + if (Find(name) == B_OK) { + // attribute already exists + if ((openMode & O_TRUNC) != 0) + _Truncate(); + } + *_cookie = cookie; + return B_OK; +} + + +status_t +Attribute::Open(const char* name, int openMode, attr_cookie** _cookie) +{ + TRACE("Open\n"); + status_t status = CheckAccess(name, openMode); + if (status < B_OK) + return status; + + status = Find(name); + if (status < B_OK) + return status; + + attr_cookie* cookie = new(std::nothrow) attr_cookie; + if (cookie == NULL) + return B_NO_MEMORY; + + // initialize the cookie + strlcpy(cookie->name, fName, B_ATTR_NAME_LENGTH); + cookie->open_mode = openMode; + cookie->create = false; + + // Should we truncate the attribute? + if ((openMode & O_TRUNC) != 0) + _Truncate(); + + *_cookie = cookie; + return B_OK; +} + + +status_t +Attribute::Stat(struct stat& stat) +{ + TRACE("Stat\n"); + if (fBodyEntry == NULL && fBlockEntry == NULL) + return B_NO_INIT; + + stat.st_type = B_RAW_TYPE; + + if (fBodyEntry != NULL) + stat.st_size = fBodyEntry->ValueSize(); + else if (fBlockEntry != NULL) + stat.st_size = fBlockEntry->ValueSize(); + + return B_OK; +} + + +status_t +Attribute::Read(attr_cookie* cookie, off_t pos, uint8* buffer, size_t* _length) +{ + if (fBodyEntry == NULL && fBlockEntry == NULL) + return B_NO_INIT; + + if (pos < 0LL) + return ERANGE; + + size_t length = *_length; + const uint8* start = (uint8 *)fBlock.Block(); + if (fBlockEntry != NULL) { + pos += fBlockEntry->ValueOffset(); + if (((uint32)pos + length) > fVolume->BlockSize() + || length > fBlockEntry->ValueSize()) + return ERANGE; + } else { + start += fVolume->InodeBlockIndex(fInode->ID()) * fVolume->InodeSize(); + const uint8* end = start + fVolume->InodeSize(); + start += EXT2_INODE_NORMAL_SIZE + fInode->Node().ExtraInodeSize() + + sizeof(uint32); + pos += fBodyEntry->ValueOffset(); + if ((pos + length) > (end - start) || length > fBodyEntry->ValueSize()) + return ERANGE; + } + memcpy(buffer, start + (uint32)pos, length); + + *_length = length; + return B_OK; +} + + +status_t +Attribute::Write(Transaction& transaction, attr_cookie* cookie, off_t pos, + const uint8* buffer, size_t* _length, bool* _created) +{ + if (!cookie->create && fBodyEntry == NULL && fBlockEntry == NULL) + return B_NO_INIT; + + // TODO: Implement + return B_ERROR; +} + + +status_t +Attribute::_Truncate() +{ + // TODO: Implement + return B_ERROR; +} + + +status_t +Attribute::_Find(const char* name, int32 index) +{ + Put(); + + fName = name; + + // try to find it in the small data region + if (fInode->HasExtraAttributes() + && recursive_lock_lock(&fInode->SmallDataLock()) == B_OK) { + uint32 block; + fVolume->GetInodeBlock(fInode->ID(), block); + + if (block != 0) { + fBlock.SetTo(block); + const uint8* start = fBlock.Block() + + fVolume->InodeBlockIndex(fInode->ID()) * fVolume->InodeSize(); + const uint8* end = start + fVolume->InodeSize(); + int32 count = 0; + if (_FindAttributeBody(start + EXT2_INODE_NORMAL_SIZE + + fInode->Node().ExtraInodeSize(), end, name, index, &count, + &fBodyEntry) == B_OK) + return B_OK; + index -= count; + } + + recursive_lock_unlock(&fInode->SmallDataLock()); + fBlock.Unset(); + } + + // then, search in the attribute directory + if (fInode->Node().ExtendedAttributesBlock() != 0) { + fBlock.SetTo(fInode->Node().ExtendedAttributesBlock()); + if (_FindAttributeBlock(fBlock.Block(), + fBlock.Block() + fVolume->BlockSize(), name, index, NULL, + &fBlockEntry) == B_OK) + return B_OK; + fBlock.Unset(); + } + + return B_ENTRY_NOT_FOUND; +} + + +status_t +Attribute::_FindAttributeBody(const uint8* start, const uint8* end, + const char* name, int32 index, int32 *count, ext2_xattr_entry** _entry) +{ + TRACE("_FindAttributeBody %p %p %s\n", start, end, name); + if (*((uint32*)start) != EXT2_XATTR_MAGIC) + return B_BAD_DATA; + return _FindAttribute(start + sizeof(uint32), end, name, index, count, + _entry); +} + + +status_t +Attribute::_FindAttributeBlock(const uint8* start, const uint8* end, const char* name, + int32 index, int32 *count, ext2_xattr_entry** _entry) +{ + TRACE("_FindAttributeBlock %p %p %s\n", start, end, name); + ext2_xattr_header *header = (ext2_xattr_header*)start; + if (!header->IsValid()) + return B_BAD_DATA; + + return _FindAttribute(start + sizeof(ext2_xattr_header), end, name, index, + count, _entry); +} + + +status_t +Attribute::_FindAttribute(const uint8* start, const uint8* end, const char* name, + int32 index, int32 *count, ext2_xattr_entry** _entry) +{ + TRACE("_FindAttribute %p %p %s\n", start, end, name); + char buffer[EXT2_XATTR_NAME_LENGTH]; + + int32 i = 0; + while (start < end) { + ext2_xattr_entry* entry = (ext2_xattr_entry*)start; + if (!entry->IsValid()) + break; + + size_t length = EXT2_XATTR_NAME_LENGTH; + if ((name != NULL && _PrefixedName(entry, buffer, &length) == B_OK + && strncmp(name, buffer, length) == 0) || index == i) { + *_entry = entry; + return B_OK; + } + start += entry->Length(); + i++; + } + + if (count != NULL) + *count = i; + return B_ENTRY_NOT_FOUND; +} + + +status_t +Attribute::_PrefixedName(ext2_xattr_entry* entry, char* _name, size_t* _nameLength) +{ + const char *indexNames[] = { "0", "user" }; + size_t l = 0; + + if (entry->NameIndex() < ((sizeof(indexNames) / sizeof(indexNames[0])))) + l = snprintf(_name, *_nameLength, "%s.%s.%.*s", + "linux", indexNames[entry->NameIndex()], entry->NameLength(), + entry->name); + else + l = snprintf(_name, *_nameLength, "%s.%d.%.*s", + "linux", entry->NameIndex(), entry->NameLength(), entry->name); + if (l < 1 || l > *_nameLength - 1) + return ENOBUFS; + + *_nameLength = l + 1; + _name[l] = '\0'; + + return B_OK; +} + diff --git a/src/add-ons/kernel/file_systems/ext2/Attribute.h b/src/add-ons/kernel/file_systems/ext2/Attribute.h new file mode 100644 index 0000000000..7f360c6549 --- /dev/null +++ b/src/add-ons/kernel/file_systems/ext2/Attribute.h @@ -0,0 +1,72 @@ +/* + * Copyright 2010, Jérôme Duval, korli@users.berlios.de. + * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. + * This file may be used under the terms of the MIT License. + */ +#ifndef ATTRIBUTE_H +#define ATTRIBUTE_H + + +#include "CachedBlock.h" +#include "Inode.h" + + +struct attr_cookie { + char name[B_ATTR_NAME_LENGTH]; + uint32 type; + int open_mode; + bool create; +}; + + +class Attribute { +public: + Attribute(Inode* inode); + Attribute(Inode* inode, attr_cookie* cookie); + ~Attribute(); + + status_t InitCheck(); + status_t CheckAccess(const char* name, int openMode); + + status_t Find(const char* name); + status_t Find(int32 index); + status_t GetName(char* name, size_t* _nameLength); + void Put(); + + status_t Create(const char* name, type_code type, + int openMode, attr_cookie** _cookie); + status_t Open(const char* name, int openMode, + attr_cookie** _cookie); + + status_t Stat(struct stat& stat); + + status_t Read(attr_cookie* cookie, off_t pos, uint8* buffer, + size_t* _length); + status_t Write(Transaction& transaction, attr_cookie* cookie, + off_t pos, const uint8* buffer, + size_t* _length, bool* _created); + +private: + status_t _Truncate(); + status_t _Find(const char* name, int32 index); + status_t _FindAttributeBody(const uint8* start, const uint8* end, + const char* name, int32 index, int32 *count, + ext2_xattr_entry** entry); + status_t _FindAttributeBlock(const uint8* start, const uint8* end, + const char* name, int32 index, int32 *count, + ext2_xattr_entry** entry); + status_t _FindAttribute(const uint8* start, const uint8* end, + const char* name, int32 index, int32 *count, + ext2_xattr_entry** entry); + status_t _PrefixedName(ext2_xattr_entry* entry, char* _name, + size_t* _nameLength); + + ::Volume* fVolume; + CachedBlock fBlock; + Inode* fInode; + ext2_xattr_entry* fBodyEntry; + ext2_xattr_entry* fBlockEntry; + const char* fName; +}; + +#endif // ATTRIBUTE_H diff --git a/src/add-ons/kernel/file_systems/ext2/AttributeIterator.cpp b/src/add-ons/kernel/file_systems/ext2/AttributeIterator.cpp deleted file mode 100644 index cedd45395c..0000000000 --- a/src/add-ons/kernel/file_systems/ext2/AttributeIterator.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2010, François Revol, . - * This file may be used under the terms of the MIT License. - */ - - -#include "AttributeIterator.h" - -#include -#include -#include - -#include "Inode.h" - - -//#define TRACE_EXT2 -#ifdef TRACE_EXT2 -# define TRACE(x...) dprintf("\33[34mext2:\33[0m " x) -#else -# define TRACE(x...) ; -#endif - - -AttributeIterator::AttributeIterator(Inode* inode) - : - fInode(inode), - fOffset(0) -{ - TRACE("AttributeIterator::%s()\n", __FUNCTION__); - ext2_xattr_header header; - size_t length = sizeof(header); - if (fInode->AttributeBlockReadAt(fOffset, (uint8*)&header, &length) == B_OK - && length == sizeof(header)) { - //header.Dump(); - if (header.IsValid()) { - fOffset = sizeof(header); - TRACE("AttributeIterator::%s: header valid\n", __FUNCTION__); - } - } -} - - -AttributeIterator::~AttributeIterator() -{ -} - - -status_t -AttributeIterator::GetNext(char* name, size_t* _nameLength, ext2_xattr_entry *_entry) -{ - TRACE("AttributeIterator::%s()\n", __FUNCTION__); - ext2_xattr_entry internalEntry; - if (_entry == NULL) - _entry = &internalEntry; - - TRACE("AttributeIterator::%s: fOffset %Ld e.MinSize %d BlockSize %d\n", - __FUNCTION__, fOffset, _entry->MinimumSize(), fInode->GetVolume()->BlockSize()); - - if (fOffset + _entry->MinimumSize() >= fInode->GetVolume()->BlockSize()) - return B_ENTRY_NOT_FOUND; - - size_t length = ext2_xattr_entry::MinimumSize(); - status_t status = fInode->AttributeBlockReadAt(fOffset, (uint8*)_entry, &length); - TRACE("AttributeIterator::%s:AttributeBlockReadAt(%Ld): 0x%08lx len %d\n", - __FUNCTION__, fOffset, status, length); - //_entry->Dump(); - - if (status != B_OK) - return status; - if (length < ext2_xattr_entry::MinimumSize()) - return B_ENTRY_NOT_FOUND; - TRACE("AttributeIterator::%s:AttributeBlockReadAt(%Ld): namelen %d %cvalid\n", - __FUNCTION__, fOffset, _entry->NameLength(), _entry->IsValid() ? ' ' : '!'); - if (!_entry->IsValid()) - return B_BAD_DATA; - - TRACE("xattr block offset %Ld: entry ino %Lu, length %u, name length %u," - " index %d\n", - fOffset, fInode->ID(), _entry->Length(), _entry->NameLength(), - _entry->NameIndex()); - - // read name - - length = _entry->NameLength(); - status = fInode->AttributeBlockReadAt(fOffset + ext2_xattr_entry::MinimumSize(), - (uint8*)_entry->name, &length); - TRACE("AttributeIterator::%s:AttributeBlockReadAt(%Ld): 0x%08lx len %d\n", - __FUNCTION__, fOffset + ext2_xattr_entry::MinimumSize(), - status, length); - - if (length < 1) - status = ENOENT; - - if (status == B_OK) { - const char *indexNames[] = { "0", "user" }; - - size_t l; - - TRACE("AttributeIterator::%s: len %d nlen %d\n", - __FUNCTION__, length, *_nameLength); - if (_entry->NameIndex() < ((sizeof(indexNames) / sizeof(indexNames[0])))) - l = snprintf(name, *_nameLength, "%s.%s.%.*s", - "linux", indexNames[_entry->NameIndex()], length, _entry->name); - else - l = snprintf(name, *_nameLength, "%s.%d.%.*s", - "linux", _entry->NameIndex(), length, _entry->name); - if (l < 1 || l > *_nameLength - 1) - status = ENOBUFS; - else { - *_nameLength = l + 1; - name[l] = '\0'; - } - - TRACE("AttributeIterator::%s: name %.*s len %d nlen %d\n", - __FUNCTION__, *_nameLength, name, length, *_nameLength); - - fOffset += _entry->Length(); - } - - return status; -} - - -status_t -AttributeIterator::Rewind() -{ - TRACE("AttributeIterator::%s()\n", __FUNCTION__); - fOffset = sizeof(ext2_xattr_header); - return B_OK; -} - - -status_t -AttributeIterator::Find(const char* name, ext2_xattr_entry *_entry) -{ - char buffer[EXT2_XATTR_NAME_LENGTH]; - size_t length = sizeof(buffer); - status_t err; - while ((err = GetNext(buffer, &length, _entry)) == B_OK) { - TRACE("AttributeIterator::%s: next is '%.*s'\n", __FUNCTION__, length > 0 ? length : 0, buffer); - _entry->Dump(); - if (strncmp(name, buffer, length) == 0) - return B_OK; - length = sizeof(buffer); - } - return ENOENT; -} - - -void -AttributeIterator::PrefixForNameIndex(uint8 index, char* prefix, size_t *length) -{ - const char *indexNames[] = { "user" }; - if (index < (sizeof(indexNames) / sizeof(indexNames[0]))) - *length = strlcpy(prefix, indexNames[index], *length); - else { - *length = strlcpy(prefix, "unknown", *length); - } -} - - -status_t -AttributeIterator::NameBufferAppend(const char* str, char *&buffer, size_t *length) -{ - size_t done; - done = strlcpy(buffer, str, *length); - *length = done > 0 ? done - 1 : 0; - buffer += done; - return B_OK; -} - diff --git a/src/add-ons/kernel/file_systems/ext2/AttributeIterator.h b/src/add-ons/kernel/file_systems/ext2/AttributeIterator.h deleted file mode 100644 index 47a444de64..0000000000 --- a/src/add-ons/kernel/file_systems/ext2/AttributeIterator.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2010, François Revol, . - * This file may be used under the terms of the MIT License. - */ -#ifndef ATTRIBUTE_ITERATOR_H -#define ATTRIBUTE_ITERATOR_H - - -#include - -#include "ext2.h" - -class Inode; - -class AttributeIterator { -public: - AttributeIterator(Inode* inode); - ~AttributeIterator(); - - status_t InitCheck() const { return (fOffset - >= sizeof(ext2_xattr_header)) ? B_OK : B_ENTRY_NOT_FOUND; } - - status_t GetNext(char* name, size_t* _nameLength, ext2_xattr_entry *_entry=NULL); - - status_t Rewind(); - - status_t Find(const char* name, ext2_xattr_entry *_entry); - -private: - AttributeIterator(const AttributeIterator&); - AttributeIterator &operator=(const AttributeIterator&); - // no implementation - - void PrefixForNameIndex(uint8 index, char* prefix, size_t *length); - status_t NameBufferAppend(const char* str, char *&buffer, size_t *length); - -private: - Inode* fInode; - off_t fOffset; -}; - -#endif // ATTRIBUTE_ITERATOR_H diff --git a/src/add-ons/kernel/file_systems/ext2/Inode.cpp b/src/add-ons/kernel/file_systems/ext2/Inode.cpp index 1b9e334dc4..96337ad140 100644 --- a/src/add-ons/kernel/file_systems/ext2/Inode.cpp +++ b/src/add-ons/kernel/file_systems/ext2/Inode.cpp @@ -32,9 +32,11 @@ Inode::Inode(Volume* volume, ino_t id) fCache(NULL), fMap(NULL), fCached(false), + fHasExtraAttributes(false), fAttributesBlock(NULL) { rw_lock_init(&fLock, "ext2 inode"); + recursive_lock_init(&fSmallDataLock, "ext2 inode small data"); TRACE("Inode::Inode(): ext2_inode: %lu, disk inode: %lu\n", sizeof(ext2_inode), fVolume->InodeSize()); @@ -70,6 +72,7 @@ Inode::Inode(Volume* volume) fInitStatus(B_NO_INIT) { rw_lock_init(&fLock, "ext2 inode"); + recursive_lock_init(&fSmallDataLock, "ext2 inode small data"); TRACE("Inode::Inode(): ext2_inode: %lu, disk inode: %lu\n", sizeof(ext2_inode), fVolume->InodeSize()); @@ -476,7 +479,7 @@ 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); + uint32 block = Node().ExtendedAttributesBlock(); if (block == 0) return B_ENTRY_NOT_FOUND; diff --git a/src/add-ons/kernel/file_systems/ext2/Inode.h b/src/add-ons/kernel/file_systems/ext2/Inode.h index 36587b66b8..91d55802fb 100644 --- a/src/add-ons/kernel/file_systems/ext2/Inode.h +++ b/src/add-ons/kernel/file_systems/ext2/Inode.h @@ -37,6 +37,8 @@ public: status_t UpdateNodeFromDisk(); status_t WriteBack(Transaction& transaction); + recursive_lock& SmallDataLock() { return fSmallDataLock; } + bool IsDirectory() const { return S_ISDIR(Mode()); } bool IsFile() const @@ -148,6 +150,8 @@ private: // information is always the same size (except in ext4) ext2_xattr_header* fAttributesBlock; status_t fInitStatus; + + mutable recursive_lock fSmallDataLock; }; diff --git a/src/add-ons/kernel/file_systems/ext2/Jamfile b/src/add-ons/kernel/file_systems/ext2/Jamfile index 8c4639881d..0f64740538 100644 --- a/src/add-ons/kernel/file_systems/ext2/Jamfile +++ b/src/add-ons/kernel/file_systems/ext2/Jamfile @@ -15,7 +15,7 @@ KernelAddon ext2 : Volume.cpp DataStream.cpp Inode.cpp - AttributeIterator.cpp + Attribute.cpp DirectoryIterator.cpp HTree.cpp HTreeEntryIterator.cpp diff --git a/src/add-ons/kernel/file_systems/ext2/ext2.h b/src/add-ons/kernel/file_systems/ext2/ext2.h index 57283004d3..2d0b331129 100644 --- a/src/add-ons/kernel/file_systems/ext2/ext2.h +++ b/src/add-ons/kernel/file_systems/ext2/ext2.h @@ -349,6 +349,9 @@ struct ext2_inode { return B_LENDIAN_TO_HOST_INT32(size); } + uint32 ExtendedAttributesBlock() const + { return B_LENDIAN_TO_HOST_INT32(file_access_control);} + uint16 ExtraInodeSize() const { return B_LENDIAN_TO_HOST_INT16(extra_inode_size); } diff --git a/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp b/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp index fb2eb0d722..1dda6c2ad7 100644 --- a/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp @@ -1,4 +1,5 @@ /* + * Copyright 2010, Jérôme Duval, korli@users.berlios.de. * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ @@ -15,7 +16,7 @@ #include #include -#include "AttributeIterator.h" +#include "Attribute.h" #include "CachedBlock.h" #include "DirectoryIterator.h" #include "ext2.h" @@ -1416,11 +1417,11 @@ ext2_open_attr_dir(fs_volume *_volume, fs_vnode *_node, void **_cookie) if (!inode->IsFile()) return EINVAL; - AttributeIterator* iterator = new(std::nothrow) AttributeIterator(inode); - if (iterator == NULL) + int32 *index = new(std::nothrow) int32; + if (index == NULL) return B_NO_MEMORY; - - *_cookie = iterator; + *index = 0; + *(int32**)_cookie = index; return B_OK; } @@ -1436,7 +1437,7 @@ static status_t ext2_free_attr_dir_cookie(fs_volume* _volume, fs_vnode* _node, void* _cookie) { TRACE("%s()\n", __FUNCTION__); - delete (AttributeIterator *)_cookie; + delete (int32 *)_cookie; return B_OK; } @@ -1447,17 +1448,22 @@ ext2_read_attr_dir(fs_volume* _volume, fs_vnode* _node, uint32* _num) { Inode* inode = (Inode*)_node->private_node; - AttributeIterator *iterator = (AttributeIterator *)_cookie; + int32 index = *(int32 *)_cookie; + Attribute attribute(inode); TRACE("%s()\n", __FUNCTION__); size_t length = bufferSize; - status_t status = iterator->GetNext(dirent->d_name, &length); + status_t status = attribute.Find(index); if (status == B_ENTRY_NOT_FOUND) { *_num = 0; return B_OK; } else if (status != B_OK) return status; + status = attribute.GetName(dirent->d_name, &length); + if (status != B_OK) + return B_OK; + Volume* volume = (Volume*)_volume->private_volume; dirent->d_dev = volume->ID(); @@ -1465,6 +1471,7 @@ ext2_read_attr_dir(fs_volume* _volume, fs_vnode* _node, dirent->d_reclen = sizeof(struct dirent) + length; *_num = 1; + *(int32*)_cookie = index + 1; return B_OK; } @@ -1472,9 +1479,9 @@ ext2_read_attr_dir(fs_volume* _volume, fs_vnode* _node, static status_t ext2_rewind_attr_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie) { - AttributeIterator *iterator = (AttributeIterator *)_cookie; + *(int32*)_cookie = 0; TRACE("%s()\n", __FUNCTION__); - return iterator->Rewind(); + return B_OK; } @@ -1492,31 +1499,15 @@ 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; + Inode* inode = (Inode*)_node->private_node; + Attribute attribute(inode); 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; + return attribute.Open(name, openMode, (attr_cookie**)_cookie); } @@ -1532,31 +1523,23 @@ 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; + delete (attr_cookie*)cookie; 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) +ext2_read_attr(fs_volume* _volume, fs_vnode* _node, void* _cookie, + off_t pos, void* buffer, size_t* _length) { TRACE("%s()\n", __FUNCTION__); + attr_cookie* cookie = (attr_cookie*)_cookie; Inode* inode = (Inode*)_node->private_node; - //Volume* volume = (Volume*)_volume->private_volume; - ext2_xattr_entry *entry = (ext2_xattr_entry *)cookie; - if (!entry->IsValid()) - return EINVAL; + Attribute attribute(inode, cookie); - if (pos < 0 || (pos + *length) > entry->ValueSize()) - return ERANGE; - - return inode->AttributeBlockReadAt(entry->ValueOffset() + pos, - (uint8 *)buffer, length); + return attribute.Read(cookie, pos, (uint8*)buffer, _length); } @@ -1571,15 +1554,14 @@ ext2_write_attr(fs_volume* _volume, fs_vnode* _node, void* cookie, static status_t ext2_read_attr_stat(fs_volume* _volume, fs_vnode* _node, - void* cookie, struct stat* stat) + void* _cookie, struct stat* stat) { - ext2_xattr_entry *entry = (ext2_xattr_entry *)cookie; + attr_cookie* cookie = (attr_cookie*)_cookie; + Inode* inode = (Inode*)_node->private_node; - stat->st_type = B_RAW_TYPE; - stat->st_size = entry->ValueSize(); - TRACE("%s: st_size %d\n", __FUNCTION__, stat->st_size); + Attribute attribute(inode, cookie); - return B_OK; + return attribute.Stat(*stat); }