1
1
use std:: {
2
+ collections:: HashSet ,
2
3
fmt:: { Display , Formatter } ,
3
4
fs:: { self , create_dir_all, read_dir} ,
4
5
io:: { self , Write } ,
@@ -26,6 +27,7 @@ use grub::RunGrubError;
26
27
use locale:: SetHwclockError ;
27
28
use mount:: { mount_root_path, UmountError } ;
28
29
use num_enum:: IntoPrimitive ;
30
+ use quirk:: get_matches_quirk;
29
31
use rustix:: {
30
32
fs:: sync,
31
33
io:: Errno ,
@@ -350,7 +352,7 @@ macro_rules! cancel_install_exit {
350
352
} ;
351
353
}
352
354
353
- #[ derive( Clone , IntoPrimitive ) ]
355
+ #[ derive( Clone , IntoPrimitive , PartialEq , Eq ) ]
354
356
#[ repr( u8 ) ]
355
357
enum InstallationStage {
356
358
SetupPartition = 1 ,
@@ -368,6 +370,7 @@ enum InstallationStage {
368
370
UmountInnerPath ,
369
371
UmountEFIPath ,
370
372
UmountRootPath ,
373
+ Quirk ,
371
374
Done ,
372
375
}
373
376
@@ -395,6 +398,7 @@ impl Display for InstallationStage {
395
398
Self :: UmountInnerPath => "umount inner path" ,
396
399
Self :: UmountEFIPath => "umount EFI path" ,
397
400
Self :: UmountRootPath => "umount root path" ,
401
+ Self :: Quirk => "run quirk" ,
398
402
Self :: Done => "done" ,
399
403
} ;
400
404
@@ -419,7 +423,8 @@ impl InstallationStage {
419
423
Self :: CopyLog => Self :: UmountInnerPath ,
420
424
Self :: UmountInnerPath => Self :: UmountEFIPath ,
421
425
Self :: UmountEFIPath => Self :: UmountRootPath ,
422
- Self :: UmountRootPath => Self :: Done ,
426
+ Self :: UmountRootPath => Self :: Quirk ,
427
+ Self :: Quirk => Self :: Done ,
423
428
Self :: Done => Self :: Done ,
424
429
}
425
430
}
@@ -436,6 +441,37 @@ impl InstallConfig {
436
441
) -> Result < bool , InstallErr > {
437
442
debug ! ( "Install config: {:#?}" , self ) ;
438
443
444
+ let quirks = get_matches_quirk ( "/usr/share/deploykit-backend/quirks" ) ;
445
+
446
+ let mut no_run = HashSet :: new ( ) ;
447
+ let mut quirk_commands = vec ! [ ] ;
448
+
449
+ for quirk in quirks {
450
+ if let Some ( skip_stages) = quirk. skip_stages {
451
+ no_run. extend ( skip_stages) ;
452
+ }
453
+ quirk_commands. push ( quirk. command ) ;
454
+ }
455
+
456
+ let no_run = no_run
457
+ . iter ( )
458
+ . flat_map ( |x| match x. as_str ( ) {
459
+ "SetupPartition" => Some ( InstallationStage :: SetupPartition ) ,
460
+ "DownloadSquashfs" => Some ( InstallationStage :: DownloadSquashfs ) ,
461
+ "ExtractSquashfs" => Some ( InstallationStage :: ExtractSquashfs ) ,
462
+ "GenerateFstab" => Some ( InstallationStage :: GenerateFstab ) ,
463
+ "Dracut" => Some ( InstallationStage :: Dracut ) ,
464
+ "InstallGrub" => Some ( InstallationStage :: InstallGrub ) ,
465
+ "GenerateSshKey" => Some ( InstallationStage :: GenerateSshKey ) ,
466
+ "ConfigureSystem" => Some ( InstallationStage :: ConfigureSystem ) ,
467
+ "SwapOff" => Some ( InstallationStage :: SwapOff ) ,
468
+ x => {
469
+ error ! ( "Unsupport skip step: {x}" ) ;
470
+ None
471
+ }
472
+ } )
473
+ . collect :: < Vec < _ > > ( ) ;
474
+
439
475
let root_fd = get_dir_fd ( Path :: new ( "/" ) ) . context ( GetDirFdSnafu ) ?;
440
476
441
477
let mut stage = InstallationStage :: default ( ) ;
@@ -464,11 +500,17 @@ impl InstallConfig {
464
500
InstallationStage :: UmountInnerPath => 8 ,
465
501
InstallationStage :: UmountEFIPath => 8 ,
466
502
InstallationStage :: UmountRootPath => 8 ,
503
+ InstallationStage :: Quirk => 8 ,
467
504
InstallationStage :: Done => 8 ,
468
505
} ;
469
506
470
507
step. store ( num, Ordering :: SeqCst ) ;
471
508
509
+ if no_run. contains ( & stage) {
510
+ stage = stage. get_next_stage ( ) ;
511
+ continue ;
512
+ }
513
+
472
514
let res = match stage {
473
515
InstallationStage :: SetupPartition => self
474
516
. setup_partition ( & progress, & tmp_mount_path, & cancel_install)
@@ -538,6 +580,27 @@ impl InstallConfig {
538
580
. context ( UmountSnafu )
539
581
. context ( PostInstallationSnafu )
540
582
. map ( |_| true ) ,
583
+ InstallationStage :: Quirk => {
584
+ for cmd in & quirk_commands {
585
+ let out = match Command :: new ( "bash" ) . arg ( "-c" ) . arg ( cmd) . output ( ) {
586
+ Ok ( out) => out,
587
+ Err ( e) => {
588
+ error ! ( "Run {} failed: {}" , cmd, e) ;
589
+ continue ;
590
+ }
591
+ } ;
592
+
593
+ if !out. status . success ( ) {
594
+ error ! (
595
+ "Run {} failed: stderr: {}" ,
596
+ cmd,
597
+ String :: from_utf8_lossy( & out. stderr)
598
+ )
599
+ }
600
+ }
601
+
602
+ Ok ( true )
603
+ }
541
604
InstallationStage :: Done => break ,
542
605
} ;
543
606
0 commit comments