Feat: Erstellt die Crate

This commit is contained in:
2026-08-26 19:08:10 +02:00
parent bc93de12ce
commit 07177265df
8 changed files with 210 additions and 81 deletions
+1
View File
@@ -3,6 +3,7 @@
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" /> <excludeFolder url="file://$MODULE_DIR$/target" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
+15 -11
View File
@@ -1,12 +1,14 @@
# AGENTS.md # AGENTS.md
Dieses Dokument definiert Richtlinien, Konventionen und Arbeitsanweisungen für KI-Agenten und LLM-Tools, die an diesem Repository oder daraus erstellten Rust-Crates arbeiten. Dieses Dokument definiert Richtlinien, Konventionen und Arbeitsanweisungen für KI-Agenten und LLM-Tools, die an diesem Repository (`sudo-ctdra`) arbeiten.
--- ---
## 1. Projektübersicht & Kontext ## 1. Projektübersicht & Kontext
- **Typ:** Rust Library Crate Template - **Projektname:** `sudo-ctdra`
- **Typ:** Rust Library
- **Zweck:** Bereitstellung von Hilfsfunktionen zur Überprüfung (`is_run_as_root`) und Anforderung von Root-Rechten via `sudo` (`run_as_root`).
- **Rust Edition:** `2024` - **Rust Edition:** `2024`
- **Einstiegspunkt:** `src/lib.rs` - **Einstiegspunkt:** `src/lib.rs`
- **CI/CD Plattform:** Gitea Actions (`.gitea/workflows/`) - **CI/CD Plattform:** Gitea Actions (`.gitea/workflows/`)
@@ -20,18 +22,19 @@ Dieses Dokument definiert Richtlinien, Konventionen und Arbeitsanweisungen für
### 2.1 Sprache & Idiomatik ### 2.1 Sprache & Idiomatik
- Verwende modernes, idiomatisches Rust (Edition 2024). - Verwende modernes, idiomatisches Rust (Edition 2024).
- Bevorzuge explizite Typen und klare Signaturen in öffentlichen Schnittstellen (`pub`). - Bevorzuge explizite Typen und klare Signaturen in öffentlichen Schnittstellen (`pub`).
- Halte die API ergonomisch und benutzerfreundlich. - Halte die API ergonomisch, leichtgewichtig und benutzerfreundlich.
### 2.2 Fehlerbehandlung ### 2.2 Fehlerbehandlung
- Nutze `Result<T, E>` und `Option<T>` für alle potenziell fehlschlagenden Operationen. - Nutze `Result<T, E>`, `Option<T>` oder explizite Fehlerrückgaben (`std::io::Error`) für alle potenziell fehlschlagenden Operationen.
- Definiere aussagekräftige, domänenspezifische Fehlertypen (z. B. via `thiserror` oder standardmäßig `std::error::Error`).
- **Verboten im produktiven Bibliothekscode (`src/`):** - **Verboten im produktiven Bibliothekscode (`src/`):**
- Unbegründete `unwrap()`, `expect()` oder `panic!()` Aufrufe. - Unbegründete `unwrap()`, `expect()` oder `panic!()` Aufrufe.
- Abrupter Programmabbruch via `std::process::exit` innerhalb von Bibliotheksfunktionen (Fehler müssen stattdessen an den Aufrufer zurückgegeben werden).
- Direktes oder ungefragtes Logging via Hilfsfunktionen oder Makros im Bibliothekscode; Fehlermeldungen / Fehlerstrukturen sind als Rückgabewerte zu liefern.
- Ignorieren von Fehlern via `let _ = ...`, es sei denn, es ist explizit begründet und dokumentiert. - Ignorieren von Fehlern via `let _ = ...`, es sei denn, es ist explizit begründet und dokumentiert.
### 2.3 Dokumentation ### 2.3 Dokumentation
- Dokumentiere alle öffentlichen Module, Structs, Enums, Traits und Funktionen mit Rustdoc-Kommentaren (`///` bzw. Modul-Ebene `//!`). - Dokumentiere alle öffentlichen Module, Structs, Enums, Traits und Funktionen mit Rustdoc-Kommentaren (`///` bzw. Modul-Ebene `//!`).
- Füge für öffentliche Schnittstellen nach Möglichkeit Code-Beispiele ein, die über `cargo test --doc` automatisch validiert werden. - Füge für öffentliche Schnittstellen Code-Beispiele ein, die über `cargo test --doc` automatisch validiert werden.
### 2.4 Code-Qualität & Formatierung ### 2.4 Code-Qualität & Formatierung
- Halte den Code stets formatiert gemäß `rustfmt` (`cargo fmt`). - Halte den Code stets formatiert gemäß `rustfmt` (`cargo fmt`).
@@ -92,10 +95,11 @@ Die CI/CD-Pipelines werden über Gitea Actions gesteuert:
--- ---
## 5. Arbeitsanweisungen für Agenten bei Projekt-Initialisierung ## 5. Arbeitsanweisungen für Agenten
Wenn dieser Template-Stand verwendet wird, um eine neue Crate zu erstellen: Bei Änderungen an diesem Repository:
1. Aktualisiere die `Cargo.toml`-Metadaten (`name`, `version`, `authors`, `repository`, `description`). 1. Pflege die Metadaten in `Cargo.toml` (`version`, `description`, etc.).
2. Passe die `README.md` an die konkrete Funktionalität der neuen Crate an. 2. Halte `README.md` und `AGENTS.md` aktuell bezüglich Funktionsumfang und Konventionen.
3. Behalte die Gitea-Workflows bei oder passe sie an das Ziel-Repository an. 3. Behalte die Gitea-Workflows bei bzw. passe sie bei Änderungen an.
4. Stelle sicher, dass keine Secrets, temporären Build-Dateien (`target/`) oder IDE-spezifischen Caches (außer `.idea` Konfigurationen) committed werden. 4. Stelle sicher, dass keine Secrets, temporären Build-Dateien (`target/`) oder IDE-spezifischen Caches (außer `.idea` Konfigurationen) committed werden.
5. Führe stets alle Prüfungen gemäß Abschnitt 3.2 vor Abschluss der Arbeiten durch.
Generated
+10 -1
View File
@@ -3,5 +3,14 @@
version = 4 version = 4
[[package]] [[package]]
name = "rust-creat-template" name = "libc"
version = "1.0.0-alpha.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d0f24f33af482526a4e3f9b47f0abb2c6377a1713c8aa4a8106994689a4cfa5"
[[package]]
name = "sudo-ctdra"
version = "1.0.0" version = "1.0.0"
dependencies = [
"libc",
]
+6 -14
View File
@@ -1,23 +1,15 @@
[package] [package]
name = "rust-creat-template" # TODO Setzen name = "sudo-ctdra"
version = "1.0.0" # TODO Setzen version = "1.0.0"
edition = "2024" edition = "2024"
authors = ['DragonSlayer_14'] # TODO Setzen authors = ['DragonSlayer_14']
readme = "README.md" readme = "README.md"
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"
repository = "https://gitea.creative-dragonslayer.de/Templates/rust-crate-template" # TODO Setzen repository = "https://gitea.creative-dragonslayer.de/Rust-Crates/sudo"
description = "Ein Template-Projekt, das fürs erstellen von Rust-Crates verwendet werden kann." # TODO Setzen description = "Eine Rust-Bibliothek zur Überprüfung und Anforderung von Root-Rechten über sudo unter Linux."
[dependencies] [dependencies]
libc = "1.0.0-alpha.4"
[profile.release] [profile.release]
debug = "none" debug = "none"
[registry]
default = "gitea"
[registries.gitea]
index = "sparse+https://gitea.creative-dragonslayer.de/api/packages/Rust-Crates/cargo/"
[net]
git-fetch-with-cli = true
+2 -2
View File
@@ -208,7 +208,7 @@ If you develop a new program, and you want it to be of the greatest possible use
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.
rust-crate-template sudo
Copyright (C) 2026 Rust-Crates Copyright (C) 2026 Rust-Crates
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -221,7 +221,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:
rust-crate-template Copyright (C) 2026 Rust-Crates sudo Copyright (C) 2026 Rust-Crates
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
+51 -53
View File
@@ -1,17 +1,54 @@
# Rust Crate Template # sudo-ctdra
Ein vorkonfiguriertes Template-Projekt für die schnelle und standardisierte Entwicklung von Rust-Crates (Libraries) mit automatisierter CI/CD-Pipeline für Gitea. Eine kompakte, leichtgewichtige Rust-Bibliothek zur Überprüfung und Anforderung von Root-/Administrator-Rechten über `sudo` unter Linux und Unix-Systemen.
--- ---
## 🚀 Übersicht & Features ## 🚀 Übersicht & Features
- **Rust Edition 2024**: Moderner Rust-Standard mit optimierten Profil-Einstellungen (`profile.release.debug = "none"`). - **Root-Prüfung (`is_run_as_root`)**: Schnelle und zuverlässige Überprüfung der effektiven Benutzer-ID (`libc::geteuid() == 0`).
- **Automatisierte CI/CD-Workflows (Gitea Actions)**: - **Prozess-Eskalation (`run_as_root`)**: Startet das aktuelle Programm über `sudo` neu, übergibt alle Befehlszeilenargumente (`std::env::args`) und ersetzt den aktuellen Prozess ([`CommandExt::exec`](https://doc.rust-lang.org/std/os/unix/process/trait.CommandExt.html#tymethod.exec)).
- **Testing-Pipeline (`testing`-Branch)**: Führt Tests und Compiler-Checks aus und erstellt automatisch ein Gitea Pre-Release (`v<VERSION>-preview`) inklusive `.crate`-Paket als Release-Asset. - **Saubere Fehlerbehandlung**: Gibt bei Fehlschlägen einen [`std::io::Error`] zurück, anstatt das Programm unkontrolliert zu beenden oder ungefragt zu loggen.
- **Main-Release-Pipeline (`main`-Branch)**: Führt Tests und Compiler-Checks aus, paketiert die Crate, veröffentlicht sie in der Gitea Cargo Package Registry und erstellt ein offizielles Gitea Release (`v<VERSION>`) mit Asset. - **Rust Edition 2024**: Moderner Rust-Standard mit optimierten Profileinstellungen.
- **Integrierte Gitea Package Registry**: Vorkonfigurierte sparse index Registry-Anbindung. - **Automatisierte CI/CD-Workflows**: Vorkonfigurierte Gitea Actions für Tests, Compiler-Checks, Paketierung und Releases.
- **GPL-3.0-or-later Lizenz**: Vorkonfiguriert mit Lizenzdatei und Metadaten.
---
## 📦 Einbindung
Füge die Crate zu deiner `Cargo.toml` hinzu:
```toml
[dependencies]
sudo-ctdra = { version = "1.0.0", registry = "gitea" }
```
Falls die Gitea Package Registry genutzt wird, trage diese in deiner `.cargo/config.toml` ein:
```toml
[registries.gitea]
index = "sparse+https://gitea.creative-dragonslayer.de/api/packages/Rust-Crates/cargo/"
```
---
## 💡 Anwendungsbeispiel
```rust
use sudo_ctdra::{is_run_as_root, run_as_root};
fn main() {
if is_run_as_root() {
println!("Programm läuft mit Root-Rechten.");
// Privilegierte Aktionen durchführen...
} else {
println!("Normale Benutzerrechte erkannt. Starte neu als Root über sudo...");
let err = run_as_root();
eprintln!("Fehler beim Ausführen von 'sudo': {err}");
std::process::exit(1);
}
}
```
--- ---
@@ -25,7 +62,9 @@ Ein vorkonfiguriertes Template-Projekt für die schnelle und standardisierte Ent
│ └── testing.yaml # CI/CD: Test, Check & Pre-Release für 'testing' │ └── testing.yaml # CI/CD: Test, Check & Pre-Release für 'testing'
├── .idea/ # Vorkonfigurierte JetBrains IDE Einstellungen ├── .idea/ # Vorkonfigurierte JetBrains IDE Einstellungen
├── src/ ├── src/
│ └── lib.rs # Einstiegspunkt der Crate / Library │ └── lib.rs # Einstiegspunkt der Crate / Bibliotheksfunktionen
├── tests/
│ └── integration_tests.rs # Integrations- und Subprozess-Tests
├── Cargo.lock ├── Cargo.lock
├── Cargo.toml # Crate-Manifest & Metadaten ├── Cargo.toml # Crate-Manifest & Metadaten
├── LICENSE # GNU General Public License v3.0 ├── LICENSE # GNU General Public License v3.0
@@ -35,39 +74,16 @@ Ein vorkonfiguriertes Template-Projekt für die schnelle und standardisierte Ent
--- ---
## 🛠️ Verwendung als Template
### 1. Template initialisieren & Metadaten anpassen
Passe nach dem Klonen bzw. Erstellen des neuen Repositories die Platzhalter in `Cargo.toml` an:
```toml
[package]
name = "mein-crate-name"
version = "0.1.0"
edition = "2024"
authors = ['DeinName <deine.email@example.com>']
readme = "README.md"
license = "GPL-3.0-or-later"
repository = "https://gitea.example.com/Organisation/mein-crate-name"
description = "Beschreibung der Crate."
```
### 2. Gitea Repository Secrets einrichten
Für die Veröffentlichung und Release-Erstellung in Gitea Actions muss mindestens ein Access-Token als Repository-Secret hinterlegt werden (z. B. unter `Einstellungen -> Secrets -> Actions`):
- `PACKAGE_TOKEN` (oder alternativ `RELEASE_TOKEN`, `GITEA_TOKEN`): Ein Personal Access Token mit Berechtigungen für Packages (`write:package`) und Repositories/Releases (`write:repository`).
---
## 💻 Lokale Entwicklung & Befehle ## 💻 Lokale Entwicklung & Befehle
Die gängigen Cargo-Befehle zur Entwicklung: Die gängigen Cargo-Befehle zur Entwicklung und Validierung:
- **Kompilierung prüfen:** - **Kompilierung prüfen:**
```bash ```bash
cargo check --all-targets cargo check --all-targets
``` ```
- **Tests ausführen:** - **Tests ausführen (Unit-, Integrations- und Doc-Tests):**
```bash ```bash
cargo test cargo test
``` ```
@@ -97,25 +113,7 @@ Die gängigen Cargo-Befehle zur Entwicklung:
| `testing` | Push auf `testing` | • `cargo test`<br>• `cargo check --all-targets`<br>• `cargo package`<br>• Erstellt/Aktualisiert Pre-Release `v<VERSION>-preview` mit `.crate`-Asset | | `testing` | Push auf `testing` | • `cargo test`<br>• `cargo check --all-targets`<br>• `cargo package`<br>• Erstellt/Aktualisiert Pre-Release `v<VERSION>-preview` mit `.crate`-Asset |
| `main` | Push auf `main` | • `cargo test`<br>• `cargo check --all-targets`<br>• `cargo package`<br>• Veröffentlicht Crate in Gitea Package Registry<br>• Erstellt/Aktualisiert Release `v<VERSION>` mit `.crate`-Asset | | `main` | Push auf `main` | • `cargo test`<br>• `cargo check --all-targets`<br>• `cargo package`<br>• Veröffentlicht Crate in Gitea Package Registry<br>• Erstellt/Aktualisiert Release `v<VERSION>` mit `.crate`-Asset |
> **Hinweis zur Versionierung:** Die Versionsnummer wird automatisch aus `Cargo.toml` (`version = "..."`) ausgelesen. Passe vor einem Merge auf `main` oder `testing` die Version in `Cargo.toml` entsprechend SemVer an. > **Hinweis zur Versionierung:** Die Versionsnummer wird automatisch aus `Cargo.toml` (`version = "..."`) ausgelesen. Passe vor einem Release / Merge die Version in `Cargo.toml` entsprechend **SemVer** an.
---
## 📦 Verwenden der Crate in anderen Projekten
Um die in der Gitea Package Registry veröffentlichte Crate in einem anderen Cargo-Projekt zu verwenden:
1. Trage die Registry in deiner lokalen `~/.cargo/config.toml` oder projektweiten `.cargo/config.toml` ein:
```toml
[registries.gitea]
index = "sparse+https://gitea.creative-dragonslayer.de/api/packages/Rust-Crates/cargo/"
```
2. Binde die Crate in deiner `Cargo.toml` ein:
```toml
[dependencies]
mein-crate-name = { version = "1.0.0", registry = "gitea" }
```
--- ---
+86
View File
@@ -0,0 +1,86 @@
//! Eine leichtgewichtige Rust-Bibliothek zur Überprüfung und Anforderung von Root-Rechten über `sudo`.
//!
//! # Beispiele
//!
//! ```rust
//! use sudo_ctdra::is_run_as_root;
//!
//! if is_run_as_root() {
//! println!("Das Programm läuft mit Root-Rechten.");
//! } else {
//! println!("Das Programm läuft mit normalen Benutzerrechten.");
//! }
//! ```
use std::env;
use std::io;
use std::os::unix::process::CommandExt;
use std::process::Command;
/// Prüft, ob das Programm mit Root-/Administrator-Rechten ausgeführt wird.
///
/// Ermittelt anhand der effektiven Benutzer-ID (`geteuid() == 0`), ob der aktuelle
/// Prozess über Root-Rechte verfügt.
///
/// # Returns
///
/// * `true` - Das Programm läuft mit erhöhten Rechten (EUID == 0)
/// * `false` - Das Programm läuft mit normalen Benutzerrechten
///
/// # Beispiele
///
/// ```rust
/// use sudo_ctdra::is_run_as_root;
///
/// let is_root = is_run_as_root();
/// println!("Läuft als Root: {}", is_root);
/// ```
#[must_use]
pub fn is_run_as_root() -> bool {
unsafe { libc::geteuid() == 0 }
}
/// Startet das Programm mit Root-Rechten über `sudo` neu.
///
/// Diese Funktion versucht das Programm mit erhöhten Rechten via `sudo` neu zu starten
/// und übergibt dabei alle bisherigen Befehlszeilenargumente (`std::env::args`).
///
/// Da bei erfolgreicher Ausführung der bestehende Prozess durch den `sudo`-Aufruf
/// ersetzt wird ([`CommandExt::exec`]), kehrt diese Funktion im Erfolgsfall nicht zurück.
///
/// # Returns
///
/// Gibt einen [`std::io::Error`] zurück, falls die Ausführung von `sudo` fehlschlägt.
///
/// # Beispiele
///
/// ```no_run
/// use sudo_ctdra::{is_run_as_root, run_as_root};
///
/// if !is_run_as_root() {
/// let err = run_as_root();
/// eprintln!("Fehler beim Neustart mit Root-Rechten: {err}");
/// }
/// ```
pub fn run_as_root() -> io::Error {
let commandline_args: Vec<String> = env::args().collect();
Command::new("sudo").args(&commandline_args).exec()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_run_as_root_matches_libc_geteuid() {
let expected = unsafe { libc::geteuid() == 0 };
assert_eq!(is_run_as_root(), expected);
}
#[test]
fn test_is_run_as_root_consistency() {
let first = is_run_as_root();
let second = is_run_as_root();
assert_eq!(first, second);
}
}
+39
View File
@@ -0,0 +1,39 @@
use std::process::Command;
use sudo_ctdra::{is_run_as_root, run_as_root};
#[test]
fn test_public_api_is_run_as_root() {
let is_root = is_run_as_root();
let expected = unsafe { libc::geteuid() == 0 };
assert_eq!(is_root, expected);
}
#[test]
fn test_run_as_root_returns_io_error_when_command_fails() {
if std::env::var("TEST_RUN_AS_ROOT_SUBPROCESS").is_ok() {
let err = run_as_root();
if err.kind() == std::io::ErrorKind::NotFound {
std::process::exit(42);
} else {
std::process::exit(1);
}
}
let current_exe =
std::env::current_exe().expect("Pfad zur Test-Executable konnte nicht ermittelt werden");
let output = Command::new(current_exe)
.arg("test_run_as_root_returns_io_error_when_command_fails")
.arg("--exact")
.arg("--nocapture")
.env("TEST_RUN_AS_ROOT_SUBPROCESS", "1")
.env("PATH", "")
.output()
.expect("Subprozess konnte nicht ausgeführt werden");
assert_eq!(
output.status.code(),
Some(42),
"Subprozess sollte mit Exit-Code 42 beendet worden sein (ErrorKind::NotFound). Stderr: {}",
String::from_utf8_lossy(&output.stderr)
);
}