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 BReferenceable(), 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), "%" B_PRId32, 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 void 103 FileSystemInitializer::LastReferenceReleased() 104 { 105 // don't delete 106 } 107 108 109 status_t 110 FileSystemInitializer::_Init(port_id port) 111 { 112 // allocate a buffer for the FS info 113 const size_t bufferSize = 1024; 114 fs_init_info* info = (fs_init_info*)malloc(bufferSize); 115 MemoryDeleter _(info); 116 117 // Read the info -- we peek only, so it won't go away and we can do the 118 // initialization again, in case we get completely unloaded are reloaded 119 // later. 120 ssize_t bytesRead = read_port_etc(port, NULL, info, bufferSize, 121 B_PEEK_PORT_MESSAGE | B_CAN_INTERRUPT, 0); 122 if (bytesRead < 0) 123 RETURN_ERROR(bytesRead); 124 125 // sanity check 126 if ((size_t)bytesRead < sizeof(fs_init_info) 127 || info->portInfoCount < 2 128 || (size_t)bytesRead < sizeof(fs_init_info) 129 + info->portInfoCount * sizeof(Port::Info)) { 130 RETURN_ERROR(B_BAD_DATA); 131 } 132 133 // get the port's team 134 port_info portInfo; 135 status_t error = get_port_info(port, &portInfo); 136 if (error != B_OK) 137 RETURN_ERROR(error); 138 139 // create and init the FileSystem 140 fFileSystem = new(std::nothrow) FileSystem; 141 if (!fFileSystem) 142 return B_NO_MEMORY; 143 144 error = fFileSystem->Init(fName, portInfo.team, info->portInfos, 145 info->portInfoCount, info->capabilities); 146 if (error != B_OK) 147 RETURN_ERROR(error); 148 149 return B_OK; 150 } 151