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