getDataProvider(T info);
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/de/mas/wiiu/jnus/fuse_wiiu/interfaces/FuseContainer.java:
--------------------------------------------------------------------------------
1 | package de.mas.wiiu.jnus.fuse_wiiu.interfaces;
2 |
3 | import jnr.ffi.Pointer;
4 | import jnr.ffi.types.off_t;
5 | import jnr.ffi.types.size_t;
6 | import ru.serce.jnrfuse.FuseFillDir;
7 | import ru.serce.jnrfuse.struct.FileStat;
8 | import ru.serce.jnrfuse.struct.FuseFileInfo;
9 |
10 | /**
11 | * Simplified version of the FuseFS interface.
12 | *
13 | * @author Maschell
14 | */
15 | public interface FuseContainer extends FuseDirectory {
16 | /**
17 | * Wrapper for the getattr function of the FuseFS interface.
18 | * When this function is called, the path will be relative to this FuseContainer
19 | *
20 | * Get file attributes.
21 | *
22 | * Similar to stat(). The 'st_dev' and 'st_blksize' fields are
23 | * ignored. The 'st_ino' field is ignored except if the 'use_ino'
24 | * mount option is given.
25 | */
26 | int getattr(String path, FileStat stat);
27 |
28 | /**
29 | * Wrapper for the getattr function of the FuseFS interface.
30 | * When this function is called, the path will be relative to this FuseContainer
31 | *
32 | * File open operation
33 | *
34 | * No creation (O_CREAT, O_EXCL) and by default also no
35 | * truncation (O_TRUNC) flags will be passed to open(). If an
36 | * application specifies O_TRUNC, fuse first calls truncate()
37 | * and then open(). Only if 'atomic_o_trunc' has been
38 | * specified and kernel version is 2.6.24 or later, O_TRUNC is
39 | * passed on to open.
40 | *
41 | * Unless the 'default_permissions' mount option is given,
42 | * open should check if the operation is permitted for the
43 | * given flags. Optionally open may also return an arbitrary
44 | * filehandle in the fuse_file_info structure, which will be
45 | * passed to all file operations.
46 | *
47 | * @see jnr.constants.platform.OpenFlags
48 | */
49 | int open(String path, FuseFileInfo fi);
50 |
51 | /**
52 | * Wrapper for the readdir function of the FuseFS interface.
53 | * When this function is called, the path will be relative to this FuseContainer
54 | *
55 | * Read directory
56 | *
57 | * This supersedes the old getdir() interface. New applications
58 | * should use this.
59 | *
60 | * The filesystem may choose between two modes of operation:
61 | *
62 | * 1) The readdir implementation ignores the offset parameter, and
63 | * passes zero to the filler function's offset. The filler
64 | * function will not return '1' (unless an error happens), so the
65 | * whole directory is read in a single readdir operation. This
66 | * works just like the old getdir() method.
67 | *
68 | * 2) The readdir implementation keeps track of the offsets of the
69 | * directory entries. It uses the offset parameter and always
70 | * passes non-zero offset to the filler function. When the buffer
71 | * is full (or an error happens) the filler function will return
72 | * '1'.
73 | */
74 | int readdir(String path, Pointer buf, FuseFillDir filter, @off_t long offset, FuseFileInfo fi);
75 |
76 | /**
77 | * Wrapper for the getattr function of the FuseFS interface.
78 | * When this function is called, the path will be relative to this FuseContainer
79 | *
80 | * Read data from an open file
81 | *
82 | * Read should return exactly the number of bytes requested except
83 | * on EOF or error, otherwise the rest of the data will be
84 | * substituted with zeroes. An exception to this is when the
85 | * 'direct_io' mount option is specified, in which case the return
86 | * value of the read system call will reflect the return value of
87 | * this operation.
88 | */
89 | int read(String path, Pointer buf, @size_t long size, @off_t long offset, FuseFileInfo fi);
90 |
91 | /**
92 | * This function will be called when ever the FuseContainer needs to update it's children.
93 | */
94 | void init();
95 |
96 | /**
97 | * This function will be called right before this FuseContainer won't be used anymore.
98 | */
99 | void deinit();
100 |
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/java/de/mas/wiiu/jnus/fuse_wiiu/interfaces/FuseDirectory.java:
--------------------------------------------------------------------------------
1 | package de.mas.wiiu.jnus.fuse_wiiu.interfaces;
2 |
3 | import java.util.Optional;
4 |
5 | /**
6 | * Representation of a directory.
7 | *
8 | * @author Maschell
9 | */
10 | public interface FuseDirectory {
11 |
12 | /**
13 | * Returns the parent of this FuseDirectory.
14 | *
15 | * @return parent
16 | */
17 | Optional getParent();
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/de/mas/wiiu/jnus/fuse_wiiu/utils/FuseContainerWrapper.java:
--------------------------------------------------------------------------------
1 | package de.mas.wiiu.jnus.fuse_wiiu.utils;
2 |
3 | import de.mas.wiiu.jnus.fuse_wiiu.implementation.*;
4 | import de.mas.wiiu.jnus.fuse_wiiu.implementation.loader.WUDFSTDataProviderLoader;
5 | import de.mas.wiiu.jnus.fuse_wiiu.implementation.loader.WumadFSTDataProviderLoader;
6 | import de.mas.wiiu.jnus.fuse_wiiu.interfaces.FuseContainer;
7 | import de.mas.wiiu.jnus.fuse_wiiu.interfaces.FuseDirectory;
8 | import de.mas.wiiu.jnus.implementations.wud.reader.WUDDiscReaderSplitted;
9 | import de.mas.wiiu.jnus.utils.Utils;
10 |
11 | import java.io.File;
12 | import java.util.HashMap;
13 | import java.util.Map;
14 | import java.util.Optional;
15 |
16 | public class FuseContainerWrapper {
17 |
18 | private final static String prefix = "[EMULATED] ";
19 |
20 | public static Map createFuseContainer(Optional parent, File c) {
21 | System.out.println("Mounting " + c.getAbsolutePath());
22 |
23 | Map result = new HashMap<>();
24 | if (c.exists() && c.isDirectory()) {
25 | File[] tmd = c.listFiles(f -> f.isFile() && f.getName().startsWith("tmd"));
26 | File[] appFiles = c.listFiles(f -> f.isFile() && f.getName().startsWith("000") && f.getName().length() == 8);
27 | if (tmd != null && tmd.length > 0 && appFiles != null && appFiles.length > 0) {
28 | result.put(prefix + c.getName(), new RemoteLocalBackupNUSTitleContainer(parent, c));
29 | return result;
30 | }
31 | }
32 |
33 |
34 | if (c.exists() && c.isDirectory()) {
35 | File[] tmd = c.listFiles(f -> f.isFile() && (f.getName().startsWith("tmd.") || f.getName().startsWith("title.tmd")));
36 | if (tmd != null && tmd.length > 0) {
37 | // In case there is a tmd file
38 |
39 | // Checks if we have the local backup format
40 | File[] versions = c.listFiles(f -> f.getName().startsWith("tmd."));
41 | if (versions != null && versions.length > 0 && c.getName().length() == 16 && Utils.StringToLong(c.getName()) > 0) {
42 | result.put(prefix + c.getName(), new LocalBackupNUSTitleContainer(parent, c));
43 | return result;
44 | }
45 |
46 | // if not return normal title container.
47 | result.put(prefix + c.getName(), new LocalNUSTitleContainer(parent, c));
48 | return result;
49 | }
50 | }
51 |
52 | if (c.exists() && c.getName().endsWith(".woomy")) {
53 | result.put(prefix + c.getName(), new WoomyNUSTitleContainer(parent, c));
54 | return result;
55 | }
56 |
57 | if (c.exists() && c.getName().endsWith(".wumad")) {
58 | result.put(prefix + c.getName(), new MultipleFSTDataProviderFuseContainer<>(parent, c, WumadFSTDataProviderLoader.getInstance()));
59 | result.put(prefix + "[EXTRA] " + c.getName(), new MultipleFSTDataProviderRecursiveFuseContainer<>(parent, c, WumadFSTDataProviderLoader.getInstance()));
60 |
61 | return result;
62 | }
63 |
64 | if (checkWUD(result, parent, c)) {
65 | return result;
66 | }
67 |
68 | if (c.isDirectory()) {
69 | result.put(c.getName(), new FSFuseContainer(parent, c));
70 | return result;
71 |
72 | }
73 | return result;
74 | }
75 |
76 | private static boolean checkWUD(Map result, Optional parent, File c) {
77 | if (c.exists() && c.isFile() && (c.getName().endsWith(".wux") || c.getName().endsWith(".wud") || c.getName().endsWith(".ddi") || c.getName().endsWith(".wumada"))) {
78 | if (c.length() == WUDDiscReaderSplitted.WUD_SPLITTED_FILE_SIZE && !c.getName().endsWith("part1.wud")) {
79 | return false;
80 | }
81 |
82 | result.put(prefix + c.getName(), new MultipleFSTDataProviderFuseContainer<>(parent, c, WUDFSTDataProviderLoader.getInstance()));
83 | result.put(prefix + "[EXTRA] " + c.getName(), new MultipleFSTDataProviderRecursiveFuseContainer<>(parent, c, WUDFSTDataProviderLoader.getInstance()));
84 | if (c.getName().endsWith("part1.wud") || c.getName().endsWith(".wux")) {
85 | result.put(prefix + "[WUD] " + c.getName(), new WUDToWUDContainer(parent, c));
86 | }
87 | return true;
88 |
89 | }
90 | return false;
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/de/mas/wiiu/jnus/fuse_wiiu/utils/TicketUtils.java:
--------------------------------------------------------------------------------
1 | package de.mas.wiiu.jnus.fuse_wiiu.utils;
2 |
3 | import de.mas.wiiu.jnus.entities.Ticket;
4 | import de.mas.wiiu.jnus.utils.FileUtils;
5 |
6 | import java.io.File;
7 | import java.io.IOException;
8 | import java.nio.file.Files;
9 | import java.util.Optional;
10 |
11 | public class TicketUtils {
12 | public static Optional getTicket(File folder, File keyFolder, long titleID, byte[] commonKey) {
13 | File ticketFile = null;
14 | if (folder != null) {
15 | ticketFile = FileUtils.getFileIgnoringFilenameCases(folder.getAbsolutePath(), "title.tik");
16 | }
17 | if (ticketFile == null) {
18 | ticketFile = FileUtils.getFileIgnoringFilenameCases(folder.getAbsolutePath(), "cetk");
19 | }
20 | Ticket ticket = null;
21 | if (ticketFile != null && ticketFile.exists()) {
22 | try {
23 | ticket = Ticket.parseTicket(ticketFile, commonKey);
24 | } catch (IOException e) {
25 | }
26 | }
27 |
28 | if (ticket == null && keyFolder != null) {
29 | File keyFile = FileUtils.getFileIgnoringFilenameCases(keyFolder.getAbsolutePath(), String.format("%016X", titleID) + ".key");
30 | if (keyFile != null && keyFile.exists()) {
31 | byte[] key;
32 | try {
33 | key = Files.readAllBytes(keyFile.toPath());
34 | if (key != null && key.length == 16) {
35 | ticket = Ticket.createTicket(key, titleID, commonKey);
36 | }
37 | } catch (IOException e) {
38 | }
39 | }
40 | }
41 | if (ticket != null) {
42 | return Optional.of(ticket);
43 | }
44 | return Optional.empty();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/de/mas/wiiu/jnus/fuse_wiiu/utils/WUDUtils.java:
--------------------------------------------------------------------------------
1 | package de.mas.wiiu.jnus.fuse_wiiu.utils;
2 |
3 | import de.mas.wiiu.jnus.WUDLoader;
4 | import de.mas.wiiu.jnus.fuse_wiiu.Settings;
5 | import de.mas.wiiu.jnus.implementations.wud.WiiUDisc;
6 | import org.apache.commons.io.FilenameUtils;
7 |
8 | import java.io.File;
9 | import java.io.PrintWriter;
10 | import java.io.StringWriter;
11 | import java.util.Optional;
12 |
13 | public class WUDUtils {
14 | public static Optional loadWUDInfo(File file) {
15 | String FSfilename = file.getName();
16 | String basename = FilenameUtils.getBaseName(FSfilename);
17 | File keyFile = new File(file.getParent() + File.separator + basename + ".key");
18 |
19 | if (!keyFile.exists() && Settings.disckeyPath != null) {
20 | System.out.println(".key not found at " + keyFile.getAbsolutePath());
21 | keyFile = new File(Settings.disckeyPath.getAbsoluteFile() + File.separator + basename + ".key");
22 | if (!keyFile.exists()) {
23 | System.out.println(".key not found at " + keyFile.getAbsolutePath());
24 | }
25 | }
26 |
27 | try {
28 | if (keyFile.exists()) {
29 | return Optional.of(WUDLoader.load(file.getAbsolutePath(), keyFile));
30 | } else {
31 | System.out.println("No .key was not found. Trying dev mode.");
32 | return Optional.of(WUDLoader.loadDev(file.getAbsolutePath()));
33 | }
34 | } catch (Exception e) {
35 | e.printStackTrace();
36 | StringWriter errors = new StringWriter();
37 | e.printStackTrace(new PrintWriter(errors));
38 | System.err.println(errors);
39 | }
40 |
41 | return Optional.empty();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------