1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-27 19:17:43 +00:00

l10n: port chmod for translation + add french

This commit is contained in:
Sylvestre Ledru 2025-06-22 18:13:06 +02:00 committed by Sylvestre Ledru
parent 05eb7ee374
commit d8ba6c01e4
5 changed files with 112 additions and 50 deletions

1
Cargo.lock generated
View file

@ -2797,6 +2797,7 @@ version = "0.1.0"
dependencies = [
"clap",
"libc",
"thiserror 2.0.12",
"uucore",
]

View file

@ -20,6 +20,7 @@ path = "src/chmod.rs"
[dependencies]
clap = { workspace = true }
libc = { workspace = true }
thiserror = { workspace = true }
uucore = { workspace = true, features = ["entries", "fs", "mode", "perms"] }
[[bin]]

View file

@ -4,3 +4,28 @@ 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}
chmod: use --no-preserve-root to override this failsafe
chmod-error-permission-denied = {$file}: Permission denied
chmod-error-new-permissions = {$file}: new permissions are {$actual}, not {$expected}
chmod-error-missing-operand = missing operand
# Help messages
chmod-help-print-help = Print help information.
chmod-help-changes = like verbose but report only when a change is made
chmod-help-quiet = suppress most error messages
chmod-help-verbose = output a diagnostic for every file processed
chmod-help-no-preserve-root = do not treat '/' specially (the default)
chmod-help-preserve-root = fail to operate recursively on '/'
chmod-help-recursive = change files and directories recursively
chmod-help-reference = use RFILE's mode instead of MODE values
# Verbose messages
chmod-verbose-failed-dangling = failed to change mode of {$file} from 0000 (---------) to 1500 (r-x-----T)
chmod-verbose-neither-changed = neither symbolic link {$file} nor referent has been changed
chmod-verbose-mode-retained = mode of {$file} retained as {$mode_octal} ({$mode_display})
chmod-verbose-failed-change = failed to change mode of file {$file} from {$old_mode} ({$old_mode_display}) to {$new_mode} ({$new_mode_display})
chmod-verbose-mode-changed = mode of {$file} changed from {$old_mode} ({$old_mode_display}) to {$new_mode} ({$new_mode_display})

View file

@ -0,0 +1,33 @@
chmod-about = Changer le mode de chaque FICHIER vers MODE.
Avec --reference, changer le mode de chaque FICHIER vers celui de RFICHIER.
chmod-usage = chmod [OPTION]... MODE[,MODE]... FICHIER...
chmod [OPTION]... MODE-OCTAL FICHIER...
chmod [OPTION]... --reference=RFICHIER FICHIER...
chmod-after-help = Chaque MODE est de la forme [ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+.
# Messages d'aide
chmod-help-print-help = Afficher les informations d'aide.
chmod-help-changes = comme verbeux mais rapporter seulement lors d'un changement
chmod-help-quiet = supprimer la plupart des messages d'erreur
chmod-help-verbose = afficher un diagnostic pour chaque fichier traité
chmod-help-no-preserve-root = ne pas traiter '/' spécialement (par défaut)
chmod-help-preserve-root = échouer à opérer récursivement sur '/'
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 dossier de ce type
chmod-error-preserve-root = il est dangereux d'opérer récursivement sur {$file}
chmod: utiliser --no-preserve-root pour outrepasser cette protection
chmod-error-permission-denied = {$file} : Permission refusée
chmod-error-new-permissions = {$file} : les nouvelles permissions sont {$actual}, pas {$expected}
chmod-error-missing-operand = opérande manquant
# Messages verbeux/de statut
chmod-verbose-failed-dangling = échec du changement de mode de {$file} de 0000 (---------) vers 1500 (r-x-----T)
chmod-verbose-neither-changed = ni le lien symbolique {$file} ni la référence n'ont été changés
chmod-verbose-mode-retained = mode de {$file} conservé comme {$mode_octal} ({$mode_display})
chmod-verbose-failed-change = échec du changement de mode du fichier {$file} de {$old_mode} ({$old_mode_display}) vers {$new_mode} ({$new_mode_display})
chmod-verbose-mode-changed = mode de {$file} changé de {$old_mode} ({$old_mode_display}) vers {$new_mode} ({$new_mode_display})

View file

@ -6,12 +6,14 @@
// spell-checker:ignore (ToDO) Chmoder cmode fmode fperm fref ugoa RFILE RFILE's
use clap::{Arg, ArgAction, Command};
use std::collections::HashMap;
use std::ffi::OsString;
use std::fs;
use std::os::unix::fs::{MetadataExt, PermissionsExt};
use std::path::Path;
use thiserror::Error;
use uucore::display::Quotable;
use uucore::error::{ExitCode, UResult, USimpleError, UUsageError, set_exit_code};
use uucore::error::{ExitCode, UError, UResult, USimpleError, UUsageError, set_exit_code};
use uucore::fs::display_permissions_unix;
use uucore::libc::mode_t;
#[cfg(not(windows))]
@ -19,7 +21,25 @@ use uucore::mode;
use uucore::perms::{TraverseSymlinks, configure_symlink_and_recursion};
use uucore::{format_usage, show, show_error};
use uucore::locale::get_message;
use uucore::locale::{get_message, get_message_with_args};
#[derive(Debug, Error)]
enum ChmodError {
#[error("{}", get_message_with_args("chmod-error-cannot-stat", HashMap::from([("file".to_string(), _0.quote().to_string())])))]
CannotStat(String),
#[error("{}", get_message_with_args("chmod-error-dangling-symlink", HashMap::from([("file".to_string(), _0.quote().to_string())])))]
DanglingSymlink(String),
#[error("{}", get_message_with_args("chmod-error-no-such-file", HashMap::from([("file".to_string(), _0.quote().to_string())])))]
NoSuchFile(String),
#[error("{}", get_message_with_args("chmod-error-preserve-root", HashMap::from([("file".to_string(), _0.quote().to_string())])))]
PreserveRoot(String),
#[error("{}", get_message_with_args("chmod-error-permission-denied", HashMap::from([("file".to_string(), _0.quote().to_string())])))]
PermissionDenied(String),
#[error("{}", get_message_with_args("chmod-error-new-permissions", HashMap::from([("file".to_string(), _0.clone()), ("actual".to_string(), _1.clone()), ("expected".to_string(), _2.clone())])))]
NewPermissions(String, String, String),
}
impl UError for ChmodError {}
mod options {
pub const HELP: &str = "help";
@ -103,11 +123,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let fmode = match matches.get_one::<String>(options::REFERENCE) {
Some(fref) => match fs::metadata(fref) {
Ok(meta) => Some(meta.mode() & 0o7777),
Err(err) => {
return Err(USimpleError::new(
1,
format!("cannot stat attributes of {}: {err}", fref.quote()),
));
Err(_) => {
return Err(ChmodError::CannotStat(fref.to_string()).into());
}
},
None => None,
@ -135,7 +152,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
};
if files.is_empty() {
return Err(UUsageError::new(1, "missing operand".to_string()));
return Err(UUsageError::new(
1,
get_message("chmod-error-missing-operand"),
));
}
let (recursive, dereference, traverse_symlinks) =
@ -168,14 +188,14 @@ pub fn uu_app() -> Command {
.arg(
Arg::new(options::HELP)
.long(options::HELP)
.help("Print help information.")
.help(get_message("chmod-help-print-help"))
.action(ArgAction::Help),
)
.arg(
Arg::new(options::CHANGES)
.long(options::CHANGES)
.short('c')
.help("like verbose but report only when a change is made")
.help(get_message("chmod-help-changes"))
.action(ArgAction::SetTrue),
)
.arg(
@ -183,40 +203,40 @@ pub fn uu_app() -> Command {
.long(options::QUIET)
.visible_alias("silent")
.short('f')
.help("suppress most error messages")
.help(get_message("chmod-help-quiet"))
.action(ArgAction::SetTrue),
)
.arg(
Arg::new(options::VERBOSE)
.long(options::VERBOSE)
.short('v')
.help("output a diagnostic for every file processed")
.help(get_message("chmod-help-verbose"))
.action(ArgAction::SetTrue),
)
.arg(
Arg::new(options::NO_PRESERVE_ROOT)
.long(options::NO_PRESERVE_ROOT)
.help("do not treat '/' specially (the default)")
.help(get_message("chmod-help-no-preserve-root"))
.action(ArgAction::SetTrue),
)
.arg(
Arg::new(options::PRESERVE_ROOT)
.long(options::PRESERVE_ROOT)
.help("fail to operate recursively on '/'")
.help(get_message("chmod-help-preserve-root"))
.action(ArgAction::SetTrue),
)
.arg(
Arg::new(options::RECURSIVE)
.long(options::RECURSIVE)
.short('R')
.help("change files and directories recursively")
.help(get_message("chmod-help-recursive"))
.action(ArgAction::SetTrue),
)
.arg(
Arg::new(options::REFERENCE)
.long("reference")
.value_hint(clap::ValueHint::FilePath)
.help("use RFILE's mode instead of MODE values"),
.help(get_message("chmod-help-reference")),
)
.arg(
Arg::new(options::MODE).required_unless_present(options::REFERENCE),
@ -265,27 +285,21 @@ impl Chmoder {
}
if !self.quiet {
show!(USimpleError::new(
1,
format!("cannot operate on dangling symlink {}", filename.quote()),
));
show!(ChmodError::DanglingSymlink(filename.to_string()));
set_exit_code(1);
}
if self.verbose {
println!(
"failed to change mode of {} from 0000 (---------) to 1500 (r-x-----T)",
filename.quote()
"{}",
get_message_with_args(
"chmod-verbose-failed-dangling",
HashMap::from([("file".to_string(), filename.quote().to_string())])
)
);
}
} else if !self.quiet {
show!(USimpleError::new(
1,
format!(
"cannot access {}: No such file or directory",
filename.quote()
)
));
show!(ChmodError::NoSuchFile(filename.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.
@ -298,13 +312,7 @@ impl Chmoder {
continue;
}
if self.recursive && self.preserve_root && filename == "/" {
return Err(USimpleError::new(
1,
format!(
"it is dangerous to operate recursively on {}\nchmod: use --no-preserve-root to override this failsafe",
filename.quote()
),
));
return Err(ChmodError::PreserveRoot(filename.to_string()).into());
}
if self.recursive {
r = self.walk_dir(file);
@ -368,12 +376,9 @@ impl Chmoder {
} else if err.kind() == std::io::ErrorKind::PermissionDenied {
// These two filenames would normally be conditionally
// quoted, but GNU's tests expect them to always be quoted
Err(USimpleError::new(
1,
format!("{}: Permission denied", file.quote()),
))
Err(ChmodError::PermissionDenied(file.to_string_lossy().to_string()).into())
} else {
Err(USimpleError::new(1, format!("{}: {err}", file.quote())))
Err(ChmodError::CannotStat(file.to_string_lossy().to_string()).into())
};
}
};
@ -420,15 +425,12 @@ impl Chmoder {
self.change_file(fperm, new_mode, file)?;
// if a permission would have been removed if umask was 0, but it wasn't because umask was not 0, print an error and fail
if (new_mode & !naively_expected_new_mode) != 0 {
return Err(USimpleError::new(
1,
format!(
"{}: new permissions are {}, not {}",
file.maybe_quote(),
display_permissions_unix(new_mode as mode_t, false),
display_permissions_unix(naively_expected_new_mode as mode_t, false)
),
));
return Err(ChmodError::NewPermissions(
file.to_string_lossy().to_string(),
display_permissions_unix(new_mode as mode_t, false),
display_permissions_unix(naively_expected_new_mode as mode_t, false),
)
.into());
}
}
}