| 417 | enum class OpenReturnMode { FD, Nothing }; |
| 418 | |
| 419 | static __wasi_fd_t doOpen(path::ParsedParent parsed, |
| 420 | int flags, |
| 421 | mode_t mode, |
| 422 | backend_t backend = NullBackend, |
| 423 | OpenReturnMode returnMode = OpenReturnMode::FD) { |
| 424 | int accessMode = (flags & O_ACCMODE); |
| 425 | if (accessMode != O_WRONLY && accessMode != O_RDONLY && |
| 426 | accessMode != O_RDWR) { |
| 427 | return -EINVAL; |
| 428 | } |
| 429 | |
| 430 | // TODO: remove assert when all functionality is complete. |
| 431 | assert((flags & ~(O_CREAT | O_EXCL | O_DIRECTORY | O_TRUNC | O_APPEND | |
| 432 | O_RDWR | O_WRONLY | O_RDONLY | O_LARGEFILE | O_NOFOLLOW | |
| 433 | O_CLOEXEC | O_NONBLOCK)) == 0); |
| 434 | |
| 435 | if (auto err = parsed.getError()) { |
| 436 | return err; |
| 437 | } |
| 438 | auto& [parent, childName] = parsed.getParentChild(); |
| 439 | if (childName.size() > WASMFS_NAME_MAX) { |
| 440 | return -ENAMETOOLONG; |
| 441 | } |
| 442 | |
| 443 | std::shared_ptr<File> child; |
| 444 | { |
| 445 | auto lockedParent = parent->locked(); |
| 446 | child = lockedParent.getChild(std::string(childName)); |
| 447 | // The requested node was not found. |
| 448 | if (!child) { |
| 449 | // If curr is the last element and the create flag is specified |
| 450 | // If O_DIRECTORY is also specified, still create a regular file: |
| 451 | // https://man7.org/linux/man-pages/man2/open.2.html#BUGS |
| 452 | if (!(flags & O_CREAT)) { |
| 453 | return -ENOENT; |
| 454 | } |
| 455 | |
| 456 | // Inserting into an unlinked directory is not allowed. |
| 457 | if (!lockedParent.getParent()) { |
| 458 | return -ENOENT; |
| 459 | } |
| 460 | |
| 461 | // Mask out everything except the permissions bits. |
| 462 | mode &= S_IALLUGO; |
| 463 | mode &= ~wasmFS.getUmask(); |
| 464 | |
| 465 | // If there is no explicitly provided backend, use the parent's backend. |
| 466 | if (!backend) { |
| 467 | backend = parent->getBackend(); |
| 468 | } |
| 469 | |
| 470 | // TODO: Check write permissions on the parent directory. |
| 471 | std::shared_ptr<File> created; |
| 472 | if (backend == parent->getBackend()) { |
| 473 | created = lockedParent.insertDataFile(std::string(childName), mode); |
| 474 | if (!created) { |
| 475 | // TODO Receive a specific error code, and report it here. For now, |
| 476 | // report a generic error. |
no test coverage detected