diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 72a671f..e38b1d1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,6 +38,7 @@ jobs: cd ${{github.workspace}}/build ./gucc/tests/test-initcpio ./gucc/tests/test-pacmanconf + ./gucc/tests/test-mtab ./gucc/tests/test-fstab_gen ./gucc/tests/test-crypttab_gen ./gucc/tests/test-grub_config_gen @@ -85,6 +86,7 @@ jobs: cd ${{github.workspace}}/build ./gucc/tests/test-initcpio ./gucc/tests/test-pacmanconf + ./gucc/tests/test-mtab ./gucc/tests/test-fstab_gen ./gucc/tests/test-crypttab_gen ./gucc/tests/test-grub_config_gen diff --git a/gucc/CMakeLists.txt b/gucc/CMakeLists.txt index 1114d14..eec883c 100644 --- a/gucc/CMakeLists.txt +++ b/gucc/CMakeLists.txt @@ -27,6 +27,7 @@ add_library(${PROJECT_NAME} SHARED src/bootloader.cpp include/gucc/bootloader.hpp src/systemd_services.cpp include/gucc/systemd_services.hpp src/autologin.cpp include/gucc/autologin.hpp + src/mtab.cpp include/gucc/mtab.hpp #src/chwd_profiles.cpp src/chwd_profiles.hpp #src/disk.cpp src/disk.hpp ) diff --git a/gucc/include/gucc/mtab.hpp b/gucc/include/gucc/mtab.hpp new file mode 100644 index 0000000..80a8cb2 --- /dev/null +++ b/gucc/include/gucc/mtab.hpp @@ -0,0 +1,24 @@ +#ifndef MTAB_HPP +#define MTAB_HPP + +#include // for optional +#include // for string +#include // for string_view +#include // for vector + +namespace gucc::mtab { + +struct MTabEntry { + std::string device{}; + std::string mountpoint{}; +}; + +// Parse mtab +auto parse_mtab(std::string_view root_mountpoint) noexcept -> std::optional>; + +// Parse mtab content +auto parse_mtab_content(std::string_view mtab_content, std::string_view root_mountpoint) noexcept -> std::vector; + +} // namespace gucc::mtab + +#endif // MTAB_HPP diff --git a/gucc/meson.build b/gucc/meson.build index 6a7f7ec..7eb1847 100644 --- a/gucc/meson.build +++ b/gucc/meson.build @@ -17,6 +17,7 @@ gucc_lib = library('gucc', 'src/bootloader.cpp', 'src/systemd_services.cpp', 'src/autologin.cpp', + 'src/mtab.cpp', ], include_directories : [include_directories('include')], dependencies: deps diff --git a/gucc/src/mtab.cpp b/gucc/src/mtab.cpp new file mode 100644 index 0000000..c16821f --- /dev/null +++ b/gucc/src/mtab.cpp @@ -0,0 +1,40 @@ +#include "gucc/mtab.hpp" +#include "gucc/file_utils.hpp" +#include "gucc/string_utils.hpp" + +using namespace std::string_view_literals; + +namespace gucc::mtab { + +auto parse_mtab_content(std::string_view mtab_content, std::string_view root_mountpoint) noexcept -> std::vector { + std::vector entries{}; + + auto&& file_content_lines = utils::make_split_view(mtab_content); + for (auto&& line : file_content_lines) { + if (line.empty() || line.starts_with('#')) { + continue; + } + + auto&& line_split = utils::make_split_view(line, ' '); + auto&& device = *utils::index_viewable_range(line_split, 0); + if (utils::size_viewable_range(line_split) >= 3 && !device.starts_with('#')) { + // e.g format: + auto&& mountpoint = *utils::index_viewable_range(line_split, 1); + if (mountpoint.starts_with(root_mountpoint)) { + entries.emplace_back(MTabEntry{.device = std::string{device}, .mountpoint = std::string{mountpoint}}); + } + } + } + return entries; +} + +auto parse_mtab(std::string_view root_mountpoint) noexcept -> std::optional> { + static constexpr auto mtab_path = "/etc/mtab"sv; + auto&& file_content = file_utils::read_whole_file(mtab_path); + if (file_content.empty()) { + return std::nullopt; + } + return mtab::parse_mtab_content(file_content, root_mountpoint); +} + +} // namespace gucc::mtab diff --git a/gucc/tests/meson.build b/gucc/tests/meson.build index ebf4adb..316037c 100644 --- a/gucc/tests/meson.build +++ b/gucc/tests/meson.build @@ -37,3 +37,11 @@ executable( link_with: [gucc_lib], include_directories: [include_directories('../include')], install: false) + +executable( + 'test-mtab', + files('unit-mtab.cpp'), + dependencies: deps, + link_with: [gucc_lib], + include_directories: [include_directories('../include')], + install: false) diff --git a/gucc/tests/unit-mtab.cpp b/gucc/tests/unit-mtab.cpp new file mode 100644 index 0000000..ad3b838 --- /dev/null +++ b/gucc/tests/unit-mtab.cpp @@ -0,0 +1,60 @@ +#include "gucc/mtab.hpp" + +#include + +#include + +using namespace std::string_view_literals; + +static constexpr auto MTAB_RUNNING_SYSTEM_TEST = R"( +proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0 + +sys /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0 +dev /dev devtmpfs rw,nosuid,relatime,size=8104116k,nr_inodes=2026029,mode=755,inode64 0 0 +run /run tmpfs rw,nosuid,nodev,relatime,mode=755,inode64 0 0 +efivarfs /sys/firmware/efi/efivars efivarfs rw,nosuid,nodev,noexec,relatime 0 0 +# test string +/dev/nvme0n1p3 /mnt btrfs rw,relatime,compress=zstd:3,ssd,discard=async,space_cache,subvolid=5,subvol=/ 0 0 +securityfs /sys/kernel/security securityfs rw,nosuid,nodev,noexec,relatime 0 0 +tmpfs /dev/shm tmpfs rw,nosuid,nodev,inode64 0 0 +devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0 +cgroup2 /sys/fs/cgroup cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot 0 0 + # test something +pstore /sys/fs/pstore pstore rw,nosuid,nodev,noexec,relatime 0 0 +bpf /sys/fs/bpf bpf rw,nosuid,nodev,noexec,relatime,mode=700 0 0 +systemd-1 /proc/sys/fs/binfmt_misc autofs rw,relatime,fd=39,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=4748 0 0 +debugfs /sys/kernel/debug debugfs rw,nosuid,nodev,noexec,relatime 0 0 +mqueue /dev/mqueue mqueue rw,nosuid,nodev,noexec,relatime 0 0 +hugetlbfs /dev/hugepages hugetlbfs rw,nosuid,nodev,relatime,pagesize=2M 0 0 +tracefs /sys/kernel/tracing tracefs rw,nosuid,nodev,noexec,relatime 0 0 +tmpfs /run/credentials/systemd-journald.service tmpfs ro,nosuid,nodev,noexec,relatime,nosymfollow,size=1024k,nr_inodes=1024,mode=700,inode64,noswap 0 0 +tmpfs /run/credentials/systemd-udev-load-credentials.service tmpfs ro,nosuid,nodev,noexec,relatime,nosymfollow,size=1024k,nr_inodes=1024,mode=700,inode64,noswap 0 0 +fusectl /sys/fs/fuse/connections fusectl rw,nosuid,nodev,noexec,relatime 0 0 +tmpfs /run/credentials/systemd-tmpfiles-setup-dev-early.service tmpfs ro,nosuid,nodev,noexec,relatime,nosymfollow,size=1024k,nr_inodes=1024,mode=700,inode64,noswap 0 0 +configfs /sys/kernel/config configfs rw,nosuid,nodev,noexec,relatime 0 0 +tmpfs /run/credentials/systemd-sysctl.service tmpfs ro,nosuid,nodev,noexec,relatime,nosymfollow,size=1024k,nr_inodes=1024,mode=700,inode64,noswap 0 0 +tmpfs /run/credentials/systemd-tmpfiles-setup-dev.service tmpfs ro,nosuid,nodev,noexec,relatime,nosymfollow,size=1024k,nr_inodes=1024,mode=700,inode64,noswap 0 0 +tmpfs /tmp tmpfs rw,nosuid,nodev,nr_inodes=1048576,inode64 0 0 +/dev/nvme0n1p1 /mnt/boot vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 0 +tmpfs /run/credentials/systemd-tmpfiles-setup.service tmpfs ro,nosuid,nodev,noexec,relatime,nosymfollow,size=1024k,nr_inodes=1024,mode=700,inode64,noswap 0 0 +binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc rw,nosuid,nodev,noexec,relatime 0 0 +tmpfs /run/credentials/systemd-vconsole-setup.service tmpfs ro,nosuid,nodev,noexec,relatime,nosymfollow,size=1024k,nr_inodes=1024,mode=700,inode64,noswap 0 0 +tmpfs /run/credentials/getty@tty1.service tmpfs ro,nosuid,nodev,noexec,relatime,nosymfollow,size=1024k,nr_inodes=1024,mode=700,inode64,noswap 0 0 +tmpfs /run/user/1000 tmpfs rw,nosuid,nodev,relatime,size=1632224k,nr_inodes=408056,mode=700,uid=1000,gid=984,inode64 0 0 +portal /run/user/1000/doc fuse.portal rw,nosuid,nodev,relatime,user_id=1000,group_id=984 0 0 +run /run/firejail/dbus tmpfs rw,nosuid,nodev,noexec,relatime,mode=755,inode64 0 0 +run /run/firejail/firejail.ro.dir tmpfs ro,nosuid,nodev,relatime,mode=755,inode64 0 0 +run /run/firejail/firejail.ro.file tmpfs ro,nosuid,nodev,relatime,mode=755,inode64 0 0 +)"sv; + +int main() { + // running system + { + const auto& mtab_entries = gucc::mtab::parse_mtab_content(MTAB_RUNNING_SYSTEM_TEST, "/mnt"sv); + assert(mtab_entries.size() == 2); + assert(mtab_entries[0].device == "/dev/nvme0n1p3"); + assert(mtab_entries[0].mountpoint == "/mnt"); + assert(mtab_entries[1].device == "/dev/nvme0n1p1"); + assert(mtab_entries[1].mountpoint == "/mnt/boot"); + } +}