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