mirror of
https://github.com/uutils/coreutils.git
synced 2025-12-23 08:47:37 +00:00
chmod: fix handling of non-UTF-8 filenames
This commit is contained in:
parent
c00c92ccc6
commit
1cfb30ecb3
1 changed files with 19 additions and 15 deletions
|
|
@ -119,11 +119,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
let quiet = matches.get_flag(options::QUIET);
|
||||
let verbose = matches.get_flag(options::VERBOSE);
|
||||
let preserve_root = matches.get_flag(options::PRESERVE_ROOT);
|
||||
let fmode = match matches.get_one::<String>(options::REFERENCE) {
|
||||
let fmode = match matches.get_one::<OsString>(options::REFERENCE) {
|
||||
Some(fref) => match fs::metadata(fref) {
|
||||
Ok(meta) => Some(meta.mode() & 0o7777),
|
||||
Err(_) => {
|
||||
return Err(ChmodError::CannotStat(fref.to_string()).into());
|
||||
return Err(ChmodError::CannotStat(fref.to_string_lossy().to_string()).into());
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
|
|
@ -135,16 +135,15 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
} else {
|
||||
modes.unwrap().to_string() // modes is required
|
||||
};
|
||||
// FIXME: enable non-utf8 paths
|
||||
let mut files: Vec<String> = matches
|
||||
.get_many::<String>(options::FILE)
|
||||
.map(|v| v.map(ToString::to_string).collect())
|
||||
let mut files: Vec<OsString> = matches
|
||||
.get_many::<OsString>(options::FILE)
|
||||
.map(|v| v.cloned().collect())
|
||||
.unwrap_or_default();
|
||||
let cmode = if fmode.is_some() {
|
||||
// "--reference" and MODE are mutually exclusive
|
||||
// if "--reference" was used MODE needs to be interpreted as another FILE
|
||||
// it wasn't possible to implement this behavior directly with clap
|
||||
files.push(cmode);
|
||||
files.push(OsString::from(cmode));
|
||||
None
|
||||
} else {
|
||||
Some(cmode)
|
||||
|
|
@ -236,6 +235,7 @@ pub fn uu_app() -> Command {
|
|||
Arg::new(options::REFERENCE)
|
||||
.long("reference")
|
||||
.value_hint(clap::ValueHint::FilePath)
|
||||
.value_parser(clap::value_parser!(OsString))
|
||||
.help(translate!("chmod-help-reference")),
|
||||
)
|
||||
.arg(
|
||||
|
|
@ -248,7 +248,8 @@ pub fn uu_app() -> Command {
|
|||
Arg::new(options::FILE)
|
||||
.required_unless_present(options::MODE)
|
||||
.action(ArgAction::Append)
|
||||
.value_hint(clap::ValueHint::AnyPath),
|
||||
.value_hint(clap::ValueHint::AnyPath)
|
||||
.value_parser(clap::value_parser!(OsString)),
|
||||
)
|
||||
// Add common arguments with chgrp, chown & chmod
|
||||
.args(uucore::perms::common_args())
|
||||
|
|
@ -267,11 +268,10 @@ struct Chmoder {
|
|||
}
|
||||
|
||||
impl Chmoder {
|
||||
fn chmod(&self, files: &[String]) -> UResult<()> {
|
||||
fn chmod(&self, files: &[OsString]) -> UResult<()> {
|
||||
let mut r = Ok(());
|
||||
|
||||
for filename in files {
|
||||
let filename = &filename[..];
|
||||
let file = Path::new(filename);
|
||||
if !file.exists() {
|
||||
if file.is_symlink() {
|
||||
|
|
@ -285,18 +285,22 @@ impl Chmoder {
|
|||
}
|
||||
|
||||
if !self.quiet {
|
||||
show!(ChmodError::DanglingSymlink(filename.to_string()));
|
||||
show!(ChmodError::DanglingSymlink(
|
||||
filename.to_string_lossy().to_string()
|
||||
));
|
||||
set_exit_code(1);
|
||||
}
|
||||
|
||||
if self.verbose {
|
||||
println!(
|
||||
"{}",
|
||||
translate!("chmod-verbose-failed-dangling", "file" => filename.quote())
|
||||
translate!("chmod-verbose-failed-dangling", "file" => filename.to_string_lossy().quote())
|
||||
);
|
||||
}
|
||||
} else if !self.quiet {
|
||||
show!(ChmodError::NoSuchFile(filename.to_string()));
|
||||
show!(ChmodError::NoSuchFile(
|
||||
filename.to_string_lossy().to_string()
|
||||
));
|
||||
}
|
||||
// GNU exits with exit code 1 even if -q or --quiet are passed
|
||||
// So we set the exit code, because it hasn't been set yet if `self.quiet` is true.
|
||||
|
|
@ -308,8 +312,8 @@ impl Chmoder {
|
|||
// should not change the permissions in this case
|
||||
continue;
|
||||
}
|
||||
if self.recursive && self.preserve_root && filename == "/" {
|
||||
return Err(ChmodError::PreserveRoot(filename.to_string()).into());
|
||||
if self.recursive && self.preserve_root && file == Path::new("/") {
|
||||
return Err(ChmodError::PreserveRoot("/".to_string()).into());
|
||||
}
|
||||
if self.recursive {
|
||||
r = self.walk_dir_with_context(file, true);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue