xref: /haiku/src/kits/storage/SymLink.cpp (revision 133da790eae949bd9ad649fd1dda854c1ca840e3)
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