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