static void Socket(Service::Interface* self) { u32* cmd_buffer = Kernel::GetCommandBuffer(); u32 domain = cmd_buffer[1]; // Address family u32 type = cmd_buffer[2]; u32 protocol = cmd_buffer[3]; // Only 0 is allowed according to 3dbrew, using 0 will let the OS decide which protocol to use if (protocol != 0) { cmd_buffer[1] = UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code return; } if (domain != AF_INET) { cmd_buffer[1] = UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code return; } if (type != SOCK_DGRAM && type != SOCK_STREAM) { cmd_buffer[1] = UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code return; } u32 socket_handle = static_cast<u32>(::socket(domain, type, protocol)); if ((s32)socket_handle != SOCKET_ERROR_VALUE) open_sockets[socket_handle] = { socket_handle, true }; int result = 0; if ((s32)socket_handle == SOCKET_ERROR_VALUE) result = TranslateError(GET_ERRNO); cmd_buffer[1] = result; cmd_buffer[2] = socket_handle; }
/** * FS_User::OpenArchive service function * Inputs: * 1 : Archive ID * 2 : Archive low path type * 3 : Archive low path size * 4 : (LowPathSize << 14) | 2 * 5 : Archive low path * Outputs: * 1 : Result of function, 0 on success, otherwise error code * 2 : Archive handle lower word (unused) * 3 : Archive handle upper word (same as file handle) */ static void OpenArchive(Service::Interface* self) { u32* cmd_buff = Service::GetCommandBuffer(); auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[1]); auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); u32 archivename_size = cmd_buff[3]; u32 archivename_ptr = cmd_buff[5]; FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); DEBUG_LOG(KERNEL, "archive_path=%s", archive_path.DebugStr().c_str()); if (archive_path.GetType() != FileSys::Empty) { ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported"); cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw; return; } ResultVal<Handle> handle = Kernel::OpenArchive(archive_id); cmd_buff[1] = handle.Code().raw; if (handle.Succeeded()) { // cmd_buff[2] isn't used according to 3dmoo's implementation. cmd_buff[3] = *handle; } else { ERROR_LOG(KERNEL, "failed to get a handle for archive"); } DEBUG_LOG(KERNEL, "called"); }
ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path) { auto archive_itr = id_code_map.find(id_code); if (archive_itr == id_code_map.end()) { return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error } return archive_itr->second->Format(path); }
ResultVal<FileSys::ArchiveFormatInfo> ArchiveManager::GetArchiveFormatInfo( ArchiveIdCode id_code, FileSys::Path& archive_path, u64 program_id) { auto archive = id_code_map.find(id_code); if (archive == id_code_map.end()) { return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error } return archive->second->GetFormatInfo(archive_path, program_id); }
ResultCode ArchiveManager::FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info, const FileSys::Path& path, u64 program_id) { auto archive_itr = id_code_map.find(id_code); if (archive_itr == id_code_map.end()) { return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error } return archive_itr->second->Format(path, format_info, program_id); }
ResultCode FormatSaveData() { // Do not create the archive again if it already exists auto archive_itr = id_code_map.find(ArchiveIdCode::SaveData); if (archive_itr == id_code_map.end()) { return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error } // Use an empty path, we do not use it when formatting the savedata return archive_itr->second->backend->Format(FileSys::Path()); }
ResultCode ArchiveManager::RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { ArchiveBackend* src_archive = GetArchive(src_archive_handle); ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); if (src_archive == nullptr || dest_archive == nullptr) return FileSys::ERR_INVALID_ARCHIVE_HANDLE; if (src_archive == dest_archive) { return src_archive->RenameDirectory(src_path, dest_path); } else { // TODO: Implement renaming across archives return UnimplementedFunction(ErrorModule::FS); } }
static void GetServiceHandle(Service::Interface* self) { ResultCode res = RESULT_SUCCESS; u32* cmd_buff = Service::GetCommandBuffer(); std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); if (nullptr != service) { cmd_buff[3] = service->GetHandle(); LOG_TRACE(Service_SRV, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]); } else { LOG_ERROR(Service_SRV, "(UNIMPLEMENTED) called port=%s", port_name.c_str()); res = UnimplementedFunction(ErrorModule::SRV); } cmd_buff[1] = res.raw; }
/** * FS_User::OpenFileDirectly service function * Inputs: * 1 : Transaction * 2 : Archive ID * 3 : Archive low path type * 4 : Archive low path size * 5 : File low path type * 6 : File low path size * 7 : Flags * 8 : Attributes * 9 : (ArchiveLowPathSize << 14) | 0x802 * 10 : Archive low path * 11 : (FileLowPathSize << 14) | 2 * 12 : File low path * Outputs: * 1 : Result of function, 0 on success, otherwise error code * 3 : File handle */ static void OpenFileDirectly(Service::Interface* self) { u32* cmd_buff = Service::GetCommandBuffer(); auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[2]); auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); u32 archivename_size = cmd_buff[4]; auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[5]); u32 filename_size = cmd_buff[6]; FileSys::Mode mode; mode.hex = cmd_buff[7]; u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes. u32 archivename_ptr = cmd_buff[10]; u32 filename_ptr = cmd_buff[12]; FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); FileSys::Path file_path(filename_type, filename_size, filename_ptr); DEBUG_LOG(KERNEL, "archive_path=%s file_path=%s, mode=%u attributes=%d", archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex, attributes); if (archive_path.GetType() != FileSys::Empty) { ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported"); cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw; return; } // TODO(Link Mauve): Check if we should even get a handle for the archive, and don't leak it // TODO(yuriks): Why is there all this duplicate (and seemingly useless) code up here? ResultVal<Handle> archive_handle = Kernel::OpenArchive(archive_id); cmd_buff[1] = archive_handle.Code().raw; if (archive_handle.Failed()) { ERROR_LOG(KERNEL, "failed to get a handle for archive"); return; } // cmd_buff[2] isn't used according to 3dmoo's implementation. cmd_buff[3] = *archive_handle; ResultVal<Handle> handle = Kernel::OpenFileFromArchive(*archive_handle, file_path, mode); cmd_buff[1] = handle.Code().raw; if (handle.Succeeded()) { cmd_buff[3] = *handle; } else { ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_path.DebugStr().c_str()); } DEBUG_LOG(KERNEL, "called"); }
ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { ArchiveBackend* src_archive = GetArchive(src_archive_handle); ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); if (src_archive == nullptr || dest_archive == nullptr) return ERR_INVALID_HANDLE; if (src_archive == dest_archive) { if (src_archive->RenameDirectory(src_path, dest_path)) return RESULT_SUCCESS; } else { // TODO: Implement renaming across archives return UnimplementedFunction(ErrorModule::FS); } // TODO(yuriks): This code probably isn't right, it'll return a Status even if the file didn't // exist or similar. Verify. return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description ErrorSummary::NothingHappened, ErrorLevel::Status); }
ResultCode ArchiveManager::CreateExtSaveData(MediaType media_type, u32 high, u32 low, const std::vector<u8>& smdh_icon, const FileSys::ArchiveFormatInfo& format_info, u64 program_id) { // Construct the binary path to the archive first FileSys::Path path = FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low); auto archive = id_code_map.find(media_type == MediaType::NAND ? ArchiveIdCode::SharedExtSaveData : ArchiveIdCode::ExtSaveData); if (archive == id_code_map.end()) { return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error } auto ext_savedata = static_cast<FileSys::ArchiveFactory_ExtSaveData*>(archive->second.get()); ResultCode result = ext_savedata->Format(path, format_info, program_id); if (result.IsError()) return result; ext_savedata->WriteIcon(path, smdh_icon.data(), smdh_icon.size()); return RESULT_SUCCESS; }