* Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "FileSystemInitializer.h"
#include <new>
#include <image.h>
#include <OS.h>
#include <port.h>
#include <team.h>
#include "AutoDeleter.h"
#include "FileSystem.h"
#include "RequestAllocator.h"
#include "RequestPort.h"
#include "Requests.h"
#include "SingleReplyRequestHandler.h"
#include "UserlandFSDefs.h"
FileSystemInitializer::FileSystemInitializer(const char* name)
:
BReferenceable(),
fName(name),
fFileSystem(NULL)
{
}
FileSystemInitializer::~FileSystemInitializer()
{
delete fFileSystem;
}
status_t
FileSystemInitializer::FirstTimeInit()
{
char portName[B_OS_NAME_LENGTH];
snprintf(portName, sizeof(portName), "_userlandfs_%s", fName);
port_id port = find_port(portName);
if (port >= 0)
return _Init(port);
port = create_port(1, portName);
if (port < 0)
RETURN_ERROR(port);
char portID[16];
snprintf(portID, sizeof(portID), "%" B_PRId32, port);
const char* args[4] = {
"/system/servers/userlandfs_server",
fName,
portID,
NULL
};
thread_id thread = load_image_etc(3, args, NULL, B_NORMAL_PRIORITY,
B_SYSTEM_TEAM, 0);
if (thread < 0) {
delete_port(port);
RETURN_ERROR(thread);
}
status_t error = set_port_owner(port, thread);
if (error == B_OK)
resume_thread(thread);
if (error == B_OK)
error = _Init(port);
if (error != B_OK) {
kill_team(thread);
delete_port(port);
RETURN_ERROR(error);
}
return B_OK;
}
void
FileSystemInitializer::LastReferenceReleased()
{
}
status_t
FileSystemInitializer::_Init(port_id port)
{
const size_t bufferSize = 1024;
fs_init_info* info = (fs_init_info*)malloc(bufferSize);
MemoryDeleter _(info);
ssize_t bytesRead = read_port_etc(port, NULL, info, bufferSize,
B_PEEK_PORT_MESSAGE | B_CAN_INTERRUPT, 0);
if (bytesRead < 0)
RETURN_ERROR(bytesRead);
if ((size_t)bytesRead < sizeof(fs_init_info)
|| info->portInfoCount < 2
|| (size_t)bytesRead < sizeof(fs_init_info)
+ info->portInfoCount * sizeof(Port::Info)) {
RETURN_ERROR(B_BAD_DATA);
}
port_info portInfo;
status_t error = get_port_info(port, &portInfo);
if (error != B_OK)
RETURN_ERROR(error);
fFileSystem = new(std::nothrow) FileSystem;
if (!fFileSystem)
return B_NO_MEMORY;
error = fFileSystem->Init(fName, portInfo.team, info->portInfos,
info->portInfoCount, info->capabilities);
if (error != B_OK)
RETURN_ERROR(error);
return B_OK;
}