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 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 26 InodeName::~InodeName() 27 { 28 if (fParent != NULL) 29 fParent->ReleaseReference(); 30 free(const_cast<char*>(fName)); 31 } 32 33 34 InodeNames::InodeNames() 35 { 36 mutex_init(&fLock, NULL); 37 } 38 39 40 InodeNames::~InodeNames() 41 { 42 while (!fNames.IsEmpty()) 43 delete fNames.RemoveHead(); 44 mutex_destroy(&fLock); 45 } 46 47 48 status_t 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 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 90 FileInfo::FileInfo() 91 : 92 fFileId(0), 93 fNames(NULL) 94 { 95 } 96 97 98 FileInfo::~FileInfo() 99 { 100 if (fNames != NULL) 101 fNames->ReleaseReference(); 102 } 103 104 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& 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 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