1/*
2 * Copyright 2022, Raghav Sharma, raghavself28@gmail.com
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "ShortAttribute.h"
8
9
10ShortAttribute::ShortAttribute(Inode* inode)
11	:
12	fInode(inode),
13	fName(NULL)
14{
15	fHeader = (AShortFormHeader*)(DIR_AFORK_PTR(fInode->Buffer(),
16		fInode->CoreInodeSize(), fInode->ForkOffset()));
17
18	fLastEntryOffset = 0;
19}
20
21
22ShortAttribute::~ShortAttribute()
23{
24}
25
26
27uint32
28ShortAttribute::_DataLength(AShortFormEntry* entry)
29{
30	return entry->namelen + entry->valuelen;
31}
32
33
34ShortAttribute::AShortFormEntry*
35ShortAttribute::_FirstEntry()
36{
37	return (AShortFormEntry*) ((char*) fHeader + sizeof(AShortFormHeader));
38}
39
40
41status_t
42ShortAttribute::Open(const char* name, int openMode, attr_cookie** _cookie)
43{
44	TRACE("ShortAttribute::Open\n");
45	status_t status;
46
47	size_t length = strlen(name);
48	status = Lookup(name, &length);
49	if (status < B_OK)
50		return status;
51
52	attr_cookie* cookie = new(std::nothrow) attr_cookie;
53	if (cookie == NULL)
54		return B_NO_MEMORY;
55
56	fName = name;
57
58	// initialize the cookie
59	strlcpy(cookie->name, fName, B_ATTR_NAME_LENGTH);
60	cookie->open_mode = openMode;
61	cookie->create = false;
62
63	*_cookie = cookie;
64	return B_OK;
65}
66
67
68status_t
69ShortAttribute::Stat(attr_cookie* cookie, struct stat& stat)
70{
71	TRACE("Short Attribute : Stat\n");
72
73	fName = cookie->name;
74
75	size_t namelength = strlen(fName);
76
77	// check if this attribute exists
78	status_t status = Lookup(fName, &namelength);
79	if (status != B_OK)
80		return status;
81
82	// We have valid attribute entry to stat
83	stat.st_type = B_XATTR_TYPE;
84	stat.st_size = _DataLength(fEntry);
85
86	return B_OK;
87}
88
89
90status_t
91ShortAttribute::Read(attr_cookie* cookie, off_t pos, uint8* buffer, size_t* length)
92{
93	TRACE("Short Attribute : Read\n");
94
95	if (pos < 0)
96		return B_BAD_VALUE;
97
98	fName = cookie->name;
99	uint32 lengthToRead = 0;
100
101	size_t namelength = strlen(fName);
102
103	status_t status = Lookup(fName, &namelength);
104
105	if(status != B_OK)
106		return status;
107
108	if (pos + *length > fEntry->valuelen)
109		lengthToRead = fEntry->valuelen - pos;
110	else
111		lengthToRead = *length;
112
113	char* ptrToOffset = (char*) fHeader + sizeof(AShortFormHeader)
114		+ 3 * sizeof(uint8) + fEntry->namelen;
115
116	memcpy(buffer, ptrToOffset, lengthToRead);
117
118	*length = lengthToRead;
119
120	return B_OK;
121}
122
123
124status_t
125ShortAttribute::GetNext(char* name, size_t* nameLength)
126{
127	TRACE("Short Attribute : GetNext\n");
128
129	AShortFormEntry* entry = _FirstEntry();
130	uint16 curOffset = 1;
131	for (int i = 0; i < fHeader->count; i++) {
132		if (curOffset > fLastEntryOffset) {
133
134			fLastEntryOffset = curOffset;
135
136			char* PtrToOffset = (char*)entry + 3 * sizeof(uint8);
137
138			memcpy(name, PtrToOffset, entry->namelen);
139			name[entry->namelen] = '\0';
140			*nameLength = entry->namelen + 1;
141			TRACE("Entry found name : %s, namelength : %ld", name, *nameLength);
142			return B_OK;
143		}
144		entry = (AShortFormEntry*)((char*)entry + 3 * sizeof(uint8) + _DataLength(entry));
145		curOffset += 3 * sizeof(uint8) + _DataLength(entry);
146	}
147
148	return B_ENTRY_NOT_FOUND;
149}
150
151
152status_t
153ShortAttribute::Lookup(const char* name, size_t* nameLength)
154{
155	TRACE("Short Attribute : Lookup\n");
156
157	AShortFormEntry* entry = _FirstEntry();
158
159	int status;
160
161	for (int i = 0; i < fHeader->count; i++) {
162		char* PtrToOffset = (char*)entry + 3 * sizeof(uint8);
163		status = strncmp(name, PtrToOffset, *nameLength);
164		if (status == 0) {
165			fEntry = entry;
166			return B_OK;
167		}
168		entry = (AShortFormEntry*)((char*)entry + 3 * sizeof(uint8) + _DataLength(entry));
169	}
170
171	return B_ENTRY_NOT_FOUND;
172}
173
174
175void
176ShortAttribute::SwapEndian()
177{
178	fHeader->totsize = B_BENDIAN_TO_HOST_INT16(fHeader->totsize);
179}
180