/* * Copyright 2022, Raghav Sharma, raghavself28@gmail.com * Distributed under the terms of the MIT License. */ #include "ShortAttribute.h" ShortAttribute::ShortAttribute(Inode* inode) : fInode(inode), fName(NULL) { fHeader = (AShortFormHeader*)(DIR_AFORK_PTR(fInode->Buffer(), fInode->CoreInodeSize(), fInode->ForkOffset())); fLastEntryOffset = 0; } ShortAttribute::~ShortAttribute() { } uint32 ShortAttribute::_DataLength(AShortFormEntry* entry) { return entry->namelen + entry->valuelen; } ShortAttribute::AShortFormEntry* ShortAttribute::_FirstEntry() { return (AShortFormEntry*) ((char*) fHeader + sizeof(AShortFormHeader)); } status_t ShortAttribute::Open(const char* name, int openMode, attr_cookie** _cookie) { TRACE("ShortAttribute::Open\n"); status_t status; size_t length = strlen(name); status = Lookup(name, &length); 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->open_mode = openMode; cookie->create = false; *_cookie = cookie; return B_OK; } status_t ShortAttribute::Stat(attr_cookie* cookie, struct stat& stat) { TRACE("Short Attribute : Stat\n"); fName = cookie->name; size_t namelength = strlen(fName); // check if this attribute exists status_t status = Lookup(fName, &namelength); if (status != B_OK) return status; // We have valid attribute entry to stat stat.st_type = B_XATTR_TYPE; stat.st_size = _DataLength(fEntry); return B_OK; } status_t ShortAttribute::Read(attr_cookie* cookie, off_t pos, uint8* buffer, size_t* length) { TRACE("Short Attribute : Read\n"); if (pos < 0) return B_BAD_VALUE; fName = cookie->name; uint32 lengthToRead = 0; size_t namelength = strlen(fName); status_t status = Lookup(fName, &namelength); if(status != B_OK) return status; if (pos + *length > fEntry->valuelen) lengthToRead = fEntry->valuelen - pos; else lengthToRead = *length; char* ptrToOffset = (char*) fHeader + sizeof(AShortFormHeader) + 3 * sizeof(uint8) + fEntry->namelen; memcpy(buffer, ptrToOffset, lengthToRead); *length = lengthToRead; return B_OK; } status_t ShortAttribute::GetNext(char* name, size_t* nameLength) { TRACE("Short Attribute : GetNext\n"); AShortFormEntry* entry = _FirstEntry(); uint16 curOffset = 1; for (int i = 0; i < fHeader->count; i++) { if (curOffset > fLastEntryOffset) { fLastEntryOffset = curOffset; char* PtrToOffset = (char*)entry + 3 * sizeof(uint8); memcpy(name, PtrToOffset, entry->namelen); name[entry->namelen] = '\0'; *nameLength = entry->namelen + 1; TRACE("Entry found name : %s, namelength : %ld", name, *nameLength); return B_OK; } entry = (AShortFormEntry*)((char*)entry + 3 * sizeof(uint8) + _DataLength(entry)); curOffset += 3 * sizeof(uint8) + _DataLength(entry); } return B_ENTRY_NOT_FOUND; } status_t ShortAttribute::Lookup(const char* name, size_t* nameLength) { TRACE("Short Attribute : Lookup\n"); AShortFormEntry* entry = _FirstEntry(); int status; for (int i = 0; i < fHeader->count; i++) { char* PtrToOffset = (char*)entry + 3 * sizeof(uint8); status = strncmp(name, PtrToOffset, *nameLength); if (status == 0) { fEntry = entry; return B_OK; } entry = (AShortFormEntry*)((char*)entry + 3 * sizeof(uint8) + _DataLength(entry)); } return B_ENTRY_NOT_FOUND; } void ShortAttribute::SwapEndian() { fHeader->totsize = B_BENDIAN_TO_HOST_INT16(fHeader->totsize); }