1// kernel_emu.cpp 2 3#include <stdarg.h> 4#include <stdio.h> 5#include <stdlib.h> 6 7#include <fsproto.h> 8#include <KernelExport.h> 9#include <OS.h> 10 11#include "RequestPort.h" 12#include "Requests.h" 13#include "RequestThread.h" 14#include "UserlandFSServer.h" 15#include "UserlandRequestHandler.h" 16 17// Taken from the OBOS Storage Kit (storage_support.cpp) 18/*! The length of the first component is returned as well as the index at 19 which the next one starts. These values are only valid, if the function 20 returns \c B_OK. 21 \param path the path to be parsed 22 \param length the variable the length of the first component is written 23 into 24 \param nextComponent the variable the index of the next component is 25 written into. \c 0 is returned, if there is no next component. 26 \return \c B_OK, if \a path is not \c NULL, \c B_BAD_VALUE otherwise 27*/ 28static 29status_t 30parse_first_path_component(const char *path, int32& length, 31 int32& nextComponent) 32{ 33 status_t error = (path ? B_OK : B_BAD_VALUE); 34 if (error == B_OK) { 35 int32 i = 0; 36 // find first '/' or end of name 37 for (; path[i] != '/' && path[i] != '\0'; i++); 38 // handle special case "/..." (absolute path) 39 if (i == 0 && path[i] != '\0') 40 i = 1; 41 length = i; 42 // find last '/' or end of name 43 for (; path[i] == '/' && path[i] != '\0'; i++); 44 if (path[i] == '\0') // this covers "" as well 45 nextComponent = 0; 46 else 47 nextComponent = i; 48 } 49 return error; 50} 51 52// new_path 53int 54new_path(const char *path, char **copy) 55{ 56 // check errors and special cases 57 if (!copy) 58 return B_BAD_VALUE; 59 if (!path) { 60 *copy = NULL; 61 return B_OK; 62 } 63 int32 len = strlen(path); 64 if (len < 1) 65 return B_ENTRY_NOT_FOUND; 66 bool appendDot = (path[len - 1] == '/'); 67 if (appendDot) 68 len++; 69 if (len >= B_PATH_NAME_LENGTH) 70 return B_NAME_TOO_LONG; 71 // check the path components 72 const char *remainder = path; 73 int32 length, nextComponent; 74 do { 75 status_t error 76 = parse_first_path_component(remainder, length, nextComponent); 77 if (error != B_OK) 78 return error; 79 if (length >= B_FILE_NAME_LENGTH) 80 error = B_NAME_TOO_LONG; 81 remainder += nextComponent; 82 } while (nextComponent != 0); 83 // clone the path 84 char *copiedPath = (char*)malloc(len + 1); 85 if (!copiedPath) 86 return B_NO_MEMORY; 87 strcpy(copiedPath, path); 88 // append a dot, if desired 89 if (appendDot) { 90 copiedPath[len] = '.'; 91 copiedPath[len] = '\0'; 92 } 93 *copy = copiedPath; 94 return B_OK; 95} 96 97// free_path 98void 99free_path(char *p) 100{ 101 free(p); 102} 103 104// #pragma mark - 105 106// get_port_and_fs 107static 108status_t 109get_port_and_fs(RequestPort** port, UserFileSystem** fileSystem) 110{ 111 // get the request thread 112 RequestThread* thread = RequestThread::GetCurrentThread(); 113 if (thread) { 114 *port = thread->GetPort(); 115 *fileSystem = thread->GetFileSystem(); 116 } else { 117 *port = UserlandFSServer::GetNotificationRequestPort(); 118 *fileSystem = UserlandFSServer::GetFileSystem(); 119 if (!*port || !*fileSystem) 120 return B_BAD_VALUE; 121 } 122 return B_OK; 123} 124 125// notify_listener 126int 127notify_listener(int op, nspace_id nsid, vnode_id vnida, vnode_id vnidb, 128 vnode_id vnidc, const char *name) 129{ 130 // get the request port and the file system 131 RequestPort* port; 132 UserFileSystem* fileSystem; 133 status_t error = get_port_and_fs(&port, &fileSystem); 134 if (error != B_OK) 135 return error; 136 // prepare the request 137 RequestAllocator allocator(port->GetPort()); 138 NotifyListenerRequest* request; 139 error = AllocateRequest(allocator, &request); 140 if (error != B_OK) 141 return error; 142 request->operation = op; 143 request->nsid = nsid; 144 request->vnida = vnida; 145 request->vnidb = vnidb; 146 request->vnidc = vnidc; 147 error = allocator.AllocateString(request->name, name); 148 if (error != B_OK) 149 return error; 150 // send the request 151 UserlandRequestHandler handler(fileSystem, NOTIFY_LISTENER_REPLY); 152 NotifyListenerReply* reply; 153 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 154 if (error != B_OK) 155 return error; 156 RequestReleaser requestReleaser(port, reply); 157 // process the reply 158 if (reply->error != B_OK) 159 return reply->error; 160 return error; 161} 162 163// notify_select_event 164void 165notify_select_event(selectsync *sync, uint32 ref) 166{ 167 // get the request port and the file system 168 RequestPort* port; 169 UserFileSystem* fileSystem; 170 status_t error = get_port_and_fs(&port, &fileSystem); 171 if (error != B_OK) 172 return; 173 // prepare the request 174 RequestAllocator allocator(port->GetPort()); 175 NotifySelectEventRequest* request; 176 error = AllocateRequest(allocator, &request); 177 if (error != B_OK) 178 return; 179 request->sync = sync; 180 request->ref = ref; 181 // send the request 182 UserlandRequestHandler handler(fileSystem, NOTIFY_SELECT_EVENT_REPLY); 183 NotifySelectEventReply* reply; 184 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 185 if (error != B_OK) 186 return; 187 RequestReleaser requestReleaser(port, reply); 188 // process the reply: nothing to do 189} 190 191// send_notification 192int 193send_notification(port_id targetPort, long token, ulong what, long op, 194 nspace_id nsida, nspace_id nsidb, vnode_id vnida, vnode_id vnidb, 195 vnode_id vnidc, const char *name) 196{ 197 // get the request port and the file system 198 RequestPort* port; 199 UserFileSystem* fileSystem; 200 status_t error = get_port_and_fs(&port, &fileSystem); 201 if (error != B_OK) 202 return error; 203 // prepare the request 204 RequestAllocator allocator(port->GetPort()); 205 SendNotificationRequest* request; 206 error = AllocateRequest(allocator, &request); 207 if (error != B_OK) 208 return error; 209 request->port = targetPort; 210 request->token = token; 211 request->what = what; 212 request->operation = op; 213 request->nsida = nsida; 214 request->nsidb = nsidb; 215 request->vnida = vnida; 216 request->vnidb = vnidb; 217 request->vnidc = vnidc; 218 error = allocator.AllocateString(request->name, name); 219 if (error != B_OK) 220 return error; 221 // send the request 222 UserlandRequestHandler handler(fileSystem, SEND_NOTIFICATION_REPLY); 223 SendNotificationReply* reply; 224 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 225 if (error != B_OK) 226 return error; 227 RequestReleaser requestReleaser(port, reply); 228 // process the reply 229 if (reply->error != B_OK) 230 return reply->error; 231 return error; 232} 233 234// #pragma mark - 235 236// get_vnode 237_EXPORT 238int 239get_vnode(nspace_id nsid, vnode_id vnid, void** data) 240{ 241 // get the request port and the file system 242 RequestPort* port; 243 UserFileSystem* fileSystem; 244 status_t error = get_port_and_fs(&port, &fileSystem); 245 if (error != B_OK) 246 return error; 247 // prepare the request 248 RequestAllocator allocator(port->GetPort()); 249 GetVNodeRequest* request; 250 error = AllocateRequest(allocator, &request); 251 if (error != B_OK) 252 return error; 253 request->nsid = nsid; 254 request->vnid = vnid; 255 // send the request 256 UserlandRequestHandler handler(fileSystem, GET_VNODE_REPLY); 257 GetVNodeReply* reply; 258 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 259 if (error != B_OK) 260 return error; 261 RequestReleaser requestReleaser(port, reply); 262 // process the reply 263 if (reply->error != B_OK) 264 return reply->error; 265 *data = reply->node; 266 return error; 267} 268 269// put_vnode 270_EXPORT 271int 272put_vnode(nspace_id nsid, vnode_id vnid) 273{ 274 // get the request port and the file system 275 RequestPort* port; 276 UserFileSystem* fileSystem; 277 status_t error = get_port_and_fs(&port, &fileSystem); 278 if (error != B_OK) 279 return error; 280 // prepare the request 281 RequestAllocator allocator(port->GetPort()); 282 PutVNodeRequest* request; 283 error = AllocateRequest(allocator, &request); 284 if (error != B_OK) 285 return error; 286 request->nsid = nsid; 287 request->vnid = vnid; 288 // send the request 289 UserlandRequestHandler handler(fileSystem, PUT_VNODE_REPLY); 290 PutVNodeReply* reply; 291 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 292 if (error != B_OK) 293 return error; 294 RequestReleaser requestReleaser(port, reply); 295 // process the reply 296 if (reply->error != B_OK) 297 return reply->error; 298 return error; 299} 300 301// new_vnode 302_EXPORT 303int 304new_vnode(nspace_id nsid, vnode_id vnid, void* data) 305{ 306 // get the request port and the file system 307 RequestPort* port; 308 UserFileSystem* fileSystem; 309 status_t error = get_port_and_fs(&port, &fileSystem); 310 if (error != B_OK) 311 return error; 312 // prepare the request 313 RequestAllocator allocator(port->GetPort()); 314 NewVNodeRequest* request; 315 error = AllocateRequest(allocator, &request); 316 if (error != B_OK) 317 return error; 318 request->nsid = nsid; 319 request->vnid = vnid; 320 request->node = data; 321 // send the request 322 UserlandRequestHandler handler(fileSystem, NEW_VNODE_REPLY); 323 NewVNodeReply* reply; 324 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 325 if (error != B_OK) 326 return error; 327 RequestReleaser requestReleaser(port, reply); 328 // process the reply 329 if (reply->error != B_OK) 330 return reply->error; 331 return error; 332} 333 334// remove_vnode 335_EXPORT 336int 337remove_vnode(nspace_id nsid, vnode_id vnid) 338{ 339 // get the request port and the file system 340 RequestPort* port; 341 UserFileSystem* fileSystem; 342 status_t error = get_port_and_fs(&port, &fileSystem); 343 if (error != B_OK) 344 return error; 345 // prepare the request 346 RequestAllocator allocator(port->GetPort()); 347 RemoveVNodeRequest* request; 348 error = AllocateRequest(allocator, &request); 349 if (error != B_OK) 350 return error; 351 request->nsid = nsid; 352 request->vnid = vnid; 353 // send the request 354 UserlandRequestHandler handler(fileSystem, REMOVE_VNODE_REPLY); 355 RemoveVNodeReply* reply; 356 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 357 if (error != B_OK) 358 return error; 359 RequestReleaser requestReleaser(port, reply); 360 // process the reply 361 if (reply->error != B_OK) 362 return reply->error; 363 return error; 364} 365 366// unremove_vnode 367_EXPORT 368int 369unremove_vnode(nspace_id nsid, vnode_id vnid) 370{ 371 // get the request port and the file system 372 RequestPort* port; 373 UserFileSystem* fileSystem; 374 status_t error = get_port_and_fs(&port, &fileSystem); 375 if (error != B_OK) 376 return error; 377 // prepare the request 378 RequestAllocator allocator(port->GetPort()); 379 UnremoveVNodeRequest* request; 380 error = AllocateRequest(allocator, &request); 381 if (error != B_OK) 382 return error; 383 request->nsid = nsid; 384 request->vnid = vnid; 385 // send the request 386 UserlandRequestHandler handler(fileSystem, UNREMOVE_VNODE_REPLY); 387 UnremoveVNodeReply* reply; 388 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 389 if (error != B_OK) 390 return error; 391 RequestReleaser requestReleaser(port, reply); 392 // process the reply 393 if (reply->error != B_OK) 394 return reply->error; 395 return error; 396} 397 398// is_vnode_removed 399_EXPORT 400int 401is_vnode_removed(nspace_id nsid, vnode_id vnid) 402{ 403 // get the request port and the file system 404 RequestPort* port; 405 UserFileSystem* fileSystem; 406 status_t error = get_port_and_fs(&port, &fileSystem); 407 if (error != B_OK) 408 return error; 409 // prepare the request 410 RequestAllocator allocator(port->GetPort()); 411 IsVNodeRemovedRequest* request; 412 error = AllocateRequest(allocator, &request); 413 if (error != B_OK) 414 return error; 415 request->nsid = nsid; 416 request->vnid = vnid; 417 // send the request 418 UserlandRequestHandler handler(fileSystem, IS_VNODE_REMOVED_REPLY); 419 IsVNodeRemovedReply* reply; 420 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 421 if (error != B_OK) 422 return error; 423 RequestReleaser requestReleaser(port, reply); 424 // process the reply 425 if (reply->error != B_OK) 426 return reply->error; 427 return reply->result; 428} 429 430// #pragma mark - 431 432// kernel_debugger 433_EXPORT 434void 435kernel_debugger(const char *message) 436{ 437 debugger(message); 438} 439 440// panic 441_EXPORT 442void 443panic(const char *format, ...) 444{ 445 char buffer[1024]; 446 strcpy(buffer, "PANIC: "); 447 int32 prefixLen = strlen(buffer); 448 int bufferSize = sizeof(buffer) - prefixLen; 449 va_list args; 450 va_start(args, format); 451 // no vsnprintf() on PPC 452 #if defined(__INTEL__) 453 vsnprintf(buffer + prefixLen, bufferSize - 1, format, args); 454 #else 455 vsprintf(buffer + prefixLen, format, args); 456 #endif 457 va_end(args); 458 buffer[sizeof(buffer) - 1] = '\0'; 459 debugger(buffer); 460} 461 462// parse_expression 463_EXPORT 464ulong 465parse_expression(char *str) 466{ 467 return 0; 468} 469 470// add_debugger_command 471_EXPORT 472int 473add_debugger_command(char *name, int (*func)(int argc, char **argv), 474 char *help) 475{ 476 return B_OK; 477} 478 479// remove_debugger_command 480_EXPORT 481int 482remove_debugger_command(char *name, int (*func)(int argc, char **argv)) 483{ 484 return B_OK; 485} 486 487// kprintf 488_EXPORT 489void 490kprintf(const char *format, ...) 491{ 492} 493 494// spawn_kernel_thread 495thread_id 496spawn_kernel_thread(thread_entry function, const char *threadName, 497 long priority, void *arg) 498{ 499 return spawn_thread(function, threadName, priority, arg); 500} 501 502