Compare commits
14 Commits
a6e1018df2
...
0328d672f3
Author | SHA1 | Date |
---|---|---|
Zbigniew Jędrzejewski-Szmek | 0328d672f3 | |
Lennart Poettering | c01ef54f7f | |
Hans de Goede | 27593a0641 | |
Zbigniew Jędrzejewski-Szmek | 165bda37ba | |
Zbigniew Jędrzejewski-Szmek | 8acb7780df | |
Lennart Poettering | a00a78b84e | |
Lennart Poettering | b45b0a69bb | |
Lennart Poettering | 23fa786ca6 | |
Lennart Poettering | 77a3cec0c7 | |
Lennart Poettering | 7dc6477dc9 | |
Lennart Poettering | a3451c2c4c | |
Lennart Poettering | fb29cdbef2 | |
Lennart Poettering | 0d9d333672 | |
Lennart Poettering | a258f4915a |
|
@ -469,6 +469,7 @@ sensor:modalias:acpi:SMO8500*:dmi:*:svnMEDION:pnAkoyaE2212TMD99720:*
|
|||
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
|
||||
|
||||
# Medion Akoya E2215T MD60198
|
||||
sensor:modalias:acpi:KIOX000A*:dmi:*svnMEDION:pnE2215TMD60198:*
|
||||
# Medion Akoya E3216 MD60900
|
||||
# Medion Akoya E3221 MD61237
|
||||
# Medion Akoya E2292 MD63390
|
||||
|
|
|
@ -161,10 +161,10 @@
|
|||
<listitem><para>Takes a directory path as an argument. All paths will be prefixed with the given alternate
|
||||
<replaceable>root</replaceable> path, including config search paths.</para>
|
||||
|
||||
<para>Note that this option does not alter how the users and groups specified in the configuration files are
|
||||
resolved. With or without this option, users and groups are always resolved according to the host's user and
|
||||
group databases, any such databases stored under the specified root directories are not
|
||||
consulted.</para></listitem>
|
||||
<para>When this option is used, the libc Name Service Switch (NSS) is bypassed for resolving users
|
||||
and groups. Instead the files <filename>/etc/passwd</filename> and <filename>/etc/group</filename>
|
||||
inside the alternate root are read directly. This means that users/groups not listed in these files
|
||||
will not be resolved, i.e. LDAP NIS and other complex databases are not considered.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
|
|
@ -2891,6 +2891,8 @@ if conf.get('ENABLE_TMPFILES') == 1
|
|||
exe = executable(
|
||||
'systemd-tmpfiles',
|
||||
'src/tmpfiles/tmpfiles.c',
|
||||
'src/tmpfiles/offline-passwd.c',
|
||||
'src/tmpfiles/offline-passwd.h',
|
||||
include_directories : includes,
|
||||
link_with : [libshared],
|
||||
dependencies : [libacl],
|
||||
|
|
|
@ -254,6 +254,21 @@ bool locale_is_valid(const char *name) {
|
|||
return true;
|
||||
}
|
||||
|
||||
int locale_is_installed(const char *name) {
|
||||
if (!locale_is_valid(name))
|
||||
return false;
|
||||
|
||||
if (STR_IN_SET(name, "C", "POSIX")) /* These ones are always OK */
|
||||
return true;
|
||||
|
||||
_cleanup_(freelocalep) locale_t loc =
|
||||
newlocale(LC_ALL_MASK, name, 0);
|
||||
if (loc == (locale_t) 0)
|
||||
return errno == ENOMEM ? -ENOMEM : false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void init_gettext(void) {
|
||||
setlocale(LC_ALL, "");
|
||||
textdomain(GETTEXT_PACKAGE);
|
||||
|
|
|
@ -31,6 +31,7 @@ typedef enum LocaleVariable {
|
|||
|
||||
int get_locales(char ***l);
|
||||
bool locale_is_valid(const char *name);
|
||||
int locale_is_installed(const char *name);
|
||||
|
||||
#define _(String) gettext(String)
|
||||
#define N_(String) String
|
||||
|
|
|
@ -818,10 +818,7 @@ ssize_t send_one_fd_iov_sa(
|
|||
const struct sockaddr *sa, socklen_t len,
|
||||
int flags) {
|
||||
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(int))];
|
||||
} control = {};
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int))) control = {};
|
||||
struct msghdr mh = {
|
||||
.msg_name = (struct sockaddr*) sa,
|
||||
.msg_namelen = len,
|
||||
|
@ -850,8 +847,6 @@ ssize_t send_one_fd_iov_sa(
|
|||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
|
||||
|
||||
mh.msg_controllen = CMSG_SPACE(sizeof(int));
|
||||
}
|
||||
k = sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags);
|
||||
if (k < 0)
|
||||
|
@ -877,10 +872,7 @@ ssize_t receive_one_fd_iov(
|
|||
int flags,
|
||||
int *ret_fd) {
|
||||
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(int))];
|
||||
} control = {};
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int))) control;
|
||||
struct msghdr mh = {
|
||||
.msg_control = &control,
|
||||
.msg_controllen = sizeof(control),
|
||||
|
|
|
@ -166,6 +166,17 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng
|
|||
(ctype*) (_found ? CMSG_DATA(_found) : NULL); \
|
||||
})
|
||||
|
||||
/* Resolves to a type that can carry cmsghdr structures. Make sure things are properly aligned, i.e. the type
|
||||
* itself is placed properly in memory and the size is also aligned to what's appropriate for "cmsghdr"
|
||||
* structures. */
|
||||
#define CMSG_BUFFER_TYPE(size) \
|
||||
union { \
|
||||
struct cmsghdr cmsghdr; \
|
||||
uint8_t buf[size]; \
|
||||
uint8_t align_check[(size) >= CMSG_SPACE(0) && \
|
||||
(size) == CMSG_ALIGN(size) ? 1 : -1]; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Certain hardware address types (e.g Infiniband) do not fit into sll_addr
|
||||
* (8 bytes) and run over the structure. This macro returns the correct size that
|
||||
|
|
|
@ -2349,11 +2349,8 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
|
|||
.iov_base = buf,
|
||||
.iov_len = sizeof(buf)-1,
|
||||
};
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
|
||||
CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)];
|
||||
} control = {};
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred)) +
|
||||
CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)) control;
|
||||
struct msghdr msghdr = {
|
||||
.msg_iov = &iovec,
|
||||
.msg_iovlen = 1,
|
||||
|
|
|
@ -884,10 +884,7 @@ static int process_socket(int fd) {
|
|||
log_debug("Processing coredump received on stdin...");
|
||||
|
||||
for (;;) {
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(int))];
|
||||
} control = {};
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int))) control;
|
||||
struct msghdr mh = {
|
||||
.msg_control = &control,
|
||||
.msg_controllen = sizeof(control),
|
||||
|
|
|
@ -205,6 +205,14 @@ static int prompt_loop(const char *text, char **l, unsigned percentage, bool (*i
|
|||
}
|
||||
}
|
||||
|
||||
static bool locale_is_ok(const char *name) {
|
||||
|
||||
if (arg_root)
|
||||
return locale_is_valid(name);
|
||||
|
||||
return locale_is_installed(name) > 0;
|
||||
}
|
||||
|
||||
static int prompt_locale(void) {
|
||||
_cleanup_strv_free_ char **locales = NULL;
|
||||
int r;
|
||||
|
@ -238,7 +246,7 @@ static int prompt_locale(void) {
|
|||
print_welcome();
|
||||
|
||||
r = prompt_loop("Please enter system locale name or number",
|
||||
locales, 60, locale_is_valid, &arg_locale);
|
||||
locales, 60, locale_is_ok, &arg_locale);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -246,7 +254,7 @@ static int prompt_locale(void) {
|
|||
return 0;
|
||||
|
||||
r = prompt_loop("Please enter system message locale name or number",
|
||||
locales, 60, locale_is_valid, &arg_locale_messages);
|
||||
locales, 60, locale_is_ok, &arg_locale_messages);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -791,10 +799,6 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
break;
|
||||
|
||||
case ARG_LOCALE:
|
||||
if (!locale_is_valid(optarg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Locale %s is not valid.", optarg);
|
||||
|
||||
r = free_and_strdup(&arg_locale, optarg);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
@ -802,10 +806,6 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
break;
|
||||
|
||||
case ARG_LOCALE_MESSAGES:
|
||||
if (!locale_is_valid(optarg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Locale %s is not valid.", optarg);
|
||||
|
||||
r = free_and_strdup(&arg_locale_messages, optarg);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
@ -927,6 +927,14 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
assert_not_reached("Unhandled option");
|
||||
}
|
||||
|
||||
/* We check if the specified locale strings are valid down here, so that we can take --root= into
|
||||
* account when looking for the locale files. */
|
||||
|
||||
if (arg_locale && !locale_is_ok(arg_locale))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Locale %s is not installed.", arg_locale);
|
||||
if (arg_locale_messages && !locale_is_ok(arg_locale_messages))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Locale %s is not installed.", arg_locale_messages);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -2806,6 +2806,9 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
if (!locale_is_valid(optarg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Locale '%s' is not valid.", optarg);
|
||||
|
||||
if (locale_is_installed(optarg) <= 0)
|
||||
log_warning("Locale '%s' is not installed, accepting anyway.", optarg);
|
||||
|
||||
r = json_variant_set_field_string(&arg_identity_extra, "preferredLanguage", optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set preferredLanguage field: %m");
|
||||
|
|
|
@ -946,10 +946,7 @@ static ssize_t read_datagram(int fd, struct ucred *ret_sender, void **ret) {
|
|||
return -ENOMEM;
|
||||
|
||||
if (ret_sender) {
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
|
||||
} control;
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
|
||||
bool found_ucred = false;
|
||||
struct cmsghdr *cmsg;
|
||||
struct msghdr mh;
|
||||
|
|
|
@ -550,11 +550,8 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
|
|||
.iov_base = buf,
|
||||
.iov_len = sizeof(buf)-1,
|
||||
};
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
|
||||
CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)];
|
||||
} control = {};
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred)) +
|
||||
CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)) control;
|
||||
struct msghdr msghdr = {
|
||||
.msg_iov = &iovec,
|
||||
.msg_iovlen = 1,
|
||||
|
|
|
@ -1268,21 +1268,14 @@ int server_process_datagram(
|
|||
int *fds = NULL, v = 0;
|
||||
size_t n_fds = 0;
|
||||
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
|
||||
/* We use NAME_MAX space for the SELinux label
|
||||
* here. The kernel currently enforces no
|
||||
* limit, but according to suggestions from
|
||||
* the SELinux people this will change and it
|
||||
* will probably be identical to NAME_MAX. For
|
||||
* now we use that, but this should be updated
|
||||
* one day when the final limit is known. */
|
||||
uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
|
||||
CMSG_SPACE(sizeof(struct timeval)) +
|
||||
CMSG_SPACE(sizeof(int)) + /* fd */
|
||||
CMSG_SPACE(NAME_MAX)]; /* selinux label */
|
||||
} control = {};
|
||||
/* We use NAME_MAX space for the SELinux label here. The kernel currently enforces no limit, but
|
||||
* according to suggestions from the SELinux people this will change and it will probably be
|
||||
* identical to NAME_MAX. For now we use that, but this should be updated one day when the final
|
||||
* limit is known. */
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred)) +
|
||||
CMSG_SPACE(sizeof(struct timeval)) +
|
||||
CMSG_SPACE(sizeof(int)) + /* fd */
|
||||
CMSG_SPACE(NAME_MAX) /* selinux label */) control;
|
||||
|
||||
union sockaddr_union sa = {};
|
||||
|
||||
|
|
|
@ -489,7 +489,7 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
|
|||
}
|
||||
|
||||
static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
|
||||
uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
|
||||
StdoutStream *s = userdata;
|
||||
struct ucred *ucred;
|
||||
struct iovec iovec;
|
||||
|
@ -500,8 +500,8 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
|
|||
struct msghdr msghdr = {
|
||||
.msg_iov = &iovec,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = buf,
|
||||
.msg_controllen = sizeof(buf),
|
||||
.msg_control = &control,
|
||||
.msg_controllen = sizeof(control),
|
||||
};
|
||||
|
||||
assert(s);
|
||||
|
|
|
@ -39,10 +39,7 @@ static void forward_syslog_iovec(
|
|||
.msg_iovlen = n_iovec,
|
||||
};
|
||||
struct cmsghdr *cmsg;
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
|
||||
} control;
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
|
||||
const char *j;
|
||||
int r;
|
||||
|
||||
|
|
|
@ -147,11 +147,9 @@ int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
|
|||
|
||||
int icmp6_receive(int fd, void *buffer, size_t size, struct in6_addr *dst,
|
||||
triple_timestamp *timestamp) {
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(int)) + /* ttl */
|
||||
CMSG_SPACE(sizeof(struct timeval))];
|
||||
} control = {};
|
||||
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int)) + /* ttl */
|
||||
CMSG_SPACE(sizeof(struct timeval))) control;
|
||||
struct iovec iov = {};
|
||||
union sockaddr_union sa = {};
|
||||
struct msghdr msg = {
|
||||
|
|
|
@ -1899,13 +1899,13 @@ static int client_receive_message_raw(
|
|||
|
||||
sd_dhcp_client *client = userdata;
|
||||
_cleanup_free_ DHCPPacket *packet = NULL;
|
||||
uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct tpacket_auxdata))) control;
|
||||
struct iovec iov = {};
|
||||
struct msghdr msg = {
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = cmsgbuf,
|
||||
.msg_controllen = sizeof(cmsgbuf),
|
||||
.msg_control = &control,
|
||||
.msg_controllen = sizeof(control),
|
||||
};
|
||||
struct cmsghdr *cmsg;
|
||||
bool checksum = true;
|
||||
|
|
|
@ -267,14 +267,14 @@ static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination,
|
|||
.iov_base = message,
|
||||
.iov_len = len,
|
||||
};
|
||||
uint8_t cmsgbuf[CMSG_LEN(sizeof(struct in_pktinfo))] = {};
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in_pktinfo))) control = {};
|
||||
struct msghdr msg = {
|
||||
.msg_name = &dest,
|
||||
.msg_namelen = sizeof(dest.in),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = cmsgbuf,
|
||||
.msg_controllen = sizeof(cmsgbuf),
|
||||
.msg_control = &control,
|
||||
.msg_controllen = sizeof(control),
|
||||
};
|
||||
struct cmsghdr *cmsg;
|
||||
struct in_pktinfo *pktinfo;
|
||||
|
@ -970,14 +970,14 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
|
|||
static int server_receive_message(sd_event_source *s, int fd,
|
||||
uint32_t revents, void *userdata) {
|
||||
_cleanup_free_ DHCPMessage *message = NULL;
|
||||
uint8_t cmsgbuf[CMSG_LEN(sizeof(struct in_pktinfo))];
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in_pktinfo))) control;
|
||||
sd_dhcp_server *server = userdata;
|
||||
struct iovec iov = {};
|
||||
struct msghdr msg = {
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = cmsgbuf,
|
||||
.msg_controllen = sizeof(cmsgbuf),
|
||||
.msg_control = &control,
|
||||
.msg_controllen = sizeof(control),
|
||||
};
|
||||
struct cmsghdr *cmsg;
|
||||
ssize_t buflen, len;
|
||||
|
|
|
@ -518,10 +518,7 @@ static int bus_socket_read_auth(sd_bus *b) {
|
|||
ssize_t k;
|
||||
int r;
|
||||
void *p;
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)];
|
||||
} control;
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)) control;
|
||||
bool handle_cmsg = false;
|
||||
|
||||
assert(b);
|
||||
|
@ -1037,8 +1034,10 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
|
|||
if (m->n_fds > 0 && *idx == 0) {
|
||||
struct cmsghdr *control;
|
||||
|
||||
mh.msg_control = control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds));
|
||||
mh.msg_controllen = control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds);
|
||||
mh.msg_controllen = CMSG_SPACE(sizeof(int) * m->n_fds);
|
||||
mh.msg_control = alloca0(mh.msg_controllen);
|
||||
control = CMSG_FIRSTHDR(&mh);
|
||||
control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds);
|
||||
control->cmsg_level = SOL_SOCKET;
|
||||
control->cmsg_type = SCM_RIGHTS;
|
||||
memcpy(CMSG_DATA(control), m->fds, sizeof(int) * m->n_fds);
|
||||
|
@ -1167,10 +1166,7 @@ int bus_socket_read_message(sd_bus *bus) {
|
|||
size_t need;
|
||||
int r;
|
||||
void *b;
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)];
|
||||
} control;
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)) control;
|
||||
bool handle_cmsg = false;
|
||||
|
||||
assert(bus);
|
||||
|
|
|
@ -361,13 +361,13 @@ int device_monitor_receive_device(sd_device_monitor *m, sd_device **ret) {
|
|||
.iov_base = &buf,
|
||||
.iov_len = sizeof(buf)
|
||||
};
|
||||
char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
|
||||
union sockaddr_union snl;
|
||||
struct msghdr smsg = {
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = cred_msg,
|
||||
.msg_controllen = sizeof(cred_msg),
|
||||
.msg_control = &control,
|
||||
.msg_controllen = sizeof(control),
|
||||
.msg_name = &snl,
|
||||
.msg_namelen = sizeof(snl),
|
||||
};
|
||||
|
|
|
@ -258,18 +258,57 @@ static int property_get_xkb(
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int process_locale_list_item(
|
||||
const char *assignment,
|
||||
char *new_locale[static _VARIABLE_LC_MAX],
|
||||
sd_bus_error *error) {
|
||||
|
||||
assert(assignment);
|
||||
assert(new_locale);
|
||||
|
||||
for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++) {
|
||||
const char *name, *e;
|
||||
|
||||
assert_se(name = locale_variable_to_string(p));
|
||||
|
||||
e = startswith(assignment, name);
|
||||
if (!e)
|
||||
continue;
|
||||
|
||||
if (*e != '=')
|
||||
continue;
|
||||
|
||||
e++;
|
||||
|
||||
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)
|
||||
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);
|
||||
|
||||
new_locale[p] = strdup(e);
|
||||
if (!new_locale[p])
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale assignment %s not valid, refusing.", assignment);
|
||||
}
|
||||
|
||||
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;
|
||||
Context *c = userdata;
|
||||
bool modified = false;
|
||||
int interactive, p, r;
|
||||
int interactive, r;
|
||||
char **i;
|
||||
|
||||
assert(m);
|
||||
assert(c);
|
||||
|
||||
r = bus_message_read_strv_extend(m, &l);
|
||||
r = sd_bus_message_read_strv(m, &l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -278,11 +317,13 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
|
|||
return r;
|
||||
|
||||
/* If single locale without variable name is provided, then we assume it is LANG=. */
|
||||
if (strv_length(l) == 1 && !strchr(*l, '=')) {
|
||||
if (!locale_is_valid(*l))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Locale data.");
|
||||
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)
|
||||
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);
|
||||
new_locale[VARIABLE_LANG] = strdup(l[0]);
|
||||
if (!new_locale[VARIABLE_LANG])
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -291,31 +332,9 @@ 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) {
|
||||
bool valid = false;
|
||||
|
||||
for (p = 0; p < _VARIABLE_LC_MAX; p++) {
|
||||
size_t k;
|
||||
const char *name;
|
||||
|
||||
name = locale_variable_to_string(p);
|
||||
assert(name);
|
||||
|
||||
k = strlen(name);
|
||||
if (startswith(*i, name) &&
|
||||
(*i)[k] == '=' &&
|
||||
locale_is_valid((*i) + k + 1)) {
|
||||
valid = true;
|
||||
|
||||
new_locale[p] = strdup((*i) + k + 1);
|
||||
if (!new_locale[p])
|
||||
return -ENOMEM;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Locale data.");
|
||||
r = process_locale_list_item(*i, new_locale, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* If LANG was specified, but not LANGUAGE, check if we should
|
||||
|
@ -338,7 +357,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
|
|||
}
|
||||
|
||||
/* Merge with the current settings */
|
||||
for (p = 0; p < _VARIABLE_LC_MAX; p++)
|
||||
for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
|
||||
if (!isempty(c->locale[p]) && isempty(new_locale[p])) {
|
||||
new_locale[p] = strdup(c->locale[p]);
|
||||
if (!new_locale[p])
|
||||
|
@ -347,7 +366,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
|
|||
|
||||
locale_simplify(new_locale);
|
||||
|
||||
for (p = 0; p < _VARIABLE_LC_MAX; p++)
|
||||
for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
|
||||
if (!streq_ptr(c->locale[p], new_locale[p])) {
|
||||
modified = true;
|
||||
break;
|
||||
|
@ -372,7 +391,7 @@ 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 */
|
||||
|
||||
for (p = 0; p < _VARIABLE_LC_MAX; p++)
|
||||
for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
|
||||
free_and_replace(c->locale[p], new_locale[p]);
|
||||
|
||||
r = locale_write_data(c, &settings);
|
||||
|
|
|
@ -580,9 +580,9 @@ static int apply_user_record_settings(pam_handle_t *handle, UserRecord *ur, bool
|
|||
if (pam_getenv(handle, "LANG")) {
|
||||
if (debug)
|
||||
pam_syslog(handle, LOG_DEBUG, "PAM environment variable $LANG already set, not changing based on user record.");
|
||||
} else if (!locale_is_valid(ur->preferred_language)) {
|
||||
} else if (locale_is_installed(ur->preferred_language) <= 0) {
|
||||
if (debug)
|
||||
pam_syslog(handle, LOG_DEBUG, "Preferred language specified in user record is not valid locally, not setting $LANG.");
|
||||
pam_syslog(handle, LOG_DEBUG, "Preferred language specified in user record is not valid or not installed, not setting $LANG.");
|
||||
} else {
|
||||
_cleanup_free_ char *joined = NULL;
|
||||
|
||||
|
|
|
@ -3687,11 +3687,8 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
|
|||
.iov_base = buf,
|
||||
.iov_len = sizeof(buf)-1,
|
||||
};
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
|
||||
CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)];
|
||||
} control = {};
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred)) +
|
||||
CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)) control;
|
||||
struct msghdr msghdr = {
|
||||
.msg_iov = &iovec,
|
||||
.msg_iovlen = 1,
|
||||
|
|
|
@ -127,10 +127,7 @@ static int send_item(
|
|||
const char *name,
|
||||
int fd) {
|
||||
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(int))];
|
||||
} control = {};
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int))) control = {};
|
||||
struct iovec iovec;
|
||||
struct msghdr mh = {
|
||||
.msg_control = &control,
|
||||
|
@ -155,7 +152,6 @@ static int send_item(
|
|||
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
memcpy(CMSG_DATA(cmsg), &data_fd, sizeof(int));
|
||||
|
||||
mh.msg_controllen = CMSG_SPACE(sizeof(int));
|
||||
iovec = IOVEC_MAKE_STRING(name);
|
||||
|
||||
if (sendmsg(socket_fd, &mh, MSG_NOSIGNAL) < 0)
|
||||
|
@ -169,10 +165,7 @@ static int recv_item(
|
|||
char **ret_name,
|
||||
int *ret_fd) {
|
||||
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(int))];
|
||||
} control = {};
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int))) control;
|
||||
char buffer[PATH_MAX+2];
|
||||
struct iovec iov = IOVEC_INIT(buffer, sizeof(buffer)-1);
|
||||
struct msghdr mh = {
|
||||
|
|
|
@ -87,11 +87,8 @@ static int dns_stream_complete(DnsStream *s, int error) {
|
|||
}
|
||||
|
||||
static int dns_stream_identify(DnsStream *s) {
|
||||
union {
|
||||
struct cmsghdr header; /* For alignment */
|
||||
uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
|
||||
+ EXTRA_CMSG_SPACE /* kernel appears to require extra space */];
|
||||
} control;
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
|
||||
+ EXTRA_CMSG_SPACE /* kernel appears to require extra space */) control;
|
||||
struct msghdr mh = {};
|
||||
struct cmsghdr *cmsg;
|
||||
socklen_t sl;
|
||||
|
|
|
@ -741,12 +741,9 @@ Manager *manager_free(Manager *m) {
|
|||
|
||||
int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
|
||||
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
|
||||
union {
|
||||
struct cmsghdr header; /* For alignment */
|
||||
uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
|
||||
+ CMSG_SPACE(int) /* ttl/hoplimit */
|
||||
+ EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
|
||||
} control;
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
|
||||
+ CMSG_SPACE(int) /* ttl/hoplimit */
|
||||
+ EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */) control;
|
||||
union sockaddr_union sa;
|
||||
struct iovec iov;
|
||||
struct msghdr mh = {
|
||||
|
@ -930,10 +927,8 @@ static int manager_ipv4_send(
|
|||
uint16_t port,
|
||||
const struct in_addr *source,
|
||||
DnsPacket *p) {
|
||||
union {
|
||||
struct cmsghdr header; /* For alignment */
|
||||
uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
||||
} control = {};
|
||||
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in_pktinfo))) control = {};
|
||||
union sockaddr_union sa;
|
||||
struct iovec iov;
|
||||
struct msghdr mh = {
|
||||
|
@ -962,10 +957,10 @@ static int manager_ipv4_send(
|
|||
struct in_pktinfo *pi;
|
||||
|
||||
mh.msg_control = &control;
|
||||
mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
|
||||
mh.msg_controllen = sizeof(control);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&mh);
|
||||
cmsg->cmsg_len = mh.msg_controllen;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
|
||||
cmsg->cmsg_level = IPPROTO_IP;
|
||||
cmsg->cmsg_type = IP_PKTINFO;
|
||||
|
||||
|
@ -988,10 +983,7 @@ static int manager_ipv6_send(
|
|||
const struct in6_addr *source,
|
||||
DnsPacket *p) {
|
||||
|
||||
union {
|
||||
struct cmsghdr header; /* For alignment */
|
||||
uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
|
||||
} control = {};
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in6_pktinfo))) control = {};
|
||||
union sockaddr_union sa;
|
||||
struct iovec iov;
|
||||
struct msghdr mh = {
|
||||
|
@ -1021,10 +1013,10 @@ static int manager_ipv6_send(
|
|||
struct in6_pktinfo *pi;
|
||||
|
||||
mh.msg_control = &control;
|
||||
mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
|
||||
mh.msg_controllen = sizeof(control);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&mh);
|
||||
cmsg->cmsg_len = mh.msg_controllen;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
||||
cmsg->cmsg_level = IPPROTO_IPV6;
|
||||
cmsg->cmsg_type = IPV6_PKTINFO;
|
||||
|
||||
|
|
|
@ -859,13 +859,10 @@ int ask_password_agent(
|
|||
pollfd[FD_INOTIFY].events = POLLIN;
|
||||
|
||||
for (;;) {
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
|
||||
char passphrase[LINE_MAX+1];
|
||||
struct iovec iovec;
|
||||
struct ucred *ucred;
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
|
||||
} control;
|
||||
ssize_t n;
|
||||
int k;
|
||||
usec_t t;
|
||||
|
@ -917,7 +914,6 @@ int ask_password_agent(
|
|||
|
||||
iovec = IOVEC_MAKE(passphrase, sizeof(passphrase));
|
||||
|
||||
zero(control);
|
||||
struct msghdr msghdr = {
|
||||
.msg_iov = &iovec,
|
||||
.msg_iovlen = 1,
|
||||
|
|
|
@ -356,12 +356,30 @@ void user_record_show(UserRecord *hr, bool show_full_group_info) {
|
|||
char buf[FORMAT_BYTES_MAX];
|
||||
|
||||
if (hr->disk_size != UINT64_MAX) {
|
||||
const char *color_on, *color_off;
|
||||
unsigned permille;
|
||||
|
||||
permille = (unsigned) ((hr->disk_free * 1000U) / hr->disk_size); /* Round down! */
|
||||
printf(" Disk Free: %s (= %u.%01u%%)\n",
|
||||
|
||||
/* Color the output red or yellow if we are below 10% resp. 25% free. Because 10% and
|
||||
* 25% can be a lot of space still, let's additionally make some absolute
|
||||
* restrictions: 1G and 2G */
|
||||
if (permille <= 100U &&
|
||||
hr->disk_free < 1024U*1024U*1024U /* 1G */) {
|
||||
color_on = ansi_highlight_red();
|
||||
color_off = ansi_normal();
|
||||
} else if (permille <= 250U &&
|
||||
hr->disk_free < 2U*1024U*1024U*1024U /* 2G */) {
|
||||
color_on = ansi_highlight_yellow();
|
||||
color_off = ansi_normal();
|
||||
} else
|
||||
color_on = color_off = "";
|
||||
|
||||
printf(" Disk Free: %s%s (= %u.%01u%%)%s\n",
|
||||
color_on,
|
||||
format_bytes(buf, sizeof(buf), hr->disk_free),
|
||||
permille / 10, permille % 10);
|
||||
permille / 10, permille % 10,
|
||||
color_off);
|
||||
} else
|
||||
printf(" Disk Free: %s\n", format_bytes(buf, sizeof(buf), hr->disk_free));
|
||||
}
|
||||
|
|
|
@ -1814,7 +1814,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
break;
|
||||
|
||||
case ARG_ROOT:
|
||||
r = parse_path_argument_and_warn(optarg, true, &arg_root);
|
||||
r = parse_path_argument_and_warn(optarg, /* suppress_root= */ false, &arg_root);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
|
|
@ -36,6 +36,28 @@ static void test_locale_is_valid(void) {
|
|||
assert_se(!locale_is_valid("\x01gar\x02 bage\x03"));
|
||||
}
|
||||
|
||||
static void test_locale_is_installed(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
/* Always available */
|
||||
assert_se(locale_is_installed("POSIX") > 0);
|
||||
assert_se(locale_is_installed("C") > 0);
|
||||
|
||||
/* Might, or might not be installed. */
|
||||
assert_se(locale_is_installed("en_EN.utf8") >= 0);
|
||||
assert_se(locale_is_installed("fr_FR.utf8") >= 0);
|
||||
assert_se(locale_is_installed("fr_FR@euro") >= 0);
|
||||
assert_se(locale_is_installed("fi_FI") >= 0);
|
||||
|
||||
/* Definitely not valid */
|
||||
assert_se(locale_is_installed("") == 0);
|
||||
assert_se(locale_is_installed("/usr/bin/foo") == 0);
|
||||
assert_se(locale_is_installed("\x01gar\x02 bage\x03") == 0);
|
||||
|
||||
/* Definitely not installed */
|
||||
assert_se(locale_is_installed("zz_ZZ") == 0);
|
||||
}
|
||||
|
||||
static void test_keymaps(void) {
|
||||
_cleanup_strv_free_ char **kmaps = NULL;
|
||||
char **p;
|
||||
|
@ -98,6 +120,7 @@ static void dump_special_glyphs(void) {
|
|||
int main(int argc, char *argv[]) {
|
||||
test_get_locales();
|
||||
test_locale_is_valid();
|
||||
test_locale_is_installed();
|
||||
test_keymaps();
|
||||
|
||||
dump_special_glyphs();
|
||||
|
|
|
@ -407,10 +407,7 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
|
|||
.iov_base = &ntpmsg,
|
||||
.iov_len = sizeof(ntpmsg),
|
||||
};
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(struct timeval))];
|
||||
} control;
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct timeval))) control;
|
||||
union sockaddr_union server_addr;
|
||||
struct msghdr msghdr = {
|
||||
.msg_iov = &iov,
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "fd-util.h"
|
||||
#include "offline-passwd.h"
|
||||
#include "path-util.h"
|
||||
#include "user-util.h"
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(uid_gid_hash_ops, char, string_hash_func, string_compare_func, free);
|
||||
|
||||
int name_to_uid_offline(
|
||||
const char *root,
|
||||
const char *user,
|
||||
uid_t *ret_uid,
|
||||
Hashmap **cache) {
|
||||
|
||||
void *found;
|
||||
int r;
|
||||
|
||||
assert(user);
|
||||
assert(ret_uid);
|
||||
assert(cache);
|
||||
|
||||
if (!*cache) {
|
||||
_cleanup_(hashmap_freep) Hashmap *uid_by_name = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
struct passwd *pw;
|
||||
const char *passwd_path;
|
||||
|
||||
passwd_path = prefix_roota(root, "/etc/passwd");
|
||||
f = fopen(passwd_path, "re");
|
||||
if (!f)
|
||||
return errno == ENOENT ? -ESRCH : -errno;
|
||||
|
||||
uid_by_name = hashmap_new(&uid_gid_hash_ops);
|
||||
if (!uid_by_name)
|
||||
return -ENOMEM;
|
||||
|
||||
while ((r = fgetpwent_sane(f, &pw)) > 0) {
|
||||
_cleanup_free_ char *n = NULL;
|
||||
|
||||
n = strdup(pw->pw_name);
|
||||
if (!n)
|
||||
return -ENOMEM;
|
||||
|
||||
r = hashmap_put(uid_by_name, n, UID_TO_PTR(pw->pw_uid));
|
||||
if (r == -EEXIST) {
|
||||
log_warning_errno(r, "Duplicate entry in %s for %s: %m", passwd_path, pw->pw_name);
|
||||
continue;
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
TAKE_PTR(n);
|
||||
}
|
||||
|
||||
*cache = TAKE_PTR(uid_by_name);
|
||||
}
|
||||
|
||||
found = hashmap_get(*cache, user);
|
||||
if (!found)
|
||||
return -ESRCH;
|
||||
|
||||
*ret_uid = PTR_TO_UID(found);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int name_to_gid_offline(
|
||||
const char *root,
|
||||
const char *group,
|
||||
gid_t *ret_gid,
|
||||
Hashmap **cache) {
|
||||
|
||||
void *found;
|
||||
int r;
|
||||
|
||||
assert(group);
|
||||
assert(ret_gid);
|
||||
assert(cache);
|
||||
|
||||
if (!*cache) {
|
||||
_cleanup_(hashmap_freep) Hashmap *gid_by_name = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
struct group *gr;
|
||||
const char *group_path;
|
||||
|
||||
group_path = prefix_roota(root, "/etc/group");
|
||||
f = fopen(group_path, "re");
|
||||
if (!f)
|
||||
return errno == ENOENT ? -ESRCH : -errno;
|
||||
|
||||
gid_by_name = hashmap_new(&uid_gid_hash_ops);
|
||||
if (!gid_by_name)
|
||||
return -ENOMEM;
|
||||
|
||||
while ((r = fgetgrent_sane(f, &gr)) > 0) {
|
||||
_cleanup_free_ char *n = NULL;
|
||||
|
||||
n = strdup(gr->gr_name);
|
||||
if (!n)
|
||||
return -ENOMEM;
|
||||
|
||||
r = hashmap_put(gid_by_name, n, GID_TO_PTR(gr->gr_gid));
|
||||
if (r == -EEXIST) {
|
||||
log_warning_errno(r, "Duplicate entry in %s for %s: %m", group_path, gr->gr_name);
|
||||
continue;
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
TAKE_PTR(n);
|
||||
}
|
||||
|
||||
*cache = TAKE_PTR(gid_by_name);
|
||||
}
|
||||
|
||||
found = hashmap_get(*cache, group);
|
||||
if (!found)
|
||||
return -ESRCH;
|
||||
|
||||
*ret_gid = PTR_TO_GID(found);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "hashmap.h"
|
||||
|
||||
int name_to_uid_offline(const char *root, const char *user, uid_t *ret_uid, Hashmap **cache);
|
||||
int name_to_gid_offline(const char *root, const char *group, gid_t *ret_gid, Hashmap **cache);
|
|
@ -39,6 +39,7 @@
|
|||
#include "main-func.h"
|
||||
#include "mkdir.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "offline-passwd.h"
|
||||
#include "pager.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-lookup.h"
|
||||
|
@ -2488,7 +2489,63 @@ static int patch_var_run(const char *fname, unsigned line, char **path) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int parse_line(const char *fname, unsigned line, const char *buffer, bool *invalid_config) {
|
||||
static int find_uid(const char *user, uid_t *ret_uid, Hashmap **cache) {
|
||||
int r;
|
||||
|
||||
assert(user);
|
||||
assert(ret_uid);
|
||||
|
||||
/* First: parse as numeric UID string */
|
||||
r = parse_uid(user, ret_uid);
|
||||
if (r >= 0)
|
||||
return r;
|
||||
|
||||
/* Second: pass to NSS if we are running "online" */
|
||||
if (!arg_root)
|
||||
return get_user_creds(&user, ret_uid, NULL, NULL, NULL, 0);
|
||||
|
||||
/* Third, synthesize "root" unconditionally */
|
||||
if (streq(user, "root")) {
|
||||
*ret_uid = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fourth: use fgetpwent() to read /etc/passwd directly, if we are "offline" */
|
||||
return name_to_uid_offline(arg_root, user, ret_uid, cache);
|
||||
}
|
||||
|
||||
static int find_gid(const char *group, gid_t *ret_gid, Hashmap **cache) {
|
||||
int r;
|
||||
|
||||
assert(group);
|
||||
assert(ret_gid);
|
||||
|
||||
/* First: parse as numeric GID string */
|
||||
r = parse_gid(group, ret_gid);
|
||||
if (r >= 0)
|
||||
return r;
|
||||
|
||||
/* Second: pass to NSS if we are running "online" */
|
||||
if (!arg_root)
|
||||
return get_group_creds(&group, ret_gid, 0);
|
||||
|
||||
/* Third, synthesize "root" unconditionally */
|
||||
if (streq(group, "root")) {
|
||||
*ret_gid = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fourth: use fgetgrent() to read /etc/group directly, if we are "offline" */
|
||||
return name_to_gid_offline(arg_root, group, ret_gid, cache);
|
||||
}
|
||||
|
||||
static int parse_line(
|
||||
const char *fname,
|
||||
unsigned line,
|
||||
const char *buffer,
|
||||
bool *invalid_config,
|
||||
Hashmap **uid_cache,
|
||||
Hashmap **gid_cache) {
|
||||
|
||||
_cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
|
||||
_cleanup_(item_free_contents) Item i = {};
|
||||
|
@ -2610,7 +2667,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, bool
|
|||
|
||||
case COPY_FILES:
|
||||
if (!i.argument) {
|
||||
i.argument = path_join(arg_root, "/usr/share/factory", i.path);
|
||||
i.argument = path_join("/usr/share/factory", i.path);
|
||||
if (!i.argument)
|
||||
return log_oom();
|
||||
|
||||
|
@ -2618,7 +2675,9 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, bool
|
|||
*invalid_config = true;
|
||||
return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG), "Source path '%s' is not absolute.", i.argument);
|
||||
|
||||
} else if (arg_root) {
|
||||
}
|
||||
|
||||
if (!empty_or_root(arg_root)) {
|
||||
char *p;
|
||||
|
||||
p = path_join(arg_root, i.argument);
|
||||
|
@ -2709,7 +2768,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, bool
|
|||
return log_syntax(NULL, LOG_ERR, fname, line, r, "Failed to substitute specifiers in argument: %m");
|
||||
}
|
||||
|
||||
if (arg_root) {
|
||||
if (!empty_or_root(arg_root)) {
|
||||
char *p;
|
||||
|
||||
p = path_join(arg_root, i.path);
|
||||
|
@ -2719,9 +2778,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, bool
|
|||
}
|
||||
|
||||
if (!empty_or_dash(user)) {
|
||||
const char *u = user;
|
||||
|
||||
r = get_user_creds(&u, &i.uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING);
|
||||
r = find_uid(user, &i.uid, uid_cache);
|
||||
if (r < 0) {
|
||||
*invalid_config = true;
|
||||
return log_syntax(NULL, LOG_ERR, fname, line, r, "Failed to resolve user '%s': %m", user);
|
||||
|
@ -2731,9 +2788,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, bool
|
|||
}
|
||||
|
||||
if (!empty_or_dash(group)) {
|
||||
const char *g = group;
|
||||
|
||||
r = get_group_creds(&g, &i.gid, USER_CREDS_ALLOW_MISSING);
|
||||
r = find_gid(group, &i.gid, gid_cache);
|
||||
if (r < 0) {
|
||||
*invalid_config = true;
|
||||
return log_syntax(NULL, LOG_ERR, fname, line, r, "Failed to resolve group '%s'.", group);
|
||||
|
@ -2941,7 +2996,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
break;
|
||||
|
||||
case ARG_ROOT:
|
||||
r = parse_path_argument_and_warn(optarg, true, &arg_root);
|
||||
r = parse_path_argument_and_warn(optarg, /* suppress_root= */ false, &arg_root);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
@ -2982,6 +3037,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoent, bool *invalid_config) {
|
||||
_cleanup_(hashmap_freep) Hashmap *uid_cache = NULL, *gid_cache = NULL;
|
||||
_cleanup_fclose_ FILE *_f = NULL;
|
||||
Iterator iterator;
|
||||
unsigned v = 0;
|
||||
|
@ -3027,7 +3083,7 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe
|
|||
if (IN_SET(*l, 0, '#'))
|
||||
continue;
|
||||
|
||||
k = parse_line(fn, v, l, &invalid_line);
|
||||
k = parse_line(fn, v, l, &invalid_line, &uid_cache, &gid_cache);
|
||||
if (k < 0) {
|
||||
if (invalid_line)
|
||||
/* Allow reporting with a special code if the caller requested this */
|
||||
|
|
|
@ -189,12 +189,12 @@ static int udev_ctrl_connection_event_handler(sd_event_source *s, int fd, uint32
|
|||
_cleanup_(udev_ctrl_disconnect_and_listen_againp) struct udev_ctrl *uctrl = NULL;
|
||||
struct udev_ctrl_msg_wire msg_wire;
|
||||
struct iovec iov = IOVEC_MAKE(&msg_wire, sizeof(struct udev_ctrl_msg_wire));
|
||||
char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
|
||||
struct msghdr smsg = {
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = cred_msg,
|
||||
.msg_controllen = sizeof(cred_msg),
|
||||
.msg_control = &control,
|
||||
.msg_controllen = sizeof(control),
|
||||
};
|
||||
struct cmsghdr *cmsg;
|
||||
struct ucred *cred;
|
||||
|
|
|
@ -906,10 +906,7 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat
|
|||
.iov_base = &msg,
|
||||
.iov_len = sizeof(msg),
|
||||
};
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
|
||||
} control = {};
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
|
||||
struct msghdr msghdr = {
|
||||
.msg_iov = &iovec,
|
||||
.msg_iovlen = 1,
|
||||
|
|
Loading…
Reference in New Issue