From d0d239e0ca16228a818b7bbf5ef69952433a5546 Mon Sep 17 00:00:00 2001 From: Cametendo Date: Wed, 22 Apr 2026 22:12:33 +0200 Subject: [PATCH] Added tab-completion and cli-arguments --- pom.xml | 27 +++++++ src/main/java/org/cametendo/BlockSize.java | 44 +++++------ src/main/java/org/cametendo/Dd.java | 1 + src/main/java/org/cametendo/FilePathAdd.java | 49 +++++++++--- src/main/java/org/cametendo/Flasher.java | 7 +- src/main/java/org/cametendo/Greeting.java | 7 +- src/main/java/org/cametendo/Main.java | 39 ++++++---- src/main/java/org/cametendo/OSDetector.java | 76 +++++++++++++++++++ src/main/java/org/cametendo/OflagHandler.java | 43 +++++------ .../org/cametendo/StorageDeviceLister.java | 15 ++-- 10 files changed, 223 insertions(+), 85 deletions(-) create mode 100644 src/main/java/org/cametendo/OSDetector.java diff --git a/pom.xml b/pom.xml index 7b44b1d..c9acbc1 100644 --- a/pom.xml +++ b/pom.xml @@ -22,4 +22,31 @@ + + + + maven-assembly-plugin + 3.6.0 + + + + org.cametendo.Main + + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + \ No newline at end of file diff --git a/src/main/java/org/cametendo/BlockSize.java b/src/main/java/org/cametendo/BlockSize.java index 2031443..ccc4d2c 100644 --- a/src/main/java/org/cametendo/BlockSize.java +++ b/src/main/java/org/cametendo/BlockSize.java @@ -3,37 +3,29 @@ import java.util.Scanner; public class BlockSize { - public static String blockSizeString = ""; + public static String blockSizeString = "4M"; + + public static String mapBlockSize(String input) { + return switch (input) { + case "1" -> "512K"; + case "2" -> "1M"; + case "3" -> "2M"; + case "4" -> "4M"; + case "5" -> "8M"; + case "6" -> "16M"; + default -> blockSizeString; + }; + } static String blockSize(Scanner UserInput) { System.out.println("Choose a block size (Default: 4M)"); System.out.println("512KB (1), 1M (2), 2M (3), 4M (4), 8M (5), 16M (6)"); - String blockSizeInput = UserInput.nextLine(); + + String input = UserInput.nextLine(); - switch (blockSizeInput) { - case "1": - blockSizeString = "512KB"; - break; - case "2": - blockSizeString = "1M"; - break; - case "3": - blockSizeString = "2M"; - break; - case "4": - blockSizeString = "4M"; - break; - case "5": - blockSizeString = "8M"; - break; - case "6": - blockSizeString = "16M"; - break; - default: - blockSizeString = "4M"; - break; - } + blockSizeString = mapBlockSize(input); + System.out.println("Using blocksize of: " + blockSizeString); return blockSizeString; } -} +} \ No newline at end of file diff --git a/src/main/java/org/cametendo/Dd.java b/src/main/java/org/cametendo/Dd.java index 2a316c6..ec916bd 100644 --- a/src/main/java/org/cametendo/Dd.java +++ b/src/main/java/org/cametendo/Dd.java @@ -20,6 +20,7 @@ public class Dd { System.out.print(c); System.out.flush(); } + OSDetector.wishWell(FilePathAdd.ImagePath); } catch (IOException e) { e.printStackTrace(); } diff --git a/src/main/java/org/cametendo/FilePathAdd.java b/src/main/java/org/cametendo/FilePathAdd.java index 35383cb..251e7eb 100644 --- a/src/main/java/org/cametendo/FilePathAdd.java +++ b/src/main/java/org/cametendo/FilePathAdd.java @@ -2,32 +2,59 @@ package org.cametendo; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Scanner; + +import org.jline.reader.LineReader; +import org.jline.reader.LineReaderBuilder; +import org.jline.reader.impl.completer.FileNameCompleter; +import org.jline.terminal.Terminal; +import org.jline.terminal.TerminalBuilder; public class FilePathAdd { public static String ImagePath = ""; - protected static String filePath(Scanner UserInput) { + protected static String filePath() throws IOException { fileQuestion(); + + Terminal terminal = TerminalBuilder.terminal(); + LineReader reader = LineReaderBuilder.builder().terminal(terminal).completer(new FileNameCompleter()).build(); + while (true) { - ImagePath = UserInput.nextLine(); + ImagePath = reader.readLine("Path: ").trim(); + if (ImagePath.isBlank()) { - System.out.println("Oops.. You didn't specify a file, did you missclick?"); + System.out.println("Oops... You didn't specify a file!"); continue; } + Path path = Path.of(ImagePath); - try { - Files.readAttributes(path, "basic:size"); - System.out.println("Using File: " + ImagePath); - return ImagePath; - } catch (IOException e) { - System.out.println("Failed to access file, invalid path or no access to file! Please try again."); + + if (!Files.exists(path) || !Files.isRegularFile(path)) { + System.out.println("Invalid file! Please ensure the path points to an ISO / image file."); + continue; } + + System.out.println("Using File: " + ImagePath); + return ImagePath; + } + } + + public static String validateAndGetFile(String ImagePath) { + try { + Path path = Path.of(ImagePath); + if (Files.exists(path) && Files.isRegularFile(path)) { + return path.toRealPath().toString(); + } else { + System.out.println("Invalid file! Please ensure the path points to an ISO / image file."); + return null; + } + } catch (IOException e) { + System.out.println("File not found! Invalid Path or no access."); + return null; } } protected static void fileQuestion() { - System.out.println("Please enter the FULL Path of your ISO / Image. (No tab-complete)"); + System.out.println("Please enter the FULL Path of your ISO / Image. (Tab-completion supported)"); } } diff --git a/src/main/java/org/cametendo/Flasher.java b/src/main/java/org/cametendo/Flasher.java index 1544207..05882b4 100644 --- a/src/main/java/org/cametendo/Flasher.java +++ b/src/main/java/org/cametendo/Flasher.java @@ -6,10 +6,10 @@ public class Flasher { String input = ""; - System.out.println("The programm wil use the following configuration, do you want to flash with this? (Y/n)"); + System.out.println("The program will use the following configuration, do you want to flash with this? (Y/n)"); System.out.println(" - To be flashed device: " + StorageDeviceLister.fullPath); System.out.println(" - To be used path: " + FilePathAdd.ImagePath); - System.out.println(" - To bed used blocksize: " + BlockSize.blockSizeString); + System.out.println(" - To be used blocksize: " + BlockSize.blockSizeString); System.out.println(" - To be used oflag: " + OflagHandler.oflagHandleString); input = UserInput.nextLine(); if (YesNo.check(input)) { @@ -19,6 +19,5 @@ public class Flasher { System.exit(0); } Dd.dd(); - System.out.println("Flash completed."); } -} +} \ No newline at end of file diff --git a/src/main/java/org/cametendo/Greeting.java b/src/main/java/org/cametendo/Greeting.java index 6ff6f5d..5a8f528 100644 --- a/src/main/java/org/cametendo/Greeting.java +++ b/src/main/java/org/cametendo/Greeting.java @@ -1,7 +1,12 @@ package org.cametendo; + +import java.util.Scanner; + public class Greeting { - public static void greeting() { + public static void greeting(Scanner UserInput) { System.out.println("Welcome to cflash!"); System.out.println("Would you like to flash an image (Y/n)"); + UserInput.nextLine(); + } } diff --git a/src/main/java/org/cametendo/Main.java b/src/main/java/org/cametendo/Main.java index f50d735..1cfff3b 100644 --- a/src/main/java/org/cametendo/Main.java +++ b/src/main/java/org/cametendo/Main.java @@ -1,25 +1,34 @@ package org.cametendo; +import java.io.IOException; import java.util.Scanner; public class Main { - public static void main(String[] args) throws InterruptedException { + public static void main(String[] args) throws InterruptedException, IOException { Scanner UserInput = new Scanner(System.in); - - Greeting.greeting(); - String input = UserInput.nextLine(); - - if (YesNo.check(input)) { - System.out.println("Please choose the to be flashed device (f. e. sda)"); - } else { - System.out.println("Canceling..."); - System.exit(0); + if (args.length == 4) { + String validatedDevice = StorageDeviceLister.validateAndGetPath(args[0]); + if (validatedDevice == null) { + return; } - StorageDeviceLister.deviceCheck(UserInput); - FilePathAdd.filePath(UserInput); - BlockSize.blockSize(UserInput); - OflagHandler.handleOflag(UserInput); - Flasher.flasher(UserInput); + String validatedFile = FilePathAdd.validateAndGetFile(args[1]); + if (validatedFile == null) { + return; + } + StorageDeviceLister.fullPath = validatedDevice; + FilePathAdd.ImagePath = validatedFile; + BlockSize.blockSizeString = BlockSize.mapBlockSize(args[2]); + OflagHandler.oflagHandleString = OflagHandler.mapOflagHandle(args[3]); + + } else { + Greeting.greeting(UserInput); + + StorageDeviceLister.deviceCheck(UserInput); + FilePathAdd.filePath(); + BlockSize.blockSize(UserInput); + OflagHandler.Oflag(UserInput); + } + Flasher.flasher(UserInput); } } diff --git a/src/main/java/org/cametendo/OSDetector.java b/src/main/java/org/cametendo/OSDetector.java new file mode 100644 index 0000000..2f6ec60 --- /dev/null +++ b/src/main/java/org/cametendo/OSDetector.java @@ -0,0 +1,76 @@ +package org.cametendo; +import java.nio.file.Path; + +public class OSDetector { + + public static void wishWell(String imagePath) { + String fileName = Path.of(imagePath).getFileName().toString().toLowerCase(); + + String osName; + + // Specialized & Advanced Distros + if (fileName.contains("nyarch")) { + osName = "Nyarch Linux (Nyaa~!)"; + } else if (fileName.contains("artix")) { + osName = "Artix Linux (Systemd-free Arch!)"; + } else if (fileName.contains("gentoo")) { + osName = "Gentoo (Enjoy the compiling...)"; + } else if (fileName.contains("nixos")) { + osName = "NixOS (Immutable & Reproducible!)"; + } else if (fileName.contains("void")) { + osName = "Void Linux"; + } else if (fileName.contains("arch")) { + osName = "Arch Linux (btw)"; + } else if (fileName.contains("alpine")) { + osName = "Alpine Linux (Minimalism at its peak)"; + } else if (fileName.contains("winux")) { + osName = "Winux (Windows without Windows)"; + } + // Mainstream Linux + else if (fileName.contains("fedora")) { + osName = "Fedora (Freehat Linux)"; + } else if (fileName.contains("debian")) { + osName = "Debian (Universal OS)"; + } else if (fileName.contains("ubuntu")) { + osName = "Ubuntu (Debian but fancy)"; + } else if (fileName.contains("mint")) { + osName = "Linux Mint"; + } else if (fileName.contains("pop-os") || fileName.contains("pop_os")) { + osName = "Pop!_OS"; + } + // The BSD Family + else if (fileName.contains("freebsd")) { + osName = "FreeBSD"; + } else if (fileName.contains("openbsd")) { + osName = "OpenBSD (Secure by default)"; + } else if (fileName.contains("netbsd")) { + osName = "NetBSD (It runs on everything!)"; + } + // Security & Privacy + else if (fileName.contains("kali")) { + osName = "Kali Linux (Happy Hacking)"; + } else if (fileName.contains("tails")) { + osName = "Tails (Incognito mode: ON)"; + } else if (fileName.contains("qubes")) { + osName = "Qubes OS (Security by Compartmentalization)"; + } + // Others & Legacy + else if (fileName.contains("win") && (fileName.contains("10") || fileName.contains("11"))) { + osName = "Windows (Spies... Spies everywhere)"; + } else if (fileName.contains("haiku")) { + osName = "Haiku OS"; + } else if (fileName.contains("reactos")) { + osName = "ReactOS"; + } + // Generic Fallbacks + else if (fileName.contains("linux")) { + osName = "Linux"; + } else if (fileName.contains("bsd")) { + osName = "BSD"; + } else { + osName = "new OS"; + } + + System.out.println("\nFlash complete! Have fun with your " + osName + " installation! 🚀"); + } +} \ No newline at end of file diff --git a/src/main/java/org/cametendo/OflagHandler.java b/src/main/java/org/cametendo/OflagHandler.java index ff533bd..7b28e29 100644 --- a/src/main/java/org/cametendo/OflagHandler.java +++ b/src/main/java/org/cametendo/OflagHandler.java @@ -3,31 +3,28 @@ import java.util.Scanner; public class OflagHandler { - public static String oflagHandleString = ""; + public static String oflagHandleString = "direct"; - static String handleOflag(Scanner UserInput) { - System.out.println("Okay, next up please define your oflag (Default: direct)"); - System.out.println("Available flags: direct (1), dsync (2), sync (3), nocache (4)"); - String oflagHandleInput = UserInput.nextLine(); + public static String mapOflagHandle(String input) { + return switch (input) { + case "1" -> "direct"; + case "2" -> "dsync"; + case "3" -> "sync"; + case "4" -> "nocache"; + case "5" -> "direct"; + default -> oflagHandleString; + }; + } + + static String Oflag(Scanner UserInput) { + System.out.println("Choose an Oflag (Default: direct)"); + System.out.println("direct (1), dsync (2), sync (3), nocache (4)"); + + String input = UserInput.nextLine(); - switch (oflagHandleInput) { - case "1": - oflagHandleString = "direct"; - break; - case "2": - oflagHandleString = "dsync"; - break; - case "3": - oflagHandleString = "sync"; - break; - case "4": - oflagHandleString = "nocache"; - break; - default: - oflagHandleString = "direct"; - break; - } - System.out.println("Using oflag: " + oflagHandleString); + oflagHandleString = mapOflagHandle(input); + + System.out.println("Using Oflag: " + oflagHandleString); return oflagHandleString; } } diff --git a/src/main/java/org/cametendo/StorageDeviceLister.java b/src/main/java/org/cametendo/StorageDeviceLister.java index d18c6b9..cdc2be3 100644 --- a/src/main/java/org/cametendo/StorageDeviceLister.java +++ b/src/main/java/org/cametendo/StorageDeviceLister.java @@ -11,10 +11,8 @@ public class StorageDeviceLister { public static String fullPath = ""; protected static String deviceCheck(Scanner UserInput) { - // 1. lsblk wird genau EINMAL aufgerufen deviceList(); - // 2. Die Abfrage-Schleife while (true) { device = UserInput.nextLine(); if (device.isBlank()) { @@ -24,20 +22,27 @@ public class StorageDeviceLister { Path path = Path.of("/dev/" + device); try { - // Versuche, den echten Pfad zu finden fullPath = path.toRealPath().toString(); - // Wenn wir hier ankommen, war der Pfad gültig System.out.println("Using device: " + fullPath); return fullPath; } catch (IOException e) { - // Fehler-Output, danach springt die Schleife wieder nach oben System.out.println("Failed to access device! Invalid path or no access. Please try again."); } } } + public static String validateAndGetPath(String deviceName) { + try { + Path path = Path.of("/dev/" + deviceName); + return path.toRealPath().toString(); + } catch (IOException e) { + System.out.println("Device not found. Invalid Path or no access."); + return null; + } + } + private static void deviceList() { try { ProcessBuilder pb = new ProcessBuilder("lsblk");