1 //---------------------------------------------------------------------- 2 // This software is part of the OpenBeOS distribution and is covered 3 // by the OpenBeOS license. 4 //--------------------------------------------------------------------- 5 /*! 6 \file SymLink.cpp 7 BSymLink implementation. 8 */ 9 10 #include <new> 11 12 #include <SymLink.h> 13 #include <Directory.h> 14 #include <Entry.h> 15 #include <Path.h> 16 #include <storage_support.h> 17 18 #ifdef USE_OPENBEOS_NAMESPACE 19 namespace OpenBeOS { 20 #endif 21 22 // constructor 23 //! Creates an uninitialized BSymLink object. 24 BSymLink::BSymLink() 25 : BNode() 26 // WORKAROUND 27 , fSecretEntry(new(nothrow) BEntry) 28 { 29 } 30 31 // copy constructor 32 //! Creates a copy of the supplied BSymLink. 33 /*! \param link the BSymLink object to be copied 34 */ 35 BSymLink::BSymLink(const BSymLink &link) 36 : BNode() 37 // WORKAROUND 38 , fSecretEntry(new(nothrow) BEntry) 39 { 40 *this = link; 41 } 42 43 // constructor 44 /*! \brief Creates a BSymLink and initializes it to the symbolic link referred 45 to by the supplied entry_ref. 46 \param ref the entry_ref referring to the symbolic link 47 */ 48 BSymLink::BSymLink(const entry_ref *ref) 49 : BNode() 50 // WORKAROUND 51 , fSecretEntry(new(nothrow) BEntry) 52 { 53 SetTo(ref); 54 } 55 56 // constructor 57 /*! \brief Creates a BSymLink and initializes it to the symbolic link referred 58 to by the supplied BEntry. 59 \param entry the BEntry referring to the symbolic link 60 */ 61 BSymLink::BSymLink(const BEntry *entry) 62 : BNode() 63 // WORKAROUND 64 , fSecretEntry(new(nothrow) BEntry) 65 { 66 SetTo(entry); 67 } 68 69 // constructor 70 /*! \brief Creates a BSymLink and initializes it to the symbolic link referred 71 to by the supplied path name. 72 \param path the symbolic link's path name 73 */ 74 BSymLink::BSymLink(const char *path) 75 : BNode() 76 // WORKAROUND 77 , fSecretEntry(new(nothrow) BEntry) 78 { 79 SetTo(path); 80 } 81 82 // constructor 83 /*! \brief Creates a BSymLink and initializes it to the symbolic link referred 84 to by the supplied path name relative to the specified BDirectory. 85 \param dir the BDirectory, relative to which the symbolic link's path name 86 is given 87 \param path the symbolic link's path name relative to \a dir 88 */ 89 BSymLink::BSymLink(const BDirectory *dir, const char *path) 90 : BNode() 91 // WORKAROUND 92 , fSecretEntry(new(nothrow) BEntry) 93 { 94 SetTo(dir, path); 95 } 96 97 // destructor 98 //! Frees all allocated resources. 99 /*! If the BSymLink is properly initialized, the symbolic link's file 100 descriptor is closed. 101 */ 102 BSymLink::~BSymLink() 103 { 104 // WORKAROUND 105 delete fSecretEntry; 106 } 107 108 // WORKAROUND 109 status_t 110 BSymLink::SetTo(const entry_ref *ref) 111 { 112 status_t error = BNode::SetTo(ref); 113 if (fSecretEntry) { 114 fSecretEntry->Unset(); 115 if (error == B_OK) 116 fSecretEntry->SetTo(ref); 117 } else 118 error = B_NO_MEMORY; 119 return error; 120 } 121 122 // WORKAROUND 123 status_t 124 BSymLink::SetTo(const BEntry *entry) 125 { 126 status_t error = BNode::SetTo(entry); 127 if (fSecretEntry) { 128 fSecretEntry->Unset(); 129 if (error == B_OK) 130 *fSecretEntry = *entry; 131 } else 132 error = B_NO_MEMORY; 133 return error; 134 } 135 136 // WORKAROUND 137 status_t 138 BSymLink::SetTo(const char *path) 139 { 140 status_t error = BNode::SetTo(path); 141 if (fSecretEntry) { 142 fSecretEntry->Unset(); 143 if (error == B_OK) 144 fSecretEntry->SetTo(path); 145 } else 146 error = B_NO_MEMORY; 147 return error; 148 } 149 150 // WORKAROUND 151 status_t 152 BSymLink::SetTo(const BDirectory *dir, const char *path) 153 { 154 status_t error = BNode::SetTo(dir, path); 155 if (fSecretEntry) { 156 fSecretEntry->Unset(); 157 if (error == B_OK) 158 fSecretEntry->SetTo(dir, path); 159 } else 160 error = B_NO_MEMORY; 161 return error; 162 } 163 164 // WORKAROUND 165 void 166 BSymLink::Unset() 167 { 168 BNode::Unset(); 169 if (fSecretEntry) 170 fSecretEntry->Unset(); 171 } 172 173 174 // ReadLink 175 //! Reads the contents of the symbolic link into a buffer. 176 /*! \param buf the buffer 177 \param size the size of the buffer 178 \return 179 - the number of bytes written into the buffer 180 - \c B_BAD_VALUE: \c NULL \a buf or the object doesn't refer to a symbolic 181 link. 182 - \c B_FILE_ERROR: The object is not initialized. 183 - some other error code 184 */ 185 ssize_t 186 BSymLink::ReadLink(char *buf, size_t size) 187 { 188 /* 189 status_t error = (buf ? B_OK : B_BAD_VALUE); 190 if (error == B_OK && InitCheck() != B_OK) 191 error = B_FILE_ERROR; 192 if (error == B_OK) 193 error = StorageKit::read_link(get_fd(), buf, size); 194 return error; 195 */ 196 // WORKAROUND 197 status_t error = (buf ? B_OK : B_BAD_VALUE); 198 if (error == B_OK && (InitCheck() != B_OK 199 || !fSecretEntry 200 || fSecretEntry->InitCheck() != B_OK)) { 201 error = B_FILE_ERROR; 202 } 203 entry_ref ref; 204 if (error == B_OK) 205 error = fSecretEntry->GetRef(&ref); 206 char path[B_PATH_NAME_LENGTH + 1]; 207 if (error == B_OK) 208 error = StorageKit::entry_ref_to_path(&ref, path, sizeof(path)); 209 if (error == B_OK) 210 error = StorageKit::read_link(path, buf, size); 211 return error; 212 } 213 214 // MakeLinkedPath 215 /*! \brief Combines a directory path and the contents of this symbolic link to 216 an absolute path. 217 \param dirPath the path name of the directory 218 \param path the BPath object to be set to the resulting path name 219 \return 220 - \c the length of the resulting path name, 221 - \c B_BAD_VALUE: \c NULL \a dirPath or \a path or the object doesn't 222 refer to a symbolic link. 223 - \c B_FILE_ERROR: The object is not initialized. 224 - \c B_NAME_TOO_LONG: The resulting path name is too long. 225 - some other error code 226 */ 227 ssize_t 228 BSymLink::MakeLinkedPath(const char *dirPath, BPath *path) 229 { 230 // R5 seems to convert the dirPath to a BDirectory, which causes links to 231 // be resolved, i.e. a "/tmp" dirPath expands to "/boot/var/tmp". 232 // That does also mean, that the dirPath must exists! 233 ssize_t result = (dirPath && path ? B_OK : B_BAD_VALUE); 234 if (result == B_OK) { 235 BDirectory dir(dirPath); 236 result = dir.InitCheck(); 237 if (result == B_OK) 238 result = MakeLinkedPath(&dir, path); 239 } 240 return result; 241 } 242 243 // MakeLinkedPath 244 /*! \brief Combines a directory path and the contents of this symbolic link to 245 an absolute path. 246 \param dir the BDirectory referring to the directory 247 \param path the BPath object to be set to the resulting path name 248 \return 249 - \c the length of the resulting path name, 250 - \c B_BAD_VALUE: \c NULL \a dir or \a path or the object doesn't 251 refer to a symbolic link. 252 - \c B_FILE_ERROR: The object is not initialized. 253 - \c B_NAME_TOO_LONG: The resulting path name is too long. 254 - some other error code 255 */ 256 ssize_t 257 BSymLink::MakeLinkedPath(const BDirectory *dir, BPath *path) 258 { 259 ssize_t result = (dir && path ? 0 : B_BAD_VALUE); 260 char contents[B_PATH_NAME_LENGTH + 1]; 261 if (result == 0) 262 result = ReadLink(contents, sizeof(contents)); 263 if (result >= 0) { 264 if (StorageKit::is_absolute_path(contents)) 265 result = path->SetTo(contents); 266 else 267 result = path->SetTo(dir, contents); 268 if (result == B_OK) 269 result = strlen(path->Path()); 270 } 271 return result; 272 } 273 274 // IsAbsolute 275 //! Returns whether this BSymLink refers to an absolute link. 276 /*! /return 277 - \c true, if the object is properly initialized and the symbolic link it 278 refers to is an absolute link, 279 - \c false, otherwise. 280 */ 281 bool 282 BSymLink::IsAbsolute() 283 { 284 char contents[B_PATH_NAME_LENGTH + 1]; 285 bool result = (ReadLink(contents, sizeof(contents)) >= 0); 286 if (result) 287 result = StorageKit::is_absolute_path(contents); 288 return result; 289 } 290 291 // WORKAROUND 292 BSymLink & 293 BSymLink::operator=(const BSymLink &link) 294 { 295 if (&link != this) { // no need to assign us to ourselves 296 Unset(); 297 static_cast<BNode&>(*this) = link; 298 if (fSecretEntry && link.fSecretEntry) 299 *fSecretEntry = *link.fSecretEntry; 300 } 301 return *this; 302 } 303 304 305 void BSymLink::_ReservedSymLink1() {} 306 void BSymLink::_ReservedSymLink2() {} 307 void BSymLink::_ReservedSymLink3() {} 308 void BSymLink::_ReservedSymLink4() {} 309 void BSymLink::_ReservedSymLink5() {} 310 void BSymLink::_ReservedSymLink6() {} 311 312 //! Returns the BSymLink's file descriptor. 313 /*! To be used instead of accessing the BNode's private \c fFd member directly. 314 \return the file descriptor, or -1, if not properly initialized. 315 */ 316 StorageKit::FileDescriptor 317 BSymLink::get_fd() const 318 { 319 return fFd; 320 } 321 322 323 #ifdef USE_OPENBEOS_NAMESPACE 324 }; // namespace OpenBeOS 325 #endif 326