1284194Sdelphij/*
2284194Sdelphij * Copyright 2002-2009 Haiku, Inc. All rights reserved.
3284194Sdelphij * Distributed under the terms of the MIT License.
4284194Sdelphij *
5284194Sdelphij * Authors:
6284194Sdelphij *		Tyler Dauwalder
7284194Sdelphij *		Ingo Weinhold, ingo_weinhold@gmx.de
8284194Sdelphij */
9284194Sdelphij
10284194Sdelphij
11284194Sdelphij#include <new>
12284194Sdelphij#include <string.h>
13284194Sdelphij
14284194Sdelphij#include <SymLink.h>
15284194Sdelphij#include <Directory.h>
16284194Sdelphij#include <Entry.h>
17284194Sdelphij#include <Path.h>
18284194Sdelphij
19284194Sdelphij#include <syscalls.h>
20284194Sdelphij
21284194Sdelphij#include "storage_support.h"
22284194Sdelphij
23284194Sdelphij
24284194Sdelphijusing namespace std;
25284194Sdelphij
26284194Sdelphij
27284194Sdelphij// Creates an uninitialized BSymLink object.
28284194SdelphijBSymLink::BSymLink()
29284194Sdelphij{
30284194Sdelphij}
31284194Sdelphij
32284194Sdelphij
33284194Sdelphij// Creates a copy of the supplied BSymLink object.
34284194SdelphijBSymLink::BSymLink(const BSymLink& other)
35284194Sdelphij	:
36284194Sdelphij	BNode(other)
37284194Sdelphij{
38284194Sdelphij}
39284194Sdelphij
40284194Sdelphij
41284194Sdelphij// Creates a BSymLink object and initializes it to the symbolic link referred
42284194Sdelphij// to by the supplied entry_ref.
43284194SdelphijBSymLink::BSymLink(const entry_ref* ref)
44284194Sdelphij	:
45284194Sdelphij	BNode(ref)
46284194Sdelphij{
47284194Sdelphij}
48284194Sdelphij
49284194Sdelphij
50284194Sdelphij// Creates a BSymLink object and initializes it to the symbolic link referred
51284194Sdelphij// to by the supplied BEntry.
52284194SdelphijBSymLink::BSymLink(const BEntry* entry)
53284194Sdelphij		: BNode(entry)
54284194Sdelphij{
55284194Sdelphij}
56284194Sdelphij
57284194Sdelphij
58284194Sdelphij// Creates a BSymLink object and initializes it to the symbolic link referred
59284194Sdelphij// to by the supplied path name.
60284194SdelphijBSymLink::BSymLink(const char* path)
61284194Sdelphij	:
62284194Sdelphij	BNode(path)
63284194Sdelphij{
64284194Sdelphij}
65284194Sdelphij
66284194Sdelphij
67284194Sdelphij// Creates a BSymLink object and initializes it to the symbolic link referred
68284194Sdelphij// to by the supplied path name relative to the specified BDirectory.
69284194SdelphijBSymLink::BSymLink(const BDirectory* dir, const char* path)
70284194Sdelphij	:
71284194Sdelphij	BNode(dir, path)
72284194Sdelphij{
73284194Sdelphij}
74284194Sdelphij
75284194Sdelphij
76284194Sdelphij// Destroys the object and frees all allocated resources.
77284194SdelphijBSymLink::~BSymLink()
78284194Sdelphij{
79284194Sdelphij}
80284194Sdelphij
81284194Sdelphij
82284194Sdelphij// Reads the contents of the symbolic link into a buffer.
83284194Sdelphijssize_t
84284194SdelphijBSymLink::ReadLink(char* buffer, size_t size)
85284194Sdelphij{
86284194Sdelphij	if (buffer == NULL)
87284194Sdelphij		return B_BAD_VALUE;
88284194Sdelphij
89284194Sdelphij	if (InitCheck() != B_OK)
90284194Sdelphij		return B_FILE_ERROR;
91284194Sdelphij
92284194Sdelphij	size_t linkLen = size;
93284194Sdelphij	status_t result = _kern_read_link(get_fd(), NULL, buffer, &linkLen);
94284194Sdelphij	if (result < B_OK)
95284194Sdelphij		return result;
96284194Sdelphij
97284194Sdelphij	if (linkLen < size)
98284194Sdelphij		buffer[linkLen] = '\0';
99284194Sdelphij	else if (size > 0)
100284194Sdelphij		buffer[size - 1] = '\0';
101284194Sdelphij
102284194Sdelphij	return linkLen;
103284194Sdelphij}
104284194Sdelphij
105284194Sdelphij
106284194Sdelphij// Combines a directory path and the contents of this symbolic link to form an
107284194Sdelphij// absolute path.
108284194Sdelphijssize_t
109284194SdelphijBSymLink::MakeLinkedPath(const char* dirPath, BPath* path)
110284194Sdelphij{
111284194Sdelphij	// BeOS seems to convert the dirPath to a BDirectory, which causes links
112284194Sdelphij	// to be resolved. This means that the dirPath must exist!
113284194Sdelphij	if (dirPath == NULL || path == NULL)
114284194Sdelphij		return B_BAD_VALUE;
115284194Sdelphij
116284194Sdelphij	BDirectory dir(dirPath);
117284194Sdelphij	ssize_t result = dir.InitCheck();
118284194Sdelphij	if (result == B_OK)
119284194Sdelphij		result = MakeLinkedPath(&dir, path);
120284194Sdelphij
121284194Sdelphij	return result;
122284194Sdelphij}
123284194Sdelphij
124284194Sdelphij
125284194Sdelphij// Combines a directory path and the contents of this symbolic link to form an
126284194Sdelphij// absolute path.
127284194Sdelphijssize_t
128284194SdelphijBSymLink::MakeLinkedPath(const BDirectory* dir, BPath* path)
129284194Sdelphij{
130284194Sdelphij	if (dir == NULL || path == NULL)
131284194Sdelphij		return B_BAD_VALUE;
132284194Sdelphij
133284194Sdelphij	char contents[B_PATH_NAME_LENGTH];
134284194Sdelphij	ssize_t result = ReadLink(contents, sizeof(contents));
135284194Sdelphij	if (result >= 0) {
136284194Sdelphij		if (BPrivate::Storage::is_absolute_path(contents))
137284194Sdelphij			result = path->SetTo(contents);
138284194Sdelphij		else
139284194Sdelphij			result = path->SetTo(dir, contents);
140284194Sdelphij
141284194Sdelphij		if (result == B_OK)
142284194Sdelphij			result = strlen(path->Path());
143284194Sdelphij	}
144284194Sdelphij
145284194Sdelphij	return result;
146284194Sdelphij}
147284194Sdelphij
148284194Sdelphij
149284194Sdelphij// Returns whether or not the object refers to an absolute path.
150284194Sdelphijbool
151284194SdelphijBSymLink::IsAbsolute()
152284194Sdelphij{
153284194Sdelphij	char contents[B_PATH_NAME_LENGTH];
154284194Sdelphij	bool result = (ReadLink(contents, sizeof(contents)) >= 0);
155284194Sdelphij	if (result)
156284194Sdelphij		result = BPrivate::Storage::is_absolute_path(contents);
157284194Sdelphij
158284194Sdelphij	return result;
159284194Sdelphij}
160284194Sdelphij
161284194Sdelphij
162284194Sdelphijvoid BSymLink::_MissingSymLink1() {}
163284194Sdelphijvoid BSymLink::_MissingSymLink2() {}
164284194Sdelphijvoid BSymLink::_MissingSymLink3() {}
165284194Sdelphijvoid BSymLink::_MissingSymLink4() {}
166284194Sdelphijvoid BSymLink::_MissingSymLink5() {}
167284194Sdelphijvoid BSymLink::_MissingSymLink6() {}
168284194Sdelphij
169284194Sdelphij
170284194Sdelphij/*!	Returns the file descriptor of the BSymLink.
171284194Sdelphij
172284194Sdelphij	This method should be used instead of accessing the private \c fFd member
173284194Sdelphij	of the BNode directly.
174284194Sdelphij
175284194Sdelphij	\return The object's file descriptor, or -1 if not properly initialized.
176284194Sdelphij*/
177284194Sdelphijint
178284194SdelphijBSymLink::get_fd() const
179284194Sdelphij{
180284194Sdelphij	return fFd;
181284194Sdelphij}
182284194Sdelphij