1/* 2 * Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6#include "UserlandFS.h" 7 8#include <KernelExport.h> 9 10#include "Compatibility.h" 11#include "Debug.h" 12#include "FileSystem.h" 13#include "FileSystemInitializer.h" 14#include "KernelDebug.h" 15#include "RequestPort.h" 16#include "Requests.h" 17#include "UserlandFSDefs.h" 18 19 20UserlandFS* UserlandFS::sUserlandFS = NULL; 21 22// constructor 23UserlandFS::UserlandFS() 24 : 25 fFileSystems(NULL), 26 fDebuggerCommandsAdded(false) 27{ 28} 29 30// destructor 31UserlandFS::~UserlandFS() 32{ 33PRINT(("UserlandFS::~UserlandFS()\n")) 34 delete fFileSystems; 35 if (fDebuggerCommandsAdded) 36 KernelDebug::RemoveDebuggerCommands(); 37} 38 39// InitUserlandFS 40status_t 41UserlandFS::InitUserlandFS(UserlandFS** _userlandFS) 42{ 43 // create the singleton instance 44 sUserlandFS = new(nothrow) UserlandFS; 45 if (!sUserlandFS) 46 return B_NO_MEMORY; 47 48 // init the thing 49 status_t error = sUserlandFS->_Init(); 50 if (error != B_OK) { 51 delete sUserlandFS; 52 sUserlandFS = NULL; 53 return error; 54 } 55 56 *_userlandFS = sUserlandFS; 57 58 return B_OK; 59} 60 61// UninitUserlandFS 62void 63UserlandFS::UninitUserlandFS() 64{ 65 delete sUserlandFS; 66 sUserlandFS = NULL; 67} 68 69// GetUserlandFS 70UserlandFS* 71UserlandFS::GetUserlandFS() 72{ 73 return sUserlandFS; 74} 75 76// RegisterFileSystem 77status_t 78UserlandFS::RegisterFileSystem(const char* name, FileSystem** _fileSystem) 79{ 80 // check parameters 81 if (!name || !_fileSystem) 82 return B_BAD_VALUE; 83 84 // check, if we do already know this file system, and create it, if not 85 FileSystemInitializer* fileSystemInitializer; 86 { 87 FileSystemLocker _(fFileSystems); 88 fileSystemInitializer = fFileSystems->Get(name); 89 if (fileSystemInitializer) { 90 fileSystemInitializer->AcquireReference(); 91 } else { 92 fileSystemInitializer = new(nothrow) FileSystemInitializer(name); 93 if (!fileSystemInitializer) 94 return B_NO_MEMORY; 95 96 status_t error = fFileSystems->Put(name, fileSystemInitializer); 97 if (error != B_OK) { 98 delete fileSystemInitializer; 99 return error; 100 } 101 } 102 } 103 104 // prepare the file system 105 status_t error = fileSystemInitializer->Access(); 106 if (error != B_OK) { 107 _UnregisterFileSystem(name); 108 return error; 109 } 110 111 *_fileSystem = fileSystemInitializer->GetFileSystem(); 112 return error; 113} 114 115// UnregisterFileSystem 116status_t 117UserlandFS::UnregisterFileSystem(FileSystem* fileSystem) 118{ 119 if (!fileSystem) 120 return B_BAD_VALUE; 121 122 return _UnregisterFileSystem(fileSystem->GetName()); 123} 124 125// CountFileSystems 126int32 127UserlandFS::CountFileSystems() const 128{ 129 return fFileSystems->Size(); 130} 131 132// _Init 133status_t 134UserlandFS::_Init() 135{ 136 // add debugger commands 137 KernelDebug::AddDebuggerCommands(); 138 fDebuggerCommandsAdded = true; 139 140 // create file system map 141 fFileSystems = new(nothrow) FileSystemMap; 142 if (!fFileSystems) 143 RETURN_ERROR(B_NO_MEMORY); 144 status_t error = fFileSystems->InitCheck(); 145 if (error != B_OK) 146 RETURN_ERROR(error); 147 148 return B_OK; 149} 150 151// _UnregisterFileSystem 152status_t 153UserlandFS::_UnregisterFileSystem(const char* name) 154{ 155 if (!name) 156 return B_BAD_VALUE; 157 158 // find the FS and decrement its reference counter 159 FileSystemInitializer* fileSystemInitializer = NULL; 160 bool deleteFS = false; 161 { 162 FileSystemLocker _(fFileSystems); 163 fileSystemInitializer = fFileSystems->Get(name); 164 if (!fileSystemInitializer) 165 return B_BAD_VALUE; 166 167 deleteFS = fileSystemInitializer->ReleaseReference() == 1; 168 if (deleteFS) 169 fFileSystems->Remove(name); 170 } 171 172 // delete the FS, if the last reference has been removed 173 if (deleteFS) 174 delete fileSystemInitializer; 175 return B_OK; 176} 177