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 10 ShortAttribute::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 22 ShortAttribute::~ShortAttribute() 23 { 24 } 25 26 27 uint32 28 ShortAttribute::_DataLength(AShortFormEntry* entry) 29 { 30 return entry->namelen + entry->valuelen; 31 } 32 33 34 AShortFormEntry* 35 ShortAttribute::_FirstEntry() 36 { 37 return (AShortFormEntry*) ((char*) fHeader + sizeof(AShortFormHeader)); 38 } 39 40 41 status_t 42 ShortAttribute::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 68 status_t 69 ShortAttribute::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 90 status_t 91 ShortAttribute::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 100 size_t namelength = strlen(fName); 101 102 status_t status = Lookup(fName, &namelength); 103 104 uint32 lengthToRead = 0; 105 106 if (pos + *length > fEntry->valuelen) 107 lengthToRead = fEntry->valuelen - pos; 108 else 109 lengthToRead = *length; 110 111 char* ptrToOffset = (char*) fHeader + sizeof(AShortFormHeader) 112 + 3 * sizeof(uint8) + fEntry->namelen; 113 114 memcpy(buffer, ptrToOffset, lengthToRead); 115 116 *length = lengthToRead; 117 118 return B_OK; 119 } 120 121 122 status_t 123 ShortAttribute::GetNext(char* name, size_t* nameLength) 124 { 125 TRACE("Short Attribute : GetNext\n"); 126 127 AShortFormEntry* entry = _FirstEntry(); 128 uint16 curOffset = 1; 129 for (int i = 0; i < fHeader->count; i++) { 130 if (curOffset > fLastEntryOffset) { 131 132 fLastEntryOffset = curOffset; 133 134 char* PtrToOffset = (char*)entry + 3 * sizeof(uint8); 135 136 memcpy(name, PtrToOffset, entry->namelen); 137 name[entry->namelen] = '\0'; 138 *nameLength = entry->namelen + 1; 139 TRACE("Entry found name : %s, namelength : %ld", name, *nameLength); 140 return B_OK; 141 } 142 entry = (AShortFormEntry*)((char*)entry + 3 * sizeof(uint8) + _DataLength(entry)); 143 curOffset += 3 * sizeof(uint8) + _DataLength(entry); 144 } 145 146 return B_ENTRY_NOT_FOUND; 147 } 148 149 150 status_t 151 ShortAttribute::Lookup(const char* name, size_t* nameLength) 152 { 153 TRACE("Short Attribute : Lookup\n"); 154 155 AShortFormEntry* entry = _FirstEntry(); 156 157 int status; 158 159 for (int i = 0; i < fHeader->count; i++) { 160 char* PtrToOffset = (char*)entry + 3 * sizeof(uint8); 161 status = strncmp(name, PtrToOffset, *nameLength); 162 if (status == 0) { 163 fEntry = entry; 164 return B_OK; 165 } 166 entry = (AShortFormEntry*)((char*)entry + 3 * sizeof(uint8) + _DataLength(entry)); 167 } 168 169 return B_ENTRY_NOT_FOUND; 170 } 171