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