1 /* 2 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "UnpackingAttributeDirectoryCookie.h" 8 9 #include "DebugSupport.h" 10 #include "PackageNode.h" 11 #include "Utils.h" 12 13 14 UnpackingAttributeDirectoryCookie::UnpackingAttributeDirectoryCookie( 15 PackageNode* packageNode) 16 : 17 fPackageNode(packageNode), 18 fAttribute(NULL), 19 fState(AUTO_PACKAGE_ATTRIBUTE_ENUM_FIRST) 20 { 21 if (fPackageNode != NULL) { 22 fPackageNode->AcquireReference(); 23 fAttribute = fPackageNode->Attributes().Head(); 24 } 25 } 26 27 28 UnpackingAttributeDirectoryCookie::~UnpackingAttributeDirectoryCookie() 29 { 30 if (fPackageNode != NULL) 31 fPackageNode->ReleaseReference(); 32 } 33 34 35 /*static*/ status_t 36 UnpackingAttributeDirectoryCookie::Open(PackageNode* packageNode, 37 AttributeDirectoryCookie*& _cookie) 38 { 39 UnpackingAttributeDirectoryCookie* cookie = new(std::nothrow) 40 UnpackingAttributeDirectoryCookie(packageNode); 41 if (cookie == NULL) 42 return B_NO_MEMORY; 43 44 _cookie = cookie; 45 return B_OK; 46 } 47 48 49 status_t 50 UnpackingAttributeDirectoryCookie::Read(dev_t volumeID, ino_t nodeID, 51 struct dirent* buffer, size_t bufferSize, uint32* _count) 52 { 53 uint32 maxCount = *_count; 54 uint32 count = 0; 55 56 dirent* previousEntry = NULL; 57 58 while (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT || fAttribute != NULL) { 59 // don't read more entries than requested 60 if (count >= maxCount) 61 break; 62 63 // align the buffer for subsequent entries 64 if (count > 0) { 65 addr_t offset = (addr_t)buffer % 8; 66 if (offset > 0) { 67 offset = 8 - offset; 68 if (bufferSize <= offset) 69 break; 70 71 previousEntry->d_reclen += offset; 72 buffer = (dirent*)((addr_t)buffer + offset); 73 bufferSize -= offset; 74 } 75 } 76 77 // get the attribute name 78 const char* name; 79 if (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT) { 80 name = AutoPackageAttributes::NameForAttribute( 81 (AutoPackageAttribute)fState); 82 } else 83 name = fAttribute->Name(); 84 85 // fill in the entry name -- checks whether the entry fits into the 86 // buffer 87 if (!set_dirent_name(buffer, bufferSize, name, strlen(name))) { 88 if (count == 0) 89 RETURN_ERROR(B_BUFFER_OVERFLOW); 90 break; 91 } 92 93 // fill in the other data 94 buffer->d_dev = volumeID; 95 buffer->d_ino = nodeID; 96 97 count++; 98 previousEntry = buffer; 99 bufferSize -= buffer->d_reclen; 100 buffer = (dirent*)((addr_t)buffer + buffer->d_reclen); 101 102 if (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT) 103 fState++; 104 else 105 fAttribute = fPackageNode->Attributes().GetNext(fAttribute); 106 } 107 108 *_count = count; 109 return B_OK; 110 } 111 112 113 status_t 114 UnpackingAttributeDirectoryCookie::Rewind() 115 { 116 if (fPackageNode != NULL) 117 fAttribute = fPackageNode->Attributes().Head(); 118 119 fState = AUTO_PACKAGE_ATTRIBUTE_ENUM_FIRST; 120 121 return B_OK; 122 } 123