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
20 UserlandFS* UserlandFS::sUserlandFS = NULL;
21
22 // constructor
UserlandFS()23 UserlandFS::UserlandFS()
24 :
25 fFileSystems(NULL),
26 fDebuggerCommandsAdded(false)
27 {
28 }
29
30 // destructor
~UserlandFS()31 UserlandFS::~UserlandFS()
32 {
33 PRINT(("UserlandFS::~UserlandFS()\n"))
34 delete fFileSystems;
35 if (fDebuggerCommandsAdded)
36 KernelDebug::RemoveDebuggerCommands();
37 }
38
39 // InitUserlandFS
40 status_t
InitUserlandFS(UserlandFS ** _userlandFS)41 UserlandFS::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
62 void
UninitUserlandFS()63 UserlandFS::UninitUserlandFS()
64 {
65 delete sUserlandFS;
66 sUserlandFS = NULL;
67 }
68
69 // GetUserlandFS
70 UserlandFS*
GetUserlandFS()71 UserlandFS::GetUserlandFS()
72 {
73 return sUserlandFS;
74 }
75
76 // RegisterFileSystem
77 status_t
RegisterFileSystem(const char * name,FileSystem ** _fileSystem)78 UserlandFS::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
116 status_t
UnregisterFileSystem(FileSystem * fileSystem)117 UserlandFS::UnregisterFileSystem(FileSystem* fileSystem)
118 {
119 if (!fileSystem)
120 return B_BAD_VALUE;
121
122 return _UnregisterFileSystem(fileSystem->GetName());
123 }
124
125 // CountFileSystems
126 int32
CountFileSystems() const127 UserlandFS::CountFileSystems() const
128 {
129 return fFileSystems->Size();
130 }
131
132 // _Init
133 status_t
_Init()134 UserlandFS::_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
152 status_t
_UnregisterFileSystem(const char * name)153 UserlandFS::_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