diff --git a/src/uu/chmod/locales/en-US.ftl b/src/uu/chmod/locales/en-US.ftl index 2f3f6748461..fb8350a797b 100644 --- a/src/uu/chmod/locales/en-US.ftl +++ b/src/uu/chmod/locales/en-US.ftl @@ -4,7 +4,6 @@ chmod-usage = chmod [OPTION]... MODE[,MODE]... FILE... chmod [OPTION]... OCTAL-MODE FILE... chmod [OPTION]... --reference=RFILE FILE... chmod-after-help = Each MODE is of the form [ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+. -chmod-error-cannot-stat = cannot stat attributes of {$file} chmod-error-dangling-symlink = cannot operate on dangling symlink {$file} chmod-error-no-such-file = cannot access {$file}: No such file or directory chmod-error-preserve-root = it is dangerous to operate recursively on {$file} @@ -15,6 +14,7 @@ chmod-error-permission-denied = cannot access {$file}: Permission denied chmod-error-new-permissions = {$file}: new permissions are {$actual}, not {$expected} chmod-error-changing-permissions = changing permissions of {$file}: {$err} chmod-error-missing-operand = missing operand +chmod-error-reference-stat = failed to get attributes of { $file }: { $error } # Help messages chmod-help-print-help = Print help information. diff --git a/src/uu/chmod/locales/fr-FR.ftl b/src/uu/chmod/locales/fr-FR.ftl index e8116f08f9c..bd43442b63c 100644 --- a/src/uu/chmod/locales/fr-FR.ftl +++ b/src/uu/chmod/locales/fr-FR.ftl @@ -16,7 +16,6 @@ chmod-help-recursive = changer les fichiers et répertoires récursivement chmod-help-reference = utiliser le mode de RFICHIER au lieu des valeurs de MODE # Messages d'erreur -chmod-error-cannot-stat = impossible d'obtenir les attributs de {$file} chmod-error-dangling-symlink = impossible d'opérer sur le lien symbolique pendouillant {$file} chmod-error-no-such-file = impossible d'accéder à {$file} : Aucun fichier ou répertoire de ce type chmod-error-preserve-root = il est dangereux d'opérer récursivement sur {$file} @@ -27,6 +26,7 @@ chmod-error-permission-denied = impossible d'accéder à {$file} : Permission re chmod-error-new-permissions = {$file} : les nouvelles permissions sont {$actual}, pas {$expected} chmod-error-changing-permissions = changement des permissions de {$file} : {$err} chmod-error-missing-operand = opérande manquant +chmod-error-reference-stat = impossible d'obtenir les attributs de { $file } : { $error } # Messages verbeux/de statut chmod-verbose-failed-dangling = échec du changement de mode de {$file} de 0000 (---------) vers 1500 (r-x-----T) diff --git a/src/uu/chmod/src/chmod.rs b/src/uu/chmod/src/chmod.rs index f586ef8a681..80d96e855c7 100644 --- a/src/uu/chmod/src/chmod.rs +++ b/src/uu/chmod/src/chmod.rs @@ -29,8 +29,10 @@ use uucore::translate; #[derive(Debug, thiserror::Error)] enum ChmodError { - #[error("{}", translate!("chmod-error-cannot-stat", "file" => _0.quote()))] - CannotStat(PathBuf), + #[error("{}", translate!("perms-cannot-access", "file" => _0.quote(), "error" => strip_errno(_1)))] + CannotStat(PathBuf, std::io::Error), + #[error("{}", translate!("chmod-error-reference-stat", "file" => _0.quote(), "error" => strip_errno(_1)))] + ReferenceStat(PathBuf, std::io::Error), #[error("{}", translate!("chmod-error-dangling-symlink", "file" => _0.quote()))] DanglingSymlink(PathBuf), #[error("{}", translate!("chmod-error-no-such-file", "file" => _0.quote()))] @@ -150,7 +152,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { Some(fref) => Some( fs::metadata(fref) .map(|meta| meta.mode() & 0o7777) - .map_err(|_| ChmodError::CannotStat(fref.into()))?, + .map_err(|err| ChmodError::ReferenceStat(fref.into(), err))?, ), None => None, }; @@ -817,7 +819,7 @@ impl Chmoder { } else if err.kind() == std::io::ErrorKind::PermissionDenied { Err(ChmodError::PermissionDenied(file.into()).into()) } else { - Err(ChmodError::CannotStat(file.into()).into()) + Err(ChmodError::CannotStat(file.into(), err).into()) }; } }; diff --git a/tests/by-util/test_chmod.rs b/tests/by-util/test_chmod.rs index f4e07d9bdbf..01052cf6c2c 100644 --- a/tests/by-util/test_chmod.rs +++ b/tests/by-util/test_chmod.rs @@ -1865,3 +1865,35 @@ mod diagnostics { .no_output(); } } + +#[test] +fn test_overlong_path_reports_os_error_and_continues() { + let ts = TestScenario::new(util_name!()); + ts.fixtures.touch("valid"); + // Every component exists, but the unnormalized operand exceeds PATH_MAX. + let path = "./".repeat(4096); + let error = uucore::error::strip_errno(&std::io::Error::from_raw_os_error(libc::ENAMETOOLONG)); + for flags in [vec![], vec!["-R"]] { + set_permissions(ts.fixtures.plus("valid"), Permissions::from_mode(0o600)).unwrap(); + let result = ts + .ucmd() + .args(&flags) + .arg("700") + .arg(&path) + .arg("valid") + .fails_with_code(1); + result.stderr_is(format!("chmod: cannot access '{path}': {error}\n")); + assert_eq!( + ts.fixtures.metadata("valid").permissions().mode() & 0o777, + 0o700 + ); + } + ts.ucmd() + .arg("--reference") + .arg(&path) + .arg("valid") + .fails_with_code(1) + .stderr_is(format!( + "chmod: failed to get attributes of '{path}': {error}\n" + )); +}