1 /* 2 * Copyright 2002-2009, Haiku Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Tyler Dauwalder 7 * Ingo Weinhold, ingo_weinhold@gmx.de 8 */ 9 10 11 /*! \file SymLink.cpp 12 BSymLink implementation. 13 */ 14 15 16 #include <new> 17 #include <string.h> 18 19 #include <SymLink.h> 20 #include <Directory.h> 21 #include <Entry.h> 22 #include <Path.h> 23 24 #include <syscalls.h> 25 26 #include "storage_support.h" 27 28 using namespace std; 29 30 31 //! Creates an uninitialized BSymLink object. 32 BSymLink::BSymLink() 33 { 34 } 35 36 37 //! Creates a copy of the supplied BSymLink. 38 /*! \param link the BSymLink object to be copied 39 */ 40 BSymLink::BSymLink(const BSymLink &link) 41 : 42 BNode(link) 43 { 44 } 45 46 47 /*! \brief Creates a BSymLink and initializes it to the symbolic link referred 48 to by the supplied entry_ref. 49 \param ref the entry_ref referring to the symbolic link 50 */ 51 BSymLink::BSymLink(const entry_ref *ref) 52 : 53 BNode(ref) 54 { 55 } 56 57 58 /*! \brief Creates a BSymLink and initializes it to the symbolic link referred 59 to by the supplied BEntry. 60 \param entry the BEntry referring to the symbolic link 61 */ 62 BSymLink::BSymLink(const BEntry *entry) 63 : BNode(entry) 64 { 65 } 66 67 68 /*! \brief Creates a BSymLink and initializes it to the symbolic link referred 69 to by the supplied path name. 70 \param path the symbolic link's path name 71 */ 72 BSymLink::BSymLink(const char *path) 73 : 74 BNode(path) 75 { 76 } 77 78 79 /*! \brief Creates a BSymLink and initializes it to the symbolic link referred 80 to by the supplied path name relative to the specified BDirectory. 81 \param dir the BDirectory, relative to which the symbolic link's path name 82 is given 83 \param path the symbolic link's path name relative to \a dir 84 */ 85 BSymLink::BSymLink(const BDirectory *dir, const char *path) 86 : 87 BNode(dir, path) 88 { 89 } 90 91 92 //! Frees all allocated resources. 93 /*! If the BSymLink is properly initialized, the symbolic link's file 94 descriptor is closed. 95 */ 96 BSymLink::~BSymLink() 97 { 98 } 99 100 101 //! Reads the contents of the symbolic link into a buffer. 102 /*! The string written to the buffer will be null-terminated. 103 \param buf the buffer 104 \param size the size of the buffer 105 \return 106 - the number of bytes written into the buffer 107 - \c B_BAD_VALUE: \c NULL \a buf or the object doesn't refer to a symbolic 108 link. 109 - \c B_FILE_ERROR: The object is not initialized. 110 - some other error code 111 */ 112 ssize_t 113 BSymLink::ReadLink(char *buffer, size_t size) 114 { 115 if (!buffer) 116 return B_BAD_VALUE; 117 if (InitCheck() != B_OK) 118 return B_FILE_ERROR; 119 120 size_t linkLen = size; 121 status_t error = _kern_read_link(get_fd(), NULL, buffer, &linkLen); 122 if (error < B_OK) 123 return error; 124 125 // null-terminate 126 if (linkLen >= size) 127 return B_BUFFER_OVERFLOW; 128 buffer[linkLen] = '\0'; 129 130 return linkLen; 131 } 132 133 134 /*! \brief Combines a directory path and the contents of this symbolic link to 135 an absolute path. 136 \param dirPath the path name of the directory 137 \param path the BPath object to be set to the resulting path name 138 \return 139 - \c the length of the resulting path name, 140 - \c B_BAD_VALUE: \c NULL \a dirPath or \a path or the object doesn't 141 refer to a symbolic link. 142 - \c B_FILE_ERROR: The object is not initialized. 143 - \c B_NAME_TOO_LONG: The resulting path name is too long. 144 - some other error code 145 */ 146 ssize_t 147 BSymLink::MakeLinkedPath(const char *dirPath, BPath *path) 148 { 149 // BeOS seems to convert the dirPath to a BDirectory, which causes links to 150 // be resolved. 151 // This does also mean that the dirPath must exist! 152 if (!dirPath || !path) 153 return B_BAD_VALUE; 154 BDirectory dir(dirPath); 155 ssize_t result = dir.InitCheck(); 156 if (result == B_OK) 157 result = MakeLinkedPath(&dir, path); 158 return result; 159 } 160 161 162 /*! \brief Combines a directory path and the contents of this symbolic link to 163 an absolute path. 164 \param dir the BDirectory referring to the directory 165 \param path the BPath object to be set to the resulting path name 166 \return 167 - \c the length of the resulting path name, 168 - \c B_BAD_VALUE: \c NULL \a dir or \a path or the object doesn't 169 refer to a symbolic link. 170 - \c B_FILE_ERROR: The object is not initialized. 171 - \c B_NAME_TOO_LONG: The resulting path name is too long. 172 - some other error code 173 */ 174 ssize_t 175 BSymLink::MakeLinkedPath(const BDirectory *dir, BPath *path) 176 { 177 if (!dir || !path) 178 return B_BAD_VALUE; 179 char contents[B_PATH_NAME_LENGTH]; 180 ssize_t result = ReadLink(contents, sizeof(contents)); 181 if (result >= 0) { 182 if (BPrivate::Storage::is_absolute_path(contents)) 183 result = path->SetTo(contents); 184 else 185 result = path->SetTo(dir, contents); 186 if (result == B_OK) 187 result = strlen(path->Path()); 188 } 189 return result; 190 } 191 192 193 //! Returns whether this BSymLink refers to an absolute link. 194 /*! /return 195 - \c true, if the object is properly initialized and the symbolic link it 196 refers to is an absolute link, 197 - \c false, otherwise. 198 */ 199 bool 200 BSymLink::IsAbsolute() 201 { 202 char contents[B_PATH_NAME_LENGTH]; 203 bool result = (ReadLink(contents, sizeof(contents)) >= 0); 204 if (result) 205 result = BPrivate::Storage::is_absolute_path(contents); 206 return result; 207 } 208 209 210 void BSymLink::_MissingSymLink1() {} 211 void BSymLink::_MissingSymLink2() {} 212 void BSymLink::_MissingSymLink3() {} 213 void BSymLink::_MissingSymLink4() {} 214 void BSymLink::_MissingSymLink5() {} 215 void BSymLink::_MissingSymLink6() {} 216 217 218 //! Returns the BSymLink's file descriptor. 219 /*! To be used instead of accessing the BNode's private \c fFd member directly. 220 \return the file descriptor, or -1, if not properly initialized. 221 */ 222 int 223 BSymLink::get_fd() const 224 { 225 return fFd; 226 } 227