1 /* 2 * Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include "FileSystemInitializer.h" 7 8 #include <new> 9 10 #include <image.h> 11 #include <OS.h> 12 13 #include <port.h> 14 #include <team.h> 15 16 #include "AutoDeleter.h" 17 18 #include "FileSystem.h" 19 #include "RequestAllocator.h" 20 #include "RequestPort.h" 21 #include "Requests.h" 22 #include "SingleReplyRequestHandler.h" 23 #include "UserlandFSDefs.h" 24 25 26 // constructor 27 FileSystemInitializer::FileSystemInitializer(const char* name) 28 : 29 Referenceable(false), 30 fName(name), 31 fFileSystem(NULL) 32 { 33 // Note: We don't copy the name. It's only needed in FirstTimeInit() and 34 // the UserlandFS makes sure it is valid until then. 35 } 36 37 38 // destructor 39 FileSystemInitializer::~FileSystemInitializer() 40 { 41 delete fFileSystem; 42 } 43 44 45 // FirstTimeInit 46 status_t 47 FileSystemInitializer::FirstTimeInit() 48 { 49 // First check whether a server for this FS is already loaded. Look for a 50 // port with the respective name. 51 char portName[B_OS_NAME_LENGTH]; 52 snprintf(portName, sizeof(portName), "_userlandfs_%s", fName); 53 54 port_id port = find_port(portName); 55 if (port >= 0) 56 return _Init(port); 57 58 // We have to start the server ourselves. First create the port we're going 59 // to use. 60 port = create_port(1, portName); 61 if (port < 0) 62 RETURN_ERROR(port); 63 64 // prepare the command line arguments 65 char portID[16]; 66 snprintf(portID, sizeof(portID), "%ld", port); 67 68 const char* args[4] = { 69 "/system/servers/userlandfs_server", 70 fName, 71 portID, 72 NULL 73 }; 74 75 // start the server 76 thread_id thread = load_image_etc(3, args, NULL, B_NORMAL_PRIORITY, 77 B_SYSTEM_TEAM, 0); 78 if (thread < 0) { 79 delete_port(port); 80 RETURN_ERROR(thread); 81 } 82 83 // let it own the port and start the team 84 status_t error = set_port_owner(port, thread); 85 if (error == B_OK) 86 resume_thread(thread); 87 88 // and do the initialization 89 if (error == B_OK) 90 error = _Init(port); 91 92 if (error != B_OK) { 93 kill_team(thread); 94 delete_port(port); 95 RETURN_ERROR(error); 96 } 97 98 return B_OK; 99 } 100 101 102 status_t 103 FileSystemInitializer::_Init(port_id port) 104 { 105 // allocate a buffer for the FS info 106 const size_t bufferSize = 1024; 107 fs_init_info* info = (fs_init_info*)malloc(bufferSize); 108 MemoryDeleter _(info); 109 110 // Read the info -- we peek only, so it won't go away and we can do the 111 // initialization again, in case we get completely unloaded are reloaded 112 // later. 113 ssize_t bytesRead = read_port_etc(port, NULL, info, bufferSize, 114 B_PEEK_PORT_MESSAGE | B_CAN_INTERRUPT, 0); 115 if (bytesRead < 0) 116 RETURN_ERROR(bytesRead); 117 118 // sanity check 119 if ((size_t)bytesRead < sizeof(fs_init_info) 120 || info->portInfoCount < 2 121 || (size_t)bytesRead < sizeof(fs_init_info) 122 + info->portInfoCount * sizeof(Port::Info)) { 123 RETURN_ERROR(B_BAD_DATA); 124 } 125 126 // get the port's team 127 port_info portInfo; 128 status_t error = get_port_info(port, &portInfo); 129 if (error != B_OK) 130 RETURN_ERROR(error); 131 132 // create and init the FileSystem 133 fFileSystem = new(std::nothrow) FileSystem; 134 if (!fFileSystem) 135 return B_NO_MEMORY; 136 137 error = fFileSystem->Init(fName, portInfo.team, info->portInfos, 138 info->portInfoCount, info->capabilities); 139 if (error != B_OK) 140 RETURN_ERROR(error); 141 142 return B_OK; 143 } 144