diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d05a280 --- /dev/null +++ b/.gitignore @@ -0,0 +1,112 @@ +# Allrounder .gitignore +# +# General +# +# backup, tmp files +# + +*~ +*.swp +*.swo +*.bak +*.tmp +*.log + +# +# systemfiles +# + +.DS_Store +Thumbs.db +ehthumbs.db +desktop.ini + +# +# build files /object files +# +# C/C++ / Java / Go / Rust +# + +*.o +*.obj +*.so +*.a +*.dll +*.exe +*.out +*.class +*.jar + +# +# build direcotries +# + +/build/ +/bin/ +/dist/ +/target/ +/out/ + +# +# packagemanager +# +# Python + +__pycache__/ +*.py[cod] +*.egg-info/ +*.egg +*.whl + +# +# Node / JavaScript +# + +node_modules/ +npm-debug.log +yarn-error.log +pnpm-lock.yaml + +# +# Ruby +# + +*.gem +.bundle/ + +# +# Java +# + +*.war +*.ear + +# +# Rust +# + +Cargo.lock +target/ + +# +# IDEs / Editor +# + +.vscode/ +.idea/ +*.iml +*.sublime-workspace +*.sublime-project + +# +# Logs / Runtime +# + +*.log +*.pid +*.seed +*.pid.lock + + +archiv/ +src/archiv/ diff --git a/src/boot/grub/setup-grub.sh b/src/boot/grub/setup-grub.sh new file mode 100644 index 0000000..ba81563 --- /dev/null +++ b/src/boot/grub/setup-grub.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# setup-grub.sh TODO: in C +set -e + +BOOT=/boot +IMG=/system.img + +KERNEL=$(ls $BOOT/vmlinuz-* | sort | tail -1) +INITRD=$(ls $BOOT/initrd.img-* | sort | tail -1) + +cat > /etc/grub.d/40_atlantis <= MAX_PACKAGES) + { + return; + } + + if (!package_exists(name)) + { + packages[package_count++] = strdup(name); + } +} + +/** +* @brief Parse .conf file +*/ +void parse_conf(const char *path) +{ + FILE *f = fopen(path, "r"); + if (!f) + { + perror(path); + return; + } + + char line[MAX_LINE]; + while (fgets(line, sizeof(line), f)) + { + char *p = trim_and_clean(line); + if (*p == 0 || *p == '#') + { + continue; + } + + add_package(p); + } + + fclose(f); +} + +/** +* @brief Write package list for chroot +*/ +void write_package_list(const char *path) +{ + FILE *f = fopen(path, "w"); + if (!f) + { + perror(path); + exit(1); + } + + for (int i = 0; i < package_count; i++) + { + fprintf(f, "%s ", packages[i]); + } + + fprintf(f, "\n"); + fclose(f); +} + + +/** +* Versionsvergleich ähnlich zu `sort -V` +* (nutzt strverscmp, GNU libc) +*/ +static int kernel_version_cmp(const void *a, const void *b) +{ + const char *ka = *(const char **)a; + const char *kb = *(const char **)b; + return strverscmp(ka, kb); +} + +/** +* Versionsvergleich ähnlich zu `sort -V` +* (nutzt strverscmp, GNU libc) +*/ +static int initrd_version_cmp(const void *a, const void *b) +{ + const char *ia = *(const char **)a; + const char *ib = *(const char **)b; + return strverscmp(ia, ib); +} + +/** +* Prüft, ob der Dateiname gültig ist: +* - beginnt mit "vmlinuz-" +* - enthält nicht "old" +*/ +static int is_valid_kernel_initrd(const char *name) +{ + if (fnmatch("vmlinuz-*", name, 0) != 0) + { + return 0; + } + + else if (fnmatch("initrd.img-*", name, 0) != 0) + { + return 0; + } + + if (strstr(name, "old") != NULL) + { + return 0; + } + + return 1; +} + +/** +* Ermittelt passende initrd-Datei zu einem Kernel +* Rückgabe: neu allokierter String oder NULL +*/ +static char *find_initrd(const char *kernel) +{ + const char *version = kernel + strlen("vmlinuz-"); + char path[512]; + + /* bevorzugt: initrd.img- */ + snprintf(path, sizeof(path), "initrd.img-%s", version); + if (access(path, R_OK) == 0) + { + return strdup(path); + } + + /* Fallback: initrd- */ + snprintf(path, sizeof(path), "initrd-%s", version); + if (access(path, R_OK) == 0) + { + return strdup(path); + } + return NULL; +} + +/** +* +*/ +int set_new_boot_files() +{ + DIR *dir; + struct dirent *entry; + + char **kernels = NULL; + size_t count = 0, capacity = 0; + + dir = opendir("."); + if (!dir) + { + perror("opendir"); + return EXIT_FAILURE; + } + + /* 1. Kernel sammeln */ + while ((entry = readdir(dir)) != NULL) + { + if (!is_valid_kernel(entry->d_name)) + { + continue; + } + + if (count == capacity) + { + capacity = capacity ? capacity * 2 : 8; + char **tmp = realloc(kernels, capacity * sizeof(char *)); + if (!tmp) + { + perror("realloc"); + closedir(dir); + return EXIT_FAILURE; + } + kernels = tmp; + } + + kernels[count] = strdup(entry->d_name); + if (!kernels[count]) + { + perror("strdup"); + closedir(dir); + return EXIT_FAILURE; + } + + count++; + } + closedir(dir); + + if (count == 0) + { + fprintf(stderr, "Fehler: Keine Kernel-Dateien (vmlinuz-*) gefunden!\n"); + return EXIT_FAILURE; + } + + /* 2. Sortieren */ + qsort(kernels, count, sizeof(char *), kernel_version_cmp); + + /* 3. Latest & Previous */ + const char *latest_kernel = kernels[count - 1]; + const char *previous_kernel = (count >= 2) ? kernels[count - 2] : NULL; + + char *latest_initrd = find_initrd(latest_kernel); + char *previous_initrd = previous_kernel ? find_initrd(previous_kernel) : NULL; + + /* 4. Ausgabe */ + printf("Neuester Kernel:\n"); + printf(" Kernel : %s\n", latest_kernel); + printf(" Initrd : %s\n", latest_initrd ? latest_initrd : "(nicht gefunden)"); + + char cmd[1024]; + + snprintf(cmd, sizeof(cmd), "ln -sf %s vmlinuz", latest_kernel); + if (!run_command_bool(cmd)) + { + fprintf(stderr, "Command failed\n"); + exit(1); + } + + snprintf(cmd, sizeof(cmd), "ln -sf %s initrd.img", latest_initrd); + if (!run_command_bool(cmd)) + { + fprintf(stderr, "Command failed\n"); + exit(1); + } + + if (previous_kernel) + { + printf("\nVorheriger Kernel:\n"); + printf(" Kernel : %s\n", previous_kernel); + printf(" Initrd : %s\n", previous_initrd ? previous_initrd : "(nicht gefunden)"); + + snprintf(cmd, sizeof(cmd), "ln -sf %s vmlinuz.old", latest_kernel); + if (!run_command_bool(cmd)) + { + fprintf(stderr, "Command failed\n"); + exit(1); + } + + snprintf(cmd, sizeof(cmd), "ln -sf %s initrd.img.old", latest_initrd); + if (!run_command_bool(cmd)) + { + fprintf(stderr, "Command failed\n"); + exit(1); + } + } + + /* 5. Cleanup */ + free(latest_initrd); + free(previous_initrd); + + for (size_t i = 0; i < count; i++) + { + free(kernels[i]); + } + free(kernels); + + return EXIT_SUCCESS; +} + +/** +* @brief Function to copy vmlinuz/initrd to /boot and set this as active kernel +*/ +bool copy_boot(const char *work_dir) +{ + // prepare directories + char rootfs[512]; + snprintf(rootfs, sizeof(rootfs), "%s/rootfs", workdir); + + char cmd[1024]; + // TODO: set the active vmlinuz/initrd + // TODO: remove old vmlinuz/initrd → atl_boot + // TODO: Kernel config kopieren + // TODO: kernel/initrd von aus externen images holen (vmlinuz+initrd+config liegen in einem zip/tar/xz archiv) + // TODO: überlegen wie das mit a/b kerneln geregelt werden soll → mehr als zwei kernel ? nur zwei kernel + + // TODO: überlegung ob kernel/initrd als UKI kommen und dann von systemdboot gestartet werden (nachträglich veränderbar über upgrade) + + // copy vmlinuz-* to vmlinuz-* + snprintf(cmd, sizeof(cmd), "cp $(ls -v %s/boot/vmlinuz-* | tail -n 1) /boot/", rootfs); + if (!run_command_bool(cmd)) + { + fprintf(stderr, "Command failed\n"); + exit(1); + } + + // copy initrd.img-* to initrd.img-* + snprintf(cmd, sizeof(cmd), "cp $(ls -v %s/boot/initrd.img-* | tail -n 1) /boot/", rootfs); + if (!run_command_bool(cmd)) + { + fprintf(stderr, "Command failed\n"); + exit(1); + } + + // copy config-* to config-* + snprintf(cmd, sizeof(cmd), "cp $(ls -v %s/boot/config-* | tail -n 1) /boot/", rootfs); + if (!run_command_bool(cmd)) + { + fprintf(stderr, "Command failed\n"); + exit(1); + } + + if (set_new_boot_files() == 0) + { + + } + else + { + fprintf(stderr, "Failed to set new boot files\n"); + exit(1); + } + + // remove the /boot directory in the system.img + snprintf(cmd, sizeof(cmd), "rm -rf %s/boot", rootfs); + if (!run_command_bool(cmd)) + { + fprintf(stderr, "Command failed\n"); + exit(1); + } +} + +bool copy_boot_ + + +/** +* @brief Function that build the main system.img +* @param release: Release branch for Ubuntu +* @param work_dir: Directory for creating the image +* @param config: Main config file for the system.img +* @param config_count: Count for other config files +* @param config_files: List of all other config files +* @return success +*/ +bool image_build(const char *release, const char *work_dir, const char *config, int config_count, char *config_files[]) +{ + // prepare directories + char rootfs[512]; + snprintf(rootfs, sizeof(rootfs), "%s/rootfs", workdir); + + // parse all conf files + for (int i = 0; i < config_count; i++) + { + parse_conf(config_files[i]); + } + + printf("Collected %d unique packages\n", pkg_count); + + char cmd[1024]; + + // Bootstrap Ubuntu + snprintf(cmd, sizeof(cmd), "debootstrap --variant=minbase %s %s http://archive.ubuntu.com/ubuntu", release, rootfs); + if (!run_command_bool(cmd)) + { + fprintf(stderr, "Command failed\n"); + exit(1); + } + + // write package list + snprintf(cmd, sizeof(cmd), "%s/packages.list", workdir); + write_pkg_list(cmd); + + // Copy list into rootfs + snprintf(cmd, sizeof(cmd), "cp %s/packages.list %s/root/packages.list", workdir, rootfs); + if (!run_command_bool(cmd)) + { + fprintf(stderr, "Command failed\n"); + exit(1); + } + + // install packages from package list + snprintf(cmd, sizeof(cmd), "chroot %s /bin/bash -c \"apt update && xargs -a /root/packages.list apt install -y --no-install-recommends\"", rootfs); + if (!run_command_bool(cmd)) + { + fprintf(stderr, "Command failed\n"); + exit(1); + } + + // clean up + snprintf(cmd, sizeof(cmd), "chroot %s apt clean", rootfs); + if (!run_command_bool(cmd)) + { + fprintf(stderr, "Command failed\n"); + exit(1); + } + + // copy vmlinuz/initrd to /boot + copy_boot(work_dir); + + + /* SquashFS */ + snprintf(cmd, sizeof(cmd), "mksquashfs %s %s/system.img -comp xz -b 1M -noappend", rootfs, workdir); + if (!run_command_bool(cmd)) + { + fprintf(stderr, "Command failed\n"); + exit(1); + } + + + printf("Image created: %s/system.img\n", workdir); + return true; +} diff --git a/src/include/atl.h b/src/include/atl.h new file mode 100644 index 0000000..25ca391 --- /dev/null +++ b/src/include/atl.h @@ -0,0 +1,30 @@ +/** +* atl.h +* +* (C) Copyright 2025 AtlantisOS Project +* by @NachtsternBuild +* +* License: GNU GENERAL PUBLIC LICENSE Version 3 +* +* Usage: +* #include "atl.h" +*/ + +#ifndef ATL_H +#define ATL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "helper.h" +#include +#include + + +#ifdef __cplusplus +} +#endif + +#endif // ATL_H +