1 /* 2 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "AutoPackageAttributes.h" 8 9 #include <algorithm> 10 #include <new> 11 12 #include <TypeConstants.h> 13 14 #include <AutoDeleter.h> 15 16 #include "AttributeCookie.h" 17 #include "DebugSupport.h" 18 #include "Package.h" 19 #include "StringConstants.h" 20 21 22 class AutoPackageAttributeCookie : public AttributeCookie { 23 public: 24 AutoPackageAttributeCookie(Package* package, AutoPackageAttribute attribute) 25 : 26 fPackage(package), 27 fAttribute(attribute) 28 { 29 fPackage->AcquireReference(); 30 } 31 32 virtual ~AutoPackageAttributeCookie() 33 { 34 fPackage->ReleaseReference(); 35 } 36 37 virtual status_t ReadAttribute(off_t offset, void* buffer, 38 size_t* bufferSize) 39 { 40 // get the attribute 41 off_t size; 42 uint32 type; 43 const void* value = AutoPackageAttributes::GetAttributeValue(fPackage, 44 fAttribute, size, type); 45 if (value == NULL) 46 return B_BAD_VALUE; 47 48 // check and clamp offset and size 49 if (offset < 0 || offset > size) 50 return B_BAD_VALUE; 51 52 size_t toCopy = *bufferSize; 53 if (offset + (off_t)toCopy > size) 54 toCopy = size - offset; 55 56 if (toCopy > 0 && user_memcpy(buffer, (const uint8*)value + offset, 57 toCopy) < B_OK) { 58 return B_BAD_ADDRESS; 59 } 60 61 *bufferSize = toCopy; 62 return B_OK; 63 } 64 65 virtual status_t ReadAttributeStat(struct stat* st) 66 { 67 if (AutoPackageAttributes::GetAttributeValue(fPackage, fAttribute, 68 st->st_size, st->st_type) == NULL) { 69 return B_BAD_VALUE; 70 } 71 72 return B_OK; 73 } 74 75 private: 76 Package* fPackage; 77 AutoPackageAttribute fAttribute; 78 }; 79 80 81 /*static*/ bool 82 AutoPackageAttributes::AttributeForName(const StringKey& name, 83 AutoPackageAttribute& _attribute) 84 { 85 for (int i = 0; i < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT; i++) { 86 if (name == StringConstants::Get().kAutoPackageAttributeNames[i]) { 87 _attribute = (AutoPackageAttribute)i; 88 return true; 89 } 90 } 91 92 return false; 93 } 94 95 96 /*static*/ const String& 97 AutoPackageAttributes::NameForAttribute(AutoPackageAttribute attribute) 98 { 99 ASSERT(attribute >= 0 && attribute < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT); 100 return StringConstants::Get().kAutoPackageAttributeNames[attribute]; 101 } 102 103 104 /*static*/ const void* 105 AutoPackageAttributes::GetAttributeValue(const Package* package, 106 AutoPackageAttribute attribute, off_t& _size, uint32& _type) 107 { 108 switch (attribute) { 109 case AUTO_PACKAGE_ATTRIBUTE_PACKAGE: 110 { 111 const char* value = package->VersionedName(); 112 _size = strlen(value) + 1; 113 _type = B_STRING_TYPE; 114 return value; 115 } 116 117 case AUTO_PACKAGE_ATTRIBUTE_PACKAGE_FILE: 118 { 119 const char* value = package->FileName(); 120 _size = strlen(value) + 1; 121 _type = B_STRING_TYPE; 122 return value; 123 } 124 125 default: 126 return NULL; 127 } 128 } 129 130 131 /*static*/ status_t 132 AutoPackageAttributes::OpenCookie(Package* package, const StringKey& name, 133 int openMode, AttributeCookie*& _cookie) 134 { 135 if (package == NULL) 136 return B_ENTRY_NOT_FOUND; 137 138 // get the attribute 139 AutoPackageAttribute attribute; 140 if (!AttributeForName(name, attribute)) 141 return B_ENTRY_NOT_FOUND; 142 143 // allocate the cookie 144 AutoPackageAttributeCookie* cookie = new(std::nothrow) 145 AutoPackageAttributeCookie(package, attribute); 146 if (cookie == NULL) 147 RETURN_ERROR(B_NO_MEMORY); 148 149 _cookie = cookie; 150 return B_OK; 151 } 152