xref: /haiku/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp (revision 25a7b01d15612846f332751841da3579db313082)
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 
InodeName(InodeNames * parent,const char * name)16 InodeName::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 
~InodeName()26 InodeName::~InodeName()
27 {
28 	if (fParent != NULL)
29 		fParent->ReleaseReference();
30 	free(const_cast<char*>(fName));
31 }
32 
33 
InodeNames()34 InodeNames::InodeNames()
35 {
36 	mutex_init(&fLock, NULL);
37 }
38 
39 
~InodeNames()40 InodeNames::~InodeNames()
41 {
42 	while (!fNames.IsEmpty())
43 		delete fNames.RemoveHead();
44 	mutex_destroy(&fLock);
45 }
46 
47 
48 status_t
AddName(InodeNames * parent,const char * name)49 InodeNames::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 
68 bool
RemoveName(InodeNames * parent,const char * name)69 InodeNames::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 
FileInfo()90 FileInfo::FileInfo()
91 	:
92 	fFileId(0),
93 	fNames(NULL)
94 {
95 }
96 
97 
~FileInfo()98 FileInfo::~FileInfo()
99 {
100 	if (fNames != NULL)
101 		fNames->ReleaseReference();
102 }
103 
104 
FileInfo(const FileInfo & fi)105 FileInfo::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 
116 FileInfo&
operator =(const FileInfo & fi)117 FileInfo::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 
132 status_t
UpdateFileHandles(FileSystem * fs)133 FileInfo::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