fix: manual partition validation - add duplicate mountpoint check, swap size validation, disk selection in is_complete, and delete flag handling in disk_free_regions_mb

This commit is contained in:
Erkan IŞIK
2026-09-18 00:45:09 +03:00
parent 7e1bf45998
commit 8633422c22
2 changed files with 42 additions and 8 deletions
+6 -4
View File
@@ -512,9 +512,9 @@ fn disk_free_regions_mb(disk: &str, exclude_nums: &[u32]) -> Result<Vec<(u64, u6
/// Eski Yali'nin DeviceTree/Operation mimarisiyle aynı felsefe:
/// - Dokunulmayan disklere ve bölümlere HİÇ dokunulmaz (veriler korunur)
/// - Silinmek işaretli bölümler `parted rm` ile kaldırılır
/// (OperationDestroyDevice karşılığı)
/// (OperationDestroyDevice corresponds)
/// - Yeni tanımlar diskin BOŞ alanlarına yerleştirilir; tüm disk
/// sıfırlanmaz (OperationCreateDevice karşılığı)
/// sıfırlanmaz (OperationCreateDevice corresponds)
/// - skip_format=false olanlar biçimlendirilir (OperationCreateFormat)
pub struct CustomPartitionJob {
pub custom_partitions: Vec<CustomPartition>,
@@ -541,9 +541,11 @@ impl Job for CustomPartitionJob {
let parts: Vec<&CustomPartition> = self.custom_partitions.iter()
.filter(|p| p.disk == *disk).collect();
// Bu disk için planlanan işlemler
// Bu disk için planlanan işlemler - her iki durumda da silinmesi
// istenen bölümlerin numaralarını topla: (1) fiziksel bölümler
// (orig_device varsa) ve (2) kullanıcı tanımlı silinme işaretleri.
let destroys: Vec<u32> = parts.iter()
.filter(|p| p.delete && !p.orig_device.is_empty())
.filter(|p| p.delete)
.filter_map(|p| crate::installer::part_number(&p.orig_device))
.collect();
let mut creates: Vec<&CustomPartition> = parts.iter()
+36 -4
View File
@@ -316,6 +316,37 @@ fn validate_manual(
if is_uefi && !has_efi {
return Some(t!("mp_no_efi").to_string());
}
// Aynı mountpoint'ta iki bölüm tanımlı mı kontrolü
let mountpoints: std::collections::HashSet<&String> = parts.iter()
.filter(live)
.map(|p| &p.mountpoint)
.collect();
if mountpoints.len() != parts.iter().filter(live).count() {
return Some(t!("mp_duplicate_mountpoint").to_string());
}
// Swap bölümünün fstype'ı swap olma kontrolü
let has_swap = parts.iter().filter(live).any(|p| p.fstype == FsType::Swap);
if has_swap {
let swap_parts: Vec<&CustomPartition> = parts.iter().filter(live).filter(|p| p.fstype == FsType::Swap).collect();
for sp in &swap_parts {
if sp.size_mb < 512 {
return Some(format!("{} swap boyutu 512 MB'den az", sp.device));
}
if sp.size_mb > 8192 {
return Some(format!("{} swap boyutu 8 GB'yi aşıyor", sp.device));
}
}
}
// Tüm bölümlerin boyutları 0'dan büyük olma kontrolü
for p in parts.iter().filter(live) {
if p.size_mb == 0 && p.mountpoint.is_empty() {
return Some(format!("{} boyut 0 (kalan alan) belirtilmiş ama mountpoint boş", p.device));
}
}
None
}
@@ -325,12 +356,12 @@ fn manual_capacity_error(parts: &[CustomPartition], disks: &[DiskInfo]) -> Optio
.filter(|p| p.disk == d.name && !p.delete)
.collect();
if defs.is_empty() { continue; }
let cap = d.size_bytes / 1_048_576;
let fixed: u64 = defs.iter().map(|p| p.size_mb).sum();
if fixed > cap {
let cap_mb = d.size_bytes / 1_048_576;
let fixed_mb: u64 = defs.iter().map(|p| p.size_mb).sum();
if fixed_mb > cap_mb {
return Some(format!(
"{}: sabit tanımlar ({:.1} GB) disk boyutunu ({:.1} GB) aşıyor",
d.name, fixed as f64 / 1024.0, cap as f64 / 1024.0
d.name, fixed_mb as f64 / 1024.0, cap_mb as f64 / 1024.0
));
}
}
@@ -403,6 +434,7 @@ impl InstallerStep for PartitionStep {
state.partition_plan.is_some()
} else {
!state.custom_partitions.is_empty()
&& state.selected_disk.is_some()
&& validate_manual(&state.custom_partitions, &state.logical_volumes, self.is_uefi).is_none()
&& manual_capacity_error(&state.custom_partitions, &state.available_disks).is_none()
}