@@ -102,6 +102,9 @@ enum GetValueErrorRaw {
102
102
#[ error( transparent) ]
103
103
Execution ( #[ from] crate :: ExecutionError ) ,
104
104
105
+ #[ error( "Invalid property value 'all'" ) ]
106
+ InvalidValueAll ,
107
+
105
108
#[ error( "No value found with that name" ) ]
106
109
MissingValue ,
107
110
}
@@ -843,13 +846,24 @@ impl Zfs {
843
846
source : Option < PropertySource > ,
844
847
) -> Result < [ String ; N ] , GetValueError > {
845
848
let mut cmd = std:: process:: Command :: new ( PFEXEC ) ;
846
- let all_names =
847
- names. into_iter ( ) . map ( |n| * n) . collect :: < Vec < & str > > ( ) . join ( "," ) ;
849
+ let all_names = names
850
+ . into_iter ( )
851
+ . map ( |n| match * n {
852
+ "all" => Err ( GetValueError {
853
+ filesystem : filesystem_name. to_string ( ) ,
854
+ name : "all" . to_string ( ) ,
855
+ err : GetValueErrorRaw :: InvalidValueAll ,
856
+ } ) ,
857
+ n => Ok ( n) ,
858
+ } )
859
+ . collect :: < Result < Vec < & str > , GetValueError > > ( ) ?
860
+ . join ( "," ) ;
848
861
849
- cmd. args ( & [ ZFS , "get" , "-Ho" , "value" , & all_names ] ) ;
862
+ cmd. args ( & [ ZFS , "get" , "-Ho" , "value" ] ) ;
850
863
if let Some ( source) = source {
851
864
cmd. args ( & [ "-s" , & source. to_string ( ) ] ) ;
852
865
}
866
+ cmd. arg ( & all_names) ;
853
867
cmd. arg ( filesystem_name) ;
854
868
let output = execute ( & mut cmd) . map_err ( |err| GetValueError {
855
869
filesystem : filesystem_name. to_string ( ) ,
@@ -940,6 +954,36 @@ pub fn get_all_omicron_datasets_for_delete() -> anyhow::Result<Vec<String>> {
940
954
mod test {
941
955
use super :: * ;
942
956
957
+ // This test validates that "get_values" at least parses correctly.
958
+ //
959
+ // To minimize test setup, we rely on a zfs dataset named "rpool" existing,
960
+ // but do not modify it within this test.
961
+ #[ cfg( target_os = "illumos" ) ]
962
+ #[ test]
963
+ fn get_values_of_rpool ( ) {
964
+ // If the rpool exists, it should have a name.
965
+ let values = Zfs :: get_values ( "rpool" , & [ "name" ; 1 ] , None )
966
+ . expect ( "Failed to query rpool type" ) ;
967
+ assert_eq ! ( values[ 0 ] , "rpool" ) ;
968
+
969
+ // We don't really care if any local properties are set, we just don't
970
+ // want this to throw an error.
971
+ let _values =
972
+ Zfs :: get_values ( "rpool" , & [ "name" ; 1 ] , Some ( PropertySource :: Local ) )
973
+ . expect ( "Failed to query rpool type" ) ;
974
+
975
+ // Also, the "all" property should not be queryable. It's normally fine
976
+ // to pass this value, it just returns a variable number of properties,
977
+ // which doesn't work with the current implementation's parsing.
978
+ let err = Zfs :: get_values ( "rpool" , & [ "all" ; 1 ] , None )
979
+ . expect_err ( "Should not be able to query for 'all' property" ) ;
980
+
981
+ assert ! (
982
+ matches!( err. err, GetValueErrorRaw :: InvalidValueAll ) ,
983
+ "Unexpected error: {err}"
984
+ ) ;
985
+ }
986
+
943
987
#[ test]
944
988
fn parse_dataset_props ( ) {
945
989
let input = "dataset_name\t available\t 1234\t -\n \
0 commit comments