|
24 | 24 | #include <sys/protosw.h>
|
25 | 25 |
|
26 | 26 | #include <ps4/kernel.h>
|
| 27 | +#include <ps4/error.h> |
27 | 28 |
|
28 | 29 | int ps4KernelSocketCreate(struct thread *td, Ps4KernelSocket **sock, int domain, int type, int protocol)
|
29 | 30 | {
|
@@ -367,3 +368,152 @@ int ps4KernelSocketSend(struct thread *td, Ps4KernelSocket *sock, const void *da
|
367 | 368 |
|
368 | 369 | return sosend(sock, NULL, &auio, 0, NULL, 0, td);
|
369 | 370 | }
|
| 371 | + |
| 372 | +int ps4StringEstimateFormatArguments(const char *format, size_t *count) |
| 373 | +{ |
| 374 | + size_t c = 0; |
| 375 | + |
| 376 | + if(format == NULL) |
| 377 | + return PS4_ERROR_ARGUMENT_PRIMARY_MISSING; |
| 378 | + |
| 379 | + if(count == NULL) |
| 380 | + return PS4_ERROR_ARGUMENT_OUT_MISSING; |
| 381 | + |
| 382 | + for(size_t i = 0; format[i] != '\0'; ++i) |
| 383 | + { |
| 384 | + if(format[i] == '%') |
| 385 | + { |
| 386 | + ++c; |
| 387 | + |
| 388 | + if(format[i + 1] == '\0') |
| 389 | + return PS4_ERROR_ARGUMENT_MALFORMED; |
| 390 | + |
| 391 | + if(format[i + 1] == '%') |
| 392 | + i++; |
| 393 | + } |
| 394 | + } |
| 395 | + |
| 396 | + *count = c; |
| 397 | + |
| 398 | + return PS4_OK; |
| 399 | +} |
| 400 | + |
| 401 | +// FIXME: Slow, improve me |
| 402 | +int ps4KernelSocketReceiveString(struct thread *td, Ps4KernelSocket *sock, void **data, size_t *size, size_t sizeMax) |
| 403 | +{ |
| 404 | + uint8_t *_data; |
| 405 | + size_t _size; |
| 406 | + size_t offset; |
| 407 | + size_t outSize; |
| 408 | + int r; |
| 409 | + |
| 410 | + if(sizeMax == 0) |
| 411 | + sizeMax = SIZE_MAX; |
| 412 | + |
| 413 | + _size = 1024; |
| 414 | + if(_size > sizeMax - 1) |
| 415 | + _size = sizeMax - 1; |
| 416 | + |
| 417 | + offset = 0; |
| 418 | + |
| 419 | + ps4KernelMemoryAllocateData((void **)&_data, _size + 1); |
| 420 | + |
| 421 | + while(1) |
| 422 | + { |
| 423 | + r = ps4KernelSocketReceive(td, sock, _data + offset, &outSize, 1, MSG_WAITALL); |
| 424 | + |
| 425 | + if(r != PS4_OK) |
| 426 | + { |
| 427 | + ps4KernelMemoryFree(data); |
| 428 | + return PS4_ERROR_BAD_REQUEST; |
| 429 | + } |
| 430 | + |
| 431 | + if(_data[offset] == '\n') |
| 432 | + break; |
| 433 | + |
| 434 | + if(offset == _size) |
| 435 | + { |
| 436 | + _size *= 2; |
| 437 | + ps4KernelMemoryReallocateData((void **)&_data, _size + 1); |
| 438 | + } |
| 439 | + |
| 440 | + ++offset; |
| 441 | + } |
| 442 | + |
| 443 | + _data[offset + 1] = '\0'; |
| 444 | + *data = (void *)_data; |
| 445 | + *size = offset + 2; |
| 446 | + |
| 447 | + return PS4_OK; |
| 448 | +} |
| 449 | + |
| 450 | +int ps4KernelSocketScanSizedWithArgumentList(struct thread *td, Ps4KernelSocket *sock, size_t size, int *match, const char *format, va_list args) |
| 451 | +{ |
| 452 | + void *data; |
| 453 | + int r; |
| 454 | + size_t outSize; |
| 455 | + |
| 456 | + if(match == NULL || format == NULL) |
| 457 | + return PS4_ERROR_ARGUMENT_MISSING; |
| 458 | + |
| 459 | + r = ps4KernelSocketReceiveString(td, sock, &data, &outSize, size); |
| 460 | + |
| 461 | + if(r == PS4_OK) |
| 462 | + { |
| 463 | + *match = vsscanf(data, format, args); |
| 464 | + ps4KernelMemoryFree(data); |
| 465 | + } |
| 466 | + |
| 467 | + return r; |
| 468 | +} |
| 469 | + |
| 470 | +int ps4KernelSocketScanWithArgumentList(struct thread *td, Ps4KernelSocket *sock, int *match, const char *format, va_list args) |
| 471 | +{ |
| 472 | + return ps4KernelSocketScanSizedWithArgumentList(td, sock, 0, match, format, args); |
| 473 | +} |
| 474 | + |
| 475 | +int ps4KernelSocketScan(struct thread *td, Ps4KernelSocket *sock, int *match, const char *format, ...) |
| 476 | +{ |
| 477 | + va_list args; |
| 478 | + int r; |
| 479 | + |
| 480 | + va_start(args, format); |
| 481 | + r = ps4KernelSocketScanWithArgumentList(td, sock, match, format, args); |
| 482 | + va_end(args); |
| 483 | + |
| 484 | + return r; |
| 485 | +} |
| 486 | + |
| 487 | +int ps4KernelSocketReceive(Ps4KernelThread *td, Ps4KernelSocket *sock, const void *data, size_t *size, size_t sizeMax, int flags) |
| 488 | +{ |
| 489 | + struct uio auio; |
| 490 | + struct iovec iov; |
| 491 | + |
| 492 | + if(td == NULL) |
| 493 | + return PS4_ERROR_ARGUMENT_THREAD_MISSING; |
| 494 | + if(sock == NULL) |
| 495 | + return PS4_ERROR_ARGUMENT_PRIMARY_MISSING; |
| 496 | + if(data == NULL) |
| 497 | + return PS4_ERROR_ARGUMENT_OUT_MISSING; |
| 498 | + if(data == NULL) |
| 499 | + return PS4_ERROR_ARGUMENT_OUT_MISSING; |
| 500 | + if(sizeMax == 0) |
| 501 | + return PS4_ERROR_ARGUMENT_SIZE_NULL; |
| 502 | + |
| 503 | + iov.iov_base = (void *)data; |
| 504 | + iov.iov_len = sizeMax; |
| 505 | + |
| 506 | + auio.uio_iov = &iov; |
| 507 | + auio.uio_iovcnt = 1; |
| 508 | + auio.uio_segflg = UIO_SYSSPACE; |
| 509 | + auio.uio_rw = UIO_READ; |
| 510 | + auio.uio_td = td; |
| 511 | + auio.uio_offset = 0; |
| 512 | + auio.uio_resid = iov.iov_len; |
| 513 | + |
| 514 | + int r = soreceive(sock, NULL, &auio, NULL, NULL, &flags); |
| 515 | + |
| 516 | + *size = sizeMax - iov.iov_len; |
| 517 | + |
| 518 | + return r; |
| 519 | +} |
0 commit comments