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 String& name = fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT 79 ? AutoPackageAttributes::NameForAttribute( 80 (AutoPackageAttribute)fState) 81 : fAttribute->Name(); 82 83 // fill in the entry name -- checks whether the entry fits into the 84 // buffer 85 if (!set_dirent_name(buffer, bufferSize, name, strlen(name))) { 86 if (count == 0) 87 RETURN_ERROR(B_BUFFER_OVERFLOW); 88 break; 89 } 90 91 // fill in the other data 92 buffer->d_dev = volumeID; 93 buffer->d_ino = nodeID; 94 95 count++; 96 previousEntry = buffer; 97 bufferSize -= buffer->d_reclen; 98 buffer = (dirent*)((addr_t)buffer + buffer->d_reclen); 99 100 if (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT) 101 fState++; 102 else 103 fAttribute = fPackageNode->Attributes().GetNext(fAttribute); 104 } 105 106 *_count = count; 107 return B_OK; 108 } 109 110 111 status_t 112 UnpackingAttributeDirectoryCookie::Rewind() 113 { 114 if (fPackageNode != NULL) 115 fAttribute = fPackageNode->Attributes().Head(); 116 117 fState = AUTO_PACKAGE_ATTRIBUTE_ENUM_FIRST; 118 119 return B_OK; 120 } 121