1/* 2 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "PackageLinkSymlink.h" 8 9#include <algorithm> 10 11#include <NodeMonitor.h> 12 13#include "AutoPackageAttributeDirectoryCookie.h" 14#include "DebugSupport.h" 15#include "NodeListener.h" 16#include "PackageLinksListener.h" 17#include "Utils.h" 18#include "Volume.h" 19 20 21static const char* const kUnknownLinkTarget = "?"; 22 23static const char* const kLinkPaths[PackageLinkSymlink::TYPE_ENUM_COUNT] 24 [PACKAGE_FS_MOUNT_TYPE_ENUM_COUNT] = { 25 { 26 "../..", 27 "../../../home/config", 28 kUnknownLinkTarget 29 }, 30 { 31 "../../../system/settings", 32 "../../../home/config/settings", 33 kUnknownLinkTarget 34 } 35}; 36 37 38static const char* 39link_path_for_mount_type(MountType mountType, PackageLinkSymlink::Type linkType) 40{ 41 if (mountType < 0 || mountType >= PACKAGE_FS_MOUNT_TYPE_ENUM_COUNT 42 || linkType < 0 || linkType >= PackageLinkSymlink::TYPE_ENUM_COUNT) { 43 return kUnknownLinkTarget; 44 } 45 46 return kLinkPaths[linkType][mountType]; 47} 48 49 50// #pragma mark - OldAttributes 51 52 53struct PackageLinkSymlink::OldAttributes : OldNodeAttributes { 54 OldAttributes(const timespec& modifiedTime, off_t fileSize) 55 : 56 fModifiedTime(modifiedTime), 57 fFileSize(fileSize) 58 { 59 } 60 61 virtual timespec ModifiedTime() const 62 { 63 return fModifiedTime; 64 } 65 66 virtual off_t FileSize() const 67 { 68 return fFileSize; 69 } 70 71private: 72 timespec fModifiedTime; 73 off_t fFileSize; 74}; 75 76 77// #pragma mark - PackageLinkSymlink 78 79 80PackageLinkSymlink::PackageLinkSymlink(Package* package, Type type) 81 : 82 Node(0), 83 fPackage(), 84 fLinkPath(kUnknownLinkTarget), 85 fType(type) 86{ 87 Update(package, NULL); 88} 89 90 91PackageLinkSymlink::~PackageLinkSymlink() 92{ 93} 94 95 96void 97PackageLinkSymlink::Update(Package* package, PackageLinksListener* listener) 98{ 99 OldAttributes oldAttributes(fModifiedTime, FileSize()); 100 101 fPackage = package; 102 103 if (package != NULL) { 104 fLinkPath = package->InstallPath(); 105 if (fLinkPath[0] != '\0') { 106 if (fType == TYPE_SETTINGS) 107 fLinkPath = ".self/settings"; 108 } else { 109 fLinkPath = link_path_for_mount_type( 110 package->Volume()->MountType(), fType); 111 } 112 } else 113 fLinkPath = kUnknownLinkTarget; 114 115 get_real_time(fModifiedTime); 116 117 if (listener != NULL) { 118 listener->PackageLinkNodeChanged(this, 119 B_STAT_SIZE | B_STAT_MODIFICATION_TIME, oldAttributes); 120 } 121} 122 123 124mode_t 125PackageLinkSymlink::Mode() const 126{ 127 return S_IFLNK | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 128} 129 130 131timespec 132PackageLinkSymlink::ModifiedTime() const 133{ 134 return fModifiedTime; 135} 136 137 138off_t 139PackageLinkSymlink::FileSize() const 140{ 141 return strlen(fLinkPath); 142} 143 144 145status_t 146PackageLinkSymlink::Read(off_t offset, void* buffer, size_t* bufferSize) 147{ 148 return B_BAD_VALUE; 149} 150 151 152status_t 153PackageLinkSymlink::Read(io_request* request) 154{ 155 return B_BAD_VALUE; 156} 157 158 159status_t 160PackageLinkSymlink::ReadSymlink(void* buffer, size_t* bufferSize) 161{ 162 size_t linkLength = strnlen(fLinkPath, B_PATH_NAME_LENGTH); 163 164 size_t bytesToCopy = std::min(linkLength, *bufferSize); 165 166 *bufferSize = linkLength; 167 168 memcpy(buffer, fLinkPath, bytesToCopy); 169 return B_OK; 170} 171 172 173status_t 174PackageLinkSymlink::OpenAttributeDirectory(AttributeDirectoryCookie*& _cookie) 175{ 176 AutoPackageAttributeDirectoryCookie* cookie = new(std::nothrow) 177 AutoPackageAttributeDirectoryCookie(); 178 if (cookie == NULL) 179 return B_NO_MEMORY; 180 181 _cookie = cookie; 182 return B_OK; 183} 184 185 186status_t 187PackageLinkSymlink::OpenAttribute(const StringKey& name, int openMode, 188 AttributeCookie*& _cookie) 189{ 190 if (!fPackage.IsSet()) 191 return B_ENTRY_NOT_FOUND; 192 193 return AutoPackageAttributes::OpenCookie(fPackage, name, openMode, _cookie); 194} 195