From ebea2b6a6c788bd70c168a8fb92968e653f58355 Mon Sep 17 00:00:00 2001 From: jaisnan Date: Mon, 2 Oct 2023 15:20:18 +0000 Subject: [PATCH 1/3] Prevent crash by detecting tar file --- src/lib.rs | 37 ++++++++++++++++++++++++++++++++++++- src/setup.rs | 1 + 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 4639354d8d02..d0dad65407c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,11 +16,11 @@ mod cmd; mod os_hacks; mod setup; -use std::env; use std::ffi::OsString; use std::os::unix::prelude::CommandExt; use std::path::{Path, PathBuf}; use std::process::Command; +use std::{env, fs}; use anyhow::{bail, Context, Result}; @@ -33,6 +33,41 @@ pub fn proxy(bin: &str) -> Result<()> { fail_if_in_dev_environment()?; if !setup::appears_setup() { setup::setup(None)?; + } else { + // Just because the folder is there, does not mean setup was complete + // What could solve this? create the folder only after setup is complete + // Check if conditions for crash are met, or conditions for completion are met + let x = setup::kani_dir()?; + let y = x.parent().unwrap().to_path_buf(); + println!("{:?}", x); + let mut z = false; + if let Ok(entries) = fs::read_dir(y.clone()) { + for entry in entries.flatten() { + if let Ok(file_type) = entry.file_type() { + if file_type.is_file() { + if let Some(file_name) = entry.file_name().to_str() { + if file_name.ends_with(".tar.gz") { + // Found a .tar.gz file + println!("Found .tar.gz file: {}", file_name); + let full_path = y.join(file_name); + let os_string: OsString = + full_path.clone().into_os_string(); + setup::setup(Some(os_string))?; + let _ = fs::remove_file(full_path); + z = true; + } + } + } + } + } + } else { + println!("Failed to read directory: {:?}", y); + } + if z { + println!("tar file time found"); + } else { + println!("tar file time not found, probably removed :)"); + } } exec(bin) } diff --git a/src/setup.rs b/src/setup.rs index b7fc48fcf83d..a3a3feed1e53 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -50,6 +50,7 @@ fn default_kani_dir() -> Result { /// Fast check to see if we look setup already pub fn appears_setup() -> bool { + // add check here kani_dir().expect("couldn't find kani directory").exists() } From d8142367b1edd7801fafc7eb9a0b827be1b037f3 Mon Sep 17 00:00:00 2001 From: jaisnan Date: Mon, 2 Oct 2023 17:56:00 +0000 Subject: [PATCH 2/3] Refactor to add setup_incomplete --- src/lib.rs | 40 +++++++--------------------------------- src/setup.rs | 22 ++++++++++++++++++++-- 2 files changed, 27 insertions(+), 35 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d0dad65407c3..9a1ac90f5dda 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,39 +34,13 @@ pub fn proxy(bin: &str) -> Result<()> { if !setup::appears_setup() { setup::setup(None)?; } else { - // Just because the folder is there, does not mean setup was complete - // What could solve this? create the folder only after setup is complete - // Check if conditions for crash are met, or conditions for completion are met - let x = setup::kani_dir()?; - let y = x.parent().unwrap().to_path_buf(); - println!("{:?}", x); - let mut z = false; - if let Ok(entries) = fs::read_dir(y.clone()) { - for entry in entries.flatten() { - if let Ok(file_type) = entry.file_type() { - if file_type.is_file() { - if let Some(file_name) = entry.file_name().to_str() { - if file_name.ends_with(".tar.gz") { - // Found a .tar.gz file - println!("Found .tar.gz file: {}", file_name); - let full_path = y.join(file_name); - let os_string: OsString = - full_path.clone().into_os_string(); - setup::setup(Some(os_string))?; - let _ = fs::remove_file(full_path); - z = true; - } - } - } - } - } - } else { - println!("Failed to read directory: {:?}", y); - } - if z { - println!("tar file time found"); - } else { - println!("tar file time not found, probably removed :)"); + // This handles cases where the setup was left incomplete due to an interrupt + // For example - https://github.com/model-checking/kani/issues/1545 + if let Some(path_to_bundle) = setup::appears_incomplete() { + setup::setup(Some(path_to_bundle.clone().into_os_string()))?; + // Suppress warning with unused assignment + // and remove the bundle if it still exists + let _ = fs::remove_file(path_to_bundle); } } exec(bin) diff --git a/src/setup.rs b/src/setup.rs index a3a3feed1e53..4f90eeab8e39 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -50,10 +50,25 @@ fn default_kani_dir() -> Result { /// Fast check to see if we look setup already pub fn appears_setup() -> bool { - // add check here kani_dir().expect("couldn't find kani directory").exists() } +// Ensure that the tar file does not exist, essentially using it's presence +// to detect setup completion as if it were a lock file. +pub fn appears_incomplete() -> Option { + let kani_dir = kani_dir().expect("couldn't find kani directory"); + let kani_dir_parent = kani_dir.parent().unwrap(); + + for entry in std::fs::read_dir(&kani_dir_parent).ok()?.flatten() { + if let Some(file_name) = entry.file_name().to_str() { + if file_name.ends_with(".tar.gz") { + return Some(kani_dir_parent.join(file_name)); + } + } + } + None +} + /// Sets up Kani by unpacking/installing to `~/.kani/kani-VERSION` pub fn setup(use_local_bundle: Option) -> Result<()> { let kani_dir = kani_dir()?; @@ -93,7 +108,10 @@ fn setup_kani_bundle(kani_dir: &Path, use_local_bundle: Option) -> Res .arg("-zxf") .arg(&path) .current_dir(&kani_dir) - .run()?; + .run() + .context( + "Failed to extract tar file, try removing Kani setup and restarting the setup step", + )?; } else { let filename = download_filename(); println!("[2/5] Downloading Kani release bundle: {}", &filename); From 3f589d2dd46f630c00b07812fd34520da0823a69 Mon Sep 17 00:00:00 2001 From: jaisnan Date: Tue, 3 Oct 2023 15:00:42 +0000 Subject: [PATCH 3/3] Fix comments and message --- src/setup.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/setup.rs b/src/setup.rs index 4f90eeab8e39..2d2c643bbdd5 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -53,7 +53,7 @@ pub fn appears_setup() -> bool { kani_dir().expect("couldn't find kani directory").exists() } -// Ensure that the tar file does not exist, essentially using it's presence +// Ensure that the tar file does not exist, essentially using its presence // to detect setup completion as if it were a lock file. pub fn appears_incomplete() -> Option { let kani_dir = kani_dir().expect("couldn't find kani directory"); @@ -110,7 +110,7 @@ fn setup_kani_bundle(kani_dir: &Path, use_local_bundle: Option) -> Res .current_dir(&kani_dir) .run() .context( - "Failed to extract tar file, try removing Kani setup and restarting the setup step", + "Failed to extract tar file, try removing Kani setup located in .kani in your home directory and restarting", )?; } else { let filename = download_filename();