diff --git a/src/main/java/org/cametendo/FilePathAdd.java b/src/main/java/org/cametendo/FilePathAdd.java index 3f70016..ad7a5b8 100644 --- a/src/main/java/org/cametendo/FilePathAdd.java +++ b/src/main/java/org/cametendo/FilePathAdd.java @@ -1,4 +1,5 @@ package org.cametendo; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -11,29 +12,31 @@ import org.jline.terminal.TerminalBuilder; /** * Handles file path input and validation for disk image files. - * - *

This class provides functionality to interactively prompt users for image file paths - * with tab completion support, validate that files exist and are regular files, and - * validate file paths from command-line arguments.

- * - * @author Cametendo - * @version 1.0 + * *

This class provides functionality to interactively prompt users for image file paths + * with tab completion support via JLine. It handles Unix-style tilde (~) expansion + * to the user's home directory and validates that paths point to existing regular files.

+ * * @author Cametendo + * @version 1.1 */ public class FilePathAdd { /** - * Stores the validated path to the selected image file. + * Stores the validated absolute path to the selected image file. */ public static String ImagePath = ""; + + /** + * Constant representing the current user's home directory path. + */ + public static final String Home = System.getProperty("user.home"); /** * Interactively prompts the user to select an image file path. - * - *

Uses JLine for enhanced terminal interaction with tab completion support. - * Validates that the selected path points to an existing regular file.

- * - * @return The validated path to the selected image file - * @throws IOException If there are I/O errors during terminal setup or file validation + * *

Uses JLine for enhanced terminal interaction with {@link FileNameCompleter}. + * The method expands the tilde (~) character if present at the start of the string + * and validates that the resulting path is a regular file before returning.

+ * * @return The validated absolute path to the selected image file + * @throws IOException If there are I/O errors during terminal setup or file resolution */ protected static String filePath() throws IOException { fileQuestion(); @@ -42,37 +45,48 @@ public class FilePathAdd { LineReader reader = LineReaderBuilder.builder().terminal(terminal).completer(new FileNameCompleter()).build(); while (true) { - ImagePath = reader.readLine("Path: ").trim(); + String input = reader.readLine("Path: ").trim(); - if (ImagePath.isBlank()) { + if (input.isBlank()) { System.out.println("Oops... You didn't specify a file!"); continue; } - Path path = Path.of(ImagePath); + // Expand tilde to the full home directory path + if (input.startsWith("~")) { + input = Home + input.substring(1); + } + + Path path = Path.of(input); if (!Files.exists(path) || !Files.isRegularFile(path)) { System.out.println("Invalid file! Please ensure the path points to an ISO / image file."); continue; } + // Convert to a real, absolute path and return + ImagePath = path.toRealPath().toString(); System.out.println("Using File: " + ImagePath); return ImagePath; } } /** - * Validates and returns the full path to an image file. - * - *

Takes a file path, validates that it exists and is a regular file, - * and returns the real path. Used for command-line argument validation.

- * - * @param ImagePath Path to the image file to validate - * @return Full validated path to the file, or null if invalid + * Validates and returns the full path to an image file from a provided string. + * *

This is primarily used for validating command-line arguments. It supports + * tilde expansion and verifies file existence and type.

+ * * @param inputPath Raw path string to validate + * @return Full validated absolute path, or {@code null} if the path is invalid or inaccessible */ - public static String validateAndGetFile(String ImagePath) { + public static String validateAndGetFile(String inputPath) { + if (inputPath == null) return null; + try { - Path path = Path.of(ImagePath); + if (inputPath.startsWith("~")) { + inputPath = Home + inputPath.substring(1); + } + + Path path = Path.of(inputPath); if (Files.exists(path) && Files.isRegularFile(path)) { return path.toRealPath().toString(); } else { @@ -86,12 +100,9 @@ public class FilePathAdd { } /** - * Displays the prompt for file path input. - * - *

Informs the user that they should enter the full path to their ISO/image file - * and mentions that tab completion is supported for convenience.

+ * Displays the prompt for file path input to the standard output. */ protected static void fileQuestion() { System.out.println("Please enter the FULL Path of your ISO / Image. (Tab-completion supported)"); } -} +} \ No newline at end of file diff --git a/src/main/java/org/cametendo/GetHome.java b/src/main/java/org/cametendo/GetHome.java new file mode 100644 index 0000000..09c0ba9 --- /dev/null +++ b/src/main/java/org/cametendo/GetHome.java @@ -0,0 +1 @@ + diff --git a/src/main/java/org/cametendo/Greeting.java b/src/main/java/org/cametendo/Greeting.java index dc29243..24f17d8 100644 --- a/src/main/java/org/cametendo/Greeting.java +++ b/src/main/java/org/cametendo/Greeting.java @@ -23,14 +23,5 @@ public class 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)"); - 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); - } - } } diff --git a/src/main/java/org/cametendo/OSDetector.java b/src/main/java/org/cametendo/OSDetector.java index ff9b0bc..9e9a845 100644 --- a/src/main/java/org/cametendo/OSDetector.java +++ b/src/main/java/org/cametendo/OSDetector.java @@ -80,7 +80,9 @@ public class OSDetector { osName = "Haiku OS"; } else if (fileName.contains("reactos")) { osName = "ReactOS"; - } + } else if (fileName.contains("jgh")) { + osName = "JGH OS (Sauerkraut juice)"; + } // Generic Fallbacks else if (fileName.contains("linux")) { osName = "Linux"; @@ -90,6 +92,6 @@ public class OSDetector { osName = "new OS"; } - System.out.println("\nFlash complete! Have fun with your " + osName + " installation! 🚀"); + 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/StorageDeviceLister.java b/src/main/java/org/cametendo/StorageDeviceLister.java index 49ec51c..b3b94d7 100644 --- a/src/main/java/org/cametendo/StorageDeviceLister.java +++ b/src/main/java/org/cametendo/StorageDeviceLister.java @@ -1,4 +1,5 @@ package org.cametendo; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -7,99 +8,127 @@ import java.util.Scanner; /** * Handles storage device detection, listing, and validation for the flashing process. - * - *

This class provides functionality to list available storage devices using lsblk, - * validate device paths, and interactively prompt users to select a target device - * for flashing operations.

- * - * @author Cametendo - * @version 1.0 + * *

Includes safety checks to ensure we don't nuke a partition that's currently in use. + * Keeps the user in the loop with a more personal touch.

+ * * @author Cametendo + * @version 1.1 */ public class StorageDeviceLister { - /** - * Stores the selected device name (without /dev/ prefix). - */ public static String device = ""; - - /** - * Stores the full validated path to the selected device. - */ public static String fullPath = ""; /** - * Interactively prompts the user to select a storage device. - * - *

Displays a list of available storage devices using the lsblk command, - * then prompts the user to enter a device name. Validates the device path - * and continues prompting until a valid device is selected.

- * - * @param UserInput Scanner object for reading user input - * @return The full validated path to the selected device + * Guides the user through selecting a safe, unmounted storage device. */ protected static String deviceCheck(Scanner UserInput) { deviceList(); while (true) { - device = UserInput.nextLine(); + System.out.print("Target device: "); + device = UserInput.nextLine().trim(); + if (device.isBlank()) { System.out.println("Oops... Device name is empty. Did you missclick?"); continue; } - Path path = Path.of("/dev/" + device); + + // Standardize path - allows entering 'sda' or '/dev/sda' + String checkPath = device.startsWith("/dev/") ? device : "/dev/" + device; + Path path = Path.of(checkPath); try { fullPath = path.toRealPath().toString(); + + // Check if the user is about to break their system + if (isMounted(fullPath)) { + System.out.println("Wait a second! " + fullPath + " is currently mounted."); + System.out.println("I can't flash to a device that's in use. Unmount it and try again!"); + continue; + } - System.out.println("Using device: " + fullPath); + System.out.println("Solid choice. Using device: " + fullPath); return fullPath; } catch (IOException e) { - System.out.println("Failed to access device! Invalid path or no access. Please try again."); + System.out.println("Hmm... I can't seem to find or access that device. Are you sure you have access to it?"); } } } /** - * Validates and returns the full path to a storage device. - * - *

Takes a device name (without /dev/ prefix), constructs the full path, - * and validates that the device exists and is accessible. Used for command-line - * argument validation.

- * - * @param deviceName Device name without /dev/ prefix (e.g., "sda") - * @return Full validated path to the device, or null if invalid + * Asks lsblk if the device or its children have an active mount point. */ - public static String validateAndGetPath(String deviceName) { + private static boolean isMounted(String devicePath) { 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; + ProcessBuilder pb = new ProcessBuilder("lsblk", "-no", "MOUNTPOINT", devicePath); + Process process = pb.start(); + + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + String line; + while ((line = reader.readLine()) != null) { + if (!line.trim().isEmpty()) { + return true; + } + } + } + process.waitFor(); + } catch (IOException | InterruptedException e) { + System.out.println("Warning: Mountstatus couldn't be verified"); + return true; } + return false; } /** - * Displays a list of available storage devices using the lsblk command. - * - *

Executes the lsblk command to show block devices and their properties, - * then prompts the user to enter a device name for selection.

+ * Lists devices with enough info for the user to make a smart decision. */ private static void deviceList() { try { - ProcessBuilder pb = new ProcessBuilder("lsblk"); + System.out.println("Scanning for block devices..."); + ProcessBuilder pb = new ProcessBuilder("lsblk", "-o", "NAME,SIZE,TYPE,RM,MOUNTPOINT"); Process process = pb.start(); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } process.waitFor(); - System.out.println("Please enter the name of your device (without /dev/):"); + + System.out.println("Enter the name of your device (e.g., sdb or nvme1n1):"); } catch (IOException | InterruptedException e) { - e.printStackTrace(); + System.out.println("Failed to run lsblk. Do you have it installed."); + } + } + + /** + * Validates a device path (e.g., from a CLI argument). + * *

Checks if the device exists, resolves the real path, and ensures + * it isn't currently mounted before giving the green light.

+ * * @param deviceName Device name (e.g., "sda" or "/dev/sda") + * @return Full validated path, or null if it's a bad idea to use it + */ + public static String validateAndGetPath(String deviceName) { + if (deviceName == null || deviceName.isBlank()) return null; + + try { + // Support both "sda" and "/dev/sda" + String checkPath = deviceName.startsWith("/dev/") ? deviceName : "/dev/" + deviceName; + Path path = Path.of(checkPath); + String resolvedPath = path.toRealPath().toString(); + + // Safety check for CLI arguments too! + if (isMounted(resolvedPath)) { + System.out.println("Hold up! " + resolvedPath + " is mounted. I won't let you flash it like that."); + return null; + } + + return resolvedPath; + } catch (IOException e) { + System.out.println("Hmm... I couldn't find a device at '" + deviceName + "'. Is it plugged in?"); + return null; } } } \ No newline at end of file