diff --git a/src/services/fs.rs b/src/services/fs.rs index 93db631..d868e71 100644 --- a/src/services/fs.rs +++ b/src/services/fs.rs @@ -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, } +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 { unsafe { - let r = fs::fsInit(); + let r = fsInit(); if r < 0 { Err(r) } else { @@ -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 { } } -impl Drop for Fs { - fn drop(&mut self) { - unsafe { - fs::fsExit(); +impl Archive { + pub fn file_open(&self, path: &Path) -> Result { + 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 { + pub fn open>(&self, path: P) -> Result { + self._open(path.as_ref(), self.get_open_flags()) + } + + fn _open(&self, path: &Path, flags: u32) -> Result { unsafe { - let mut handle: u32 = 0; - let wide = p.as_os_str().encode_wide().collect::>(); - 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::>(); + 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 for fs::FS_PathType { +impl From for FS_PathType { fn from(p: PathType) -> Self { use self::PathType::*; use libctru::services::fs::FS_PathType::*; @@ -117,8 +196,8 @@ impl From for fs::FS_PathType { } } -impl From for PathType { - fn from(f: fs::FS_PathType) -> Self { +impl From 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 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 for fs::FS_ArchiveID { +impl From for FS_ArchiveID { fn from(a: ArchiveID) -> Self { use self::ArchiveID::*; use libctru::services::fs::FS_ArchiveID::*;