mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
l10n: port chmod for translation + add french
This commit is contained in:
parent
05eb7ee374
commit
d8ba6c01e4
5 changed files with 112 additions and 50 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2797,6 +2797,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"libc",
|
"libc",
|
||||||
|
"thiserror 2.0.12",
|
||||||
"uucore",
|
"uucore",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ path = "src/chmod.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
|
thiserror = { workspace = true }
|
||||||
uucore = { workspace = true, features = ["entries", "fs", "mode", "perms"] }
|
uucore = { workspace = true, features = ["entries", "fs", "mode", "perms"] }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
|
|
@ -4,3 +4,28 @@ chmod-usage = chmod [OPTION]... MODE[,MODE]... FILE...
|
||||||
chmod [OPTION]... OCTAL-MODE FILE...
|
chmod [OPTION]... OCTAL-MODE FILE...
|
||||||
chmod [OPTION]... --reference=RFILE FILE...
|
chmod [OPTION]... --reference=RFILE FILE...
|
||||||
chmod-after-help = Each MODE is of the form [ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+.
|
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})
|
||||||
|
|
33
src/uu/chmod/locales/fr-FR.ftl
Normal file
33
src/uu/chmod/locales/fr-FR.ftl
Normal 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})
|
|
@ -6,12 +6,14 @@
|
||||||
// spell-checker:ignore (ToDO) Chmoder cmode fmode fperm fref ugoa RFILE RFILE's
|
// spell-checker:ignore (ToDO) Chmoder cmode fmode fperm fref ugoa RFILE RFILE's
|
||||||
|
|
||||||
use clap::{Arg, ArgAction, Command};
|
use clap::{Arg, ArgAction, Command};
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::os::unix::fs::{MetadataExt, PermissionsExt};
|
use std::os::unix::fs::{MetadataExt, PermissionsExt};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use thiserror::Error;
|
||||||
use uucore::display::Quotable;
|
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::fs::display_permissions_unix;
|
||||||
use uucore::libc::mode_t;
|
use uucore::libc::mode_t;
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
|
@ -19,7 +21,25 @@ use uucore::mode;
|
||||||
use uucore::perms::{TraverseSymlinks, configure_symlink_and_recursion};
|
use uucore::perms::{TraverseSymlinks, configure_symlink_and_recursion};
|
||||||
use uucore::{format_usage, show, show_error};
|
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 {
|
mod options {
|
||||||
pub const HELP: &str = "help";
|
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) {
|
let fmode = match matches.get_one::<String>(options::REFERENCE) {
|
||||||
Some(fref) => match fs::metadata(fref) {
|
Some(fref) => match fs::metadata(fref) {
|
||||||
Ok(meta) => Some(meta.mode() & 0o7777),
|
Ok(meta) => Some(meta.mode() & 0o7777),
|
||||||
Err(err) => {
|
Err(_) => {
|
||||||
return Err(USimpleError::new(
|
return Err(ChmodError::CannotStat(fref.to_string()).into());
|
||||||
1,
|
|
||||||
format!("cannot stat attributes of {}: {err}", fref.quote()),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => None,
|
None => None,
|
||||||
|
@ -135,7 +152,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if files.is_empty() {
|
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) =
|
let (recursive, dereference, traverse_symlinks) =
|
||||||
|
@ -168,14 +188,14 @@ pub fn uu_app() -> Command {
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::HELP)
|
Arg::new(options::HELP)
|
||||||
.long(options::HELP)
|
.long(options::HELP)
|
||||||
.help("Print help information.")
|
.help(get_message("chmod-help-print-help"))
|
||||||
.action(ArgAction::Help),
|
.action(ArgAction::Help),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::CHANGES)
|
Arg::new(options::CHANGES)
|
||||||
.long(options::CHANGES)
|
.long(options::CHANGES)
|
||||||
.short('c')
|
.short('c')
|
||||||
.help("like verbose but report only when a change is made")
|
.help(get_message("chmod-help-changes"))
|
||||||
.action(ArgAction::SetTrue),
|
.action(ArgAction::SetTrue),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
|
@ -183,40 +203,40 @@ pub fn uu_app() -> Command {
|
||||||
.long(options::QUIET)
|
.long(options::QUIET)
|
||||||
.visible_alias("silent")
|
.visible_alias("silent")
|
||||||
.short('f')
|
.short('f')
|
||||||
.help("suppress most error messages")
|
.help(get_message("chmod-help-quiet"))
|
||||||
.action(ArgAction::SetTrue),
|
.action(ArgAction::SetTrue),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::VERBOSE)
|
Arg::new(options::VERBOSE)
|
||||||
.long(options::VERBOSE)
|
.long(options::VERBOSE)
|
||||||
.short('v')
|
.short('v')
|
||||||
.help("output a diagnostic for every file processed")
|
.help(get_message("chmod-help-verbose"))
|
||||||
.action(ArgAction::SetTrue),
|
.action(ArgAction::SetTrue),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::NO_PRESERVE_ROOT)
|
Arg::new(options::NO_PRESERVE_ROOT)
|
||||||
.long(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),
|
.action(ArgAction::SetTrue),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::PRESERVE_ROOT)
|
Arg::new(options::PRESERVE_ROOT)
|
||||||
.long(options::PRESERVE_ROOT)
|
.long(options::PRESERVE_ROOT)
|
||||||
.help("fail to operate recursively on '/'")
|
.help(get_message("chmod-help-preserve-root"))
|
||||||
.action(ArgAction::SetTrue),
|
.action(ArgAction::SetTrue),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::RECURSIVE)
|
Arg::new(options::RECURSIVE)
|
||||||
.long(options::RECURSIVE)
|
.long(options::RECURSIVE)
|
||||||
.short('R')
|
.short('R')
|
||||||
.help("change files and directories recursively")
|
.help(get_message("chmod-help-recursive"))
|
||||||
.action(ArgAction::SetTrue),
|
.action(ArgAction::SetTrue),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::REFERENCE)
|
Arg::new(options::REFERENCE)
|
||||||
.long("reference")
|
.long("reference")
|
||||||
.value_hint(clap::ValueHint::FilePath)
|
.value_hint(clap::ValueHint::FilePath)
|
||||||
.help("use RFILE's mode instead of MODE values"),
|
.help(get_message("chmod-help-reference")),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::MODE).required_unless_present(options::REFERENCE),
|
Arg::new(options::MODE).required_unless_present(options::REFERENCE),
|
||||||
|
@ -265,27 +285,21 @@ impl Chmoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.quiet {
|
if !self.quiet {
|
||||||
show!(USimpleError::new(
|
show!(ChmodError::DanglingSymlink(filename.to_string()));
|
||||||
1,
|
|
||||||
format!("cannot operate on dangling symlink {}", filename.quote()),
|
|
||||||
));
|
|
||||||
set_exit_code(1);
|
set_exit_code(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.verbose {
|
if self.verbose {
|
||||||
println!(
|
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 {
|
} else if !self.quiet {
|
||||||
show!(USimpleError::new(
|
show!(ChmodError::NoSuchFile(filename.to_string()));
|
||||||
1,
|
|
||||||
format!(
|
|
||||||
"cannot access {}: No such file or directory",
|
|
||||||
filename.quote()
|
|
||||||
)
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
// GNU exits with exit code 1 even if -q or --quiet are passed
|
// 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.
|
// 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;
|
continue;
|
||||||
}
|
}
|
||||||
if self.recursive && self.preserve_root && filename == "/" {
|
if self.recursive && self.preserve_root && filename == "/" {
|
||||||
return Err(USimpleError::new(
|
return Err(ChmodError::PreserveRoot(filename.to_string()).into());
|
||||||
1,
|
|
||||||
format!(
|
|
||||||
"it is dangerous to operate recursively on {}\nchmod: use --no-preserve-root to override this failsafe",
|
|
||||||
filename.quote()
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
if self.recursive {
|
if self.recursive {
|
||||||
r = self.walk_dir(file);
|
r = self.walk_dir(file);
|
||||||
|
@ -368,12 +376,9 @@ impl Chmoder {
|
||||||
} else if err.kind() == std::io::ErrorKind::PermissionDenied {
|
} else if err.kind() == std::io::ErrorKind::PermissionDenied {
|
||||||
// These two filenames would normally be conditionally
|
// These two filenames would normally be conditionally
|
||||||
// quoted, but GNU's tests expect them to always be quoted
|
// quoted, but GNU's tests expect them to always be quoted
|
||||||
Err(USimpleError::new(
|
Err(ChmodError::PermissionDenied(file.to_string_lossy().to_string()).into())
|
||||||
1,
|
|
||||||
format!("{}: Permission denied", file.quote()),
|
|
||||||
))
|
|
||||||
} else {
|
} 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)?;
|
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 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 {
|
if (new_mode & !naively_expected_new_mode) != 0 {
|
||||||
return Err(USimpleError::new(
|
return Err(ChmodError::NewPermissions(
|
||||||
1,
|
file.to_string_lossy().to_string(),
|
||||||
format!(
|
|
||||||
"{}: new permissions are {}, not {}",
|
|
||||||
file.maybe_quote(),
|
|
||||||
display_permissions_unix(new_mode as mode_t, false),
|
display_permissions_unix(new_mode as mode_t, false),
|
||||||
display_permissions_unix(naively_expected_new_mode as mode_t, false)
|
display_permissions_unix(naively_expected_new_mode as mode_t, false),
|
||||||
),
|
)
|
||||||
));
|
.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue