mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
install: add missing directory chown
* Re-factor the copy function chown into a function that can be re-used. * Fix bug where the group overwrote the user. * Add chown compatibility to follow GNU coreutils. * Reduce two chown calls to a single syscall only when needed. * Fixes #4361
This commit is contained in:
parent
ae65abe4a5
commit
5876cd2581
1 changed files with 59 additions and 60 deletions
|
@ -466,6 +466,8 @@ fn directory(paths: &[String], b: &Behavior) -> UResult<()> {
|
|||
uucore::error::set_exit_code(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
chown_optional_user_group(path, b)?;
|
||||
}
|
||||
// If the exit code was set, or show! has been called at least once
|
||||
// (which sets the exit code as well), function execution will end after
|
||||
|
@ -626,6 +628,62 @@ fn copy_files_into_dir(files: &[PathBuf], target_dir: &Path, b: &Behavior) -> UR
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Handle incomplete user/group parings for chown.
|
||||
///
|
||||
/// Returns a Result type with the Err variant containing the error message.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// _path_ must exist.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If the owner or group are invalid or copy system call fails, we print a verbose error and
|
||||
/// return an empty error value.
|
||||
///
|
||||
fn chown_optional_user_group(path: &Path, b: &Behavior) -> UResult<()> {
|
||||
let owner = if !b.owner.is_empty() {
|
||||
match usr2uid(&b.owner) {
|
||||
Ok(u) => Some(u),
|
||||
_ => return Err(InstallError::NoSuchUser(b.owner.clone()).into()),
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let group = if !b.group.is_empty() {
|
||||
match grp2gid(&b.group) {
|
||||
Ok(g) => Some(g),
|
||||
_ => return Err(InstallError::NoSuchGroup(b.group.clone()).into()),
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let meta = match fs::metadata(path) {
|
||||
Ok(meta) => meta,
|
||||
Err(e) => return Err(InstallError::MetadataFailed(e).into()),
|
||||
};
|
||||
|
||||
let verbosity = Verbosity {
|
||||
groups_only: owner.is_none(),
|
||||
level: VerbosityLevel::Normal,
|
||||
};
|
||||
|
||||
if owner.is_some() || group.is_some() {
|
||||
match wrap_chown(path, &meta, owner, group, false, verbosity) {
|
||||
Ok(n) => {
|
||||
if !n.is_empty() {
|
||||
show_error!("{}", n);
|
||||
}
|
||||
}
|
||||
Err(e) => show_error!("{}", e),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Copy one file to a new location, changing metadata.
|
||||
///
|
||||
/// Returns a Result type with the Err variant containing the error message.
|
||||
|
@ -708,66 +766,7 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> UResult<()> {
|
|||
return Err(InstallError::ChmodFailed(to.to_path_buf()).into());
|
||||
}
|
||||
|
||||
if !b.owner.is_empty() {
|
||||
let meta = match fs::metadata(to) {
|
||||
Ok(meta) => meta,
|
||||
Err(e) => return Err(InstallError::MetadataFailed(e).into()),
|
||||
};
|
||||
|
||||
let owner_id = match usr2uid(&b.owner) {
|
||||
Ok(g) => g,
|
||||
_ => return Err(InstallError::NoSuchUser(b.owner.clone()).into()),
|
||||
};
|
||||
let gid = meta.gid();
|
||||
match wrap_chown(
|
||||
to,
|
||||
&meta,
|
||||
Some(owner_id),
|
||||
Some(gid),
|
||||
false,
|
||||
Verbosity {
|
||||
groups_only: false,
|
||||
level: VerbosityLevel::Normal,
|
||||
},
|
||||
) {
|
||||
Ok(n) => {
|
||||
if !n.is_empty() {
|
||||
show_error!("{}", n);
|
||||
}
|
||||
}
|
||||
Err(e) => show_error!("{}", e),
|
||||
}
|
||||
}
|
||||
|
||||
if !b.group.is_empty() {
|
||||
let meta = match fs::metadata(to) {
|
||||
Ok(meta) => meta,
|
||||
Err(e) => return Err(InstallError::MetadataFailed(e).into()),
|
||||
};
|
||||
|
||||
let group_id = match grp2gid(&b.group) {
|
||||
Ok(g) => g,
|
||||
_ => return Err(InstallError::NoSuchGroup(b.group.clone()).into()),
|
||||
};
|
||||
match wrap_chown(
|
||||
to,
|
||||
&meta,
|
||||
Some(group_id),
|
||||
None,
|
||||
false,
|
||||
Verbosity {
|
||||
groups_only: true,
|
||||
level: VerbosityLevel::Normal,
|
||||
},
|
||||
) {
|
||||
Ok(n) => {
|
||||
if !n.is_empty() {
|
||||
show_error!("{}", n);
|
||||
}
|
||||
}
|
||||
Err(e) => show_error!("{}", e),
|
||||
}
|
||||
}
|
||||
chown_optional_user_group(to, b)?;
|
||||
|
||||
if b.preserve_timestamps {
|
||||
let meta = match fs::metadata(from) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue