1
1
use crate :: api:: processor:: Response :: { Error , FetchFileChunk , GetInfo , ListFiles , Reboot } ;
2
2
use crate :: api:: websocket:: { ConnectionState , SessionEvent , WebSocketSession } ;
3
- use anyhow:: anyhow;
3
+ use anyhow:: { anyhow, bail } ;
4
4
use embedded_svc:: ws:: FrameType ;
5
5
use esp_idf_svc:: hal:: gpio:: Pull ;
6
6
use esp_idf_svc:: ping:: Info ;
7
+ use esp_idf_svc:: sys:: { ctime, fstat, stat, strerror, S_IFDIR , S_IFMT } ;
7
8
use serde:: { Deserialize , Serialize } ;
9
+ use std:: ffi:: CString ;
8
10
use std:: fs:: { read_dir, FileType } ;
9
11
use std:: io:: { Read , Seek } ;
10
12
use std:: mem:: MaybeUninit ;
13
+ use std:: os:: fd:: AsFd ;
14
+ use std:: os:: unix:: fs:: MetadataExt ;
11
15
use std:: path:: Path ;
12
16
use std:: time:: SystemTime ;
13
17
use time:: serde:: timestamp:: milliseconds;
@@ -94,7 +98,10 @@ impl Processor {
94
98
95
99
fn list_files ( & self , path : & str ) -> anyhow:: Result < Response > {
96
100
let dir_path = Path :: new ( & self . root_dir ) . join ( path) ;
97
- log:: info!( "Listing files at {}" , dir_path. to_str( ) . unwrap_or( "<Unknown>" ) ) ;
101
+ log:: info!(
102
+ "Listing files at {}" ,
103
+ dir_path. to_str( ) . unwrap_or( "<Unknown>" )
104
+ ) ;
98
105
// Ideally we should find a way to learn the size of all files, but we need to
99
106
// iterate over all files anyway... so.. maybe not? :/
100
107
let mut files: Vec < File > = vec ! [ ] ;
@@ -110,13 +117,25 @@ impl Processor {
110
117
continue ;
111
118
}
112
119
let path = path. unwrap ( ) ;
113
- let metadata = entry. metadata ( ) ?;
120
+
121
+ // Notice: there's entry.metadata(), but somehow the implementation of rust's std
122
+ // is broken and cannot return correct stat. So we call C lib directly to get
123
+ // stat for the file instead.
124
+ let path_c_str = CString :: new ( path. as_bytes ( ) ) ;
125
+ let mut file_stat = stat:: default ( ) ;
126
+ let ret = unsafe { stat ( path_c_str?. as_ptr ( ) , & mut file_stat) } ;
127
+ if ret != 0 {
128
+ bail ! ( "Failed to get file {} stat with error: {}" , path, unsafe {
129
+ CString :: from_raw( strerror( ret) ) . to_str( ) ?
130
+ } ) ;
131
+ }
132
+
114
133
files. push ( File {
115
134
path,
116
- size : metadata . len ( ) ,
117
- modified_at : metadata . modified ( ) ? . into ( ) ,
118
- created_at : metadata . created ( ) ? . into ( ) ,
119
- is_dir : metadata . is_dir ( ) ,
135
+ size : file_stat . st_size as u64 ,
136
+ modified_at : OffsetDateTime :: from_unix_timestamp ( file_stat . st_mtim . tv_sec ) ? ,
137
+ created_at : OffsetDateTime :: from_unix_timestamp ( file_stat . st_ctim . tv_sec ) ? ,
138
+ is_dir : file_stat . st_mode & S_IFMT == S_IFDIR ,
120
139
} )
121
140
}
122
141
Ok ( ListFiles {
0 commit comments