Update to latest JNUSLib version

This commit is contained in:
Maschell 2020-12-20 15:36:54 +01:00
parent f3a1457518
commit 623b8a6c9d
13 changed files with 146 additions and 64 deletions

12
pom.xml
View File

@ -92,7 +92,7 @@
<dependency>
<groupId>com.github.Maschell</groupId>
<artifactId>JNUSLib</artifactId>
<version>e3be1f5</version>
<version>b95e1ab</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
@ -109,5 +109,15 @@
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
</dependencies>
</project>

View File

@ -3,7 +3,9 @@ package de.mas.wiiu.jnus.fuse_wiiu.implementation;
import java.util.Optional;
import java.util.function.Supplier;
import de.mas.wiiu.jnus.entities.fst.FSTEntry;
import de.mas.wiiu.jnus.entities.FST.nodeentry.DirectoryEntry;
import de.mas.wiiu.jnus.entities.FST.nodeentry.FileEntry;
import de.mas.wiiu.jnus.entities.FST.nodeentry.NodeEntry;
import de.mas.wiiu.jnus.fuse_wiiu.interfaces.FuseContainer;
import de.mas.wiiu.jnus.fuse_wiiu.interfaces.FuseDirectory;
import de.mas.wiiu.jnus.interfaces.FSTDataProvider;
@ -42,11 +44,11 @@ public class FSTDataProviderContainer implements FuseContainer {
@Override
public int open(String path, FuseFileInfo fi) {
Optional<FSTEntry> entryOpt = FSTUtils.getFSTEntryByFullPath(getDataProvider().getRoot(), path);
Optional<NodeEntry> entryOpt = FSTUtils.getFSTEntryByFullPath(getDataProvider().getRoot(), path);
if (entryOpt.isPresent()) {
if (entryOpt.get().isDir()) {
if (entryOpt.get().isDirectory()) {
return -ErrorCodes.EISDIR();
} else if (!entryOpt.get().isNotInPackage()) {
} else if (!entryOpt.get().isLink()) {
return 0;
}
}
@ -60,18 +62,18 @@ public class FSTDataProviderContainer implements FuseContainer {
stat.st_nlink.set(2);
return 0;
}
Optional<FSTEntry> entryOpt = FSTUtils.getFSTEntryByFullPath(getDataProvider().getRoot(), path);
Optional<NodeEntry> entryOpt = FSTUtils.getFSTEntryByFullPath(getDataProvider().getRoot(), path);
int res = 0;
if (entryOpt.isPresent()) {
FSTEntry entry = entryOpt.get();
if (entry.isDir()) {
NodeEntry entry = entryOpt.get();
if (entry.isDirectory()) {
stat.st_mode.set(FileStat.S_IFDIR | 0755);
stat.st_nlink.set(2);
} else {
stat.st_mode.set(FileStat.S_IFREG | FileStat.ALL_READ);
stat.st_nlink.set(1);
stat.st_size.set(entry.getFileSize());
stat.st_size.set(((FileEntry) entry).getSize());
}
} else {
System.out.println("error for " + path);
@ -82,10 +84,10 @@ public class FSTDataProviderContainer implements FuseContainer {
@Override
public int readdir(String path, Pointer buf, FuseFillDir filter, long offset, FuseFileInfo fi) {
FSTEntry entry = getDataProvider().getRoot();
DirectoryEntry entry = getDataProvider().getRoot();
if (!path.equals("/")) {
Optional<FSTEntry> entryOpt = FSTUtils.getFileEntryDir(entry, path);
Optional<DirectoryEntry> entryOpt = FSTUtils.getFileEntryDir(entry, path);
if (!entryOpt.isPresent()) {
return -ErrorCodes.ENOENT();
}
@ -95,9 +97,9 @@ public class FSTDataProviderContainer implements FuseContainer {
filter.apply(buf, ".", null, 0);
filter.apply(buf, "..", null, 0);
for (FSTEntry e : entry.getChildren()) {
if (!e.isNotInPackage()) {
filter.apply(buf, e.getFilename(), null, 0);
for (NodeEntry e : entry.getChildren()) {
if (!e.isLink()) {
filter.apply(buf, e.getName(), null, 0);
}
}
return 0;
@ -105,19 +107,19 @@ public class FSTDataProviderContainer implements FuseContainer {
@Override
public int read(String path, Pointer buf, long size, long offset, FuseFileInfo fi) {
Optional<FSTEntry> entryopt = FSTUtils.getFSTEntryByFullPath(getDataProvider().getRoot(), path);
if (entryopt.isPresent() && !entryopt.get().isNotInPackage()) {
Optional<NodeEntry> entryopt = FSTUtils.getFSTEntryByFullPath(getDataProvider().getRoot(), path);
if (entryopt.isPresent() && !entryopt.get().isLink() && entryopt.get().isFile()) {
FSTEntry entry = entryopt.get();
FileEntry entry = (FileEntry) entryopt.get();
if (offset >= entry.getFileSize()) {
if (offset >= entry.getSize()) {
return 0;
}
if (offset + size > entry.getFileSize()) {
size = entry.getFileSize() - offset;
if (offset + size > entry.getSize()) {
size = entry.getSize() - offset;
}
if(size > Integer.MAX_VALUE) {
if (size > Integer.MAX_VALUE) {
System.err.println("Request read size was too big.");
return -ErrorCodes.EIO();
}

View File

@ -24,9 +24,9 @@ public class LocalBackupNUSTitleContainer extends GroupFuseContainer {
@Override
protected void doInit() {
File[] wud = folder.listFiles(f -> f.isDirectory() && f.getName().startsWith("v"));
File[] wud = folder.listFiles(f -> f.getName().startsWith("tmd."));
for (File versionF : wud) {
short version = Short.parseShort(versionF.getName().substring(1));
short version = Short.parseShort(versionF.getName().substring(4));
this.addFuseContainer(String.format("v%d", version), new FSTDataProviderContainer(Optional.of(this), () -> {
long titleID = Utils.StringToLong(folder.getName());
NUSTitle t = null;

View File

@ -7,8 +7,8 @@ import java.util.Optional;
import de.mas.wiiu.jnus.NUSTitle;
import de.mas.wiiu.jnus.NUSTitleLoaderLocal;
import de.mas.wiiu.jnus.entities.TMD;
import de.mas.wiiu.jnus.entities.Ticket;
import de.mas.wiiu.jnus.entities.TMD.TitleMetaData;
import de.mas.wiiu.jnus.fuse_wiiu.Settings;
import de.mas.wiiu.jnus.fuse_wiiu.interfaces.FuseDirectory;
import de.mas.wiiu.jnus.fuse_wiiu.utils.TicketUtils;
@ -28,7 +28,7 @@ public class LocalNUSTitleContainer extends GroupFuseContainer {
long titleID = 0;
short version = 0;
try {
TMD tmd = TMD.parseTMD(new File(folder.getAbsoluteFile() + File.separator + "title.tmd"));
TitleMetaData tmd = TitleMetaData.parseTMD(new File(folder.getAbsoluteFile() + File.separator + "title.tmd"));
titleID = tmd.getTitleID();
version = tmd.getTitleVersion();
} catch (IOException | ParseException e2) {

View File

@ -12,6 +12,7 @@ import lombok.val;
public class MultipleFSTDataProviderFuseContainer<T> extends GroupFuseContainer {
private final File file;
private final FSTDataProviderLoader<T> loader;
private int i = 0;
public MultipleFSTDataProviderFuseContainer(Optional<FuseDirectory> parent, File file, FSTDataProviderLoader<T> loader) {
super(parent);
@ -31,7 +32,7 @@ public class MultipleFSTDataProviderFuseContainer<T> extends GroupFuseContainer
void parseContents(List<FSTDataProvider> dps) {
for (val dp : dps) {
this.addFuseContainer(dp.getName(), new FSTDataProviderContainer(getParent(), dp));
this.addFuseContainer(dp.getName() + "_" + (++i), new FSTDataProviderContainer(getParent(), dp));
}
}
}

View File

@ -7,7 +7,8 @@ import java.util.List;
import java.util.Optional;
import de.mas.wiiu.jnus.NUSTitleLoaderFST;
import de.mas.wiiu.jnus.entities.fst.FSTEntry;
import de.mas.wiiu.jnus.entities.FST.nodeentry.DirectoryEntry;
import de.mas.wiiu.jnus.entities.FST.nodeentry.FileEntry;
import de.mas.wiiu.jnus.fuse_wiiu.Settings;
import de.mas.wiiu.jnus.fuse_wiiu.interfaces.FSTDataProviderLoader;
import de.mas.wiiu.jnus.fuse_wiiu.interfaces.FuseDirectory;
@ -25,34 +26,29 @@ public class MultipleFSTDataProviderRecursiveFuseContainer<T> extends MultipleFS
void parseContents(List<FSTDataProvider> dps) {
try {
for (FSTDataProvider dp : dps) {
for (FSTEntry tmd : FSTUtils.getFSTEntriesByRegEx(dp.getRoot(), ".*tmd")) {
Optional<FSTEntry> parentOpt = tmd.getParent();
if (parentOpt.isPresent()) {
FSTEntry parent = parentOpt.get();
if (parent.getFileChildren().stream().filter(f -> f.getFilename().endsWith(".app")).findAny().isPresent()) {
FSTDataProvider fdp = null;
for (FileEntry tmd : FSTUtils.getFSTEntriesByRegEx(dp.getRoot(), ".*tmd")) {
DirectoryEntry parent = tmd.getParent();
if (parent.getFileChildren().stream().filter(f -> f.getName().endsWith(".app")).findAny().isPresent()) {
FSTDataProvider fdp = null;
try {
fdp = new FSTDataProviderNUSTitle(NUSTitleLoaderFST.loadNUSTitle(dp, parent, Settings.retailCommonKey));
} catch (IOException | ParseException e) {
try {
fdp = new FSTDataProviderNUSTitle(NUSTitleLoaderFST.loadNUSTitle(dp, parent, Settings.retailCommonKey));
} catch (IOException | ParseException e) {
try {
fdp = new FSTDataProviderNUSTitle(NUSTitleLoaderFST.loadNUSTitle(dp, parent, Settings.devCommonKey));
} catch (Exception e1) {
System.out.println("Ignoring " + parent.getFilename() + " :" + e1.getClass().getName() + " " + e1.getMessage());
continue;
}
} catch (Exception e) {
System.out.println("Ignoring " + parent.getFilename() + " :" + e.getClass().getName() + " " + e.getMessage());
fdp = new FSTDataProviderNUSTitle(NUSTitleLoaderFST.loadNUSTitle(dp, parent, Settings.devCommonKey));
} catch (Exception e1) {
System.out.println("Ignoring " + parent.getName() + " :" + e1.getClass().getName() + " " + e1.getMessage());
continue;
}
FSTDataProvider fdpCpy = fdp;
this.addFuseContainer("[DECRYPTED] [" + dp.getName() + "] " + parent.getFilename(),
new FSTDataProviderContainer(getParent(), fdpCpy));
} catch (Exception e) {
System.out.println("Ignoring " + parent.getName() + " :" + e.getClass().getName() + " " + e.getMessage());
continue;
}
}
FSTDataProvider fdpCpy = fdp;
this.addFuseContainer("[DECRYPTED] [" + dp.getName() + "] " + parent.getName(), new FSTDataProviderContainer(getParent(), fdpCpy));
}
}
if (dp instanceof HasNUSTitle) {

View File

@ -7,7 +7,7 @@ import java.util.Optional;
import java.util.function.Supplier;
import de.mas.wiiu.jnus.NUSTitle;
import de.mas.wiiu.jnus.entities.content.Content;
import de.mas.wiiu.jnus.entities.TMD.Content;
import de.mas.wiiu.jnus.fuse_wiiu.interfaces.FuseContainer;
import de.mas.wiiu.jnus.fuse_wiiu.interfaces.FuseDirectory;
import jnr.ffi.Pointer;

View File

@ -0,0 +1,62 @@
package de.mas.wiiu.jnus.fuse_wiiu.implementation;
import java.io.File;
import java.io.IOException;
import java.util.Optional;
import de.mas.wiiu.jnus.NUSTitle;
import de.mas.wiiu.jnus.NUSTitleLoaderRemoteLocal;
import de.mas.wiiu.jnus.entities.Ticket;
import de.mas.wiiu.jnus.fuse_wiiu.Settings;
import de.mas.wiiu.jnus.fuse_wiiu.interfaces.FuseDirectory;
import de.mas.wiiu.jnus.fuse_wiiu.utils.TicketUtils;
import de.mas.wiiu.jnus.implementations.FSTDataProviderNUSTitle;
import de.mas.wiiu.jnus.utils.Utils;
public class RemoteLocalBackupNUSTitleContainer extends GroupFuseContainer {
private File folder;
public RemoteLocalBackupNUSTitleContainer(Optional<FuseDirectory> parent, File folder) {
super(parent);
this.folder = folder;
}
@Override
protected void doInit() {
File[] wud = folder.listFiles(f -> f.getName().startsWith("tmd."));
for (File versionF : wud) {
short version = Short.parseShort(versionF.getName().substring(4));
this.addFuseContainer(String.format("v%d", version), new FSTDataProviderContainer(Optional.of(this), () -> {
long titleID = Utils.StringToLong(folder.getName());
NUSTitle t = null;
Optional<Ticket> ticketOpt = TicketUtils.getTicket(folder, Settings.titlekeyPath, titleID, Settings.retailCommonKey);
System.out.println(ticketOpt);
if (!ticketOpt.isPresent()) {
return null;
}
Ticket ticket = ticketOpt.get();
try {
t = NUSTitleLoaderRemoteLocal.loadNUSTitle(folder.getAbsolutePath(), version, ticket);
} catch (Exception e) {
// Try dev ticket
ticket = Ticket.createTicket(ticket.getEncryptedKey(), titleID, Settings.devCommonKey);
try {
t = NUSTitleLoaderRemoteLocal.loadNUSTitle(folder.getAbsolutePath(), version, ticket);
} catch (Exception e1) {
e.printStackTrace();
e1.printStackTrace();
}
}
try {
return new FSTDataProviderNUSTitle(t);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}));
}
}
}

View File

@ -8,7 +8,7 @@ import de.mas.wiiu.jnus.fuse_wiiu.interfaces.FuseContainer;
import de.mas.wiiu.jnus.fuse_wiiu.interfaces.FuseDirectory;
import de.mas.wiiu.jnus.fuse_wiiu.utils.WUDUtils;
import de.mas.wiiu.jnus.implementations.wud.WUDImage;
import de.mas.wiiu.jnus.implementations.wud.parser.WUDInfo;
import de.mas.wiiu.jnus.implementations.wud.WiiUDisc;
import jnr.ffi.Pointer;
import ru.serce.jnrfuse.ErrorCodes;
import ru.serce.jnrfuse.FuseFillDir;
@ -17,7 +17,7 @@ import ru.serce.jnrfuse.struct.FuseFileInfo;
public class WUDToWUDContainer implements FuseContainer {
private final String filename;
private final Optional<WUDInfo> wudInfo;
private final Optional<WiiUDisc> wudInfo;
private final Optional<FuseDirectory> parent;
public WUDToWUDContainer(Optional<FuseDirectory> parent, File c) {
@ -91,7 +91,7 @@ public class WUDToWUDContainer implements FuseContainer {
try {
byte[] data;
data = wudInfo.get().getWUDDiscReader().readEncryptedToByteArray(offset, 0, size);
data = wudInfo.get().getReader().get().readEncryptedToByteArray(offset, 0, size);
buf.put(0, data, 0, data.length);
return data.length;
} catch (IOException e) {

View File

@ -11,11 +11,11 @@ import de.mas.wiiu.jnus.WUDLoader;
import de.mas.wiiu.jnus.fuse_wiiu.Settings;
import de.mas.wiiu.jnus.fuse_wiiu.interfaces.FSTDataProviderLoader;
import de.mas.wiiu.jnus.fuse_wiiu.utils.WUDUtils;
import de.mas.wiiu.jnus.implementations.wud.parser.WUDInfo;
import de.mas.wiiu.jnus.implementations.wud.WiiUDisc;
import de.mas.wiiu.jnus.interfaces.FSTDataProvider;
import lombok.Getter;
public class WUDFSTDataProviderLoader implements FSTDataProviderLoader<WUDInfo> {
public class WUDFSTDataProviderLoader implements FSTDataProviderLoader<WiiUDisc> {
@Getter
private static WUDFSTDataProviderLoader instance = new WUDFSTDataProviderLoader();
@ -23,7 +23,7 @@ public class WUDFSTDataProviderLoader implements FSTDataProviderLoader<WUDInfo>
}
@Override
public List<FSTDataProvider> getDataProvider(WUDInfo info) {
public List<FSTDataProvider> getDataProvider(WiiUDisc info) {
List<FSTDataProvider> dps = new ArrayList<>();
try {
dps = WUDLoader.getPartitonsAsFSTDataProvider(info, Settings.retailCommonKey);
@ -38,7 +38,7 @@ public class WUDFSTDataProviderLoader implements FSTDataProviderLoader<WUDInfo>
}
@Override
public Optional<WUDInfo> loadInfo(File input) {
public Optional<WiiUDisc> loadInfo(File input) {
return WUDUtils.loadWUDInfo(input);
}
}

View File

@ -10,6 +10,7 @@ import de.mas.wiiu.jnus.fuse_wiiu.implementation.LocalBackupNUSTitleContainer;
import de.mas.wiiu.jnus.fuse_wiiu.implementation.LocalNUSTitleContainer;
import de.mas.wiiu.jnus.fuse_wiiu.implementation.MultipleFSTDataProviderFuseContainer;
import de.mas.wiiu.jnus.fuse_wiiu.implementation.MultipleFSTDataProviderRecursiveFuseContainer;
import de.mas.wiiu.jnus.fuse_wiiu.implementation.RemoteLocalBackupNUSTitleContainer;
import de.mas.wiiu.jnus.fuse_wiiu.implementation.WUDToWUDContainer;
import de.mas.wiiu.jnus.fuse_wiiu.implementation.WoomyNUSTitleContainer;
import de.mas.wiiu.jnus.fuse_wiiu.implementation.loader.WUDFSTDataProviderLoader;
@ -25,14 +26,22 @@ public class FuseContainerWrapper {
public static Map<String, FuseContainer> createFuseContainer(Optional<FuseDirectory> parent, File c) {
System.out.println("Mounting " + c.getAbsolutePath());
Map<String, FuseContainer> result = new HashMap<>();
if (c.exists() && c.isDirectory()) {
File[] tmd = c.listFiles(f -> f.isFile() && f.getName().startsWith("tmd."));
if (tmd != null && tmd.length > 0) {
result.put(prefix + c.getName(), new RemoteLocalBackupNUSTitleContainer(parent, c));
return result;
}
}
if (c.exists() && c.isDirectory()) {
File[] tmd = c.listFiles(f -> f.isFile() && f.getName().equals("title.tmd"));
if (tmd != null && tmd.length > 0) {
// In case there is a tmd file
// Checks if we have the local backup format
File[] versions = c.listFiles(f -> f.isDirectory() && f.getName().startsWith("v"));
File[] versions = c.listFiles(f -> f.getName().startsWith("tmd."));
if (versions != null && versions.length > 0 && c.getName().length() == 16 && Utils.StringToLong(c.getName()) > 0) {
result.put(prefix + c.getName(), new LocalBackupNUSTitleContainer(parent, c));
return result;
@ -55,8 +64,7 @@ public class FuseContainerWrapper {
return result;
}
if (checkWUD(result, parent, c)) {
return result;
}
@ -70,7 +78,7 @@ public class FuseContainerWrapper {
}
private static boolean checkWUD(Map<String, FuseContainer> result, Optional<FuseDirectory> parent, File c) {
if (c.exists() && c.isFile() && (c.getName().endsWith(".wux") || c.getName().endsWith(".wud") || c.getName().endsWith(".ddi"))) {
if (c.exists() && c.isFile() && (c.getName().endsWith(".wux") || c.getName().endsWith(".wud") || c.getName().endsWith(".ddi") || c.getName().endsWith(".wumada"))) {
if (c.length() == WUDDiscReaderSplitted.WUD_SPLITTED_FILE_SIZE && !c.getName().endsWith("part1.wud")) {
return false;
}

View File

@ -14,6 +14,9 @@ public class TicketUtils {
if (folder != null) {
ticketFile = FileUtils.getFileIgnoringFilenameCases(folder.getAbsolutePath(), "title.tik");
}
if (ticketFile == null) {
ticketFile = FileUtils.getFileIgnoringFilenameCases(folder.getAbsolutePath(), "cetk");
}
Ticket ticket = null;
if (ticketFile != null && ticketFile.exists()) {
try {

View File

@ -9,10 +9,10 @@ import org.apache.commons.io.FilenameUtils;
import de.mas.wiiu.jnus.WUDLoader;
import de.mas.wiiu.jnus.fuse_wiiu.Settings;
import de.mas.wiiu.jnus.implementations.wud.parser.WUDInfo;
import de.mas.wiiu.jnus.implementations.wud.WiiUDisc;
public class WUDUtils {
public static Optional<WUDInfo> loadWUDInfo(File file) {
public static Optional<WiiUDisc> loadWUDInfo(File file) {
String FSfilename = file.getName();
String basename = FilenameUtils.getBaseName(FSfilename);
File keyFile = new File(file.getParent() + File.separator + basename + ".key");