12
12
// See the License for the specific language governing permissions and
13
13
// limitations under the License.
14
14
15
+ use log:: info;
15
16
use std:: collections:: HashMap ;
16
17
use std:: fmt:: Debug ;
17
18
use std:: fmt:: Formatter ;
@@ -26,10 +27,9 @@ use anyhow::anyhow;
26
27
use async_trait:: async_trait;
27
28
use futures:: io:: copy;
28
29
use futures:: AsyncReadExt ;
29
- use log:: info;
30
30
use suppaftp:: async_native_tls:: TlsConnector ;
31
31
use suppaftp:: list:: File ;
32
- use suppaftp:: types:: FileType ;
32
+ use suppaftp:: types:: { FileType , Response } ;
33
33
use suppaftp:: FtpError ;
34
34
use suppaftp:: FtpStream ;
35
35
use suppaftp:: Status ;
@@ -237,47 +237,52 @@ impl Accessor for Backend {
237
237
}
238
238
239
239
async fn create ( & self , args : & OpCreate ) -> Result < ( ) > {
240
- let path = args. path ( ) ;
241
-
242
240
let mut ftp_stream = self . ftp_connect ( Operation :: Create ) . await ?;
243
241
244
- if args. mode ( ) == ObjectMode :: FILE {
245
- ftp_stream
246
- . put_file ( & path, & mut "" . as_bytes ( ) )
247
- . await
248
- . map_err ( |e| {
249
- other ( ObjectError :: new (
250
- Operation :: Create ,
251
- path,
252
- anyhow ! ( "put request: {e:?}" ) ,
253
- ) )
254
- } ) ?;
255
-
256
- ftp_stream
257
- . quit ( )
258
- . await
259
- . map_err ( |e| new_request_quit_err ( e, Operation :: Create , path) ) ?;
260
-
261
- return Ok ( ( ) ) ;
242
+ let paths: Vec < & str > = args. path ( ) . split_inclusive ( '/' ) . collect ( ) ;
243
+
244
+ let mut curr_path = String :: new ( ) ;
245
+
246
+ for path in paths {
247
+ curr_path. push_str ( path) ;
248
+ // try to create directory
249
+ if curr_path. ends_with ( '/' ) {
250
+ match ftp_stream. mkdir ( & curr_path) . await {
251
+ // Do nothing if status is FileUnavailable or OK(()) is return.
252
+ Err ( FtpError :: UnexpectedResponse ( Response {
253
+ status : Status :: FileUnavailable ,
254
+ ..
255
+ } ) )
256
+ | Ok ( ( ) ) => ( ) ,
257
+ Err ( e) => {
258
+ return Err ( other ( ObjectError :: new (
259
+ Operation :: Create ,
260
+ args. path ( ) ,
261
+ anyhow ! ( "mkdir request: {e:?}" ) ,
262
+ ) ) ) ;
263
+ }
264
+ }
265
+ } else {
266
+ // else, create file
267
+ ftp_stream
268
+ . put_file ( & curr_path, & mut "" . as_bytes ( ) )
269
+ . await
270
+ . map_err ( |e| {
271
+ other ( ObjectError :: new (
272
+ Operation :: Create ,
273
+ path,
274
+ anyhow ! ( "put request: {e:?}" ) ,
275
+ ) )
276
+ } ) ?;
277
+ }
262
278
}
263
279
264
- if args. mode ( ) == ObjectMode :: DIR {
265
- ftp_stream. mkdir ( & path) . await . map_err ( |e| {
266
- other ( ObjectError :: new (
267
- Operation :: Create ,
268
- path,
269
- anyhow ! ( "mkdir request: {e:?}" ) ,
270
- ) )
271
- } ) ?;
272
-
273
- ftp_stream
274
- . quit ( )
275
- . await
276
- . map_err ( |e| new_request_quit_err ( e, Operation :: Create , path) ) ?;
277
- return Ok ( ( ) ) ;
278
- }
280
+ ftp_stream
281
+ . quit ( )
282
+ . await
283
+ . map_err ( |e| new_request_quit_err ( e, Operation :: Create , args. path ( ) ) ) ?;
279
284
280
- unreachable ! ( )
285
+ return Ok ( ( ) ) ;
281
286
}
282
287
283
288
async fn read ( & self , args : & OpRead ) -> Result < BytesReader > {
@@ -319,6 +324,8 @@ impl Accessor for Backend {
319
324
}
320
325
321
326
async fn write ( & self , args : & OpWrite , r : BytesReader ) -> Result < u64 > {
327
+ // TODO: create before write
328
+
322
329
let path = args. path ( ) ;
323
330
324
331
let mut ftp_stream = self . ftp_connect ( Operation :: Write ) . await ?;
0 commit comments