|
|
|
@ -4,16 +4,68 @@ use collections::Vec;
@@ -4,16 +4,68 @@ use collections::Vec;
|
|
|
|
|
|
|
|
|
|
use path::Path; |
|
|
|
|
|
|
|
|
|
use libctru::services::fs; |
|
|
|
|
use libctru::services::fs::*; |
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug)] |
|
|
|
|
pub enum PathType { |
|
|
|
|
Invalid, |
|
|
|
|
Empty, |
|
|
|
|
Binary, |
|
|
|
|
ASCII, |
|
|
|
|
UTF16, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug)] |
|
|
|
|
pub enum ArchiveID { |
|
|
|
|
RomFS, |
|
|
|
|
Savedata, |
|
|
|
|
Extdata, |
|
|
|
|
SharedExtdata, |
|
|
|
|
SystemSavedata, |
|
|
|
|
Sdmc, |
|
|
|
|
SdmcWriteOnly, |
|
|
|
|
BossExtdata, |
|
|
|
|
CardSpiFS, |
|
|
|
|
ExtDataAndBossExtdata, |
|
|
|
|
SystemSaveData2, |
|
|
|
|
NandRW, |
|
|
|
|
NandRO, |
|
|
|
|
NandROWriteAccess, |
|
|
|
|
SaveDataAndContent, |
|
|
|
|
SaveDataAndContent2, |
|
|
|
|
NandCtrFS, |
|
|
|
|
TwlPhoto, |
|
|
|
|
NandTwlFS, |
|
|
|
|
GameCardSavedata, |
|
|
|
|
UserSavedata, |
|
|
|
|
DemoSavedata, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub struct Fs { |
|
|
|
|
pd: PhantomData<i32>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub struct Archive { |
|
|
|
|
id: ArchiveID, |
|
|
|
|
handle: u64, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub struct File { |
|
|
|
|
handle: u32, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub struct OpenOptions { |
|
|
|
|
read: bool, |
|
|
|
|
write: bool, |
|
|
|
|
create: bool, |
|
|
|
|
arch_handle: u64, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Fs { |
|
|
|
|
pub fn init() -> Result<Fs, i32> { |
|
|
|
|
unsafe { |
|
|
|
|
let r = fs::fsInit(); |
|
|
|
|
let r = fsInit(); |
|
|
|
|
if r < 0 { |
|
|
|
|
Err(r) |
|
|
|
|
} else { |
|
|
|
@ -26,8 +78,8 @@ impl Fs {
@@ -26,8 +78,8 @@ impl Fs {
|
|
|
|
|
let mut handle = 0u64; |
|
|
|
|
unsafe { |
|
|
|
|
let id = ArchiveID::Sdmc; |
|
|
|
|
let path = fs::fsMakePath(PathType::Empty.into(), ptr::null() as *const _); |
|
|
|
|
let ret = fs::FSUSER_OpenArchive(&mut handle, id.into(), path); |
|
|
|
|
let path = fsMakePath(PathType::Empty.into(), ptr::null() as *const _); |
|
|
|
|
let ret = FSUSER_OpenArchive(&mut handle, id.into(), path); |
|
|
|
|
if ret < 0 { |
|
|
|
|
Err(ret) |
|
|
|
|
} else { |
|
|
|
@ -40,70 +92,97 @@ impl Fs {
@@ -40,70 +92,97 @@ impl Fs {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Drop for Fs { |
|
|
|
|
fn drop(&mut self) { |
|
|
|
|
unsafe { |
|
|
|
|
fs::fsExit(); |
|
|
|
|
impl Archive { |
|
|
|
|
pub fn file_open(&self, path: &Path) -> Result<File, i32> { |
|
|
|
|
self.file_open_options().read(true).create(true).open(path) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn file_open_options(&self) -> OpenOptions { |
|
|
|
|
OpenOptions { |
|
|
|
|
read: false, |
|
|
|
|
write: false, |
|
|
|
|
create: false, |
|
|
|
|
arch_handle: self.handle, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn id(&self) -> ArchiveID { |
|
|
|
|
self.id |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl OpenOptions { |
|
|
|
|
pub fn read(&mut self, read: bool) -> &mut OpenOptions { |
|
|
|
|
self.read = read; |
|
|
|
|
self |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn write(&mut self, write: bool) -> &mut OpenOptions { |
|
|
|
|
self.write = write; |
|
|
|
|
self |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub struct Archive { |
|
|
|
|
id: ArchiveID, |
|
|
|
|
handle: u64, |
|
|
|
|
} |
|
|
|
|
pub fn create(&mut self, create: bool) -> &mut OpenOptions { |
|
|
|
|
self.create = create; |
|
|
|
|
self |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Archive { |
|
|
|
|
pub fn open_file(&self, p: &Path) -> Result<File, i32> { |
|
|
|
|
pub fn open<P: AsRef<Path>>(&self, path: P) -> Result<File, i32> { |
|
|
|
|
self._open(path.as_ref(), self.get_open_flags()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn _open(&self, path: &Path, flags: u32) -> Result<File, i32> { |
|
|
|
|
unsafe { |
|
|
|
|
let mut handle: u32 = 0; |
|
|
|
|
let wide = p.as_os_str().encode_wide().collect::<Vec<_>>(); |
|
|
|
|
let path = fs::fsMakePath(PathType::UTF16.into(), wide.as_slice().as_ptr() as *mut _); |
|
|
|
|
let ret = fs::FSUSER_OpenFile(&mut handle, self.handle, path, fs::FS_OPEN_READ, 0); |
|
|
|
|
let mut file_handle: u32 = 0; |
|
|
|
|
let wide = path.as_os_str().encode_wide().collect::<Vec<_>>(); |
|
|
|
|
let ctr_path = fsMakePath(PathType::UTF16.into(), wide.as_slice().as_ptr() as *mut _); |
|
|
|
|
let ret = FSUSER_OpenFile(&mut file_handle, self.arch_handle, ctr_path, flags, 0); |
|
|
|
|
if ret < 0 { |
|
|
|
|
Err(ret) |
|
|
|
|
} else { |
|
|
|
|
Ok(File { handle: handle }) |
|
|
|
|
Ok(File { handle: file_handle }) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn id(&self) -> ArchiveID { |
|
|
|
|
self.id |
|
|
|
|
fn get_open_flags(&self) -> u32 { |
|
|
|
|
match (self.read, self.write, self.create) { |
|
|
|
|
(true, false, false) => FS_OPEN_READ, |
|
|
|
|
(false, true, false) => FS_OPEN_WRITE, |
|
|
|
|
(true, false, true) => FS_OPEN_READ | FS_OPEN_CREATE, |
|
|
|
|
(true, true, false) => FS_OPEN_READ | FS_OPEN_WRITE, |
|
|
|
|
(true, true, true) => FS_OPEN_READ | FS_OPEN_WRITE | FS_OPEN_CREATE, |
|
|
|
|
_ => 0, //failure case
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Drop for Archive { |
|
|
|
|
impl Drop for Fs { |
|
|
|
|
fn drop(&mut self) { |
|
|
|
|
unsafe { |
|
|
|
|
fs::FSUSER_CloseArchive(self.handle); |
|
|
|
|
fsExit(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub struct File { |
|
|
|
|
handle: u32, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Drop for File { |
|
|
|
|
impl Drop for Archive { |
|
|
|
|
fn drop(&mut self) { |
|
|
|
|
unsafe { |
|
|
|
|
fs::FSFILE_Close(self.handle); |
|
|
|
|
FSUSER_CloseArchive(self.handle); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug)] |
|
|
|
|
pub enum PathType { |
|
|
|
|
Invalid, |
|
|
|
|
Empty, |
|
|
|
|
Binary, |
|
|
|
|
ASCII, |
|
|
|
|
UTF16, |
|
|
|
|
impl Drop for File { |
|
|
|
|
fn drop(&mut self) { |
|
|
|
|
unsafe { |
|
|
|
|
FSFILE_Close(self.handle); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl From<PathType> for fs::FS_PathType { |
|
|
|
|
impl From<PathType> for FS_PathType { |
|
|
|
|
fn from(p: PathType) -> Self { |
|
|
|
|
use self::PathType::*; |
|
|
|
|
use libctru::services::fs::FS_PathType::*; |
|
|
|
@ -117,8 +196,8 @@ impl From<PathType> for fs::FS_PathType {
@@ -117,8 +196,8 @@ impl From<PathType> for fs::FS_PathType {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl From<fs::FS_PathType> for PathType { |
|
|
|
|
fn from(f: fs::FS_PathType) -> Self { |
|
|
|
|
impl From<FS_PathType> for PathType { |
|
|
|
|
fn from(f: FS_PathType) -> Self { |
|
|
|
|
use self::PathType::*; |
|
|
|
|
use libctru::services::fs::FS_PathType::*; |
|
|
|
|
match f { |
|
|
|
@ -131,33 +210,7 @@ impl From<fs::FS_PathType> for PathType {
@@ -131,33 +210,7 @@ impl From<fs::FS_PathType> for PathType {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug)] |
|
|
|
|
pub enum ArchiveID { |
|
|
|
|
RomFS, |
|
|
|
|
Savedata, |
|
|
|
|
Extdata, |
|
|
|
|
SharedExtdata, |
|
|
|
|
SystemSavedata, |
|
|
|
|
Sdmc, |
|
|
|
|
SdmcWriteOnly, |
|
|
|
|
BossExtdata, |
|
|
|
|
CardSpiFS, |
|
|
|
|
ExtDataAndBossExtdata, |
|
|
|
|
SystemSaveData2, |
|
|
|
|
NandRW, |
|
|
|
|
NandRO, |
|
|
|
|
NandROWriteAccess, |
|
|
|
|
SaveDataAndContent, |
|
|
|
|
SaveDataAndContent2, |
|
|
|
|
NandCtrFS, |
|
|
|
|
TwlPhoto, |
|
|
|
|
NandTwlFS, |
|
|
|
|
GameCardSavedata, |
|
|
|
|
UserSavedata, |
|
|
|
|
DemoSavedata, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl From<ArchiveID> for fs::FS_ArchiveID { |
|
|
|
|
impl From<ArchiveID> for FS_ArchiveID { |
|
|
|
|
fn from(a: ArchiveID) -> Self { |
|
|
|
|
use self::ArchiveID::*; |
|
|
|
|
use libctru::services::fs::FS_ArchiveID::*; |
|
|
|
|