xref: /haiku/src/kits/storage/SymLink.cpp (revision 4f00613311d0bd6b70fa82ce19931c41f071ea4e)
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 /*!	\param buf the buffer
97 	\param size the size of the buffer
98 	\return
99 	- the number of bytes written into the buffer
100 	- \c B_BAD_VALUE: \c NULL \a buf or the object doesn't refer to a symbolic
101 	  link.
102 	- \c B_FILE_ERROR: The object is not initialized.
103 	- some other error code
104 */
105 ssize_t
106 BSymLink::ReadLink(char *buffer, size_t size)
107 {
108 	if (!buffer)
109 		return B_BAD_VALUE;
110 	if (InitCheck() != B_OK)
111 		return B_FILE_ERROR;
112 
113 	status_t error = _kern_read_link(get_fd(), NULL, buffer, &size);
114 	if (error < B_OK)
115 		return error;
116 
117 	return size;
118 }
119 
120 // MakeLinkedPath
121 /*!	\brief Combines a directory path and the contents of this symbolic link to
122 	an absolute path.
123 	\param dirPath the path name of the directory
124 	\param path the BPath object to be set to the resulting path name
125 	\return
126 	- \c the length of the resulting path name,
127 	- \c B_BAD_VALUE: \c NULL \a dirPath or \a path or the object doesn't
128 		 refer to a symbolic link.
129 	- \c B_FILE_ERROR: The object is not initialized.
130 	- \c B_NAME_TOO_LONG: The resulting path name is too long.
131 	- some other error code
132 */
133 ssize_t
134 BSymLink::MakeLinkedPath(const char *dirPath, BPath *path)
135 {
136 	// R5 seems to convert the dirPath to a BDirectory, which causes links to
137 	// be resolved, i.e. a "/tmp" dirPath expands to "/boot/var/tmp".
138 	// That does also mean, that the dirPath must exists!
139 	if (!dirPath || !path)
140 		return B_BAD_VALUE;
141 	BDirectory dir(dirPath);
142 	ssize_t result = dir.InitCheck();
143 	if (result == B_OK)
144 		result = MakeLinkedPath(&dir, path);
145 	return result;
146 }
147 
148 // MakeLinkedPath
149 /*!	\brief Combines a directory path and the contents of this symbolic link to
150 	an absolute path.
151 	\param dir the BDirectory referring to the directory
152 	\param path the BPath object to be set to the resulting path name
153 	\return
154 	- \c the length of the resulting path name,
155 	- \c B_BAD_VALUE: \c NULL \a dir or \a path or the object doesn't
156 		 refer to a symbolic link.
157 	- \c B_FILE_ERROR: The object is not initialized.
158 	- \c B_NAME_TOO_LONG: The resulting path name is too long.
159 	- some other error code
160 */
161 ssize_t
162 BSymLink::MakeLinkedPath(const BDirectory *dir, BPath *path)
163 {
164 	if (!dir || !path)
165 		return B_BAD_VALUE;
166 	char contents[B_PATH_NAME_LENGTH];
167 	ssize_t result = ReadLink(contents, sizeof(contents));
168 	if (result >= 0) {
169 		if (BPrivate::Storage::is_absolute_path(contents))
170 			result = path->SetTo(contents);
171 		else
172 			result = path->SetTo(dir, contents);
173 		if (result == B_OK)
174 			result = strlen(path->Path());
175 	}
176 	return result;
177 }
178 
179 // IsAbsolute
180 //!	Returns whether this BSymLink refers to an absolute link.
181 /*!	/return
182 	- \c true, if the object is properly initialized and the symbolic link it
183 	  refers to is an absolute link,
184 	- \c false, otherwise.
185 */
186 bool
187 BSymLink::IsAbsolute()
188 {
189 	char contents[B_PATH_NAME_LENGTH];
190 	bool result = (ReadLink(contents, sizeof(contents)) >= 0);
191 	if (result)
192 		result = BPrivate::Storage::is_absolute_path(contents);
193 	return result;
194 }
195 
196 
197 void BSymLink::_MissingSymLink1() {}
198 void BSymLink::_MissingSymLink2() {}
199 void BSymLink::_MissingSymLink3() {}
200 void BSymLink::_MissingSymLink4() {}
201 void BSymLink::_MissingSymLink5() {}
202 void BSymLink::_MissingSymLink6() {}
203 
204 //! Returns the BSymLink's file descriptor.
205 /*! To be used instead of accessing the BNode's private \c fFd member directly.
206 	\return the file descriptor, or -1, if not properly initialized.
207 */
208 int
209 BSymLink::get_fd() const
210 {
211 	return fFd;
212 }
213 
214 
215 #ifdef USE_OPENBEOS_NAMESPACE
216 };		// namespace OpenBeOS
217 #endif
218 
219