Fixed bugs

This commit is contained in:
Cametendo
2026-04-28 11:49:35 +02:00
parent e15e7f26d5
commit 063cbbd568
5 changed files with 123 additions and 89 deletions

View File

@@ -1,4 +1,5 @@
package org.cametendo; package org.cametendo;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
@@ -11,29 +12,31 @@ import org.jline.terminal.TerminalBuilder;
/** /**
* Handles file path input and validation for disk image files. * Handles file path input and validation for disk image files.
* * * <p>This class provides functionality to interactively prompt users for image file paths
* <p>This class provides functionality to interactively prompt users for image file paths * with tab completion support via JLine. It handles Unix-style tilde (~) expansion
* with tab completion support, validate that files exist and are regular files, and * to the user's home directory and validates that paths point to existing regular files.</p>
* validate file paths from command-line arguments.</p> * * @author Cametendo
* * @version 1.1
* @author Cametendo
* @version 1.0
*/ */
public class FilePathAdd { 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 = ""; 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. * Interactively prompts the user to select an image file path.
* * * <p>Uses JLine for enhanced terminal interaction with {@link FileNameCompleter}.
* <p>Uses JLine for enhanced terminal interaction with tab completion support. * The method expands the tilde (~) character if present at the start of the string
* Validates that the selected path points to an existing regular file.</p> * and validates that the resulting path is a regular file before returning.</p>
* * * @return The validated absolute path to the selected image file
* @return The validated path to the selected image file * @throws IOException If there are I/O errors during terminal setup or file resolution
* @throws IOException If there are I/O errors during terminal setup or file validation
*/ */
protected static String filePath() throws IOException { protected static String filePath() throws IOException {
fileQuestion(); fileQuestion();
@@ -42,37 +45,48 @@ public class FilePathAdd {
LineReader reader = LineReaderBuilder.builder().terminal(terminal).completer(new FileNameCompleter()).build(); LineReader reader = LineReaderBuilder.builder().terminal(terminal).completer(new FileNameCompleter()).build();
while (true) { 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!"); System.out.println("Oops... You didn't specify a file!");
continue; 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)) { if (!Files.exists(path) || !Files.isRegularFile(path)) {
System.out.println("Invalid file! Please ensure the path points to an ISO / image file."); System.out.println("Invalid file! Please ensure the path points to an ISO / image file.");
continue; continue;
} }
// Convert to a real, absolute path and return
ImagePath = path.toRealPath().toString();
System.out.println("Using File: " + ImagePath); System.out.println("Using File: " + ImagePath);
return ImagePath; return ImagePath;
} }
} }
/** /**
* Validates and returns the full path to an image file. * Validates and returns the full path to an image file from a provided string.
* * * <p>This is primarily used for validating command-line arguments. It supports
* <p>Takes a file path, validates that it exists and is a regular file, * tilde expansion and verifies file existence and type.</p>
* and returns the real path. Used for command-line argument validation.</p> * * @param inputPath Raw path string to validate
* * @return Full validated absolute path, or {@code null} if the path is invalid or inaccessible
* @param ImagePath Path to the image file to validate
* @return Full validated path to the file, or null if invalid
*/ */
public static String validateAndGetFile(String ImagePath) { public static String validateAndGetFile(String inputPath) {
if (inputPath == null) return null;
try { 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)) { if (Files.exists(path) && Files.isRegularFile(path)) {
return path.toRealPath().toString(); return path.toRealPath().toString();
} else { } else {
@@ -86,10 +100,7 @@ public class FilePathAdd {
} }
/** /**
* Displays the prompt for file path input. * Displays the prompt for file path input to the standard output.
*
* <p>Informs the user that they should enter the full path to their ISO/image file
* and mentions that tab completion is supported for convenience.</p>
*/ */
protected static void fileQuestion() { protected static void fileQuestion() {
System.out.println("Please enter the FULL Path of your ISO / Image. (Tab-completion supported)"); System.out.println("Please enter the FULL Path of your ISO / Image. (Tab-completion supported)");

View File

@@ -0,0 +1 @@

View File

@@ -23,14 +23,5 @@ public class Greeting {
*/ */
public static void greeting(Scanner UserInput) { public static void greeting(Scanner UserInput) {
System.out.println("Welcome to cflash!"); 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);
}
} }
} }

View File

@@ -80,6 +80,8 @@ public class OSDetector {
osName = "Haiku OS"; osName = "Haiku OS";
} else if (fileName.contains("reactos")) { } else if (fileName.contains("reactos")) {
osName = "ReactOS"; osName = "ReactOS";
} else if (fileName.contains("jgh")) {
osName = "JGH OS (Sauerkraut juice)";
} }
// Generic Fallbacks // Generic Fallbacks
else if (fileName.contains("linux")) { else if (fileName.contains("linux")) {
@@ -90,6 +92,6 @@ public class OSDetector {
osName = "new OS"; 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!");
} }
} }

View File

@@ -1,4 +1,5 @@
package org.cametendo; package org.cametendo;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
@@ -7,99 +8,127 @@ import java.util.Scanner;
/** /**
* Handles storage device detection, listing, and validation for the flashing process. * Handles storage device detection, listing, and validation for the flashing process.
* * * <p>Includes safety checks to ensure we don't nuke a partition that's currently in use.
* <p>This class provides functionality to list available storage devices using lsblk, * Keeps the user in the loop with a more personal touch.</p>
* validate device paths, and interactively prompt users to select a target device * * @author Cametendo
* for flashing operations.</p> * @version 1.1
*
* @author Cametendo
* @version 1.0
*/ */
public class StorageDeviceLister { public class StorageDeviceLister {
/**
* Stores the selected device name (without /dev/ prefix).
*/
public static String device = ""; public static String device = "";
/**
* Stores the full validated path to the selected device.
*/
public static String fullPath = ""; public static String fullPath = "";
/** /**
* Interactively prompts the user to select a storage device. * Guides the user through selecting a safe, unmounted storage device.
*
* <p>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.</p>
*
* @param UserInput Scanner object for reading user input
* @return The full validated path to the selected device
*/ */
protected static String deviceCheck(Scanner UserInput) { protected static String deviceCheck(Scanner UserInput) {
deviceList(); deviceList();
while (true) { while (true) {
device = UserInput.nextLine(); System.out.print("Target device: ");
device = UserInput.nextLine().trim();
if (device.isBlank()) { if (device.isBlank()) {
System.out.println("Oops... Device name is empty. Did you missclick?"); System.out.println("Oops... Device name is empty. Did you missclick?");
continue; 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 { try {
fullPath = path.toRealPath().toString(); fullPath = path.toRealPath().toString();
System.out.println("Using device: " + fullPath); // 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("Solid choice. Using device: " + fullPath);
return fullPath; return fullPath;
} catch (IOException e) { } 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. * Asks lsblk if the device or its children have an active mount point.
*
* <p>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.</p>
*
* @param deviceName Device name without /dev/ prefix (e.g., "sda")
* @return Full validated path to the device, or null if invalid
*/ */
public static String validateAndGetPath(String deviceName) { private static boolean isMounted(String devicePath) {
try { try {
Path path = Path.of("/dev/" + deviceName); ProcessBuilder pb = new ProcessBuilder("lsblk", "-no", "MOUNTPOINT", devicePath);
return path.toRealPath().toString(); Process process = pb.start();
} catch (IOException e) {
System.out.println("Device not found. Invalid Path or no access."); try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
return null; 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. * Lists devices with enough info for the user to make a smart decision.
*
* <p>Executes the lsblk command to show block devices and their properties,
* then prompts the user to enter a device name for selection.</p>
*/ */
private static void deviceList() { private static void deviceList() {
try { 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(); Process process = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line; String line;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
System.out.println(line); System.out.println(line);
} }
process.waitFor(); 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) { } 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).
* * <p>Checks if the device exists, resolves the real path, and ensures
* it isn't currently mounted before giving the green light.</p>
* * @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;
} }
} }
} }