2 * Copyright 2010-2011, Jérôme Duval, korli@users.berlios.de.
3 * Copyright 2010, François Revol, <revol@free.fr>.
4 * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
5 * This file may be used under the terms of the MIT License.
8 //! connection between pure inode and kernel_interface attributes
11 #include "Attribute.h"
19 # define TRACE(x...) dprintf("\33[34mbtrfs:\33[0m " x)
21 # define TRACE(x...) ;
25 Attribute::Attribute(Inode
* inode
)
27 fVolume(inode
->GetVolume()),
34 Attribute::Attribute(Inode
* inode
, attr_cookie
* cookie
)
36 fVolume(inode
->GetVolume()),
43 Attribute::~Attribute()
49 Attribute::CheckAccess(const char* name
, int openMode
)
51 return fInode
->CheckPermissions(open_mode_to_access(openMode
)
52 | (openMode
& O_TRUNC
? W_OK
: 0));
57 Attribute::Open(const char* name
, int openMode
, attr_cookie
** _cookie
)
60 status_t status
= CheckAccess(name
, openMode
);
64 status
= _Lookup(name
, strlen(name
));
68 attr_cookie
* cookie
= new(std::nothrow
) attr_cookie
;
74 // initialize the cookie
75 strlcpy(cookie
->name
, fName
, B_ATTR_NAME_LENGTH
);
76 cookie
->open_mode
= openMode
;
77 cookie
->create
= false;
85 Attribute::Stat(struct stat
& stat
)
89 size_t nameLength
= strlen(fName
);
90 btrfs_dir_entry
* entries
;
92 status_t status
= _Lookup(fName
, nameLength
, &entries
, &length
);
96 btrfs_dir_entry
* entry
;
97 status
= _FindEntry(entries
, length
, fName
, nameLength
, &entry
);
103 // found an entry to stat
104 stat
.st_type
= B_XATTR_TYPE
;
105 stat
.st_size
= entry
->DataLength();
112 Attribute::Read(attr_cookie
* cookie
, off_t pos
, uint8
* buffer
, size_t* _length
)
117 size_t nameLength
= strlen(fName
);
118 btrfs_dir_entry
* entries
;
120 status_t status
= _Lookup(fName
, nameLength
, &entries
, &length
);
124 btrfs_dir_entry
* entry
;
125 status
= _FindEntry(entries
, length
, fName
, nameLength
, &entry
);
126 if (status
!= B_OK
) {
131 // found an entry to read
132 if (pos
+ *_length
> entry
->DataLength())
133 length
= entry
->DataLength() - pos
;
135 length
= *_length
- pos
;
136 memcpy(buffer
, (uint8
*)entry
+ entry
->NameLength()
137 + sizeof(btrfs_dir_entry
) + (uint32
)pos
, length
);
146 Attribute::_Lookup(const char* name
, size_t nameLength
,
147 btrfs_dir_entry
** _entries
, uint32
* _length
)
149 uint32 hash
= calculate_crc((uint32
)~1, (uint8
*)name
, nameLength
);
150 struct btrfs_key key
;
151 key
.SetType(BTRFS_KEY_TYPE_XATTR_ITEM
);
152 key
.SetObjectID(fInode
->ID());
155 btrfs_dir_entry
* entries
;
157 status_t status
= fInode
->GetVolume()->FSTree()->FindExact(key
,
158 (void**)&entries
, &length
);
159 if (status
!= B_OK
) {
160 TRACE("AttributeIterator::Lookup(): Couldn't find entry with hash %"
161 B_PRIu32
" \"%s\"\n", hash
, name
);
165 if (_entries
== NULL
)
178 Attribute::_FindEntry(btrfs_dir_entry
* entries
, size_t length
,
179 const char* name
, size_t nameLength
, btrfs_dir_entry
** _entry
)
181 btrfs_dir_entry
* entry
= entries
;
183 while (current
< length
) {
184 current
+= entry
->Length();
186 // TODO there could be several entries with the same name hash
187 entry
= (btrfs_dir_entry
*)((uint8
*)entry
+ entry
->Length());