1/*
2 * Copyright 2002-2009 Haiku, Inc. All rights reserved.
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#include <new>
12#include <string.h>
13
14#include <SymLink.h>
15#include <Directory.h>
16#include <Entry.h>
17#include <Path.h>
18
19#include <syscalls.h>
20
21#include "storage_support.h"
22
23
24using namespace std;
25
26
27// Creates an uninitialized BSymLink object.
28BSymLink::BSymLink()
29{
30}
31
32
33// Creates a copy of the supplied BSymLink object.
34BSymLink::BSymLink(const BSymLink& other)
35	:
36	BNode(other)
37{
38}
39
40
41// Creates a BSymLink object and initializes it to the symbolic link referred
42// to by the supplied entry_ref.
43BSymLink::BSymLink(const entry_ref* ref)
44	:
45	BNode(ref)
46{
47}
48
49
50// Creates a BSymLink object and initializes it to the symbolic link referred
51// to by the supplied BEntry.
52BSymLink::BSymLink(const BEntry* entry)
53		: BNode(entry)
54{
55}
56
57
58// Creates a BSymLink object and initializes it to the symbolic link referred
59// to by the supplied path name.
60BSymLink::BSymLink(const char* path)
61	:
62	BNode(path)
63{
64}
65
66
67// Creates a BSymLink object and initializes it to the symbolic link referred
68// to by the supplied path name relative to the specified BDirectory.
69BSymLink::BSymLink(const BDirectory* dir, const char* path)
70	:
71	BNode(dir, path)
72{
73}
74
75
76// Destroys the object and frees all allocated resources.
77BSymLink::~BSymLink()
78{
79}
80
81
82// Reads the contents of the symbolic link into a buffer.
83ssize_t
84BSymLink::ReadLink(char* buffer, size_t size)
85{
86	if (buffer == NULL)
87		return B_BAD_VALUE;
88
89	if (InitCheck() != B_OK)
90		return B_FILE_ERROR;
91
92	size_t linkLen = size;
93	status_t result = _kern_read_link(get_fd(), NULL, buffer, &linkLen);
94	if (result < B_OK)
95		return result;
96
97	if (linkLen < size)
98		buffer[linkLen] = '\0';
99	else if (size > 0)
100		buffer[size - 1] = '\0';
101
102	return linkLen;
103}
104
105
106// Combines a directory path and the contents of this symbolic link to form an
107// absolute path.
108ssize_t
109BSymLink::MakeLinkedPath(const char* dirPath, BPath* path)
110{
111	// BeOS seems to convert the dirPath to a BDirectory, which causes links
112	// to be resolved. This means that the dirPath must exist!
113	if (dirPath == NULL || path == NULL)
114		return B_BAD_VALUE;
115
116	BDirectory dir(dirPath);
117	ssize_t result = dir.InitCheck();
118	if (result == B_OK)
119		result = MakeLinkedPath(&dir, path);
120
121	return result;
122}
123
124
125// Combines a directory path and the contents of this symbolic link to form an
126// absolute path.
127ssize_t
128BSymLink::MakeLinkedPath(const BDirectory* dir, BPath* path)
129{
130	if (dir == NULL || path == NULL)
131		return B_BAD_VALUE;
132
133	char contents[B_PATH_NAME_LENGTH];
134	ssize_t result = ReadLink(contents, sizeof(contents));
135	if (result >= 0) {
136		if (BPrivate::Storage::is_absolute_path(contents))
137			result = path->SetTo(contents);
138		else
139			result = path->SetTo(dir, contents);
140
141		if (result == B_OK)
142			result = strlen(path->Path());
143	}
144
145	return result;
146}
147
148
149// Returns whether or not the object refers to an absolute path.
150bool
151BSymLink::IsAbsolute()
152{
153	char contents[B_PATH_NAME_LENGTH];
154	bool result = (ReadLink(contents, sizeof(contents)) >= 0);
155	if (result)
156		result = BPrivate::Storage::is_absolute_path(contents);
157
158	return result;
159}
160
161
162void BSymLink::_MissingSymLink1() {}
163void BSymLink::_MissingSymLink2() {}
164void BSymLink::_MissingSymLink3() {}
165void BSymLink::_MissingSymLink4() {}
166void BSymLink::_MissingSymLink5() {}
167void BSymLink::_MissingSymLink6() {}
168
169
170/*!	Returns the file descriptor of the BSymLink.
171
172	This method should be used instead of accessing the private \c fFd member
173	of the BNode directly.
174
175	\return The object's file descriptor, or -1 if not properly initialized.
176*/
177int
178BSymLink::get_fd() const
179{
180	return fFd;
181}
182