Enhanced flexibility in how resource images are mounted.
Can now choose location at which resource image is mounted with mount_at() method. This method also returns a handle which can be used to later unmount the image.
This commit is contained in:
parent
2e781e2183
commit
9fb11e3317
@ -112,16 +112,24 @@ impl ResourceImage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mount(&mut self) -> Result<()> {
|
|
||||||
if CommandLine::noverity() {
|
|
||||||
self.mount_noverity()?;
|
|
||||||
} else {
|
|
||||||
self.mount_verity()?;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// Mount resource image at default mount path and process manifest file if it exists
|
||||||
|
pub fn mount(&mut self) -> Result<()> {
|
||||||
|
let _ = self.mount_at(self.mount_path())?;
|
||||||
self.process_manifest_file()
|
self.process_manifest_file()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mount resource image at specified path without processing manifest file.
|
||||||
|
/// Returns a ResourceMount object which can be stored and later used to unmount
|
||||||
|
/// the image.
|
||||||
|
pub fn mount_at<P: AsRef<Path>>(&mut self, mount_path: P) -> Result<ResourceMount> {
|
||||||
|
if CommandLine::noverity() {
|
||||||
|
self.mount_noverity(mount_path.as_ref())
|
||||||
|
} else {
|
||||||
|
self.mount_verity(mount_path.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_compressed(&self) -> bool {
|
pub fn is_compressed(&self) -> bool {
|
||||||
self.header.has_flag(ImageHeader::FLAG_DATA_COMPRESSED)
|
self.header.has_flag(ImageHeader::FLAG_DATA_COMPRESSED)
|
||||||
}
|
}
|
||||||
@ -175,18 +183,20 @@ impl ResourceImage {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mount_verity(&self) -> Result<()> {
|
fn mount_verity(&self, mount_path: &Path) -> Result<ResourceMount> {
|
||||||
let verity_dev = self.setup_verity_device()?;
|
let verity_dev = self.setup_verity_device()?;
|
||||||
|
let verity_path = format!("/dev/mapper/{}", verity_dev);
|
||||||
|
|
||||||
info!("Mounting dm-verity device to {}", self.mount_path().display());
|
info!("Mounting dm-verity device to {}", mount_path.display());
|
||||||
|
|
||||||
fs::create_dir_all(self.mount_path())?;
|
fs::create_dir_all(mount_path)?;
|
||||||
|
|
||||||
util::mount(&verity_dev.to_string_lossy(), self.mount_path(), None)
|
util::mount(verity_path, mount_path, None)?;
|
||||||
|
Ok(ResourceMount::new_verity(mount_path, verity_dev))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_verity_device(&self) -> Result<PathBuf> {
|
pub fn setup_verity_device(&self) -> Result<String> {
|
||||||
if !CommandLine::nosignatures() {
|
if !CommandLine::nosignatures() {
|
||||||
match self.header.public_key()? {
|
match self.header.public_key()? {
|
||||||
Some(pubkey) => {
|
Some(pubkey) => {
|
||||||
@ -202,9 +212,7 @@ impl ResourceImage {
|
|||||||
if !self.has_verity_hashtree() {
|
if !self.has_verity_hashtree() {
|
||||||
self.generate_verity_hashtree()?;
|
self.generate_verity_hashtree()?;
|
||||||
}
|
}
|
||||||
let devname = self.verity().setup(&self.metainfo())?;
|
self.verity().setup(&self.metainfo())
|
||||||
Ok(Path::new("/dev/mapper").join(devname))
|
|
||||||
// verity::setup_image_device(self.path(), &self.metainfo())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_verity_hashtree(&self) -> Result<()> {
|
pub fn generate_verity_hashtree(&self) -> Result<()> {
|
||||||
@ -246,22 +254,23 @@ impl ResourceImage {
|
|||||||
|
|
||||||
// Mount the resource image but use a simple loop mount rather than setting up a dm-verity
|
// Mount the resource image but use a simple loop mount rather than setting up a dm-verity
|
||||||
// device for the image.
|
// device for the image.
|
||||||
fn mount_noverity(&self) -> Result<()> {
|
fn mount_noverity(&self, mount_path: &Path) -> Result<ResourceMount> {
|
||||||
info!("loop mounting image to {} (noverity)", self.mount_path().display());
|
info!("loop mounting image to {} (noverity)", self.mount_path().display());
|
||||||
|
|
||||||
if self.is_compressed() {
|
if self.is_compressed() {
|
||||||
self.decompress()?;
|
self.decompress()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mount_path = self.mount_path();
|
|
||||||
let loopdev = LoopDevice::create(self.path(), Some(4096), true)?;
|
let loopdev = LoopDevice::create(self.path(), Some(4096), true)?;
|
||||||
|
|
||||||
info!("Loop device created: {}", loopdev);
|
info!("Loop device created: {}", loopdev);
|
||||||
info!("Mounting to: {}", mount_path.display());
|
info!("Mounting to: {}", mount_path.display());
|
||||||
|
|
||||||
fs::create_dir_all(&mount_path)?;
|
fs::create_dir_all(mount_path)?;
|
||||||
|
|
||||||
util::mount(&loopdev.device_str(), mount_path, Some("-oro"))
|
util::mount(&loopdev.device_str(), mount_path, Some("-oro"))?;
|
||||||
|
|
||||||
|
Ok(ResourceMount::new_loop(mount_path, loopdev))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the path at which to mount this resource image.
|
// Return the path at which to mount this resource image.
|
||||||
@ -492,3 +501,50 @@ fn maybe_add_dir_entry(entry: DirEntry,
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ResourceMountType {
|
||||||
|
Unmounted,
|
||||||
|
Verity(String),
|
||||||
|
Loop(LoopDevice),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ResourceMount {
|
||||||
|
mountpoint: PathBuf,
|
||||||
|
mounttype: ResourceMountType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceMount {
|
||||||
|
fn new_verity(mountpoint: &Path, dev: String) -> ResourceMount {
|
||||||
|
Self::new(mountpoint, ResourceMountType::Verity(dev))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_loop(mountpoint: &Path, loopdev: LoopDevice) -> ResourceMount {
|
||||||
|
Self::new(mountpoint, ResourceMountType::Loop(loopdev))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(mountpoint: &Path, mounttype: ResourceMountType) -> ResourceMount {
|
||||||
|
let mountpoint = mountpoint.to_path_buf();
|
||||||
|
ResourceMount {
|
||||||
|
mountpoint, mounttype
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unmount(&mut self) -> Result<()> {
|
||||||
|
match self.mounttype {
|
||||||
|
ResourceMountType::Verity(ref dev) => {
|
||||||
|
util::umount(&self.mountpoint)?;
|
||||||
|
Verity::close_device(dev.as_str())?;
|
||||||
|
self.mounttype = ResourceMountType::Unmounted;
|
||||||
|
},
|
||||||
|
ResourceMountType::Loop(ref loopdev) => {
|
||||||
|
util::umount(&self.mountpoint)?;
|
||||||
|
loopdev.detach()?;
|
||||||
|
self.mounttype = ResourceMountType::Unmounted;
|
||||||
|
},
|
||||||
|
ResourceMountType::Unmounted => {
|
||||||
|
warn!("Resource image is already unmounted from {}", self.mountpoint.display());
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user