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