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 ShortAttribute::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 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 124 status_t 125 ShortAttribute::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 152 status_t 153 ShortAttribute::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 175 void 176 ShortAttribute::SwapEndian() 177 { 178 fHeader->totsize = B_BENDIAN_TO_HOST_INT16(fHeader->totsize); 179 } 180