├── .clang-check ├── .clang-format ├── .csmock-kfp.js ├── .github └── workflows │ ├── codeql.yml │ ├── coverity.yml │ ├── csmock.yml │ ├── reuse.yml │ └── tests.yml ├── .gitignore ├── .packit.yaml ├── AUTHORS ├── ChangeLog ├── INSTALL ├── LICENSES ├── BSD-3-Clause.txt ├── CC0-1.0.txt ├── FSFAP-no-warranty-disclaimer.txt ├── FSFAP.txt └── GPL-2.0-or-later.txt ├── Makefile.am ├── Makefile.common ├── NEWS ├── README.md ├── REUSE.toml ├── autogen.sh ├── configure.ac ├── debug ├── aliases.sh ├── clang-check ├── gdbinit ├── scan-build.args ├── valgrind.supp └── vimrc ├── m4 ├── as-ac-expand.m4 └── libcmocka.m4 ├── man ├── Makefile.am └── sid.8.in ├── rpm └── sid.spec ├── src ├── Makefile.am ├── base │ ├── Makefile.am │ ├── buf-type-linear.c │ ├── buf-type-vector.c │ ├── buf.c │ ├── comms.c │ ├── conv-base64.c │ └── util.c ├── daemon │ ├── Makefile.am │ └── sid.c ├── iface │ ├── Makefile.am │ ├── ifc.c │ └── srv-lnk.c ├── include │ ├── base │ │ ├── buf-common.h │ │ ├── buf-type.h │ │ ├── buf.h │ │ ├── comms.h │ │ ├── conv-base64.h │ │ ├── conv.h │ │ └── util.h │ ├── iface │ │ ├── ifc-internal.h │ │ ├── ifc.h │ │ └── srv-lnk.h │ ├── internal │ │ ├── bmp.h │ │ ├── bptree.h │ │ ├── common.h │ │ ├── comp-attrs.h │ │ ├── fmt.h │ │ ├── hash.h │ │ ├── list.h │ │ ├── mem.h │ │ └── util.h │ ├── log │ │ └── log.h │ └── resource │ │ ├── kvs.h │ │ ├── mod-reg.h │ │ ├── mod.h │ │ ├── res-type-regs.h │ │ ├── res.h │ │ ├── ubr.h │ │ ├── ucmd-mod.h │ │ └── wrk-ctl.h ├── internal │ ├── Makefile.am │ ├── bmp.c │ ├── bptree.c │ ├── fmt.c │ ├── hash.c │ ├── list.c │ ├── mem.c │ └── util.c ├── log │ ├── Makefile.am │ ├── log-target-journal.c │ ├── log-target-standard.c │ ├── log-target-syslog.c │ └── log.c ├── modules │ ├── Makefile.am │ └── ucmd │ │ ├── Makefile.am │ │ ├── block │ │ ├── Makefile.am │ │ ├── blkid │ │ │ ├── Makefile.am │ │ │ ├── blkid-key-mapper.gperf │ │ │ ├── blkid-key.h │ │ │ ├── blkid-type-mapper.gperf │ │ │ ├── blkid-type.h │ │ │ └── blkid.c │ │ ├── dm_mpath │ │ │ ├── Makefile.am │ │ │ └── dm_mpath.c │ │ └── dummy_block │ │ │ ├── Makefile.am │ │ │ └── dummy_block.c │ │ └── type │ │ ├── Makefile.am │ │ ├── dm │ │ ├── Makefile.am │ │ ├── dm.c │ │ ├── dm.h │ │ └── lvm │ │ │ ├── Makefile.am │ │ │ └── lvm.c │ │ └── dummy_type │ │ ├── Makefile.am │ │ └── dummy_type.c ├── resource │ ├── Makefile.am │ ├── aggr.c │ ├── kvs.c │ ├── mod-reg.c │ ├── res.c │ ├── sid.c │ ├── ubr.c │ └── wrk-ctl.c └── tools │ ├── Makefile.am │ ├── sidctl │ ├── Makefile.am │ └── sidctl.c │ └── usid │ ├── Makefile.am │ └── usid.c ├── systemd ├── Makefile.am ├── sid.service.in ├── sid.socket.in └── sid.sysconfig.in ├── tests ├── .gitignore ├── Makefile.am ├── test_bitmap.c ├── test_bptree.c ├── test_buffer.c ├── test_db_sync.c ├── test_hash.c ├── test_iface.c ├── test_internal.c ├── test_kv_store.c └── test_notify.c └── udev ├── 00-sid.rules └── Makefile.am /.clang-check: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | -Isrc/include 8 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | --- 8 | Language: Cpp 9 | AccessModifierOffset: -2 10 | AlignAfterOpenBracket: Align 11 | AlignArrayOfStructures: None 12 | AlignConsecutiveAssignments: 13 | Enabled: true 14 | AcrossEmptyLines: true 15 | AcrossComments: true 16 | AlignCompound: true 17 | PadOperators: true 18 | AlignConsecutiveBitFields: 19 | Enabled: true 20 | AcrossEmptyLines: true 21 | AcrossComments: true 22 | AlignConsecutiveDeclarations: 23 | Enabled: true 24 | AcrossEmptyLines: false 25 | AcrossComments: false 26 | AlignConsecutiveMacros: 27 | Enabled: true 28 | AcrossEmptyLines: true 29 | AcrossComments: true 30 | AlignEscapedNewlines: Right 31 | AlignOperands: Align 32 | AlignTrailingComments: true 33 | AllowAllArgumentsOnNextLine: false 34 | AllowAllConstructorInitializersOnNextLine: false 35 | AllowAllParametersOfDeclarationOnNextLine: false 36 | AllowShortBlocksOnASingleLine: Never 37 | AllowShortCaseLabelsOnASingleLine: false 38 | AllowShortEnumsOnASingleLine: false 39 | AllowShortFunctionsOnASingleLine: None 40 | AllowShortIfStatementsOnASingleLine: Never 41 | AllowShortLambdasOnASingleLine: All 42 | AllowShortLoopsOnASingleLine: false 43 | AlwaysBreakAfterReturnType: None 44 | AlwaysBreakAfterDefinitionReturnType: None 45 | AlwaysBreakBeforeMultilineStrings: false 46 | AlwaysBreakTemplateDeclarations: MultiLine 47 | BinPackArguments: false 48 | BinPackParameters: false 49 | BitFieldColonSpacing: None 50 | BreakAfterJavaFieldAnnotations: false 51 | BreakBeforeBinaryOperators: None 52 | BreakBeforeBraces: Linux 53 | BreakBeforeConceptDeclarations: Never 54 | BreakBeforeTernaryOperators: true 55 | BreakConstructorInitializers: BeforeColon 56 | BreakInheritanceList: BeforeColon 57 | BreakStringLiterals: true 58 | ColumnLimit: 132 59 | CompactNamespaces: false 60 | ConstructorInitializerIndentWidth: 8 61 | ContinuationIndentWidth: 8 62 | Cpp11BracedListStyle: true 63 | DeriveLineEnding: true 64 | DerivePointerAlignment: false 65 | DisableFormat: false 66 | EmptyLineAfterAccessModifier: Never 67 | EmptyLineBeforeAccessModifier: Always 68 | ExperimentalAutoDetectBinPacking: false 69 | FixNamespaceComments: true 70 | ForEachMacros: 71 | - list_iterate 72 | - list_iterate_back 73 | - list_iterate_items_gen 74 | - list_iterate_items 75 | - list_iterate_items_gen_back 76 | - list_iterate_items_back 77 | - list_iterate_items_gen_safe 78 | - list_iterate_items_safe 79 | - list_iterate_items_gen_safe_back 80 | - list_iterate_items_safe_back 81 | IncludeBlocks: Regroup 82 | IncludeCategories: 83 | - Regex: '^"config.h"' 84 | Priority: -3 85 | - Regex: '^"internal/comp-attrs.h"' 86 | Priority: -2 87 | - Regex: '^"internal/common.h"' 88 | Priority: -1 89 | - Regex: '^".*"' 90 | Priority: 1 91 | - Regex: '^' 92 | Priority: 3 93 | - Regex: '^<.*>' 94 | Priority: 2 95 | IndentAccessModifiers: false 96 | IndentCaseBlocks: false 97 | IndentCaseLabels: true 98 | IndentExternBlock: NoIndent 99 | IndentGotoLabels: false 100 | IndentPPDirectives: BeforeHash 101 | IndentRequiresClause: false 102 | IndentWidth: 8 103 | IndentWrappedFunctionNames: true 104 | InsertBraces: false 105 | InsertTrailingCommas: Wrapped 106 | JavaScriptQuotes: Leave 107 | JavaScriptWrapImports: true 108 | KeepEmptyLinesAtTheStartOfBlocks: false 109 | LambdaBodyIndentation: Signature 110 | MaxEmptyLinesToKeep: 1 111 | NamespaceIndentation: None 112 | ObjCBinPackProtocolList: Auto 113 | ObjCBlockIndentWidth: 2 114 | ObjCBreakBeforeNestedBlockParam: true 115 | ObjCSpaceAfterProperty: false 116 | ObjCSpaceBeforeProtocolList: true 117 | PPIndentWidth: 8 118 | PackConstructorInitializers: Never 119 | PenaltyBreakAssignment: 2 120 | PenaltyBreakBeforeFirstCallParameter: 19 121 | PenaltyBreakComment: 300 122 | PenaltyBreakFirstLessLess: 120 123 | PenaltyBreakString: 1000 124 | PenaltyBreakTemplateDeclaration: 10 125 | PenaltyExcessCharacter: 1000000 126 | PenaltyReturnTypeOnItsOwnLine: 60 127 | PointerAlignment: Right 128 | QualifierAlignment: Left 129 | ReferenceAlignment: Right 130 | ReflowComments: true 131 | RequiresClausePosition: OwnLine 132 | SeparateDefinitionBlocks: Always 133 | ShortNamespaceLines: 1 134 | SortIncludes: CaseSensitive 135 | SortJavaStaticImport: Before 136 | SortUsingDeclarations: true 137 | SpaceAfterCStyleCast: true 138 | SpaceAfterLogicalNot: false 139 | SpaceAfterTemplateKeyword: true 140 | SpaceAroundPointerQualifiers: Both 141 | SpaceBeforeAssignmentOperators: true 142 | SpaceBeforeCaseColon: false 143 | SpaceBeforeCpp11BracedList: true 144 | SpaceBeforeCtorInitializerColon: false 145 | SpaceBeforeInheritanceColon: false 146 | SpaceBeforeParens: ControlStatements 147 | SpaceBeforeRangeBasedForLoopColon: true 148 | SpaceBeforeSquareBrackets: false 149 | SpaceInEmptyBlock: true 150 | SpaceInEmptyParentheses: false 151 | SpacesBeforeTrailingComments: 1 152 | SpacesInAngles: false 153 | SpacesInCStyleCastParentheses: false 154 | SpacesInConditionalStatement: false 155 | SpacesInContainerLiterals: false 156 | SpacesInParentheses: false 157 | SpacesInSquareBrackets: false 158 | Standard: Latest 159 | TabWidth: 8 160 | UseCRLF: false 161 | UseTab: AlignWithSpaces 162 | --- 163 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | name: CodeQL analysis 8 | 9 | on: 10 | push: 11 | branches: [ "main" ] 12 | pull_request: 13 | branches: [ "main" ] 14 | schedule: 15 | - cron: '43 13 * * 3' 16 | workflow_dispatch: 17 | 18 | jobs: 19 | analyze: 20 | name: Analyze 21 | runs-on: 'ubuntu-latest' 22 | permissions: 23 | actions: read 24 | contents: read 25 | security-events: write 26 | 27 | strategy: 28 | fail-fast: false 29 | matrix: 30 | language: [ 'cpp' ] 31 | 32 | steps: 33 | - name: Checkout repository 34 | uses: actions/checkout@v4 35 | 36 | # Initializes the CodeQL tools for scanning. 37 | - name: Initialize CodeQL 38 | uses: github/codeql-action/init@v3 39 | with: 40 | languages: ${{ matrix.language }} 41 | 42 | - name: Install build dependencies 43 | run: | 44 | sudo apt -qq update 45 | sudo apt -y -qq install build-essential autoconf-archive gperf libxen-dev libsystemd-dev libudev-dev libblkid-dev libcmocka-dev 46 | 47 | - name: Build 48 | run: | 49 | ./autogen.sh && ./configure --disable-mod-block-dm_mpath && make -j 50 | 51 | - name: Perform CodeQL Analysis 52 | uses: github/codeql-action/analyze@v3 53 | with: 54 | category: "/language:${{matrix.language}}" 55 | -------------------------------------------------------------------------------- /.github/workflows/coverity.yml: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | name: Coverity scan 8 | 9 | on: 10 | schedule: 11 | - cron: '0 0 * * 0' 12 | workflow_dispatch: 13 | 14 | jobs: 15 | build: 16 | 17 | runs-on: ubuntu-latest 18 | 19 | env: 20 | COV_PROJECT_NAME: sid-project/sid 21 | COV_TOKEN: ${{ secrets.COV_TOKEN }} 22 | COV_EMAIL: ${{ secrets.COV_EMAIL }} 23 | COV_TOOLS_URL: https://scan.coverity.com/download/linux64 24 | COV_TOOLS_TGZ: cov-tools.tar.gz 25 | COV_TOOLS_DIR: cov-tools 26 | COV_RESULTS_DIR: cov-int 27 | COV_SUBMIT_URL: https://scan.coverity.com/builds 28 | 29 | steps: 30 | - name: Checkout the repository 31 | uses: actions/checkout@v4 32 | 33 | - name: Install build dependencies 34 | run: | 35 | sudo apt -qq update 36 | sudo apt -y -qq install build-essential autoconf-archive gperf libxen-dev libsystemd-dev libudev-dev libblkid-dev libcmocka-dev 37 | 38 | - name: Configure 39 | run: | 40 | ./autogen.sh && ./configure --disable-mod-block-dm_mpath 41 | 42 | - name: Download Coverity 43 | run: | 44 | wget -nv -O "$COV_TOOLS_TGZ" --post-data "project=$COV_PROJECT_NAME&token=$COV_TOKEN" "$COV_TOOLS_URL" 45 | mkdir "$COV_TOOLS_DIR" 46 | tar xzf "$COV_TOOLS_TGZ" --strip 1 -C "$COV_TOOLS_DIR" 47 | 48 | - name: Build 49 | run: | 50 | export PATH="$(pwd)/$COV_TOOLS_DIR/bin:$PATH" 51 | cov-build --dir "$COV_RESULTS_DIR" make -j 52 | sed -i '/COV_TOKEN=/d' "$COV_RESULTS_DIR/build-log.txt" 53 | sed -i '/COV_EMAIL=/d' "$COV_RESULTS_DIR/build-log.txt" 54 | 55 | - name: Upload the build log 56 | uses: actions/upload-artifact@v4 57 | with: 58 | name: build-log 59 | path: cov-int/build-log.txt 60 | 61 | - name: Submit results 62 | run: | 63 | tar -czf sid.tgz "$COV_RESULTS_DIR" 64 | git config --global --add safe.directory "$GITHUB_WORKSPACE" 65 | GIT_HEAD_HASH="$(git rev-parse HEAD)" 66 | curl --fail --output curl.log \ 67 | --form project="$COV_PROJECT_NAME" \ 68 | --form token="$COV_TOKEN" \ 69 | --form email="$COV_EMAIL" \ 70 | --form file=@sid.tgz \ 71 | --form version="$GIT_HEAD_HASH" \ 72 | --form description="Github Coverity Scan Workflow" \ 73 | "$COV_SUBMIT_URL" 74 | -------------------------------------------------------------------------------- /.github/workflows/csmock.yml: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | name: csmock static analysis 8 | 9 | on: 10 | pull_request: 11 | branches: 12 | - main 13 | push: 14 | branches: 15 | - main 16 | workflow_dispatch: 17 | 18 | jobs: 19 | build: 20 | 21 | runs-on: ubuntu-22.04 22 | 23 | env: 24 | CI_IMAGE: fedora:latest 25 | CI_CONTAINER: sid-fedora-latest 26 | 27 | CSMOCK_CHROOTS: "default" 28 | CSMOCK_TOOLS: "clang,cppcheck,gcc" 29 | 30 | steps: 31 | - name: Checkout the repository 32 | uses: actions/checkout@v4 33 | 34 | - name: Install podman 35 | run: | 36 | sudo apt -qq update 37 | sudo apt -y -qq install podman 38 | 39 | - name: Start the container 40 | run: | 41 | podman run -d -t --name ${{ env.CI_CONTAINER }} --privileged --volume "$(pwd):/app" --workdir "/app" ${{ env.CI_IMAGE }} 42 | 43 | - name: Enable Copr with latest csmock 44 | run: | 45 | podman exec -it ${{ env.CI_CONTAINER }} bash -c "dnf -y install dnf-plugins-core && dnf -y copr enable @codescan/csutils" 46 | 47 | - name: Install rpmbuild and csmock 48 | run: | 49 | podman exec -it ${{ env.CI_CONTAINER }} bash -c "dnf -y install rpm-build csmock" 50 | 51 | - name: Install SID build dependencies in the container 52 | run: | 53 | podman exec -it ${{ env.CI_CONTAINER }} bash -c "dnf -y install dnf-plugins-core && dnf -y builddep rpm/sid.spec" 54 | 55 | - name: Build SID in the container and create tarball 56 | run: | 57 | podman exec -it ${{ env.CI_CONTAINER }} bash -c "./autogen.sh && ./configure && make -j && make dist" 58 | 59 | - name: Build the SRPM 60 | run: podman exec -it ${{ env.CI_CONTAINER }} bash -c "rpmbuild -bs --define '_sourcedir .' rpm/sid.spec" 61 | 62 | - name: Run csmock 63 | run: podman exec -it ${{ env.CI_CONTAINER }} bash -c "csmock --known-false-positives .csmock-kfp.js --cppcheck-add-flag='--check-level=exhaustive' -o sid-csmock-results.tar.xz -r ${{ env.CSMOCK_CHROOTS }} --tools ${{ env.CSMOCK_TOOLS }} ~/rpmbuild/SRPMS/sid*.src.rpm" 64 | 65 | - name: Check csmock results 66 | run: podman exec -it ${{ env.CI_CONTAINER }} bash -c "tar -xf sid-csmock-results.tar.xz && test -s sid-csmock-results/scan-results-summary.txt && exit 1 || exit 0" 67 | 68 | - name: Upload the test csmock logs 69 | if: always() 70 | uses: actions/upload-artifact@v4 71 | with: 72 | name: csmock_logs 73 | path: sid-csmock-results/* 74 | -------------------------------------------------------------------------------- /.github/workflows/reuse.yml: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | name: License check 8 | 9 | on: 10 | pull_request: 11 | branches: 12 | - main 13 | push: 14 | branches: 15 | - main 16 | workflow_dispatch: 17 | 18 | jobs: 19 | build: 20 | 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - name: Checkout the repository 25 | uses: actions/checkout@v4 26 | 27 | - name: REUSE license check 28 | uses: fsfe/reuse-action@v4 29 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | name: Unit tests 8 | 9 | on: 10 | pull_request: 11 | branches: 12 | - main 13 | push: 14 | branches: 15 | - main 16 | workflow_dispatch: 17 | 18 | jobs: 19 | build: 20 | 21 | runs-on: ubuntu-latest 22 | 23 | env: 24 | CI_IMAGE: fedora:latest 25 | CI_CONTAINER: sid-fedora-latest 26 | 27 | steps: 28 | - name: Checkout the repository 29 | uses: actions/checkout@v4 30 | 31 | - name: Install podman 32 | run: | 33 | sudo apt -qq update 34 | sudo apt -y -qq install podman 35 | 36 | - name: Start the container 37 | run: | 38 | podman run -d -t --name ${{ env.CI_CONTAINER }} --privileged --volume "$(pwd):/app" --workdir "/app" ${{ env.CI_IMAGE }} 39 | 40 | - name: Install SID build dependencies in the container 41 | run: | 42 | podman exec -it ${{ env.CI_CONTAINER }} bash -c "dnf -y install dnf-plugins-core && dnf -y builddep rpm/sid.spec" 43 | 44 | - name: Install SID test dependencies in the container 45 | run: | 46 | podman exec -it ${{ env.CI_CONTAINER }} bash -c "dnf -y install libcmocka-devel libcmocka" 47 | 48 | - name: Build SID in the container 49 | run: | 50 | podman exec -it ${{ env.CI_CONTAINER }} bash -c "./autogen.sh && ./configure && make -j" 51 | 52 | - name: Run tests 53 | run: podman exec -it ${{ env.CI_CONTAINER }} bash -c "./autogen.sh && ./configure && make check" 54 | 55 | - name: Upload the test suite logs 56 | if: always() 57 | uses: actions/upload-artifact@v4 58 | with: 59 | name: test_logs 60 | path: tests/test-suite.log 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /autoconf 2 | /aclocal.m4 3 | /autom4te.cache 4 | /configure 5 | /config.status 6 | /config.log 7 | /autoscan.log 8 | /configure.scan 9 | **/.deps 10 | **/.libs 11 | 12 | src/include/stamp-h1 13 | src/include/config.h.in 14 | src/include/config.h 15 | 16 | **/am--include-marker 17 | **/\# 18 | 19 | m4/lt*.m4 20 | m4/libtool.m4 21 | 22 | **/Makefile 23 | **/Makefile.in 24 | 25 | /cscope.in.out 26 | /cscope.out 27 | /cscope.po.out 28 | /tags 29 | 30 | **/*.o 31 | **/*.lo 32 | **/*.la 33 | **/*.a 34 | **/*~ 35 | 36 | src/daemon/sid 37 | src/modules/ucmd/block/blkid/blkid-type-mapper.c 38 | src/modules/ucmd/block/blkid/blkid-key-mapper.c 39 | src/tools/usid/usid 40 | src/tools/sidctl/sidctl 41 | systemd/sid.service 42 | systemd/sid.socket 43 | systemd/sid.sysconfig 44 | man/sid.8 45 | udev/00-sid.rules 46 | 47 | libtool 48 | 49 | .gdbinit 50 | .valgrind.supp 51 | 52 | .mk.log 53 | 54 | *.swp 55 | 56 | .vscode/ 57 | .cache/ 58 | 59 | /compile_commands.json 60 | /cov-int 61 | -------------------------------------------------------------------------------- /.packit.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | actions: 8 | post-upstream-clone: 9 | - './autogen.sh' 10 | - './configure' 11 | create-archive: 12 | - 'make' 13 | - 'make dist' 14 | - 'bash -c "ls *.tar*"' 15 | get-current-version: 16 | - 'bash -c "./configure --version | head -n1 | cut -f3 -d\" \""' 17 | 18 | jobs: 19 | - job: copr_build 20 | metadata: 21 | targets: 22 | - fedora-rawhide-aarch64 23 | - fedora-rawhide-ppc64le 24 | - fedora-rawhide-x86_64 25 | - fedora-latest-aarch64 26 | - fedora-latest-ppc64le 27 | - fedora-latest-x86_64 28 | - fedora-latest-stable-aarch64 29 | - fedora-latest-stable-ppc64le 30 | - fedora-latest-stable-x86_64 31 | trigger: pull_request 32 | 33 | - job: copr_build 34 | trigger: commit 35 | owner: "@storage" 36 | project: sid-daily 37 | branch: main 38 | preserve_project: true 39 | 40 | srpm_build_deps: 41 | - make 42 | - gcc 43 | - libtool 44 | - autoconf 45 | - autoconf-archive 46 | - automake 47 | - gperf 48 | - libtool 49 | - multilib-rpm-config 50 | - gcc 51 | - systemd-rpm-macros 52 | - systemd-devel 53 | - libudev-devel 54 | - libuuid-devel 55 | - libblkid-devel 56 | - device-mapper-multipath-devel 57 | 58 | downstream_package_name: sid 59 | specfile_path: rpm/sid.spec 60 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | MAINTAINER: 2 | 3 | Peter Rajnoha 4 | 5 | CONTRIBUTORS: 6 | 7 | Benjamin Marzinski 8 | Gennadii Altukhov 9 | Todd Gill 10 | Vojtech Trefny 11 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sid-project/sid/7ae0254ea16ad5b2c8ac049404fa43e2915957e2/ChangeLog -------------------------------------------------------------------------------- /LICENSES/BSD-3-Clause.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) . 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | -------------------------------------------------------------------------------- /LICENSES/CC0-1.0.txt: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /LICENSES/FSFAP-no-warranty-disclaimer.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2008 Micah J. Cowan 2 | 3 | Copying and distribution of this file, with or without modification, 4 | are permitted in any medium without royalty provided the copyright 5 | notice and this notice are preserved. 6 | -------------------------------------------------------------------------------- /LICENSES/FSFAP.txt: -------------------------------------------------------------------------------- 1 | Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty. 2 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | ACLOCAL_AMFLAGS = -I m4 8 | SUBDIRS = src udev systemd man . tests 9 | 10 | EXTRA_DIST = LICENSES 11 | -------------------------------------------------------------------------------- /Makefile.common: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | AM_CPPFLAGS = -I$(top_srcdir)/src/include -include $(CONFIG_HEADER) 8 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sid-project/sid/7ae0254ea16ad5b2c8ac049404fa43e2915957e2/NEWS -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Storage Instantiation Daemon 3 | 4 | Storage Instantiation Daemon (SID) is a project that aims to help with 5 | Linux storage device state tracking that encompasses device layers, 6 | groups and whole stacks by monitoring progression of events. Based on 7 | monitored states and further recorded information, it is able to trigger 8 | associated actions for well-defined triggers, including activation and 9 | deactivation of devices and their layers in the stack. 10 | 11 | SID positions itself on top of *udev*, reacting to *uevents*. It is 12 | closely interlinked and cooperating with *udev daemon*. The udev daemon 13 | is enhanced with specialized *sid* udev builtin command that is used to 14 | communicate with SID. SID also listens to *udev uevents* issued by udev 15 | daemon which in turn triggers further processing. 16 | 17 | At its core, SID provides an *infrastructure* and an *API* for various 18 | device subsystems to create *modules* that handle specific device types 19 | and their abstractions. For this purpose, it organizes overall uevent 20 | processing into *discrete and controlled steps* and, through an API, it 21 | provides access to its own *SID database* for use within core parts as 22 | well as modules to store and retrieve extended information besides udev 23 | daemon’s database capabilities. 24 | 25 | The SID database contains both *internal* and *general-purpose records*. 26 | The internal records are accessed only through dedicated API calls which 27 | are used to track and support device dependencies, grouping, triggers 28 | and associated actions. The general-purpose records can be stored and 29 | retrieved by modules directly with a possibility to define their *key 30 | components*, *scope of visibility* and *access type*. 31 | 32 | Since SID keeps track of the overall storage device stack and grouping, 33 | it provides an insight into the stack, the device and group dependencies 34 | and it is able to notify when there are changes to certain parts of the 35 | device stack to which there needs to be an appropriate action executed 36 | either inside (using SID’s triggers and associated actions) or outside 37 | SID itself (using *extended notifications* that SID sends out). 38 | -------------------------------------------------------------------------------- /REUSE.toml: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: CC0-1.0 5 | # 6 | 7 | version = 1 8 | 9 | [[annotations]] 10 | path = [".csmock-kfp.js", ".gitignore", "AUTHORS", "README.md", "tests/.gitignore"] 11 | SPDX-FileCopyrightText = "2017-2025 Red Hat, Inc." 12 | SPDX-License-Identifier = "CC0-1.0" 13 | 14 | [[annotations]] 15 | path = ["INSTALL"] 16 | SPDX-FileCopyrightText = "1994-1996, 1999-2002, 2004-2016 Free Software Foundation, Inc." 17 | SPDX-License-Identifier = "FSFAP" 18 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 5 | # 6 | # SPDX-License-Identifier: GPL-2.0-or-later 7 | # 8 | 9 | DIE=0 10 | 11 | (autoreconf --version) > /dev/null 2>&1 || { 12 | echo 13 | echo "Autoreconf utility not found." 14 | echo "The autoreconf utility is part of autoconf package." 15 | echo 16 | DIE=1 17 | } 18 | 19 | (automake --version) > /dev/null 2>&1 || { 20 | echo 21 | echo "Automake utility not found." 22 | DIE=1 23 | } 24 | 25 | test "$DIE" -eq "1" && exit 1 26 | 27 | echo 28 | echo "Updating configuration files..." 29 | 30 | autoreconf --force --install 31 | 32 | echo 33 | echo "Now use 'configure' and 'make' to compile the source tree..." 34 | -------------------------------------------------------------------------------- /debug/aliases.sh: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | alias autogen-sid='echo -e "\n ========== AUTOGENERATING =====\n ..."; ./autogen.sh' 8 | alias configure-sid='echo -e "\n ========== CONFIGURING ========\n ..."; ./configure --disable-static --with-systemdsystemunitdir=/etc/systemd/system --with-udevrulesdir=/etc/udev/rules.d --enable-valgrind --enable-mod-block-dummy --enable-mod-type-dummy CC=clang' 9 | alias configure-sid-gcc='echo -e "\n ========== CONFIGURING ========\n ..."; ./configure --disable-static --with-systemdsystemunitdir=/etc/systemd/system --with-udevrulesdir=/etc/udev/rules.d CC=gcc' 10 | alias configure-sid-g++='echo -e "\n ========== CONFIGURING ========\n ..."; ./configure --disable-static --with-systemdsystemunitdir=/etc/systemd/system --with-udevrulesdir=/etc/udev/rules.d CC=g++' 11 | alias build-sid='echo -e "\n ========== BUILDING ===========\n ..."; make V=1 &> .mk.log; \ 12 | echo -e "\n ========== ERROR LOG ==========\n ..."; grep -E "Error [0-9]*|.*:[0-9]*:[0-9]*: error:" < .mk.log; \ 13 | echo -e "\n ========== WARNING LOG ========\n ..."; grep -E ".*:[0-9]*:[0-9]*: warning:" < .mk.log; \ 14 | echo -e "\n ========== UNDEFINED REFS =====\n"; grep -E "undefined reference to " < .mk.log; \ 15 | echo -e "\n"' 16 | alias install-sid='echo -e "\n ========== INSTALLING =========\n ..."; make install' 17 | alias reload-sid='echo -e "\n ========== RELOADING =========\n ..." \ 18 | echo -e "reloading udev rules...\n"; udevadm control -R; \ 19 | echo -e "reloading systemd daemon...\n"; systemctl daemon-reload' 20 | alias setup-sid='echo -e "\n ========== SETTING UP =========\n ..."; \ 21 | echo -e "stopping possibly running sid.service unit...\n"; systemctl stop sid sid.socket; \ 22 | echo -e "restarting sid.socket unit...\n"; systemctl restart sid.socket' 23 | alias libs-sid='echo -en "Adding /usr/local/lib/sid to LD_LIBRARY_PATH... "; if [[ $LD_LIBRARY_PATH =~ :/usr/local/lib/sid($|:) ]]; then echo "already there"; else export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/sid; echo "added"; fi' 24 | alias all-sid='autogen-sid; configure-sid; build-sid; install-sid; reload-sid; setup-sid; libs-sid' 25 | alias all-sid-nosetup='autogen-sid; configure-sid; build-sid; install-sid; reload-sid; libs-sid' 26 | alias rsid='stdbuf -o L sid -f -vv 2>&1 | ov -f' 27 | 28 | alias sid-dbdump-jq='sidctl dbdump -f json | jq -C --tab | less -r' 29 | alias sid-resources-jq='sidctl resources -f json | jq -C --tab | less -r' 30 | alias dsid='sidctl dbdump -f json | json-tui' 31 | alias ddsid='sidctl devices -f json | json-tui' 32 | -------------------------------------------------------------------------------- /debug/clang-check: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | -Isrc/include 8 | -------------------------------------------------------------------------------- /debug/gdbinit: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | set debuginfod enabled on 8 | #et prompt \033[91m(gdb) \033[0m 9 | set args -f -vv 10 | 11 | set non-stop on 12 | set detach-on-fork off 13 | set follow-fork-mode child 14 | 15 | set print frame-arguments all 16 | set print type nested-type-limit unlimited 17 | 18 | define str_vector_dump 19 | set $i = $arg1 20 | while $i < $arg2 21 | print (const char *) ((struct iovec *) $arg0)[$i].iov_base 22 | set $i = $i + 1 23 | end 24 | end 25 | 26 | document str_vector_dump 27 | Print the string elements of struct iovec. 28 | Usage: str_vector_dump 29 | end 30 | 31 | define print_gdb_env 32 | show args 33 | show follow-fork-mode 34 | show detach-on-fork 35 | end 36 | 37 | alias -a btf = backtrace -full -frame-arguments all 38 | alias -a ffmc = set follow-fork-mode child 39 | alias -a ffmp = set follow-fork-mode parent 40 | alias -a dof0 = set detach-on-fork off 41 | alias -a dof1 = set detach-on-fork on 42 | alias -a pge = print_gdb_env 43 | -------------------------------------------------------------------------------- /debug/scan-build.args: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | -enable-checker core -enable-checker apiModeling -enable-checker unix -enable-checker deadcode -enable-checker security.insecureAPI.UncheckedReturn -enable-checker security.insecureAPI.getpw -enable-checker security.insecureAPI.gets -enable-checker security.insecureAPI.mktemp -enable-checker security.insecureAPI.mkstemp -enable-checker security.insecureAPI.vfork -enable-checker nullability.NullPassedToNonnull -enable-checker nullability.NullReturnedFromNonnull -enable-checker alpha.security.ArrayBoundV2 -enable-checker alpha.unix.cstring.OutOfBounds 8 | -------------------------------------------------------------------------------- /debug/valgrind.supp: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | { 8 | 20 | Memcheck:Leak 21 | match-leak-kinds: indirect 22 | fun:malloc 23 | fun:malloc_multiply 24 | fun:prioq_new 25 | fun:prioq_ensure_allocated 26 | fun:sd_event_new 27 | fun:sid_res_create 28 | fun:main 29 | } 30 | 31 | { 32 | 33 | Memcheck:Leak 34 | match-leak-kinds: indirect 35 | fun:realloc 36 | fun:greedy_realloc 37 | fun:process_epoll 38 | fun:sd_event_wait 39 | fun:sd_event_run 40 | fun:sd_event_loop 41 | fun:sid_res_ev_loop_run 42 | fun:main 43 | } 44 | 45 | { 46 | 47 | Memcheck:Leak 48 | match-leak-kinds: indirect 49 | fun:reallocarray 50 | fun:prioq_put 51 | fun:source_set_pending 52 | fun:process_io 53 | fun:process_epoll 54 | fun:sd_event_wait 55 | fun:sd_event_run 56 | fun:sd_event_loop 57 | fun:sid_res_ev_loop_run 58 | fun:main 59 | } 60 | 61 | { 62 | 63 | Memcheck:Leak 64 | match-leak-kinds: indirect 65 | fun:realloc 66 | fun:greedy_realloc 67 | fun:process_epoll 68 | fun:sd_event_wait 69 | fun:sd_event_prepare 70 | fun:sd_event_run 71 | fun:sd_event_loop 72 | fun:sid_res_ev_loop_run 73 | fun:main 74 | } 75 | 76 | { 77 | 78 | Memcheck:Leak 79 | match-leak-kinds: indirect 80 | fun:realloc 81 | fun:resize_buckets 82 | fun:hashmap_base_put_boldly 83 | fun:hashmap_put 84 | fun:sd_event_add_child 85 | fun:sid_res_ev_create_child 86 | fun:_init_worker_proxy 87 | fun:sid_res_create 88 | fun:_do_worker_control_get_new_worker 89 | fun:sid_wrk_ctl_get_new_worker 90 | fun:_get_worker 91 | fun:_on_ubridge_interface_event 92 | } 93 | 94 | { 95 | 96 | Memcheck:Leak 97 | match-leak-kinds: indirect 98 | fun:calloc 99 | fun:hashmap_base_new 100 | fun:hashmap_base_ensure_allocated 101 | fun:_hashmap_ensure_allocated 102 | fun:sd_event_add_child 103 | fun:sid_res_ev_create_child 104 | fun:_init_worker_proxy 105 | fun:sid_res_create 106 | fun:_do_worker_control_get_new_worker 107 | fun:sid_wrk_ctl_get_new_worker 108 | fun:_get_worker 109 | fun:_on_ubridge_interface_event 110 | } 111 | -------------------------------------------------------------------------------- /debug/vimrc: -------------------------------------------------------------------------------- 1 | " 2 | " SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | " 4 | " SPDX-License-Identifier: GPL-2.0-or-later 5 | " 6 | 7 | let g:syntastic_clang_check_config_file = ".clang-check" 8 | let g:syntastic_c_checkers = ['make', 'clang_check'] 9 | 10 | let g:syntastic_always_populate_loc_list = 1 11 | let g:syntastic_auto_loc_list = 1 12 | let g:syntastic_check_on_open = 1 13 | let g:syntastic_check_on_wq = 0 14 | -------------------------------------------------------------------------------- /m4/as-ac-expand.m4: -------------------------------------------------------------------------------- 1 | dnl as-ac-expand.m4 0.2.0 -*- autoconf -*- 2 | dnl autostars m4 macro for expanding directories using configure's prefix 3 | 4 | dnl 5 | dnl SPDX-FileCopyrightText: (C) 2003, 2004, 2005 Thomas Vander Stichele 6 | dnl 7 | dnl SPDX-License-Identifier: FSFAP-no-warranty-disclaimer 8 | dnl 9 | 10 | dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR) 11 | 12 | dnl example: 13 | dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir) 14 | dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local 15 | 16 | AC_DEFUN([AS_AC_EXPAND], 17 | [ 18 | EXP_VAR=[$1] 19 | FROM_VAR=[$2] 20 | 21 | dnl first expand prefix and exec_prefix if necessary 22 | prefix_save=$prefix 23 | exec_prefix_save=$exec_prefix 24 | 25 | dnl if no prefix given, then use /usr/local, the default prefix 26 | if test "x$prefix" = "xNONE"; then 27 | prefix="$ac_default_prefix" 28 | fi 29 | dnl if no exec_prefix given, then use prefix 30 | if test "x$exec_prefix" = "xNONE"; then 31 | exec_prefix=$prefix 32 | fi 33 | 34 | full_var="$FROM_VAR" 35 | dnl loop until it doesn't change anymore 36 | while true; do 37 | new_full_var="`eval echo $full_var`" 38 | if test "x$new_full_var" = "x$full_var"; then break; fi 39 | full_var=$new_full_var 40 | done 41 | 42 | dnl clean up 43 | full_var=$new_full_var 44 | AC_SUBST([$1], "$full_var") 45 | 46 | dnl restore prefix and exec_prefix 47 | prefix=$prefix_save 48 | exec_prefix=$exec_prefix_save 49 | ]) 50 | 51 | -------------------------------------------------------------------------------- /m4/libcmocka.m4: -------------------------------------------------------------------------------- 1 | dnl 2 | dnl SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | dnl 4 | dnl SPDX-License-Identifier: FSFAP-no-warranty-disclaimer 5 | dnl 6 | 7 | dnl A macro to check presence of cmocka on the system 8 | AC_DEFUN([AM_CHECK_CMOCKA], 9 | [ 10 | PKG_CHECK_EXISTS(cmocka >= 1.0.0, 11 | [AC_CHECK_HEADERS([stdarg.h stddef.h setjmp.h], 12 | [], dnl We are only intrested in action-if-not-found 13 | [AC_MSG_WARN([Header files stdarg.h stddef.h setjmp.h are required by cmocka]) 14 | cmocka_required_headers="no" 15 | ] 16 | ) 17 | AS_IF([test x"$cmocka_required_headers" != x"no"], 18 | [PKG_CHECK_MODULES([CMOCKA], [cmocka], [have_cmocka="yes"])] 19 | )], 20 | dnl PKG_CHECK_EXISTS ACTION-IF-NOT-FOUND 21 | [AC_MSG_WARN([No libcmocka-1.0.0 or newer library found, cmocka tests will not be built])] 22 | ) 23 | AM_CONDITIONAL([HAVE_CMOCKA], [test x$have_cmocka = xyes]) 24 | ]) 25 | -------------------------------------------------------------------------------- /man/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | dist_man8_MANS = sid.8 8 | 9 | distclean-local: 10 | $(RM) $(dist_man8_MANS) 11 | -------------------------------------------------------------------------------- /man/sid.8.in: -------------------------------------------------------------------------------- 1 | .SH COPYRIGHT Copyright (C) 2020-2024 Red Hat, Inc. All rights reserved. 2 | .\" SPDX-License-Identifier: GPL-2.0-or-later 3 | .TH SID 8 "Storage Instantiation Daemon version @VERSION@" "Red Hat, Inc." 4 | . 5 | .SH NAME 6 | . 7 | sid \(em Storage Instantiation Daemon 8 | . 9 | .SH SYNOPSIS 10 | . 11 | .B sid 12 | .RB [ \-f ] 13 | .RB [ \-h ] 14 | .RB [ \-v ] 15 | .RB [ \-V ] 16 | . 17 | .SH DESCRIPTION 18 | Storage Instantiation Daemon (SID) aims to help with Linux storage 19 | device state tracking that encompasses device layers, groups and whole 20 | stacks by monitoring progression of events. Based on monitored states 21 | and further recorded information, it is able to trigger associated 22 | actions for well-defined triggers, including activation and deactivation 23 | of devices and their layers in the stack. 24 | 25 | SID positions itself on top of \fBudev\fP, reacting to udev uevents. 26 | It is closely interlinked and cooperating with udev daemon. A specialized 27 | \fBusid\fP helper command is executed in udev rules to communicate with 28 | SID daemon which in turn triggers further processing. 29 | 30 | At its core, SID provides an infrastructure and an API for various 31 | device subsystems to create modules that handle specific device types 32 | and their abstractions. For this purpose, it organizes overall uevent 33 | processing into discrete and controlled steps and, through an API, it 34 | provides access to its own SID database for use within core parts as 35 | well as modules to store and retrieve extended information besides udev 36 | daemon’s database capabilities. 37 | 38 | The SID database contains both internal and general-purpose records. 39 | The internal records are accessed only through dedicated API calls which 40 | are used to track and support device dependencies, grouping, triggers 41 | and associated actions. The general-purpose records can be stored and 42 | retrieved by modules directly with a possibility to define their key 43 | components, scope of visibility and access type. 44 | 45 | Since SID keeps track of the overall storage device stack and grouping, 46 | it provides an insight into the stack, the device and group dependencies 47 | and it is able to notify when there are changes to certain parts of the 48 | device stack to which there needs to be an appropriate action executed 49 | either inside (using SID’s triggers and associated actions) or outside 50 | SID itself (using extended notifications that SID sends out). 51 | . 52 | .SH OPTIONS 53 | .TP 54 | .BR \-f ", " \-\-foreground 55 | Run in foreground. 56 | .TP 57 | .BR \-h ", " \-\-help 58 | Display the help text. 59 | .TP 60 | .BR \-j ", " \-\-journal 61 | Log to the journal. 62 | .TP 63 | .BR \-v ", " \-\-verbose 64 | Run in verbose mode. Repeat up to 4 times to increase the level of detail 65 | of log messages. 66 | .TP 67 | .BR \-V ", " \-\-version 68 | Display version, configuration and compilation information. 69 | . 70 | .SH SEE ALSO 71 | .BR udev (7) 72 | .BR systemd-udevd (8) 73 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | SUBDIRS = base internal log iface resource daemon modules tools 8 | 9 | uninstall-hook: 10 | test -d ${DESTDIR}${pkglibdir} && rmdir ${DESTDIR}${pkglibdir} 11 | test -d ${DESTDIR}${pkgincludedir} && rmdir ${DESTDIR}${pkgincludedir} 12 | -------------------------------------------------------------------------------- /src/base/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | include $(top_srcdir)/Makefile.common 8 | 9 | pkglib_LTLIBRARIES = libsidbase.la 10 | 11 | libsidbase_la_SOURCES = buf-type-linear.c \ 12 | buf-type-vector.c \ 13 | buf.c \ 14 | comms.c \ 15 | conv-base64.c \ 16 | util.c 17 | 18 | basedir = $(pkgincludedir)/base 19 | 20 | base_HEADERS = $(top_srcdir)/src/include/base/buf-common.h \ 21 | $(top_srcdir)/src/include/base/buf-type.h \ 22 | $(top_srcdir)/src/include/base/buf.h \ 23 | $(top_srcdir)/src/include/base/comms.h \ 24 | $(top_srcdir)/src/include/base/conv-base64.h \ 25 | $(top_srcdir)/src/include/base/conv.h \ 26 | $(top_srcdir)/src/include/base/util.h 27 | 28 | libsidbase_la_LDFLAGS = -version-info 0:0:0 29 | 30 | uninstall-hook: 31 | test -d ${DESTDIR}${basedir} && rmdir ${DESTDIR}${basedir} 32 | -------------------------------------------------------------------------------- /src/base/buf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "base/buf.h" 8 | 9 | #include "base/buf-type.h" 10 | 11 | #include 12 | #include 13 | 14 | static const struct sid_buf_type *_buffer_type_registry[] = 15 | {[SID_BUF_TYPE_LINEAR] = &sid_buf_type_linear, [SID_BUF_TYPE_VECTOR] = &sid_buf_type_vector}; 16 | 17 | static bool _check_buf(struct sid_buf *buf) 18 | { 19 | struct sid_buf_stat *stat = &buf->stat; 20 | 21 | /* We are checking only limit right now so if no limit, nothing to check as well. */ 22 | if (stat->init.limit == 0) 23 | return true; 24 | 25 | return (stat->init.limit >= stat->init.size && stat->init.limit >= stat->init.alloc_step && 26 | stat->init.limit % stat->init.alloc_step == 0); 27 | } 28 | 29 | struct sid_buf *sid_buf_create(const struct sid_buf_spec *spec, const struct sid_buf_init *init, int *ret_code) 30 | { 31 | struct sid_buf *buf = NULL; 32 | int r = 0; 33 | 34 | if (!spec || !init) { 35 | r = -EINVAL; 36 | goto out; 37 | } 38 | 39 | if (!(buf = malloc(sizeof(*buf)))) { 40 | r = -ENOMEM; 41 | goto out; 42 | } 43 | 44 | buf->stat = (struct sid_buf_stat) { 45 | .spec = *spec, 46 | .init = *init, 47 | .usage = (struct sid_buf_usage) {0}, 48 | }; 49 | 50 | buf->mem = NULL; 51 | buf->fd = -1; 52 | buf->mark.set = false; 53 | buf->mark.pos = 0; 54 | 55 | if (!_check_buf(buf)) { 56 | r = -EINVAL; 57 | goto out; 58 | } 59 | 60 | if ((r = _buffer_type_registry[spec->type]->create(buf)) < 0) 61 | goto out; 62 | out: 63 | if (ret_code) 64 | *ret_code = r; 65 | if (r < 0) { 66 | free(buf); 67 | return NULL; 68 | } else 69 | return buf; 70 | } 71 | 72 | void sid_buf_destroy(struct sid_buf *buf) 73 | { 74 | (void) _buffer_type_registry[buf->stat.spec.type]->destroy(buf); 75 | free(buf); 76 | } 77 | 78 | int sid_buf_reset_init(struct sid_buf *buf, const struct sid_buf_init *init) 79 | { 80 | struct sid_buf_stat orig_stat = buf->stat; 81 | 82 | if (!init) 83 | return -EINVAL; 84 | 85 | buf->stat.init = *init; 86 | buf->mark.set = false; 87 | buf->mark.pos = 0; 88 | 89 | if (!_check_buf(buf)) { 90 | buf->stat = orig_stat; 91 | return -EINVAL; 92 | } 93 | 94 | return _buffer_type_registry[buf->stat.spec.type]->reset(buf); 95 | } 96 | 97 | int sid_buf_reset(struct sid_buf *buf) 98 | { 99 | buf->mark.set = false; 100 | buf->mark.pos = 0; 101 | 102 | return _buffer_type_registry[buf->stat.spec.type]->reset(buf); 103 | } 104 | 105 | int sid_buf_add(struct sid_buf *buf, const void *data, size_t len, const void **mem, size_t *pos) 106 | { 107 | size_t tmp_pos; 108 | int r; 109 | 110 | if (buf->mark.set) 111 | return -EBUSY; 112 | 113 | if ((r = _buffer_type_registry[buf->stat.spec.type]->add(buf, data, len, mem, &tmp_pos)) < 0) 114 | return r; 115 | 116 | if (mem) { 117 | buf->mark.set = true; 118 | buf->mark.pos = tmp_pos; 119 | } 120 | 121 | if (pos) 122 | *pos = tmp_pos; 123 | 124 | return 0; 125 | } 126 | 127 | int sid_buf_add_fmt(struct sid_buf *buf, const void **mem, size_t *pos, const char *fmt, ...) 128 | { 129 | size_t tmp_pos; 130 | va_list ap; 131 | int r; 132 | 133 | if (buf->mark.set) 134 | return -EBUSY; 135 | 136 | va_start(ap, fmt); 137 | r = _buffer_type_registry[buf->stat.spec.type]->add_fmt(buf, mem, &tmp_pos, fmt, ap); 138 | va_end(ap); 139 | 140 | if (r < 0) 141 | return r; 142 | 143 | if (mem) { 144 | buf->mark.set = true; 145 | buf->mark.pos = tmp_pos; 146 | } 147 | 148 | if (pos) 149 | *pos = tmp_pos; 150 | 151 | return 0; 152 | } 153 | 154 | int sid_buf_add_vfmt(struct sid_buf *buf, const void **mem, size_t *pos, const char *fmt, va_list ap) 155 | { 156 | size_t tmp_pos; 157 | int r; 158 | 159 | if (buf->mark.set) 160 | return -EBUSY; 161 | 162 | if ((r = _buffer_type_registry[buf->stat.spec.type]->add_fmt(buf, mem, &tmp_pos, fmt, ap)) < 0) 163 | return r; 164 | 165 | if (mem) { 166 | buf->mark.set = true; 167 | buf->mark.pos = tmp_pos; 168 | } 169 | 170 | if (pos) 171 | *pos = tmp_pos; 172 | 173 | return 0; 174 | } 175 | 176 | static int _do_sid_buf_release(struct sid_buf *buf, size_t pos, sid_buf_pos_t whence, bool rewind) 177 | { 178 | size_t count = sid_buf_count(buf); 179 | 180 | if (!count) 181 | return pos ? -ERANGE : 0; 182 | 183 | if (pos > count) 184 | return -ERANGE; 185 | 186 | if (whence == SID_BUF_POS_REL) 187 | pos = count - pos; /* translate relative to absolute */ 188 | 189 | return _buffer_type_registry[buf->stat.spec.type]->release(buf, pos, rewind); 190 | } 191 | 192 | int sid_buf_unbind(struct sid_buf *buf, size_t pos, sid_buf_pos_t whence) 193 | { 194 | return _do_sid_buf_release(buf, pos, whence, false); 195 | } 196 | 197 | int sid_buf_rewind(struct sid_buf *buf, size_t pos, sid_buf_pos_t whence) 198 | { 199 | return _do_sid_buf_release(buf, pos, whence, true); 200 | } 201 | 202 | static int _do_sid_buf_mem_release(struct sid_buf *buf, const void *mem, bool rewind) 203 | { 204 | if (!mem || mem < buf->mem) 205 | return -EINVAL; 206 | 207 | return _buffer_type_registry[buf->stat.spec.type]->release_mem(buf, mem, rewind); 208 | } 209 | 210 | int sid_buf_unbind_mem(struct sid_buf *buf, const void *mem) 211 | { 212 | return _do_sid_buf_mem_release(buf, mem, false); 213 | } 214 | 215 | int sid_buf_rewind_mem(struct sid_buf *buf, const void *mem) 216 | { 217 | return _do_sid_buf_mem_release(buf, mem, true); 218 | } 219 | 220 | bool sid_buf_is_complete(struct sid_buf *buf, int *ret_code) 221 | { 222 | return _buffer_type_registry[buf->stat.spec.type]->is_complete(buf, ret_code); 223 | } 224 | 225 | int sid_buf_get_data_from(struct sid_buf *buf, size_t pos, const void **data, size_t *data_size) 226 | { 227 | if (pos > sid_buf_count(buf)) 228 | return -ERANGE; 229 | 230 | if (!buf->mark.set || pos < buf->mark.set) { 231 | buf->mark.set = true; 232 | buf->mark.pos = pos; 233 | } 234 | 235 | return _buffer_type_registry[buf->stat.spec.type]->get_data(buf, pos, data, data_size); 236 | } 237 | 238 | int sid_buf_get_data(struct sid_buf *buf, const void **data, size_t *data_size) 239 | { 240 | return sid_buf_get_data_from(buf, 0, data, data_size); 241 | } 242 | 243 | int sid_buf_get_fd(struct sid_buf *buf) 244 | { 245 | return _buffer_type_registry[buf->stat.spec.type]->get_fd(buf); 246 | } 247 | 248 | ssize_t sid_buf_read(struct sid_buf *buf, int fd) 249 | { 250 | return _buffer_type_registry[buf->stat.spec.type]->read(buf, fd); 251 | } 252 | 253 | ssize_t sid_buf_write(struct sid_buf *buf, int fd, size_t pos) 254 | { 255 | return _buffer_type_registry[buf->stat.spec.type]->write(buf, fd, pos); 256 | } 257 | 258 | size_t sid_buf_count(struct sid_buf *buf) 259 | { 260 | return _buffer_type_registry[buf->stat.spec.type]->count(buf); 261 | } 262 | 263 | struct sid_buf_stat sid_buf_stat(struct sid_buf *buf) 264 | { 265 | return buf->stat; 266 | } 267 | 268 | int sid_buf_write_all(struct sid_buf *buf, int fd) 269 | { 270 | size_t pos; 271 | ssize_t n; 272 | 273 | if (!buf || fd < 0) 274 | return -EINVAL; 275 | 276 | for (pos = 0;; pos += n) { 277 | n = sid_buf_write(buf, fd, pos); 278 | 279 | if (n < 0) { 280 | if (n == -ENODATA) 281 | break; 282 | 283 | if (n == -EAGAIN || n == -EINTR) { 284 | n = 0; 285 | continue; 286 | } 287 | return n; 288 | } 289 | } 290 | return 0; 291 | } 292 | -------------------------------------------------------------------------------- /src/base/comms.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "base/comms.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | static void _comms_unix_addr_init(const char *path, size_t path_len, struct sockaddr_un *addr, socklen_t *addr_len) 16 | { 17 | memset(addr, 0, sizeof(*addr)); 18 | addr->sun_family = AF_UNIX; 19 | memcpy(addr->sun_path, path, path_len); 20 | *addr_len = offsetof(struct sockaddr_un, sun_path) + path_len; 21 | } 22 | 23 | int sid_comms_unix_create(const char *path, size_t path_len, int type) 24 | { 25 | int socket_fd = -1; 26 | struct sockaddr_un addr; 27 | socklen_t addr_len; 28 | int r; 29 | 30 | if (!path_len || path_len >= sizeof(addr.sun_path)) { 31 | r = -EINVAL; 32 | goto fail; 33 | } 34 | 35 | if ((socket_fd = socket(AF_UNIX, type, 0)) < 0) { 36 | r = -errno; 37 | goto fail; 38 | } 39 | 40 | _comms_unix_addr_init(path, path_len, &addr, &addr_len); 41 | 42 | if (bind(socket_fd, (struct sockaddr *) &addr, addr_len)) { 43 | r = -errno; 44 | goto fail; 45 | } 46 | 47 | if (type & (SOCK_STREAM | SOCK_SEQPACKET)) { 48 | if (listen(socket_fd, 0) < 0) { 49 | r = -errno; 50 | goto fail; 51 | } 52 | } 53 | 54 | return socket_fd; 55 | fail: 56 | if (socket_fd >= 0) 57 | (void) close(socket_fd); 58 | return r; 59 | } 60 | 61 | int sid_comms_unix_init(const char *path, size_t path_len, int type) 62 | { 63 | struct sockaddr_un addr; 64 | int socket_fd = -1; 65 | socklen_t addr_len; 66 | int r; 67 | 68 | if (!path_len || path_len >= sizeof(addr.sun_path)) { 69 | r = -EINVAL; 70 | goto fail; 71 | } 72 | 73 | if ((socket_fd = socket(AF_UNIX, type, 0)) < 0) { 74 | r = -errno; 75 | goto fail; 76 | } 77 | 78 | if (!(type & (SOCK_STREAM | SOCK_SEQPACKET))) 79 | return socket_fd; 80 | 81 | _comms_unix_addr_init(path, path_len, &addr, &addr_len); 82 | 83 | if (connect(socket_fd, (struct sockaddr *) &addr, addr_len) < 0) { 84 | r = -errno; 85 | goto fail; 86 | } 87 | 88 | return socket_fd; 89 | fail: 90 | if (socket_fd >= 0) 91 | (void) close(socket_fd); 92 | return r; 93 | } 94 | 95 | static ssize_t _do_comms_unix_send(int socket_fd, struct iovec *iov, size_t iov_len, int fd_to_send) 96 | { 97 | struct msghdr msg = {0}; 98 | struct cmsghdr *cmsg; 99 | 100 | union { 101 | char control[CMSG_SPACE(sizeof(int))]; 102 | struct cmsghdr alignment; 103 | } u = {0}; 104 | 105 | ssize_t r; 106 | 107 | msg.msg_iov = iov; 108 | msg.msg_iovlen = iov_len; 109 | 110 | if (fd_to_send > -1) { 111 | msg.msg_control = u.control; 112 | msg.msg_controllen = sizeof(u.control); 113 | cmsg = CMSG_FIRSTHDR(&msg); 114 | cmsg->cmsg_level = SOL_SOCKET; 115 | cmsg->cmsg_type = SCM_RIGHTS; 116 | cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 117 | memcpy(CMSG_DATA(cmsg), &fd_to_send, sizeof(int)); 118 | } 119 | 120 | if ((r = sendmsg(socket_fd, &msg, 0) < 0)) 121 | return -errno; 122 | else 123 | return r; 124 | } 125 | 126 | ssize_t sid_comms_unix_send(int socket_fd, void *buf, ssize_t buf_len, int fd_to_send) 127 | { 128 | struct iovec iov = {.iov_base = buf, .iov_len = buf_len}; 129 | 130 | return _do_comms_unix_send(socket_fd, &iov, 1, fd_to_send); 131 | } 132 | 133 | ssize_t sid_comms_unix_send_iovec(int socket_fd, struct iovec *iov, size_t iov_len, int fd_to_send) 134 | { 135 | return _do_comms_unix_send(socket_fd, iov, iov_len, fd_to_send); 136 | } 137 | 138 | static ssize_t _do_comms_unix_recv(int socket_fd, struct iovec *iov, size_t iov_len, int *fd_received) 139 | { 140 | struct msghdr msg = {0}; 141 | struct cmsghdr *cmsg; 142 | 143 | union { 144 | char control[CMSG_SPACE(sizeof(int))]; 145 | struct cmsghdr alignment; 146 | } u; 147 | 148 | ssize_t r; 149 | 150 | msg.msg_iov = iov; 151 | msg.msg_iovlen = iov_len; 152 | msg.msg_control = u.control; 153 | msg.msg_controllen = sizeof(u.control); 154 | 155 | *fd_received = -1; 156 | 157 | if ((r = recvmsg(socket_fd, &msg, 0)) < 0) 158 | return -errno; 159 | 160 | cmsg = CMSG_FIRSTHDR(&msg); 161 | if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int)) && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) 162 | memcpy(fd_received, CMSG_DATA(cmsg), sizeof(int)); 163 | 164 | return r; 165 | } 166 | 167 | ssize_t sid_comms_unix_recv(int socket_fd, void *buf, ssize_t buf_len, int *fd_received) 168 | { 169 | struct iovec iov = {.iov_base = buf, .iov_len = buf_len}; 170 | 171 | return _do_comms_unix_recv(socket_fd, &iov, 1, fd_received); 172 | } 173 | 174 | ssize_t sid_comms_unix_recv_iovec(int socket_fd, struct iovec *iov, size_t iov_len, int *fd_received) 175 | { 176 | return _do_comms_unix_recv(socket_fd, iov, iov_len, fd_received); 177 | } 178 | -------------------------------------------------------------------------------- /src/base/conv-base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2005-2011, Jouni Malinen 3 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | static const unsigned char base64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 13 | 14 | /** 15 | * sid_conv_base64_encoded_len - Size necessary for sid_binary_encode 16 | * @in_len: Length of the data to be encoded 17 | * Returns: output length needed to store the base64 encoded data, including 18 | * padding and NULL bytes, or 0 if the buffer overflowed. 19 | */ 20 | 21 | size_t sid_conv_base64_encoded_len(size_t in_len) 22 | { 23 | size_t out_len = 1; /* NULL termination */ 24 | 25 | if (!in_len) 26 | return out_len; 27 | out_len += ((in_len - 1) / 3 + 1) * 4; /* 4 bytes for every 3 (rounded up) */ 28 | if (out_len < in_len) 29 | return 0; 30 | return out_len; 31 | } 32 | 33 | /** 34 | * sid_conv_base64_encode - Base64 encode 35 | * @src: Data to be encoded 36 | * @in_len: Length of the data to be encoded 37 | * @dest: pre-allocated buffer to store the encoded data 38 | * @out_len: Length of the encoded data 39 | * Returns: buffer of out_len bytes of encoded data 40 | * 41 | * Returned buffer is nul terminated to make it easier to use as a C string. 42 | */ 43 | int sid_conv_base64_encode(const unsigned char *src, size_t in_len, unsigned char *dest, size_t out_len) 44 | { 45 | unsigned char *pos; 46 | const unsigned char *end, *in; 47 | size_t check_size; 48 | 49 | check_size = sid_conv_base64_encoded_len(in_len); 50 | if ((in_len && !src) || !dest || check_size == 0 || check_size > out_len) 51 | return -EINVAL; 52 | 53 | end = src + in_len; 54 | in = src; 55 | pos = dest; 56 | while (end - in >= 3) { 57 | *pos++ = base64_table[in[0] >> 2]; 58 | *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; 59 | *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)]; 60 | *pos++ = base64_table[in[2] & 0x3f]; 61 | in += 3; 62 | } 63 | 64 | if (end - in) { 65 | *pos++ = base64_table[in[0] >> 2]; 66 | if (end - in == 1) { 67 | *pos++ = base64_table[(in[0] & 0x03) << 4]; 68 | *pos++ = '='; 69 | } else { 70 | *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; 71 | *pos++ = base64_table[(in[1] & 0x0f) << 2]; 72 | } 73 | *pos++ = '='; 74 | } 75 | 76 | *pos = '\0'; 77 | return 0; 78 | } 79 | 80 | /** 81 | * sid_conv_base64_decode - Base64 decode 82 | * @src: Data to be decoded 83 | * @len: Length of the data to be decoded 84 | * @out_len: Pointer to output length variable 85 | * Returns: Allocated buffer of out_len bytes of decoded data, 86 | * or %NULL on failure 87 | * 88 | * Caller is responsible for freeing the returned buffer. 89 | */ 90 | unsigned char *sid_conv_base64_decode(const unsigned char *src, size_t len, size_t *out_len) 91 | { 92 | unsigned char dtable[256], *out, *pos, block[4], tmp; 93 | size_t i, count, olen; 94 | int pad = 0; 95 | 96 | memset(dtable, 0x80, 256); 97 | for (i = 0; i < sizeof(base64_table) - 1; i++) 98 | dtable[base64_table[i]] = (unsigned char) i; 99 | dtable['='] = 0; 100 | 101 | count = 0; 102 | for (i = 0; i < len; i++) { 103 | if (dtable[src[i]] != 0x80) 104 | count++; 105 | } 106 | 107 | if (count == 0 || count % 4) 108 | return NULL; 109 | 110 | olen = count / 4 * 3; 111 | pos = out = malloc(olen); 112 | if (out == NULL) 113 | return NULL; 114 | 115 | count = 0; 116 | for (i = 0; i < len; i++) { 117 | tmp = dtable[src[i]]; 118 | if (tmp == 0x80) 119 | continue; 120 | 121 | if (src[i] == '=') 122 | pad++; 123 | block[count] = tmp; 124 | count++; 125 | if (count == 4) { 126 | *pos++ = (block[0] << 2) | (block[1] >> 4); 127 | *pos++ = (block[1] << 4) | (block[2] >> 2); 128 | *pos++ = (block[2] << 6) | block[3]; 129 | count = 0; 130 | if (pad) { 131 | if (pad == 1) 132 | pos--; 133 | else if (pad == 2) 134 | pos -= 2; 135 | else { 136 | /* Invalid padding */ 137 | free(out); 138 | return NULL; 139 | } 140 | break; 141 | } 142 | } 143 | } 144 | 145 | *out_len = pos - out; 146 | return out; 147 | } 148 | -------------------------------------------------------------------------------- /src/base/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "base/util.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | /* 17 | * Environment-related utilities. 18 | */ 19 | 20 | int sid_util_env_get_ull(const char *key, unsigned long long min, unsigned long long max, unsigned long long *val) 21 | { 22 | unsigned long long ret; 23 | char *env_val; 24 | char *p; 25 | 26 | if (!(env_val = getenv(key))) 27 | return -ENOKEY; 28 | 29 | errno = 0; 30 | ret = strtoull(env_val, &p, 10); 31 | if (errno || !p || *p) 32 | return -EINVAL; 33 | 34 | if (min != max) 35 | if (ret < min || ret > max) 36 | return -ERANGE; 37 | 38 | *val = ret; 39 | return 0; 40 | } 41 | 42 | /* 43 | * fd-related utilites 44 | */ 45 | 46 | ssize_t sid_util_fd_read_all(int fd, void *buf, size_t len) 47 | { 48 | ssize_t n, total = 0; 49 | 50 | if (len > SSIZE_MAX) 51 | return -ERANGE; 52 | 53 | while (len) { 54 | n = read(fd, buf, len); 55 | if (n < 0) { 56 | if (errno == EINTR || errno == EAGAIN) 57 | continue; 58 | return -errno; 59 | } 60 | if (!n) 61 | return total; 62 | buf += n; 63 | total += n; 64 | len -= n; 65 | } 66 | return total; 67 | } 68 | 69 | /* 70 | * Kernel cmdline-related utilities. 71 | */ 72 | 73 | static int _get_proc_cmdline(char *buf, off_t size) 74 | { 75 | int fd, r = 0; 76 | off_t len = 0; 77 | ssize_t bytes; 78 | 79 | if (!buf || !size) 80 | return -EINVAL; 81 | 82 | fd = open("/proc/cmdline", O_RDONLY); 83 | if (fd < 0) { 84 | return (errno) ? -errno : -1; 85 | } 86 | while (len < size) { 87 | bytes = read(fd, buf + len, size - len); 88 | if (!bytes) 89 | break; 90 | if (bytes < 0) { 91 | if (errno == EINTR || errno == EAGAIN) 92 | continue; 93 | r = (errno) ? -errno : -1; 94 | goto out; 95 | } 96 | len += bytes; 97 | } 98 | out: 99 | (void) close(fd); 100 | if (r) 101 | memset(buf, 0, size); 102 | return r; 103 | } 104 | 105 | #define DELIM " \t\n" 106 | 107 | bool sid_util_kernel_get_arg(const char *arg, char **value, int *ret_code) 108 | { 109 | int r = 0; 110 | static char buf[4097]; 111 | char *ptr, *limit, *next, *val, *end; 112 | 113 | if (!arg) { 114 | r = -EINVAL; 115 | goto out; 116 | } 117 | 118 | if (buf[0] == '\0') 119 | r = _get_proc_cmdline(buf, 4096); 120 | 121 | if (r) 122 | goto out; 123 | 124 | end = buf + strlen(buf); 125 | next = buf; 126 | while (next) { 127 | while (*next && strchr(DELIM, *next)) 128 | next++; 129 | if (!*next) 130 | goto out; 131 | ptr = next; 132 | next = strpbrk(ptr, DELIM); 133 | val = strchr(ptr, '='); 134 | if (next && val >= next) 135 | val = NULL; 136 | limit = (val) ?: (next) ?: end; 137 | if (strlen(arg) != limit - ptr || strncmp(arg, ptr, limit - ptr)) 138 | continue; 139 | if (value) { 140 | if (!val) { 141 | r = -EINVAL; 142 | goto out; 143 | } 144 | limit = (next) ?: end; 145 | *value = strndup(val, limit - val); 146 | if (!*value) { 147 | r = -ENOMEM; 148 | goto out; 149 | } 150 | } 151 | r = 1; 152 | break; 153 | } 154 | 155 | out: 156 | if (ret_code) 157 | *ret_code = (r < 0) ? r : 0; 158 | return (r > 0); 159 | } 160 | 161 | /* 162 | * sysfs-related utilities 163 | */ 164 | 165 | int sid_util_sysfs_get(const char *path, char *buf, size_t buf_size, size_t *char_count) 166 | { 167 | FILE *fp; 168 | size_t len; 169 | int r = -1; 170 | 171 | if (!(fp = fopen(path, "r"))) { 172 | r = -errno; 173 | goto out; 174 | } 175 | 176 | if (!(fgets(buf, buf_size, fp))) { 177 | r = -EIO; 178 | goto out; 179 | } 180 | 181 | if ((len = strlen(buf)) && buf[len - 1] == '\n') 182 | buf[--len] = '\0'; 183 | 184 | if (char_count) 185 | *char_count = len + 1; 186 | 187 | r = 0; 188 | out: 189 | if (fp) 190 | fclose(fp); 191 | 192 | return r; 193 | } 194 | -------------------------------------------------------------------------------- /src/daemon/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | include $(top_srcdir)/Makefile.common 8 | 9 | sbin_PROGRAMS = sid 10 | 11 | sid_SOURCES = sid.c 12 | 13 | sid_LDADD = $(top_builddir)/src/resource/libsidresource.la \ 14 | $(top_builddir)/src/internal/libsidinternal.la \ 15 | $(top_builddir)/src/base/libsidbase.la \ 16 | $(top_builddir)/src/log/libsidlog.la 17 | -------------------------------------------------------------------------------- /src/iface/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | include $(top_srcdir)/Makefile.common 8 | 9 | pkglib_LTLIBRARIES = libsidiface_servicelink.la libsidiface.la 10 | 11 | ifacedir = $(pkgincludedir)/iface 12 | 13 | libsidiface_servicelink_la_SOURCES = srv-lnk.c 14 | 15 | iface_servicelinkdir = ${ifacedir} 16 | 17 | iface_servicelink_HEADERS = $(top_srcdir)/src/include/iface/srv-lnk.h 18 | 19 | libsidiface_servicelink_la_CFLAGS = $(SYSTEMD_CFLAGS) 20 | 21 | libsidiface_servicelink_la_LDFLAGS = -version-info 0:0:0 22 | 23 | libsidiface_servicelink_la_LIBADD = $(top_builddir)/src/internal/libsidinternal.la \ 24 | $(top_builddir)/src/base/libsidbase.la \ 25 | $(top_builddir)/src/log/libsidlog.la \ 26 | $(SYSTEMD_LIBS) 27 | 28 | libsidiface_la_SOURCES = ifc.c 29 | 30 | libsidiface_la_LIBADD = $(top_builddir)/src/base/libsidbase.la 31 | 32 | iface_HEADERS = $(top_srcdir)/src/include/iface/ifc.h \ 33 | $(top_srcdir)/src/include/iface/ifc-internal.h 34 | 35 | libsidiface_la_LDFLAGS = -version-info 0:0:0 36 | 37 | uninstall-hook: 38 | test -d ${DESTDIR}${ifacedir} && rmdir ${DESTDIR}${ifacedir} 39 | -------------------------------------------------------------------------------- /src/include/base/buf-common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_BUF_COMMON_H 8 | #define _SID_BUF_COMMON_H 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #define SID_BUF_SIZE_PREFIX_TYPE uint32_t 19 | #define SID_BUF_SIZE_PREFIX_LEN (sizeof(SID_BUF_SIZE_PREFIX_TYPE)) 20 | 21 | typedef enum { 22 | SID_BUF_BACKEND_MALLOC, 23 | SID_BUF_BACKEND_MEMFD, 24 | SID_BUF_BACKEND_FILE, 25 | } sid_buf_backend_t; 26 | 27 | typedef enum { 28 | SID_BUF_TYPE_LINEAR, 29 | SID_BUF_TYPE_VECTOR, 30 | } sid_buf_type_t; 31 | 32 | typedef enum { 33 | SID_BUF_MODE_PLAIN, /* plain buffer */ 34 | SID_BUF_MODE_SIZE_PREFIX, /* has SID_BUF_SIZE_PREFIX_TYPE size prefix */ 35 | } sid_buf_mode_t; 36 | 37 | struct sid_buf_spec { 38 | sid_buf_backend_t backend; 39 | sid_buf_type_t type; 40 | sid_buf_mode_t mode; 41 | 42 | union { 43 | struct { 44 | const char *path; 45 | } file; 46 | } ext; 47 | }; 48 | 49 | #define SID_BUF_SPEC(...) ((struct sid_buf_spec) {__VA_ARGS__}) 50 | 51 | struct sid_buf_init { 52 | size_t size; 53 | size_t alloc_step; 54 | size_t limit; 55 | }; 56 | 57 | #define SID_BUF_INIT(...) ((struct sid_buf_init) {__VA_ARGS__}) 58 | 59 | struct sid_buf_usage { 60 | size_t allocated; 61 | size_t used; 62 | }; 63 | 64 | struct sid_buf_stat { 65 | struct sid_buf_spec spec; 66 | struct sid_buf_init init; 67 | struct sid_buf_usage usage; 68 | }; 69 | 70 | #ifdef __cplusplus 71 | } 72 | #endif 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/include/base/buf-type.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_BUF_TYPE_H 8 | #define _SID_BUF_TYPE_H 9 | 10 | #include "base/buf-common.h" 11 | 12 | #include 13 | #include 14 | 15 | struct sid_buf { 16 | struct sid_buf_stat stat; 17 | void *mem; 18 | int fd; 19 | 20 | struct { 21 | bool set; 22 | size_t pos; 23 | } mark; 24 | }; 25 | 26 | struct sid_buf_type { 27 | int (*create)(struct sid_buf *buf); 28 | int (*destroy)(struct sid_buf *buf); 29 | int (*reset)(struct sid_buf *buf); 30 | int (*add)(struct sid_buf *buf, const void *data, size_t len, const void **mem, size_t *pos); 31 | int (*add_fmt)(struct sid_buf *buf, const void **mem, size_t *pos, const char *fmt, va_list ap); 32 | int (*release)(struct sid_buf *buf, size_t pos, bool rewind); 33 | int (*release_mem)(struct sid_buf *buf, const void *mem, bool rewind); 34 | bool (*is_complete)(struct sid_buf *buf, int *ret_code); 35 | int (*get_data)(struct sid_buf *buf, size_t pos, const void **data, size_t *data_size); 36 | int (*get_fd)(struct sid_buf *buf); 37 | size_t (*count)(struct sid_buf *buf); 38 | ssize_t (*read)(struct sid_buf *buf, int fd); 39 | ssize_t (*write)(struct sid_buf *buf, int fd, size_t pos); 40 | }; 41 | 42 | extern const struct sid_buf_type sid_buf_type_linear; 43 | extern const struct sid_buf_type sid_buf_type_vector; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/include/base/buf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_BUF_H 8 | #define _SID_BUF_H 9 | 10 | #include "base/buf-common.h" 11 | 12 | #include 13 | #include 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | struct sid_buf; 20 | 21 | typedef enum { 22 | SID_BUF_POS_ABS, 23 | SID_BUF_POS_REL, 24 | } sid_buf_pos_t; 25 | 26 | struct sid_buf *sid_buf_create(const struct sid_buf_spec *spec, const struct sid_buf_init *init, int *ret_code); 27 | void sid_buf_destroy(struct sid_buf *buf); 28 | int sid_buf_reset(struct sid_buf *buf); 29 | int sid_buf_reset_init(struct sid_buf *buf, const struct sid_buf_init *init); 30 | int sid_buf_add(struct sid_buf *buf, const void *data, size_t len, const void **mem, size_t *pos); 31 | int sid_buf_add_fmt(struct sid_buf *buf, const void **mem, size_t *pos, const char *fmt, ...); 32 | int sid_buf_add_vfmt(struct sid_buf *buf, const void **mem, size_t *pos, const char *fmt, va_list ap); 33 | int sid_buf_unbind(struct sid_buf *buf, size_t pos, sid_buf_pos_t whence); 34 | int sid_buf_rewind(struct sid_buf *buf, size_t pos, sid_buf_pos_t whence); 35 | int sid_buf_unbind_mem(struct sid_buf *buf, const void *mem); 36 | int sid_buf_rewind_mem(struct sid_buf *buf, const void *mem); 37 | bool sid_buf_is_complete(struct sid_buf *buf, int *ret_code); 38 | ssize_t sid_buf_read(struct sid_buf *buf, int fd); 39 | ssize_t sid_buf_write(struct sid_buf *buf, int fd, size_t pos); 40 | int sid_buf_get_data_from(struct sid_buf *buf, size_t pos, const void **data, size_t *data_size); 41 | int sid_buf_get_data(struct sid_buf *buf, const void **data, size_t *data_size); 42 | int sid_buf_get_fd(struct sid_buf *buf); 43 | size_t sid_buf_count(struct sid_buf *buf); 44 | struct sid_buf_stat sid_buf_stat(struct sid_buf *buf); 45 | int sid_buf_write_all(struct sid_buf *buf, int fd); 46 | 47 | #ifdef __cplusplus 48 | } 49 | #endif 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /src/include/base/comms.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_COMMS_H 8 | #define _SID_COMMS_H 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | int sid_comms_unix_create(const char *path, size_t path_len, int type); 19 | int sid_comms_unix_init(const char *path, size_t path_len, int type); 20 | 21 | ssize_t sid_comms_unix_send(int socket_fd, void *buf, ssize_t buf_len, int fd_to_send); 22 | ssize_t sid_comms_unix_send_iovec(int socket_fd, struct iovec *iov, size_t iov_len, int fd_to_send); 23 | 24 | ssize_t sid_comms_unix_recv(int socket_fd, void *buf, ssize_t buf_len, int *fd_received); 25 | ssize_t sid_comms_unix_recv_iovec(int socket_fd, struct iovec *iov, size_t iov_len, int *fd_received); 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/include/base/conv-base64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2005, Jouni Malinen 3 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | #ifndef SID_CONV_BASE64_H 9 | #define SID_CONV_BASE64_H 10 | 11 | #include 12 | 13 | size_t sid_conv_base64_encoded_len(size_t in_len); 14 | int sid_conv_base64_encode(const unsigned char *src, size_t len, unsigned char *dest, size_t out_len); 15 | unsigned char *sid_conv_base64_decode(const unsigned char *src, size_t len, size_t *out_len); 16 | 17 | #endif /* SID_CONV_BASE64_H */ 18 | -------------------------------------------------------------------------------- /src/include/base/conv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef SID_CONV_H 8 | #define SID_CONV_H 9 | 10 | #include "base/conv-base64.h" 11 | 12 | #endif /* SID_CONV_H */ 13 | -------------------------------------------------------------------------------- /src/include/base/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_BASE_UTIL_H 8 | #define _SID_BASE_UTIL_H 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /* 19 | * Environment-related utilities. 20 | */ 21 | int sid_util_env_get_ull(const char *key, unsigned long long min, unsigned long long max, unsigned long long *val); 22 | 23 | /* 24 | * fd-related utilities 25 | */ 26 | ssize_t sid_util_fd_read_all(int fd, void *buf, size_t len); 27 | 28 | /* 29 | * Kernel-related utilities. 30 | */ 31 | 32 | /* Note: sid_util_kernel_get_arg reads kernel config line only once, then it is stored in internal static variable. */ 33 | bool sid_util_kernel_get_arg(const char *arg, char **value, int *ret_code); 34 | 35 | /* 36 | * sysfs-related utilities. 37 | */ 38 | 39 | int sid_util_sysfs_get(const char *path, char *buf, size_t buf_size, size_t *char_count); 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/include/iface/ifc-internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_IFC_INTERNAL_H 8 | #define _SID_IFC_INTERNAL_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #include "internal/comp-attrs.h" 15 | 16 | #include "iface/ifc.h" 17 | 18 | struct sid_ifc_msg_header { 19 | uint64_t status; 20 | uint8_t prot; 21 | uint8_t cmd; 22 | uint16_t flags; 23 | } __packed; 24 | 25 | #define SID_IFC_MSG_HEADER(...) ((struct sid_ifc_msg_header) {__VA_ARGS__}) 26 | 27 | #define SID_IFC_MSG_HEADER_SIZE sizeof(struct sid_ifc_msg_header) 28 | 29 | #define SID_IFC_SOCKET_PATH "\0sid-ubridge.socket" 30 | #define SID_IFC_SOCKET_PATH_LEN (sizeof(SID_IFC_SOCKET_PATH) - 1) 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/include/iface/ifc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_IFC_H 8 | #define _SID_IFC_H 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #define SID_IFC_PROTOCOL 2 19 | 20 | typedef enum { 21 | _SID_IFC_CMD_START = 0, 22 | SID_IFC_CMD_UNDEFINED = _SID_IFC_CMD_START, /* virtual cmd if cmd not defined at all */ 23 | SID_IFC_CMD_UNKNOWN = 1, /* virtual cmd if cmd defined, but not recognized */ 24 | SID_IFC_CMD_ACTIVE = 2, 25 | SID_IFC_CMD_CHECKPOINT = 3, 26 | SID_IFC_CMD_REPLY = 4, 27 | SID_IFC_CMD_SCAN = 5, 28 | SID_IFC_CMD_VERSION = 6, 29 | SID_IFC_CMD_DBDUMP = 7, 30 | SID_IFC_CMD_DBSTATS = 8, 31 | SID_IFC_CMD_RESOURCES = 9, 32 | SID_IFC_CMD_DEVICES = 10, 33 | _SID_IFC_CMD_END = SID_IFC_CMD_DEVICES, 34 | } sid_ifc_cmd_t; 35 | 36 | #define SID_IFC_CMD_STATUS_MASK_OVERALL UINT64_C(0x0000000000000001) 37 | #define SID_IFC_CMD_STATUS_SUCCESS UINT64_C(0x0000000000000000) 38 | #define SID_IFC_CMD_STATUS_FAILURE UINT64_C(0x0000000000000001) 39 | 40 | #define SID_IFC_CMD_FL_FMT_MASK UINT16_C(0x0003) 41 | #define SID_IFC_CMD_FL_FMT_TABLE UINT16_C(0x0000) 42 | #define SID_IFC_CMD_FL_FMT_JSON UINT16_C(0x0001) 43 | #define SID_IFC_CMD_FL_FMT_ENV UINT16_C(0x0002) 44 | #define SID_IFC_CMD_FL_UNMODIFIED_DATA UINT16_C(0x0004) 45 | 46 | struct sid_ifc_checkpoint_data { 47 | char *name; 48 | char **keys; 49 | unsigned int nr_keys; 50 | }; 51 | 52 | struct sid_ifc_unmodified_data { 53 | char *mem; 54 | size_t size; 55 | }; 56 | 57 | struct sid_ifc_req { 58 | sid_ifc_cmd_t cmd; 59 | uint64_t flags; 60 | uint64_t seqnum; 61 | 62 | union { 63 | struct sid_ifc_checkpoint_data checkpoint; 64 | struct sid_ifc_unmodified_data unmodified; 65 | } data; 66 | }; 67 | 68 | struct sid_ifc_rsl; 69 | 70 | const char *sid_ifc_cmd_type_to_name(sid_ifc_cmd_t cmd); 71 | sid_ifc_cmd_t sid_ifc_cmd_name_to_type(const char *cmd_name); 72 | int sid_ifc_req(struct sid_ifc_req *req, struct sid_ifc_rsl **rsl); 73 | void sid_ifc_rsl_free(struct sid_ifc_rsl *rsl); 74 | int sid_ifc_rsl_get_status(struct sid_ifc_rsl *rsl, uint64_t *status); 75 | int sid_ifc_rsl_get_protocol(struct sid_ifc_rsl *rsl, uint8_t *prot); 76 | const char *sid_ifc_rsl_get_data(struct sid_ifc_rsl *rsl, size_t *size_p); 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /src/include/iface/srv-lnk.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_SERVICE_LINK_H 8 | #define _SID_SERVICE_LINK_H 9 | 10 | #include "log/log.h" 11 | 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | typedef enum { 19 | SID_SRV_LNK_TYPE_NONE, 20 | SID_SRV_LNK_TYPE_SYSTEMD, 21 | SID_SRV_LNK_TYPE_LOGGER, 22 | } sid_srv_lnk_type_t; 23 | 24 | /* no notification */ 25 | #define SID_SRV_LNK_NOTIF_NONE UINT64_C(0x0000000000000000) 26 | /* discard any further service notifications; no arg */ 27 | #define SID_SRV_LNK_NOTIF_UNSET UINT64_C(0x0000000000000001) 28 | /* notify about service status; arg is STATUS= */ 29 | #define SID_SRV_LNK_NOTIF_STATUS UINT64_C(0x0000000000000002) 30 | /* notify about service reaching an error with errno; arg is 'ERRNO=' or 'ERRNO=' */ 31 | #define SID_SRV_LNK_NOTIF_ERRNO UINT64_C(0x0000000000000004) 32 | /* notify about service being ready; no arg */ 33 | #define SID_SRV_LNK_NOTIF_READY UINT64_C(0x0000000000000008) 34 | /* notify about service being reloaded; no arg */ 35 | #define SID_SRV_LNK_NOTIF_RELOADING UINT64_C(0x0000000000000010) 36 | /* notify about service being stopped; no arg */ 37 | #define SID_SRV_LNK_NOTIF_STOPPING UINT64_C(0x0000000000000020) 38 | /* notify about service being still alive; no arg */ 39 | #define SID_SRV_LNK_NOTIF_WATCHDOG_REFRESH UINT64_C(0x0000000000000040) 40 | /* notify about service reaching a point where watchdog action needs to be executed; no arg */ 41 | #define SID_SRV_LNK_NOTIF_WATCHDOG_TRIGGER UINT64_C(0x0000000000000080) 42 | /* notify with a message */ 43 | #define SID_SRV_LNK_NOTIF_MESSAGE UINT64_C(0x0000000000000100) 44 | 45 | typedef uint64_t sid_srv_lnk_notif_t; 46 | 47 | #define SID_SRV_LNK_FL_NONE UINT64_C(0x0000000000000000) 48 | #define SID_SRV_LNK_FL_CLONEABLE UINT64_C(0x0000000000000001) 49 | 50 | typedef uint64_t sid_srv_lnk_fl_t; 51 | 52 | struct sid_srv_lnk; 53 | struct sid_srv_lnk_grp; 54 | 55 | #define SID_SRV_LNK_KEY_STATUS "STATUS" 56 | #define SID_SRV_LNK_KEY_ERRNO "ERRNO" 57 | 58 | #define SID_SRV_LNK_KEY_ACTIVATION_TYPE "SERVICE_ACTIVATION_TYPE" 59 | #define SID_SRV_LNK_VAL_ACTIVATION_FD "FD_PRELOAD" 60 | 61 | #define SID_SRV_LNK_FD_ACTIVATION_FDS_START SD_LISTEN_FDS_START 62 | 63 | /* int sd_listen_fds(int unset_environment) */ 64 | #define sid_srv_lnk_fd_activation_present sd_listen_fds 65 | 66 | /* int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) */ 67 | #define sid_srv_lnk_fd_is_socket_unix sd_is_socket_unix 68 | 69 | struct sid_srv_lnk *sid_srv_lnk_create(sid_srv_lnk_type_t type, const char *name); 70 | struct sid_srv_lnk *sid_srv_lnk_clone(struct sid_srv_lnk *sl, const char *name); 71 | void sid_srv_lnk_destroy(struct sid_srv_lnk *sl); 72 | 73 | void sid_srv_lnk_set_flags(struct sid_srv_lnk *sl, sid_srv_lnk_fl_t flags); 74 | void sid_srv_lnk_set_data(struct sid_srv_lnk *sl, void *data); 75 | 76 | void sid_srv_lnk_notif_add(struct sid_srv_lnk *sl, sid_srv_lnk_notif_t notification); 77 | void sid_srv_lnk_notif_del(struct sid_srv_lnk *sl, sid_srv_lnk_notif_t notification); 78 | 79 | struct sid_srv_lnk_grp *sid_srv_lnk_grp_create(const char *name); 80 | struct sid_srv_lnk_grp *sid_srv_lnk_grp_clone(struct sid_srv_lnk_grp *slg, const char *name); 81 | struct sid_srv_lnk_grp *sid_srv_lnk_grp_merge(struct sid_srv_lnk_grp *dest_slg, struct sid_srv_lnk_grp *src_slg); 82 | void sid_srv_lnk_grp_destroy(struct sid_srv_lnk_grp *slg); 83 | void sid_srv_lnk_grp_destroy_with_members(struct sid_srv_lnk_grp *slg); 84 | 85 | void sid_srv_lnk_grp_add(struct sid_srv_lnk_grp *slg, struct sid_srv_lnk *sl); 86 | int sid_srv_lnk_grp_del(struct sid_srv_lnk_grp *slg, struct sid_srv_lnk *sl); 87 | 88 | /* 89 | * Send service notification. 90 | * Arguments depend on notification type used - see comments in enum service_notification_t definition. 91 | */ 92 | 93 | #define SID_SRV_LNK_DEFAULT_LOG_CTX \ 94 | ((sid_log_ctx_t) {.level_id = LOG_DEBUG, .errno_id = 0, .src_file = __FILE__, .src_line = __LINE__, .src_func = __func__}) 95 | 96 | #define SID_SRV_LNK_DEFAULT_LOG_REQ ((sid_log_req_t) {.pfx = NULL, .ctx = &SID_SRV_LNK_DEFAULT_LOG_CTX}) 97 | 98 | int sid_srv_lnk_notify(struct sid_srv_lnk *sl, sid_srv_lnk_notif_t notification, struct sid_log_req *log_req, const char *fmt, ...); 99 | 100 | int sid_srv_lnk_vnotify(struct sid_srv_lnk *sl, 101 | sid_srv_lnk_notif_t notification, 102 | struct sid_log_req *log_req, 103 | const char *fmt, 104 | va_list ap); 105 | 106 | int sid_srv_lnk_grp_notify(struct sid_srv_lnk_grp *slg, 107 | sid_srv_lnk_notif_t notification, 108 | struct sid_log_req *log_req, 109 | const char *fmt, 110 | ...); 111 | 112 | int sid_srv_lnk_grp_vnotify(struct sid_srv_lnk_grp *slg, 113 | sid_srv_lnk_notif_t notification, 114 | struct sid_log_req *log_req, 115 | const char *fmt, 116 | va_list ap); 117 | 118 | #ifdef __cplusplus 119 | } 120 | #endif 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /src/include/internal/bmp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_BMP_H 8 | #define _SID_BMP_H 9 | 10 | #include 11 | #include 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | struct bmp; 18 | 19 | struct bmp *bmp_create(size_t bit_count, bool invert, int *ret_code); 20 | void bmp_destroy(struct bmp *bmp); 21 | int bmp_set_bit(struct bmp *bmp, size_t bit_pos); 22 | int bmp_unset_bit(struct bmp *bmp, size_t bit_pos); 23 | bool bmp_bit_is_set(struct bmp *bmp, size_t bit_pos, int *ret_code); 24 | size_t bmp_get_bit_count(struct bmp *bmp); 25 | size_t bmp_get_bit_set_count(struct bmp *bmp); 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/include/internal/bptree.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_BPTREE_H 8 | #define _SID_BPTREE_H 9 | 10 | #include 11 | #include 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | typedef struct bptree bptree_t; 18 | typedef struct bptree_iter bptree_iter_t; 19 | 20 | typedef enum { 21 | BPTREE_UPDATE_SKIP, /* skip new value (keep old value) */ 22 | BPTREE_UPDATE_WRITE, /* write new value (overwrite old value) */ 23 | BPTREE_UPDATE_REMOVE, /* remove old value */ 24 | } bptree_update_action_t; 25 | 26 | /* 27 | * bptree_update_fn_t callback type to define bptree_update's bptree_update_fn callback function. 28 | * Function of this type returns: 29 | * 0 for bptree to keep old data 30 | * 1 for bptree to update old_data with new_data (new_data may be modified and/or newly allocated by this function) 31 | */ 32 | typedef bptree_update_action_t (*bptree_update_cb_fn_t)(const char *key, 33 | void *old_data, 34 | size_t old_data_size, 35 | unsigned old_data_ref_count, 36 | void **new_data, 37 | size_t *new_data_size, 38 | void *arg); 39 | 40 | typedef void ( 41 | *bptree_iterate_fn_t)(const char *key, void *data, size_t data_size, unsigned data_ref_count, void *bptree_iterate_fn_arg); 42 | 43 | bptree_t *bptree_create(int order); 44 | int bptree_add(bptree_t *bptree, const char *key, void *data, size_t data_size); 45 | int bptree_add_alias(bptree_t *bptree, const char *key, const char *alias, bool force); 46 | int bptree_update(bptree_t *bptree, 47 | const char *key, 48 | void **data, 49 | size_t *data_size, 50 | bptree_update_cb_fn_t bptree_update_fn, 51 | void *bptree_update_fn_arg); 52 | int bptree_del(bptree_t *bptree, const char *key); 53 | void *bptree_lookup(bptree_t *bptree, const char *key, size_t *data_size, unsigned *data_ref_count); 54 | int bptree_get_height(bptree_t *bptree); 55 | size_t bptree_get_size(bptree_t *bptree, size_t *meta_size, size_t *data_size); 56 | size_t bptree_get_entry_count(bptree_t *bptree); 57 | int bptree_destroy(bptree_t *bptree); 58 | int bptree_destroy_with_fn(bptree_t *bptree, bptree_iterate_fn_t fn, void *fn_arg); 59 | 60 | void bptree_iter(bptree_t *bptree, const char *key_start, const char *key_end, bptree_iterate_fn_t fn, void *fn_arg); 61 | 62 | bptree_iter_t *bptree_iter_create(bptree_t *bptree, const char *key_start, const char *key_end); 63 | bptree_iter_t *bptree_iter_create_prefix(bptree_t *bptree, const char *prefix); 64 | void *bptree_iter_current(bptree_iter_t *iter, const char **key, size_t *data_size, unsigned *data_ref_count); 65 | const char *bptree_iter_current_key(bptree_iter_t *iter); 66 | void *bptree_iter_next(bptree_iter_t *iter, const char **key, size_t *data_size, unsigned *data_ref_count); 67 | void bptree_iter_reset(bptree_iter_t *iter, const char *key_start, const char *key_end); 68 | void bptree_iter_reset_prefix(bptree_iter_t *iter, const char *prefix); 69 | void bptree_iter_destroy(bptree_iter_t *iter); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /src/include/internal/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_INTERNAL_COMMON_H 8 | #define _SID_INTERNAL_COMMON_H 9 | 10 | #define SYSTEM_DEV_PATH "/dev" 11 | #define SYSTEM_SYSFS_PATH "/sys" 12 | #define SYSTEM_PROC_PATH "/proc" 13 | 14 | #define SYSTEM_SYSFS_SLAVES "slaves" 15 | 16 | #define UDEV_KEY_ACTION "ACTION" 17 | #define UDEV_KEY_DEVPATH "DEVPATH" 18 | #define UDEV_KEY_DEVTYPE "DEVTYPE" 19 | #define UDEV_KEY_MAJOR "MAJOR" 20 | #define UDEV_KEY_MINOR "MINOR" 21 | #define UDEV_KEY_SEQNUM "SEQNUM" 22 | #define UDEV_KEY_DISKSEQ "DISKSEQ" 23 | #define UDEV_KEY_SYNTH_UUID "SYNTH_UUID" 24 | #define UDEV_KEY_PARTN "PARTN" 25 | 26 | #define UDEV_VALUE_DEVTYPE_UNKNOWN "unknown" 27 | #define UDEV_VALUE_DEVTYPE_DISK "disk" 28 | #define UDEV_VALUE_DEVTYPE_PARTITION "partition" 29 | 30 | typedef enum { 31 | UDEV_ACTION_UNKNOWN, 32 | UDEV_ACTION_ADD, 33 | UDEV_ACTION_CHANGE, 34 | UDEV_ACTION_REMOVE, 35 | UDEV_ACTION_MOVE, 36 | UDEV_ACTION_ONLINE, 37 | UDEV_ACTION_OFFLINE, 38 | UDEV_ACTION_BIND, 39 | UDEV_ACTION_UNBIND 40 | } udev_action_t; 41 | 42 | typedef enum { 43 | UDEV_DEVTYPE_UNKNOWN, 44 | UDEV_DEVTYPE_DISK, 45 | UDEV_DEVTYPE_PARTITION, 46 | } udev_devtype_t; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /src/include/internal/comp-attrs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_COMP_ATTRS_H 8 | #define _SID_COMP_ATTRS_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /* variable attributes */ 15 | #define __packed __attribute__((packed)) 16 | #define __unused __attribute__((unused)) 17 | #define __aligned __attribute__((aligned)) 18 | #define __aligned_to(x) __attribute__((aligned(x))) 19 | #define __malloc __attribute__((malloc)) 20 | 21 | /* function attributes */ 22 | #define __format_printf(x, y) __attribute__((format(printf, x, y))) 23 | #define __constructor __attribute__((constructor)) 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/include/internal/fmt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_FMT_H 8 | #define _SID_FMT_H 9 | 10 | #include "base/buf.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | typedef enum { 22 | FMT_NONE = -1, 23 | FMT_TABLE, 24 | FMT_JSON, 25 | FMT_ENV, 26 | } fmt_output_t; 27 | 28 | int fmt_doc_start(fmt_output_t format, struct sid_buf *buf, int level); 29 | int fmt_doc_end(fmt_output_t format, struct sid_buf *buf, int level); 30 | 31 | int fmt_arr_start(fmt_output_t format, struct sid_buf *buf, int level, const char *array_name, bool with_comma); 32 | int fmt_arr_end(fmt_output_t format, struct sid_buf *buf, int level); 33 | 34 | int fmt_elm_start(fmt_output_t format, struct sid_buf *buf, int level, bool with_comma); 35 | int fmt_elm_end(fmt_output_t format, struct sid_buf *buf, int level); 36 | 37 | int fmt_elm_name(fmt_output_t format, struct sid_buf *buf, int level, const char *elem_name, bool with_comma); 38 | 39 | int fmt_fld_str(fmt_output_t format, struct sid_buf *buf, int level, const char *field_name, const char *value, bool with_comma); 40 | 41 | int fmt_fld_bin(fmt_output_t format, 42 | struct sid_buf *buf, 43 | int level, 44 | const char *field_name, 45 | const char *value, 46 | size_t len, 47 | bool with_comma); 48 | 49 | int fmt_fld_uint(fmt_output_t format, struct sid_buf *buf, int level, const char *field_name, uint value, bool with_comma); 50 | 51 | int fmt_fld_uint64(fmt_output_t format, struct sid_buf *buf, int level, const char *field_name, uint64_t value, bool with_comma); 52 | 53 | int fmt_fld_int64(fmt_output_t format, struct sid_buf *buf, int level, const char *field_name, int64_t value, bool with_comma); 54 | 55 | int fmt_fld_bool(fmt_output_t format, struct sid_buf *buf, int level, const char *field_name, bool value, bool with_comma); 56 | 57 | int fmt_arr_fld_uint(fmt_output_t format, struct sid_buf *buf, int level, uint value, bool with_comma); 58 | 59 | int fmt_arr_fld_str(fmt_output_t format, struct sid_buf *buf, int level, const char *value, bool with_comma); 60 | 61 | int fmt_arr_fld_bin(fmt_output_t format, struct sid_buf *buf, int level, const char *value, size_t len, bool with_comma); 62 | 63 | int fmt_null_byte(struct sid_buf *buf); 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /src/include/internal/hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2001-2004 Sistina Software, Inc. 3 | * SPDX-FileCopyrightText: (C) 2004-2025 Red Hat, Inc. 4 | * 5 | * SPDX-License-Identifier: GPL-2.0-or-later 6 | */ 7 | 8 | #ifndef _SID_HASH_H 9 | #define _SID_HASH_H 10 | 11 | #include 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | struct hash_table; 19 | struct hash_node; 20 | 21 | typedef void (*hash_iterate_fn_t)(const void *key, uint32_t key_size, void *data, size_t data_size); 22 | 23 | struct hash_table *hash_create(unsigned size_hint); 24 | void hash_wipe(struct hash_table *t); 25 | void hash_destroy(struct hash_table *t); 26 | 27 | int hash_add(struct hash_table *t, const void *key, uint32_t key_size, void *data, size_t data_size); 28 | void *hash_lookup(struct hash_table *t, const void *key, uint32_t key_size, size_t *data_size); 29 | void hash_del(struct hash_table *t, const void *key, uint32_t key_size); 30 | 31 | unsigned hash_get_entry_count(struct hash_table *t); 32 | size_t hash_get_size(struct hash_table *t, size_t *meta_size, size_t *data_size); 33 | void hash_iter(struct hash_table *t, hash_iterate_fn_t f); 34 | 35 | struct hash_node *hash_get_first(struct hash_table *t); 36 | struct hash_node *hash_get_next(struct hash_table *t, struct hash_node *n); 37 | 38 | char *hash_get_key(struct hash_table *t, struct hash_node *n, uint32_t *key_size); 39 | void *hash_get_data(struct hash_table *t, struct hash_node *n, size_t *data_size); 40 | 41 | /* 42 | * hash_insert() replaces the data of an existing 43 | * entry with a matching key if one exists. Otherwise 44 | * it adds a new entry. 45 | * 46 | * hash_insert_allow_multiple() inserts a new entry if 47 | * another entry with the same key already exists. 48 | * data_size is the size of the data being inserted. 49 | * 50 | * If two entries with the same key exist, 51 | * (added using hash_insert_allow_multiple), then: 52 | * . hash_lookup() returns the first one it finds, and 53 | * hash_lookup_with_data() returns the one with a matching 54 | * data_size/data. 55 | * . hash_del() removes the first one it finds, and 56 | * hash_del_with_data() removes the one with a matching 57 | * data_size/data. 58 | * 59 | * If a single entry with a given key exists, and it has 60 | * zero data_size, then: 61 | * . hash_lookup() returns it 62 | * . hash_lookup_with_data(data_size=0) returns it 63 | * . hash_del() removes it 64 | * . hash_del_with_data(data_size=0) removes it 65 | * 66 | * hash_lookup_with_count() is a single call that will 67 | * both lookup a key's data and check if there is more 68 | * than one entry with the given key. 69 | * 70 | * (It is not meant to retrieve all the entries with the 71 | * given key. In the common case where a single entry exists 72 | * for the key, it is useful to have a single call that will 73 | * both look up the data and indicate if multiple data 74 | * exist for the key.) 75 | * 76 | * hash_lookup_with_count: 77 | * . If no entries exist, the function returns NULL, and 78 | * the count is set to 0. 79 | * . If only one entry exists, the data of that entry is 80 | * returned and count is set to 1. 81 | * . If N entries exists, the data of the first entry is 82 | * returned and count is set to N. 83 | */ 84 | 85 | int hash_add_allow_multiple(struct hash_table *t, const char *key, uint32_t key_size, void *data, size_t data_size); 86 | void *hash_lookup_with_data(struct hash_table *t, const char *key, uint32_t key_size, void *data, size_t data_size); 87 | void *hash_lookup_with_count(struct hash_table *t, const char *key, uint32_t key_size, size_t *data_size, unsigned *count); 88 | void hash_del_with_data(struct hash_table *t, const char *key, uint32_t key_size, void *data, size_t data_size); 89 | 90 | #define hash_iterate(v, h) for (v = hash_get_first((h)); v; v = hash_get_next((h), v)) 91 | 92 | /* 93 | * THE FUNCTIONS BELOW ARE EXTRA TO ORIGINAL CODE TAKEN FROM LVM2 SOURCE TREE AND ITS dm_hash_table IMPLEMENTATION. 94 | */ 95 | 96 | typedef enum { 97 | HASH_UPDATE_SKIP, /* skip new value (keep old value) */ 98 | HASH_UPDATE_WRITE, /* write new value (overwrite old value) */ 99 | HASH_UPDATE_REMOVE, /* remove old value */ 100 | } hash_update_action_t; 101 | 102 | /* 103 | * hash_update_cb_fn_t callback type to define hash_update's hash_update_fn callback function. 104 | * Function of this type returns: 105 | * 0 for hash table to keep old_data 106 | * 1 for hash table to update old_data with new_data (new_data may be modified and/or newly allocated by this function) 107 | */ 108 | typedef hash_update_action_t (*hash_update_cb_fn_t)(const void *key, 109 | uint32_t key_size, 110 | void *old_data, 111 | size_t old_data_size, 112 | void **new_data, 113 | size_t *new_data_size, 114 | void *arg); 115 | 116 | /* 117 | * hash_update function calls hash_update_fn callback with hash_update_fn_arg right before the update 118 | * and based on callback's return value, it either keeps the old data or updates with new data. 119 | */ 120 | int hash_update(struct hash_table *t, 121 | const void *key, 122 | uint32_t key_size, 123 | void **data, 124 | size_t *data_size, 125 | hash_update_cb_fn_t hash_update_fn, 126 | void *hash_update_fn_arg); 127 | 128 | #ifdef __cplusplus 129 | } 130 | #endif 131 | 132 | #endif 133 | -------------------------------------------------------------------------------- /src/include/internal/list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2001-2004 Sistina Software, Inc. 3 | * SPDX-FileCopyrightText: (C) 2004-2025 Red Hat, Inc. 4 | * 5 | * SPDX-License-Identifier: GPL-2.0-or-later 6 | */ 7 | 8 | #ifndef _SID_LIST_H 9 | #define _SID_LIST_H 10 | 11 | #include 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | struct list { 19 | struct list *n; 20 | struct list *p; 21 | }; 22 | 23 | #define list_iterate(v, head) for (v = (head)->n; v != head; v = v->n) 24 | 25 | #define list_iterate_back(v, head) for (v = (head)->p; v != head; v = v->p) 26 | 27 | #define list_struct_base(v, t, head) ((t *) ((char *) (v) - offsetof(t, head))) 28 | 29 | #define list_item(v, t) list_struct_base((v), t, list) 30 | 31 | #define list_iterate_items_gen(v, head, field) \ 32 | for (v = list_struct_base((head)->n, __typeof__(*v), field); &v->field != (head); \ 33 | v = list_struct_base(v->field.n, __typeof__(*v), field)) 34 | 35 | #define list_iterate_items(v, head) list_iterate_items_gen (v, (head), list) 36 | 37 | #define list_iterate_items_gen_back(v, head, field) \ 38 | for (v = list_struct_base((head)->p, __typeof__(*v), field); &v->field != (head); \ 39 | v = list_struct_base(v->field.p, __typeof__(*v), field)) 40 | 41 | #define list_iterate_items_back(v, head) list_iterate_items_gen_back (v, (head), list) 42 | 43 | #define list_iterate_items_gen_safe(v, t, head, field) \ 44 | for (v = list_struct_base((head)->n, __typeof__(*v), field), t = list_struct_base(v->field.n, __typeof__(*v), field); \ 45 | &v->field != (head); \ 46 | v = t, t = list_struct_base(v->field.n, __typeof__(*v), field)) 47 | 48 | #define list_iterate_items_safe(v, t, head) list_iterate_items_gen_safe (v, t, (head), list) 49 | 50 | #define list_iterate_items_gen_safe_back(v, t, head, field) \ 51 | for (v = list_struct_base((head)->p, __typeof__(*v), field), t = list_struct_base(v->field.p, __typeof__(*v), field); \ 52 | &v->field != (head); \ 53 | v = t, t = list_struct_base(v->field.p, __typeof__(*v), field)) 54 | 55 | #define list_iterate_items_safe_back(v, t, head) list_iterate_items_gen_safe_back (v, t, (head), list) 56 | 57 | void list_init(struct list *head); 58 | void list_add(struct list *head, struct list *elem); 59 | void list_del(struct list *elem); 60 | bool list_is_empty(const struct list *head); 61 | unsigned int list_get_size(const struct list *head); 62 | 63 | #ifdef __cplusplus 64 | } 65 | #endif 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /src/include/internal/mem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_MEM_H 8 | #define _SID_MEM_H 9 | 10 | #include "internal/comp-attrs.h" 11 | 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /* align memory pointer 'p' upwards to 'a' bytes */ 19 | #define MEM_ALIGN_UP(p, a) (((uintptr_t) (p) + (a) - 1) & ~((a) - 1)) 20 | 21 | /* get padding in bytes needed to align memory pointer 'p' upwards to 'a' bytes */ 22 | #define MEM_ALIGN_UP_PAD(p, a) (-((uintptr_t) (p)) & ((a) - 1)) 23 | 24 | void *mem_zalloc(size_t size) __malloc; 25 | void *mem_freen(void *mem); 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/include/internal/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_INTERNAL_UTIL_H 8 | #define _SID_INTERNAL_UTIL_H 9 | 10 | #include "internal/common.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #define UTIL_SWAP(a, b) \ 24 | do { \ 25 | typeof(a) tmp = (a); \ 26 | (a) = (b); \ 27 | (b) = tmp; \ 28 | } while (0) 29 | 30 | #define UTIL_IN_SET(a, ...) \ 31 | ({ \ 32 | typeof(a) _arr[] = {__VA_ARGS__}; \ 33 | int _found = 0; \ 34 | for (unsigned int _i = 0; _i < sizeof(_arr) / sizeof(_arr[0]); _i++) { \ 35 | if (a == _arr[_i]) { \ 36 | _found = 1; \ 37 | break; \ 38 | } \ 39 | } \ 40 | _found; \ 41 | }) 42 | 43 | /* 44 | * All functions that need to use allocated memory and they provide a 45 | * possibility to use preallocated memory contain 'util_mem_t *mem' 46 | * parameter to pass this preallocated memory for use. 47 | * If 'mem' or 'mem->base' is NULL, the functions allocate the memory 48 | * by themselves. 49 | */ 50 | typedef struct util_mem { 51 | void *base; 52 | size_t size; 53 | } util_mem_t; 54 | 55 | /* 56 | * Process-related utilities. 57 | */ 58 | int util_proc_pid_to_str(pid_t pid, char *buf, size_t buf_size); 59 | 60 | /* 61 | * Udev-related utilities. 62 | */ 63 | udev_action_t util_udev_str_to_action(const char *str); 64 | const char *util_udev_action_to_str(const udev_action_t action); 65 | udev_devtype_t util_udev_str_to_devtyoe(const char *str); 66 | const char *util_udev_devtype_to_str(udev_devtype_t devtype); 67 | 68 | /* 69 | * String-related utilities. 70 | */ 71 | #define UTIL_STR_DEFAULT_DELIMS " \t\r\n\v\f" 72 | #define UTIL_STR_DEFAULT_QUOTES "\"\'" 73 | 74 | #define UTIL_STR_END(s) ((s)[0] == '\0') 75 | #define UTIL_STR_END_PUT(s) ((s)[0] = '\0') 76 | #define UTIL_STR_EMPTY(s) (!(s) || UTIL_STR_END(s)) 77 | 78 | int util_str_get_kv(char *str, char **key, char **val); 79 | char *util_str_rstr(const char *haystack, const char *needle); 80 | char *util_str_combstr(const char *haystack, const char *prefix, const char *needle, const char *suffix, bool ignorecase); 81 | char *util_str_copy_len(const char *str, size_t len, char *buf, size_t buf_size); 82 | 83 | typedef int (*util_str_token_fn_t)(const char *token, size_t len, bool merge_back, void *data); 84 | int util_str_iterate_tokens(const char *str, 85 | const char *delims, 86 | const char *quotes, 87 | util_str_token_fn_t token_fn, 88 | void *token_fn_data); 89 | 90 | char *util_str_comb_to_str(util_mem_t *mem, const char *prefix, const char *str, const char *suffix); 91 | 92 | char **util_str_comb_to_strv(util_mem_t *mem, 93 | const char *prefix, 94 | const char *str, 95 | const char *suffix, 96 | const char *delims, 97 | const char *quotes); 98 | char **util_strv_copy(util_mem_t *mem, const char **strv); 99 | 100 | char *util_str_copy_substr(util_mem_t *mem, const char *str, size_t start, size_t len); 101 | 102 | /* 103 | * Time-related utilities. 104 | */ 105 | uint64_t util_time_get_now_usec(clockid_t clock_id); 106 | 107 | /* 108 | * UUID-related utilities. 109 | */ 110 | #define UTIL_UUID_STR_SIZE UUID_STR_LEN 111 | 112 | char *util_uuid_gen_str(util_mem_t *mem); 113 | bool util_uuid_check_str(const char *str); 114 | char *util_uuid_get_boot_id(util_mem_t *mem, int *ret_code); 115 | 116 | #ifdef __cplusplus 117 | } 118 | #endif 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /src/include/log/log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_LOG_H 8 | #define _SID_LOG_H 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | typedef struct sid_log sid_log_t; 20 | 21 | typedef enum { 22 | SID_LOG_TGT_NONE, 23 | SID_LOG_TGT_STANDARD, 24 | SID_LOG_TGT_SYSLOG, 25 | SID_LOG_TGT_JOURNAL, 26 | } sid_log_tgt_t; 27 | 28 | typedef struct sid_log_pfx sid_log_pfx_t; 29 | 30 | typedef struct sid_log_pfx { 31 | const char *s; 32 | sid_log_pfx_t *n; 33 | } sid_log_pfx_t; 34 | 35 | typedef struct sid_log_ctx { 36 | int level_id; 37 | int errno_id; 38 | const char *src_file; 39 | int src_line; 40 | const char *src_func; 41 | } sid_log_ctx_t; 42 | 43 | typedef struct sid_log_req { 44 | sid_log_pfx_t *pfx; 45 | sid_log_ctx_t *ctx; 46 | } sid_log_req_t; 47 | 48 | struct sid_log_tgt { 49 | const char *name; 50 | void (*open)(int verbose_mode); 51 | void (*close)(void); 52 | void (*output)(const sid_log_req_t *req, const char *format, va_list ap); 53 | }; 54 | 55 | extern const struct sid_log_tgt log_target_standard; 56 | extern const struct sid_log_tgt log_target_syslog; 57 | extern const struct sid_log_tgt log_target_journal; 58 | 59 | void sid_log_init(sid_log_tgt_t target, int verbose_mode); 60 | sid_log_t *sid_log_init_with_handle(sid_log_tgt_t target, int verbose_mode); 61 | void sid_log_close(sid_log_t *log); 62 | void sid_log_change_tgt(sid_log_t *log, sid_log_tgt_t new_target); 63 | void sid_log_set_pfx(sid_log_t *log, const char *prefix); 64 | 65 | __attribute__((format(printf, 3, 4))) void sid_log_output(sid_log_t *log, sid_log_req_t *req, const char *format, ...); 66 | void sid_log_voutput(sid_log_t *log, sid_log_req_t *req, const char *format, va_list ap); 67 | 68 | #define SID_LOG_PRINT LOG_LOCAL0 69 | 70 | #define SID_LOG_LINE(h, l, p, e, ...) \ 71 | sid_log_output(h, \ 72 | &(struct sid_log_req) {.pfx = p ? &(sid_log_pfx_t) {.s = p, .n = NULL} : NULL, \ 73 | .ctx = &((sid_log_ctx_t) {.level_id = l, \ 74 | .errno_id = e, \ 75 | .src_file = __FILE__, \ 76 | .src_line = __LINE__, \ 77 | .src_func = __func__})}, \ 78 | __VA_ARGS__) 79 | 80 | #define sid_log_debug(p, ...) SID_LOG_LINE(NULL, LOG_DEBUG, p, 0, __VA_ARGS__) 81 | #define sid_log_info(p, ...) SID_LOG_LINE(NULL, LOG_INFO, p, 0, __VA_ARGS__) 82 | #define sid_log_notice(p, ...) SID_LOG_LINE(NULL, LOG_NOTICE, p, 0, __VA_ARGS__) 83 | #define sid_log_warning(p, ...) SID_LOG_LINE(NULL, LOG_WARNING, p, 0, __VA_ARGS__) 84 | #define sid_log_error(p, ...) SID_LOG_LINE(NULL, LOG_ERR, p, 0, __VA_ARGS__) 85 | #define sid_log_print(p, ...) SID_LOG_LINE(NULL, SID_LOG_PRINT, p, 0, __VA_ARGS__) 86 | #define sid_log_error_errno(p, e, ...) SID_LOG_LINE(NULL, LOG_ERR, p, e, __VA_ARGS__) 87 | #define sid_log_sys_error(p, x, y) log_error_errno(p, errno, "%s%s%s failed", y, *y ? ": " : "", x) 88 | 89 | #define sid_log_hdebug(h, p, ...) SID_LOG_LINE(h, LOG_DEBUG, p, 0, __VA_ARGS__) 90 | #define sid_log_hinfo(h, p, ...) SID_LOG_LINE(h, LOG_INFO, p, 0, __VA_ARGS__) 91 | #define sid_log_hnotice(h, p, ...) SID_LOG_LINE(h, LOG_NOTICE, p, 0, __VA_ARGS__) 92 | #define sid_log_hwarning(h, p, ...) SID_LOG_LINE(h, LOG_WARNING, p, 0, __VA_ARGS__) 93 | #define sid_log_herror(h, p, ...) SID_LOG_LINE(h, LOG_ERR, p, 0, __VA_ARGS__) 94 | #define sid_log_hprint(h, p, ...) SID_LOG_LINE(h, SID_LOG_PRINT, p, 0, __VA_ARGS__) 95 | #define sid_log_herror_errno(h, p, e, ...) SID_LOG_LINE(h, LOG_ERR, p, e, __VA_ARGS__) 96 | #define sid_log_hsys_error(h, p, x, y) sid_log_herror_errno(h, p, errno, "%s%s%s failed", y, *y ? ": " : "", x) 97 | 98 | #define SID_INTERNAL_ERROR "Internal error: " 99 | 100 | #ifdef __cplusplus 101 | } 102 | #endif 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /src/include/resource/mod-reg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_MOD_REG_H 8 | #define _SID_MOD_REG_H 9 | 10 | #include "resource/mod.h" 11 | #include "resource/res.h" 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | /* For use in struct sid_mod_reg_res_params.flags field. */ 18 | #define SID_MOD_REG_FL_PRELOAD UINT64_C(0x0000000000000001) 19 | 20 | /* For use in struct sid_mod_sym_params.flags field. */ 21 | #define SID_MOD_SYM_FL_WARN_ON_MISSING UINT64_C(0x0000000000000001) 22 | #define SID_MOD_SYM_FL_FAIL_ON_MISSING UINT64_C(0x0000000000000002) 23 | #define SID_MOD_SYM_FL_INDIRECT UINT64_C(0x0000000000000004) 24 | 25 | struct sid_mod_sym_params { 26 | const char *name; /* module symbol name */ 27 | uint64_t flags; /* SID_MOD_SYM_FL_* flags */ 28 | }; 29 | 30 | #define SID_MOD_SYM_PARAMS(...) ((struct sid_mod_sym_params) {__VA_ARGS__}) 31 | #define SID_MOD_SYM_PARAMS_ARRAY(...) ((struct sid_mod_sym_params[]) {__VA_ARGS__, SID_MOD_SYM_PARAMS()}) 32 | 33 | struct sid_mod_reg_res_params { 34 | const char *directory; /* directory with modules */ 35 | const char *module_prefix; /* common prefix for all modules */ 36 | const char *module_suffix; /* common suffix for all modules */ 37 | uint64_t flags; /* SID_MOD_REG_FL_* flags */ 38 | void *cb_arg; /* custom arg passed to module_cb_fn_t (init/exit/reset callbacks) */ 39 | const struct sid_mod_sym_params *symbol_params; /* NULL-terminated list of symbol params */ 40 | }; 41 | 42 | int sid_mod_reg_load_mods(sid_res_t *mod_registry_res); 43 | sid_res_t *sid_mod_reg_load_mod(sid_res_t *mod_registry_res, const char *mod_name); 44 | sid_res_t *sid_mod_reg_get_mod(sid_res_t *mod_registry_res, const char *mod_name); 45 | int sid_mod_reg_unload_mod(sid_res_t *mod_res); 46 | int sid_mod_reg_get_mod_syms(sid_res_t *mod_res, const void ***ret); 47 | 48 | int sid_mod_reg_reset_mods(sid_res_t *mod_registry_res); 49 | int sid_mod_reg_reset_mod(sid_res_t *mod_res); 50 | 51 | int sid_mod_reg_add_mod_subreg(sid_res_t *mod_res, sid_res_t *mod_subregistry_res); 52 | 53 | bool sid_mod_reg_match_dep(sid_res_t *res1, sid_res_t *res2); 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/include/resource/mod.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_MOD_H 8 | #define _SID_MOD_H 9 | 10 | #include "res.h" 11 | 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | struct sid_mod; 19 | 20 | typedef int64_t sid_mod_prio_t; 21 | typedef int sid_mod_cb_fn_t(sid_res_t *mod_res, void *cb_arg); 22 | 23 | #define SID_MOD_NAME_MAX_LEN 255 24 | #define SID_MOD_NAME_DELIM "/" 25 | #define SID_MOD_NAME_DELIM_LEN (sizeof(SID_MOD_NAME_DELIM) - 1) 26 | 27 | #define SID_MOD_FN(name, fn) sid_mod_cb_fn_t *sid_mod_##name = fn; 28 | 29 | #define SID_MOD_PRIO(val) sid_mod_prio_t sid_mod_prio = val; 30 | #define SID_MOD_ALIASES(val) const char *sid_mod_aliases = val "\0"; 31 | #define SID_MOD_INIT(fn) SID_MOD_FN(init, fn) 32 | #define SID_MOD_EXIT(fn) SID_MOD_FN(exit, fn) 33 | #define SID_MOD_RESET(fn) SID_MOD_FN(reset, fn) 34 | 35 | const char *sid_mod_get_full_name(sid_res_t *mod_res); 36 | const char *sid_mod_get_name(sid_res_t *mod_res); 37 | void sid_mod_set_data(sid_res_t *mod_res, void *data); 38 | void *sid_mod_get_data(sid_res_t *mod_res); 39 | 40 | #ifdef __cplusplus 41 | } 42 | #endif 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/include/resource/res-type-regs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_RESOURCE_TYPE_REGS_H 8 | #define _SID_RESOURCE_TYPE_REGS_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | extern const sid_res_type_t sid_res_type_aggr; 15 | extern const sid_res_type_t sid_res_type_kvs; 16 | extern const sid_res_type_t sid_res_type_mod_reg; 17 | extern const sid_res_type_t sid_res_type_sid; 18 | extern const sid_res_type_t sid_res_type_ubr; 19 | extern const sid_res_type_t sid_res_type_wrk_ctl; 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/include/resource/ubr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_UBR_H 8 | #define _SID_UBR_H 9 | 10 | #include "resource/res.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | int sid_ubr_cmd_dbdump(sid_res_t *ubridge_res, const char *file_path); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/include/resource/wrk-ctl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_WRK_CTL_H 8 | #define _SID_WRK_CTL_H 9 | 10 | #include "base/buf-common.h" 11 | #include "resource/res.h" 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | /* Basic worker properties */ 18 | typedef enum { 19 | SID_WRK_TYPE_INTERNAL, /* fork only to execute internal code */ 20 | SID_WRK_TYPE_EXTERNAL, /* fork + exec to execute external code */ 21 | } sid_wrk_type_t; 22 | 23 | typedef enum { 24 | SID_WRK_STATE_UNKNOWN, /* worker state is not known/not applicable */ 25 | SID_WRK_STATE_NEW, /* worker is newly created and it's not initialized yet */ 26 | SID_WRK_STATE_IDLE, /* worker is already initialized and it's idle at the moment */ 27 | SID_WRK_STATE_ASSIGNED, /* first message sent to worker for it to start execution */ 28 | SID_WRK_STATE_EXITING, /* worker yielded itself, exit signal sent back to worker, waiting for worker to exit */ 29 | SID_WRK_STATE_TIMED_OUT, /* worker has timed out, exit signal sent back to worker, waiting for worker to exit */ 30 | SID_WRK_STATE_EXITED, /* worker has exited */ 31 | } sid_wrk_state_t; 32 | 33 | /* Worker initialization specification */ 34 | typedef int sid_wrk_init_cb_fn_t(sid_res_t *res, void *arg); 35 | 36 | struct sid_wrk_init_cb_spec { 37 | sid_wrk_init_cb_fn_t *fn; 38 | void *arg; 39 | }; 40 | 41 | #define SID_WRK_INIT_CB_SPEC(...) ((struct sid_wrk_init_cb_spec) {__VA_ARGS__}) 42 | 43 | /* Wire specification */ 44 | typedef enum { 45 | SID_WRK_WIRE_NONE, 46 | SID_WRK_WIRE_PIPE_TO_WRK, /* pipe wire "proxy --> worker" */ 47 | SID_WRK_WIRE_PIPE_TO_PRX, /* pipe wire "proxy <-- worker" */ 48 | SID_WRK_WIRE_SOCKET, /* socket wire "proxy <--> worker" */ 49 | } sid_wrk_wire_type_t; 50 | 51 | struct sid_wrk_wire_spec { 52 | sid_wrk_wire_type_t type; 53 | 54 | struct { 55 | bool used; 56 | 57 | union { 58 | struct { 59 | int fd_redir; /* FD to redirect into/from a pipe (depending on pipe direction) on worker side */ 60 | } pipe; 61 | 62 | struct { 63 | int fd_redir; /* FD to redirect into a socket on worker side */ 64 | } socket; 65 | }; 66 | } ext; 67 | }; 68 | 69 | #define SID_WRK_WIRE_SPEC(...) ((struct sid_wrk_wire_spec) {__VA_ARGS__}) 70 | 71 | /* Transmit/receive data specification */ 72 | struct sid_wrk_data_spec { 73 | void *data; 74 | size_t data_size; 75 | 76 | struct { 77 | bool used; 78 | 79 | union { 80 | struct { 81 | int fd_pass; /* FD to pass through a socket wire */ 82 | } socket; 83 | }; 84 | } ext; 85 | }; 86 | 87 | #define SID_WRK_DATA_SPEC(...) ((struct sid_wrk_data_spec) {__VA_ARGS__}) 88 | 89 | /* Channel specification */ 90 | struct sid_wrk_chan; 91 | 92 | typedef int sid_wrk_lane_cb_fn_t(sid_res_t *res, struct sid_wrk_chan *channel, struct sid_wrk_data_spec *data_spec, void *arg); 93 | 94 | struct sid_wrk_lane_cb_spec { 95 | sid_wrk_lane_cb_fn_t *fn; 96 | void *arg; 97 | }; 98 | 99 | #define SID_WRK_LANE_CB_SPEC(...) ((struct sid_wrk_lane_cb_spec) {__VA_ARGS__}) 100 | 101 | struct sid_wrk_lane_spec { 102 | struct sid_wrk_lane_cb_spec cb; /* callback called on lane activity */ 103 | struct sid_buf_init buf_init; /* lane buffer initialization parameters */ 104 | struct iovec data_suffix; 105 | }; 106 | 107 | #define SID_WRK_LANE_SPEC(...) ((struct sid_wrk_lane_spec) {__VA_ARGS__}) 108 | 109 | struct sid_wrk_chan_spec { 110 | const char *id; 111 | struct sid_wrk_wire_spec wire; 112 | struct sid_wrk_lane_spec worker_tx; 113 | struct sid_wrk_lane_spec worker_rx; 114 | struct sid_wrk_lane_spec proxy_tx; 115 | struct sid_wrk_lane_spec proxy_rx; 116 | }; 117 | 118 | #define SID_WRK_CHAN_SPEC(...) ((struct sid_wrk_chan_spec) {__VA_ARGS__}) 119 | #define SID_WRK_CHAN_SPEC_ARRAY(...) ((struct sid_wrk_chan_spec[]) {__VA_ARGS__, SID_WRK_CHAN_SPEC()}) 120 | 121 | /* Timeout specification */ 122 | struct sid_wrk_timeout_spec { 123 | uint64_t usec; 124 | int signum; 125 | }; 126 | 127 | #define SID_WRK_TIMEOUT_SPEC(...) ((struct sid_wrk_timeout_spec) {__VA_ARGS__}) 128 | 129 | /* Worker-control resource parameters */ 130 | struct sid_wrk_ctl_res_params { 131 | sid_wrk_type_t worker_type; /* type of workers this controller creates */ 132 | struct sid_wrk_init_cb_spec init_cb_spec; /* worker initialization callback specification */ 133 | const struct sid_wrk_chan_spec *channel_specs; /* NULL-terminated list of proxy <-> worker channel specs */ 134 | const struct sid_wrk_timeout_spec timeout_spec; /* timeout specification */ 135 | }; 136 | 137 | int sid_wrk_ctl_chan_send(sid_res_t *res, const char *channel_id, struct sid_wrk_data_spec *data_spec); 138 | int sid_wrk_ctl_chan_close(sid_res_t *res, const char *channel_id); 139 | 140 | /* Worker creation/lookup. */ 141 | struct sid_wrk_params { 142 | const char *id; 143 | 144 | union { 145 | struct { 146 | const char *exec_file; 147 | const char *args; 148 | const char *env; 149 | } external; 150 | }; 151 | 152 | void *worker_arg; 153 | void *worker_proxy_arg; 154 | 155 | struct sid_wrk_timeout_spec timeout_spec; 156 | }; 157 | 158 | #define SID_WRK_PARAMS(...) ((struct sid_wrk_params) {__VA_ARGS__}) 159 | 160 | int sid_wrk_ctl_get_new_worker(sid_res_t *worker_control_res, struct sid_wrk_params *params, sid_res_t **res_p); 161 | int sid_wrk_ctl_run_new_worker(sid_res_t *worker_control_res, 162 | struct sid_wrk_params *params, 163 | sid_res_srv_lnk_def_t service_link_defs[]); 164 | int sid_wrk_ctl_run_worker(sid_res_t *worker_control_res, sid_res_srv_lnk_def_t service_link_defs[]); 165 | sid_res_t *sid_wrk_ctl_get_idle_worker(sid_res_t *worker_control_res); 166 | sid_res_t *sid_wrk_ctl_find_worker(sid_res_t *worker_control_res, const char *id); 167 | 168 | /* Worker utility functions. */ 169 | bool sid_wrk_ctl_detect_worker(sid_res_t *res); 170 | sid_wrk_state_t sid_wrk_ctl_get_worker_state(sid_res_t *res); 171 | const char *sid_wrk_ctl_get_worker_id(sid_res_t *res); 172 | void *sid_wrk_ctl_get_worker_arg(sid_res_t *res); 173 | 174 | /* Yield current worker and make it available for others to use. */ 175 | int sid_wrk_ctl_yield_worker(sid_res_t *res); 176 | 177 | #ifdef __cplusplus 178 | } 179 | #endif 180 | 181 | #endif 182 | -------------------------------------------------------------------------------- /src/internal/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | include $(top_srcdir)/Makefile.common 8 | 9 | pkglib_LTLIBRARIES = libsidinternal.la 10 | 11 | libsidinternal_la_SOURCES = mem.c \ 12 | bmp.c \ 13 | list.c \ 14 | util.c \ 15 | hash.c \ 16 | fmt.c \ 17 | bptree.c 18 | 19 | internaldir = $(pkgincludedir)/internal 20 | 21 | internal_HEADERS = $(top_srcdir)/src/include/internal/common.h \ 22 | $(top_srcdir)/src/include/internal/comp-attrs.h \ 23 | $(top_srcdir)/src/include/internal/mem.h \ 24 | $(top_srcdir)/src/include/internal/bmp.h \ 25 | $(top_srcdir)/src/include/internal/list.h \ 26 | $(top_srcdir)/src/include/internal/util.h \ 27 | $(top_srcdir)/src/include/internal/fmt.h \ 28 | $(top_srcdir)/src/include/internal/hash.h \ 29 | $(top_srcdir)/src/include/internal/bptree.h 30 | 31 | libsidinternal_la_CFLAGS = $(UUID_CFLAGS) 32 | 33 | libsidinternal_la_LDFLAGS = -version-info 0:0:0 34 | 35 | libsidinternal_la_LIBADD = $(UUID_LIBS) $(top_builddir)/src/base/libsidbase.la 36 | 37 | uninstall-hook: 38 | test -d ${DESTDIR}${internaldir} && rmdir ${DESTDIR}${internaldir} 39 | -------------------------------------------------------------------------------- /src/internal/bmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "internal/comp-attrs.h" 8 | 9 | #include "internal/bmp.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | struct bmp { 17 | size_t bit_count; 18 | size_t bit_set_count; 19 | unsigned mem[]; 20 | } __packed; 21 | 22 | #define BLOCK_SIZE sizeof(unsigned) 23 | #define BITS_PER_BLOCK (BLOCK_SIZE * CHAR_BIT) 24 | static unsigned BLOCK_SHIFT = 0; 25 | 26 | static unsigned _log2n_recursive(unsigned n) 27 | { 28 | return n > 1 ? _log2n_recursive(n / 2) + 1 : 0; 29 | } 30 | 31 | __constructor static void _init_bmp() 32 | { 33 | BLOCK_SHIFT = _log2n_recursive(BITS_PER_BLOCK); 34 | } 35 | 36 | struct bmp *bmp_create(size_t bit_count, bool invert, int *ret_code) 37 | { 38 | size_t mem_size; 39 | struct bmp *bmp = NULL; 40 | int r = 0; 41 | 42 | if (!bit_count) { 43 | r = -EINVAL; 44 | goto out; 45 | } 46 | 47 | mem_size = ((bit_count - 1) / BITS_PER_BLOCK + 1) * BLOCK_SIZE; 48 | 49 | if (!(bmp = malloc(sizeof(struct bmp) + mem_size))) { 50 | r = -ENOMEM; 51 | goto out; 52 | } 53 | 54 | bmp->bit_count = bit_count; 55 | 56 | if (invert) { 57 | memset(bmp->mem, UCHAR_MAX, mem_size); 58 | bmp->bit_set_count = bit_count; 59 | } else { 60 | memset(bmp->mem, 0, mem_size); 61 | bmp->bit_set_count = 0; 62 | } 63 | out: 64 | if (ret_code) 65 | *ret_code = r; 66 | return bmp; 67 | } 68 | 69 | void bmp_destroy(struct bmp *bmp) 70 | { 71 | free(bmp); 72 | } 73 | 74 | static int _get_coord(struct bmp *bmp, size_t bit_pos, unsigned *block, unsigned *bit) 75 | { 76 | if (bit_pos >= bmp->bit_count) 77 | return -ERANGE; 78 | 79 | *block = bit_pos >> BLOCK_SHIFT; 80 | *bit = 1 << (bit_pos & (BITS_PER_BLOCK - 1)); 81 | 82 | return 0; 83 | } 84 | 85 | int bmp_set_bit(struct bmp *bmp, size_t bit_pos) 86 | { 87 | unsigned block, bit; 88 | int r; 89 | 90 | if ((r = _get_coord(bmp, bit_pos, &block, &bit)) < 0) 91 | return r; 92 | 93 | if (!(bmp->mem[block] & bit)) { 94 | bmp->mem[block] |= bit; 95 | bmp->bit_set_count++; 96 | } 97 | 98 | return 0; 99 | } 100 | 101 | int bmp_unset_bit(struct bmp *bmp, size_t bit_pos) 102 | { 103 | unsigned block, bit; 104 | int r; 105 | 106 | if ((r = _get_coord(bmp, bit_pos, &block, &bit)) < 0) 107 | return r; 108 | 109 | if (bmp->mem[block] & bit) { 110 | bmp->mem[block] &= ~bit; 111 | bmp->bit_set_count--; 112 | } 113 | 114 | return 0; 115 | } 116 | 117 | bool bmp_bit_is_set(struct bmp *bmp, size_t bit_pos, int *ret_code) 118 | { 119 | unsigned block, bit; 120 | int r; 121 | 122 | if ((r = _get_coord(bmp, bit_pos, &block, &bit)) < 0) { 123 | if (ret_code) 124 | *ret_code = r; 125 | return 0; 126 | } 127 | 128 | return bmp->mem[block] & bit; 129 | } 130 | 131 | size_t bmp_get_bit_count(struct bmp *bmp) 132 | { 133 | return bmp->bit_count; 134 | } 135 | 136 | size_t bmp_get_bit_set_count(struct bmp *bmp) 137 | { 138 | return bmp->bit_set_count; 139 | } 140 | -------------------------------------------------------------------------------- /src/internal/list.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2001-2004 Sistina Software, Inc. 3 | * SPDX-FileCopyrightText: (C) 2004-2025 Red Hat, Inc. 4 | * 5 | * SPDX-License-Identifier: GPL-2.0-or-later 6 | */ 7 | 8 | #include "internal/list.h" 9 | 10 | void list_init(struct list *head) 11 | { 12 | head->n = head->p = head; 13 | } 14 | 15 | void list_add(struct list *head, struct list *elem) 16 | { 17 | elem->n = head; 18 | elem->p = head->p; 19 | head->p->n = elem; 20 | head->p = elem; 21 | } 22 | 23 | void list_del(struct list *elem) 24 | { 25 | elem->n->p = elem->p; 26 | elem->p->n = elem->n; 27 | } 28 | 29 | bool list_is_empty(const struct list *head) 30 | { 31 | return head->n == head; 32 | } 33 | 34 | unsigned int list_get_size(const struct list *head) 35 | { 36 | unsigned int i = 0; 37 | const struct list *v; 38 | 39 | list_iterate (v, head) 40 | i++; 41 | 42 | return i; 43 | } 44 | -------------------------------------------------------------------------------- /src/internal/mem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "internal/mem.h" 8 | 9 | #include 10 | 11 | void *mem_zalloc(size_t size) 12 | { 13 | void *p; 14 | 15 | if ((p = malloc(size))) 16 | memset(p, 0, size); 17 | 18 | return p; 19 | } 20 | 21 | void *mem_freen(void *mem) 22 | { 23 | free(mem); 24 | return NULL; 25 | } 26 | -------------------------------------------------------------------------------- /src/log/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | include $(top_srcdir)/Makefile.common 8 | 9 | pkglib_LTLIBRARIES = libsidlog.la 10 | 11 | libsidlog_la_SOURCES = log-target-standard.c \ 12 | log-target-syslog.c \ 13 | log-target-journal.c \ 14 | log.c 15 | 16 | logdir = $(pkgincludedir)/log 17 | 18 | log_HEADERS = $(top_srcdir)/src/include/log/log.h 19 | 20 | libsidlog_la_LIBADD = $(SYSTEMD_LIBS) 21 | 22 | libsidlog_la_LDFLAGS = -version-info 0:0:0 23 | 24 | uninstall-hook: 25 | test -d ${DESTDIR}${logdir} && rmdir ${DESTDIR}${logdir} 26 | -------------------------------------------------------------------------------- /src/log/log-target-journal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "log/log.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | static int _max_level_id = -1; 15 | static int _force_err_out = 0; 16 | static int _with_pids = 0; 17 | static int _with_src_info = 1; 18 | 19 | static void _log_journal_open(int verbose_mode) 20 | { 21 | switch (verbose_mode) { 22 | case 0: 23 | _max_level_id = LOG_NOTICE; 24 | break; 25 | case 1: 26 | _max_level_id = LOG_INFO; 27 | break; 28 | case 2: 29 | _max_level_id = LOG_DEBUG; 30 | break; 31 | case 3: 32 | _max_level_id = LOG_DEBUG; 33 | _with_src_info = 1; 34 | _force_err_out = 1; 35 | break; 36 | default: 37 | _max_level_id = LOG_DEBUG; 38 | _with_src_info = 1; 39 | _force_err_out = 1; 40 | _with_pids = 1; 41 | break; 42 | } 43 | } 44 | 45 | static void _log_journal_close(void) 46 | { 47 | fflush(stdout); 48 | fflush(stderr); 49 | } 50 | 51 | static void _log_journal_output(const sid_log_req_t *req, const char *format, va_list ap) 52 | { 53 | char msg[LINE_MAX]; 54 | sid_log_pfx_t *pfx; 55 | size_t printed, remaining; 56 | int r; 57 | 58 | if (req->ctx->level_id > _max_level_id) 59 | return; 60 | 61 | for (printed = 0, remaining = sizeof(msg), pfx = req->pfx; pfx; pfx = pfx->n) { 62 | r = snprintf(msg + printed, remaining, "<%s> ", pfx->s ?: ""); 63 | 64 | if (r >= remaining) { 65 | sd_journal_send("MESSAGE=(log prefix too long)", 66 | "PRIORITY=%d", 67 | req->ctx->level_id, 68 | "CODE_FILE=%s", 69 | req->ctx->src_file, 70 | "CODE_LINE=%d", 71 | req->ctx->src_line, 72 | "CODE_FUNC=%s", 73 | req->ctx->src_func, 74 | NULL); 75 | return; 76 | } 77 | 78 | remaining -= r; 79 | printed += r; 80 | } 81 | 82 | r = vsnprintf(msg + printed, remaining, format, ap); 83 | 84 | if (r < 0 || r >= remaining) 85 | sd_journal_send("MESSAGE=(log message truncated)", 86 | "PRIORITY=%d", 87 | req->ctx->level_id, 88 | "CODE_FILE=%s", 89 | req->ctx->src_file, 90 | "CODE_LINE=%d", 91 | req->ctx->src_line, 92 | "CODE_FUNC=%s", 93 | req->ctx->src_func, 94 | NULL); 95 | 96 | if (r > 0) { 97 | if (_with_src_info) 98 | sd_journal_send("MESSAGE=%s", 99 | msg, 100 | "PREFIX=%s", 101 | req->pfx ? req->pfx->s : "", 102 | "PRIORITY=%d", 103 | req->ctx->level_id, 104 | "CODE_FILE=%s", 105 | req->ctx->src_file, 106 | "CODE_LINE=%d", 107 | req->ctx->src_line, 108 | "CODE_FUNC=%s", 109 | req->ctx->src_func, 110 | NULL); 111 | else 112 | sd_journal_send("MESSAGE=%s", 113 | msg, 114 | "PREFIX=%s", 115 | req->pfx ? req->pfx->s : "", 116 | "PRIORITY=%d", 117 | req->ctx->level_id, 118 | NULL); 119 | } 120 | } 121 | 122 | const struct sid_log_tgt log_target_journal = {.name = "journal", 123 | .open = _log_journal_open, 124 | .close = _log_journal_close, 125 | .output = _log_journal_output}; 126 | -------------------------------------------------------------------------------- /src/log/log-target-standard.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "log/log.h" 8 | 9 | #include 10 | #include 11 | 12 | static int _max_level_id = -1; 13 | static int _force_err_out = 0; 14 | static int _with_pids = 0; 15 | static int _with_src_info = 0; 16 | 17 | static void _log_standard_open(int verbose_mode) 18 | { 19 | switch (verbose_mode) { 20 | case 0: 21 | _max_level_id = LOG_NOTICE; 22 | break; 23 | case 1: 24 | _max_level_id = LOG_INFO; 25 | break; 26 | case 2: 27 | _max_level_id = LOG_DEBUG; 28 | break; 29 | case 3: 30 | _max_level_id = LOG_DEBUG; 31 | _with_src_info = 1; 32 | _force_err_out = 1; 33 | break; 34 | default: 35 | _max_level_id = LOG_DEBUG; 36 | _with_src_info = 1; 37 | _force_err_out = 1; 38 | _with_pids = 1; 39 | break; 40 | } 41 | } 42 | 43 | static void _log_standard_close(void) 44 | { 45 | fflush(stdout); 46 | fflush(stderr); 47 | } 48 | 49 | static void _log_standard_output(const sid_log_req_t *req, const char *format, va_list ap) 50 | { 51 | FILE *out_file; 52 | sid_log_pfx_t *pfx; 53 | 54 | if (req->ctx->level_id > _max_level_id && req->ctx->level_id != SID_LOG_PRINT) 55 | return; 56 | 57 | out_file = _force_err_out ? stderr : req->ctx->level_id <= LOG_WARNING ? stderr : stdout; 58 | 59 | if (_with_pids) 60 | fprintf(out_file, "[%d:%d]:", getppid(), getpid()); 61 | 62 | if (_with_src_info) 63 | fprintf(out_file, 64 | "%s:%d%s%s\t", 65 | req->ctx->src_file, 66 | req->ctx->src_line, 67 | req->ctx->src_func ? ":" : "", 68 | req->ctx->src_func ?: ""); 69 | 70 | for (pfx = req->pfx; pfx; pfx = pfx->n) 71 | fprintf(out_file, "<%s> ", pfx->s ?: ""); 72 | 73 | vfprintf(out_file, format, ap); 74 | 75 | if (req->ctx->errno_id) 76 | fprintf(out_file, ": %s.", strerror(req->ctx->errno_id)); 77 | 78 | fputc('\n', out_file); 79 | } 80 | 81 | const struct sid_log_tgt log_target_standard = {.name = "standard", 82 | .open = _log_standard_open, 83 | .close = _log_standard_close, 84 | .output = _log_standard_output}; 85 | -------------------------------------------------------------------------------- /src/log/log-target-syslog.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "log/log.h" 8 | 9 | #include 10 | #include 11 | 12 | #define SID_SYSLOG_IDENT "sid" 13 | 14 | static int _max_level_id = -1; 15 | 16 | static void _log_syslog_open(int verbose_mode) 17 | { 18 | switch (verbose_mode) { 19 | case 0: 20 | _max_level_id = LOG_NOTICE; 21 | break; 22 | case 1: 23 | _max_level_id = LOG_INFO; 24 | break; 25 | default: 26 | _max_level_id = LOG_DEBUG; 27 | break; 28 | } 29 | 30 | openlog(SID_SYSLOG_IDENT, LOG_PID, LOG_DAEMON); 31 | } 32 | 33 | static void _log_syslog_close(void) 34 | { 35 | closelog(); 36 | } 37 | 38 | static void _log_syslog_output(const sid_log_req_t *req, const char *format, va_list ap) 39 | { 40 | char msg[LINE_MAX]; 41 | sid_log_pfx_t *pfx; 42 | size_t printed, remaining; 43 | int r; 44 | 45 | if (req->ctx->level_id > _max_level_id) 46 | return; 47 | 48 | for (printed = 0, remaining = sizeof(msg), pfx = req->pfx; pfx; pfx = pfx->n) { 49 | r = snprintf(msg, sizeof(msg), "<%s> ", pfx->s ?: ""); 50 | 51 | if (r >= remaining) { 52 | syslog(req->ctx->level_id, SID_INTERNAL_ERROR "%s: (log prefix too long)", __func__); 53 | vsyslog(req->ctx->level_id, format, ap); 54 | return; 55 | } 56 | 57 | remaining -= r; 58 | printed += r; 59 | } 60 | 61 | r = vsnprintf(msg + printed, remaining, format, ap); 62 | 63 | if (r < 0 || r >= remaining) 64 | syslog(req->ctx->level_id, SID_INTERNAL_ERROR "%s: (log message truncated)", __func__); 65 | 66 | if (r > 0) 67 | syslog(req->ctx->level_id, "%s", msg); 68 | } 69 | 70 | const struct sid_log_tgt log_target_syslog = {.name = "syslog", 71 | .open = _log_syslog_open, 72 | .close = _log_syslog_close, 73 | .output = _log_syslog_output}; 74 | -------------------------------------------------------------------------------- /src/log/log.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "log/log.h" 8 | 9 | struct sid_log { 10 | int handle_required; 11 | sid_log_tgt_t target; 12 | int verbose_mode; 13 | const char *prefix; 14 | } _log = {SID_LOG_TGT_NONE, 0}; 15 | 16 | static const struct sid_log_tgt *log_target_registry[] = {[SID_LOG_TGT_STANDARD] = &log_target_standard, 17 | [SID_LOG_TGT_SYSLOG] = &log_target_syslog, 18 | [SID_LOG_TGT_JOURNAL] = &log_target_journal}; 19 | 20 | void sid_log_init(sid_log_tgt_t target, int verbose_mode) 21 | { 22 | if (_log.target != SID_LOG_TGT_NONE) 23 | return; 24 | 25 | _log.handle_required = 0; 26 | _log.target = target; 27 | _log.verbose_mode = verbose_mode; 28 | 29 | if (target != SID_LOG_TGT_NONE) 30 | log_target_registry[_log.target]->open(verbose_mode); 31 | } 32 | 33 | sid_log_t *sid_log_init_with_handle(sid_log_tgt_t target, int verbose_mode) 34 | { 35 | sid_log_init(target, verbose_mode); 36 | _log.handle_required = 1; 37 | 38 | return &_log; 39 | } 40 | 41 | void sid_log_close(sid_log_t *log) 42 | { 43 | if (log && log != &_log) 44 | return; 45 | 46 | if (_log.target != SID_LOG_TGT_NONE) 47 | log_target_registry[_log.target]->close(); 48 | } 49 | 50 | void sid_log_change_tgt(sid_log_t *log, sid_log_tgt_t new_target) 51 | { 52 | if (!log || log->target == new_target) 53 | return; 54 | 55 | if (log->target != SID_LOG_TGT_NONE) 56 | log_target_registry[log->target]->close(); 57 | if (new_target != SID_LOG_TGT_NONE) 58 | log_target_registry[new_target]->open(log->verbose_mode); 59 | 60 | log->target = new_target; 61 | } 62 | 63 | void sid_log_set_pfx(sid_log_t *log, const char *prefix) 64 | { 65 | if (!log) 66 | return; 67 | 68 | log->prefix = prefix; 69 | } 70 | 71 | void sid_log_voutput(sid_log_t *log, sid_log_req_t *req, const char *format, va_list ap) 72 | { 73 | static int log_ignored = 0; 74 | int orig_errno = errno; 75 | sid_log_req_t tmp_req; 76 | sid_log_pfx_t pfx; 77 | 78 | if (log && log->prefix) { 79 | pfx.s = log->prefix; 80 | pfx.n = req->pfx; 81 | tmp_req.pfx = &pfx; 82 | tmp_req.ctx = req->ctx; 83 | req = &tmp_req; 84 | } 85 | 86 | if (_log.handle_required && (log != &_log)) { 87 | if (!log_ignored) { 88 | tmp_req.pfx = NULL; 89 | tmp_req.ctx = &((sid_log_ctx_t) {.level_id = LOG_ERR, 90 | .errno_id = 0, 91 | .src_file = req->ctx->src_file, 92 | .src_line = req->ctx->src_line, 93 | .src_func = req->ctx->src_func}); 94 | sid_log_voutput(&_log, 95 | &tmp_req, 96 | SID_INTERNAL_ERROR "Incorrect or missing log handle, skipping log messages.", 97 | ap); 98 | log_ignored = 1; 99 | } 100 | goto out; 101 | } 102 | 103 | if (_log.target == SID_LOG_TGT_NONE) 104 | return; 105 | 106 | if (req->ctx->errno_id < 0) 107 | req->ctx->errno_id = -req->ctx->errno_id; 108 | 109 | log_target_registry[_log.target]->output(req, format, ap); 110 | out: 111 | errno = orig_errno; 112 | } 113 | 114 | void sid_log_output(sid_log_t *log, sid_log_req_t *req, const char *format, ...) 115 | { 116 | va_list ap; 117 | 118 | va_start(ap, format); 119 | sid_log_voutput(log, req, format, ap); 120 | va_end(ap); 121 | } 122 | -------------------------------------------------------------------------------- /src/modules/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | SUBDIRS = ucmd 8 | 9 | uninstall-hook: 10 | test -d ${DESTDIR}${pkglibdir}/modules && rmdir ${DESTDIR}${pkglibdir}/modules || true 11 | -------------------------------------------------------------------------------- /src/modules/ucmd/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | SUBDIRS = type block 8 | 9 | uninstall-hook: 10 | test -d ${DESTDIR}${pkglibdir}/modules/ucmd && rmdir ${DESTDIR}${pkglibdir}/modules/ucmd || true 11 | -------------------------------------------------------------------------------- /src/modules/ucmd/block/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | SUBDIRS = 8 | 9 | if BUILD_MOD_UCMD_BLOCK_BLKID 10 | SUBDIRS += blkid 11 | endif 12 | 13 | if BUILD_MOD_UCMD_BLOCK_DM_MPATH 14 | SUBDIRS += dm_mpath 15 | endif 16 | 17 | if BUILD_MOD_UCMD_BLOCK_DUMMY 18 | SUBDIRS += dummy_block 19 | endif 20 | 21 | uninstall-hook: 22 | test -d ${DESTDIR}${pkglibdir}/modules/ucmd/block && rmdir ${DESTDIR}${pkglibdir}/modules/ucmd/block || true 23 | -------------------------------------------------------------------------------- /src/modules/ucmd/block/blkid/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | include $(top_srcdir)/Makefile.common 8 | 9 | blkiddir = $(pkglibdir)/modules/ucmd/block 10 | 11 | %.c: %.gperf 12 | $(AM_V_GEN) \ 13 | if $(GPERF) $(GPERFFLAGS) < $< >$@.temp; then \ 14 | mv $@.temp $@; \ 15 | elif $(GPERF) --version >/dev/null 2>&1; then \ 16 | $(RM) $@.temp; \ 17 | exit 1; \ 18 | else \ 19 | $(RM) $@.temp; \ 20 | touch $@; \ 21 | fi 22 | 23 | blkid_LTLIBRARIES = blkid.la 24 | 25 | blkid_la_SOURCES = blkid-type.h \ 26 | blkid-type-mapper.c \ 27 | blkid-key.h \ 28 | blkid-key-mapper.c \ 29 | blkid.c 30 | 31 | blkid_la_CFLAGS = $(BLKID_CFLAGS) 32 | 33 | blkid_la_LDFLAGS = -module -avoid-version 34 | 35 | blkid_la_LIBADD = $(top_builddir)/src/resource/libsidresource.la \ 36 | $(BLKID_LIBS) 37 | 38 | EXTRA_DIST = blkid-type-mapper.gperf \ 39 | blkid-key-mapper.gperf 40 | 41 | mostlyclean-local: 42 | $(RM) blkid-type-mapper.c 43 | -------------------------------------------------------------------------------- /src/modules/ucmd/block/blkid/blkid-key-mapper.gperf: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | %{ 8 | #include "blkid-key.h" 9 | 10 | #define BLKID_XKEY(key, flags) [U_ID_##key] = (const struct blkid_xkey) {U_ID_##key, "ID_" #key, flags} 11 | 12 | const struct blkid_xkey blkid_xkey_arr[] = { 13 | BLKID_XKEY(FS_TYPE, BLKID_FL_ENC), 14 | BLKID_XKEY(FS_USAGE, BLKID_FL_ORIG), 15 | BLKID_XKEY(FS_VERSION, BLKID_FL_ENC), 16 | BLKID_XKEY(FS_UUID, BLKID_FL_ORIG | BLKID_FL_SAFE | BLKID_FL_ENC), 17 | BLKID_XKEY(FS_UUID_ENC, BLKID_FL_NONE), 18 | BLKID_XKEY(FS_UUID_SUB, BLKID_FL_ORIG | BLKID_FL_SAFE | BLKID_FL_ENC), 19 | BLKID_XKEY(FS_UUID_SUB_ENC, BLKID_FL_NONE), 20 | BLKID_XKEY(FS_LABEL, BLKID_FL_ORIG | BLKID_FL_SAFE | BLKID_FL_ENC), 21 | BLKID_XKEY(FS_LABEL_ENC, BLKID_FL_NONE), 22 | BLKID_XKEY(FS_SIZE, BLKID_FL_ORIG), 23 | BLKID_XKEY(FS_LASTBLOCK, BLKID_FL_ORIG), 24 | BLKID_XKEY(FS_BLOCKSIZE, BLKID_FL_ORIG), 25 | BLKID_XKEY(FS_SYSTEM_ID, BLKID_FL_ENC), 26 | BLKID_XKEY(FS_PUBLISHER_ID, BLKID_FL_ENC), 27 | BLKID_XKEY(FS_APPLICATION_ID, BLKID_FL_ENC), 28 | BLKID_XKEY(FS_BOOT_SYSTEM_ID, BLKID_FL_ENC), 29 | BLKID_XKEY(FS_VOLUME_ID, BLKID_FL_ENC), 30 | BLKID_XKEY(FS_LOGICAL_VOLUME_ID, BLKID_FL_ENC), 31 | BLKID_XKEY(FS_VOLUME_SET_ID, BLKID_FL_ENC), 32 | BLKID_XKEY(FS_DATA_PREPARER_ID, BLKID_FL_ENC), 33 | BLKID_XKEY(PART_TABLE_UUID, BLKID_FL_ORIG), 34 | BLKID_XKEY(PART_TABLE_TYPE, BLKID_FL_ORIG), 35 | BLKID_XKEY(PART_ENTRY_SCHEME, BLKID_FL_ORIG), 36 | BLKID_XKEY(PART_ENTRY_NAME, BLKID_FL_ENC), 37 | BLKID_XKEY(PART_ENTRY_TYPE, BLKID_FL_ENC), 38 | BLKID_XKEY(PART_ENTRY_UUID, BLKID_FL_ORIG), 39 | BLKID_XKEY(PART_ENTRY_FLAGS, BLKID_FL_ORIG), 40 | BLKID_XKEY(PART_ENTRY_NUMBER, BLKID_FL_ORIG), 41 | BLKID_XKEY(PART_ENTRY_OFFSET, BLKID_FL_ORIG), 42 | BLKID_XKEY(PART_ENTRY_SIZE, BLKID_FL_ORIG), 43 | BLKID_XKEY(PART_ENTRY_DISK, BLKID_FL_ORIG), 44 | BLKID_XKEY(NUM_KEYS, BLKID_FL_ORIG), 45 | }; 46 | 47 | #define BLKID_XKEY_GET(i) &blkid_xkey_arr[i] 48 | 49 | %} 50 | struct blkid_key; 51 | %language=ANSI-C 52 | %includes 53 | %null-strings 54 | %omit-struct-type 55 | %struct-type 56 | %define slot-name blkid_key_name 57 | %define hash-function-name blkid_key_hash 58 | %define lookup-function-name blkid_key_lookup 59 | %readonly-tables 60 | %% 61 | TYPE, BLKID_XKEY_GET(U_ID_FS_TYPE) 62 | USAGE, BLKID_XKEY_GET(U_ID_FS_USAGE) 63 | VERSION, BLKID_XKEY_GET(U_ID_FS_VERSION) 64 | UUID, BLKID_XKEY_GET(U_ID_FS_UUID) 65 | UUID_SUB, BLKID_XKEY_GET(U_ID_FS_UUID_SUB) 66 | LABEL, BLKID_XKEY_GET(U_ID_FS_LABEL) 67 | FSSIZE, BLKID_XKEY_GET(U_ID_FS_SIZE) 68 | FSLASTBLOCK, BLKID_XKEY_GET(U_ID_FS_LASTBLOCK) 69 | FSBLOCKSIZE, BLKID_XKEY_GET(U_ID_FS_BLOCKSIZE) 70 | SYSTEM_ID, BLKID_XKEY_GET(U_ID_FS_SYSTEM_ID) 71 | PUBLISHER_ID, BLKID_XKEY_GET(U_ID_FS_PUBLISHER_ID) 72 | APPLICATION_ID, BLKID_XKEY_GET(U_ID_FS_APPLICATION_ID) 73 | BOOT_SYSTEM_ID, BLKID_XKEY_GET(U_ID_FS_BOOT_SYSTEM_ID) 74 | VOLUME_ID, BLKID_XKEY_GET(U_ID_FS_VOLUME_ID) 75 | LOGICAL_VOLUME_ID, BLKID_XKEY_GET(U_ID_FS_LOGICAL_VOLUME_ID) 76 | VOLUME_SET_ID, BLKID_XKEY_GET(U_ID_FS_VOLUME_SET_ID) 77 | DATA_PREPARER_ID, BLKID_XKEY_GET(U_ID_FS_DATA_PREPARER_ID) 78 | PTUUID, BLKID_XKEY_GET(U_ID_PART_TABLE_UUID) 79 | PTTYPE, BLKID_XKEY_GET(U_ID_PART_TABLE_TYPE) 80 | PART_ENTRY_SCHEME, BLKID_XKEY_GET(U_ID_PART_ENTRY_SCHEME) 81 | PART_ENTRY_NAME BLKID_XKEY_GET(U_ID_PART_ENTRY_NAME) 82 | PART_ENTRY_TYPE BLKID_XKEY_GET(U_ID_PART_ENTRY_TYPE) 83 | PART_ENTRY_UUID BLKID_XKEY_GET(U_ID_PART_ENTRY_UUID) 84 | PART_ENTRY_FLAGS BLKID_XKEY_GET(U_ID_PART_ENTRY_FLAGS) 85 | PART_ENTRY_NUMBER BLKID_XKEY_GET(U_ID_PART_ENTRY_NUMBER) 86 | PART_ENTRY_OFFSET BLKID_XKEY_GET(U_ID_PART_ENTRY_OFFSET) 87 | PART_ENTRY_SIZE BLKID_XKEY_GET(U_ID_PART_ENTRY_SIZE) 88 | PART_ENTRY_DISK BLKID_XKEY_GET(U_ID_PART_ENTRY_DISK) 89 | -------------------------------------------------------------------------------- /src/modules/ucmd/block/blkid/blkid-key.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef SID_BLKID_KEY_H 8 | #define SID_BLKID_KEY_H 9 | 10 | #include 11 | 12 | #define BLKID_FL_NONE 0x00 13 | #define BLKID_FL_ORIG 0x01 14 | #define BLKID_FL_SAFE 0x02 15 | #define BLKID_FL_ENC 0x04 16 | 17 | struct blkid_xkey { 18 | unsigned num; 19 | const char *name; 20 | unsigned flags; 21 | }; 22 | 23 | struct blkid_key { 24 | const char *blkid_key_name; 25 | const struct blkid_xkey *xkey; 26 | }; 27 | 28 | enum { 29 | U_ID_FS_TYPE, 30 | U_ID_FS_USAGE, 31 | U_ID_FS_VERSION, 32 | U_ID_FS_UUID, 33 | U_ID_FS_UUID_ENC, 34 | U_ID_FS_UUID_SUB, 35 | U_ID_FS_UUID_SUB_ENC, 36 | U_ID_FS_LABEL, 37 | U_ID_FS_LABEL_ENC, 38 | U_ID_FS_SIZE, 39 | U_ID_FS_LASTBLOCK, 40 | U_ID_FS_BLOCKSIZE, 41 | U_ID_FS_SYSTEM_ID, 42 | U_ID_FS_PUBLISHER_ID, 43 | U_ID_FS_APPLICATION_ID, 44 | U_ID_FS_BOOT_SYSTEM_ID, 45 | U_ID_FS_VOLUME_ID, 46 | U_ID_FS_LOGICAL_VOLUME_ID, 47 | U_ID_FS_VOLUME_SET_ID, 48 | U_ID_FS_DATA_PREPARER_ID, 49 | U_ID_PART_TABLE_UUID, 50 | U_ID_PART_TABLE_TYPE, 51 | U_ID_PART_ENTRY_SCHEME, 52 | U_ID_PART_ENTRY_NAME, 53 | U_ID_PART_ENTRY_TYPE, 54 | U_ID_PART_ENTRY_UUID, 55 | U_ID_PART_ENTRY_FLAGS, 56 | U_ID_PART_ENTRY_NUMBER, 57 | U_ID_PART_ENTRY_OFFSET, 58 | U_ID_PART_ENTRY_SIZE, 59 | U_ID_PART_ENTRY_DISK, 60 | U_ID_NUM_KEYS, 61 | }; 62 | 63 | extern const struct blkid_xkey blkid_xkey_arr[]; 64 | 65 | const struct blkid_key *blkid_key_lookup(const char *key, size_t len); 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /src/modules/ucmd/block/blkid/blkid-type-mapper.gperf: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | %{ 8 | #include "blkid-type.h" 9 | %} 10 | struct blkid_type; 11 | %language=ANSI-C 12 | %includes 13 | %null-strings 14 | %omit-struct-type 15 | %struct-type 16 | %define slot-name blkid_type_name 17 | %define hash-function-name blkid_type_hash 18 | %define lookup-function-name blkid_type_lookup 19 | %readonly-tables 20 | %% 21 | linux_raid_member, MOD_NAME_MD 22 | ddf_raid_member, MOD_NAME_MD 23 | isw_raid_member, MOD_NAME_MD 24 | lsi_mega_raid_member, MOD_NAME_MD 25 | via_raid_member, MOD_NAME_MD 26 | silicon_medley_raid_member, MOD_NAME_MD 27 | nvidia_raid_member, MOD_NAME_MD 28 | promise_fasttrack_raid_member, MOD_NAME_MD 29 | hpt45x_raid_member, MOD_NAME_MD 30 | hpt37x_raid_member, MOD_NAME_MD 31 | adaptec_raid_member, MOD_NAME_MD 32 | jmicron_raid_member, MOD_NAME_MD 33 | bcache, MOD_NAME_BCACHE 34 | bcachefs, MOD_NAME_FS 35 | ceph_bluestore, MOD_NAME_CEPH 36 | drbd, MOD_NAME_DRBD 37 | drbdmanage_control_volume, MOD_NAME_DRBD 38 | drbdproxy_datalog, MOD_NAME_DRBD 39 | LVM2_member, MOD_NAME_DM 40 | LVM1_member, MOD_NAME_DM 41 | DM_snapshot_cow, MOD_NAME_DM 42 | DM_verity_hash, MOD_NAME_DM 43 | DM_integrity, MOD_NAME_DM 44 | crypto_LUKS, MOD_NAME_DM 45 | VMFS_volume_member, MOD_NAME_FS 46 | ubi, MOD_NAME_UBI 47 | vdo, MOD_NAME_VDO 48 | stratis, MOD_NAME_STRATIS 49 | BitLocker, MOD_NAME_BITLOCKER 50 | cs_fvault2, MOD_NAME_FILEVAULT 51 | vfat, MOD_NAME_FS 52 | swsuspend, MOD_NAME_FS 53 | swap, MOD_NAME_FS 54 | xfs, MOD_NAME_FS 55 | xfs_external_log, MOD_NAME_FS 56 | exfs, MOD_NAME_FS 57 | ext4dev, MOD_NAME_FS 58 | ext4, MOD_NAME_FS 59 | ext3, MOD_NAME_FS 60 | ext2, MOD_NAME_FS 61 | jbd, MOD_NAME_FS 62 | reiserfs, MOD_NAME_FS 63 | reiser4, MOD_NAME_FS 64 | jfs, MOD_NAME_FS 65 | udf, MOD_NAME_FS 66 | iso9660, MOD_NAME_FS 67 | zfs_member, MOD_NAME_FS 68 | hfsplus, MOD_NAME_FS 69 | hfs, MOD_NAME_FS 70 | ufs, MOD_NAME_FS 71 | hpfs, MOD_NAME_FS 72 | sysv, MOD_NAME_FS 73 | xenix, MOD_NAME_FS 74 | ntfs, MOD_NAME_FS 75 | ReFS, MOD_NAME_FS 76 | cramfs, MOD_NAME_FS 77 | romfs, MOD_NAME_FS 78 | minix, MOD_NAME_FS 79 | gfs, MOD_NAME_FS 80 | gfs2, MOD_NAME_FS 81 | ocfs, MOD_NAME_FS 82 | ocfs2, MOD_NAME_FS 83 | oracleasm, MOD_NAME_FS 84 | vxfs, MOD_NAME_FS 85 | squashfs, MOD_NAME_FS 86 | squashfs3, MOD_NAME_FS 87 | nss, MOD_NAME_FS 88 | btrfs, MOD_NAME_FS 89 | ubifs, MOD_NAME_FS 90 | bfs, MOD_NAME_FS 91 | VMFS, MOD_NAME_FS 92 | befs, MOD_NAME_FS 93 | nilfs2, MOD_NAME_FS 94 | exfat, MOD_NAME_FS 95 | f2fs, MOD_NAME_FS 96 | mpool, MOD_NAME_FS 97 | apfs, MOD_NAME_FS 98 | zonefs, MOD_NAME_FS 99 | erofs, MOD_NAME_FS 100 | -------------------------------------------------------------------------------- /src/modules/ucmd/block/blkid/blkid-type.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef SID_BLKID_TYPE_H 8 | #define SID_BLKID_TYPE_H 9 | 10 | #include 11 | 12 | #define MOD_NAME_NONE "-" 13 | #define MOD_NAME_MD "md" 14 | #define MOD_NAME_BCACHE "bcache" 15 | #define MOD_NAME_CEPH "ceph" 16 | #define MOD_NAME_DRBD "drbd" 17 | #define MOD_NAME_DM "dm" 18 | #define MOD_NAME_UBI "ubi" 19 | #define MOD_NAME_VDO "vdo" 20 | #define MOD_NAME_STRATIS "stratis" 21 | #define MOD_NAME_BITLOCKER "bitlocker" 22 | #define MOD_NAME_FILEVAULT "filevault" 23 | #define MOD_NAME_SWAP "swap" 24 | #define MOD_NAME_FS "fs" 25 | 26 | struct blkid_type { 27 | const char *blkid_type_name; 28 | const char *module_name; 29 | }; 30 | 31 | const struct blkid_type *blkid_type_lookup(const char *key, size_t len); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/modules/ucmd/block/blkid/blkid.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "blkid-key.h" 8 | #include "blkid-type.h" 9 | #include "resource/ucmd-mod.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | SID_UCMD_MOD_PRIO(0) 23 | 24 | static int _blkid_init(sid_res_t *mod_res, struct sid_ucmd_common_ctx *ucmd_common_ctx) 25 | { 26 | const struct blkid_xkey *xkey; 27 | unsigned i; 28 | 29 | sid_res_log_debug(mod_res, "init"); 30 | 31 | xkey = &blkid_xkey_arr[i = 0]; 32 | while (xkey->num < U_ID_NUM_KEYS) { 33 | if (sid_ucmd_kv_reserve(mod_res, ucmd_common_ctx, SID_KV_NS_UDEV, xkey->name, SID_KV_FL_FRG_RD) < 0) { 34 | sid_res_log_error(mod_res, "Failed to reserve blkid udev key %s.", xkey->name); 35 | return -1; 36 | } 37 | 38 | xkey = &blkid_xkey_arr[++i]; 39 | } 40 | 41 | if (sid_ucmd_kv_reserve(mod_res, ucmd_common_ctx, SID_KV_NS_DEV, SID_UCMD_KEY_DEVICE_NEXT_MOD, SID_KV_FL_FRG_RD) < 0) { 42 | sid_res_log_error(mod_res, "Failed to reserve blkid device key %s.", SID_UCMD_KEY_DEVICE_NEXT_MOD); 43 | return -1; 44 | } 45 | 46 | return 0; 47 | } 48 | SID_UCMD_MOD_INIT(_blkid_init) 49 | 50 | static int _blkid_exit(sid_res_t *mod_res, struct sid_ucmd_common_ctx *ucmd_common_ctx) 51 | { 52 | const struct blkid_xkey *xkey; 53 | unsigned i; 54 | 55 | sid_res_log_debug(mod_res, "exit"); 56 | 57 | xkey = &blkid_xkey_arr[i = 0]; 58 | while (xkey->num < U_ID_NUM_KEYS) { 59 | if (sid_ucmd_kv_unreserve(mod_res, ucmd_common_ctx, SID_KV_NS_UDEV, xkey->name) < 0) { 60 | sid_res_log_error(mod_res, "Failed to unreserve blkid udev key %s.", xkey->name); 61 | return -1; 62 | } 63 | 64 | xkey = &blkid_xkey_arr[++i]; 65 | } 66 | 67 | if (sid_ucmd_kv_unreserve(mod_res, ucmd_common_ctx, SID_KV_NS_DEV, SID_UCMD_KEY_DEVICE_NEXT_MOD) < 0) { 68 | sid_res_log_error(mod_res, "Failed to unreserve blkid device key %s.", SID_UCMD_KEY_DEVICE_NEXT_MOD); 69 | return -1; 70 | } 71 | 72 | return 0; 73 | } 74 | SID_UCMD_MOD_EXIT(_blkid_exit) 75 | 76 | static int _blkid_reset(sid_res_t *mod_res, struct sid_ucmd_common_ctx *ucmd_common_ctx) 77 | { 78 | sid_res_log_debug(mod_res, "reset"); 79 | return 0; 80 | } 81 | SID_UCMD_MOD_RESET(_blkid_reset) 82 | 83 | static int _add_property(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx, const char *name, const char *value) 84 | { 85 | const struct blkid_key *blkid_key; 86 | const struct blkid_type *blkid_type; 87 | char s[256]; 88 | const char *k; 89 | const char *v; 90 | int r = 0; 91 | 92 | if (!(blkid_key = blkid_key_lookup(name, strlen(name)))) { 93 | sid_res_log_warning(mod_res, "Unhandled blkid key %s.", name); 94 | return -ENOKEY; 95 | } 96 | 97 | if (blkid_key->xkey->flags & BLKID_FL_ORIG) { 98 | if (blkid_key->xkey->flags & BLKID_FL_SAFE) { 99 | blkid_safe_string(value, s, sizeof(s)); 100 | v = s; 101 | } else 102 | v = value; 103 | 104 | if ((r = sid_ucmd_kv_va_set(mod_res, 105 | ucmd_ctx, 106 | .ns = SID_KV_NS_UDEV, 107 | .key = blkid_key->xkey->name, 108 | .val = v, 109 | .fl = SID_KV_FL_SC | SID_KV_FL_RD)) < 0) 110 | goto out; 111 | } 112 | 113 | if (blkid_key->xkey->flags & BLKID_FL_ENC) { 114 | blkid_encode_string(value, s, sizeof(s)); 115 | v = s; 116 | 117 | if (blkid_key->xkey->flags & BLKID_FL_ORIG) 118 | k = blkid_xkey_arr[blkid_key->xkey->num + 1].name; 119 | else 120 | k = blkid_key->xkey->name; 121 | 122 | if ((r = sid_ucmd_kv_va_set(mod_res, ucmd_ctx, .ns = SID_KV_NS_UDEV, .key = k, .val = v, .fl = SID_KV_FL_SC | SID_KV_FL_RD)) < 0) 123 | goto out; 124 | } 125 | 126 | if (blkid_key->xkey->num == U_ID_FS_TYPE) { 127 | if ((blkid_type = blkid_type_lookup(value, strlen(value)))) { 128 | if ((r = sid_ucmd_kv_va_set(mod_res, 129 | ucmd_ctx, 130 | .ns = SID_KV_NS_DEV, 131 | .key = SID_UCMD_KEY_DEVICE_NEXT_MOD, 132 | .val = blkid_type->module_name, 133 | .fl = SID_KV_FL_SCPS | SID_KV_FL_RD)) < 0) 134 | goto out; 135 | } 136 | } 137 | 138 | out: 139 | return r; 140 | } 141 | 142 | static int _probe_superblocks(blkid_probe pr) 143 | { 144 | struct stat st; 145 | int rc; 146 | 147 | if (fstat(blkid_probe_get_fd(pr), &st)) 148 | return -errno; 149 | 150 | blkid_probe_enable_partitions(pr, 1); 151 | 152 | if (!S_ISCHR(st.st_mode) && blkid_probe_get_size(pr) <= 1024 * 1440 && blkid_probe_is_wholedisk(pr)) { 153 | /* 154 | * check if the small disk is partitioned, if yes then 155 | * don't probe for filesystems. 156 | */ 157 | blkid_probe_enable_superblocks(pr, 0); 158 | 159 | rc = blkid_do_fullprobe(pr); 160 | if (rc < 0) 161 | return rc; /* -1 = error, 1 = nothing, 0 = success */ 162 | 163 | if (blkid_probe_lookup_value(pr, "PTTYPE", NULL, NULL) == 0) 164 | return 0; /* partition table detected */ 165 | } 166 | 167 | blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS); 168 | blkid_probe_enable_superblocks(pr, 1); 169 | 170 | return blkid_do_safeprobe(pr); 171 | } 172 | 173 | static int _blkid_scan_next(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 174 | { 175 | char dev_path[PATH_MAX]; 176 | int64_t offset = 0; 177 | int noraid = 0; 178 | int fd = -1; 179 | blkid_probe pr = NULL; 180 | const char *data; 181 | const char *name; 182 | int nvals; 183 | int i; 184 | int r = -1; 185 | 186 | sid_res_log_debug(mod_res, "scan-next"); 187 | 188 | pr = blkid_new_probe(); 189 | if (!pr) 190 | goto out; 191 | 192 | blkid_probe_set_superblocks_flags(pr, 193 | BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE | 194 | BLKID_SUBLKS_FSINFO | BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION); 195 | 196 | // TODO: Also decide when to use offset (including exact value) and noraid options. 197 | 198 | snprintf(dev_path, sizeof(dev_path), SYSTEM_DEV_PATH "/%s", sid_ucmd_ev_get_dev_name(ucmd_ctx)); 199 | 200 | if ((fd = open(dev_path, O_RDONLY | O_CLOEXEC)) < 0) { 201 | sid_res_log_error_errno(mod_res, errno, "Failed to open device %s", dev_path); 202 | goto out; 203 | } 204 | 205 | if ((r = blkid_probe_set_device(pr, fd, offset, 0)) < 0) 206 | goto out; 207 | 208 | sid_res_log_debug(mod_res, "Probe %s %sraid offset=%" PRIi64, dev_path, noraid ? "no" : "", offset); 209 | 210 | if ((r = _probe_superblocks(pr)) < 0) 211 | goto out; 212 | 213 | nvals = blkid_probe_numof_values(pr); 214 | for (i = 0; i < nvals; i++) { 215 | if (blkid_probe_get_value(pr, i, &name, &data, NULL)) 216 | continue; 217 | 218 | if (_add_property(mod_res, ucmd_ctx, name, data) < 0) 219 | sid_res_log_warning(mod_res, "Failed to add property %s.", name); 220 | } 221 | 222 | r = 0; 223 | out: 224 | if (fd >= 0) 225 | (void) close(fd); 226 | if (pr) 227 | blkid_free_probe(pr); 228 | 229 | return r; 230 | } 231 | SID_UCMD_SCAN_NEXT(_blkid_scan_next) 232 | 233 | static int _blkid_scan_error(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 234 | { 235 | sid_res_log_debug(mod_res, "scan-error"); 236 | return 0; 237 | } 238 | SID_UCMD_SCAN_ERROR(_blkid_scan_error) 239 | -------------------------------------------------------------------------------- /src/modules/ucmd/block/dm_mpath/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | include $(top_srcdir)/Makefile.common 8 | 9 | dm_mpathdir = $(pkglibdir)/modules/ucmd/block 10 | 11 | dm_mpath_LTLIBRARIES = dm_mpath.la 12 | 13 | dm_mpath_la_SOURCES = dm_mpath.c 14 | 15 | dm_mpath_la_LDFLAGS = -module -avoid-version 16 | 17 | dm_mpath_la_LIBADD = $(top_builddir)/src/base/libsidbase.la \ 18 | $(top_builddir)/src/resource/libsidresource.la \ 19 | -lmpathvalid 20 | -------------------------------------------------------------------------------- /src/modules/ucmd/block/dm_mpath/dm_mpath.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "base/util.h" 8 | #include "resource/ucmd-mod.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | SID_UCMD_MOD_PRIO(-1) 16 | 17 | #define U_DEV_PATH "DM_MULTIPATH_DEVICE_PATH" 18 | #define X_VALID "VALID" 19 | #define X_WWID "WWID" 20 | 21 | static int _dm_mpath_init(sid_res_t *mod_res, struct sid_ucmd_common_ctx *ucmd_common_ctx) 22 | { 23 | sid_res_log_debug(mod_res, "init"); 24 | 25 | /* TODO - set up dm/udev logging */ 26 | if (mpathvalid_init(MPATH_LOG_PRIO_NOLOG, MPATH_LOG_STDERR)) { 27 | sid_res_log_error(mod_res, "failed to initialize mpathvalid"); 28 | return -1; 29 | } 30 | 31 | if (sid_ucmd_kv_reserve(mod_res, ucmd_common_ctx, SID_KV_NS_UDEV, U_DEV_PATH, SID_KV_FL_FRG_RD) < 0) { 32 | sid_res_log_error(mod_res, "Failed to reserve multipath udev key %s.", U_DEV_PATH); 33 | goto fail; 34 | } 35 | 36 | return 0; 37 | fail: 38 | mpathvalid_exit(); 39 | return -1; 40 | } 41 | SID_UCMD_MOD_INIT(_dm_mpath_init) 42 | 43 | static int _dm_mpath_exit(sid_res_t *mod_res, struct sid_ucmd_common_ctx *ucmd_common_ctx) 44 | { 45 | sid_res_log_debug(mod_res, "exit"); 46 | 47 | if (sid_ucmd_kv_unreserve(mod_res, ucmd_common_ctx, SID_KV_NS_UDEV, U_DEV_PATH) < 0) 48 | sid_res_log_error(mod_res, "Failed to unreserve multipath udev key %s.", U_DEV_PATH); 49 | 50 | mpathvalid_exit(); 51 | return 0; 52 | } 53 | SID_UCMD_MOD_EXIT(_dm_mpath_exit) 54 | 55 | static int _kernel_cmdline_allow(void) 56 | { 57 | char *value = NULL; 58 | 59 | if (!sid_util_kernel_get_arg("nompath", NULL, NULL) && !sid_util_kernel_get_arg("nompath", &value, NULL)) 60 | return 1; 61 | if (value && strcmp(value, "off") != 0) 62 | return 1; 63 | return 0; 64 | } 65 | 66 | static int _dm_mpath_reset(sid_res_t *mod_res, struct sid_ucmd_common_ctx *ucmd_common_ctx) 67 | { 68 | sid_res_log_debug(mod_res, "reset"); 69 | return 0; 70 | } 71 | SID_UCMD_MOD_RESET(_dm_mpath_reset) 72 | 73 | static int _is_parent_multipathed(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 74 | { 75 | const char **parent; 76 | const char *valid_str; 77 | int mpath_valid = MPATH_IS_ERROR; 78 | char *p; 79 | int r = 0; 80 | 81 | parent = sid_ucmd_dev_stack_va_get(mod_res, ucmd_ctx, .method = SID_DEV_SEARCH_IMM_ANC, .ret_code = &r); 82 | if (r < 0 || !parent) 83 | return 0; 84 | 85 | valid_str = sid_ucmd_kv_va_get(mod_res, ucmd_ctx, .ns = SID_KV_NS_DEV, .frg_dev_key = parent[0], .key = X_VALID); 86 | free(parent); 87 | 88 | if (!valid_str || !valid_str[0]) 89 | return 0; 90 | 91 | errno = 0; 92 | mpath_valid = strtol(valid_str, &p, 10); 93 | if (errno || !p || *p) 94 | return 0; 95 | 96 | if (mpath_valid == MPATH_IS_VALID) { 97 | sid_res_log_debug(mod_res, "%s whole disk is a multipath path", sid_ucmd_ev_get_dev_name(ucmd_ctx)); 98 | sid_ucmd_kv_va_set(mod_res, ucmd_ctx, .ns = SID_KV_NS_UDEV, .key = U_DEV_PATH, .val = "1", .fl = SID_KV_FL_RD); 99 | return 1; 100 | } 101 | 102 | sid_res_log_debug(mod_res, "%s whole disk is not a multipath path", sid_ucmd_ev_get_dev_name(ucmd_ctx)); 103 | return 0; 104 | } 105 | 106 | static int _dm_mpath_scan_next(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 107 | { 108 | int r; 109 | char *wwid; 110 | char valid_str[2]; 111 | 112 | sid_res_log_debug(mod_res, "scan-next"); 113 | 114 | if (!_kernel_cmdline_allow()) // treat failure as allowed 115 | return 0; 116 | 117 | switch (sid_ucmd_ev_get_dev_type(ucmd_ctx)) { 118 | case UDEV_DEVTYPE_DISK: 119 | break; 120 | case UDEV_DEVTYPE_PARTITION: 121 | return _is_parent_multipathed(mod_res, ucmd_ctx); 122 | case UDEV_DEVTYPE_UNKNOWN: 123 | return 0; 124 | } 125 | 126 | if (mpathvalid_reload_config() < 0) { 127 | sid_res_log_error(mod_res, "failed to reinitialize mpathvalid"); 128 | return -1; 129 | } 130 | // currently treats MPATH_SMART like MPATH_STRICT 131 | r = mpathvalid_is_path(sid_ucmd_ev_get_dev_name(ucmd_ctx), MPATH_DEFAULT, &wwid, NULL, 0); 132 | sid_res_log_debug(mod_res, "%s mpathvalid_is_path returned %d", sid_ucmd_ev_get_dev_name(ucmd_ctx), r); 133 | 134 | if (r == MPATH_IS_VALID) { 135 | const char *old_valid_str; 136 | char *p; 137 | int old_valid; 138 | 139 | old_valid_str = sid_ucmd_kv_va_get(mod_res, ucmd_ctx, .ns = SID_KV_NS_DEVMOD, .key = X_VALID); 140 | if (old_valid_str && old_valid_str[0]) { 141 | errno = 0; 142 | old_valid = strtol(old_valid_str, &p, 10); 143 | // If old_valid is garbage assume the device 144 | // wasn't claimed before 145 | if (errno || !p || *p || old_valid != MPATH_IS_VALID) { 146 | sid_res_log_debug(mod_res, 147 | "previously released %s. not claiming", 148 | sid_ucmd_ev_get_dev_name(ucmd_ctx)); 149 | r = MPATH_IS_NOT_VALID; 150 | } 151 | } 152 | } else if (r == MPATH_IS_VALID_NO_CHECK) 153 | r = MPATH_IS_VALID; 154 | 155 | if (r == MPATH_IS_VALID) 156 | sid_ucmd_kv_va_set(mod_res, ucmd_ctx, .ns = SID_KV_NS_UDEV, .key = U_DEV_PATH, .val = "1", .fl = SID_KV_FL_RD); 157 | else if (r != MPATH_IS_ERROR) 158 | sid_ucmd_kv_va_set(mod_res, ucmd_ctx, .ns = SID_KV_NS_UDEV, .key = U_DEV_PATH, .val = "0", .fl = SID_KV_FL_RD); 159 | 160 | if (r != MPATH_IS_ERROR && snprintf(valid_str, sizeof(valid_str), "%d", r) < sizeof(valid_str) && valid_str[0]) 161 | sid_ucmd_kv_va_set(mod_res, 162 | ucmd_ctx, 163 | .ns = SID_KV_NS_DEVMOD, 164 | .key = X_VALID, 165 | .val = valid_str, 166 | .fl = SID_KV_FL_RD | SID_KV_FL_SCPS); 167 | if (wwid) { 168 | sid_ucmd_kv_va_set(mod_res, 169 | ucmd_ctx, 170 | .ns = SID_KV_NS_DEVMOD, 171 | .key = X_WWID, 172 | .val = wwid, 173 | .fl = SID_KV_FL_RD | SID_KV_FL_SCPS); 174 | free(wwid); 175 | } 176 | return (r != MPATH_IS_ERROR) ? 0 : -1; 177 | } 178 | SID_UCMD_SCAN_NEXT(_dm_mpath_scan_next) 179 | 180 | static int _dm_mpath_scan_error(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 181 | { 182 | sid_res_log_debug(mod_res, "scan-error"); 183 | return 0; 184 | } 185 | SID_UCMD_SCAN_ERROR(_dm_mpath_scan_error) 186 | -------------------------------------------------------------------------------- /src/modules/ucmd/block/dummy_block/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | include $(top_srcdir)/Makefile.common 8 | 9 | dummy_blockdir = $(pkglibdir)/modules/ucmd/block 10 | 11 | dummy_block_LTLIBRARIES = dummy_block.la 12 | 13 | dummy_block_la_SOURCES = dummy_block.c 14 | 15 | dummy_block_la_LDFLAGS = -module -avoid-version 16 | 17 | dummy_block_la_LIBADD = $(top_builddir)/src/resource/libsidresource.la 18 | -------------------------------------------------------------------------------- /src/modules/ucmd/block/dummy_block/dummy_block.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "resource/ucmd-mod.h" 8 | 9 | SID_UCMD_MOD_PRIO(1) 10 | 11 | static int _dummy_block_init(sid_res_t *mod_res, struct sid_ucmd_common_ctx *ucmd_common_ctx) 12 | { 13 | sid_res_log_debug(mod_res, "init"); 14 | return 0; 15 | } 16 | SID_UCMD_MOD_INIT(_dummy_block_init) 17 | 18 | static int _dummy_block_exit(sid_res_t *mod_res, struct sid_ucmd_common_ctx *ucmd_common_ctx) 19 | { 20 | sid_res_log_debug(mod_res, "exit"); 21 | return 0; 22 | } 23 | SID_UCMD_MOD_EXIT(_dummy_block_exit) 24 | 25 | static int _dummy_block_reset(sid_res_t *mod_res, struct sid_ucmd_common_ctx *ucmd_common_ctx) 26 | { 27 | sid_res_log_debug(mod_res, "reset"); 28 | return 0; 29 | } 30 | SID_UCMD_MOD_RESET(_dummy_block_reset) 31 | 32 | static int _dummy_block_scan_a_init(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 33 | { 34 | sid_res_log_debug(mod_res, "scan-a-init"); 35 | return 0; 36 | } 37 | SID_UCMD_SCAN_A_INIT(_dummy_block_scan_a_init) 38 | 39 | static int _dummy_block_scan_pre(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 40 | { 41 | sid_res_log_debug(mod_res, "scan-pre"); 42 | return 0; 43 | } 44 | SID_UCMD_SCAN_PRE(_dummy_block_scan_pre) 45 | 46 | static int _dummy_block_scan_current(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd) 47 | { 48 | sid_res_log_debug(mod_res, "scan-current"); 49 | return 0; 50 | } 51 | SID_UCMD_SCAN_CURRENT(_dummy_block_scan_current) 52 | 53 | static int _dummy_block_scan_next(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 54 | { 55 | sid_res_log_debug(mod_res, "scan-next"); 56 | return 0; 57 | } 58 | SID_UCMD_SCAN_NEXT(_dummy_block_scan_next) 59 | 60 | static int _dummy_block_scan_post_current(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 61 | { 62 | sid_res_log_debug(mod_res, "scan-post-current"); 63 | return 0; 64 | } 65 | SID_UCMD_SCAN_POST_CURRENT(_dummy_block_scan_post_current) 66 | 67 | static int _dummy_block_scan_post_next(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 68 | { 69 | sid_res_log_debug(mod_res, "scan-post-next"); 70 | return 0; 71 | } 72 | SID_UCMD_SCAN_POST_NEXT(_dummy_block_scan_post_next) 73 | 74 | static int _dummy_block_scan_a_exit(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 75 | { 76 | sid_res_log_debug(mod_res, "scan-a-exit"); 77 | return 0; 78 | } 79 | SID_UCMD_SCAN_A_EXIT(_dummy_block_scan_a_exit) 80 | 81 | static int _dummy_block_scan_remove_init(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 82 | { 83 | sid_res_log_debug(mod_res, "scan-remove-init"); 84 | return 0; 85 | } 86 | SID_UCMD_SCAN_REMOVE_INIT(_dummy_block_scan_remove_init) 87 | 88 | static int _dummy_block_scan_remove(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 89 | { 90 | sid_res_log_debug(mod_res, "scan-remove"); 91 | return 0; 92 | } 93 | SID_UCMD_SCAN_REMOVE(_dummy_block_scan_remove) 94 | 95 | static int _dummy_block_scan_remove_exit(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 96 | { 97 | sid_res_log_debug(mod_res, "scan-remove-exit"); 98 | return 0; 99 | } 100 | SID_UCMD_SCAN_REMOVE_EXIT(_dummy_block_scan_remove_exit) 101 | 102 | static int _dummy_block_scan_b_init(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 103 | { 104 | sid_res_log_debug(mod_res, "scan-b-init"); 105 | return 0; 106 | } 107 | SID_UCMD_SCAN_B_INIT(_dummy_block_scan_b_init) 108 | 109 | static int _dummy_block_scan_action_current(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 110 | { 111 | sid_res_log_debug(mod_res, "scan-action-current"); 112 | return 0; 113 | } 114 | SID_UCMD_SCAN_ACTION_CURRENT(_dummy_block_scan_action_current) 115 | 116 | static int _dummy_block_scan_action_next(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 117 | { 118 | sid_res_log_debug(mod_res, "scan-action-next"); 119 | return 0; 120 | } 121 | SID_UCMD_SCAN_ACTION_NEXT(_dummy_block_scan_action_next) 122 | 123 | static int _dummy_block_scan_b_exit(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 124 | { 125 | sid_res_log_debug(mod_res, "scan-b-exit"); 126 | return 0; 127 | } 128 | SID_UCMD_SCAN_B_EXIT(_dummy_block_scan_b_exit) 129 | 130 | static int _dummy_block_scan_error(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 131 | { 132 | sid_res_log_debug(mod_res, "scan-error"); 133 | return 0; 134 | } 135 | SID_UCMD_SCAN_ERROR(_dummy_block_scan_error) 136 | -------------------------------------------------------------------------------- /src/modules/ucmd/type/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | SUBDIRS = 8 | 9 | if BUILD_MOD_UCMD_TYPE_DM 10 | SUBDIRS += dm 11 | endif 12 | 13 | if BUILD_MOD_UCMD_TYPE_DUMMY 14 | SUBDIRS += dummy_type 15 | endif 16 | 17 | uninstall-hook: 18 | test -d ${DESTDIR}${pkglibdir}/modules/ucmd/type && rmdir ${DESTDIR}${pkglibdir}/modules/ucmd/type || true 19 | -------------------------------------------------------------------------------- /src/modules/ucmd/type/dm/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | include $(top_srcdir)/Makefile.common 8 | 9 | if BUILD_MOD_UCMD_TYPE_DM__LVM 10 | SUBDIRS = lvm 11 | endif 12 | 13 | dmdir = $(pkglibdir)/modules/ucmd/type 14 | 15 | dm_LTLIBRARIES = dm.la 16 | 17 | dm_la_SOURCES = dm.c dm.h 18 | 19 | dm_la_LDFLAGS = -module -avoid-version 20 | 21 | dm_la_LIBADD = $(top_builddir)/src/base/libsidbase.la \ 22 | $(top_builddir)/src/resource/libsidresource.la 23 | 24 | install-data-local: 25 | ${MKDIR_P} ${DESTDIR}${pkglibdir}/modules/ucmd/type/dm 26 | 27 | uninstall-local: 28 | test -d ${DESTDIR}${pkglibdir}/modules/ucmd/type/dm && rmdir ${DESTDIR}${pkglibdir}/modules/ucmd/type/dm || true 29 | -------------------------------------------------------------------------------- /src/modules/ucmd/type/dm/dm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef _SID_UCMD_MOD_TYPE_DM_H 8 | #define _SID_UCMD_MOD_TYPE_DM_H 9 | 10 | #include 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | #define SID_UCMD_MOD_DM_FN_NAME_SCAN_SUBSYS_MATCH_CURRENT "sid_ucmd_dm_scan_subsys_match_current" 17 | #define SID_UCMD_MOD_DM_FN_NAME_SCAN_SUBSYS_MATCH_NEXT "sid_ucmd_dm_scan_subsys_match_next" 18 | 19 | #define SID_UCMD_MOD_DM_SCAN_SUBSYS_MATCH_CURRENT(fn) SID_UCMD_FN(dm_scan_subsys_match_current, _SID_UCMD_FN_CHECK_TYPE(fn)) 20 | #define SID_UCMD_MOD_DM_SCAN_SUBSYS_MATCH_NEXT(fn) SID_UCMD_FN(dm_scan_subsys_match_next, _SID_UCMD_FN_CHECK_TYPE(fn)) 21 | 22 | #define DM_X_NAME "name" 23 | #define DM_X_UUID "uuid" 24 | #define DM_X_COOKIE_FLAGS "cookie_flags" 25 | 26 | typedef uint16_t dm_cookie_fl_t; 27 | 28 | #define DM_UDEV_DISABLE_DM_RULES_FLAG 0x0001 29 | #define DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG 0x0002 30 | #define DM_UDEV_DISABLE_DISK_RULES_FLAG 0x0004 31 | #define DM_UDEV_DISABLE_OTHER_RULES_FLAG 0x0008 32 | #define DM_UDEV_LOW_PRIORITY_FLAG 0x0010 33 | #define DM_UDEV_DISABLE_LIBRARY_FALLBACK 0x0020 34 | #define DM_UDEV_PRIMARY_SOURCE_FLAG 0x0040 35 | 36 | #define DM_SUBSYSTEM_UDEV_FLAG0 0x0100 37 | #define DM_SUBSYSTEM_UDEV_FLAG1 0x0200 38 | #define DM_SUBSYSTEM_UDEV_FLAG2 0x0400 39 | #define DM_SUBSYSTEM_UDEV_FLAG3 0x0800 40 | #define DM_SUBSYSTEM_UDEV_FLAG4 0x1000 41 | #define DM_SUBSYSTEM_UDEV_FLAG5 0x2000 42 | #define DM_SUBSYSTEM_UDEV_FLAG6 0x4000 43 | #define DM_SUBSYSTEM_UDEV_FLAG7 0x8000 44 | 45 | #ifdef __cplusplus 46 | } 47 | #endif 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/modules/ucmd/type/dm/lvm/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | include $(top_srcdir)/Makefile.common 8 | 9 | lvmdir = $(pkglibdir)/modules/ucmd/type/dm 10 | 11 | lvm_LTLIBRARIES = lvm.la 12 | 13 | lvm_la_SOURCES = lvm.c 14 | 15 | lvm_la_LDFLAGS = -module -avoid-version 16 | 17 | lvm_la_LIBADD = $(top_builddir)/src/base/libsidbase.la \ 18 | $(top_builddir)/src/resource/libsidresource.la 19 | -------------------------------------------------------------------------------- /src/modules/ucmd/type/dummy_type/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | include $(top_srcdir)/Makefile.common 8 | 9 | dummy_typedir = $(pkglibdir)/modules/ucmd/type 10 | 11 | dummy_type_LTLIBRARIES = dummy_type.la 12 | 13 | dummy_type_la_SOURCES = dummy_type.c 14 | 15 | dummy_type_la_LDFLAGS = -module -avoid-version 16 | 17 | dummy_type_la_LIBADD = $(top_builddir)/src/resource/libsidresource.la 18 | -------------------------------------------------------------------------------- /src/modules/ucmd/type/dummy_type/dummy_type.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "resource/ucmd-mod.h" 8 | 9 | SID_UCMD_MOD_PRIO(1) 10 | 11 | static int _dummy_type_init(sid_res_t *mod_res, struct sid_ucmd_common_ctx *ucmd_common_ctx) 12 | { 13 | sid_res_log_debug(mod_res, "init"); 14 | return 0; 15 | } 16 | SID_UCMD_MOD_INIT(_dummy_type_init) 17 | 18 | static int _dummy_type_exit(sid_res_t *mod_res, struct sid_ucmd_common_ctx *ucmd_common_ctx) 19 | { 20 | sid_res_log_debug(mod_res, "exit"); 21 | return 0; 22 | } 23 | SID_UCMD_MOD_EXIT(_dummy_type_exit) 24 | 25 | static int _dummy_type_reset(sid_res_t *mod_res, struct sid_ucmd_common_ctx *ucmd_common_ctx) 26 | { 27 | sid_res_log_debug(mod_res, "reset"); 28 | return 0; 29 | } 30 | SID_UCMD_MOD_RESET(_dummy_type_reset) 31 | 32 | static int _dummy_type_scan_a_init(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 33 | { 34 | sid_res_log_debug(mod_res, "scan-a-init"); 35 | return 0; 36 | } 37 | SID_UCMD_SCAN_A_INIT(_dummy_type_scan_a_init) 38 | 39 | static int _dummy_type_scan_pre(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 40 | { 41 | sid_res_log_debug(mod_res, "scan-pre"); 42 | return 0; 43 | } 44 | SID_UCMD_SCAN_PRE(_dummy_type_scan_pre) 45 | 46 | static int _dummy_type_scan_current(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 47 | { 48 | sid_res_log_debug(mod_res, "scan-current"); 49 | return 0; 50 | } 51 | SID_UCMD_SCAN_CURRENT(_dummy_type_scan_current) 52 | 53 | static int _dummy_type_scan_next(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 54 | { 55 | sid_res_log_debug(mod_res, "scan-next"); 56 | return 0; 57 | } 58 | SID_UCMD_SCAN_NEXT(_dummy_type_scan_next) 59 | 60 | static int _dummy_type_scan_post_current(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 61 | { 62 | sid_res_log_debug(mod_res, "scan-post-current"); 63 | return 0; 64 | } 65 | SID_UCMD_SCAN_POST_CURRENT(_dummy_type_scan_post_current) 66 | 67 | static int _dummy_type_scan_post_next(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 68 | { 69 | sid_res_log_debug(mod_res, "scan-post-next"); 70 | return 0; 71 | } 72 | SID_UCMD_SCAN_POST_NEXT(_dummy_type_scan_post_next) 73 | 74 | static int _dummy_type_scan_a_exit(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 75 | { 76 | sid_res_log_debug(mod_res, "scan-a-exit"); 77 | return 0; 78 | } 79 | SID_UCMD_SCAN_A_EXIT(_dummy_type_scan_a_exit) 80 | 81 | static int _dummy_type_scan_remove_init(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 82 | { 83 | sid_res_log_debug(mod_res, "scan-remove-init"); 84 | return 0; 85 | } 86 | SID_UCMD_SCAN_REMOVE_INIT(_dummy_type_scan_remove_init) 87 | 88 | static int _dummy_type_scan_remove(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 89 | { 90 | sid_res_log_debug(mod_res, "scan-remove"); 91 | return 0; 92 | } 93 | SID_UCMD_SCAN_REMOVE(_dummy_type_scan_remove) 94 | 95 | static int _dummy_type_scan_remove_exit(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 96 | { 97 | sid_res_log_debug(mod_res, "scan-remove-exit"); 98 | return 0; 99 | } 100 | SID_UCMD_SCAN_REMOVE_EXIT(_dummy_type_scan_remove_exit) 101 | 102 | static int _dummy_type_scan_b_init(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 103 | { 104 | sid_res_log_debug(mod_res, "scan-b-init"); 105 | return 0; 106 | } 107 | SID_UCMD_SCAN_B_INIT(_dummy_type_scan_b_init) 108 | 109 | static int _dummy_type_scan_action_current(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 110 | { 111 | sid_res_log_debug(mod_res, "scan-action-current"); 112 | return 0; 113 | } 114 | SID_UCMD_SCAN_ACTION_CURRENT(_dummy_type_scan_action_current) 115 | 116 | static int _dummy_type_scan_action_next(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 117 | { 118 | sid_res_log_debug(mod_res, "scan-action-next"); 119 | return 0; 120 | } 121 | SID_UCMD_SCAN_ACTION_NEXT(_dummy_type_scan_action_next) 122 | 123 | static int _dummy_type_scan_b_exit(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 124 | { 125 | sid_res_log_debug(mod_res, "scan-b-exit"); 126 | return 0; 127 | } 128 | SID_UCMD_SCAN_B_EXIT(_dummy_type_scan_b_exit) 129 | 130 | static int _dummy_type_scan_error(sid_res_t *mod_res, struct sid_ucmd_ctx *ucmd_ctx) 131 | { 132 | sid_res_log_debug(mod_res, "scan-error"); 133 | return 0; 134 | } 135 | SID_UCMD_SCAN_ERROR(_dummy_type_scan_error) 136 | -------------------------------------------------------------------------------- /src/resource/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | include $(top_srcdir)/Makefile.common 8 | 9 | pkglib_LTLIBRARIES = libsidresource.la 10 | 11 | libsidresource_la_SOURCES = res.c \ 12 | aggr.c \ 13 | ubr.c \ 14 | mod-reg.c \ 15 | kvs.c \ 16 | wrk-ctl.c \ 17 | sid.c 18 | 19 | resourcedir = $(pkgincludedir)/resource 20 | 21 | resource_HEADERS = $(top_srcdir)/src/include/resource/res.h \ 22 | $(top_srcdir)/src/include/resource/res-type-regs.h \ 23 | $(top_srcdir)/src/include/resource/mod.h \ 24 | $(top_srcdir)/src/include/resource/mod-reg.h \ 25 | $(top_srcdir)/src/include/resource/kvs.h \ 26 | $(top_srcdir)/src/include/resource/ucmd-mod.h \ 27 | $(top_srcdir)/src/include/resource/ubr.h \ 28 | $(top_srcdir)/src/include/resource/wrk-ctl.h 29 | 30 | libsidresource_la_CFLAGS = $(SYSTEMD_CFLAGS) \ 31 | $(UDEV_CFLAGS) 32 | 33 | libsidresource_la_LDFLAGS = -version-info 0:0:0 34 | 35 | libsidresource_la_LIBADD = $(top_builddir)/src/internal/libsidinternal.la \ 36 | $(top_builddir)/src/base/libsidbase.la \ 37 | $(top_builddir)/src/iface/libsidiface_servicelink.la \ 38 | $(top_builddir)/src/iface/libsidiface.la \ 39 | $(SYSTEMD_LIBS) \ 40 | $(UDEV_LIBS) \ 41 | -ldl 42 | 43 | uninstall-hook: 44 | test -d ${DESTDIR}${resourcedir} && rmdir ${DESTDIR}${resourcedir} 45 | -------------------------------------------------------------------------------- /src/resource/aggr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "resource/res.h" 8 | 9 | /* 10 | * This resource is only used to aggregate other resources. 11 | * There's no resource-specific implementation here. 12 | */ 13 | 14 | static int _init_aggregate(sid_res_t *res, const void *kickstart_data, void **data) 15 | { 16 | *data = (void *) kickstart_data; 17 | return 0; 18 | } 19 | 20 | const sid_res_type_t sid_res_type_aggr = { 21 | .name = "aggregate", 22 | .short_name = "agg", 23 | .description = "Simple resource to aggregate other resources.", 24 | .init = _init_aggregate, 25 | }; 26 | -------------------------------------------------------------------------------- /src/resource/sid.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "resource/res.h" 8 | #include "resource/ubr.h" 9 | 10 | #include 11 | 12 | static int _on_sid_signal_event(sid_res_ev_src_t *es, const struct signalfd_siginfo *si, void *arg) 13 | { 14 | sid_res_t *res = arg; 15 | sid_res_t *ubridge_res; 16 | 17 | switch (si->ssi_signo) { 18 | case SIGTERM: 19 | case SIGINT: 20 | sid_res_ev_loop_exit(res); 21 | break; 22 | case SIGPIPE: 23 | break; 24 | case SIGHUP: /* TODO: Reload config on SIGHUP? */ 25 | break; 26 | case SIGUSR1: 27 | if ((ubridge_res = sid_res_search(res, SID_RES_SEARCH_IMM_DESC, &sid_res_type_ubr, NULL))) 28 | (void) sid_ubr_cmd_dbdump(ubridge_res, NULL); 29 | default: 30 | break; 31 | }; 32 | 33 | return 0; 34 | } 35 | 36 | static int _init_sid(sid_res_t *res, const void *kickstart_data, void **data) 37 | { 38 | sigset_t mask; 39 | 40 | sigemptyset(&mask); 41 | sigaddset(&mask, SIGCHLD); 42 | if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) { 43 | sid_res_log_error(res, "Failed to block SIGCHLD signal."); 44 | goto fail; 45 | } 46 | 47 | sigemptyset(&mask); 48 | sigaddset(&mask, SIGTERM); 49 | sigaddset(&mask, SIGINT); 50 | sigaddset(&mask, SIGPIPE); 51 | sigaddset(&mask, SIGHUP); 52 | sigaddset(&mask, SIGUSR1); 53 | 54 | if (sid_res_ev_create_signal(res, NULL, mask, _on_sid_signal_event, 0, "signal_handler", res) < 0) { 55 | sid_res_log_error(res, "Failed to create signal handlers."); 56 | goto fail; 57 | } 58 | 59 | if (!sid_res_create(res, 60 | &sid_res_type_ubr, 61 | SID_RES_FL_NONE, 62 | SID_RES_NO_CUSTOM_ID, 63 | SID_RES_NO_PARAMS, 64 | SID_RES_PRIO_NORMAL, 65 | SID_RES_NO_SERVICE_LINKS)) { 66 | sid_res_log_error(res, "Failed to create udev bridge interface."); 67 | goto fail; 68 | } 69 | 70 | return 0; 71 | fail: 72 | return -1; 73 | } 74 | 75 | const sid_res_type_t sid_res_type_sid = { 76 | .name = "Storage Instantiation Daemon", 77 | .short_name = "sid", 78 | .description = "Top level resource representing Storage Instantiation Daemon.", 79 | .with_event_loop = 1, 80 | .with_watchdog = 1, 81 | .init = _init_sid, 82 | }; 83 | -------------------------------------------------------------------------------- /src/tools/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | SUBDIRS = usid sidctl 8 | -------------------------------------------------------------------------------- /src/tools/sidctl/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | include $(top_srcdir)/Makefile.common 8 | 9 | sbin_PROGRAMS = sidctl 10 | 11 | sidctl_SOURCES = sidctl.c 12 | 13 | sidctl_LDADD = $(top_builddir)/src/internal/libsidinternal.la \ 14 | $(top_builddir)/src/base/libsidbase.la \ 15 | $(top_builddir)/src/iface/libsidiface.la \ 16 | $(top_builddir)/src/log/libsidlog.la 17 | -------------------------------------------------------------------------------- /src/tools/sidctl/sidctl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "base/buf.h" 8 | #include "iface/ifc.h" 9 | #include "internal/fmt.h" 10 | #include "log/log.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define LOG_PREFIX "sidctl" 20 | 21 | #define KEY_SIDCTL_PROTOCOL "SIDCTL_PROTOCOL" 22 | #define KEY_SIDCTL_MAJOR "SIDCTL_MAJOR" 23 | #define KEY_SIDCTL_MINOR "SIDCTL_MINOR" 24 | #define KEY_SIDCTL_RELEASE "SIDCTL_RELEASE" 25 | 26 | #define KEY_SID_IFC_PROTOCOL "SID_IFC_PROTOCOL" 27 | #define KEY_SID_MAJOR "SID_MAJOR" 28 | #define KEY_SID_MINOR "SID_MINOR" 29 | #define KEY_SID_RELEASE "SID_RELEASE" 30 | 31 | static int _sid_cmd(sid_ifc_cmd_t cmd, uint16_t format) 32 | { 33 | struct sid_ifc_rsl *rsl = NULL; 34 | const char *data; 35 | size_t size; 36 | int r; 37 | struct sid_ifc_req req = {.cmd = cmd, .flags = format}; 38 | 39 | if ((r = sid_ifc_req(&req, &rsl)) < 0) { 40 | sid_log_error_errno(LOG_PREFIX, r, "Command request failed"); 41 | return -1; 42 | } 43 | 44 | if ((data = sid_ifc_rsl_get_data(rsl, &size)) != NULL) 45 | printf("%s", data); 46 | else { 47 | uint64_t status; 48 | if (sid_ifc_rsl_get_status(rsl, &status) != 0 || status & SID_IFC_CMD_STATUS_FAILURE) { 49 | sid_log_error(LOG_PREFIX, "Command failed"); 50 | r = -1; 51 | } 52 | } 53 | 54 | sid_ifc_rsl_free(rsl); 55 | return r; 56 | } 57 | 58 | static int _sid_cmd_version(uint16_t format) 59 | { 60 | struct sid_buf *outbuf = NULL; 61 | int r; 62 | 63 | outbuf = sid_buf_create(&SID_BUF_SPEC(), &SID_BUF_INIT(.size = 4096, .alloc_step = 1), NULL); 64 | if (!outbuf) 65 | return -1; 66 | 67 | fmt_doc_start(format, outbuf, 0); 68 | 69 | fmt_elm_name(format, outbuf, 0, "SIDCTL_VERSION", false); 70 | fmt_elm_start(format, outbuf, 0, false); 71 | fmt_fld_uint(format, outbuf, 1, KEY_SIDCTL_PROTOCOL, SID_IFC_PROTOCOL, false); 72 | fmt_fld_uint(format, outbuf, 1, KEY_SIDCTL_MAJOR, SID_VERSION_MAJOR, true); 73 | fmt_fld_uint(format, outbuf, 1, KEY_SIDCTL_MINOR, SID_VERSION_MINOR, true); 74 | fmt_fld_uint(format, outbuf, 1, KEY_SIDCTL_RELEASE, SID_VERSION_RELEASE, true); 75 | fmt_elm_end(format, outbuf, 0); 76 | fmt_elm_name(format, outbuf, 0, "SID_VERSION", true); 77 | if ((r = sid_buf_write_all(outbuf, fileno(stdout))) < 0) 78 | sid_log_error_errno(LOG_PREFIX, r, "failed to write version information"); 79 | sid_buf_reset(outbuf); 80 | if (_sid_cmd(SID_IFC_CMD_VERSION, format) < 0) { 81 | fmt_doc_start(format, outbuf, 0); 82 | fmt_doc_end(format, outbuf, 0); 83 | } else 84 | fflush(stdout); 85 | fmt_doc_end(format, outbuf, 0); 86 | 87 | if ((r = sid_buf_write_all(outbuf, fileno(stdout))) < 0) 88 | sid_log_error_errno(LOG_PREFIX, r, "failed to write output ending"); 89 | sid_buf_destroy(outbuf); 90 | return r; 91 | } 92 | 93 | static void _help(FILE *f) 94 | { 95 | fprintf(f, 96 | "Usage: sidctl [-h|--help] [-v|--verbose] [-V|--version] [-f|--format json] [command]\n" 97 | "\n" 98 | "Control and Query the SID daemon.\n" 99 | "\n" 100 | "Global options:\n" 101 | " -f|--format env|json|table Show the output in specified format.\n" 102 | " -h|--help Show this help information.\n" 103 | " -v|--verbose Verbose mode, repeat to increase level.\n" 104 | " -V|--version Show SIDCTL version.\n" 105 | "\n" 106 | "Commands and arguments:\n" 107 | "\n" 108 | " version\n" 109 | " Get SIDCTL and SID daemon version.\n" 110 | " Input: None.\n" 111 | " Output: SID_IFC_PROTOCOL/MAJOR/MINOR/RELEASE for SIDCTL version.\n" 112 | " SID_IFC_PROTOCOL/MAJOR/MINOR/RELEASE for SID version.\n" 113 | "\n" 114 | " dbdump\n" 115 | " Dump the SID daemon database.\n" 116 | " Input: None.\n" 117 | " Output: Listing of all database entries.\n" 118 | "\n" 119 | " dbstats\n" 120 | " Show stats for the SID daemon database.\n" 121 | " Input: None.\n" 122 | " Output: Database statistics.\n" 123 | "\n" 124 | " devices\n" 125 | " List devices with basic set of properties.\n" 126 | " Input: None.\n" 127 | " Output: Listing of all known devices and their basic properties.\n" 128 | "\n" 129 | " resources\n" 130 | " Show current SID resource tree.\n" 131 | " Input: None.\n" 132 | " Output: Resource tree.\n" 133 | "\n"); 134 | } 135 | 136 | static void _version(FILE *f) 137 | { 138 | fprintf(f, PACKAGE_STRING "\n"); 139 | fprintf(f, "Configuration line: %s\n", SID_CONFIGURE_LINE); 140 | fprintf(f, "Compiled by: %s on %s with %s\n", SID_COMPILED_BY, SID_COMPILATION_HOST, SID_COMPILER); 141 | } 142 | 143 | static int _get_format(char *format) 144 | { 145 | if (format == NULL) 146 | return -1; 147 | if (!strcasecmp(format, "json")) 148 | return SID_IFC_CMD_FL_FMT_JSON; 149 | if (!strcasecmp(format, "env")) 150 | return SID_IFC_CMD_FL_FMT_ENV; 151 | if (!strcasecmp(format, "table")) 152 | return SID_IFC_CMD_FL_FMT_TABLE; 153 | return -1; 154 | } 155 | 156 | int main(int argc, char *argv[]) 157 | { 158 | int opt; 159 | int verbose = 0; 160 | int r = -1; 161 | int format = SID_IFC_CMD_FL_FMT_TABLE; 162 | sid_ifc_cmd_t cmd; 163 | 164 | struct option longopts[] = { 165 | {"format", required_argument, NULL, 'f'}, 166 | {"help", no_argument, NULL, 'h'}, 167 | {"verbose", no_argument, NULL, 'v'}, 168 | {"version", no_argument, NULL, 'V'}, 169 | {NULL, no_argument, NULL, 0}, 170 | }; 171 | 172 | while ((opt = getopt_long(argc, argv, "f:hvV", longopts, NULL)) != EOF) { 173 | switch (opt) { 174 | case 'h': 175 | _help(stdout); 176 | return EXIT_SUCCESS; 177 | case 'f': 178 | if ((format = _get_format(optarg)) < 0) { 179 | _help(stderr); 180 | return EXIT_FAILURE; 181 | } 182 | break; 183 | case 'v': 184 | verbose++; 185 | break; 186 | case 'V': 187 | _version(stdout); 188 | return EXIT_SUCCESS; 189 | default: 190 | _help(stderr); 191 | return EXIT_FAILURE; 192 | } 193 | } 194 | 195 | if (optind != argc - 1) { 196 | _help(stderr); 197 | return EXIT_FAILURE; 198 | } 199 | 200 | sid_log_init(SID_LOG_TGT_STANDARD, verbose); 201 | 202 | switch ((cmd = sid_ifc_cmd_name_to_type(argv[optind]))) { 203 | case SID_IFC_CMD_VERSION: 204 | r = _sid_cmd_version(format); 205 | break; 206 | case SID_IFC_CMD_DBDUMP: 207 | case SID_IFC_CMD_DBSTATS: 208 | case SID_IFC_CMD_RESOURCES: 209 | case SID_IFC_CMD_DEVICES: 210 | r = _sid_cmd(cmd, format); 211 | break; 212 | default: 213 | _help(stderr); 214 | } 215 | return (r < 0) ? EXIT_FAILURE : EXIT_SUCCESS; 216 | } 217 | -------------------------------------------------------------------------------- /src/tools/usid/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | include $(top_srcdir)/Makefile.common 8 | 9 | udevdir = $(UDEV_DIR) 10 | 11 | udev_PROGRAMS = usid 12 | 13 | usid_SOURCES = usid.c 14 | 15 | usid_LDADD = $(top_builddir)/src/base/libsidbase.la \ 16 | $(top_builddir)/src/iface/libsidiface.la \ 17 | $(top_builddir)/src/log/libsidlog.la 18 | 19 | -------------------------------------------------------------------------------- /systemd/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | dist_systemdsystemunit_DATA = sid.socket \ 8 | sid.service 9 | 10 | dist_sysconfig_DATA = sid.sysconfig 11 | 12 | $(dist_systemdsystemunit_DATA):%:%.in 13 | $(SED) -e "s|(SBINDIR)|$(sbindir)|" \ 14 | -e "s|(SYSCONFIGDIR)|$(sysconfigdir)|" \ 15 | $< >$@ 16 | 17 | $(dist_sysconfig_DATA):%:%.in 18 | $(SED) -e "s|(SYSTEMDSYSTEMUNITDIR)|$(systemdsystemunitdir)|" $< >$@ 19 | 20 | distclean-local: 21 | $(RM) $(dist_systemdsystemunit_DATA) \ 22 | $(dist_sysconfig_DATA) 23 | 24 | EXTRA_DIST = sid.socket.in \ 25 | sid.service.in \ 26 | sid.sysconfig.in 27 | -------------------------------------------------------------------------------- /systemd/sid.service.in: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | [Unit] 8 | Description=Storage Instantiation Daemon 9 | DefaultDependencies=no 10 | After=systemd-udevd.service 11 | Before=sysinit.target 12 | 13 | [Service] 14 | Type=notify 15 | EnvironmentFile=(SYSCONFIGDIR)/sid.sysconfig 16 | Environment=SERVICE_ACTIVATION_TYPE=FD_PRELOAD 17 | ExecStart=(SBINDIR)/sid -f 18 | -------------------------------------------------------------------------------- /systemd/sid.socket.in: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | [Unit] 8 | Description=Storage Instantiation Daemon socket 9 | DefaultDependencies=no 10 | Before=sockets.target 11 | After=systemd-udevd-kernel.socket 12 | 13 | [Socket] 14 | ListenStream=@sid-ubridge.socket 15 | PassCredentials=yes 16 | 17 | [Install] 18 | WantedBy=sockets.target 19 | -------------------------------------------------------------------------------- /systemd/sid.sysconfig.in: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | # This file is part of SID. 8 | # It provides settings for (SYSTEMDSYSTEMUNITDIR)/sid.service. 9 | 10 | # Verbosity level. 11 | VERBOSE=0 12 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !Makefile.am 4 | !*.c 5 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | if HAVE_CMOCKA 8 | 9 | include $(top_srcdir)/Makefile.common 10 | 11 | LOG_DRIVER = CMOCKA_MESSAGE_OUTPUT=TAP $(top_srcdir)/autoconf/tap-driver.sh 12 | 13 | check_PROGRAMS = \ 14 | test_buffer \ 15 | test_hash \ 16 | test_notify \ 17 | test_kv_store \ 18 | test_bitmap \ 19 | test_iface \ 20 | test_internal \ 21 | test_bptree \ 22 | test_db_sync 23 | 24 | TESTS = $(check_PROGRAMS) 25 | test_buffer_SOURCES = test_buffer.c 26 | test_buffer_LDADD = $(top_builddir)/src/internal/libsidinternal.la \ 27 | $(top_builddir)/src/base/libsidbase.la -lcmocka 28 | test_hash_SOURCES = test_hash.c 29 | test_hash_LDADD = $(top_builddir)/src/internal/libsidinternal.la \ 30 | $(top_builddir)/src/base/libsidbase.la -lcmocka 31 | test_kv_store_SOURCES = test_kv_store.c 32 | test_kv_store_CFLAGS = -I$(top_srcdir)/src/include/resource 33 | test_kv_store_LDADD = \ 34 | $(top_builddir)/src/base/libsidbase.la \ 35 | $(top_builddir)/src/resource/libsidresource.la -lcmocka 36 | test_notify_SOURCES = test_notify.c 37 | test_notify_LDFLAGS = -Wl,--wrap=sd_notify -Wl,--wrap=sid_buf_get_data 38 | test_notify_LDADD = \ 39 | $(top_builddir)/src/iface/libsidiface_servicelink.la -lcmocka 40 | test_bitmap_SOURCES = test_bitmap.c 41 | test_bitmap_LDADD = $(top_builddir)/src/internal/libsidinternal.la \ 42 | $(top_builddir)/src/base/libsidbase.la -lcmocka 43 | test_iface_SOURCES = test_iface.c 44 | test_iface_LDFLAGS = -Wl,--wrap=read -Wl,--wrap=close -Wl,--wrap=getenv \ 45 | -Wl,--wrap=sid_comms_unix_init -Wl,--wrap=sid_comms_unix_recv \ 46 | -Wl,--wrap=sid_buf_write_all -Wl,--wrap=sid_buf_read \ 47 | -Wl,--wrap=mmap -Wl,--wrap=munmap 48 | test_iface_LDADD = $(top_builddir)/src/base/libsidbase.la -lcmocka 49 | test_internal_SOURCES = test_internal.c 50 | test_internal_LDADD = $(top_builddir)/src/internal/libsidinternal.la \ 51 | $(top_builddir)/src/base/libsidbase.la -lcmocka 52 | test_bptree_SOURCES = test_bptree.c 53 | test_bptree_LDADD = $(top_builddir)/src/internal/libsidinternal.la \ 54 | $(top_builddir)/src/base/libsidbase.la -lcmocka 55 | test_db_sync_SOURCES = test_db_sync.c 56 | test_db_sync_CFLAGS = -I$(top_srcdir)/src/include/resource 57 | test_db_sync_LDADD = \ 58 | $(top_builddir)/src/base/libsidbase.la \ 59 | $(top_builddir)/src/resource/libsidresource.la -lcmocka 60 | 61 | endif # HAVE_CMOCKA 62 | -------------------------------------------------------------------------------- /tests/test_bitmap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | static void test_invert_bmp(void **state) 17 | { 18 | int i, ret; 19 | struct bmp *bmp = bmp_create(32, true, &ret); 20 | assert_non_null(bmp); 21 | assert_int_equal(ret, 0); 22 | assert_int_equal(bmp_get_bit_count(bmp), bmp_get_bit_set_count(bmp)); 23 | for (i = 0; i < 32; i++) 24 | assert_int_equal(bmp_unset_bit(bmp, i), 0); 25 | assert_int_equal(bmp_unset_bit(bmp, 32), -ERANGE); 26 | assert_int_equal(bmp_get_bit_set_count(bmp), 0); 27 | } 28 | 29 | int main(void) 30 | { 31 | const struct CMUnitTest tests[] = { 32 | cmocka_unit_test(test_invert_bmp), 33 | }; 34 | return cmocka_run_group_tests(tests, NULL, NULL); 35 | } 36 | -------------------------------------------------------------------------------- /tests/test_hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "internal/hash.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #define KEY_COUNT 10 18 | 19 | char *test_array[KEY_COUNT] = { 20 | "1", 21 | "2", 22 | "3", 23 | "4", 24 | "5", 25 | "6", 26 | "7", 27 | "8", 28 | "9", 29 | "10", 30 | }; 31 | 32 | static void test_hash_add() 33 | { 34 | unsigned count = 0; 35 | struct hash_table *t = hash_create(5); 36 | 37 | for (int i = 0; i < KEY_COUNT; i++) 38 | assert_int_equal(hash_add(t, test_array[i], strlen(test_array[i]) + 1, test_array[i], strlen(test_array[i]) + 1), 39 | 0); 40 | 41 | assert_int_equal(hash_get_entry_count(t), KEY_COUNT); 42 | 43 | hash_wipe(t); 44 | assert_int_equal(hash_get_entry_count(t), 0); 45 | 46 | for (int i = 0; i < KEY_COUNT; i++) 47 | assert_int_equal(hash_add(t, test_array[i], strlen(test_array[i]) + 1, test_array[i], strlen(test_array[i]) + 1), 48 | 0); 49 | 50 | for (int i = 0; i < KEY_COUNT; i++) 51 | assert_int_equal(hash_add_allow_multiple(t, 52 | test_array[i], 53 | strlen(test_array[i]) + 1, 54 | test_array[i], 55 | strlen(test_array[i]) + 1), 56 | 0); 57 | 58 | for (int i = 0; i < KEY_COUNT; i++) { 59 | assert_string_equal(hash_lookup_with_count(t, test_array[i], strlen(test_array[i]) + 1, NULL, &count), 60 | test_array[i]); 61 | assert_int_equal(count, 2); 62 | } 63 | 64 | assert_int_equal(hash_get_entry_count(t), KEY_COUNT * 2); 65 | 66 | hash_destroy(t); 67 | } 68 | 69 | static void test_hash_lookup() 70 | { 71 | struct hash_table *t = hash_create(10); 72 | ; 73 | 74 | for (int i = 0; i < KEY_COUNT; i++) 75 | assert_int_equal(hash_add(t, test_array[i], strlen(test_array[i]) + 1, test_array[i], strlen(test_array[i]) + 1), 76 | 0); 77 | 78 | for (int i = 0; i < KEY_COUNT; i++) { 79 | assert_string_equal(hash_lookup_with_data(t, 80 | test_array[i], 81 | strlen(test_array[i]) + 1, 82 | test_array[i], 83 | strlen(test_array[i]) + 1), 84 | test_array[i]); 85 | } 86 | 87 | hash_destroy(t); 88 | } 89 | 90 | int main(void) 91 | { 92 | const struct CMUnitTest tests[] = { 93 | cmocka_unit_test(test_hash_add), 94 | cmocka_unit_test(test_hash_lookup), 95 | }; 96 | return cmocka_run_group_tests(tests, NULL, NULL); 97 | } 98 | -------------------------------------------------------------------------------- /tests/test_internal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "internal/comp-attrs.h" 8 | 9 | #include "internal/util.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | static void check_strv(char **output, char **goal) 19 | { 20 | while (*output && *goal) { 21 | assert_string_equal(*output, *goal); 22 | output++; 23 | goal++; 24 | } 25 | assert_null(*output); 26 | assert_null(*goal); 27 | } 28 | 29 | static void do_mem_test(const char *prefix, const char *str, const char *suffix, char *goal[]) 30 | { 31 | char buffer[128] __aligned_to(sizeof(char *)); 32 | char **output = (char **) buffer; 33 | struct util_mem mem = {.base = buffer, .size = sizeof(buffer)}; 34 | 35 | assert_ptr_equal(util_str_comb_to_strv(&mem, prefix, str, suffix, UTIL_STR_DEFAULT_DELIMS, UTIL_STR_DEFAULT_QUOTES), 36 | output); 37 | check_strv(output, goal); 38 | } 39 | 40 | static void fail_mem_test(const char *prefix, const char *str, const char *suffix) 41 | { 42 | char buffer[128] __aligned_to(sizeof(char *)); 43 | struct util_mem mem = {.base = buffer, .size = sizeof(buffer)}; 44 | 45 | assert_null(util_str_comb_to_strv(&mem, prefix, str, suffix, UTIL_STR_DEFAULT_DELIMS, UTIL_STR_DEFAULT_QUOTES)); 46 | } 47 | 48 | static void comb_mem_test0(void **state) 49 | { 50 | do_mem_test(NULL, NULL, NULL, (char *[]) {NULL}); 51 | } 52 | 53 | static void comb_mem_test1(void **state) 54 | { 55 | do_mem_test(NULL, "simple", NULL, (char *[]) {"simple", NULL}); 56 | } 57 | 58 | static void comb_mem_test2(void **state) 59 | { 60 | do_mem_test(NULL, "less simple", NULL, (char *[]) {"less", "simple", NULL}); 61 | } 62 | 63 | static void comb_mem_test3(void **state) 64 | { 65 | do_mem_test(NULL, "\n \tmany\t \t\tdelims\n here\t\n ", NULL, (char *[]) {"many", "delims", "here", NULL}); 66 | } 67 | 68 | static void comb_mem_test4(void **state) 69 | { 70 | do_mem_test(NULL, "\\we\\ignore\\ \\slashes\\", NULL, (char *[]) {"\\we\\ignore\\", "\\slashes\\", NULL}); 71 | } 72 | 73 | static void comb_mem_test5(void **state) 74 | { 75 | do_mem_test(NULL, "", NULL, (char *[]) {NULL}); 76 | } 77 | 78 | static void comb_mem_test6(void **state) 79 | { 80 | do_mem_test(NULL, "\f\n\t \v", NULL, (char *[]) {NULL}); 81 | } 82 | 83 | static void comb_mem_test7(void **state) 84 | { 85 | do_mem_test(" one two\n", "three", "four\tfive\n", (char *[]) {"one", "two", "three", "four", "five", NULL}); 86 | } 87 | 88 | static void comb_mem_test8(void **state) 89 | { 90 | do_mem_test(NULL, "\"simple quotes\"", NULL, (char *[]) {"simple quotes", NULL}); 91 | } 92 | 93 | static void comb_mem_test9(void **state) 94 | { 95 | do_mem_test(NULL, "'other quotes'", NULL, (char *[]) {"other quotes", NULL}); 96 | } 97 | 98 | static void comb_mem_test10(void **state) 99 | { 100 | do_mem_test("'\"quoted string\"'", NULL, NULL, (char *[]) {"\"quoted string\"", NULL}); 101 | } 102 | 103 | static void comb_mem_test11(void **state) 104 | { 105 | do_mem_test(NULL, NULL, "\"'other quoted string'\"", (char *[]) {"'other quoted string'", NULL}); 106 | } 107 | 108 | static void comb_mem_test12(void **state) 109 | { 110 | do_mem_test(NULL, NULL, "can't won't", (char *[]) {"cant wont", NULL}); 111 | } 112 | 113 | static void comb_mem_test13(void **state) 114 | { 115 | do_mem_test(NULL, NULL, "this' is' a f\"ront merge\"", (char *[]) {"this is", "a", "front merge", NULL}); 116 | } 117 | 118 | static void comb_mem_test14(void **state) 119 | { 120 | do_mem_test("'this 'is a", "\"back me\"rge", NULL, (char *[]) {"this is", "a", "back merge", NULL}); 121 | } 122 | 123 | static void comb_mem_test15(void **state) 124 | { 125 | do_mem_test("still' 'more' 'merging", 126 | "fun\" \"with\" \"merging", 127 | "mixed\" \"quote' 'merging", 128 | (char *[]) {"still more merging", "fun with merging", "mixed quote merging", NULL}); 129 | } 130 | 131 | static void comb_mem_test16(void **state) 132 | { 133 | do_mem_test(NULL, NULL, "merging\" 'with' \"embedded quotes", (char *[]) {"merging 'with' embedded", "quotes", NULL}); 134 | } 135 | 136 | static void comb_mem_test17(void **state) 137 | { 138 | do_mem_test("\"Goonies don't say\"' \"Die\"'", 139 | NULL, 140 | "\"Actually, it's \"'\"Goonies never say'\" 'Die'\"'\"'", 141 | (char *[]) {"Goonies don't say \"Die\"", "Actually, it's \"Goonies never say 'Die'\"", NULL}); 142 | } 143 | 144 | static void bad_mem_test_missing1(void **state) 145 | { 146 | fail_mem_test("only one 'quote", NULL, NULL); 147 | } 148 | 149 | static void bad_mem_test_missing2(void **state) 150 | { 151 | fail_mem_test(NULL, "only one 'quote", NULL); 152 | } 153 | 154 | static void bad_mem_test_missing3(void **state) 155 | { 156 | fail_mem_test(NULL, "\"only three\"\"quotes", NULL); 157 | } 158 | 159 | static void bad_mem_test_missing4(void **state) 160 | { 161 | fail_mem_test(NULL, "\"two missmatched' quotes", NULL); 162 | } 163 | 164 | static void bad_mem_test_missing5(void **state) 165 | { 166 | fail_mem_test(NULL, "'four missmatched\" \"quotes\"", NULL); 167 | } 168 | 169 | static void bad_mem_test_missing6(void **state) 170 | { 171 | fail_mem_test("quotes don't", "match when they're \"in different sections\"", NULL); 172 | } 173 | 174 | static void bad_mem_test_small(void **state) 175 | { 176 | char buffer[16] __aligned_to(sizeof(char *)); 177 | struct util_mem mem = {.base = buffer, .size = sizeof(buffer)}; 178 | 179 | assert_null(util_str_comb_to_strv(&mem, "too", "many", "strings", UTIL_STR_DEFAULT_DELIMS, UTIL_STR_DEFAULT_QUOTES)); 180 | } 181 | 182 | static void do_alloc_test(const char *prefix, const char *str, const char *suffix, char *goal[]) 183 | { 184 | char **output = util_str_comb_to_strv(NULL, prefix, str, suffix, UTIL_STR_DEFAULT_DELIMS, UTIL_STR_DEFAULT_QUOTES); 185 | assert_non_null(output); 186 | check_strv(output, goal); 187 | free(output); 188 | } 189 | 190 | static void comb_alloc_test0(void **state) 191 | { 192 | do_alloc_test(NULL, NULL, NULL, (char *[]) {NULL}); 193 | } 194 | 195 | static void comb_alloc_test1(void **state) 196 | { 197 | do_alloc_test("prefix", "str", "suffix", (char *[]) {"prefix", "str", "suffix", NULL}); 198 | } 199 | 200 | int main(void) 201 | { 202 | const struct CMUnitTest tests[] = { 203 | cmocka_unit_test(comb_mem_test0), cmocka_unit_test(comb_mem_test1), 204 | cmocka_unit_test(comb_mem_test2), cmocka_unit_test(comb_mem_test3), 205 | cmocka_unit_test(comb_mem_test4), cmocka_unit_test(comb_mem_test5), 206 | cmocka_unit_test(comb_mem_test6), cmocka_unit_test(comb_mem_test7), 207 | cmocka_unit_test(comb_mem_test8), cmocka_unit_test(comb_mem_test9), 208 | cmocka_unit_test(comb_mem_test10), cmocka_unit_test(comb_mem_test11), 209 | cmocka_unit_test(comb_mem_test12), cmocka_unit_test(comb_mem_test13), 210 | cmocka_unit_test(comb_mem_test14), cmocka_unit_test(comb_mem_test15), 211 | cmocka_unit_test(comb_mem_test16), cmocka_unit_test(comb_mem_test17), 212 | cmocka_unit_test(bad_mem_test_small), cmocka_unit_test(bad_mem_test_missing1), 213 | cmocka_unit_test(bad_mem_test_missing2), cmocka_unit_test(bad_mem_test_missing3), 214 | cmocka_unit_test(bad_mem_test_missing4), cmocka_unit_test(bad_mem_test_missing5), 215 | cmocka_unit_test(bad_mem_test_missing6), cmocka_unit_test(comb_alloc_test0), 216 | cmocka_unit_test(comb_alloc_test1), 217 | }; 218 | return cmocka_run_group_tests(tests, NULL, NULL); 219 | } 220 | -------------------------------------------------------------------------------- /tests/test_notify.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "../src/iface/srv-lnk.c" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | int __wrap_sd_notify(int unset_environment, const char *state) 18 | { 19 | assert_string_equal(state, mock_ptr_type(char *)); 20 | return 0; 21 | } 22 | 23 | int __real_sid_buf_get_data(struct sid_buf *buf, const void **data, size_t *data_size); 24 | 25 | int __wrap_sid_buf_get_data(struct sid_buf *buf, const void **data, size_t *data_size) 26 | { 27 | int r = __real_sid_buf_get_data(buf, data, data_size); 28 | assert_true(!*data || *data_size); 29 | return r; 30 | } 31 | 32 | static void test_notify_ready(void **state) 33 | { 34 | struct sid_srv_lnk *sl = sid_srv_lnk_create(SID_SRV_LNK_TYPE_SYSTEMD, "systemd"); 35 | 36 | assert_non_null(sl); 37 | sid_srv_lnk_notif_add(sl, SID_SRV_LNK_NOTIF_READY); 38 | will_return(__wrap_sd_notify, "READY=1\n"); 39 | assert_int_equal(sid_srv_lnk_notify(sl, SID_SRV_LNK_NOTIF_READY, &SID_SRV_LNK_DEFAULT_LOG_REQ, NULL), 0); 40 | sid_srv_lnk_destroy(sl); 41 | } 42 | 43 | static void test_notify_ready_reloading(void **state) 44 | { 45 | struct sid_srv_lnk *sl = sid_srv_lnk_create(SID_SRV_LNK_TYPE_SYSTEMD, "systemd"); 46 | 47 | assert_non_null(sl); 48 | sid_srv_lnk_notif_add(sl, SID_SRV_LNK_NOTIF_READY); 49 | sid_srv_lnk_notif_add(sl, SID_SRV_LNK_NOTIF_RELOADING); 50 | will_return(__wrap_sd_notify, "READY=1\nRELOADING=1\n"); 51 | assert_int_equal( 52 | sid_srv_lnk_notify(sl, SID_SRV_LNK_NOTIF_READY | SID_SRV_LNK_NOTIF_RELOADING, &SID_SRV_LNK_DEFAULT_LOG_REQ, NULL), 53 | 0); 54 | sid_srv_lnk_destroy(sl); 55 | } 56 | 57 | static void test_notify_blank(void **state) 58 | { 59 | struct sid_srv_lnk *sl = sid_srv_lnk_create(SID_SRV_LNK_TYPE_SYSTEMD, "systemd"); 60 | 61 | assert_non_null(sl); 62 | sid_srv_lnk_notif_add(sl, SID_SRV_LNK_NOTIF_STATUS); 63 | will_return(__wrap_sd_notify, ""); 64 | assert_int_equal(sid_srv_lnk_notify(sl, SID_SRV_LNK_NOTIF_STATUS, &SID_SRV_LNK_DEFAULT_LOG_REQ, NULL), 0); 65 | sid_srv_lnk_destroy(sl); 66 | } 67 | 68 | static void test_notify_errno(void **state) 69 | { 70 | struct sid_srv_lnk *sl = sid_srv_lnk_create(SID_SRV_LNK_TYPE_SYSTEMD, "systemd"); 71 | 72 | assert_non_null(sl); 73 | sid_srv_lnk_notif_add(sl, SID_SRV_LNK_NOTIF_ERRNO); 74 | will_return(__wrap_sd_notify, "ERRNO=2\n"); 75 | assert_int_equal(sid_srv_lnk_notify(sl, SID_SRV_LNK_NOTIF_ERRNO, &SID_SRV_LNK_DEFAULT_LOG_REQ, "ERRNO=%d\n", 2), 0); 76 | sid_srv_lnk_destroy(sl); 77 | } 78 | 79 | static void test_notify_errno_status(void **state) 80 | { 81 | struct sid_srv_lnk *sl = sid_srv_lnk_create(SID_SRV_LNK_TYPE_SYSTEMD, "systemd"); 82 | 83 | assert_non_null(sl); 84 | sid_srv_lnk_notif_add(sl, SID_SRV_LNK_NOTIF_ERRNO); 85 | sid_srv_lnk_notif_add(sl, SID_SRV_LNK_NOTIF_STATUS); 86 | will_return(__wrap_sd_notify, "STATUS=testing\nERRNO=2\n"); 87 | assert_int_equal(sid_srv_lnk_notify(sl, 88 | SID_SRV_LNK_NOTIF_ERRNO | SID_SRV_LNK_NOTIF_STATUS, 89 | &SID_SRV_LNK_DEFAULT_LOG_REQ, 90 | "ERRNO=%d\nSTATUS=testing", 91 | 2), 92 | 0); 93 | sid_srv_lnk_destroy(sl); 94 | } 95 | 96 | int main(void) 97 | { 98 | const struct CMUnitTest tests[] = { 99 | cmocka_unit_test(test_notify_ready), 100 | cmocka_unit_test(test_notify_ready_reloading), 101 | cmocka_unit_test(test_notify_blank), 102 | cmocka_unit_test(test_notify_errno), 103 | cmocka_unit_test(test_notify_errno_status), 104 | }; 105 | return cmocka_run_group_tests(tests, NULL, NULL); 106 | } 107 | -------------------------------------------------------------------------------- /udev/00-sid.rules: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | SUBSYSTEM!="block", GOTO="sid_end" 8 | ACTION!="add|change|remove", GOTO="sid_end" 9 | 10 | IMPORT{db}="SID_DEV_ID" 11 | IMPORT{program}="usid scan" 12 | ENV{.SID_TAGS}=="?*", TAG+="$env{.SID_TAGS}" 13 | 14 | LABEL="sid_end" 15 | -------------------------------------------------------------------------------- /udev/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: (C) 2017-2025 Red Hat, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-2.0-or-later 5 | # 6 | 7 | dist_udevrules_DATA = 00-sid.rules 8 | --------------------------------------------------------------------------------