Update to recent Syndicate Nim API
This commit is contained in:
parent
0e25a32850
commit
afb7d9c2a4
15 changed files with 986 additions and 65 deletions
2
.envrc
2
.envrc
|
@ -1,2 +0,0 @@
|
|||
source_env ..
|
||||
use nix
|
41
README.md
41
README.md
|
@ -1,29 +1,38 @@
|
|||
# Syndicated Device Event Broadcaster
|
||||
# Synit device managment toolkit
|
||||
|
||||
An actor for broadcasting Linux Kernel uevents.
|
||||
Intended as a kit for building native a device manager for [Synit](https://synit.org).
|
||||
This is not a replacement for udev/eudev or mdev/mdevd.
|
||||
|
||||
Intended as part of native a device manager for [Synit](https://synit.org). This is not a replacement for udev/eudev or mdev/mdevd.
|
||||
|
||||
Message Schema is at [./uevent.prs](./uevent.prs).
|
||||
Message Schema is at [uevents.prs](./uevents.prs).
|
||||
|
||||
If you are looking for documentation on how to parse and handle Linux uevents, please let me know when you find it.
|
||||
|
||||
Example Syndicate server configuration:
|
||||
Example configuration for logging uevents:
|
||||
```
|
||||
? <machine-dataspace ?machine> [
|
||||
#!/usr/bin/env -S syndicate-server --config
|
||||
|
||||
<require-service <daemon syndev>>
|
||||
|
||||
<daemon syndev {
|
||||
argv: ["/bin/syndev"]
|
||||
protocol: application/syndicate
|
||||
}>
|
||||
|
||||
? <service-object <daemon syndev> ?cap> [
|
||||
$cap { machine: $machine }
|
||||
<q <service uevent-dump>>
|
||||
? <a <service uevent-dump> <accepted ?stream>> [
|
||||
$stream ?? ?msg [
|
||||
$log ! <log "uevent" { line: ?msg }>
|
||||
]
|
||||
]
|
||||
|
||||
? <q <service uevent-dump>> [
|
||||
<require-service <daemon dump-uevent>>
|
||||
? <service-object <daemon dump-uevent> ?obj> [
|
||||
let ?rewriter = <* $config [<rewrite ?resp <a <service uevent-dump> $resp>>]>
|
||||
$obj <resolve <uevent-dump> $rewriter>
|
||||
]
|
||||
]
|
||||
|
||||
<daemon dump-uevent {
|
||||
argv: ["/bin/dump-uevent" ]
|
||||
clearEnv: #t
|
||||
env: { BUILD_SUM: $sum }
|
||||
protocol: application/syndicate
|
||||
}>
|
||||
|
||||
```
|
||||
|
||||
Example message stream:
|
||||
|
|
7
Tupfile
7
Tupfile
|
@ -1,3 +1,6 @@
|
|||
include_rules
|
||||
: |> !nim_lk |> {lockfile}
|
||||
: {lockfile} |> !nim_cfg |> | ./<lock>
|
||||
|
||||
: sbom.json |> !sbom-to-nix |> | ./<lock>
|
||||
run ./Tuprules.jq sbom.json
|
||||
|
||||
: foreach {bin} |> !assert_built |>
|
||||
|
|
12
Tuprules.jq
Executable file
12
Tuprules.jq
Executable file
|
@ -0,0 +1,12 @@
|
|||
#! /usr/bin/env -S jq --raw-output --from-file
|
||||
.metadata.component.properties as $props |
|
||||
$props |
|
||||
( map( select(.name | .[0:10] == "nim:binDir") ) +
|
||||
map( select(.name | .[0:10] == "nim:srcDir") ) |
|
||||
map( .value )
|
||||
) + ["."] | .[0] as $binDir |
|
||||
|
||||
$props |
|
||||
map( select(.name | .[0:8] == "nim:bin:") ) |
|
||||
map( ": \($binDir)/\(.value).nim |> !nim_bin |> $(BIN_DIR)/\(.name[8:]) {bin}" ) |
|
||||
join("\n")
|
|
@ -1,4 +1,6 @@
|
|||
include ../syndicate-nim/depends.tup
|
||||
NIM = $(DIRENV) $(NIM)
|
||||
NIM_FLAGS += --path:$(TUP_CWD)/../syndicate-nim/src
|
||||
NIM_GROUPS += $(TUP_CWD)/<lock>
|
||||
PROJECT_DIR = $(TUP_CWD)
|
||||
|
||||
NIM_GROUPS += $(SYNDICATE_PROTOCOL)
|
||||
NIM_GROUPS += $(PROJECT_DIR)/<lock>
|
||||
NIM_GROUPS += $(PROJECT_DIR)/<schema>
|
||||
|
|
192
build-nim-sbom.nix
Normal file
192
build-nim-sbom.nix
Normal file
|
@ -0,0 +1,192 @@
|
|||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchgit,
|
||||
fetchzip,
|
||||
runCommand,
|
||||
xorg,
|
||||
nim,
|
||||
nimOverrides,
|
||||
}:
|
||||
|
||||
let
|
||||
fetchers = {
|
||||
fetchzip =
|
||||
{ url, sha256, ... }:
|
||||
fetchzip {
|
||||
name = "source";
|
||||
inherit url sha256;
|
||||
};
|
||||
fetchgit =
|
||||
{
|
||||
fetchSubmodules ? false,
|
||||
leaveDotGit ? false,
|
||||
rev,
|
||||
sha256,
|
||||
url,
|
||||
...
|
||||
}:
|
||||
fetchgit {
|
||||
inherit
|
||||
fetchSubmodules
|
||||
leaveDotGit
|
||||
rev
|
||||
sha256
|
||||
url
|
||||
;
|
||||
};
|
||||
};
|
||||
|
||||
filterPropertiesToAttrs =
|
||||
prefix: properties:
|
||||
lib.pipe properties [
|
||||
(builtins.filter ({ name, ... }: (lib.strings.hasPrefix prefix name)))
|
||||
(map (
|
||||
{ name, value }:
|
||||
{
|
||||
name = lib.strings.removePrefix prefix name;
|
||||
inherit value;
|
||||
}
|
||||
))
|
||||
builtins.listToAttrs
|
||||
];
|
||||
|
||||
buildNimCfg =
|
||||
{ backend, components, ... }:
|
||||
let
|
||||
componentSrcDirs = map (
|
||||
{ properties, ... }:
|
||||
let
|
||||
fodProps = filterPropertiesToAttrs "nix:fod:" properties;
|
||||
fod = fetchers.${fodProps.method} fodProps;
|
||||
srcDir = fodProps.srcDir or "";
|
||||
in
|
||||
if srcDir == "" then fod else "${fod}/${srcDir}"
|
||||
) components;
|
||||
in
|
||||
runCommand "nim.cfg"
|
||||
{
|
||||
outputs = [
|
||||
"out"
|
||||
"src"
|
||||
];
|
||||
nativeBuildInputs = [ xorg.lndir ];
|
||||
}
|
||||
''
|
||||
pkgDir=$src/pkg
|
||||
cat << EOF >> $out
|
||||
backend:${backend}
|
||||
path:"$src"
|
||||
path:"$pkgDir"
|
||||
EOF
|
||||
mkdir -p "$pkgDir"
|
||||
${lib.strings.concatMapStrings (d: ''
|
||||
lndir "${d}" "$pkgDir"
|
||||
'') componentSrcDirs}
|
||||
'';
|
||||
|
||||
buildCommands = lib.attrsets.mapAttrsToList (
|
||||
output: input: ''
|
||||
nim compile $nimFlags --out:${output} ${input}
|
||||
''
|
||||
);
|
||||
|
||||
installCommands = lib.attrsets.mapAttrsToList (
|
||||
output: input: ''
|
||||
install -Dt $out/bin ${output}
|
||||
''
|
||||
);
|
||||
|
||||
applySbom =
|
||||
sbom:
|
||||
{
|
||||
passthru ? { },
|
||||
...
|
||||
}@prevAttrs:
|
||||
let
|
||||
properties = # SBOM metadata.component.properties as an attrset.
|
||||
lib.attrsets.recursiveUpdate (builtins.listToAttrs sbom.metadata.component.properties)
|
||||
passthru.properties or { };
|
||||
|
||||
nimBin = # A mapping of Nim module file paths to names of programs.
|
||||
lib.attrsets.recursiveUpdate (lib.pipe properties [
|
||||
(lib.attrsets.filterAttrs (name: value: lib.strings.hasPrefix "nim:bin:" name))
|
||||
(lib.attrsets.mapAttrs' (
|
||||
name: value: {
|
||||
name = lib.strings.removePrefix "nim:bin:" name;
|
||||
value = "${properties."nim:binDir" or (properties."nim:srcDir" or ".")}/${value}";
|
||||
}
|
||||
))
|
||||
]) passthru.nimBin or { };
|
||||
in
|
||||
{
|
||||
strictDeps = true;
|
||||
|
||||
pname = prevAttrs.pname or sbom.metadata.component.name;
|
||||
version = prevAttrs.version or sbom.metadata.component.version or null;
|
||||
|
||||
configurePhase =
|
||||
prevAttrs.configurePhase or ''
|
||||
runHook preConfigure
|
||||
echo "nim.cfg << $nimCfg"
|
||||
cat $nimCfg >> nim.cfg
|
||||
cat << EOF >> nim.cfg
|
||||
nimcache:"$NIX_BUILD_TOP/nimcache"
|
||||
parallelBuild:$NIX_BUILD_CORES
|
||||
EOF
|
||||
runHook postConfigure
|
||||
'';
|
||||
|
||||
buildPhase =
|
||||
prevAttrs.buildPhase or ''
|
||||
runHook preBuild
|
||||
${lib.strings.concatLines (buildCommands nimBin)}
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase =
|
||||
prevAttrs.installPhase or ''
|
||||
runHook preInstall
|
||||
${lib.strings.concatLines (installCommands nimBin)}
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
nativeBuildInputs = (prevAttrs.nativeBuildInputs or [ ]) ++ [ nim ];
|
||||
|
||||
nimCfg =
|
||||
prevAttrs.nimCfg or (buildNimCfg {
|
||||
backend = prevAttrs.nimBackend or properties."nim:backend" or "c";
|
||||
inherit (sbom) components;
|
||||
});
|
||||
|
||||
passthru = {
|
||||
inherit sbom properties nimBin;
|
||||
};
|
||||
};
|
||||
|
||||
applyOverrides =
|
||||
prevAttrs:
|
||||
builtins.foldl' (
|
||||
prevAttrs:
|
||||
{ name, ... }@component:
|
||||
if (builtins.hasAttr name nimOverrides) then
|
||||
prevAttrs // (nimOverrides.${name} component prevAttrs)
|
||||
else
|
||||
prevAttrs
|
||||
) prevAttrs prevAttrs.passthru.sbom.components;
|
||||
|
||||
compose =
|
||||
callerArg: sbom: finalAttrs:
|
||||
let
|
||||
callerAttrs = if builtins.isAttrs callerArg then callerArg else callerArg finalAttrs;
|
||||
sbomAttrs = callerAttrs // (applySbom sbom callerAttrs);
|
||||
overrideAttrs = sbomAttrs // (applyOverrides sbomAttrs);
|
||||
in
|
||||
overrideAttrs;
|
||||
in
|
||||
callerArg: sbomArg:
|
||||
let
|
||||
sbom = if builtins.isAttrs sbomArg then sbomArg else builtins.fromJSON (builtins.readFile sbomArg);
|
||||
overrideSbom = f: stdenv.mkDerivation (compose callerArg (sbom // (f sbom)));
|
||||
in
|
||||
(stdenv.mkDerivation (compose callerArg sbom)) // { inherit overrideSbom; }
|
17
default.nix
17
default.nix
|
@ -1,7 +1,10 @@
|
|||
{ pkgs ? import <nixpkgs> { } }:
|
||||
|
||||
pkgs.buildNimPackage {
|
||||
name = "syndicate_utils_linux";
|
||||
lockFile = ./lock.json;
|
||||
src = pkgs.lib.sources.cleanSource ./.;
|
||||
}
|
||||
{
|
||||
pkgs ? import <nixpkgs> { },
|
||||
}:
|
||||
with pkgs;
|
||||
let
|
||||
buildNimSbom = pkgs.callPackage ./build-nim-sbom.nix { };
|
||||
in
|
||||
buildNimSbom (finalAttrs: {
|
||||
src = if lib.inNixShell then null else lib.cleanSource ./.;
|
||||
}) ./sbom.json
|
||||
|
|
598
sbom.json
Normal file
598
sbom.json
Normal file
|
@ -0,0 +1,598 @@
|
|||
{
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.6",
|
||||
"metadata": {
|
||||
"component": {
|
||||
"type": "application",
|
||||
"bom-ref": "pkg:nim/syndev",
|
||||
"name": "syndev",
|
||||
"description": "Syndicate utilties for Linux.",
|
||||
"version": "20240806",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Emery Hemingway"
|
||||
}
|
||||
],
|
||||
"licenses": [
|
||||
{
|
||||
"license": {
|
||||
"id": "Unlicense"
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "nim:skipExt",
|
||||
"value": "nim"
|
||||
},
|
||||
{
|
||||
"name": "nim:bin:uevent-dump",
|
||||
"value": "uevent_dump"
|
||||
},
|
||||
{
|
||||
"name": "nim:srcDir",
|
||||
"value": "src"
|
||||
},
|
||||
{
|
||||
"name": "nim:backend",
|
||||
"value": "c"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"type": "library",
|
||||
"bom-ref": "pkg:nim/syndicate",
|
||||
"name": "syndicate",
|
||||
"version": "20240802",
|
||||
"externalReferences": [
|
||||
{
|
||||
"url": "https://git.syndicate-lang.org/ehmry/syndicate-nim/archive/423d7e9944c7b29055ae44be6bdbba2c885fc94e.tar.gz",
|
||||
"type": "source-distribution"
|
||||
},
|
||||
{
|
||||
"url": "https://git.syndicate-lang.org/ehmry/syndicate-nim",
|
||||
"type": "vcs"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "nix:fod:method",
|
||||
"value": "fetchzip"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:path",
|
||||
"value": "/nix/store/zry30gjkabnyar9pf941nsmlq0pgh7lb-source"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:rev",
|
||||
"value": "423d7e9944c7b29055ae44be6bdbba2c885fc94e"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:sha256",
|
||||
"value": "16qkszw2gsbyg97i5jzz2lczhffkjfmh42h3h7v5k8rhf4l471r1"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:url",
|
||||
"value": "https://git.syndicate-lang.org/ehmry/syndicate-nim/archive/423d7e9944c7b29055ae44be6bdbba2c885fc94e.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:ref",
|
||||
"value": "20240802"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:srcDir",
|
||||
"value": "src"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bom-ref": "pkg:nim/nimcrypto",
|
||||
"name": "nimcrypto",
|
||||
"version": "485f7b3cfa83c1beecc0e31be0e964d697aa74d7",
|
||||
"externalReferences": [
|
||||
{
|
||||
"url": "https://github.com/cheatfate/nimcrypto/archive/485f7b3cfa83c1beecc0e31be0e964d697aa74d7.tar.gz",
|
||||
"type": "source-distribution"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/cheatfate/nimcrypto",
|
||||
"type": "vcs"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "nix:fod:method",
|
||||
"value": "fetchzip"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:path",
|
||||
"value": "/nix/store/fkrcpp8lzj2yi21na79xm63xk0ggnqsp-source"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:rev",
|
||||
"value": "485f7b3cfa83c1beecc0e31be0e964d697aa74d7"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:sha256",
|
||||
"value": "1h3dzdbc9kacwpi10mj73yjglvn7kbizj1x8qc9099ax091cj5xn"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:url",
|
||||
"value": "https://github.com/cheatfate/nimcrypto/archive/485f7b3cfa83c1beecc0e31be0e964d697aa74d7.tar.gz"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bom-ref": "pkg:nim/preserves",
|
||||
"name": "preserves",
|
||||
"version": "20240802",
|
||||
"externalReferences": [
|
||||
{
|
||||
"url": "https://git.syndicate-lang.org/ehmry/preserves-nim/archive/7ecc8cec3e119476a560d0c529b902a180852faa.tar.gz",
|
||||
"type": "source-distribution"
|
||||
},
|
||||
{
|
||||
"url": "https://git.syndicate-lang.org/ehmry/preserves-nim.git",
|
||||
"type": "vcs"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "nix:fod:method",
|
||||
"value": "fetchzip"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:path",
|
||||
"value": "/nix/store/3927dikh3a73gdmag890908kip1ali30-source"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:rev",
|
||||
"value": "7ecc8cec3e119476a560d0c529b902a180852faa"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:sha256",
|
||||
"value": "1151y09qbq3b7cn1rh39ln8kh22fq3vdic6vbsmdbc7vfyhnlyg0"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:url",
|
||||
"value": "https://git.syndicate-lang.org/ehmry/preserves-nim/archive/7ecc8cec3e119476a560d0c529b902a180852faa.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:ref",
|
||||
"value": "20240802"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:srcDir",
|
||||
"value": "src"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bom-ref": "pkg:nim/sys",
|
||||
"name": "sys",
|
||||
"version": "4ef3b624db86e331ba334e705c1aa235d55b05e1",
|
||||
"externalReferences": [
|
||||
{
|
||||
"url": "https://github.com/ehmry/nim-sys/archive/4ef3b624db86e331ba334e705c1aa235d55b05e1.tar.gz",
|
||||
"type": "source-distribution"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/ehmry/nim-sys.git",
|
||||
"type": "vcs"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "nix:fod:method",
|
||||
"value": "fetchzip"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:path",
|
||||
"value": "/nix/store/syhxsjlsdqfap0hk4qp3s6kayk8cqknd-source"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:rev",
|
||||
"value": "4ef3b624db86e331ba334e705c1aa235d55b05e1"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:sha256",
|
||||
"value": "1q4qgw4an4mmmcbx48l6xk1jig1vc8p9cq9dbx39kpnb0890j32q"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:url",
|
||||
"value": "https://github.com/ehmry/nim-sys/archive/4ef3b624db86e331ba334e705c1aa235d55b05e1.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:srcDir",
|
||||
"value": "src"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bom-ref": "pkg:nim/taps",
|
||||
"name": "taps",
|
||||
"version": "20240405",
|
||||
"externalReferences": [
|
||||
{
|
||||
"url": "https://git.sr.ht/~ehmry/nim_taps/archive/8c8572cd971d1283e6621006b310993c632da247.tar.gz",
|
||||
"type": "source-distribution"
|
||||
},
|
||||
{
|
||||
"url": "https://git.sr.ht/~ehmry/nim_taps",
|
||||
"type": "vcs"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "nix:fod:method",
|
||||
"value": "fetchzip"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:path",
|
||||
"value": "/nix/store/6y14ia52kr7jyaa0izx37mlablmq9s65-source"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:rev",
|
||||
"value": "8c8572cd971d1283e6621006b310993c632da247"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:sha256",
|
||||
"value": "1dp166bv9x773jmfqppg5i3v3rilgff013vb11yzwcid9l7s3iy8"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:url",
|
||||
"value": "https://git.sr.ht/~ehmry/nim_taps/archive/8c8572cd971d1283e6621006b310993c632da247.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:ref",
|
||||
"value": "20240405"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:srcDir",
|
||||
"value": "src"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bom-ref": "pkg:nim/solo5_dispatcher",
|
||||
"name": "solo5_dispatcher",
|
||||
"version": "20240522",
|
||||
"externalReferences": [
|
||||
{
|
||||
"url": "https://git.sr.ht/~ehmry/solo5_dispatcher/archive/cc64ef99416b22b12e4a076d33de9e25a163e57d.tar.gz",
|
||||
"type": "source-distribution"
|
||||
},
|
||||
{
|
||||
"url": "https://git.sr.ht/~ehmry/solo5_dispatcher",
|
||||
"type": "vcs"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "nix:fod:method",
|
||||
"value": "fetchzip"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:path",
|
||||
"value": "/nix/store/4jj467pg4hs6warhksb8nsxn9ykz8c7c-source"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:rev",
|
||||
"value": "cc64ef99416b22b12e4a076d33de9e25a163e57d"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:sha256",
|
||||
"value": "1v9i9fqgx1g76yrmz2xwj9mxfwbjfpar6dsyygr68fv9031cqxq7"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:url",
|
||||
"value": "https://git.sr.ht/~ehmry/solo5_dispatcher/archive/cc64ef99416b22b12e4a076d33de9e25a163e57d.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:ref",
|
||||
"value": "20240522"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:srcDir",
|
||||
"value": "pkg"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bom-ref": "pkg:nim/npeg",
|
||||
"name": "npeg",
|
||||
"version": "1.2.2",
|
||||
"externalReferences": [
|
||||
{
|
||||
"url": "https://github.com/zevv/npeg/archive/ec0cc6e64ea4c62d2aa382b176a4838474238f8d.tar.gz",
|
||||
"type": "source-distribution"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/zevv/npeg.git",
|
||||
"type": "vcs"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "nix:fod:method",
|
||||
"value": "fetchzip"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:path",
|
||||
"value": "/nix/store/xpn694ibgipj8xak3j4bky6b3k0vp7hh-source"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:rev",
|
||||
"value": "ec0cc6e64ea4c62d2aa382b176a4838474238f8d"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:sha256",
|
||||
"value": "1fi9ls3xl20bmv1ikillxywl96i9al6zmmxrbffx448gbrxs86kg"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:url",
|
||||
"value": "https://github.com/zevv/npeg/archive/ec0cc6e64ea4c62d2aa382b176a4838474238f8d.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:ref",
|
||||
"value": "1.2.2"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:srcDir",
|
||||
"value": "src"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bom-ref": "pkg:nim/nim-bigints",
|
||||
"name": "bigints",
|
||||
"version": "20231006",
|
||||
"externalReferences": [
|
||||
{
|
||||
"url": "https://github.com/ehmry/nim-bigints/archive/86ea14d31eea9275e1408ca34e6bfe9c99989a96.tar.gz",
|
||||
"type": "source-distribution"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/ehmry/nim-bigints.git",
|
||||
"type": "vcs"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "nix:fod:method",
|
||||
"value": "fetchzip"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:path",
|
||||
"value": "/nix/store/jvrm392g8adfsgf36prgwkbyd7vh5jsw-source"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:rev",
|
||||
"value": "86ea14d31eea9275e1408ca34e6bfe9c99989a96"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:sha256",
|
||||
"value": "15pcpmnk1bnw3k8769rjzcpg00nahyrypwbxs88jnwr4aczp99j4"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:url",
|
||||
"value": "https://github.com/ehmry/nim-bigints/archive/86ea14d31eea9275e1408ca34e6bfe9c99989a96.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:ref",
|
||||
"value": "20231006"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:srcDir",
|
||||
"value": "src"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bom-ref": "pkg:nim/cps",
|
||||
"name": "cps",
|
||||
"version": "0.10.4",
|
||||
"externalReferences": [
|
||||
{
|
||||
"url": "https://github.com/nim-works/cps/archive/2a4d771a715ba45cfba3a82fa625ae7ad6591c8b.tar.gz",
|
||||
"type": "source-distribution"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nim-works/cps",
|
||||
"type": "vcs"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "nix:fod:method",
|
||||
"value": "fetchzip"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:path",
|
||||
"value": "/nix/store/m9vpcf3dq6z2h1xpi1vlw0ycxp91s5p7-source"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:rev",
|
||||
"value": "2a4d771a715ba45cfba3a82fa625ae7ad6591c8b"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:sha256",
|
||||
"value": "0c62k5wpq9z9mn8cd4rm8jjc4z0xmnak4piyj5dsfbyj6sbdw2bf"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:url",
|
||||
"value": "https://github.com/nim-works/cps/archive/2a4d771a715ba45cfba3a82fa625ae7ad6591c8b.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:ref",
|
||||
"value": "0.10.4"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bom-ref": "pkg:nim/stew",
|
||||
"name": "stew",
|
||||
"version": "3c91b8694e15137a81ec7db37c6c58194ec94a6a",
|
||||
"externalReferences": [
|
||||
{
|
||||
"url": "https://github.com/status-im/nim-stew/archive/3c91b8694e15137a81ec7db37c6c58194ec94a6a.tar.gz",
|
||||
"type": "source-distribution"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/status-im/nim-stew",
|
||||
"type": "vcs"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "nix:fod:method",
|
||||
"value": "fetchzip"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:path",
|
||||
"value": "/nix/store/mqg8qzsbcc8xqabq2yzvlhvcyqypk72c-source"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:rev",
|
||||
"value": "3c91b8694e15137a81ec7db37c6c58194ec94a6a"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:sha256",
|
||||
"value": "17lfhfxp5nxvld78xa83p258y80ks5jb4n53152cdr57xk86y07w"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:url",
|
||||
"value": "https://github.com/status-im/nim-stew/archive/3c91b8694e15137a81ec7db37c6c58194ec94a6a.tar.gz"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "library",
|
||||
"bom-ref": "pkg:nim/getdns",
|
||||
"name": "getdns",
|
||||
"version": "20230806",
|
||||
"externalReferences": [
|
||||
{
|
||||
"url": "https://git.sr.ht/~ehmry/getdns-nim/archive/e4ae0992ed7c5540e6d498f3074d06c8f454a0b6.tar.gz",
|
||||
"type": "source-distribution"
|
||||
},
|
||||
{
|
||||
"url": "https://git.sr.ht/~ehmry/getdns-nim",
|
||||
"type": "vcs"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "nix:fod:method",
|
||||
"value": "fetchzip"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:path",
|
||||
"value": "/nix/store/j8i20k9aarzppg4p234449140nnnaycq-source"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:rev",
|
||||
"value": "e4ae0992ed7c5540e6d498f3074d06c8f454a0b6"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:sha256",
|
||||
"value": "1dp53gndr6d9s9601dd5ipkiq94j53hlx46mxv8gpr8nd98bqysg"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:url",
|
||||
"value": "https://git.sr.ht/~ehmry/getdns-nim/archive/e4ae0992ed7c5540e6d498f3074d06c8f454a0b6.tar.gz"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:ref",
|
||||
"value": "20230806"
|
||||
},
|
||||
{
|
||||
"name": "nix:fod:srcDir",
|
||||
"value": "src"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"dependencies": [
|
||||
{
|
||||
"ref": "pkg:nim/syndev",
|
||||
"dependsOn": [
|
||||
"pkg:nim/syndicate"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ref": "pkg:nim/syndicate",
|
||||
"dependsOn": [
|
||||
"pkg:nim/nimcrypto",
|
||||
"pkg:nim/preserves",
|
||||
"pkg:nim/sys",
|
||||
"pkg:nim/taps",
|
||||
"pkg:nim/solo5_dispatcher"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ref": "pkg:nim/nimcrypto",
|
||||
"dependsOn": []
|
||||
},
|
||||
{
|
||||
"ref": "pkg:nim/preserves",
|
||||
"dependsOn": [
|
||||
"pkg:nim/npeg",
|
||||
"pkg:nim/nim-bigints"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ref": "pkg:nim/sys",
|
||||
"dependsOn": [
|
||||
"pkg:nim/cps",
|
||||
"pkg:nim/stew"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ref": "pkg:nim/taps",
|
||||
"dependsOn": [
|
||||
"pkg:nim/getdns",
|
||||
"pkg:nim/sys",
|
||||
"pkg:nim/cps",
|
||||
"pkg:nim/solo5_dispatcher"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ref": "pkg:nim/solo5_dispatcher",
|
||||
"dependsOn": [
|
||||
"pkg:nim/cps"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ref": "pkg:nim/npeg",
|
||||
"dependsOn": []
|
||||
},
|
||||
{
|
||||
"ref": "pkg:nim/nim-bigints",
|
||||
"dependsOn": []
|
||||
},
|
||||
{
|
||||
"ref": "pkg:nim/cps",
|
||||
"dependsOn": []
|
||||
},
|
||||
{
|
||||
"ref": "pkg:nim/stew",
|
||||
"dependsOn": []
|
||||
},
|
||||
{
|
||||
"ref": "pkg:nim/getdns",
|
||||
"dependsOn": []
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
include_rules
|
||||
: foreach *.nim | $(SYNDICATE_PROTOCOL) |> !nim_bin |> {bin}
|
||||
: {bin} |> !assert_built |>
|
2
src/schema/Tupfile
Normal file
2
src/schema/Tupfile
Normal file
|
@ -0,0 +1,2 @@
|
|||
include_rules
|
||||
: foreach ../../*.prs |> !preserves-schema-nim |> %B.nim | $(PROJECT_DIR)/<schema>
|
19
src/schema/uevents.nim
Normal file
19
src/schema/uevents.nim
Normal file
|
@ -0,0 +1,19 @@
|
|||
|
||||
import
|
||||
preserves, std/tables
|
||||
|
||||
type
|
||||
UventDumpStep* {.preservesRecord: "uevent-dump".} = object
|
||||
|
||||
Uevent* {.preservesRecord: "uvent".} = object
|
||||
`subsystem`*: string
|
||||
`devpath`*: string
|
||||
`action`*: string
|
||||
`attrs`*: Table[Symbol, string]
|
||||
`seqnum`*: BiggestInt
|
||||
|
||||
proc `$`*(x: UventDumpStep | Uevent): string =
|
||||
`$`(toPreserves(x))
|
||||
|
||||
proc encode*(x: UventDumpStep | Uevent): seq[byte] =
|
||||
encode(toPreserves(x))
|
|
@ -3,9 +3,13 @@
|
|||
|
||||
# *Do not misinterpret any of this as documentation for handling Linux uevents.*
|
||||
|
||||
import std/[nativesockets, os, parseutils, posix]
|
||||
import pkg/sys/[handles, ioqueue, sockets]
|
||||
import preserves, syndicate, syndicate/relays
|
||||
import
|
||||
std/[nativesockets, options, os, parseutils, posix, sets],
|
||||
pkg/sys/[handles, ioqueue, sockets],
|
||||
pkg/preserves,
|
||||
pkg/syndicate,
|
||||
pkg/syndicate/protocols/[gatekeeper, sturdy],
|
||||
./schema/uevents
|
||||
|
||||
var
|
||||
AF_NETLINK {.importc, header: "sys/socket.h", nodecl.}: uint16
|
||||
|
@ -38,7 +42,9 @@ proc openUeventSocket: SocketHandle =
|
|||
close(result)
|
||||
raise newException(IOError, "Netlink not supported")
|
||||
|
||||
proc openUeventSocketAsync: AsyncConn[sockets.Protocol.Unix] =
|
||||
type Socket = AsyncConn[sockets.Protocol.Unix]
|
||||
|
||||
proc openUeventSocketAsync: Socket =
|
||||
let fd = openUeventSocket()
|
||||
var flags = fcntl(fd.cint, F_GETFL)
|
||||
if flags < 0:
|
||||
|
@ -46,9 +52,15 @@ proc openUeventSocketAsync: AsyncConn[sockets.Protocol.Unix] =
|
|||
flags = flags or O_NONBLOCK
|
||||
if fcntl(fd.cint, F_SETFL, flags) < 0:
|
||||
raiseOSError(osLastError())
|
||||
AsyncConn[sockets.Protocol.Unix] fd.SocketFD.initHandle.newAsyncSocket
|
||||
fd.SocketFD.initHandle.newAsyncSocket.Socket
|
||||
|
||||
proc sendMessage(turn: var Turn; ds: Cap; buf: string; n: int) =
|
||||
type
|
||||
MessageRelay = ref object
|
||||
facet: Facet
|
||||
dataspace, attenuation: Cap
|
||||
sock: Socket
|
||||
|
||||
proc sendMessage(relay: MessageRelay; turn: Turn; buf: string; n: int) =
|
||||
var
|
||||
msg = initRecord("uevent", toPreserves"", toPreserves"", toSymbol"", initDictionary(), 0.toPreserves)
|
||||
key, val: string
|
||||
|
@ -83,24 +95,45 @@ proc sendMessage(turn: var Turn; ds: Cap; buf: string; n: int) =
|
|||
return
|
||||
if msg.record[3].dict.len > 0:
|
||||
cannonicalize(msg.record[3])
|
||||
message(turn, ds, msg)
|
||||
message(turn, relay.dataspace, msg)
|
||||
msg.record[3].dict.setLen(0)
|
||||
|
||||
proc loop(facet: Facet; ds: Cap; sock: AsyncConn[sockets.Protocol.Unix]) {.asyncio.} =
|
||||
proc loop(relay: MessageRelay; ) {.asyncio.} =
|
||||
let buf = new string
|
||||
buf[].setLen(16 shl 10)
|
||||
while true:
|
||||
let n = read(sock, buf)
|
||||
if n < 1: stopActor(facet)
|
||||
let n = relay.sock.read(buf)
|
||||
if n < 1: stopActor(relay.facet)
|
||||
else:
|
||||
proc act(turn: var Turn) =
|
||||
sendMessage(turn, ds, buf[], n)
|
||||
run(facet, act)
|
||||
proc act(turn: Turn) =
|
||||
relay.sendMessage(turn, buf[], n)
|
||||
relay.facet.run(act)
|
||||
|
||||
runActor("uevent_dump") do (turn: var Turn):
|
||||
let sock = openUeventSocketAsync()
|
||||
onStop(turn) do (turn: var Turn):
|
||||
close(sock)
|
||||
resolveEnvironment(turn) do (turn: var Turn; ds: Cap):
|
||||
discard trampoline:
|
||||
whelp loop(turn.facet, ds, sock)
|
||||
proc observeOnly: Caveat =
|
||||
"""<reject <not <rec Observe [<_> <_>]>>>""".parsePreserves.preservesTo(Caveat).get
|
||||
|
||||
proc newMessageRelay(turn: Turn): MessageRelay =
|
||||
new result
|
||||
result.sock = openUeventSocketAsync()
|
||||
result.facet = turn.facet
|
||||
result.dataspace = turn.newDataspace()
|
||||
result.attenuation = result.dataspace.attenuate observeOnly()
|
||||
discard trampoline:
|
||||
whelp result.loop()
|
||||
# Start reading from the socket.
|
||||
|
||||
proc spawnUdevDumpActor*(turn: Turn; gatekeeper: Cap): Actor {.discardable.} =
|
||||
during(turn, gatekeeper, Resolve?:{ 0: UventDumpStep.matchType }) do:
|
||||
# At least one subscriber asserted.
|
||||
let relay = turn.newMessageRelay()
|
||||
during(turn, gatekeeper, Resolve?:{ 0: UventDumpStep.matchType, 1: grab() }) do (observer: Cap):
|
||||
publish(turn, observer, ResolvedAccepted(responderSession: relay.attenuation))
|
||||
do:
|
||||
relay.sock.close()
|
||||
# All subscribers retracted.
|
||||
|
||||
when isMainModule:
|
||||
import syndicate/relays
|
||||
runActor("main") do (turn: Turn):
|
||||
resolveEnvironment(turn) do (turn: Turn; gatekeeper: Cap):
|
||||
spawnUdevDumpActor(turn, gatekeeper)
|
||||
|
|
|
@ -1,13 +1,61 @@
|
|||
# Package
|
||||
# Emulate Nimble from CycloneDX data at sbom.json.
|
||||
|
||||
version = "20240315"
|
||||
author = "Emery Hemingway"
|
||||
description = "Syndicate utilties for Linux."
|
||||
license = "Unlicense"
|
||||
srcDir = "src"
|
||||
bin = @["uevent_dump"]
|
||||
import std/json
|
||||
|
||||
proc lookupComponent(sbom: JsonNode; bomRef: string): JsonNode =
|
||||
for c in sbom{"components"}.getElems.items:
|
||||
if c{"bom-ref"}.getStr == bomRef:
|
||||
return c
|
||||
result = newJNull()
|
||||
|
||||
# Dependencies
|
||||
let
|
||||
sbom = (getPkgDir() & "/sbom.json").readFile.parseJson
|
||||
comp = sbom{"metadata", "component"}
|
||||
bomRef = comp{"bom-ref"}.getStr
|
||||
|
||||
requires "nim >= 1.6.12", "syndicate >= 20240208", "https://github.com/ehmry/nim-sys.git#b974e1a4ca6ae7d89fc9e7b3714b1e7daf6f33e5", "https://github.com/nim-works/cps"
|
||||
version = comp{"version"}.getStr
|
||||
author = comp{"authors"}[0]{"name"}.getStr
|
||||
description = comp{"description"}.getStr
|
||||
license = comp{"licenses"}[0]{"license", "id"}.getStr
|
||||
|
||||
for prop in comp{"properties"}.getElems.items:
|
||||
let (key, val) = (prop{"name"}.getStr, prop{"value"}.getStr)
|
||||
case key
|
||||
of "nim:skipDirs:":
|
||||
add(skipDirs, val)
|
||||
of "nim:skipFiles:":
|
||||
add(skipFiles, val)
|
||||
of "nim:skipExt":
|
||||
add(skipExt, val)
|
||||
of "nim:installDirs":
|
||||
add(installDirs, val)
|
||||
of "nim:installFiles":
|
||||
add(installFiles, val)
|
||||
of "nim:installExt":
|
||||
add(installExt, val)
|
||||
of "nim:binDir":
|
||||
add(binDir, val)
|
||||
of "nim:srcDir":
|
||||
add(srcDir, val)
|
||||
of "nim:backend":
|
||||
add(backend, val)
|
||||
else:
|
||||
if key.startsWith "nim:bin:":
|
||||
namedBin[key[8..key.high]] = val
|
||||
|
||||
for depend in sbom{"dependencies"}.items:
|
||||
if depend{"ref"}.getStr == bomRef:
|
||||
for depRef in depend{"dependsOn"}.items:
|
||||
let dep = sbom.lookupComponent(depRef.getStr)
|
||||
var spec = dep{"name"}.getStr
|
||||
for extRef in dep{"externalReferences"}.elems:
|
||||
if extRef{"type"}.getStr == "vcs":
|
||||
spec = extRef{"url"}.getStr
|
||||
break
|
||||
let ver = dep{"version"}.getStr
|
||||
if ver != "":
|
||||
if ver.allCharsInSet {'0'..'9', '.'}: spec.add " == "
|
||||
else: spec.add '#'
|
||||
spec.add ver
|
||||
requires spec
|
||||
break
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
version 1.
|
||||
|
||||
Uevent = <uvent @subsystem string @devpath string @action string @attrs {symbol: string ...:...} @seqnum int> .
|
8
uevents.prs
Normal file
8
uevents.prs
Normal file
|
@ -0,0 +1,8 @@
|
|||
version 1.
|
||||
|
||||
# Message type.
|
||||
Uevent = <uvent @subsystem string @devpath string @action string @attrs {symbol: string ...:...} @seqnum int> .
|
||||
|
||||
# Gatekeeper step for subscribing to uvent messages.
|
||||
# Stepping with <uevent-dump { }> is also fine.
|
||||
UventDumpStep = <uevent-dump> .
|
Loading…
Reference in a new issue