forked from pisilinux-rs/yali-rs
Merge branch 'main' into 'main'
Main See merge request ayhanyalcinsoy/yali-rs!2
This commit is contained in:
@@ -90,6 +90,7 @@ finish_title = "Installation Complete"
|
||||
# ── Execution (extra) ─────────────────────────────────────
|
||||
install_failed = "Installation failed"
|
||||
install_done = "Installation complete! Click Next to continue."
|
||||
install_current_file = "Current file"
|
||||
retry_install = "Retry"
|
||||
finish_next = "Finish →"
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ finish_title = "Kurulum Tamamlandı"
|
||||
# ── Execution (ek) ────────────────────────────────────────
|
||||
install_failed = "Kurulum başarısız"
|
||||
install_done = "Kurulum tamamlandı! Devam etmek için İleri'ye basın."
|
||||
install_current_file = "İşlemdeki dosya"
|
||||
retry_install = "Yeniden Dene"
|
||||
finish_next = "Tamamlandı →"
|
||||
|
||||
|
||||
@@ -137,11 +137,12 @@ pub fn apply_to_state(af: &AnswerFile, state: &mut crate::installer::GlobalState
|
||||
let efi_mb = if is_uefi { 512u64 } else { 0 };
|
||||
let total_mb = info.size_bytes / 1024 / 1024;
|
||||
|
||||
// Tavsiye edilen swap: RAM * 1.5, min 512 MB, max 8192 MB
|
||||
// Swap: RAM * 1.0, min 512 MB, max 2048 MB, ayrıca diskin %10'unu geçmesin
|
||||
let mut sys = sysinfo::System::new();
|
||||
sys.refresh_memory();
|
||||
let ram_mb = sys.total_memory() / 1024 / 1024;
|
||||
let swap_mb = (ram_mb * 3 / 2).clamp(512, 8192);
|
||||
let ram_mb = sys.total_memory() / 1024 / 1024;
|
||||
let disk_10pct = total_mb / 10;
|
||||
let swap_mb = ram_mb.clamp(512, 2048).min(disk_10pct);
|
||||
|
||||
let overhead = efi_mb + swap_mb + 512;
|
||||
let root_mb = total_mb.saturating_sub(overhead);
|
||||
|
||||
@@ -205,6 +205,7 @@ pub struct GlobalState {
|
||||
pub available_disks: Vec<DiskInfo>,
|
||||
pub install_progress: f32,
|
||||
pub install_log: Vec<String>,
|
||||
pub install_current_file: Option<String>,
|
||||
pub demo_mode: bool,
|
||||
pub is_dark: bool,
|
||||
pub rescue_mode: bool,
|
||||
@@ -271,6 +272,7 @@ impl Default for GlobalState {
|
||||
available_disks: Vec::new(),
|
||||
install_progress: 0.0,
|
||||
install_log: Vec::new(),
|
||||
install_current_file: None,
|
||||
demo_mode: false,
|
||||
is_dark: true,
|
||||
rescue_mode: false,
|
||||
|
||||
+145
-28
@@ -129,17 +129,42 @@ impl Job for CopyFilesJob {
|
||||
async fn run(&self, ui: &UiSender) -> Result<(), String> {
|
||||
ui.log(format!("rsync {} → {}", self.source, self.target));
|
||||
|
||||
// --info=progress2 ham çıktı verir; gerçek uygulamada
|
||||
// satır satır parse edilerek ilerleme güncellenebilir.
|
||||
let is_root_source = self.source.trim_end_matches('/') == "";
|
||||
|
||||
let mut args: Vec<String> = vec![
|
||||
"-aAXH".to_string(),
|
||||
"--info=progress2".to_string(),
|
||||
"--exclude=/proc".to_string(),
|
||||
"--exclude=/sys".to_string(),
|
||||
"--exclude=/dev".to_string(),
|
||||
"--exclude=/run".to_string(),
|
||||
"--exclude=/proc/**".to_string(),
|
||||
"--exclude=/sys/**".to_string(),
|
||||
"--exclude=/dev/**".to_string(),
|
||||
"--exclude=/run/**".to_string(),
|
||||
"--exclude=/tmp/**".to_string(),
|
||||
"--exclude=/var/tmp/**".to_string(),
|
||||
"--exclude=/var/cache/**".to_string(),
|
||||
"--exclude=/home/**".to_string(),
|
||||
"--exclude=/root/**".to_string(),
|
||||
"--exclude=/lost+found".to_string(),
|
||||
"--exclude=*.sqfs".to_string(),
|
||||
];
|
||||
|
||||
// Kaynak canlı sistem köküyse ekstra exclude'ler
|
||||
if is_root_source {
|
||||
args.extend_from_slice(&[
|
||||
"--exclude=/bootmnt/**".to_string(),
|
||||
"--exclude=/ro_branch/**".to_string(),
|
||||
"--exclude=/mnt/**".to_string(),
|
||||
"--exclude=/media/**".to_string(),
|
||||
"--exclude=/var/log/journal/**".to_string(),
|
||||
"--exclude=/var/lib/pisi/cache/**".to_string(),
|
||||
"--exclude=/var/lib/pisi/archives/**".to_string(),
|
||||
"--exclude=/etc/adjtime".to_string(),
|
||||
"--exclude=/etc/mtab".to_string(),
|
||||
"--exclude=/etc/resolv.conf".to_string(),
|
||||
"--exclude=/etc/hostname".to_string(),
|
||||
"--exclude=/etc/machine-id".to_string(),
|
||||
]);
|
||||
}
|
||||
|
||||
if let (Ok(source_path), Ok(target_path)) = (
|
||||
std::path::Path::new(&self.source).canonicalize(),
|
||||
std::path::Path::new(&self.target).canonicalize(),
|
||||
@@ -743,6 +768,26 @@ async fn sync_partition_table(disk: &str) {
|
||||
/// 2. Sabit aday listesini dene (her adayda bin/ + etc/ varlığı aranır)
|
||||
/// 3. Hiçbiri bulunamazsa `/` (canlı sistem kökü) kullan — rsync
|
||||
/// zaten /proc /sys /dev /run'u exclude eder.
|
||||
fn has_root_fs(path: &std::path::Path) -> bool {
|
||||
(path.join("bin").exists() || path.join("usr/bin").exists()) && path.join("etc").exists()
|
||||
}
|
||||
|
||||
fn is_iso_mount(path: &str) -> bool {
|
||||
let sqfs_check = [
|
||||
"pisi/pisi.sqfs",
|
||||
"live/pisi.sqfs",
|
||||
"live/filesystem.squashfs",
|
||||
"casper/filesystem.squashfs",
|
||||
"live squashfs",
|
||||
];
|
||||
for pattern in &sqfs_check {
|
||||
if std::path::Path::new(path).join(pattern).exists() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn detect_source_dir() -> String {
|
||||
// 1. /proc/mounts içinde squashfs veya overlay mount noktalarını tara
|
||||
if let Ok(mounts) = std::fs::read_to_string("/proc/mounts") {
|
||||
@@ -756,7 +801,7 @@ pub fn detect_source_dir() -> String {
|
||||
"squashfs" => {
|
||||
if mount_pt != "/" {
|
||||
let p = std::path::Path::new(mount_pt);
|
||||
if p.join("bin").exists() || p.join("usr/bin").exists() {
|
||||
if has_root_fs(p) {
|
||||
return format!("{}/", mount_pt.trim_end_matches('/'));
|
||||
}
|
||||
}
|
||||
@@ -768,7 +813,7 @@ pub fn detect_source_dir() -> String {
|
||||
if let Some(lower) = opt.strip_prefix("lowerdir=") {
|
||||
for dir in lower.split(':') {
|
||||
let p = std::path::Path::new(dir);
|
||||
if p.exists() && (p.join("bin").exists() || p.join("usr/bin").exists()) {
|
||||
if p.exists() && has_root_fs(p) {
|
||||
return format!("{}/", dir.trim_end_matches('/'));
|
||||
}
|
||||
}
|
||||
@@ -781,7 +826,8 @@ pub fn detect_source_dir() -> String {
|
||||
}
|
||||
|
||||
// 2. Sabit aday listesi (her adayda bin/ + etc/ kontrolü)
|
||||
let candidates = [
|
||||
// NOT: /bootmnt ISO kökü olabilir; altında pisi.sqfs varsa atlanır.
|
||||
for path in &[
|
||||
"/run/livecd/squashfs-root",
|
||||
"/run/live/rootfs",
|
||||
"/run/live/medium",
|
||||
@@ -791,19 +837,19 @@ pub fn detect_source_dir() -> String {
|
||||
"/mnt/cdrom",
|
||||
"/bootmnt/live",
|
||||
"/bootmnt/livecd",
|
||||
"/bootmnt",
|
||||
];
|
||||
for path in &candidates {
|
||||
] {
|
||||
let p = std::path::Path::new(path);
|
||||
if p.exists() {
|
||||
let has_bin = p.join("bin").exists() || p.join("usr/bin").exists();
|
||||
let has_etc = p.join("etc").exists();
|
||||
if has_bin && has_etc {
|
||||
return format!("{}/", path);
|
||||
}
|
||||
if p.exists() && has_root_fs(p) {
|
||||
return format!("{}/", path);
|
||||
}
|
||||
}
|
||||
|
||||
// 2b. /bootmnt son çare; ama ISO köküyse (pisi.sqfs varsa) atla
|
||||
let bootmnt = std::path::Path::new("/bootmnt");
|
||||
if bootmnt.exists() && !is_iso_mount("/bootmnt") && has_root_fs(bootmnt) {
|
||||
return "/bootmnt/".to_string();
|
||||
}
|
||||
|
||||
// 3. Hiçbiri bulunamazsa canlı sistem kökü
|
||||
"/".to_string()
|
||||
}
|
||||
@@ -1324,6 +1370,8 @@ impl Job for CleanupLiveJob {
|
||||
// YALI desktop dosyaları
|
||||
let _ = tokio::fs::remove_file(format!("{}/usr/share/applications/yali.desktop", mt)).await;
|
||||
let _ = tokio::fs::remove_file(format!("{}/usr/share/applications/yali-bin.desktop", mt)).await;
|
||||
let _ = tokio::fs::remove_dir_all(format!("{}/bootmnt", mt)).await;
|
||||
|
||||
|
||||
ui.log("✓ Live temizlik tamamlandı");
|
||||
Ok(())
|
||||
@@ -1661,20 +1709,37 @@ impl Job for CreateUserJob {
|
||||
&self.username,
|
||||
]).await?;
|
||||
|
||||
// chpasswd ile şifre ayarla (stdin üzerinden güvenli)
|
||||
ui.log(format!("Şifre ayarlanıyor: {}", self.username));
|
||||
let chpasswd_input = format!("{}:{}", self.username, self.password);
|
||||
set_password_via_chpasswd(&self.mount, &chpasswd_input).await?;
|
||||
// // chpasswd ile şifre ayarla (stdin üzerinden güvenli)
|
||||
// ui.log(format!("Şifre ayarlanıyor: {}", self.username));
|
||||
// let chpasswd_input = format!("{}:{}", self.username, self.password);
|
||||
// set_password_via_chpasswd(&self.mount, &chpasswd_input).await?;
|
||||
|
||||
// Root şifresi: belirlenmişse ayarla, yoksa kilitle
|
||||
// // Root şifresi: belirlenmişse ayarla, yoksa kilitle
|
||||
// if self.root_password.is_empty() {
|
||||
// ui.log("Root hesabı kilitleniyor…");
|
||||
// run_chroot(&self.mount, &["passwd", "-l", "root"]).await?;
|
||||
// } else {
|
||||
// ui.log("Root şifresi ayarlanıyor…");
|
||||
// let root_input = format!("root:{}", self.root_password);
|
||||
// set_password_via_chpasswd(&self.mount, &root_input).await?;
|
||||
// }
|
||||
|
||||
// 2. chpasswd ile şifre ayarla (YENİ BASİTLEŞTİRİLMİŞ VE KESİN YÖNTEM)
|
||||
ui.log(format!("Şifre ayarlanıyor: {}", self.username));
|
||||
// sh -c kullanarak echo ile chpasswd'e şifreyi güvenli bir şekilde üflüyoruz
|
||||
let user_cmd = format!("echo '{}:{}' | chpasswd -c SHA512", self.username, self.password);
|
||||
run_chroot(&self.mount, &["sh", "-c", &user_cmd]).await?;
|
||||
|
||||
// 3. Root şifresi: belirlenmişse ayarla, yoksa kilitle
|
||||
if self.root_password.is_empty() {
|
||||
ui.log("Root hesabı kilitleniyor…");
|
||||
run_chroot(&self.mount, &["passwd", "-l", "root"]).await?;
|
||||
} else {
|
||||
ui.log("Root şifresi ayarlanıyor…");
|
||||
let root_input = format!("root:{}", self.root_password);
|
||||
set_password_via_chpasswd(&self.mount, &root_input).await?;
|
||||
}
|
||||
let root_cmd = format!("echo 'root:{}' | chpasswd -c SHA512", self.root_password);
|
||||
run_chroot(&self.mount, &["sh", "-c", &root_cmd]).await?;
|
||||
}
|
||||
|
||||
|
||||
// sudoers: wheel grubu sudo yetkisi alsın
|
||||
let sudoers_dir = format!("{}/etc/sudoers.d", self.mount);
|
||||
@@ -1693,6 +1758,43 @@ impl Job for CreateUserJob {
|
||||
}
|
||||
}
|
||||
|
||||
// /// `chpasswd` komutuna stdin üzerinden kullanıcı:şifre gönderir.
|
||||
// async fn set_password_via_chpasswd(mount: &str, input: &str) -> Result<(), String> {
|
||||
// if DEMO_MODE.load(std::sync::atomic::Ordering::Relaxed) {
|
||||
// tokio::time::sleep(std::time::Duration::from_millis(2500)).await;
|
||||
// return Ok(());
|
||||
// }
|
||||
|
||||
// use tokio::io::AsyncWriteExt;
|
||||
// use tokio::process::Command;
|
||||
|
||||
// let mut child = Command::new("chroot")
|
||||
// .args([mount, "chpasswd"])
|
||||
// .stdin(std::process::Stdio::piped())
|
||||
// .stdout(std::process::Stdio::null())
|
||||
// .stderr(std::process::Stdio::piped())
|
||||
// .spawn()
|
||||
// .map_err(|e| format!("chpasswd başlatılamadı: {}", e))?;
|
||||
|
||||
// if let Some(mut stdin) = child.stdin.take() {
|
||||
// let mut data = input.as_bytes().to_vec();
|
||||
// if !data.ends_with(b"\n") {
|
||||
// data.push(b'\n');
|
||||
// }
|
||||
// stdin.write_all(&data).await
|
||||
// .map_err(|e| format!("chpasswd stdin yazma hatası: {}", e))?;
|
||||
// }
|
||||
|
||||
// let output = child.wait_with_output().await
|
||||
// .map_err(|e| format!("chpasswd bekleme hatası: {}", e))?;
|
||||
|
||||
// if output.status.success() {
|
||||
// Ok(())
|
||||
// } else {
|
||||
// Err(String::from_utf8_lossy(&output.stderr).trim().to_string())
|
||||
// }
|
||||
// }
|
||||
|
||||
/// `chpasswd` komutuna stdin üzerinden kullanıcı:şifre gönderir.
|
||||
async fn set_password_via_chpasswd(mount: &str, input: &str) -> Result<(), String> {
|
||||
if DEMO_MODE.load(std::sync::atomic::Ordering::Relaxed) {
|
||||
@@ -1705,6 +1807,7 @@ async fn set_password_via_chpasswd(mount: &str, input: &str) -> Result<(), Strin
|
||||
|
||||
let mut child = Command::new("chroot")
|
||||
.args([mount, "chpasswd"])
|
||||
// Gerekirse varsayılan algoritmayı garantiye almak için araya "-c", "SHA512" argümanları eklenebilir.
|
||||
.stdin(std::process::Stdio::piped())
|
||||
.stdout(std::process::Stdio::null())
|
||||
.stderr(std::process::Stdio::piped())
|
||||
@@ -1712,10 +1815,24 @@ async fn set_password_via_chpasswd(mount: &str, input: &str) -> Result<(), Strin
|
||||
.map_err(|e| format!("chpasswd başlatılamadı: {}", e))?;
|
||||
|
||||
if let Some(mut stdin) = child.stdin.take() {
|
||||
stdin.write_all(input.as_bytes()).await
|
||||
let mut data = input.as_bytes().to_vec();
|
||||
if !data.ends_with(b"\n") {
|
||||
data.push(b'\n');
|
||||
}
|
||||
|
||||
// 1. Veriyi tampon belleğe yaz
|
||||
stdin.write_all(&data).await
|
||||
.map_err(|e| format!("chpasswd stdin yazma hatası: {}", e))?;
|
||||
|
||||
// 2. KRİTİK EKSİK: Tampondaki veriyi chpasswd sürecine zorla gönder (Sıvazla)
|
||||
stdin.flush().await
|
||||
.map_err(|e| format!("chpasswd stdin flush hatası: {}", e))?;
|
||||
|
||||
// 3. Kanalı elinle kapatarak chpasswd'e "bitti" (EOF) sinyali yolla
|
||||
drop(stdin);
|
||||
}
|
||||
|
||||
// wait_with_output zaten arkada kalan süreçleri temizler ve çıktıları toplar
|
||||
let output = child.wait_with_output().await
|
||||
.map_err(|e| format!("chpasswd bekleme hatası: {}", e))?;
|
||||
|
||||
@@ -1724,7 +1841,7 @@ async fn set_password_via_chpasswd(mount: &str, input: &str) -> Result<(), Strin
|
||||
} else {
|
||||
Err(String::from_utf8_lossy(&output.stderr).trim().to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// fstab'ı doğrudan dosyaya yazar (genfstab yerine; ISO ortamında daha güvenilir).
|
||||
pub struct GenerateFstabJob {
|
||||
|
||||
@@ -41,6 +41,7 @@ impl InstallerStep for ExecutionStep {
|
||||
|
||||
state.install_progress = 0.0;
|
||||
state.install_log.clear();
|
||||
state.install_current_file = None;
|
||||
state.install_log.push(t!("install_starting").to_string());
|
||||
}
|
||||
|
||||
@@ -289,6 +290,15 @@ impl InstallerStep for ExecutionStep {
|
||||
);
|
||||
});
|
||||
|
||||
if let Some(ref current_file) = state.install_current_file {
|
||||
ui.add_space(4.0);
|
||||
ui.label(
|
||||
egui::RichText::new(format!("{}: {}", t!("install_current_file"), current_file))
|
||||
.size(12.0)
|
||||
.color(theme::c_text_dim()),
|
||||
);
|
||||
}
|
||||
|
||||
ui.add_space(4.0);
|
||||
ui.add(
|
||||
egui::ProgressBar::new(state.install_progress)
|
||||
|
||||
+7
-3
@@ -39,9 +39,13 @@ impl InstallerStep for FinishStep {
|
||||
theme::primary_button(&t!("finish_restart"))
|
||||
.min_size(egui::vec2(200.0, 44.0)),
|
||||
).clicked() {
|
||||
let _ = std::process::Command::new("systemctl")
|
||||
.arg("reboot")
|
||||
.spawn();
|
||||
ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close);
|
||||
std::thread::spawn(|| {
|
||||
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||
let _ = std::process::Command::new("reboot")
|
||||
.arg("-f")
|
||||
.spawn();
|
||||
});
|
||||
}
|
||||
|
||||
ui.add_space(12.0);
|
||||
|
||||
Reference in New Issue
Block a user