mirror of
https://github.com/Maschell/JWUPClient.git
synced 2024-11-22 07:59:16 +01:00
Added copy / copydir command. Added commandline command to dump the disc to sd
This commit is contained in:
parent
020f1e185a
commit
b676392315
25
README.md
25
README.md
@ -2,7 +2,7 @@ A port of smea's client (WUPClient.py) for the wupserver.
|
|||||||
|
|
||||||
Open it with
|
Open it with
|
||||||
```
|
```
|
||||||
java -jar jwupclient 192.168.x.x
|
java -jar jwupclient.jar 192.168.x.x
|
||||||
```
|
```
|
||||||
|
|
||||||
The following commands are supported (in my ulgy written shell).
|
The following commands are supported (in my ulgy written shell).
|
||||||
@ -35,6 +35,29 @@ arguments:
|
|||||||
-dst <destination folder on wiiu> (sets the destination folder on your PC)
|
-dst <destination folder on wiiu> (sets the destination folder on your PC)
|
||||||
-fullpath (keeps the absolute path of the wiiu)
|
-fullpath (keeps the absolute path of the wiiu)
|
||||||
|
|
||||||
|
|
||||||
|
###dumping a disc###
|
||||||
|
Command to dump the whole disc (code, content and meta folder) to sd
|
||||||
|
```
|
||||||
|
dumpdisc
|
||||||
|
```
|
||||||
|
|
||||||
|
The result will be stored on sd:/dumps/[TITLEID]
|
||||||
|
|
||||||
|
You can set a regular expression all files and dir will be checked to.
|
||||||
|
*Examples*
|
||||||
|
To dump only the code folder
|
||||||
|
```
|
||||||
|
dumpdisc -file /code/.*
|
||||||
|
```
|
||||||
|
|
||||||
|
To disable the check on dir (and so check the pattern on ALL files of the disc) use the -deepSearch parameter
|
||||||
|
|
||||||
|
Example: to dump all .szs files
|
||||||
|
```
|
||||||
|
dumpdisc -file .*.szs -deepSearch
|
||||||
|
```
|
||||||
|
|
||||||
Server and smea's client.
|
Server and smea's client.
|
||||||
https://github.com/smealum/iosuhax/tree/master/wupserver
|
https://github.com/smealum/iosuhax/tree/master/wupserver
|
||||||
|
|
||||||
|
BIN
jwupclient.jar
BIN
jwupclient.jar
Binary file not shown.
@ -4,6 +4,8 @@ import java.util.Scanner;
|
|||||||
|
|
||||||
import de.mas.wupclient.client.WUPClient;
|
import de.mas.wupclient.client.WUPClient;
|
||||||
import de.mas.wupclient.client.operations.DownloadUploadOperations;
|
import de.mas.wupclient.client.operations.DownloadUploadOperations;
|
||||||
|
import de.mas.wupclient.client.operations.DumperOperations;
|
||||||
|
import de.mas.wupclient.client.operations.FileOperations;
|
||||||
import de.mas.wupclient.client.operations.SpecialOperations;
|
import de.mas.wupclient.client.operations.SpecialOperations;
|
||||||
import de.mas.wupclient.client.operations.UtilOperations;
|
import de.mas.wupclient.client.operations.UtilOperations;
|
||||||
|
|
||||||
@ -21,6 +23,7 @@ public class Starter {
|
|||||||
System.out.println();
|
System.out.println();
|
||||||
System.out.print(w.getCwd() + " > ");
|
System.out.print(w.getCwd() + " > ");
|
||||||
Scanner reader = new Scanner(System.in); // Reading from System.in
|
Scanner reader = new Scanner(System.in); // Reading from System.in
|
||||||
|
|
||||||
while(!exit){
|
while(!exit){
|
||||||
|
|
||||||
String input = reader.nextLine();
|
String input = reader.nextLine();
|
||||||
@ -51,6 +54,8 @@ public class Starter {
|
|||||||
UtilOperations util = UtilOperations.UtilOperationsFactory(w);
|
UtilOperations util = UtilOperations.UtilOperationsFactory(w);
|
||||||
SpecialOperations special = SpecialOperations.SpecialOperationsFactory(w);
|
SpecialOperations special = SpecialOperations.SpecialOperationsFactory(w);
|
||||||
DownloadUploadOperations dlul = DownloadUploadOperations.DownloadUploadOperationsFactory(w);
|
DownloadUploadOperations dlul = DownloadUploadOperations.DownloadUploadOperationsFactory(w);
|
||||||
|
DumperOperations dump = DumperOperations.DumperOperationsFactory(w);
|
||||||
|
|
||||||
String[] inputs = input.split(" ");
|
String[] inputs = input.split(" ");
|
||||||
switch(inputs[0]){
|
switch(inputs[0]){
|
||||||
case "ls":
|
case "ls":
|
||||||
@ -117,6 +122,24 @@ public class Starter {
|
|||||||
case "nandtickets": //download to full path
|
case "nandtickets": //download to full path
|
||||||
special.parseAndDownloadTickets();
|
special.parseAndDownloadTickets();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "dumpdisc":
|
||||||
|
String pattern = ".*";
|
||||||
|
boolean deepSearch = false;
|
||||||
|
if(inputs.length > 1){
|
||||||
|
for(int i = 1;i < inputs.length;i++){
|
||||||
|
if(inputs[i].equals("-file")){
|
||||||
|
if(inputs.length >= i+1){
|
||||||
|
pattern = inputs[i+1];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(inputs[i].equals("-deepSearch")){
|
||||||
|
deepSearch = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dump.dumpDisc(pattern,deepSearch);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
System.out.println("Command not found!");
|
System.out.println("Command not found!");
|
||||||
|
@ -106,7 +106,7 @@ public class DownloadUploadOperations extends Operations {
|
|||||||
if(read_result.getResultValue() <= 0)
|
if(read_result.getResultValue() <= 0)
|
||||||
break;
|
break;
|
||||||
if((total_read /1024) % 50 == 0){
|
if((total_read /1024) % 50 == 0){
|
||||||
System.out.println(String.format("%.3f", (double)(total_read /1024.0)) + " kb done");
|
System.out.print("Downloading file: " + String.format("%.3f", (double)(total_read /1024.0)) + " kb done\r");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fsa.FSA_CloseFile(fsa_handle, res.getData());
|
fsa.FSA_CloseFile(fsa_handle, res.getData());
|
||||||
|
93
src/de/mas/wupclient/client/operations/DumperOperations.java
Normal file
93
src/de/mas/wupclient/client/operations/DumperOperations.java
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
package de.mas.wupclient.client.operations;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import de.mas.wupclient.client.WUPClient;
|
||||||
|
import de.mas.wupclient.client.utils.FEntry;
|
||||||
|
import de.mas.wupclient.client.utils.Logger;
|
||||||
|
import de.mas.wupclient.client.utils.MetaInformation;
|
||||||
|
import de.mas.wupclient.client.utils.Utils;
|
||||||
|
|
||||||
|
public class DumperOperations extends Operations {
|
||||||
|
private static Map<WUPClient,DumperOperations> instances = new HashMap<>();
|
||||||
|
public static DumperOperations DumperOperationsFactory(WUPClient client){
|
||||||
|
if(!instances.containsKey(client)){
|
||||||
|
instances.put(client, new DumperOperations(client));
|
||||||
|
}
|
||||||
|
return instances.get(client);
|
||||||
|
}
|
||||||
|
UtilOperations util = null;
|
||||||
|
FileOperations file = null;
|
||||||
|
DownloadUploadOperations dlul = null;
|
||||||
|
|
||||||
|
private DumperOperations(WUPClient client) {
|
||||||
|
super(client);
|
||||||
|
setUtil(UtilOperations.UtilOperationsFactory(client));
|
||||||
|
setDLUL(DownloadUploadOperations.DownloadUploadOperationsFactory(client));
|
||||||
|
setFile(FileOperations.FileOperationsFactory(client));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean dumpDisc(String pattern,boolean deepSearch) throws IOException{
|
||||||
|
try{
|
||||||
|
util.mount_sdcard();
|
||||||
|
int res = util.mount("/dev/odd03", "/vol/storage_odd_content_dump", 2);
|
||||||
|
if(res != 0){
|
||||||
|
//throw new MountingFailedException();
|
||||||
|
}
|
||||||
|
System.out.println("Grabbing meta information!");
|
||||||
|
byte[] metafile = dlul.downloadFileToByteArray("/vol/storage_odd_content_dump/meta/meta.xml");
|
||||||
|
if(metafile == null){
|
||||||
|
throw new LoadMetaFailedException();
|
||||||
|
}
|
||||||
|
MetaInformation title = Utils.readMeta(new ByteArrayInputStream(metafile));
|
||||||
|
Logger.log("Dumping " + title.getLongnameEN() + "(" + title.getTitleIDAsString() + ")");
|
||||||
|
file.mkdir("/vol/storage_sdcard/dumps", 0x600);
|
||||||
|
file.mkdir("/vol/storage_sdcard/dumps/" + title.getTitleIDAsString(), 0x600);
|
||||||
|
if(pattern != ".*"){
|
||||||
|
System.out.println("Searching matching files. This could take a while");
|
||||||
|
}
|
||||||
|
file.cpdir("/vol/storage_odd_content_dump","/vol/storage_sdcard/dumps/" + title.getTitleIDAsString(),"",pattern,deepSearch);
|
||||||
|
|
||||||
|
//}catch (MountingFailedException e) {
|
||||||
|
// Logger.logErr("Mounting failed");
|
||||||
|
}catch (LoadMetaFailedException e){
|
||||||
|
Logger.logErr("Loading meta.xml failed");
|
||||||
|
}finally{
|
||||||
|
util.unmount("/vol/storage_odd_content_dump", 2);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UtilOperations getUtil() {
|
||||||
|
return util;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUtil(UtilOperations util) {
|
||||||
|
this.util = util;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DownloadUploadOperations getDLUL() {
|
||||||
|
return dlul;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDLUL(DownloadUploadOperations dlul) {
|
||||||
|
this.dlul = dlul;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileOperations getFile() {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFile(FileOperations file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -137,12 +137,29 @@ public class FSAOperations extends Operations {
|
|||||||
if(result.getResultValue() == 0){
|
if(result.getResultValue() == 0){
|
||||||
stats = new FStats(result.getData());
|
stats = new FStats(result.getData());
|
||||||
}
|
}
|
||||||
System.out.println(result.getResultValue());
|
|
||||||
return new Result<FStats>(result.getResultValue(), stats);
|
return new Result<FStats>(result.getResultValue(), stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result<Integer> FSA_ReadFilePtr(int fsa_handle, int src_handle, int i, int block_size, int buffer_ptr) {
|
|
||||||
// TODO Auto-generated method stub
|
public Result<byte[]> FSA_ReadFilePtr(int handle, int filehandle, int size, int cnt, int ptr) throws IOException {
|
||||||
return null;
|
byte[] inbuffer = new byte[0x520];
|
||||||
|
Utils.writeIntToByteArray(inbuffer, size, 0x08);
|
||||||
|
Utils.writeIntToByteArray(inbuffer, cnt, 0x0C);
|
||||||
|
Utils.writeIntToByteArray(inbuffer, filehandle, 0x14);
|
||||||
|
|
||||||
|
Result<byte[][]> result = system.ioctlv(handle, 0x0F, new byte[][] {inbuffer}, new int[]{0x293}, new int[0][], new int[][]{new int[]{ptr,size*cnt}});
|
||||||
|
|
||||||
|
return new Result<byte[]>(result.getResultValue(),result.getData()[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<byte[]> FSA_WriteFilePtr(int handle, int file_handle, int size, int cnt, int ptr) throws IOException {
|
||||||
|
byte[] inbuffer = new byte[0x520];
|
||||||
|
Utils.writeIntToByteArray(inbuffer, size, 0x08);
|
||||||
|
Utils.writeIntToByteArray(inbuffer, cnt, 0x0C);
|
||||||
|
Utils.writeIntToByteArray(inbuffer, file_handle, 0x14);
|
||||||
|
|
||||||
|
Result<byte[][]> result = system.ioctlv(handle, 0x10, new byte[][] {inbuffer}, new int[]{0x293}, new int[][]{new int[]{ptr,size*cnt}},new int[0][]);
|
||||||
|
|
||||||
|
return new Result<byte[]>(result.getResultValue(),result.getData()[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,14 @@ package de.mas.wupclient.client.operations;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import de.mas.wupclient.client.WUPClient;
|
import de.mas.wupclient.client.WUPClient;
|
||||||
|
import de.mas.wupclient.client.utils.FEntry;
|
||||||
|
import de.mas.wupclient.client.utils.FStats;
|
||||||
import de.mas.wupclient.client.utils.Logger;
|
import de.mas.wupclient.client.utils.Logger;
|
||||||
import de.mas.wupclient.client.utils.Result;
|
import de.mas.wupclient.client.utils.Result;
|
||||||
|
|
||||||
@ -34,13 +39,44 @@ public class FileOperations extends Operations {
|
|||||||
}
|
}
|
||||||
public int createDir(String path, int flags) throws IOException{
|
public int createDir(String path, int flags) throws IOException{
|
||||||
int fsa_handle = getClient().get_fsa_handle();
|
int fsa_handle = getClient().get_fsa_handle();
|
||||||
return fsa.FSA_MakeDir(fsa_handle, path, 2);
|
return fsa.FSA_MakeDir(fsa_handle, path, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FSA_ReadFilePtr needs to be implemented
|
|
||||||
public boolean cp(String source, String target) throws IOException{
|
public boolean cp(String source, String target) throws IOException{
|
||||||
return copyFile(source, target);
|
return copyFile(source, target);
|
||||||
}
|
}
|
||||||
|
public boolean cpdir(String source, String destination)throws IOException{
|
||||||
|
return cpdir(source, destination,"",".*",false);
|
||||||
|
}
|
||||||
|
public boolean cpdir(String source, String destination,boolean deepSearch)throws IOException{
|
||||||
|
return cpdir(source, destination,"",".*",deepSearch);
|
||||||
|
}
|
||||||
|
public boolean cpdir(String source, String destination,String relativePath,String pattern,boolean deepSearch)throws IOException{
|
||||||
|
System.out.println("Copying folder " +source + " to " + destination);
|
||||||
|
List<FEntry> entries = util.ls(source,true);
|
||||||
|
for(FEntry entry : entries){
|
||||||
|
String new_relativePath = relativePath+ "/" + entry.getFilename();
|
||||||
|
String src_filename = source + "/" + entry.getFilename();
|
||||||
|
String dst_filename = destination + "/" + entry.getFilename();
|
||||||
|
Pattern p = Pattern.compile(pattern);
|
||||||
|
Matcher m = p.matcher(new_relativePath);
|
||||||
|
Matcher m1 = p.matcher(new_relativePath + "/");
|
||||||
|
boolean matches = m.matches() || m1.matches();
|
||||||
|
if(matches || deepSearch){
|
||||||
|
if(entry.isFile()){
|
||||||
|
if(matches){
|
||||||
|
boolean result = cp(src_filename,dst_filename);
|
||||||
|
if(!result) break;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
mkdir(dst_filename, 0x600);
|
||||||
|
cpdir(src_filename, dst_filename,new_relativePath,pattern,deepSearch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean copyFile(String source, String destination) throws IOException{
|
public boolean copyFile(String source, String destination) throws IOException{
|
||||||
@ -50,31 +86,57 @@ public class FileOperations extends Operations {
|
|||||||
Logger.logErr("copyFile error: couldn't open " + source);
|
Logger.logErr("copyFile error: couldn't open " + source);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Result<Integer> result_dst = fsa.FSA_OpenFile(fsa_handle, destination, "r");
|
|
||||||
|
Result<Integer> result_dst = fsa.FSA_OpenFile(fsa_handle, destination, "w");
|
||||||
if(result_dst.getResultValue() != 0){
|
if(result_dst.getResultValue() != 0){
|
||||||
Logger.logErr("copyFile error: couldn't open " + destination);
|
Logger.logErr("copyFile error: couldn't open " + destination);
|
||||||
fsa.FSA_CloseFile(fsa_handle, result_src.getData());
|
fsa.FSA_CloseFile(fsa_handle, result_src.getData());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int block_size = 0x10000;
|
int block_size = 0x20000;
|
||||||
int buffer_ptr = system.alloc(block_size, 0x40);
|
int buffer_ptr = system.alloc(block_size, 0x40);
|
||||||
int i =0;
|
int i =0;
|
||||||
int src_handle = result_src.getData();
|
int src_handle = result_src.getData();
|
||||||
int dst_handle = result_dst.getData();
|
int dst_handle = result_dst.getData();
|
||||||
boolean result = true;
|
boolean result = true;
|
||||||
|
|
||||||
|
Result<FStats> result_stat = fsa.FSA_StatFile(fsa_handle, src_handle);
|
||||||
|
if(result_stat.getResultValue() < 0){
|
||||||
|
Logger.log("copyFile error: FSA_StatFile failed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
long file_size = result_stat.getData().getPhyssize();
|
||||||
|
System.out.println("Copying " + source + " to " + destination + " ("+ (file_size /1024.0f) +" kb)");
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
while(true){
|
while(true){
|
||||||
Result<Integer> result_read = fsa.FSA_ReadFilePtr(fsa_handle, src_handle, 0x1, block_size, buffer_ptr);
|
Result<byte[]> result_read = fsa.FSA_ReadFilePtr(fsa_handle, src_handle, 0x1, block_size, buffer_ptr);
|
||||||
if(result_read.getResultValue() < 0){
|
int result_val = result_read.getResultValue();
|
||||||
|
if(result_val < 0){
|
||||||
Logger.log("copyFile error: reading source file failed.");
|
Logger.log("copyFile error: reading source file failed.");
|
||||||
result = false;
|
result = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
i += result_val;
|
||||||
|
Result<byte[]> result_write = fsa.FSA_WriteFilePtr(fsa_handle, dst_handle, 0x1, result_val, buffer_ptr);
|
||||||
|
int result_write_val = result_read.getResultValue();
|
||||||
|
if(result_write_val < 0){
|
||||||
|
Logger.log("copyFile error: writing destination file failed.");
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
long diff_time = System.currentTimeMillis() - startTime;
|
||||||
|
|
||||||
|
System.out.print("" + String.format("Writing File: progress %08X bytes (%02.02f", i,(i*1.0/file_size*1.0)*100) + "%) (" + String.format("%04d", (int)((i*1.0f) /(diff_time*1.0f)))+" kb/s)\r");
|
||||||
|
if(result_val < block_size){
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
System.out.println("Wrote " + source + " to " + destination + " ("+ (file_size /1024.0f) +" kb)");
|
||||||
system.free(buffer_ptr);
|
system.free(buffer_ptr);
|
||||||
fsa.FSA_CloseFile(fsa_handle, src_handle);
|
fsa.FSA_CloseFile(fsa_handle, src_handle);
|
||||||
fsa.FSA_CloseFile(fsa_handle, dst_handle);
|
fsa.FSA_CloseFile(fsa_handle, dst_handle);
|
||||||
return result;
|
return result;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
public UtilOperations getUtil() {
|
public UtilOperations getUtil() {
|
||||||
return util;
|
return util;
|
||||||
|
@ -148,7 +148,7 @@ public class UtilOperations extends Operations {
|
|||||||
fsa.FSA_CloseDir(fsa_handle, result.getData());
|
fsa.FSA_CloseDir(fsa_handle, result.getData());
|
||||||
final_result = true;
|
final_result = true;
|
||||||
}else{
|
}else{
|
||||||
Logger.logErr("path does not exists");
|
Logger.logErr("path does not exists: error " + result.getResultValue());
|
||||||
final_result = false;
|
final_result = false;
|
||||||
}
|
}
|
||||||
getClient().FSA_Close(getClient().get_fsa_handle());
|
getClient().FSA_Close(getClient().get_fsa_handle());
|
||||||
|
@ -35,5 +35,19 @@ public class FStats {
|
|||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
return sb.append("Size: " + size + " Physicalsize:" + physsize).toString();
|
return sb.append("Size: " + size + " Physicalsize:" + physsize).toString();
|
||||||
}
|
}
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
public void setSize(int size) {
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
public int getPhyssize() {
|
||||||
|
return physsize;
|
||||||
|
}
|
||||||
|
public void setPhyssize(int physsize) {
|
||||||
|
this.physsize = physsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user