1// BeOSKernelFileSystem.cpp
2
3#include "BeOSKernelFileSystem.h"
4
5#include <new>
6
7#include "beos_kernel_emu.h"
8#include "BeOSKernelVolume.h"
9#include "fs_cache.h"
10#include "fs_interface.h"
11
12
13static const int32 kMaxBlockCacheBlocks = 16384;
14
15
16// constructor
17BeOSKernelFileSystem::BeOSKernelFileSystem(const char* fsName,
18	beos_vnode_ops* fsOps)
19	:
20	FileSystem(fsName),
21	fFSOps(fsOps),
22	fBlockCacheInitialized(false)
23{
24	_InitCapabilities();
25}
26
27
28// destructor
29BeOSKernelFileSystem::~BeOSKernelFileSystem()
30{
31	if (fBlockCacheInitialized)
32		beos_shutdown_block_cache();
33}
34
35
36// Init
37status_t
38BeOSKernelFileSystem::Init()
39{
40	// init the block cache
41	status_t error = beos_init_block_cache(kMaxBlockCacheBlocks, 0);
42	if (error != B_OK)
43		RETURN_ERROR(error);
44
45	fBlockCacheInitialized = true;
46	return B_OK;
47}
48
49
50// CreateVolume
51status_t
52BeOSKernelFileSystem::CreateVolume(Volume** volume, dev_t id)
53{
54	// check initialization and parameters
55	if (!fFSOps || !volume)
56		return B_BAD_VALUE;
57
58	// create the volume
59	*volume = new(std::nothrow) BeOSKernelVolume(this, id, fFSOps,
60		fVolumeCapabilities);
61	if (!*volume)
62		return B_NO_MEMORY;
63	return B_OK;
64}
65
66// DeleteVolume
67status_t
68BeOSKernelFileSystem::DeleteVolume(Volume* volume)
69{
70	if (!volume || !dynamic_cast<BeOSKernelVolume*>(volume))
71		return B_BAD_VALUE;
72	delete volume;
73	return B_OK;
74}
75
76// _InitCapabilities
77void
78BeOSKernelFileSystem::_InitCapabilities()
79{
80	fCapabilities.ClearAll();
81	fVolumeCapabilities.ClearAll();
82	fNodeCapabilities.ClearAll();
83
84	// FS interface type
85	fClientFSType = CLIENT_FS_BEOS_KERNEL;
86
87	// FS operations
88	fCapabilities.Set(FS_CAPABILITY_MOUNT, fFSOps->mount);
89
90
91	// Volume operations
92	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_UNMOUNT, fFSOps->unmount);
93
94	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_READ_FS_INFO, fFSOps->rfsstat);
95	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_WRITE_FS_INFO,
96		fFSOps->wfsstat);
97	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_SYNC, fFSOps->sync);
98
99	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_GET_VNODE, fFSOps->read_vnode);
100
101	// index directory & index operations
102	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_OPEN_INDEX_DIR,
103		fFSOps->open_indexdir);
104	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_CLOSE_INDEX_DIR,
105		fFSOps->close_indexdir);
106	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_FREE_INDEX_DIR_COOKIE,
107		fFSOps->free_indexdircookie);
108	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_READ_INDEX_DIR,
109		fFSOps->read_indexdir);
110	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_REWIND_INDEX_DIR,
111		fFSOps->rewind_indexdir);
112
113	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_CREATE_INDEX,
114		fFSOps->create_index);
115	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_REMOVE_INDEX,
116		fFSOps->remove_index);
117	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_READ_INDEX_STAT,
118		fFSOps->stat_index);
119
120	// query operations
121	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_OPEN_QUERY,
122		fFSOps->open_query);
123	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_CLOSE_QUERY,
124		fFSOps->close_query);
125	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_FREE_QUERY_COOKIE,
126		fFSOps->free_querycookie);
127	fVolumeCapabilities.Set(FS_VOLUME_CAPABILITY_READ_QUERY,
128		fFSOps->read_query);
129	// missing: FS_VOLUME_CAPABILITY_REWIND_QUERY,
130
131	// vnode operations
132	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_LOOKUP, fFSOps->walk);
133	// missing: FS_VNODE_CAPABILITY_GET_VNODE_NAME,
134
135	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_PUT_VNODE, fFSOps->write_vnode);
136	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_REMOVE_VNODE,
137		fFSOps->remove_vnode);
138
139	// VM file access
140	// missing: FS_VNODE_CAPABILITY_CAN_PAGE,
141	// missing: FS_VNODE_CAPABILITY_READ_PAGES,
142	// missing: FS_VNODE_CAPABILITY_WRITE_PAGES,
143
144	// cache file access
145	// missing: FS_VNODE_CAPABILITY_GET_FILE_MAP,
146
147	// common operations
148	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_IOCTL, fFSOps->ioctl);
149	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_SET_FLAGS, fFSOps->setflags);
150	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_SELECT, fFSOps->select);
151	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_DESELECT, fFSOps->deselect);
152	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_FSYNC, fFSOps->fsync);
153
154	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ_SYMLINK, fFSOps->readlink);
155	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_CREATE_SYMLINK, fFSOps->symlink);
156
157	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_LINK, fFSOps->link);
158	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_UNLINK, fFSOps->unlink);
159	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_RENAME, fFSOps->rename);
160
161	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_ACCESS, fFSOps->access);
162	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ_STAT, fFSOps->rstat);
163	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_WRITE_STAT, fFSOps->wstat);
164
165	// file operations
166	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_CREATE, fFSOps->create);
167	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_OPEN, fFSOps->open);
168	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_CLOSE, fFSOps->close);
169	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_FREE_COOKIE, fFSOps->free_cookie);
170	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ, fFSOps->read);
171	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_WRITE, fFSOps->write);
172
173	// directory operations
174	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_CREATE_DIR, fFSOps->mkdir);
175	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_REMOVE_DIR, fFSOps->rmdir);
176	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_OPEN_DIR, fFSOps->opendir);
177	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_CLOSE_DIR, fFSOps->closedir);
178	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_FREE_DIR_COOKIE,
179		fFSOps->free_dircookie);
180	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ_DIR, fFSOps->readdir);
181	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_REWIND_DIR, fFSOps->rewinddir);
182
183	// attribute directory operations
184	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_OPEN_ATTR_DIR,
185		fFSOps->open_attrdir);
186	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_CLOSE_ATTR_DIR,
187		fFSOps->close_attrdir);
188	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_FREE_ATTR_DIR_COOKIE,
189		fFSOps->free_attrdircookie);
190	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR_DIR,
191		fFSOps->read_attrdir);
192	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_REWIND_ATTR_DIR,
193		fFSOps->rewind_attrdir);
194
195	// attribute operations
196	// we emulate open_attr() and free_attr_dir_cookie() if either read_attr()
197	// or write_attr() is present
198	bool hasAttributes = (fFSOps->read_attr || fFSOps->write_attr);
199	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_CREATE_ATTR, hasAttributes);
200	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_OPEN_ATTR, hasAttributes);
201	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_CLOSE_ATTR, false);
202	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_FREE_ATTR_COOKIE, hasAttributes);
203	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR, fFSOps->read_attr);
204	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_WRITE_ATTR, fFSOps->write_attr);
205
206	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR_STAT,
207		fFSOps->stat_attr);
208	// missing: FS_VNODE_CAPABILITY_WRITE_ATTR_STAT
209	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_RENAME_ATTR, fFSOps->rename_attr);
210	fNodeCapabilities.Set(FS_VNODE_CAPABILITY_REMOVE_ATTR, fFSOps->remove_attr);
211}
212
213
214// #pragma mark -
215
216
217// get_beos_file_system_node_capabilities
218//
219// Service function for beos_kernel_emu.cpp. Declared in beos_kernel_emu.h.
220void
221get_beos_file_system_node_capabilities(FSVNodeCapabilities& capabilities)
222{
223	BeOSKernelFileSystem* fileSystem
224		= static_cast<BeOSKernelFileSystem*>(FileSystem::GetInstance());
225	fileSystem->GetNodeCapabilities(capabilities);
226}
227
228
229// #pragma mark - bootstrapping
230
231
232status_t
233userlandfs_create_file_system(const char* fsName, image_id image,
234	FileSystem** _fileSystem)
235{
236	// get the symbols "fs_entry" and "api_version"
237	beos_vnode_ops* fsOps;
238	status_t error = get_image_symbol(image, "fs_entry", B_SYMBOL_TYPE_DATA,
239		(void**)&fsOps);
240	if (error != B_OK)
241		RETURN_ERROR(error);
242	int32* apiVersion;
243	error = get_image_symbol(image, "api_version", B_SYMBOL_TYPE_DATA,
244		(void**)&apiVersion);
245	if (error != B_OK)
246		RETURN_ERROR(error);
247
248	// check api version
249	if (*apiVersion != BEOS_FS_API_VERSION)
250		RETURN_ERROR(B_ERROR);
251
252	// create the file system
253	BeOSKernelFileSystem* fileSystem
254		= new(std::nothrow) BeOSKernelFileSystem(fsName, fsOps);
255	if (!fileSystem)
256		RETURN_ERROR(B_NO_MEMORY);
257
258	error = fileSystem->Init();
259	if (error != B_OK) {
260		delete fileSystem;
261		return error;
262	}
263
264	*_fileSystem = fileSystem;
265	return B_OK;
266}
267