mirror of
https://github.com/switchbrew/libnx.git
synced 2025-11-11 09:11:25 +01:00
Find RomFS mounts by name Find RomFS files by path or with a mount Iterate RomFS directory entries
225 lines
7.9 KiB
C
225 lines
7.9 KiB
C
/**
|
|
* @file romfs_dev.h
|
|
* @brief RomFS driver.
|
|
* @author yellows8
|
|
* @author mtheall
|
|
* @author fincs
|
|
* @copyright libnx Authors
|
|
*/
|
|
#pragma once
|
|
|
|
#include "../../types.h"
|
|
#include "../../services/fs.h"
|
|
#include "../../services/ncm_types.h"
|
|
|
|
/// RomFS header.
|
|
typedef struct
|
|
{
|
|
u64 headerSize; ///< Size of the header.
|
|
u64 dirHashTableOff; ///< Offset of the directory hash table.
|
|
u64 dirHashTableSize; ///< Size of the directory hash table.
|
|
u64 dirTableOff; ///< Offset of the directory table.
|
|
u64 dirTableSize; ///< Size of the directory table.
|
|
u64 fileHashTableOff; ///< Offset of the file hash table.
|
|
u64 fileHashTableSize; ///< Size of the file hash table.
|
|
u64 fileTableOff; ///< Offset of the file table.
|
|
u64 fileTableSize; ///< Size of the file table.
|
|
u64 fileDataOff; ///< Offset of the file data.
|
|
} romfs_header;
|
|
|
|
/// RomFS directory.
|
|
typedef struct
|
|
{
|
|
u32 parent; ///< Offset of the parent directory.
|
|
u32 sibling; ///< Offset of the next sibling directory.
|
|
u32 childDir; ///< Offset of the first child directory.
|
|
u32 childFile; ///< Offset of the first file.
|
|
u32 nextHash; ///< Directory hash table pointer.
|
|
u32 nameLen; ///< Name length.
|
|
uint8_t name[]; ///< Name. (UTF-8)
|
|
} romfs_dir;
|
|
|
|
/// RomFS file.
|
|
typedef struct
|
|
{
|
|
u32 parent; ///< Offset of the parent directory.
|
|
u32 sibling; ///< Offset of the next sibling file.
|
|
u64 dataOff; ///< Offset of the file's data.
|
|
u64 dataSize; ///< Length of the file's data.
|
|
u32 nextHash; ///< File hash table pointer.
|
|
u32 nameLen; ///< Name length.
|
|
uint8_t name[]; ///< Name. (UTF-8)
|
|
} romfs_file;
|
|
|
|
/**
|
|
* @brief Mounts the Application's RomFS.
|
|
* @param name Device mount name.
|
|
* @remark This function is intended to be used to access one's own RomFS.
|
|
* If the application is running as NRO, it mounts the embedded RomFS section inside the NRO.
|
|
* If on the other hand it's an NSO, it behaves identically to \ref romfsMountFromCurrentProcess.
|
|
*/
|
|
Result romfsMountSelf(const char *name);
|
|
|
|
/**
|
|
* @brief Mounts RomFS from an open file.
|
|
* @param file FsFile of the RomFS image.
|
|
* @param offset Offset of the RomFS within the file.
|
|
* @param name Device mount name.
|
|
*/
|
|
Result romfsMountFromFile(FsFile file, u64 offset, const char *name);
|
|
|
|
/**
|
|
* @brief Mounts RomFS from an open storage.
|
|
* @param storage FsStorage of the RomFS image.
|
|
* @param offset Offset of the RomFS within the storage.
|
|
* @param name Device mount name.
|
|
*/
|
|
Result romfsMountFromStorage(FsStorage storage, u64 offset, const char *name);
|
|
|
|
/**
|
|
* @brief Mounts RomFS using the current process host program RomFS.
|
|
* @param name Device mount name.
|
|
*/
|
|
Result romfsMountFromCurrentProcess(const char *name);
|
|
|
|
/**
|
|
* @brief Mounts RomFS of a running program.
|
|
* @note Permission needs to be set in the NPDM.
|
|
* @param program_id ProgramId to mount.
|
|
* @param name Device mount name.
|
|
*/
|
|
Result romfsMountDataStorageFromProgram(u64 program_id, const char *name);
|
|
|
|
/**
|
|
* @brief Mounts RomFS from a file path in a mounted fsdev device.
|
|
* @param path File path.
|
|
* @param offset Offset of the RomFS within the file.
|
|
* @param name Device mount name.
|
|
*/
|
|
Result romfsMountFromFsdev(const char *path, u64 offset, const char *name);
|
|
|
|
/**
|
|
* @brief Mounts RomFS from SystemData.
|
|
* @param dataId SystemDataId to mount.
|
|
* @param storageId Storage ID to mount from.
|
|
* @param name Device mount name.
|
|
*/
|
|
Result romfsMountFromDataArchive(u64 dataId, NcmStorageId storageId, const char *name);
|
|
|
|
/// Unmounts the RomFS device.
|
|
Result romfsUnmount(const char *name);
|
|
|
|
/// Wrapper for \ref romfsMountSelf with the default "romfs" device name.
|
|
static inline Result romfsInit(void)
|
|
{
|
|
return romfsMountSelf("romfs");
|
|
}
|
|
|
|
/// Wrapper for \ref romfsUnmount with the default "romfs" device name.
|
|
static inline Result romfsExit(void)
|
|
{
|
|
return romfsUnmount("romfs");
|
|
}
|
|
|
|
/// Opaque handle to a RomFS mount
|
|
typedef struct romfs_mount romfs_mount;
|
|
|
|
/// Object for interacting with a romfs_file
|
|
typedef struct
|
|
{
|
|
romfs_mount *mount; ///< The RomFS mount the file is associated with.
|
|
romfs_file *file; ///< Detail about the actual RomFS file.
|
|
|
|
u64 offset; ///< The starting offset in RomFS for file data.
|
|
u64 pos; ///< Current read position into the file.
|
|
} romfs_fileobj;
|
|
|
|
/**
|
|
* @brief Finds a RomFS mount by the given name, the default mount name is "romfs"
|
|
* @param name The name of the mount to search for
|
|
* @param mount A pointer to a romfs_mount pointer to fill out with the mount information
|
|
*/
|
|
Result romfsFindMount(const char *name, romfs_mount **mount);
|
|
|
|
/**
|
|
* @brief Finds a file in RomFS automatically determining the mount
|
|
* @param path The path to the file
|
|
* @param file A pointer to a romfs_fileobj structure to fill out
|
|
* @remark The path structure should follow <mount name>:<path> (i.e. romfs:/data/file.txt)
|
|
* If no mount name is provided the default of "romfs" will be used.
|
|
*/
|
|
Result romfsFindFile(const char *path, romfs_fileobj *file);
|
|
|
|
/**
|
|
* @brief Finds a file in a specific RomFS mount
|
|
* @param mount The mount to search in
|
|
* @param path The path to the file
|
|
* @param file A pointer to a romfs_fileobj structure to fill out
|
|
* @remark The mount name prefix is not required and is ignored if provided
|
|
*/
|
|
Result romfsFindFileInMount(romfs_mount *mount, const char *path, romfs_fileobj *file);
|
|
|
|
/**
|
|
* @brief Reads data from the specified RomFS file.
|
|
* @param file The RomFS file to read from.
|
|
* @param buffer The buffer to read data into.
|
|
* @param size The number of bytes to read.
|
|
* @param offset The offset in bytes from the beginning of the file to start reading from.
|
|
* @param nread A pointer in which the number of total bytes read will be written to.
|
|
* @remark The file's position pointer is not updated by this function.
|
|
*/
|
|
Result romfsReadFile(romfs_fileobj *file, void *buffer, u64 size, u64 offset, u64 *nread);
|
|
|
|
typedef struct
|
|
{
|
|
romfs_mount *mount; ///< The RomFS mount associated with the directory.
|
|
romfs_dir *dir; ///< Information about the directory being searched.
|
|
u32 state; ///< Current iteration count.
|
|
u32 childDir; ///< Next child directory of the directory.
|
|
u32 childFile; ///< Next child file of the directory.
|
|
} romfs_diriter;
|
|
|
|
typedef enum
|
|
{
|
|
RomfsDirEntryType_File = 0,
|
|
RomfsDirEntryType_Dir
|
|
} RomfsDirEntryType;
|
|
|
|
typedef struct
|
|
{
|
|
RomfsDirEntryType type; ///< Type of this entry.
|
|
union
|
|
{
|
|
const romfs_file *file; ///< Entry information if type is RomfsDirEntryType_File.
|
|
const romfs_dir *dir; ///< Entry information if type is RomfsDirEntryType_Dir.
|
|
};
|
|
|
|
const char *name; ///< Basename of the entry, not null-terminated, UTF-8 coded.
|
|
u32 name_len; ///< Length in bytes of the basename.
|
|
} romfs_direntry;
|
|
|
|
/**
|
|
* @brief Initialises the directory iterator for seaching at the given path, automatically determines mount.
|
|
* @param path The directory path to search.
|
|
* @param iter The directory iterator to fill out with found information.
|
|
* @remark The path structure should follow <mount name>:<path> (i.e. romfs:/data/folder).
|
|
* If no mount name is provided the default of "romfs" will be used.
|
|
*/
|
|
Result romfsDirOpen(const char *path, romfs_diriter *iter);
|
|
|
|
/**
|
|
* @brief Initialises the directory iterator for seaching at the given path in the supplied mount.
|
|
* @param mount The RomFS mount to search in.
|
|
* @param path The directory path to search.
|
|
* @param iter The directory iterator to fill out with found information.
|
|
* @remark The mount does not need to be specified in the path and is ignored if provided.
|
|
*/
|
|
Result romfsDirOpenWithMount(romfs_mount *mount, const char *path, romfs_diriter *iter);
|
|
|
|
/**
|
|
* @brief Gets the next entry in the directory, returns false on error or when no more entries are found.
|
|
* @param iter The directory iterator.
|
|
* @param entry The entry to fill out with information.
|
|
*/
|
|
bool romfsDirNext(romfs_diriter *iter, romfs_direntry *entry);
|