init commit: 0.1.0
This commit is contained in:
commit
57e82f86a5
|
@ -0,0 +1,3 @@
|
|||
.direnv/*
|
||||
/target
|
||||
result
|
|
@ -0,0 +1,77 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "nixos-reedsreboot"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"strum",
|
||||
"strum_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.26.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f"
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.26.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.52"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "nixos-reedsreboot"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
description = "Determine if you need to reboot your NixOS machine"
|
||||
license = "GPL-2.0"
|
||||
repository = "https://github.com/thefossguy/nixos-reedsreboot"
|
||||
readme = "README.md"
|
||||
keywords = [ "nixos" ]
|
||||
categories = [ "command-line-utilities" ]
|
||||
|
||||
[dependencies]
|
||||
strum = "0.26"
|
||||
strum_macros = "0.26"
|
|
@ -0,0 +1,4 @@
|
|||
# nixos-needsreboot
|
||||
|
||||
Checks if you should reboot your NixOS machine in case an upgrade brought in
|
||||
some new goodies. :)
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1709309926,
|
||||
"narHash": "sha256-VZFBtXGVD9LWTecGi6eXrE0hJ/mVB3zGUlHImUs2Qak=",
|
||||
"rev": "79baff8812a0d68e24a836df0a364c678089e2c7",
|
||||
"revCount": 556338,
|
||||
"type": "tarball",
|
||||
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.2311.556338%2Brev-79baff8812a0d68e24a836df0a364c678089e2c7/018dfea4-6d6e-74d3-b5df-3d859de1988e/source.tar.gz"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://flakehub.com/f/NixOS/nixpkgs/%2A.tar.gz"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
inputs = {
|
||||
# a better way of using the latest stable version of nixpkgs
|
||||
# without specifying specific release
|
||||
nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/*.tar.gz";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }:
|
||||
let
|
||||
# helpers for producing system-specific outputs
|
||||
supportedSystems = [
|
||||
"aarch64-linux"
|
||||
"riscv64-linux"
|
||||
"x86_64-linux"
|
||||
];
|
||||
forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f {
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
});
|
||||
in
|
||||
{
|
||||
devShells = forEachSupportedSystem ({ pkgs, ... }: {
|
||||
default = pkgs.mkShell {
|
||||
packages = with pkgs; [
|
||||
rustup
|
||||
gdb
|
||||
pkg-config
|
||||
|
||||
# formatting this flake
|
||||
nixpkgs-fmt
|
||||
];
|
||||
};
|
||||
});
|
||||
|
||||
packages = forEachSupportedSystem ({ pkgs, ... }: {
|
||||
default = pkgs.rustPlatform.buildRustPackage {
|
||||
pname = "nixos-needsreboot";
|
||||
version = "0.1.0";
|
||||
src = ./.;
|
||||
|
||||
cargoHash = "sha256-5b8db/Jy17u+olpJy4aeR7BO7m01yxzg++ar2u5gYk0=";
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
use std::{error::Error, fmt, fs};
|
||||
use strum::IntoEnumIterator;
|
||||
use strum_macros::EnumIter;
|
||||
|
||||
use crate::{NEW_SYSTEM_PATH, OLD_SYSTEM_PATH};
|
||||
|
||||
#[derive(EnumIter)]
|
||||
enum ModuleType {
|
||||
LinuxKernel,
|
||||
Systemd,
|
||||
}
|
||||
|
||||
// for printing messages
|
||||
impl fmt::Display for ModuleType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::LinuxKernel => write!(f, "Linux Kernel"),
|
||||
Self::Systemd => write!(f, "Systemd"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for getting the "suffix"
|
||||
impl fmt::Debug for ModuleType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::LinuxKernel => write!(f, "/kernel"),
|
||||
Self::Systemd => write!(f, "/system"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleType {
|
||||
fn get_nix_store_path(&self, use_old_path: bool) -> Result<String, Box<dyn Error>> {
|
||||
let suffix = match self {
|
||||
Self::LinuxKernel => "/kernel",
|
||||
Self::Systemd => "/systemd",
|
||||
};
|
||||
let strip_suffix = match self {
|
||||
Self::Systemd => false,
|
||||
Self::LinuxKernel => true,
|
||||
};
|
||||
|
||||
let system_path = if use_old_path {
|
||||
OLD_SYSTEM_PATH.to_string()
|
||||
} else {
|
||||
NEW_SYSTEM_PATH.to_string()
|
||||
};
|
||||
|
||||
let tmp_module_path = fs::read_link(system_path + suffix)?
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.expect("Cannot convert PathBuf to String");
|
||||
|
||||
let nix_module_path = if strip_suffix {
|
||||
let split_module_path = tmp_module_path.split('/').collect::<Vec<&str>>();
|
||||
let mut module_dir = split_module_path
|
||||
.get(1..4)
|
||||
.ok_or("Cannot find the module's directory in /nix/store")?
|
||||
.join("/");
|
||||
module_dir.insert(0, '/');
|
||||
module_dir
|
||||
} else {
|
||||
tmp_module_path
|
||||
};
|
||||
|
||||
Ok(nix_module_path)
|
||||
}
|
||||
|
||||
fn get_linux_version(linux_path: &str) -> Result<String, Box<dyn Error>> {
|
||||
let lib_modules_path = fs::read_dir(linux_path)?
|
||||
.nth(0)
|
||||
.ok_or("Expected one directory in ".to_string() + linux_path)??
|
||||
.path()
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.expect("Cannot convert PathBuf to String");
|
||||
let linux_version = lib_modules_path.split('/').nth(6).ok_or(
|
||||
"Could not determine Linux kernel version from path: ".to_string() + &lib_modules_path,
|
||||
)?;
|
||||
|
||||
Ok(linux_version.to_string())
|
||||
}
|
||||
|
||||
fn get_systemd_version(systemd_path: &str) -> Result<String, Box<dyn Error>> {
|
||||
let split_systemd_path = systemd_path.split('-').collect::<Vec<&str>>();
|
||||
let systemd_version = split_systemd_path
|
||||
.get(2..)
|
||||
.ok_or("Could not determine Systemd version from path: ".to_string() + systemd_path)?
|
||||
.join("-");
|
||||
Ok(systemd_version)
|
||||
}
|
||||
|
||||
fn get_version(&self) -> Result<(String, String), Box<dyn Error>> {
|
||||
let old_module_root_path = self.get_nix_store_path(true)?;
|
||||
let new_module_root_path = self.get_nix_store_path(false)?;
|
||||
|
||||
let old_module_version: String;
|
||||
let new_module_version: String;
|
||||
|
||||
match self {
|
||||
Self::LinuxKernel => {
|
||||
let linux_path = old_module_root_path + "/lib/modules";
|
||||
old_module_version = Self::get_linux_version(&linux_path)?;
|
||||
new_module_version = Self::get_linux_version(&linux_path)?;
|
||||
}
|
||||
Self::Systemd => {
|
||||
old_module_version = Self::get_systemd_version(&old_module_root_path)?;
|
||||
new_module_version = Self::get_systemd_version(&new_module_root_path)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok((old_module_version, new_module_version))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn upgrades_available() -> Result<bool, Box<dyn Error>> {
|
||||
let mut needs_reboot = false;
|
||||
'x: for module in ModuleType::iter() {
|
||||
let (mut old_module_version, mut new_module_version) = module.get_version()?;
|
||||
|
||||
if old_module_version != new_module_version {
|
||||
if old_module_version.len() != new_module_version.len() {
|
||||
if old_module_version.contains("-rc") && !new_module_version.contains("-rc") {
|
||||
old_module_version = old_module_version.replace("-rc", ".");
|
||||
new_module_version.push_str(".0");
|
||||
} else if new_module_version.contains("-rc") && !old_module_version.contains("-rc")
|
||||
{
|
||||
new_module_version = new_module_version.replace("-rc", ".");
|
||||
old_module_version.push_str(".0");
|
||||
} else if new_module_version.contains("-rc") && old_module_version.contains("-rc") {
|
||||
new_module_version = new_module_version.replace("-rc", ".");
|
||||
old_module_version = old_module_version.replace("-rc", ".");
|
||||
}
|
||||
}
|
||||
|
||||
let old_version = &old_module_version.split('.').collect::<Vec<&str>>();
|
||||
let new_version = &new_module_version.split('.').collect::<Vec<&str>>();
|
||||
|
||||
for (old, new) in old_version.iter().zip(new_version.iter()) {
|
||||
if new > old {
|
||||
eprintln!("DEBUG: needs upgrading for module '{module}'");
|
||||
needs_reboot = true;
|
||||
break 'x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(needs_reboot)
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
use std::error::Error;
|
||||
use std::fs;
|
||||
|
||||
mod compare_nixos_modules;
|
||||
|
||||
pub static OLD_SYSTEM_PATH: &str = "/run/booted-system";
|
||||
pub static NEW_SYSTEM_PATH: &str = "/nix/var/nix/profiles/system";
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
if std::path::Path::new("/nix/var/nix/profiles/system").exists() {
|
||||
let old_system_id = fs::read_to_string(OLD_SYSTEM_PATH.to_string() + "/nixos-version")?;
|
||||
let new_system_id = fs::read_to_string(NEW_SYSTEM_PATH.to_string() + "/nixos-version")?;
|
||||
|
||||
if old_system_id == new_system_id {
|
||||
eprintln!("DEBUG: you are using the latest NixOS generation, no need to reboot");
|
||||
} else if compare_nixos_modules::upgrades_available()? {
|
||||
fs::File::create("/var/run/reboot-required")?;
|
||||
} else {
|
||||
eprintln!("DEBUG: no updates available, moar uptime!!!");
|
||||
}
|
||||
} else {
|
||||
eprintln!("This binary is intedned to run only on NixOS.");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue