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 21 static const char* const kUnknownLinkTarget = "?"; 22 23 static 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 38 static const char* 39 link_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 53 struct 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 71 private: 72 timespec fModifiedTime; 73 off_t fFileSize; 74 }; 75 76 77 // #pragma mark - PackageLinkSymlink 78 79 80 PackageLinkSymlink::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 91 PackageLinkSymlink::~PackageLinkSymlink() 92 { 93 } 94 95 96 void 97 PackageLinkSymlink::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 124 mode_t 125 PackageLinkSymlink::Mode() const 126 { 127 return S_IFLNK | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 128 } 129 130 131 timespec 132 PackageLinkSymlink::ModifiedTime() const 133 { 134 return fModifiedTime; 135 } 136 137 138 off_t 139 PackageLinkSymlink::FileSize() const 140 { 141 return strlen(fLinkPath); 142 } 143 144 145 status_t 146 PackageLinkSymlink::Read(off_t offset, void* buffer, size_t* bufferSize) 147 { 148 return B_BAD_VALUE; 149 } 150 151 152 status_t 153 PackageLinkSymlink::Read(io_request* request) 154 { 155 return B_BAD_VALUE; 156 } 157 158 159 status_t 160 PackageLinkSymlink::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 173 status_t 174 PackageLinkSymlink::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 186 status_t 187 PackageLinkSymlink::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