1
1
//! This example shows how to add a directory to a private forest (also HAMT) which encrypts it.
2
2
//! It also shows how to retrieve encrypted nodes from the forest using `PrivateRef`s.
3
3
4
- use chrono:: Utc ;
4
+ use chrono:: { Utc , prelude :: * } ;
5
5
use libipld:: Cid ;
6
6
use rand:: { thread_rng, rngs:: ThreadRng } ;
7
7
use std:: {
8
8
rc:: Rc ,
9
9
fs:: { File , OpenOptions } ,
10
- io:: { Read , Write }
10
+ io:: { Read , Write } ,
11
+ os:: unix:: fs:: MetadataExt
11
12
} ;
12
13
use wnfs:: {
13
14
dagcbor, Hasher , utils,
@@ -266,16 +267,19 @@ impl<'a> PrivateDirectoryHelper<'a> {
266
267
}
267
268
}
268
269
269
- fn get_file_as_byte_vec ( & mut self , filename : & String ) -> Result < Vec < u8 > , String > {
270
+ fn get_file_as_byte_vec ( & mut self , filename : & String ) -> Result < ( Vec < u8 > , i64 ) , String > {
270
271
let f = File :: open ( & filename) ;
271
272
if f. is_ok ( ) {
272
- let metadata = std:: fs:: metadata ( & filename) ;
273
- if metadata. is_ok ( ) {
274
- let mut buffer = vec ! [ 0 ; metadata. ok( ) . unwrap( ) . len( ) as usize ] ;
273
+ let metadata_res = std:: fs:: metadata ( & filename) ;
274
+ if metadata_res. is_ok ( ) {
275
+ let metadata = metadata_res. ok ( ) . unwrap ( ) ;
276
+ let modification_time_seconds = metadata. mtime ( ) ;
277
+
278
+ let mut buffer = vec ! [ 0 ; metadata. len( ) as usize ] ;
275
279
f. ok ( ) . unwrap ( ) . read ( & mut buffer) . expect ( "buffer overflow" ) ;
276
- Ok ( buffer)
280
+ Ok ( ( buffer, modification_time_seconds ) )
277
281
} else {
278
- trace ! ( "wnfsError in get_file_as_byte_vec, unable to read metadata: {:?}" , metadata . err( ) . unwrap( ) ) ;
282
+ trace ! ( "wnfsError in get_file_as_byte_vec, unable to read metadata: {:?}" , metadata_res . err( ) . unwrap( ) ) ;
279
283
Err ( "wnfsError unable to read metadata" . to_string ( ) )
280
284
}
281
285
} else {
@@ -287,10 +291,11 @@ impl<'a> PrivateDirectoryHelper<'a> {
287
291
288
292
pub async fn write_file_from_path ( & mut self , forest : Rc < PrivateForest > , root_dir : Rc < PrivateDirectory > , path_segments : & [ String ] , filename : & String ) -> Result < ( Cid , PrivateRef ) , String > {
289
293
let content: Vec < u8 > ;
294
+ let modification_time_seconds: i64 ;
290
295
let try_content = self . get_file_as_byte_vec ( filename) ;
291
296
if try_content. is_ok ( ) {
292
- content = try_content. ok ( ) . unwrap ( ) ;
293
- let writefile_res = self . write_file ( forest, root_dir, path_segments, content) . await ;
297
+ ( content, modification_time_seconds ) = try_content. ok ( ) . unwrap ( ) ;
298
+ let writefile_res = self . write_file ( forest, root_dir, path_segments, content, modification_time_seconds ) . await ;
294
299
if writefile_res. is_ok ( ) {
295
300
Ok ( writefile_res. ok ( ) . unwrap ( ) )
296
301
} else {
@@ -326,12 +331,17 @@ impl<'a> PrivateDirectoryHelper<'a> {
326
331
327
332
}
328
333
329
- pub async fn write_file ( & mut self , forest : Rc < PrivateForest > , root_dir : Rc < PrivateDirectory > , path_segments : & [ String ] , content : Vec < u8 > ) -> Result < ( Cid , PrivateRef ) , String > {
334
+ pub async fn write_file ( & mut self , forest : Rc < PrivateForest > , root_dir : Rc < PrivateDirectory > , path_segments : & [ String ] , content : Vec < u8 > , modification_time_seconds : i64 ) -> Result < ( Cid , PrivateRef ) , String > {
335
+ let mut modification_time_utc: DateTime < Utc > = Utc :: now ( ) ;
336
+ if modification_time_seconds > 0 {
337
+ let naive_datetime = NaiveDateTime :: from_timestamp_opt ( modification_time_seconds, 0 ) . unwrap ( ) ;
338
+ modification_time_utc = DateTime :: from_utc ( naive_datetime, Utc ) ;
339
+ }
330
340
let write_res = root_dir
331
341
. write (
332
342
path_segments,
333
343
true ,
334
- Utc :: now ( ) ,
344
+ modification_time_utc ,
335
345
content,
336
346
forest,
337
347
& mut self . store ,
@@ -477,6 +487,65 @@ impl<'a> PrivateDirectoryHelper<'a> {
477
487
478
488
}
479
489
490
+ pub async fn mv ( & mut self , forest : Rc < PrivateForest > , root_dir : Rc < PrivateDirectory > , source_path_segments : & [ String ] , target_path_segments : & [ String ] ) -> Result < ( Cid , PrivateRef ) , String > {
491
+ let mv_result = root_dir
492
+ . basic_mv (
493
+ source_path_segments,
494
+ target_path_segments,
495
+ true ,
496
+ Utc :: now ( ) ,
497
+ forest,
498
+ & mut self . store ,
499
+ & mut self . rng ,
500
+ )
501
+ . await ;
502
+ if mv_result. is_ok ( ) {
503
+ let PrivateOpResult {
504
+ root_dir, forest, ..
505
+ } = mv_result. ok ( ) . unwrap ( ) ;
506
+
507
+ let update_res = self . update_forest ( forest) . await ;
508
+ if update_res. is_ok ( ) {
509
+ Ok ( ( update_res. ok ( ) . unwrap ( ) , root_dir. header . get_private_ref ( ) ) )
510
+ } else {
511
+ trace ! ( "wnfsError occured in mv update_res: {:?}" , update_res. as_ref( ) . err( ) . unwrap( ) ) ;
512
+ Err ( update_res. err ( ) . unwrap ( ) . to_string ( ) )
513
+ }
514
+ } else {
515
+ trace ! ( "wnfsError occured in mv mv_result: {:?}" , mv_result. as_ref( ) . err( ) . unwrap( ) ) ;
516
+ Err ( mv_result. err ( ) . unwrap ( ) . to_string ( ) )
517
+ }
518
+ }
519
+
520
+ pub async fn cp ( & mut self , forest : Rc < PrivateForest > , root_dir : Rc < PrivateDirectory > , source_path_segments : & [ String ] , target_path_segments : & [ String ] ) -> Result < ( Cid , PrivateRef ) , String > {
521
+ let cp_result = root_dir
522
+ . cp (
523
+ source_path_segments,
524
+ target_path_segments,
525
+ true ,
526
+ Utc :: now ( ) ,
527
+ forest,
528
+ & mut self . store ,
529
+ & mut self . rng
530
+ )
531
+ . await ;
532
+ if cp_result. is_ok ( ) {
533
+ let PrivateOpResult { forest, root_dir, .. }
534
+ = cp_result. ok ( ) . unwrap ( ) ;
535
+
536
+ let update_res = self . update_forest ( forest) . await ;
537
+ if update_res. is_ok ( ) {
538
+ Ok ( ( update_res. ok ( ) . unwrap ( ) , root_dir. header . get_private_ref ( ) ) )
539
+ } else {
540
+ trace ! ( "wnfsError occured in cp update_res: {:?}" , update_res. as_ref( ) . err( ) . unwrap( ) ) ;
541
+ Err ( update_res. err ( ) . unwrap ( ) . to_string ( ) )
542
+ }
543
+ } else {
544
+ trace ! ( "wnfsError occured in cp cp_result: {:?}" , cp_result. as_ref( ) . err( ) . unwrap( ) ) ;
545
+ Err ( cp_result. err ( ) . unwrap ( ) . to_string ( ) )
546
+ }
547
+ }
548
+
480
549
pub async fn ls_files ( & mut self , forest : Rc < PrivateForest > , root_dir : Rc < PrivateDirectory > , path_segments : & [ String ] ) -> Result < Vec < ( String , Metadata ) > , String > {
481
550
482
551
let res = root_dir
@@ -538,11 +607,11 @@ impl<'a> PrivateDirectoryHelper<'a> {
538
607
return runtime. block_on ( self . write_file_from_path ( forest, root_dir, path_segments, filename) ) ;
539
608
}
540
609
541
- pub fn synced_write_file ( & mut self , forest : Rc < PrivateForest > , root_dir : Rc < PrivateDirectory > , path_segments : & [ String ] , content : Vec < u8 > ) -> Result < ( Cid , PrivateRef ) , String >
610
+ pub fn synced_write_file ( & mut self , forest : Rc < PrivateForest > , root_dir : Rc < PrivateDirectory > , path_segments : & [ String ] , content : Vec < u8 > , modification_time_seconds : i64 ) -> Result < ( Cid , PrivateRef ) , String >
542
611
{
543
612
let runtime =
544
613
tokio:: runtime:: Runtime :: new ( ) . expect ( "Unable to create a runtime" ) ;
545
- return runtime. block_on ( self . write_file ( forest, root_dir, path_segments, content) ) ;
614
+ return runtime. block_on ( self . write_file ( forest, root_dir, path_segments, content, modification_time_seconds ) ) ;
546
615
}
547
616
548
617
pub fn synced_read_file_to_path ( & mut self , forest : Rc < PrivateForest > , root_dir : Rc < PrivateDirectory > , path_segments : & [ String ] , filename : & String ) -> Result < String , String >
@@ -572,6 +641,18 @@ impl<'a> PrivateDirectoryHelper<'a> {
572
641
return runtime. block_on ( self . mkdir ( forest, root_dir, path_segments) ) ;
573
642
}
574
643
644
+ pub fn synced_mv ( & mut self , forest : Rc < PrivateForest > , root_dir : Rc < PrivateDirectory > , source_path_segments : & [ String ] , target_path_segments : & [ String ] ) -> Result < ( Cid , PrivateRef ) , String > {
645
+ let runtime =
646
+ tokio:: runtime:: Runtime :: new ( ) . expect ( "Unable to create a runtime" ) ;
647
+ return runtime. block_on ( self . mv ( forest, root_dir, source_path_segments, target_path_segments) ) ;
648
+ }
649
+
650
+ pub fn synced_cp ( & mut self , forest : Rc < PrivateForest > , root_dir : Rc < PrivateDirectory > , source_path_segments : & [ String ] , target_path_segments : & [ String ] ) -> Result < ( Cid , PrivateRef ) , String > {
651
+ let runtime =
652
+ tokio:: runtime:: Runtime :: new ( ) . expect ( "Unable to create a runtime" ) ;
653
+ return runtime. block_on ( self . cp ( forest, root_dir, source_path_segments, target_path_segments) ) ;
654
+ }
655
+
575
656
pub fn synced_rm ( & mut self , forest : Rc < PrivateForest > , root_dir : Rc < PrivateDirectory > , path_segments : & [ String ] ) -> Result < ( Cid , PrivateRef ) , String >
576
657
{
577
658
let runtime =
@@ -621,7 +702,7 @@ mod private_tests {
621
702
let ( forest_cid, private_ref) = helper. init ( forest, empty_key) . await ;
622
703
let forest = helper. load_forest ( forest_cid) . await . unwrap ( ) ;
623
704
let root_dir = helper. get_root_dir ( forest. to_owned ( ) , private_ref. to_owned ( ) ) . await . unwrap ( ) ;
624
- let ( new_cid, _) = helper. write_file ( forest. to_owned ( ) , root_dir. to_owned ( ) , & [ "root" . into ( ) , "hello" . into ( ) , "world.txt" . into ( ) ] , b"hello, world!" . to_vec ( ) ) . await ;
705
+ let ( new_cid, _) = helper. write_file ( forest. to_owned ( ) , root_dir. to_owned ( ) , & [ "root" . into ( ) , "hello" . into ( ) , "world.txt" . into ( ) ] , b"hello, world!" . to_vec ( ) , 0 ) . await ;
625
706
let forest = helper. load_forest ( new_cid) . await . unwrap ( ) ;
626
707
let ls_result = helper. ls_files ( forest. to_owned ( ) , root_dir. to_owned ( ) , & [ "root" . into ( ) ] ) . await ;
627
708
println ! ( "ls: {:?}" , ls_result) ;
0 commit comments