Skip to content

Commit

Permalink
util::fs::script
Browse files Browse the repository at this point in the history
  • Loading branch information
maxkofler committed Dec 8, 2023
1 parent 3e535c7 commit ab6f1b3
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/util/fs/fsentry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,16 @@ pub use directory::*;
mod elf;
pub use elf::*;

mod script;
pub use script::*;

/// A filesystem entry
#[derive(Clone)]
pub enum FSEntry {
/// An ELF file
ELF(ELFFile),
/// A script file
Script(ScriptFile),
/// A symlink
Symlink(OsString),
/// Some other file
Expand Down Expand Up @@ -67,6 +72,14 @@ impl FSEntry {
.e_context(|| format!("Parsing ELF file {}", path.to_string_lossy()))?;

return Ok(Self::ELF(f));
} else if infer::text::is_shellscript(&buf) {
trace!("[infer] SCR : {}", &path.to_string_lossy());

let f = ScriptFile::parse(&path, name).e_context(|| {
format!("Parsing SCRIPT file {}", path.to_string_lossy())
})?;

return Ok(Self::Script(f));
}
}
}
Expand All @@ -82,6 +95,7 @@ impl FSEntry {
pub fn name(&self) -> &OsStr {
match self {
Self::ELF(n) => &n.name,
Self::Script(n) => &n.name,
Self::Symlink(n) => n,
Self::OtherFile(n) => n,
Self::Directory(d) => &d.name,
Expand Down
56 changes: 56 additions & 0 deletions src/util/fs/fsentry/script.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use std::{
collections::LinkedList,
ffi::OsString,
fs::File,
io::{BufRead, BufReader},
path::{Path, PathBuf},
};

use crate::error::{Error, ErrorExt};

/// A fs entry that is a script (has a shbang at its start)
#[derive(Clone)]
pub struct ScriptFile {
/// The name of the file
pub name: OsString,

/// The interpreter for the file
/// (<path to the interpreter>, <array of arguments>)
pub interpreter: Option<(PathBuf, Vec<OsString>)>,
}

impl ScriptFile {
/// Parses an `ELFFile` from the provided path
/// # Arguments
/// * `path` - The path to parse the file from
pub fn parse(path: &Path, name: OsString) -> Result<Self, Error> {
let context = || format!("Parsing SCRIPT file {}", path.to_string_lossy());

// Read the first line
let first_line = {
let mut file = BufReader::new(File::open(path).e_context(context)?);
let mut shbang = String::new();
file.read_line(&mut shbang).e_context(context)?;
shbang
};

// Remove the shbang from the start ('#!')
let first_line = first_line.trim_start_matches("#!");

// Split the line into its pieces
let mut split: LinkedList<OsString> = first_line
.split(' ')
.map(|s| OsString::from(s.trim()))
.collect();

// Split the interpreter path from its arguments
let interpreter = split.pop_front().map(|i| {
(
PathBuf::from(i),
split.into_iter().collect::<Vec<OsString>>(),
)
});

Ok(Self { name, interpreter })
}
}

0 comments on commit ab6f1b3

Please sign in to comment.