Skip to content

Commit

Permalink
install: correctly detect DASDs if they're behind a symlink
Browse files Browse the repository at this point in the history
  • Loading branch information
bgilbert committed Jul 8, 2020
1 parent 4018f68 commit 4501977
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 17 deletions.
27 changes: 12 additions & 15 deletions src/blockdev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use nix::{errno::Errno, mount};
use regex::Regex;
use std::collections::HashMap;
use std::convert::TryInto;
use std::fs::{metadata, read_dir, read_link, read_to_string, remove_dir, File, OpenOptions};
use std::fs::{metadata, read_dir, read_to_string, remove_dir, File, OpenOptions};
use std::num::{NonZeroU32, NonZeroU64};
use std::os::linux::fs::MetadataExt;
use std::os::raw::c_int;
Expand All @@ -30,6 +30,7 @@ use std::thread::sleep;
use std::time::Duration;

use crate::errors::*;
use crate::io::resolve_link;

#[derive(Debug)]
pub struct Disk {
Expand Down Expand Up @@ -374,21 +375,17 @@ impl Partition {
// Now assume a kpartx "partition", where the path is a symlink to
// an unpartitioned DM device node.
// /sys/block/dm-1
match read_link(Path::new(&self.path)) {
Ok(target) => {
let devdir = basedir.join(
Path::new(&target)
.file_name()
.chain_err(|| format!("target {} has no filename", self.path))?,
);
if devdir.exists() {
return Ok(devdir);
}
let (target, is_link) = resolve_link(&self.path)?;
if is_link {
let devdir = basedir.join(
target
.file_name()
.chain_err(|| format!("target {} has no filename", target.display()))?,
);
if devdir.exists() {
return Ok(devdir);
}
// ignore if not symlink
Err(e) if e.kind() == std::io::ErrorKind::InvalidInput => (),
Err(e) => return Err(e).chain_err(|| format!("reading link {}", self.path)),
};
}

// Give up
bail!(
Expand Down
9 changes: 7 additions & 2 deletions src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub fn install(config: &InstallConfig) -> Result<()> {
}
}

if config.device.starts_with("/dev/dasd") {
if is_dasd(config)? {
#[cfg(target_arch = "s390x")]
s390x::prepare_dasd(&config)?;
}
Expand Down Expand Up @@ -186,7 +186,7 @@ fn write_disk(
let sector_size = get_sector_size(dest)?;

// copy the image
let image_copy = if config.device.starts_with("/dev/dasd") {
let image_copy = if is_dasd(config)? {
#[cfg(target_arch = "s390x")]
{
s390x::image_copy_s390x
Expand Down Expand Up @@ -485,6 +485,11 @@ fn clear_partition_table(dest: &mut File, table: &mut dyn PartTable) -> Result<(
Ok(())
}

fn is_dasd(config: &InstallConfig) -> Result<bool> {
let (target, _) = resolve_link(&config.device)?;
Ok(target.to_string_lossy().starts_with("/dev/dasd"))
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
13 changes: 13 additions & 0 deletions src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
// limitations under the License.

use error_chain::bail;
use std::fs::read_link;
use std::io::{ErrorKind, Read, Write};
use std::path::{Path, PathBuf};

use crate::errors::*;

Expand Down Expand Up @@ -76,3 +78,14 @@ pub fn copy_exactly_n(
}
Ok(n)
}

// If path is a symlink, resolve it and return (target, true)
// If not, return (path, false)
pub fn resolve_link<P: AsRef<Path>>(path: P) -> Result<(PathBuf, bool)> {
let path = path.as_ref();
match read_link(path) {
Ok(target) => Ok((target, true)),
Err(e) if e.kind() == std::io::ErrorKind::InvalidInput => Ok((path.to_path_buf(), false)),
Err(e) => Err(e).chain_err(|| format!("reading link {}", path.display())),
}
}

0 comments on commit 4501977

Please sign in to comment.