Add BSD::Control::Feature#status

This commit is contained in:
0x1eef 2024-03-07 23:41:45 -03:00
parent e84e824579
commit 4eaf98b9bc
5 changed files with 123 additions and 0 deletions

View file

@ -1,5 +1,8 @@
#include <libhbsdcontrol.h> #include <libhbsdcontrol.h>
#include <ruby.h> #include <ruby.h>
#include <sys/extattr.h>
#include <libutil.h>
#include <errno.h>
#include "include/ffi.h" #include "include/ffi.h"
/** /**
@ -56,6 +59,43 @@ ffi_reset(VALUE self, VALUE rb_feature, VALUE rb_path)
} }
/**
* BSD::Control::FFI.status
**/
VALUE
ffi_status(VALUE self, VALUE rb_feature, VALUE rb_path)
{
VALUE rb_enable_flag, rb_disable_flag;
char *enable_flag, *disable_flag, *path, enable_data[2], disable_data[2];
int namespace;
rb_enable_flag = rb_funcall(rb_feature, rb_intern("enable"), 0);
rb_disable_flag = rb_funcall(rb_feature, rb_intern("disable"), 0);
Check_Type(rb_path, T_STRING);
Check_Type(rb_enable_flag, T_STRING);
Check_Type(rb_disable_flag, T_STRING);
path = RSTRING_PTR(rb_path);
enable_flag = RSTRING_PTR(rb_enable_flag);
disable_flag = RSTRING_PTR(rb_disable_flag);
if (extattr_string_to_namespace("system", &namespace) == -1) {
rb_syserr_fail(errno, "extattr_string_to_namespace");
}
if (extattr_get_file(path, namespace, enable_flag, &enable_data, 2) == -1) {
rb_syserr_fail(errno, "extattr_get_file");
}
if (extattr_get_file(path, namespace, disable_flag, &disable_data, 2) == -1) {
rb_syserr_fail(errno, "extattr_get_file");
}
if (strcmp(enable_data, disable_data) == 0) {
return (ID2SYM(rb_intern("conflict")));
} else if (strcmp(enable_data, "1") == 0) {
return (ID2SYM(rb_intern("enabled")));
} else {
return (ID2SYM(rb_intern("disabled")));
}
}
/** /**
* BSD::Control::FFI.library_version * BSD::Control::FFI.library_version
**/ **/

View file

@ -15,5 +15,6 @@ Init_hbsdctl(void)
rb_define_singleton_method(rb_mFFI, "available_features", ffi_available_features, 0); rb_define_singleton_method(rb_mFFI, "available_features", ffi_available_features, 0);
rb_define_singleton_method(rb_mFFI, "library_version", ffi_library_version, 0); rb_define_singleton_method(rb_mFFI, "library_version", ffi_library_version, 0);
rb_define_singleton_method(rb_mFFI, "reset!", ffi_reset, 2); rb_define_singleton_method(rb_mFFI, "reset!", ffi_reset, 2);
rb_define_singleton_method(rb_mFFI, "status", ffi_status, 2);
rb_define_private_method(rb_cFeature, "set!", feature_set, 2); rb_define_private_method(rb_cFeature, "set!", feature_set, 2);
} }

View file

@ -1,4 +1,5 @@
#include <ruby.h> #include <ruby.h>
VALUE ffi_library_version(VALUE); VALUE ffi_library_version(VALUE);
VALUE ffi_available_features(VALUE); VALUE ffi_available_features(VALUE);
VALUE ffi_status(VALUE, VALUE, VALUE);
VALUE ffi_reset(VALUE, VALUE, VALUE); VALUE ffi_reset(VALUE, VALUE, VALUE);

View file

@ -55,6 +55,47 @@ module BSD::Control
FFI.reset!(self, path) FFI.reset!(self, path)
end end
##
# @return [Boolean]
# Returns true when a feature is enabled.
def enabled?(path)
status(path) == :enabled
end
##
# @return [Boolean]
# Returns true when a feature is disabled.
def disabled?(path)
status(path) == :disabled
end
##
# @return [Boolean]
# Returns true when a feature is configured to use the system default.
def sysdef?(path)
status(path) == :sysdef
end
##
# @return [Boolean]
# Returns true when a feature is in conflict
# (i.e: the feature is both enabled and disabled at the same time).
def conflict?(path)
status(path) == :conflict
end
##
# @param [String] path
# The path to a file.
# @return [Symbol]
# Returns the feature status of a file.
# Status can be one of: `:conflict`, `:sysdef`, `:enabled`, `:disabled`.
def status(path)
FFI.status(self, path)
rescue Errno::ENOATTR
:sysdef
end
# @endgroup # @endgroup
## ##

View file

@ -0,0 +1,40 @@
require_relative "../setup"
module BSD::Control
class EnableFeatureTest < Test::Unit::TestCase
require 'fileutils'
include FileUtils
def test_mprotect_sysdef_status
touch(file)
assert_equal :sysdef,
BSD::Control.feature!(:mprotect).status(file)
ensure
rm(file)
end
def test_mprotect_enabled_status
touch(file)
BSD::Control.feature!(:mprotect).enable!(file)
assert_equal :enabled,
BSD::Control.feature!(:mprotect).status(file)
ensure
rm(file)
end
def test_mprotect_disabled_status
touch(file)
BSD::Control.feature!(:mprotect).disable!(file)
assert_equal :disabled,
BSD::Control.feature!(:mprotect).status(file)
ensure
rm(file)
end
private
def file
File.join(__dir__, "file")
end
end
end