1/* 2 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "Package.h" 8 9#include <errno.h> 10#include <fcntl.h> 11#include <stdlib.h> 12#include <string.h> 13#include <unistd.h> 14 15#include <util/AutoLock.h> 16 17#include "DebugSupport.h" 18#include "PackageDomain.h" 19#include "Version.h" 20 21 22const char* const kArchitectureNames[B_PACKAGE_ARCHITECTURE_ENUM_COUNT] = { 23 "any", 24 "x86", 25 "x86_gcc2", 26}; 27 28 29Package::Package(PackageDomain* domain, dev_t deviceID, ino_t nodeID) 30 : 31 fDomain(domain), 32 fFileName(NULL), 33 fName(NULL), 34 fInstallPath(NULL), 35 fVersion(NULL), 36 fArchitecture(B_PACKAGE_ARCHITECTURE_ENUM_COUNT), 37 fLinkDirectory(NULL), 38 fFD(-1), 39 fOpenCount(0), 40 fNodeID(nodeID), 41 fDeviceID(deviceID) 42{ 43 mutex_init(&fLock, "packagefs package"); 44} 45 46 47Package::~Package() 48{ 49 while (PackageNode* node = fNodes.RemoveHead()) 50 node->ReleaseReference(); 51 52 while (Resolvable* resolvable = fResolvables.RemoveHead()) 53 delete resolvable; 54 55 while (Dependency* dependency = fDependencies.RemoveHead()) 56 delete dependency; 57 58 free(fFileName); 59 free(fName); 60 free(fInstallPath); 61 delete fVersion; 62 63 mutex_destroy(&fLock); 64} 65 66 67status_t 68Package::Init(const char* fileName) 69{ 70 fFileName = strdup(fileName); 71 if (fFileName == NULL) 72 RETURN_ERROR(B_NO_MEMORY); 73 74 return B_OK; 75} 76 77 78status_t 79Package::SetName(const char* name) 80{ 81 if (fName != NULL) 82 free(fName); 83 84 fName = strdup(name); 85 if (fName == NULL) 86 RETURN_ERROR(B_NO_MEMORY); 87 88 return B_OK; 89} 90 91 92status_t 93Package::SetInstallPath(const char* installPath) 94{ 95 if (fInstallPath != NULL) 96 free(fInstallPath); 97 98 fInstallPath = strdup(installPath); 99 if (fInstallPath == NULL) 100 RETURN_ERROR(B_NO_MEMORY); 101 102 return B_OK; 103} 104 105 106void 107Package::SetVersion(::Version* version) 108{ 109 if (fVersion != NULL) 110 delete fVersion; 111 112 fVersion = version; 113} 114 115 116const char* 117Package::ArchitectureName() const 118{ 119 if (fArchitecture < 0 120 || fArchitecture >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) { 121 return NULL; 122 } 123 124 return kArchitectureNames[fArchitecture]; 125} 126 127 128void 129Package::AddNode(PackageNode* node) 130{ 131 fNodes.Add(node); 132 node->AcquireReference(); 133} 134 135 136void 137Package::AddResolvable(Resolvable* resolvable) 138{ 139 fResolvables.Add(resolvable); 140} 141 142 143void 144Package::AddDependency(Dependency* dependency) 145{ 146 fDependencies.Add(dependency); 147} 148 149 150int 151Package::Open() 152{ 153 MutexLocker locker(fLock); 154 if (fOpenCount > 0) { 155 fOpenCount++; 156 return fFD; 157 } 158 159 // open the file 160 fFD = openat(fDomain->DirectoryFD(), fFileName, O_RDONLY); 161 if (fFD < 0) { 162 ERROR("Failed to open package file \"%s\"\n", fFileName); 163 return errno; 164 } 165 166 // stat it to verify that it's still the same file 167 struct stat st; 168 if (fstat(fFD, &st) < 0) { 169 ERROR("Failed to stat package file \"%s\"\n", fFileName); 170 close(fFD); 171 fFD = -1; 172 return errno; 173 } 174 175 if (st.st_dev != fDeviceID || st.st_ino != fNodeID) { 176 close(fFD); 177 fFD = -1; 178 RETURN_ERROR(B_ENTRY_NOT_FOUND); 179 } 180 181 fOpenCount = 1; 182 return fFD; 183} 184 185 186void 187Package::Close() 188{ 189 MutexLocker locker(fLock); 190 if (fOpenCount == 0) { 191 ERROR("Package open count already 0!\n"); 192 return; 193 } 194 195 if (--fOpenCount == 0) { 196 close(fFD); 197 fFD = -1; 198 } 199} 200