Browse Source

Add metadata struct and functions

pull/10/head
Fenrir 8 years ago
parent
commit
6ab8bd0efd
  1. 55
      src/services/fs.rs

55
src/services/fs.rs

@ -60,6 +60,11 @@ pub struct File {
offset: u64, offset: u64,
} }
pub struct Metadata {
attributes: u32,
size: u64,
}
#[derive(Clone)] #[derive(Clone)]
pub struct OpenOptions { pub struct OpenOptions {
read: bool, read: bool,
@ -74,8 +79,8 @@ pub struct ReadDir {
} }
pub struct DirEntry { pub struct DirEntry {
root: Arc<PathBuf>,
entry: FS_DirectoryEntry, entry: FS_DirectoryEntry,
root: Arc<PathBuf>,
} }
struct Dir(u32); struct Dir(u32);
@ -128,25 +133,27 @@ impl File {
OpenOptions::new().write(true).create(true).archive(arch).open(path.as_ref()) OpenOptions::new().write(true).create(true).archive(arch).open(path.as_ref())
} }
pub fn len(&self) -> Result<u64, i32> { pub fn set_len(&mut self, len: u64) -> Result<(), i32> {
unsafe { unsafe {
let mut len = 0; let r = FSFILE_SetSize(self.handle, len);
let r = FSFILE_GetSize(self.handle, &mut len);
if r < 0 { if r < 0 {
Err(r) Err(r)
} else { } else {
Ok(len) Ok(())
} }
} }
} }
pub fn set_len(&mut self, len: u64) -> Result<(), i32> { // Right now the only file metadata we really have is file size
// This will probably expand later on
pub fn metadata(&self) -> Result<Metadata, i32> {
unsafe { unsafe {
let r = FSFILE_SetSize(self.handle, len); let mut size = 0;
let r = FSFILE_GetSize(self.handle, &mut size);
if r < 0 { if r < 0 {
Err(r) Err(r)
} else { } else {
Ok(()) Ok(Metadata { attributes: 0, size: size })
} }
} }
} }
@ -197,6 +204,20 @@ impl File {
} }
} }
impl Metadata {
pub fn is_dir(&self) -> bool {
self.attributes == self.attributes | FS_ATTRIBUTE_DIRECTORY
}
pub fn is_file(&self) -> bool {
!self.is_dir()
}
pub fn len(&self) -> u64 {
self.size
}
}
impl OpenOptions { impl OpenOptions {
pub fn new() -> OpenOptions { pub fn new() -> OpenOptions {
OpenOptions { OpenOptions {
@ -290,6 +311,12 @@ impl DirEntry {
self.root.join(&self.file_name()) self.root.join(&self.file_name())
} }
// Requiring the user to explicitly pass in the Archive here is pretty ugly,
// But I'm not sure of how else to do it right now.
pub fn metadata(&self, arch: &Archive) -> Result<Metadata, i32> {
metadata(&arch, self.path())
}
pub fn file_name(&self) -> OsString { pub fn file_name(&self) -> OsString {
let filename = truncate_utf16_at_nul(&self.entry.name); let filename = truncate_utf16_at_nul(&self.entry.name);
OsString::from_wide(filename) OsString::from_wide(filename)
@ -309,6 +336,16 @@ pub fn create_dir<P: AsRef<Path>>(arch: &Archive, path: P) -> Result<(), i32> {
} }
} }
pub fn metadata<P: AsRef<Path>>(arch: &Archive, path: P) -> Result<Metadata, i32> {
let maybe_file = File::open(&arch, path.as_ref());
let maybe_dir = read_dir(&arch, path.as_ref());
match (maybe_file, maybe_dir) {
(Ok(file), _) => file.metadata(),
(_, Ok(_dir)) => Ok(Metadata { attributes: FS_ATTRIBUTE_DIRECTORY, size: 0 }),
(Err(r), _) => Err(r),
}
}
pub fn remove_dir<P: AsRef<Path>>(arch: &Archive, path: P) -> Result<(), i32> { pub fn remove_dir<P: AsRef<Path>>(arch: &Archive, path: P) -> Result<(), i32> {
unsafe { unsafe {
let path = to_utf16(path.as_ref()); let path = to_utf16(path.as_ref());
@ -390,7 +427,7 @@ fn readdir(arch: &Archive, p: &Path) -> Result<ReadDir, i32> {
} }
} }
// TODO: Determine if interior NULLs are premitted in 3DS file paths // TODO: Determine if we should check UTF-16 paths for interior NULs
fn to_utf16(path: &Path) -> Vec<u16> { fn to_utf16(path: &Path) -> Vec<u16> {
path.as_os_str().encode_wide().collect::<Vec<_>>() path.as_os_str().encode_wide().collect::<Vec<_>>()
} }

Loading…
Cancel
Save