For the TCP Gecko Installer I tried to implement a function to replace files on games. However, I'm getting an ACCESS_ERROR when calling FSOpenFile():
Client code in Java:
In case you're wondering, Cafiine does not actually replace files the same way I'm trying to. It only fools the Wii U into pulling the files from the network instead of the disk. However, I'm trying to just replace the file so the replacement file is being used from now on instead without requesting it over the network over and over again. I'm not sure if this is even possible since the SDK says this about the error message:
It might mean that disks just aren't writable (I'm using the digital version though) but isn't there maybe a way to do it? This project might help as well. Thanks
@dimok
@QuarkTheAwesome
@Maschell
@FIX94
@wj44
@NWPlayer123
Code:
case COMMAND_REPLACE_FILE: {
// Receive the file path
char file_path[FS_MAX_FULLPATH_SIZE] = {0};
receiveString(bss, clientfd, file_path, FS_MAX_FULLPATH_SIZE);
considerInitializingFileSystem();
// Create an empty file for writing. Its contents will be erased
int handle;
int status = FSOpenFile(client, commandBlock, file_path, "w", &handle, FS_RET_ALL_ERROR);
if (status == FS_STATUS_OK) {
// Send the OK status
((int *) buffer)[0] = status;
ret = sendwait(bss, clientfd, buffer, 4);
ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (OK status)")
// Set the file handle position to the beginning
ret = FSSetPosFile(client, commandBlock, handle, 0, FS_RET_ALL_ERROR);
ASSERT_FUNCTION_SUCCEEDED(ret, "FSSetPosFile")
// Allocate the file bytes buffer
unsigned int file_buffer_size = 0x2000;
char *fileBuffer = (char *) OSAllocFromSystem(file_buffer_size, FS_IO_BUFFER_ALIGN);
ASSERT_ALLOCATED(fileBuffer, "File buffer")
// Send the maximum file buffer size
ret = sendwait(bss, clientfd, &file_buffer_size, 4);
ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (maximum file buffer size)")
while (true) {
// Receive the data bytes length
unsigned int dataLength;
ret = recvwait(bss, clientfd, &dataLength, 4);
ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (File bytes length)")
ASSERT_MAXIMUM_HOLDS(file_buffer_size, dataLength, "File buffer overrun attempted")
if (dataLength > 0) {
// Receive the data
ret = recvwait(bss, clientfd, fileBuffer, dataLength);
ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (File buffer)")
// Write the data (and advance file handle position implicitly)
ret = FSWriteFile(client, commandBlock, fileBuffer, 1,
dataLength, handle, 0, FS_RET_ALL_ERROR);
ASSERT_FUNCTION_SUCCEEDED(ret, "FSWriteFile")
} else {
// Done with receiving the new file
break;
}
}
/*// Flush the file back
ret = FSFlushFile(client, commandBlock, handle, FS_RET_ALL_ERROR);
CHECK_FUNCTION_FAILED(ret, "FSFlushFile")*/
// Close the file
ret = FSCloseFile(client, commandBlock, handle, FS_RET_ALL_ERROR);
ASSERT_FUNCTION_SUCCEEDED(ret, "FSCloseFile")
// Free the file buffer
OSFreeToSystem(fileBuffer);
} else {
// Send the status
((int *) buffer)[0] = status;
ret = sendwait(bss, clientfd, buffer, 4);
ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (status)")
}
break;
}
Code:
public FileSystemStatus replaceFile(String remoteFilePath, String localFilePath) throws IOException
{
// Read the file bytes
Path localFile = Paths.get(localFilePath);
byte[] fileBytes = Files.readAllBytes(localFile);
try (CloseableReentrantLock ignored = reentrantLock.acquire())
{
// Send the command and remote file path
sendCommand(Command.REPLACE_REMOTE_FILE);
writeString(remoteFilePath);
dataSender.flush();
FileSystemStatus status = readFileSystemStatus();
// Continue if the file has been opened successfully
if (status == FileSystemStatus.OK)
{
sendFileBytes(fileBytes);
}
return status;
}
}
private void sendFileBytes(byte[] fileBytes) throws IOException
{
int maximumChunkSize = dataReceiver.readInt();
int fileBytesIndex = 0;
// Send the file bytes in chunks
while (fileBytesIndex < fileBytes.length)
{
int chunkSize = fileBytes.length - fileBytesIndex;
if (chunkSize > maximumChunkSize)
{
chunkSize = maximumChunkSize;
}
// Send the current chunk size
dataSender.writeInt(chunkSize);
sendPartialBytes(fileBytes, fileBytesIndex, chunkSize);
dataSender.flush();
fileBytesIndex += chunkSize;
}
// Let the server know that we're done
dataSender.writeInt(0);
dataSender.flush();
}
private void sendPartialBytes(byte[] bytes, int startingIndex, int length) throws IOException
{
byte[] sendBytes = new byte[length];
System.arraycopy(bytes, startingIndex, sendBytes, 0, length);
dataSender.write(sendBytes);
}
Code:
Access mode is invalid (e.g. specified "r+" for read-only media).
@dimok
@QuarkTheAwesome
@Maschell
@FIX94
@wj44
@NWPlayer123
Last edited by BullyWiiPlaza,