Add portable mode with removable media detection and scanning
This commit is contained in:
@@ -1786,6 +1786,14 @@ impl Database {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_portable(&self, id: i64, portable: bool, mount_point: Option<&str>) -> SqlResult<()> {
|
||||
self.conn.execute(
|
||||
"UPDATE appimages SET is_portable = ?2, mount_point = ?3 WHERE id = ?1",
|
||||
params![id, portable as i32, mount_point],
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// --- Launch statistics ---
|
||||
|
||||
pub fn get_top_launched(&self, limit: i32) -> SqlResult<Vec<(String, u64)>> {
|
||||
|
||||
@@ -11,6 +11,7 @@ pub mod integrator;
|
||||
pub mod launcher;
|
||||
pub mod notification;
|
||||
pub mod orphan;
|
||||
pub mod portable;
|
||||
pub mod report;
|
||||
pub mod security;
|
||||
pub mod updater;
|
||||
|
||||
71
src/core/portable.rs
Normal file
71
src/core/portable.rs
Normal file
@@ -0,0 +1,71 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// Information about a mounted removable device.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MountInfo {
|
||||
pub device: String,
|
||||
pub mount_point: PathBuf,
|
||||
pub fs_type: String,
|
||||
}
|
||||
|
||||
/// Detect removable media mount points by parsing /proc/mounts.
|
||||
/// Looks for user-accessible removable paths with common removable fs types.
|
||||
pub fn detect_removable_mounts() -> Vec<MountInfo> {
|
||||
let content = match std::fs::read_to_string("/proc/mounts") {
|
||||
Ok(c) => c,
|
||||
Err(_) => return Vec::new(),
|
||||
};
|
||||
|
||||
let removable_prefixes = ["/media/", "/run/media/", "/mnt/"];
|
||||
let removable_fs = ["vfat", "exfat", "ntfs", "ntfs3", "fuseblk", "ext4", "ext3", "btrfs"];
|
||||
|
||||
content
|
||||
.lines()
|
||||
.filter_map(|line| {
|
||||
let parts: Vec<&str> = line.split_whitespace().collect();
|
||||
if parts.len() < 3 {
|
||||
return None;
|
||||
}
|
||||
let device = parts[0];
|
||||
let mount_point = parts[1];
|
||||
let fs_type = parts[2];
|
||||
|
||||
// Check if mount point is in a removable location
|
||||
let is_removable = removable_prefixes
|
||||
.iter()
|
||||
.any(|prefix| mount_point.starts_with(prefix));
|
||||
|
||||
if !is_removable {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Check filesystem type
|
||||
if !removable_fs.contains(&fs_type) {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(MountInfo {
|
||||
device: device.to_string(),
|
||||
mount_point: PathBuf::from(mount_point),
|
||||
fs_type: fs_type.to_string(),
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Check if a given path is located on a removable device.
|
||||
pub fn is_path_on_removable(path: &Path) -> bool {
|
||||
let mounts = detect_removable_mounts();
|
||||
mounts.iter().any(|m| path.starts_with(&m.mount_point))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_is_path_on_removable_with_no_mounts() {
|
||||
// On a test system, /home paths shouldn't be on removable media
|
||||
assert!(!is_path_on_removable(Path::new("/home/user/test.AppImage")));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user