@@ -69,11 +69,13 @@ impl<ObjectID: FsVerityHashValue> Drop for Repository<ObjectID> {
69
69
}
70
70
71
71
impl < ObjectID : FsVerityHashValue > Repository < ObjectID > {
72
+ /// Return the objects directory.
72
73
pub fn objects_dir ( & self ) -> ErrnoResult < & OwnedFd > {
73
74
self . objects
74
75
. get_or_try_init ( || ensure_dir_and_openat ( & self . repository , "objects" , OFlags :: PATH ) )
75
76
}
76
77
78
+ /// Open a repository at the target directory and path.
77
79
pub fn open_path ( dirfd : impl AsFd , path : impl AsRef < Path > ) -> Result < Self > {
78
80
let path = path. as_ref ( ) ;
79
81
@@ -92,12 +94,14 @@ impl<ObjectID: FsVerityHashValue> Repository<ObjectID> {
92
94
} )
93
95
}
94
96
97
+ /// Open the default user-owned composefs repository.
95
98
pub fn open_user ( ) -> Result < Self > {
96
99
let home = std:: env:: var ( "HOME" ) . with_context ( || "$HOME must be set when in user mode" ) ?;
97
100
98
101
Self :: open_path ( CWD , PathBuf :: from ( home) . join ( ".var/lib/composefs" ) )
99
102
}
100
103
104
+ /// Open the default system-global composefs repository.
101
105
pub fn open_system ( ) -> Result < Self > {
102
106
Self :: open_path ( CWD , PathBuf :: from ( "/sysroot/composefs" . to_string ( ) ) )
103
107
}
@@ -114,6 +118,7 @@ impl<ObjectID: FsVerityHashValue> Repository<ObjectID> {
114
118
tokio:: task:: spawn_blocking ( move || self_. ensure_object ( & data) ) . await ?
115
119
}
116
120
121
+ /// Given a blob of data, store it in the repository.
117
122
pub fn ensure_object ( & self , data : & [ u8 ] ) -> Result < ObjectID > {
118
123
let dirfd = self . objects_dir ( ) ?;
119
124
let id: ObjectID = compute_verity ( data) ;
@@ -216,6 +221,10 @@ impl<ObjectID: FsVerityHashValue> Repository<ObjectID> {
216
221
Ok ( fd)
217
222
}
218
223
224
+ /// By default fsverity is required to be enabled on the target
225
+ /// filesystem. Setting this disables verification of digests
226
+ /// and an instance of [`Self`] can be used on a filesystem
227
+ /// without fsverity support.
219
228
pub fn set_insecure ( & mut self , insecure : bool ) -> & mut Self {
220
229
self . insecure = insecure;
221
230
self
@@ -236,6 +245,8 @@ impl<ObjectID: FsVerityHashValue> Repository<ObjectID> {
236
245
format ! ( "objects/{}" , id. to_object_pathname( ) )
237
246
}
238
247
248
+ /// Check if the provided splitstream is present in the repository;
249
+ /// if so, return its fsverity digest.
239
250
pub fn has_stream ( & self , sha256 : & Sha256Digest ) -> Result < Option < ObjectID > > {
240
251
let stream_path = format ! ( "streams/{}" , hex:: encode( sha256) ) ;
241
252
@@ -260,7 +271,7 @@ impl<ObjectID: FsVerityHashValue> Repository<ObjectID> {
260
271
}
261
272
}
262
273
263
- /// Basically the same as has_stream() except that it performs expensive verification
274
+ /// Similar to [`Self:: has_stream`] but performs more expensive verification.
264
275
pub fn check_stream ( & self , sha256 : & Sha256Digest ) -> Result < Option < ObjectID > > {
265
276
let stream_path = format ! ( "streams/{}" , hex:: encode( sha256) ) ;
266
277
match self . openat ( & stream_path, OFlags :: RDONLY ) {
@@ -301,6 +312,8 @@ impl<ObjectID: FsVerityHashValue> Repository<ObjectID> {
301
312
}
302
313
}
303
314
315
+ /// Write the given splitstream to the repository with the
316
+ /// provided name.
304
317
pub fn write_stream (
305
318
& self ,
306
319
writer : SplitStreamWriter < ObjectID > ,
@@ -374,6 +387,7 @@ impl<ObjectID: FsVerityHashValue> Repository<ObjectID> {
374
387
Ok ( object_id)
375
388
}
376
389
390
+ /// Open a splitstream with the given name.
377
391
pub fn open_stream (
378
392
& self ,
379
393
name : & str ,
@@ -392,6 +406,8 @@ impl<ObjectID: FsVerityHashValue> Repository<ObjectID> {
392
406
SplitStreamReader :: new ( file)
393
407
}
394
408
409
+ /// Given an object identifier (a digest), return a read-only file descriptor
410
+ /// for its contents. The fsverity digest is verified (if the repository is not in `insecure` mode).
395
411
pub fn open_object ( & self , id : & ObjectID ) -> Result < OwnedFd > {
396
412
self . open_with_verity ( & Self :: format_object_path ( id) , id)
397
413
}
@@ -412,7 +428,13 @@ impl<ObjectID: FsVerityHashValue> Repository<ObjectID> {
412
428
Ok ( ( ) )
413
429
}
414
430
415
- /// this function is not safe for untrusted users
431
+ /// Write `data into the repository as an image with the given `name`.
432
+ ///
433
+ /// The fsverity digest is returned.
434
+ ///
435
+ /// # Integrity
436
+ ///
437
+ /// This function is not safe for untrusted users.
416
438
pub fn write_image ( & self , name : Option < & str > , data : & [ u8 ] ) -> Result < ObjectID > {
417
439
let object_id = self . ensure_object ( data) ?;
418
440
@@ -429,7 +451,13 @@ impl<ObjectID: FsVerityHashValue> Repository<ObjectID> {
429
451
Ok ( object_id)
430
452
}
431
453
432
- /// this function is not safe for untrusted users
454
+ /// Import the data from the provided read into the repository as an image.
455
+ ///
456
+ /// The fsverity digest is returned.
457
+ ///
458
+ /// # Integrity
459
+ ///
460
+ /// This function is not safe for untrusted users.
433
461
pub fn import_image < R : Read > ( & self , name : & str , image : & mut R ) -> Result < ObjectID > {
434
462
let mut data = vec ! [ ] ;
435
463
image. read_to_end ( & mut data) ?;
@@ -460,6 +488,8 @@ impl<ObjectID: FsVerityHashValue> Repository<ObjectID> {
460
488
}
461
489
}
462
490
491
+ /// Create a detached mount of an image. This file descriptor can then
492
+ /// be attached via e.g. `move_mount`.
463
493
pub fn mount ( & self , name : & str ) -> Result < OwnedFd > {
464
494
let ( image, enable_verity) = self . open_image ( name) ?;
465
495
Ok ( composefs_fsmount (
@@ -470,6 +500,7 @@ impl<ObjectID: FsVerityHashValue> Repository<ObjectID> {
470
500
) ?)
471
501
}
472
502
503
+ /// Mount the image with the provided digest at the target path.
473
504
pub fn mount_at ( & self , name : & str , mountpoint : impl AsRef < Path > ) -> Result < ( ) > {
474
505
Ok ( mount_at (
475
506
self . mount ( name) ?,
@@ -540,6 +571,7 @@ impl<ObjectID: FsVerityHashValue> Repository<ObjectID> {
540
571
Ok ( ( ) )
541
572
}
542
573
574
+ /// Open the provided path in the repository.
543
575
fn openat ( & self , name : & str , flags : OFlags ) -> ErrnoResult < OwnedFd > {
544
576
// Unconditionally add CLOEXEC as we always want it.
545
577
openat (
@@ -599,13 +631,19 @@ impl<ObjectID: FsVerityHashValue> Repository<ObjectID> {
599
631
Ok ( objects)
600
632
}
601
633
634
+ /// Given an image, return the set of all objects referenced by it.
602
635
pub fn objects_for_image ( & self , name : & str ) -> Result < HashSet < ObjectID > > {
603
636
let ( image, _) = self . open_image ( name) ?;
604
637
let mut data = vec ! [ ] ;
605
638
std:: fs:: File :: from ( image) . read_to_end ( & mut data) ?;
606
639
Ok ( crate :: erofs:: reader:: collect_objects ( & data) ?)
607
640
}
608
641
642
+ /// Perform a garbage collection operation.
643
+ ///
644
+ /// # Locking
645
+ ///
646
+ /// An exclusive lock is held for the duration of this operation.
609
647
pub fn gc ( & self ) -> Result < ( ) > {
610
648
flock ( & self . repository , FlockOperation :: LockExclusive ) ?;
611
649
0 commit comments