| 105 | } |
| 106 | |
| 107 | bool MountRootFSImagePath(const fextl::string& SquashFS, bool EroFS) { |
| 108 | pid_t ParentTID = ::getpid(); |
| 109 | MountFolder = fmt::format("{}/.FEXMount{}-XXXXXX", FEXServerClient::GetServerMountFolder(), ParentTID); |
| 110 | char* MountFolderStr = MountFolder.data(); |
| 111 | |
| 112 | // Make the temporary mount folder |
| 113 | if (mkdtemp(MountFolderStr) == nullptr) { |
| 114 | LogMan::Msg::EFmt("[FEXServer] Couldn't create temporary mount name: {}", MountFolder); |
| 115 | return false; |
| 116 | } |
| 117 | |
| 118 | // Change the permissions |
| 119 | if (chmod(MountFolderStr, 0777) != 0) { |
| 120 | LogMan::Msg::EFmt("[FEXServer] Couldn't change permissions on temporary mount: {}", MountFolder); |
| 121 | rmdir(MountFolderStr); |
| 122 | return false; |
| 123 | } |
| 124 | |
| 125 | // Create local FDs so our internal forks can communicate |
| 126 | int fds[2]; |
| 127 | pipe2(fds, 0); |
| 128 | |
| 129 | int pid = fork(); |
| 130 | if (pid == 0) { |
| 131 | // Child |
| 132 | close(fds[0]); // Close read side |
| 133 | const char* argv[4]; |
| 134 | argv[0] = EroFS ? "erofsfuse" : "squashfuse"; |
| 135 | argv[1] = SquashFS.c_str(); |
| 136 | argv[2] = MountFolder.c_str(); |
| 137 | argv[3] = nullptr; |
| 138 | |
| 139 | // Try and execute {erofsfuse, squashfuse} to mount our rootfs |
| 140 | if (execvpe(argv[0], (char* const*)argv, environ) == -1) { |
| 141 | // Give a hopefully helpful error message for users |
| 142 | LogMan::Msg::EFmt("[FEXServer] '{}' Couldn't execute for some reason: {} {}\n", argv[0], errno, strerror(errno)); |
| 143 | LogMan::Msg::EFmt("[FEXServer] To mount squashfs rootfs files you need {} installed\n", argv[0]); |
| 144 | LogMan::Msg::EFmt("[FEXServer] Check your FUSE setup.\n"); |
| 145 | |
| 146 | // Let the parent know that we couldn't execute for some reason |
| 147 | uint64_t error {1}; |
| 148 | write(fds[1], &error, sizeof(error)); |
| 149 | |
| 150 | // End the child |
| 151 | exit(1); |
| 152 | } |
| 153 | } else { |
| 154 | FuseMountPID = pid; |
| 155 | // Parent |
| 156 | // Wait for the child to exit |
| 157 | // This will happen with execvpe of squashmount or exit on failure |
| 158 | while (waitpid(pid, nullptr, 0) == -1 && errno == EINTR) |
| 159 | ; |
| 160 | |
| 161 | // Check the child pipe for messages |
| 162 | pollfd PollFD; |
| 163 | PollFD.fd = fds[0]; |
| 164 | PollFD.events = POLLIN; |
no test coverage detected