1/*
2 * Copyright 2012 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Pawe�� Dziepak, pdziepak@quarnos.org
7 */
8
9
10#include "FileInfo.h"
11
12#include "FileSystem.h"
13#include "Request.h"
14
15
16InodeName::InodeName(InodeNames* parent, const char* name)
17	:
18	fParent(parent),
19	fName(strdup(name))
20{
21	if (fParent != NULL)
22		fParent->AcquireReference();
23}
24
25
26InodeName::~InodeName()
27{
28	if (fParent != NULL)
29		fParent->ReleaseReference();
30	free(const_cast<char*>(fName));
31}
32
33
34InodeNames::InodeNames()
35{
36	mutex_init(&fLock, NULL);
37}
38
39
40InodeNames::~InodeNames()
41{
42	while (!fNames.IsEmpty())
43		delete fNames.RemoveHead();
44	mutex_destroy(&fLock);
45}
46
47
48status_t
49InodeNames::AddName(InodeNames* parent, const char* name)
50{
51	MutexLocker _(fLock);
52
53	InodeName* current = fNames.Head();
54	while (current != NULL) {
55		if (current->fParent == parent && !strcmp(current->fName, name))
56			return B_OK;
57		current = fNames.GetNext(current);
58	}
59
60	InodeName* newName = new InodeName(parent, name);
61	if (newName == NULL)
62		return B_NO_MEMORY;
63	fNames.Add(newName);
64	return B_OK;
65}
66
67
68bool
69InodeNames::RemoveName(InodeNames* parent, const char* name)
70{
71	MutexLocker _(fLock);
72
73	InodeName* previous = NULL;
74	InodeName* current = fNames.Head();
75	while (current != NULL) {
76		if (current->fParent == parent && !strcmp(current->fName, name)) {
77			fNames.Remove(previous, current);
78			delete current;
79			break;
80		}
81
82		previous = current;
83		current = fNames.GetNext(current);
84	}
85
86	return fNames.IsEmpty();
87}
88
89
90FileInfo::FileInfo()
91	:
92	fFileId(0),
93	fNames(NULL)
94{
95}
96
97
98FileInfo::~FileInfo()
99{
100	if (fNames != NULL)
101		fNames->ReleaseReference();
102}
103
104
105FileInfo::FileInfo(const FileInfo& fi)
106	:
107	fFileId(fi.fFileId),
108	fHandle(fi.fHandle),
109	fNames(fi.fNames)
110{
111	if (fNames != NULL)
112		fNames->AcquireReference();
113}
114
115
116FileInfo&
117FileInfo::operator=(const FileInfo& fi)
118{
119	fFileId = fi.fFileId;
120	fHandle = fi.fHandle;
121
122	if (fNames != NULL)
123		fNames->ReleaseReference();
124	fNames = fi.fNames;
125	if (fNames != NULL)
126		fNames->AcquireReference();
127
128	return *this;
129}
130
131
132status_t
133FileInfo::UpdateFileHandles(FileSystem* fs)
134{
135	ASSERT(fs != NULL);
136
137	Request request(fs->Server(), fs);
138	RequestBuilder& req = request.Builder();
139
140	req.PutRootFH();
141
142	uint32 lookupCount = 0;
143	const char** path = fs->Path();
144	if (path != NULL) {
145		for (; path[lookupCount] != NULL; lookupCount++)
146			req.LookUp(path[lookupCount]);
147	}
148
149	uint32 i;
150	InodeNames* names = fNames;
151	for (i = 0; names != NULL; i++) {
152		if (names->fNames.IsEmpty())
153			return B_ENTRY_NOT_FOUND;
154
155		names = names->fNames.Head()->fParent;
156	}
157
158	if (i > 0) {
159		names = fNames;
160		InodeNames** pathNames = new InodeNames*[i];
161		if (pathNames == NULL)
162			return B_NO_MEMORY;
163
164		for (i = 0; names != NULL; i++) {
165			pathNames[i] = names;
166			names = names->fNames.Head()->fParent;
167		}
168
169		for (; i > 0; i--) {
170			if (!strcmp(pathNames[i - 1]->fNames.Head()->fName, ""))
171				continue;
172
173			req.LookUp(pathNames[i - 1]->fNames.Head()->fName);
174			lookupCount++;
175		}
176		delete[] pathNames;
177	}
178
179	req.GetFH();
180
181	if (fs->IsAttrSupported(FATTR4_FILEID)) {
182		AttrValue attr;
183		attr.fAttribute = FATTR4_FILEID;
184		attr.fFreePointer = false;
185		attr.fData.fValue64 = fFileId;
186		req.Verify(&attr, 1);
187	}
188
189	status_t result = request.Send();
190	if (result != B_OK)
191		return result;
192
193	ReplyInterpreter& reply = request.Reply();
194
195	reply.PutRootFH();
196	for (uint32 i = 0; i < lookupCount; i++)
197		reply.LookUp();
198
199	FileHandle handle;
200	result = reply.GetFH(&handle);
201	if (result != B_OK)
202		return result;
203
204	if (fs->IsAttrSupported(FATTR4_FILEID)) {
205		result = reply.Verify();
206		if (result != B_OK)
207			return result;
208	}
209
210	fHandle = handle;
211	fNames->fHandle = handle;
212
213	return B_OK;
214}
215
216