Add set_created and set_accessed public functions in File.
Small code refactoring included.
This commit is contained in:
parent
b38ea78f3e
commit
c4e6d59492
163
src/dir.rs
163
src/dir.rs
@ -107,13 +107,20 @@ pub(crate) struct DirFileEntryData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DirFileEntryData {
|
impl DirFileEntryData {
|
||||||
|
fn new(name: [u8; 11], attrs: FileAttributes) -> Self {
|
||||||
|
DirFileEntryData {
|
||||||
|
name, attrs,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn first_cluster(&self, fat_type: FatType) -> Option<u32> {
|
pub(crate) fn first_cluster(&self, fat_type: FatType) -> Option<u32> {
|
||||||
let first_cluster_hi = if fat_type == FatType::Fat32 { self.first_cluster_hi } else { 0 };
|
let first_cluster_hi = if fat_type == FatType::Fat32 { self.first_cluster_hi } else { 0 };
|
||||||
let n = ((first_cluster_hi as u32) << 16) | self.first_cluster_lo as u32;
|
let n = ((first_cluster_hi as u32) << 16) | self.first_cluster_lo as u32;
|
||||||
if n == 0 { None } else { Some(n) }
|
if n == 0 { None } else { Some(n) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_first_cluster(&mut self, cluster: Option<u32>, fat_type: FatType) {
|
fn set_first_cluster(&mut self, cluster: Option<u32>, fat_type: FatType) {
|
||||||
let n = cluster.unwrap_or(0);
|
let n = cluster.unwrap_or(0);
|
||||||
if fat_type == FatType::Fat32 {
|
if fat_type == FatType::Fat32 {
|
||||||
self.first_cluster_hi = (n >> 16) as u16;
|
self.first_cluster_hi = (n >> 16) as u16;
|
||||||
@ -129,7 +136,7 @@ impl DirFileEntryData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_size(&mut self, size: u32) {
|
fn set_size(&mut self, size: u32) {
|
||||||
self.size = size;
|
self.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,19 +169,19 @@ impl DirFileEntryData {
|
|||||||
self.access_date = date.to_u16();
|
self.access_date = date.to_u16();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_modified(&mut self, date_time: DateTime) {
|
fn set_modified(&mut self, date_time: DateTime) {
|
||||||
self.modify_date = date_time.date.to_u16();
|
self.modify_date = date_time.date.to_u16();
|
||||||
self.modify_time = date_time.time.to_u16();
|
self.modify_time = date_time.time.to_u16();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "chrono")]
|
#[cfg(feature = "chrono")]
|
||||||
pub(crate) fn reset_created(&mut self) {
|
fn reset_created(&mut self) {
|
||||||
let now = DateTime::from(chrono::Local::now());
|
let now = DateTime::from(chrono::Local::now());
|
||||||
self.set_created(now);
|
self.set_created(now);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "chrono")]
|
#[cfg(feature = "chrono")]
|
||||||
pub(crate) fn reset_accessed(&mut self) -> bool {
|
fn reset_accessed(&mut self) -> bool {
|
||||||
let now = Date::from(chrono::Local::now().date());
|
let now = Date::from(chrono::Local::now().date());
|
||||||
if now == self.accessed() {
|
if now == self.accessed() {
|
||||||
false
|
false
|
||||||
@ -185,30 +192,30 @@ impl DirFileEntryData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "chrono")]
|
#[cfg(feature = "chrono")]
|
||||||
pub(crate) fn reset_modified(&mut self) {
|
fn reset_modified(&mut self) {
|
||||||
let now = DateTime::from(chrono::Local::now());
|
let now = DateTime::from(chrono::Local::now());
|
||||||
self.set_modified(now);
|
self.set_modified(now);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "chrono"))]
|
#[cfg(not(feature = "chrono"))]
|
||||||
pub(crate) fn reset_created(&mut self) {
|
fn reset_created(&mut self) {
|
||||||
// nop - user controls timestamps manually
|
// nop - user controls timestamps manually
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "chrono"))]
|
#[cfg(not(feature = "chrono"))]
|
||||||
pub(crate) fn reset_accessed(&mut self) -> bool {
|
fn reset_accessed(&mut self) -> bool {
|
||||||
// nop - user controls timestamps manually
|
// nop - user controls timestamps manually
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "chrono"))]
|
#[cfg(not(feature = "chrono"))]
|
||||||
pub(crate) fn reset_modified(&mut self) {
|
fn reset_modified(&mut self) {
|
||||||
// nop - user controls timestamps manually
|
// nop - user controls timestamps manually
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn serialize(&self, wrt: &mut Write) -> io::Result<()> {
|
fn serialize(&self, wrt: &mut Write) -> io::Result<()> {
|
||||||
wrt.write_all(&self.name)?;
|
wrt.write_all(&self.name)?;
|
||||||
wrt.write_u8(self.attrs.bits())?;
|
wrt.write_u8(self.attrs.bits())?;
|
||||||
wrt.write_u8(self.reserved_0)?;
|
wrt.write_u8(self.reserved_0)?;
|
||||||
@ -228,6 +235,10 @@ impl DirFileEntryData {
|
|||||||
self.name[0] == DIR_ENTRY_FREE_FLAG
|
self.name[0] == DIR_ENTRY_FREE_FLAG
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_free(&mut self) {
|
||||||
|
self.name[0] = DIR_ENTRY_FREE_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
fn is_end(&self) -> bool {
|
fn is_end(&self) -> bool {
|
||||||
self.name[0] == 0
|
self.name[0] == 0
|
||||||
}
|
}
|
||||||
@ -247,6 +258,20 @@ struct DirLfnEntryData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DirLfnEntryData {
|
impl DirLfnEntryData {
|
||||||
|
fn new(order: u8, checksum: u8) -> Self {
|
||||||
|
DirLfnEntryData {
|
||||||
|
order, checksum,
|
||||||
|
attrs: FileAttributes::LFN,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn copy_name_from_slice(&mut self, lfn_part: &[u16; LFN_PART_LEN]) {
|
||||||
|
self.name_0.copy_from_slice(&lfn_part[0..5]);
|
||||||
|
self.name_1.copy_from_slice(&lfn_part[5..5+6]);
|
||||||
|
self.name_2.copy_from_slice(&lfn_part[11..11+2]);
|
||||||
|
}
|
||||||
|
|
||||||
fn serialize(&self, wrt: &mut Write) -> io::Result<()> {
|
fn serialize(&self, wrt: &mut Write) -> io::Result<()> {
|
||||||
wrt.write_u8(self.order)?;
|
wrt.write_u8(self.order)?;
|
||||||
for ch in self.name_0.iter() {
|
for ch in self.name_0.iter() {
|
||||||
@ -269,6 +294,10 @@ impl DirLfnEntryData {
|
|||||||
self.order == DIR_ENTRY_FREE_FLAG
|
self.order == DIR_ENTRY_FREE_FLAG
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_free(&mut self) {
|
||||||
|
self.order = DIR_ENTRY_FREE_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
fn is_end(&self) -> bool {
|
fn is_end(&self) -> bool {
|
||||||
self.order == 0
|
self.order == 0
|
||||||
}
|
}
|
||||||
@ -339,6 +368,13 @@ impl DirEntryData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_free(&mut self) {
|
||||||
|
match self {
|
||||||
|
&mut DirEntryData::File(ref mut file) => file.set_free(),
|
||||||
|
&mut DirEntryData::Lfn(ref mut lfn) => lfn.set_free(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn is_end(&self) -> bool {
|
fn is_end(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
&DirEntryData::File(ref file) => file.is_end(),
|
&DirEntryData::File(ref file) => file.is_end(),
|
||||||
@ -443,13 +479,80 @@ impl From<chrono::DateTime<Local>> for DateTime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct FileEntryInfo {
|
pub(crate) struct DirEntryEditor {
|
||||||
pub(crate) data: DirFileEntryData,
|
data: DirFileEntryData,
|
||||||
pos: u64,
|
pos: u64,
|
||||||
|
dirty: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileEntryInfo {
|
impl DirEntryEditor {
|
||||||
pub(crate) fn write(&self, fs: FileSystemRef) -> io::Result<()> {
|
fn new(data: DirFileEntryData, pos: u64) -> DirEntryEditor {
|
||||||
|
DirEntryEditor {
|
||||||
|
data, pos,
|
||||||
|
dirty: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn inner(&self) -> &DirFileEntryData {
|
||||||
|
&self.data
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_first_cluster(&mut self, first_cluster: Option<u32>, fat_type: FatType) {
|
||||||
|
if first_cluster != self.data.first_cluster(fat_type) {
|
||||||
|
self.data.set_first_cluster(first_cluster, fat_type);
|
||||||
|
self.dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_size(&mut self, size: u32) {
|
||||||
|
match self.data.size() {
|
||||||
|
Some(n) if size != n => {
|
||||||
|
self.data.set_size(size);
|
||||||
|
self.dirty = true;
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_created(&mut self, date_time: DateTime) {
|
||||||
|
if date_time != self.data.created() {
|
||||||
|
self.data.set_created(date_time);
|
||||||
|
self.dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_accessed(&mut self, date: Date) {
|
||||||
|
if date != self.data.accessed() {
|
||||||
|
self.data.set_accessed(date);
|
||||||
|
self.dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_modified(&mut self, date_time: DateTime) {
|
||||||
|
if date_time != self.data.modified() {
|
||||||
|
self.data.set_modified(date_time);
|
||||||
|
self.dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn reset_accessed(&mut self) {
|
||||||
|
self.dirty |= self.data.reset_accessed();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn reset_modified(&mut self) {
|
||||||
|
self.data.reset_modified();
|
||||||
|
self.dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn flush(&mut self, fs: FileSystemRef) -> io::Result<()> {
|
||||||
|
if self.dirty {
|
||||||
|
self.write(fs)?;
|
||||||
|
self.dirty = false;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, fs: FileSystemRef) -> io::Result<()> {
|
||||||
let mut disk = fs.disk.borrow_mut();
|
let mut disk = fs.disk.borrow_mut();
|
||||||
disk.seek(io::SeekFrom::Start(self.pos))?;
|
disk.seek(io::SeekFrom::Start(self.pos))?;
|
||||||
self.data.serialize(&mut *disk)
|
self.data.serialize(&mut *disk)
|
||||||
@ -510,11 +613,8 @@ impl <'a, 'b> DirEntry<'a, 'b> {
|
|||||||
self.data.first_cluster(self.fs.fat_type)
|
self.data.first_cluster(self.fs.fat_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn entry_info(&self) -> FileEntryInfo {
|
fn entry_info(&self) -> DirEntryEditor {
|
||||||
FileEntryInfo {
|
DirEntryEditor::new(self.data.clone(), self.entry_pos)
|
||||||
data: self.data.clone(),
|
|
||||||
pos: self.entry_pos,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns File struct for this entry.
|
/// Returns File struct for this entry.
|
||||||
@ -700,11 +800,7 @@ impl <'a, 'b> Dir<'a, 'b> {
|
|||||||
for _ in 0..num {
|
for _ in 0..num {
|
||||||
let mut data = DirEntryData::deserialize(&mut stream)?;
|
let mut data = DirEntryData::deserialize(&mut stream)?;
|
||||||
trace!("removing dir entry {:?}", data);
|
trace!("removing dir entry {:?}", data);
|
||||||
match data {
|
data.set_free();
|
||||||
DirEntryData::File(ref mut data) =>
|
|
||||||
data.name[0] = DIR_ENTRY_FREE_FLAG,
|
|
||||||
DirEntryData::Lfn(ref mut data) => data.order = DIR_ENTRY_FREE_FLAG,
|
|
||||||
};
|
|
||||||
stream.seek(SeekFrom::Current(-(DIR_ENTRY_SIZE as i64)))?;
|
stream.seek(SeekFrom::Current(-(DIR_ENTRY_SIZE as i64)))?;
|
||||||
data.serialize(&mut stream)?;
|
data.serialize(&mut stream)?;
|
||||||
}
|
}
|
||||||
@ -821,24 +917,15 @@ impl <'a, 'b> Dir<'a, 'b> {
|
|||||||
if lfn_part_len < LFN_PART_LEN {
|
if lfn_part_len < LFN_PART_LEN {
|
||||||
lfn_part[lfn_part_len] = 0;
|
lfn_part[lfn_part_len] = 0;
|
||||||
}
|
}
|
||||||
let mut lfn_entry = DirLfnEntryData {
|
let mut lfn_entry = DirLfnEntryData::new(order, lfn_chsum);
|
||||||
order,
|
lfn_entry.copy_name_from_slice(&lfn_part);
|
||||||
attrs: FileAttributes::LFN,
|
|
||||||
checksum: lfn_chsum,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
lfn_entry.name_0.copy_from_slice(&lfn_part[0..5]);
|
|
||||||
lfn_entry.name_1.copy_from_slice(&lfn_part[5..5+6]);
|
|
||||||
lfn_entry.name_2.copy_from_slice(&lfn_part[11..11+2]);
|
|
||||||
lfn_entry.serialize(&mut stream)?;
|
lfn_entry.serialize(&mut stream)?;
|
||||||
}
|
}
|
||||||
let mut raw_entry = DirFileEntryData {
|
let mut raw_entry = DirFileEntryData::new(short_name, attrs);
|
||||||
name: short_name,
|
|
||||||
attrs,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
raw_entry.set_first_cluster(first_cluster, self.fs.fat_type);
|
raw_entry.set_first_cluster(first_cluster, self.fs.fat_type);
|
||||||
raw_entry.reset_created();
|
raw_entry.reset_created();
|
||||||
|
raw_entry.reset_accessed();
|
||||||
|
raw_entry.reset_modified();
|
||||||
raw_entry.serialize(&mut stream)?;
|
raw_entry.serialize(&mut stream)?;
|
||||||
let end_pos = stream.seek(io::SeekFrom::Current(0))?;
|
let end_pos = stream.seek(io::SeekFrom::Current(0))?;
|
||||||
let abs_pos = stream.abs_pos().map(|p| p - DIR_ENTRY_SIZE);
|
let abs_pos = stream.abs_pos().map(|p| p - DIR_ENTRY_SIZE);
|
||||||
|
79
src/file.rs
79
src/file.rs
@ -4,7 +4,7 @@ use std::io::{SeekFrom, ErrorKind};
|
|||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use fs::FileSystemRef;
|
use fs::FileSystemRef;
|
||||||
use dir::{FileEntryInfo, DateTime};
|
use dir::{DirEntryEditor, DateTime, Date};
|
||||||
|
|
||||||
/// FAT file used for reading and writing.
|
/// FAT file used for reading and writing.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -16,19 +16,17 @@ pub struct File<'a, 'b: 'a> {
|
|||||||
// current position in this file
|
// current position in this file
|
||||||
offset: u32,
|
offset: u32,
|
||||||
// file dir entry - None for root dir
|
// file dir entry - None for root dir
|
||||||
entry: Option<FileEntryInfo>,
|
entry: Option<DirEntryEditor>,
|
||||||
// should file dir entry be flushed?
|
// file-system reference
|
||||||
entry_dirty: bool,
|
|
||||||
fs: FileSystemRef<'a, 'b>,
|
fs: FileSystemRef<'a, 'b>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a, 'b> File<'a, 'b> {
|
impl <'a, 'b> File<'a, 'b> {
|
||||||
pub(crate) fn new(first_cluster: Option<u32>, entry: Option<FileEntryInfo>, fs: FileSystemRef<'a, 'b>) -> Self {
|
pub(crate) fn new(first_cluster: Option<u32>, entry: Option<DirEntryEditor>, fs: FileSystemRef<'a, 'b>) -> Self {
|
||||||
File {
|
File {
|
||||||
first_cluster, entry, fs,
|
first_cluster, entry, fs,
|
||||||
current_cluster: None, // cluster before first one
|
current_cluster: None, // cluster before first one
|
||||||
offset: 0,
|
offset: 0,
|
||||||
entry_dirty: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,11 +34,10 @@ impl <'a, 'b> File<'a, 'b> {
|
|||||||
let offset = self.offset;
|
let offset = self.offset;
|
||||||
match self.entry {
|
match self.entry {
|
||||||
Some(ref mut e) => {
|
Some(ref mut e) => {
|
||||||
e.data.reset_modified();
|
e.reset_modified();
|
||||||
if e.data.size().map_or(false, |s| offset > s) {
|
if e.inner().size().map_or(false, |s| offset > s) {
|
||||||
e.data.set_size(offset);
|
e.set_size(offset);
|
||||||
}
|
}
|
||||||
self.entry_dirty = true;
|
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
@ -48,18 +45,12 @@ impl <'a, 'b> File<'a, 'b> {
|
|||||||
|
|
||||||
/// Truncate file to current position.
|
/// Truncate file to current position.
|
||||||
pub fn truncate(&mut self) -> io::Result<()> {
|
pub fn truncate(&mut self) -> io::Result<()> {
|
||||||
let offset = self.offset;
|
|
||||||
match self.entry {
|
match self.entry {
|
||||||
Some(ref mut e) => {
|
Some(ref mut e) => {
|
||||||
if e.data.size().map_or(false, |s| offset == s) {
|
e.set_size(self.offset);
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
e.data.set_size(self.offset);
|
|
||||||
if self.offset == 0 {
|
if self.offset == 0 {
|
||||||
e.data.set_first_cluster(None, self.fs.fat_type);
|
e.set_first_cluster(None, self.fs.fat_type);
|
||||||
}
|
}
|
||||||
self.entry_dirty = true;
|
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
@ -91,32 +82,47 @@ impl <'a, 'b> File<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn flush_dir_entry(&self) -> io::Result<()> {
|
pub(crate) fn flush_dir_entry(&mut self) -> io::Result<()> {
|
||||||
if self.entry_dirty {
|
match self.entry {
|
||||||
match self.entry {
|
Some(ref mut e) => e.flush(self.fs)?,
|
||||||
Some(ref e) => e.write(self.fs)?,
|
_ => {},
|
||||||
_ => {},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set date and time of creation for this file.
|
||||||
|
///
|
||||||
|
/// Note: if chrono feature is enabled (default) library automatically updates all timestamps
|
||||||
|
pub fn set_created(&mut self, date_time: DateTime) {
|
||||||
|
match self.entry {
|
||||||
|
Some(ref mut e) => e.set_created(date_time),
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set date of last access for this file.
|
||||||
|
///
|
||||||
|
/// Note: if chrono feature is enabled (default) library automatically updates all timestamps
|
||||||
|
pub fn set_accessed(&mut self, date: Date) {
|
||||||
|
match self.entry {
|
||||||
|
Some(ref mut e) => e.set_accessed(date),
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set date and time of last modification for this file.
|
/// Set date and time of last modification for this file.
|
||||||
///
|
///
|
||||||
/// Note: if chrono feature is enabled (default) library automatically updates all timestamps
|
/// Note: if chrono feature is enabled (default) library automatically updates all timestamps
|
||||||
pub fn set_modified(&mut self, date_time: DateTime) {
|
pub fn set_modified(&mut self, date_time: DateTime) {
|
||||||
match self.entry {
|
match self.entry {
|
||||||
Some(ref mut e) => {
|
Some(ref mut e) => e.set_modified(date_time),
|
||||||
e.data.set_modified(date_time);
|
|
||||||
self.entry_dirty = true;
|
|
||||||
},
|
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bytes_left_in_file(&self) -> Option<usize> {
|
fn bytes_left_in_file(&self) -> Option<usize> {
|
||||||
match self.entry {
|
match self.entry {
|
||||||
Some(ref e) => e.data.size().map(|s| (s - self.offset) as usize),
|
Some(ref e) => e.inner().size().map(|s| (s - self.offset) as usize),
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,12 +130,9 @@ impl <'a, 'b> File<'a, 'b> {
|
|||||||
fn set_first_cluster(&mut self, cluster: u32) {
|
fn set_first_cluster(&mut self, cluster: u32) {
|
||||||
self.first_cluster = Some(cluster);
|
self.first_cluster = Some(cluster);
|
||||||
match self.entry {
|
match self.entry {
|
||||||
Some(ref mut e) => {
|
Some(ref mut e) => e.set_first_cluster(self.first_cluster, self.fs.fat_type),
|
||||||
e.data.set_first_cluster(self.first_cluster, self.fs.fat_type);
|
|
||||||
},
|
|
||||||
None => {},
|
None => {},
|
||||||
}
|
}
|
||||||
self.entry_dirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn first_cluster(&self) -> Option<u32> {
|
pub(crate) fn first_cluster(&self) -> Option<u32> {
|
||||||
@ -190,7 +193,7 @@ impl<'a, 'b> Read for File<'a, 'b> {
|
|||||||
self.current_cluster = Some(current_cluster);
|
self.current_cluster = Some(current_cluster);
|
||||||
|
|
||||||
match self.entry {
|
match self.entry {
|
||||||
Some(ref mut e) if !self.fs.read_only => self.entry_dirty |= e.data.reset_accessed(),
|
Some(ref mut e) if !self.fs.read_only => e.reset_accessed(),
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
Ok(read_bytes)
|
Ok(read_bytes)
|
||||||
@ -230,7 +233,7 @@ impl<'a, 'b> Write for File<'a, 'b> {
|
|||||||
if self.first_cluster.is_none() {
|
if self.first_cluster.is_none() {
|
||||||
self.set_first_cluster(new_cluster);
|
self.set_first_cluster(new_cluster);
|
||||||
}
|
}
|
||||||
if self.entry.clone().map_or(true, |e| e.data.size().is_none()) {
|
if self.entry.clone().map_or(true, |e| e.inner().size().is_none()) {
|
||||||
// zero new directory cluster
|
// zero new directory cluster
|
||||||
trace!("zeroing directory cluser {}", new_cluster);
|
trace!("zeroing directory cluser {}", new_cluster);
|
||||||
let abs_pos = self.fs.offset_from_cluster(new_cluster);
|
let abs_pos = self.fs.offset_from_cluster(new_cluster);
|
||||||
@ -279,16 +282,16 @@ impl<'a, 'b> Seek for File<'a, 'b> {
|
|||||||
let mut new_pos = match pos {
|
let mut new_pos = match pos {
|
||||||
SeekFrom::Current(x) => self.offset as i64 + x,
|
SeekFrom::Current(x) => self.offset as i64 + x,
|
||||||
SeekFrom::Start(x) => x as i64,
|
SeekFrom::Start(x) => x as i64,
|
||||||
SeekFrom::End(x) => self.entry.iter().next().map_or(None, |e| e.data.size()).expect("cannot seek from end if size is unknown") as i64 + x,
|
SeekFrom::End(x) => self.entry.iter().next().map_or(None, |e| e.inner().size()).expect("cannot seek from end if size is unknown") as i64 + x,
|
||||||
};
|
};
|
||||||
if new_pos < 0 {
|
if new_pos < 0 {
|
||||||
return Err(io::Error::new(ErrorKind::InvalidInput, "invalid seek"));
|
return Err(io::Error::new(ErrorKind::InvalidInput, "invalid seek"));
|
||||||
}
|
}
|
||||||
new_pos = match self.entry {
|
new_pos = match self.entry {
|
||||||
Some(ref e) => {
|
Some(ref e) => {
|
||||||
if e.data.size().map_or(false, |s| new_pos > s as i64) {
|
if e.inner().size().map_or(false, |s| new_pos > s as i64) {
|
||||||
info!("seek beyond end of file");
|
info!("seek beyond end of file");
|
||||||
e.data.size().unwrap() as i64 // safe
|
e.inner().size().unwrap() as i64 // safe
|
||||||
} else {
|
} else {
|
||||||
new_pos
|
new_pos
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user