mirror of
https://github.com/systemd/systemd
synced 2025-09-27 15:54:47 +02:00
Compare commits
7 Commits
65ab27211c
...
414cbc3c73
Author | SHA1 | Date | |
---|---|---|---|
![]() |
414cbc3c73 | ||
![]() |
cb2ae9f8b9 | ||
![]() |
4327574fc1 | ||
![]() |
ef4a91a7e8 | ||
![]() |
42e15a6f1a | ||
![]() |
8f20232fcb | ||
![]() |
bd47b0dac4 |
@ -1849,17 +1849,34 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-i</option></term>
|
||||
<term><option>--ignore-inhibitors</option></term>
|
||||
<term><option>--check-inhibitors=</option></term>
|
||||
|
||||
<listitem>
|
||||
<para>When system shutdown or a sleep state is requested, ignore inhibitor locks. Applications can establish
|
||||
inhibitor locks to avoid that certain important operations (such as CD burning or suchlike) are interrupted
|
||||
by system shutdown or a sleep state. Any user may take these locks and privileged users may override these
|
||||
locks. If any locks are taken, shutdown and sleep state requests will normally fail (unless privileged) and a
|
||||
list of active locks is printed. However, if <option>--ignore-inhibitors</option> is specified, the
|
||||
established locks are ignored and not shown, and the operation attempted anyway, possibly requiring
|
||||
additional privileges.</para>
|
||||
<para>When system shutdown or sleep state is request, this option controls how to deal with
|
||||
inhibitor locks. It takes one of <literal>auto</literal>, <literal>yes</literal> or
|
||||
<literal>no</literal>. Defaults to <literal>auto</literal>, which will behave like
|
||||
<literal>yes</literal> for interactive invocations (i.e. from a TTY) and <literal>no</literal>
|
||||
for non-interactive invocations.
|
||||
<literal>yes</literal> will let the request respect inhibitor locks.
|
||||
<literal>no</literal> will let the request ignore inhibitor locks.
|
||||
</para>
|
||||
<para>Applications can establish inhibitor locks to avoid that certain important operations
|
||||
(such as CD burning or suchlike) are interrupted by system shutdown or a sleep state. Any user may
|
||||
take these locks and privileged users may override these locks.
|
||||
If any locks are taken, shutdown and sleep state requests will normally fail (unless privileged)
|
||||
and a list of active locks is printed.
|
||||
However, if <literal>no</literal> is specified or <literal>auto</literal> is specified on a
|
||||
non-interactive requests, the established locks are ignored and not shown, and the operation
|
||||
attempted anyway, possibly requiring additional privileges.
|
||||
May be overriden by <option>--force</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-i</option></term>
|
||||
|
||||
<listitem>
|
||||
<para>Shortcut for <option>--check-inhibitors=no</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
@ -409,6 +409,13 @@
|
||||
be ignored.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>TxQueueLength=</varname></term>
|
||||
<listitem>
|
||||
<para>Specifies the transmit queue length of the device in number of packets. An unsigned integer
|
||||
in the range 0..4294967294. When unset, the kernel's default will be used.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>MTUBytes=</varname></term>
|
||||
<listitem>
|
||||
|
@ -832,6 +832,14 @@ if default_locale == ''
|
||||
endif
|
||||
conf.set_quoted('SYSTEMD_DEFAULT_LOCALE', default_locale)
|
||||
|
||||
localegen_path = get_option('localegen-path')
|
||||
have = false
|
||||
if localegen_path != ''
|
||||
conf.set_quoted('LOCALEGEN_PATH', localegen_path)
|
||||
have = true
|
||||
endif
|
||||
conf.set10('HAVE_LOCALEGEN', have)
|
||||
|
||||
conf.set_quoted('GETTEXT_PACKAGE', meson.project_name())
|
||||
|
||||
service_watchdog = get_option('service-watchdog')
|
||||
|
@ -240,6 +240,8 @@ option('gshadow', type : 'boolean',
|
||||
description : 'support for shadow group')
|
||||
option('default-locale', type : 'string', value : '',
|
||||
description : 'default locale used when /etc/locale.conf does not exist')
|
||||
option('localegen-path', type : 'string', value : '',
|
||||
description : 'absolute path to the locale-gen binary in case the system is using locale-gen')
|
||||
option('service-watchdog', type : 'string', value : '3min',
|
||||
description : 'default watchdog setting for systemd services')
|
||||
|
||||
|
@ -125,9 +125,9 @@ _systemctl () {
|
||||
[STANDALONE]='--all -a --reverse --after --before --defaults --force -f --full -l --global
|
||||
--help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall --now
|
||||
--quiet -q --system --user --version --runtime --recursive -r --firmware-setup
|
||||
--show-types -i --ignore-inhibitors --plain --failed --value --fail --dry-run --wait'
|
||||
--show-types --plain --failed --value --fail --dry-run --wait'
|
||||
[ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --job-mode --root
|
||||
--preset-mode -n --lines -o --output -M --machine --message --timestamp'
|
||||
--preset-mode -n --lines -o --output -M --machine --message --timestamp --check-inhibitors'
|
||||
)
|
||||
|
||||
if __contains_word "--user" ${COMP_WORDS[*]}; then
|
||||
@ -179,6 +179,9 @@ _systemctl () {
|
||||
--timestamp)
|
||||
comps='pretty us µs utc us+utc µs+utc'
|
||||
;;
|
||||
--check-inhibitors)
|
||||
comps='auto yes no'
|
||||
;;
|
||||
esac
|
||||
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
|
||||
return 0
|
||||
|
@ -443,6 +443,13 @@ done
|
||||
_values -s , "${_styles[@]}"
|
||||
}
|
||||
|
||||
(( $+functions[_systemctl_check_inhibitors] )) ||
|
||||
_systemctl_check_inhibitors() {
|
||||
local -a _modes
|
||||
_modes=(auto yes no)
|
||||
_values -s , "${_modes[@]}"
|
||||
}
|
||||
|
||||
# Build arguments for "systemctl" to be used in completion.
|
||||
local -a _modes; _modes=("--user" "--system")
|
||||
# Use the last mode (they are exclusive and the last one is used).
|
||||
@ -460,7 +467,7 @@ _arguments -s \
|
||||
'--before[Show units ordered before]' \
|
||||
{-l,--full}"[Don't ellipsize unit names on output]" \
|
||||
'--show-types[When showing sockets, show socket type]' \
|
||||
{-i,--ignore-inhibitors}'[When executing a job, ignore jobs dependencies]' \
|
||||
'--check-inhibitors[Specify if inhibitors should be checked]:mode:_systemctl_check_inhibitors' \
|
||||
{-q,--quiet}'[Suppress output]' \
|
||||
'--no-block[Do not wait until operation finished]' \
|
||||
'--no-legend[Do not print a legend, i.e. the column headers and the footer with hints]' \
|
||||
|
@ -33,6 +33,10 @@ static inline bool streq_ptr(const char *a, const char *b) {
|
||||
return strcmp_ptr(a, b) == 0;
|
||||
}
|
||||
|
||||
static inline bool strcaseeq_ptr(const char *a, const char *b) {
|
||||
return strcasecmp_ptr(a, b) == 0;
|
||||
}
|
||||
|
||||
static inline char* strstr_ptr(const char *haystack, const char *needle) {
|
||||
if (!haystack || !needle)
|
||||
return NULL;
|
||||
|
@ -57,16 +57,15 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias,
|
||||
const struct ether_addr *mac, uint32_t mtu,
|
||||
uint32_t gso_max_size, size_t gso_max_segments) {
|
||||
int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac,
|
||||
uint32_t txqueuelen, uint32_t mtu, uint32_t gso_max_size, size_t gso_max_segments) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
|
||||
int r;
|
||||
|
||||
assert(rtnl);
|
||||
assert(ifindex > 0);
|
||||
|
||||
if (!alias && !mac && mtu == 0 && gso_max_size == 0 && gso_max_segments == 0)
|
||||
if (!alias && !mac && txqueuelen == UINT32_MAX && mtu == 0 && gso_max_size == 0 && gso_max_segments == 0)
|
||||
return 0;
|
||||
|
||||
if (!*rtnl) {
|
||||
@ -91,6 +90,12 @@ int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias,
|
||||
return r;
|
||||
}
|
||||
|
||||
if (txqueuelen < UINT32_MAX) {
|
||||
r = sd_netlink_message_append_u32(message, IFLA_TXQLEN, txqueuelen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (mtu != 0) {
|
||||
r = sd_netlink_message_append_u32(message, IFLA_MTU, mtu);
|
||||
if (r < 0)
|
||||
|
@ -70,8 +70,8 @@ static inline bool rtnl_message_type_is_mdb(uint16_t type) {
|
||||
}
|
||||
|
||||
int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name);
|
||||
int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, uint32_t mtu,
|
||||
uint32_t gso_max_size, size_t gso_max_segments);
|
||||
int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac,
|
||||
uint32_t txqueuelen, uint32_t mtu, uint32_t gso_max_size, size_t gso_max_segments);
|
||||
int rtnl_get_link_alternative_names(sd_netlink **rtnl, int ifindex, char ***ret);
|
||||
int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const *alternative_names);
|
||||
int rtnl_set_link_alternative_names_by_ifname(sd_netlink **rtnl, const char *ifname, char * const *alternative_names);
|
||||
|
@ -6,18 +6,21 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "bus-polkit.h"
|
||||
#include "copy.h"
|
||||
#include "env-file-label.h"
|
||||
#include "env-file.h"
|
||||
#include "env-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio-label.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "kbd-util.h"
|
||||
#include "keymap-util.h"
|
||||
#include "locale-util.h"
|
||||
#include "macro.h"
|
||||
#include "mkdir.h"
|
||||
#include "nulstr-util.h"
|
||||
#include "process-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "tmpfile-util.h"
|
||||
@ -780,3 +783,211 @@ int x11_convert_to_vconsole(Context *c) {
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
bool locale_gen_check_available(void) {
|
||||
#if HAVE_LOCALEGEN
|
||||
if (access(LOCALEGEN_PATH, X_OK) < 0) {
|
||||
if (errno != ENOENT)
|
||||
log_warning_errno(errno, "Unable to determine whether " LOCALEGEN_PATH " exists and is executable, assuming it is not: %m");
|
||||
return false;
|
||||
}
|
||||
if (access("/etc/locale.gen", F_OK) < 0) {
|
||||
if (errno != ENOENT)
|
||||
log_warning_errno(errno, "Unable to determine whether /etc/locale.gen exists, assuming it does not: %m");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_LOCALEGEN
|
||||
static bool locale_encoding_is_utf8_or_unspecified(const char *locale) {
|
||||
const char *c = strchr(locale, '.');
|
||||
return !c || strcaseeq(c, ".UTF-8") || strcasestr(locale, ".UTF-8@");
|
||||
}
|
||||
|
||||
static int locale_gen_locale_supported(const char *locale_entry) {
|
||||
/* Returns an error valus <= 0 if the locale-gen entry is invalid or unsupported,
|
||||
* 1 in case the locale entry is valid, and -EOPNOTSUPP specifically in case
|
||||
* the distributor has not provided us with a SUPPORTED file to check
|
||||
* locale for validity. */
|
||||
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
int r;
|
||||
|
||||
assert(locale_entry);
|
||||
|
||||
/* Locale templates without country code are never supported */
|
||||
if (!strstr(locale_entry, "_"))
|
||||
return -EINVAL;
|
||||
|
||||
f = fopen("/usr/share/i18n/SUPPORTED", "re");
|
||||
if (!f) {
|
||||
if (errno == ENOENT)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"Unable to check validity of locale entry %s: /usr/share/i18n/SUPPORTED does not exist",
|
||||
locale_entry);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
|
||||
r = read_line(f, LONG_LINE_MAX, &line);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to read /usr/share/i18n/SUPPORTED: %m");
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
line = strstrip(line);
|
||||
if (strcaseeq_ptr(line, locale_entry))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int locale_gen_enable_locale(const char *locale) {
|
||||
#if HAVE_LOCALEGEN
|
||||
_cleanup_fclose_ FILE *fr = NULL, *fw = NULL;
|
||||
_cleanup_(unlink_and_freep) char *temp_path = NULL;
|
||||
_cleanup_free_ char *locale_entry = NULL;
|
||||
bool locale_enabled = false, first_line = false;
|
||||
bool write_new = false;
|
||||
int r;
|
||||
|
||||
if (isempty(locale))
|
||||
return 0;
|
||||
|
||||
if (locale_encoding_is_utf8_or_unspecified(locale)) {
|
||||
locale_entry = strjoin(locale, " UTF-8");
|
||||
if (!locale_entry)
|
||||
return -ENOMEM;
|
||||
} else
|
||||
return -ENOEXEC; /* We do not process non-UTF-8 locale */
|
||||
|
||||
r = locale_gen_locale_supported(locale_entry);
|
||||
if (r == 0)
|
||||
return -EINVAL;
|
||||
if (r < 0 && r != -EOPNOTSUPP)
|
||||
return r;
|
||||
|
||||
fr = fopen("/etc/locale.gen", "re");
|
||||
if (!fr) {
|
||||
if (errno != ENOENT)
|
||||
return -errno;
|
||||
write_new = true;
|
||||
}
|
||||
|
||||
r = fopen_temporary("/etc/locale.gen", &fw, &temp_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (write_new)
|
||||
(void) fchmod(fileno(fw), 0644);
|
||||
else {
|
||||
/* apply mode & xattrs of the original file to new file */
|
||||
r = copy_access(fileno(fr), fileno(fw));
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = copy_xattr(fileno(fr), fileno(fw));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!write_new) {
|
||||
/* The config file ends with a line break, which we do not want to include before potentially appending a new locale
|
||||
* instead of uncommenting an existing line. By prepending linebreaks, we can avoid buffering this file but can still write
|
||||
* a nice config file without empty lines */
|
||||
first_line = true;
|
||||
for (;;) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
char *line_locale;
|
||||
|
||||
r = read_line(fr, LONG_LINE_MAX, &line);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (locale_enabled) {
|
||||
/* Just complete writing the file if the new locale was already enabled */
|
||||
if (!first_line)
|
||||
fputc('\n', fw);
|
||||
fputs(line, fw);
|
||||
first_line = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
line = strstrip(line);
|
||||
if (isempty(line)) {
|
||||
fputc('\n', fw);
|
||||
first_line = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
line_locale = line;
|
||||
if (line_locale[0] == '#')
|
||||
line_locale = strstrip(line_locale + 1);
|
||||
else if (strcaseeq_ptr(line_locale, locale_entry))
|
||||
return 0; /* the file already had our locale activated, so skip updating it */
|
||||
|
||||
if (strcaseeq_ptr(line_locale, locale_entry)) {
|
||||
/* Uncomment existing line for new locale */
|
||||
if (!first_line)
|
||||
fputc('\n', fw);
|
||||
fputs(locale_entry, fw);
|
||||
locale_enabled = true;
|
||||
first_line = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The line was not for the locale we want to enable, just copy it */
|
||||
if (!first_line)
|
||||
fputc('\n', fw);
|
||||
fputs(line, fw);
|
||||
first_line = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add locale to enable to the end of the file if it was not found as commented line */
|
||||
if (!locale_enabled) {
|
||||
if (!write_new)
|
||||
fputc('\n', fw);
|
||||
fputs(locale_entry, fw);
|
||||
}
|
||||
fputc('\n', fw);
|
||||
|
||||
r = fflush_sync_and_check(fw);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (rename(temp_path, "/etc/locale.gen") < 0)
|
||||
return -errno;
|
||||
temp_path = mfree(temp_path);
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int locale_gen_run(void) {
|
||||
#if HAVE_LOCALEGEN
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
r = safe_fork("(sd-localegen)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_WAIT, &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
execl(LOCALEGEN_PATH, LOCALEGEN_PATH, NULL);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
@ -42,3 +42,7 @@ int x11_convert_to_vconsole(Context *c);
|
||||
int x11_write_data(Context *c);
|
||||
void locale_simplify(char *locale[_VARIABLE_LC_MAX]);
|
||||
int locale_write_data(Context *c, char ***settings);
|
||||
|
||||
bool locale_gen_check_available(void);
|
||||
int locale_gen_enable_locale(const char *locale);
|
||||
int locale_gen_run(void);
|
||||
|
@ -26,6 +26,9 @@
|
||||
#include "verbs.h"
|
||||
#include "virt.h"
|
||||
|
||||
/* Enough time for locale-gen to finish server-side (in case it is in use) */
|
||||
#define LOCALE_SLOW_BUS_CALL_TIMEOUT_USEC (2*USEC_PER_MINUTE)
|
||||
|
||||
static PagerFlags arg_pager_flags = 0;
|
||||
static bool arg_ask_password = true;
|
||||
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
|
||||
@ -176,7 +179,8 @@ static int set_locale(int argc, char **argv, void *userdata) {
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_call(bus, m, 0, &error, NULL);
|
||||
/* We use a longer timeout for the method call in case localed is running locale-gen */
|
||||
r = sd_bus_call(bus, m, LOCALE_SLOW_BUS_CALL_TIMEOUT_USEC, &error, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r));
|
||||
|
||||
|
@ -262,6 +262,7 @@ static int property_get_xkb(
|
||||
static int process_locale_list_item(
|
||||
const char *assignment,
|
||||
char *new_locale[static _VARIABLE_LC_MAX],
|
||||
bool use_localegen,
|
||||
sd_bus_error *error) {
|
||||
|
||||
assert(assignment);
|
||||
@ -283,7 +284,7 @@ static int process_locale_list_item(
|
||||
|
||||
if (!locale_is_valid(e))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale %s is not valid, refusing.", e);
|
||||
if (locale_is_installed(e) <= 0)
|
||||
if (!use_localegen && locale_is_installed(e) <= 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale %s not installed, refusing.", e);
|
||||
if (new_locale[p])
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale variable %s set twice, refusing.", name);
|
||||
@ -298,6 +299,47 @@ static int process_locale_list_item(
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale assignment %s not valid, refusing.", assignment);
|
||||
}
|
||||
|
||||
static int locale_gen_process_locale(char *new_locale[static _VARIABLE_LC_MAX],
|
||||
sd_bus_error *error) {
|
||||
int r;
|
||||
assert(new_locale);
|
||||
|
||||
for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++) {
|
||||
if (p == VARIABLE_LANGUAGE)
|
||||
continue;
|
||||
if (isempty(new_locale[p]))
|
||||
continue;
|
||||
if (locale_is_installed(new_locale[p]))
|
||||
continue;
|
||||
|
||||
r = locale_gen_enable_locale(new_locale[p]);
|
||||
if (r == -ENOEXEC) {
|
||||
log_error_errno(r, "Refused to enable locale for generation: %m");
|
||||
return sd_bus_error_setf(error,
|
||||
SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Specified locale is not installed and non-UTF-8 locale will not be auto-generated: %s",
|
||||
new_locale[p]);
|
||||
} else if (r == -EINVAL) {
|
||||
log_error_errno(r, "Failed to enable invalid locale %s for generation.", new_locale[p]);
|
||||
return sd_bus_error_setf(error,
|
||||
SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Can not enable locale generation for invalid locale: %s",
|
||||
new_locale[p]);
|
||||
} else if (r < 0) {
|
||||
log_error_errno(r, "Failed to enable locale for generation: %m");
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to enable locale generation: %m");
|
||||
}
|
||||
|
||||
r = locale_gen_run();
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to generate locale: %m");
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to generate locale: %m");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *error) {
|
||||
_cleanup_(locale_variables_freep) char *new_locale[_VARIABLE_LC_MAX] = {};
|
||||
_cleanup_strv_free_ char **settings = NULL, **l = NULL;
|
||||
@ -305,6 +347,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
|
||||
bool modified = false;
|
||||
int interactive, r;
|
||||
char **i;
|
||||
bool use_localegen;
|
||||
|
||||
assert(m);
|
||||
assert(c);
|
||||
@ -317,11 +360,13 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
use_localegen = locale_gen_check_available();
|
||||
|
||||
/* If single locale without variable name is provided, then we assume it is LANG=. */
|
||||
if (strv_length(l) == 1 && !strchr(l[0], '=')) {
|
||||
if (!locale_is_valid(l[0]))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid locale specification: %s", l[0]);
|
||||
if (locale_is_installed(l[0]) <= 0)
|
||||
if (!use_localegen && locale_is_installed(l[0]) <= 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified locale is not installed: %s", l[0]);
|
||||
|
||||
new_locale[VARIABLE_LANG] = strdup(l[0]);
|
||||
@ -333,7 +378,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
|
||||
|
||||
/* Check whether a variable is valid */
|
||||
STRV_FOREACH(i, l) {
|
||||
r = process_locale_list_item(*i, new_locale, error);
|
||||
r = process_locale_list_item(*i, new_locale, use_localegen, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -392,9 +437,17 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
/* Generate locale in case it is missing and the system is using locale-gen */
|
||||
if (use_localegen) {
|
||||
r = locale_gen_process_locale(new_locale, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
|
||||
free_and_replace(c->locale[p], new_locale[p]);
|
||||
|
||||
/* Write locale configuration */
|
||||
r = locale_write_data(c, &settings);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to set locale: %m");
|
||||
|
@ -96,17 +96,19 @@ int logind_check_inhibitors(enum action a) {
|
||||
char **s;
|
||||
int r;
|
||||
|
||||
if (arg_ignore_inhibitors || arg_force > 0)
|
||||
if (arg_check_inhibitors == 0 || arg_force > 0)
|
||||
return 0;
|
||||
|
||||
if (arg_when > 0)
|
||||
return 0;
|
||||
|
||||
if (geteuid() == 0)
|
||||
return 0;
|
||||
if (arg_check_inhibitors < 0) {
|
||||
if (geteuid() == 0)
|
||||
return 0;
|
||||
|
||||
if (!on_tty())
|
||||
return 0;
|
||||
if (!on_tty())
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (arg_transport != BUS_TRANSPORT_LOCAL)
|
||||
return 0;
|
||||
|
@ -74,7 +74,7 @@ bool arg_no_wall = false;
|
||||
bool arg_no_reload = false;
|
||||
bool arg_value = false;
|
||||
bool arg_show_types = false;
|
||||
bool arg_ignore_inhibitors = false;
|
||||
int arg_check_inhibitors = -1;
|
||||
bool arg_dry_run = false;
|
||||
bool arg_quiet = false;
|
||||
bool arg_full = false;
|
||||
@ -241,7 +241,10 @@ static int systemctl_help(void) {
|
||||
" -T --show-transaction When enqueuing a unit job, show full transaction\n"
|
||||
" --show-types When showing sockets, explicitly show their type\n"
|
||||
" --value When showing properties, only print the value\n"
|
||||
" -i --ignore-inhibitors When shutting down or sleeping, ignore inhibitors\n"
|
||||
" --check-inhibitors=MODE\n"
|
||||
" Specify if checking inhibitors before shutting down,\n"
|
||||
" sleeping or hibernating\n"
|
||||
" -i Shortcut for --check-inhibitors=no\n"
|
||||
" --kill-who=WHO Whom to send signal to\n"
|
||||
" -s --signal=SIGNAL Which signal to send\n"
|
||||
" --what=RESOURCES Which types of resources to remove\n"
|
||||
@ -364,6 +367,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
ARG_REVERSE,
|
||||
ARG_AFTER,
|
||||
ARG_BEFORE,
|
||||
ARG_CHECK_INHIBITORS,
|
||||
ARG_DRY_RUN,
|
||||
ARG_SHOW_TYPES,
|
||||
ARG_IRREVERSIBLE,
|
||||
@ -415,7 +419,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
{ "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
|
||||
{ "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
|
||||
{ "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
|
||||
{ "ignore-inhibitors", no_argument, NULL, 'i' },
|
||||
{ "ignore-inhibitors", no_argument, NULL, 'i' }, /* compatibility only */
|
||||
{ "check-inhibitors", required_argument, NULL, ARG_CHECK_INHIBITORS },
|
||||
{ "value", no_argument, NULL, ARG_VALUE },
|
||||
{ "user", no_argument, NULL, ARG_USER },
|
||||
{ "system", no_argument, NULL, ARG_SYSTEM },
|
||||
@ -716,7 +721,18 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
arg_ignore_inhibitors = true;
|
||||
arg_check_inhibitors = 0;
|
||||
break;
|
||||
|
||||
case ARG_CHECK_INHIBITORS:
|
||||
if (streq(optarg, "auto"))
|
||||
arg_check_inhibitors = -1;
|
||||
else {
|
||||
r = parse_boolean(optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse --check-inhibitors= argument: %s", optarg);
|
||||
arg_check_inhibitors = r;
|
||||
}
|
||||
break;
|
||||
|
||||
case ARG_PLAIN:
|
||||
|
@ -59,7 +59,7 @@ extern bool arg_no_wall;
|
||||
extern bool arg_no_reload;
|
||||
extern bool arg_value;
|
||||
extern bool arg_show_types;
|
||||
extern bool arg_ignore_inhibitors;
|
||||
extern int arg_check_inhibitors;
|
||||
extern bool arg_dry_run;
|
||||
extern bool arg_quiet;
|
||||
extern bool arg_full;
|
||||
|
@ -40,6 +40,7 @@ Link.Name, config_parse_ifname, 0,
|
||||
Link.AlternativeName, config_parse_ifnames, IFNAME_VALID_ALTERNATIVE, offsetof(link_config, alternative_names)
|
||||
Link.AlternativeNamesPolicy, config_parse_alternative_names_policy, 0, offsetof(link_config, alternative_names_policy)
|
||||
Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias)
|
||||
Link.TxQueueLength, config_parse_txqueuelen, 0, offsetof(link_config, txqueuelen)
|
||||
Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(link_config, mtu)
|
||||
Link.BitsPerSecond, config_parse_si_uint64, 0, offsetof(link_config, speed)
|
||||
Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex)
|
||||
|
@ -150,6 +150,7 @@ int link_load_one(link_config_ctx *ctx, const char *filename) {
|
||||
.rx_flow_control = -1,
|
||||
.tx_flow_control = -1,
|
||||
.autoneg_flow_control = -1,
|
||||
.txqueuelen = UINT32_MAX,
|
||||
};
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(link->features); i++)
|
||||
@ -426,9 +427,11 @@ static int link_config_apply_rtnl_settings(sd_netlink **rtnl, const link_config
|
||||
} else
|
||||
mac = config->mac;
|
||||
|
||||
r = rtnl_set_link_properties(rtnl, ifindex, config->alias, mac, config->mtu, config->gso_max_size, config->gso_max_segments);
|
||||
r = rtnl_set_link_properties(rtnl, ifindex, config->alias, mac, config->txqueuelen, config->mtu,
|
||||
config->gso_max_size, config->gso_max_segments);
|
||||
if (r < 0)
|
||||
log_device_warning_errno(device, r, "Could not set Alias=, MACAddress= or MTU=, ignoring: %m");
|
||||
log_device_warning_errno(device, r, "Could not set Alias=, MACAddress=, TxQueueLength=, MTU=, "
|
||||
"GenericSegmentOffloadMaxBytes= or GenericSegmentOffloadMaxSegments=, ignoring: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -701,6 +704,40 @@ int config_parse_ifalias(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_txqueuelen(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
uint32_t k, *v = data;
|
||||
int r;
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*v = UINT32_MAX;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = safe_atou32(rvalue, &k);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s=, ignoring assignment: %s.", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
if (k == UINT32_MAX) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid %s=, ignoring assignment: %s.", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*v = k;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* const mac_address_policy_table[_MAC_ADDRESS_POLICY_MAX] = {
|
||||
[MAC_ADDRESS_POLICY_PERSISTENT] = "persistent",
|
||||
[MAC_ADDRESS_POLICY_RANDOM] = "random",
|
||||
|
@ -46,6 +46,7 @@ struct link_config {
|
||||
char *name;
|
||||
char **alternative_names;
|
||||
char *alias;
|
||||
uint32_t txqueuelen;
|
||||
uint32_t mtu;
|
||||
uint32_t gso_max_segments;
|
||||
size_t gso_max_size;
|
||||
@ -90,6 +91,7 @@ MACAddressPolicy mac_address_policy_from_string(const char *p) _pure_;
|
||||
const struct ConfigPerfItem* link_config_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_txqueuelen);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_mac_address_policy);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_name_policy);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_alternative_names_policy);
|
||||
|
@ -20,6 +20,7 @@ Name=
|
||||
AlternativeNamesPolicy=
|
||||
AlternativeName=
|
||||
Alias=
|
||||
TxQueueLength=
|
||||
MTUBytes=
|
||||
BitsPerSecond=
|
||||
Duplex=
|
||||
|
Loading…
x
Reference in New Issue
Block a user