An error returned by a Linx.Sysctl operation.
Built from a failed File.read/1 / File.write/2 against a
/proc/sys/... path, or — for the cross-namespace verbs —
from a failure during the setns dance the NIF performs on a
throwaway pthread.
The shape:
:key— the dot-form sysctl key the caller passed in, e.g."net.ipv4.ip_forward".:path— the resolved procfs path the operation targeted, e.g."/proc/sys/net/ipv4/ip_forward".:operation— what we were trying to do, as an atom::read,:write,:list— the procfs I/O itself failed.:open_ns,:unshare,:setns,:chdir,:thread— namespace-acquisition failures from the cross-namespace NIF (only seen when a cross-namespace:inoption was used).
:errno— the POSIX errno as an atom (:enoent,:eperm,:eacces,:einval, …).:code— the matching positive errno integer, ornilif we don't have a mapping for this atom. Included for symmetry withLinx.Mount.Error/Linx.User.Error/Linx.Cgroup.Error.
Pattern-match on :errno and :operation to handle specific
failures:
case Linx.Sysctl.write("net.ipv4.ip_forward", 1) do
:ok ->
:ok
{:error, %Linx.Sysctl.Error{errno: :eacces}} ->
# Needs root.
:no_perm
{:error, %Linx.Sysctl.Error{errno: :enoent}} ->
# No such sysctl on this kernel.
:unknown_knob
endImplements Exception, so an error can be raised or rendered
with Exception.message/1.
Caller-side input mistakes (a malformed key, a multi-line value
the kernel would silently truncate) surface as
{:error, {:bad_key, reason}} / {:error, {:bad_value, reason}}
instead — distinct from kernel rejections, mirroring
Linx.User's :bad_map / %Error{} split.
Summary
Functions
Builds a %Linx.Sysctl.Error{} from a posix-atom errno, the
dot-form key, the resolved procfs path, and the operation we
attempted.
Types
@type operation() ::
:read | :write | :list | :open_ns | :unshare | :setns | :chdir | :thread
@type t() :: %Linx.Sysctl.Error{ __exception__: true, code: pos_integer() | nil, errno: atom(), key: String.t(), operation: operation(), path: Path.t() }