systemd: merge branch systemd into main
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1333
This commit is contained in:
@@ -66,20 +66,26 @@ int dhcp_validate_duid_len(DUIDType duid_type, size_t duid_len, bool strict) {
|
||||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
static int dhcp_identifier_set_duid_llt(const uint8_t *addr, size_t addr_len, uint16_t arp_type, usec_t t, struct duid *ret_duid, size_t *ret_len) {
|
||||
static int dhcp_identifier_set_duid_llt(
|
||||
const struct hw_addr_data *hw_addr,
|
||||
uint16_t arp_type,
|
||||
usec_t t,
|
||||
struct duid *ret_duid,
|
||||
size_t *ret_len) {
|
||||
|
||||
uint16_t time_from_2000y;
|
||||
|
||||
assert(addr);
|
||||
assert(hw_addr);
|
||||
assert(ret_duid);
|
||||
assert(ret_len);
|
||||
|
||||
if (addr_len == 0)
|
||||
if (hw_addr->length == 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (arp_type == ARPHRD_ETHER)
|
||||
assert_return(addr_len == ETH_ALEN, -EINVAL);
|
||||
assert_return(hw_addr->length == ETH_ALEN, -EINVAL);
|
||||
else if (arp_type == ARPHRD_INFINIBAND)
|
||||
assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
|
||||
assert_return(hw_addr->length == INFINIBAND_ALEN, -EINVAL);
|
||||
else
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
@@ -91,33 +97,38 @@ static int dhcp_identifier_set_duid_llt(const uint8_t *addr, size_t addr_len, ui
|
||||
unaligned_write_be16(&ret_duid->type, DUID_TYPE_LLT);
|
||||
unaligned_write_be16(&ret_duid->llt.htype, arp_type);
|
||||
unaligned_write_be32(&ret_duid->llt.time, time_from_2000y);
|
||||
memcpy(ret_duid->llt.haddr, addr, addr_len);
|
||||
memcpy(ret_duid->llt.haddr, hw_addr->bytes, hw_addr->length);
|
||||
|
||||
*ret_len = offsetof(struct duid, llt.haddr) + addr_len;
|
||||
*ret_len = offsetof(struct duid, llt.haddr) + hw_addr->length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dhcp_identifier_set_duid_ll(const uint8_t *addr, size_t addr_len, uint16_t arp_type, struct duid *ret_duid, size_t *ret_len) {
|
||||
assert(addr);
|
||||
static int dhcp_identifier_set_duid_ll(
|
||||
const struct hw_addr_data *hw_addr,
|
||||
uint16_t arp_type,
|
||||
struct duid *ret_duid,
|
||||
size_t *ret_len) {
|
||||
|
||||
assert(hw_addr);
|
||||
assert(ret_duid);
|
||||
assert(ret_len);
|
||||
|
||||
if (addr_len == 0)
|
||||
if (hw_addr->length == 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (arp_type == ARPHRD_ETHER)
|
||||
assert_return(addr_len == ETH_ALEN, -EINVAL);
|
||||
assert_return(hw_addr->length == ETH_ALEN, -EINVAL);
|
||||
else if (arp_type == ARPHRD_INFINIBAND)
|
||||
assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
|
||||
assert_return(hw_addr->length == INFINIBAND_ALEN, -EINVAL);
|
||||
else
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
unaligned_write_be16(&ret_duid->type, DUID_TYPE_LL);
|
||||
unaligned_write_be16(&ret_duid->ll.htype, arp_type);
|
||||
memcpy(ret_duid->ll.haddr, addr, addr_len);
|
||||
memcpy(ret_duid->ll.haddr, hw_addr->bytes, hw_addr->length);
|
||||
|
||||
*ret_len = offsetof(struct duid, ll.haddr) + addr_len;
|
||||
*ret_len = offsetof(struct duid, ll.haddr) + hw_addr->length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -179,8 +190,7 @@ static int dhcp_identifier_set_duid_uuid(struct duid *ret_duid, size_t *ret_len)
|
||||
|
||||
int dhcp_identifier_set_duid(
|
||||
DUIDType duid_type,
|
||||
const uint8_t *addr,
|
||||
size_t addr_len,
|
||||
const struct hw_addr_data *hw_addr,
|
||||
uint16_t arp_type,
|
||||
usec_t llt_time,
|
||||
bool test_mode,
|
||||
@@ -189,11 +199,11 @@ int dhcp_identifier_set_duid(
|
||||
|
||||
switch (duid_type) {
|
||||
case DUID_TYPE_LLT:
|
||||
return dhcp_identifier_set_duid_llt(addr, addr_len, arp_type, llt_time, ret_duid, ret_len);
|
||||
return dhcp_identifier_set_duid_llt(hw_addr, arp_type, llt_time, ret_duid, ret_len);
|
||||
case DUID_TYPE_EN:
|
||||
return dhcp_identifier_set_duid_en(test_mode, ret_duid, ret_len);
|
||||
case DUID_TYPE_LL:
|
||||
return dhcp_identifier_set_duid_ll(addr, addr_len, arp_type, ret_duid, ret_len);
|
||||
return dhcp_identifier_set_duid_ll(hw_addr, arp_type, ret_duid, ret_len);
|
||||
case DUID_TYPE_UUID:
|
||||
return dhcp_identifier_set_duid_uuid(ret_duid, ret_len);
|
||||
default:
|
||||
@@ -204,8 +214,7 @@ int dhcp_identifier_set_duid(
|
||||
|
||||
int dhcp_identifier_set_iaid(
|
||||
int ifindex,
|
||||
const uint8_t *mac,
|
||||
size_t mac_len,
|
||||
const struct hw_addr_data *hw_addr,
|
||||
bool legacy_unstable_byteorder,
|
||||
bool use_mac,
|
||||
void *ret) {
|
||||
@@ -219,6 +228,10 @@ int dhcp_identifier_set_iaid(
|
||||
uint64_t id;
|
||||
int r;
|
||||
|
||||
assert(ifindex > 0);
|
||||
assert(hw_addr);
|
||||
assert(ret);
|
||||
|
||||
if (udev_available() && !use_mac) {
|
||||
/* udev should be around */
|
||||
|
||||
@@ -247,7 +260,7 @@ int dhcp_identifier_set_iaid(
|
||||
id = siphash24(name, strlen(name), HASH_KEY.bytes);
|
||||
else
|
||||
/* fall back to MAC address if no predictable name available */
|
||||
id = siphash24(mac, mac_len, HASH_KEY.bytes);
|
||||
id = siphash24(hw_addr->bytes, hw_addr->length, HASH_KEY.bytes);
|
||||
|
||||
id32 = (id & 0xffffffff) ^ (id >> 32);
|
||||
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "sd-id128.h"
|
||||
|
||||
#include "ether-addr-util.h"
|
||||
#include "macro.h"
|
||||
#include "sparse-endian.h"
|
||||
#include "time-util.h"
|
||||
@@ -58,8 +59,7 @@ int dhcp_validate_duid_len(DUIDType duid_type, size_t duid_len, bool strict);
|
||||
int dhcp_identifier_set_duid_en(bool test_mode, struct duid *ret_duid, size_t *ret_len);
|
||||
int dhcp_identifier_set_duid(
|
||||
DUIDType duid_type,
|
||||
const uint8_t *addr,
|
||||
size_t addr_len,
|
||||
const struct hw_addr_data *hw_addr,
|
||||
uint16_t arp_type,
|
||||
usec_t llt_time,
|
||||
bool test_mode,
|
||||
@@ -67,8 +67,7 @@ int dhcp_identifier_set_duid(
|
||||
size_t *ret_len);
|
||||
int dhcp_identifier_set_iaid(
|
||||
int ifindex,
|
||||
const uint8_t *mac,
|
||||
size_t mac_len,
|
||||
const struct hw_addr_data *hw_addr,
|
||||
bool legacy_unstable_byteorder,
|
||||
bool use_mac,
|
||||
void *ret);
|
||||
|
@@ -71,6 +71,7 @@ struct sd_dhcp6_client {
|
||||
char **vendor_class;
|
||||
OrderedHashmap *extra_options;
|
||||
OrderedSet *vendor_options;
|
||||
bool rapid_commit;
|
||||
|
||||
struct sd_dhcp6_lease *lease;
|
||||
|
||||
|
@@ -510,7 +510,7 @@ int dhcp6_option_parse(
|
||||
if (buflen < offsetof(DHCP6Option, data))
|
||||
return -EBADMSG;
|
||||
|
||||
if (*offset >= buflen - offsetof(DHCP6Option, data))
|
||||
if (*offset > buflen - offsetof(DHCP6Option, data))
|
||||
return -EBADMSG;
|
||||
|
||||
len = unaligned_read_be16(buf + *offset + offsetof(DHCP6Option, len));
|
||||
@@ -520,14 +520,14 @@ int dhcp6_option_parse(
|
||||
|
||||
*ret_option_code = unaligned_read_be16(buf + *offset + offsetof(DHCP6Option, code));
|
||||
*ret_option_data_len = len;
|
||||
*ret_option_data = buf + *offset + offsetof(DHCP6Option, data);
|
||||
*ret_option_data = len == 0 ? NULL : buf + *offset + offsetof(DHCP6Option, data);
|
||||
*offset += offsetof(DHCP6Option, data) + len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp6_option_parse_status(const uint8_t *data, size_t data_len, char **ret_status_message) {
|
||||
assert(data);
|
||||
assert(data || data_len == 0);
|
||||
|
||||
if (data_len < sizeof(uint16_t))
|
||||
return -EBADMSG;
|
||||
@@ -805,7 +805,7 @@ int dhcp6_option_parse_addresses(
|
||||
struct in6_addr **addrs,
|
||||
size_t *count) {
|
||||
|
||||
assert(optval);
|
||||
assert(optval || optlen == 0);
|
||||
assert(addrs);
|
||||
assert(count);
|
||||
|
||||
@@ -828,8 +828,8 @@ static int parse_domain(const uint8_t **data, size_t *len, char **ret) {
|
||||
int r;
|
||||
|
||||
assert(data);
|
||||
assert(*data);
|
||||
assert(len);
|
||||
assert(*data || *len == 0);
|
||||
assert(ret);
|
||||
|
||||
optval = *data;
|
||||
@@ -893,7 +893,7 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, size_t optlen, char **r
|
||||
_cleanup_free_ char *domain = NULL;
|
||||
int r;
|
||||
|
||||
assert(optval);
|
||||
assert(optval || optlen == 0);
|
||||
assert(ret);
|
||||
|
||||
r = parse_domain(&optval, &optlen, &domain);
|
||||
@@ -912,7 +912,7 @@ int dhcp6_option_parse_domainname_list(const uint8_t *optval, size_t optlen, cha
|
||||
_cleanup_strv_free_ char **names = NULL;
|
||||
int r;
|
||||
|
||||
assert(optval);
|
||||
assert(optval || optlen == 0);
|
||||
assert(ret);
|
||||
|
||||
if (optlen <= 1)
|
||||
|
@@ -122,9 +122,8 @@ int sd_dhcp6_client_set_mac(
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(client->hw_addr.bytes, addr, addr_len);
|
||||
client->hw_addr.length = addr_len;
|
||||
client->arp_type = arp_type;
|
||||
hw_addr_set(&client->hw_addr, addr, addr_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -223,8 +222,8 @@ static int dhcp6_client_set_duid_internal(
|
||||
|
||||
} else {
|
||||
#if 0 /* NM_IGNORED */
|
||||
r = dhcp_identifier_set_duid(duid_type, client->hw_addr.bytes, client->hw_addr.length,
|
||||
client->arp_type, llt_time, client->test_mode, &client->duid, &client->duid_len);
|
||||
r = dhcp_identifier_set_duid(duid_type, &client->hw_addr, client->arp_type, llt_time,
|
||||
client->test_mode, &client->duid, &client->duid_len);
|
||||
if (r == -EOPNOTSUPP)
|
||||
return log_dhcp6_client_errno(client, r,
|
||||
"Failed to set %s. MAC address is not set or "
|
||||
@@ -310,7 +309,7 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
|
||||
if (client->iaid_set)
|
||||
return 0;
|
||||
|
||||
r = dhcp_identifier_set_iaid(client->ifindex, client->hw_addr.bytes, client->hw_addr.length,
|
||||
r = dhcp_identifier_set_iaid(client->ifindex, &client->hw_addr,
|
||||
/* legacy_unstable_byteorder = */ true,
|
||||
/* use_mac = */ client->test_mode,
|
||||
&iaid);
|
||||
@@ -501,6 +500,14 @@ int dhcp6_client_set_transaction_id(sd_dhcp6_client *client, uint32_t transactio
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_rapid_commit(sd_dhcp6_client *client, int enable) {
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(!sd_dhcp6_client_is_running(client), -EBUSY);
|
||||
|
||||
client->rapid_commit = enable;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) {
|
||||
assert_return(client, -EINVAL);
|
||||
|
||||
@@ -724,9 +731,11 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) {
|
||||
break;
|
||||
|
||||
case DHCP6_STATE_SOLICITATION:
|
||||
r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (client->rapid_commit) {
|
||||
r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = client_append_common_options_in_managed_mode(client, &opt, &optlen,
|
||||
&client->ia_na, &client->ia_pd);
|
||||
@@ -1170,6 +1179,10 @@ static int client_process_advertise_or_rapid_commit_reply(
|
||||
if (message->type == DHCP6_MESSAGE_REPLY) {
|
||||
bool rapid_commit;
|
||||
|
||||
if (!client->rapid_commit)
|
||||
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Received unexpected reply message, even we sent a solicit message without the rapid commit option, ignoring.");
|
||||
|
||||
r = dhcp6_lease_get_rapid_commit(lease, &rapid_commit);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -1477,6 +1490,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
|
||||
.ifindex = -1,
|
||||
.request_ia = DHCP6_REQUEST_IA_NA | DHCP6_REQUEST_IA_PD,
|
||||
.fd = -1,
|
||||
.rapid_commit = true,
|
||||
};
|
||||
|
||||
*ret = TAKE_PTR(client);
|
||||
|
@@ -469,7 +469,9 @@ static int dhcp6_lease_parse_message(
|
||||
|
||||
r = dhcp6_option_parse(message->options, len, &offset, &optcode, &optlen, &optval);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_dhcp6_client_errno(client, r,
|
||||
"Failed to parse option header at offset %zu of total length %zu: %m",
|
||||
offset, len);
|
||||
|
||||
switch (optcode) {
|
||||
case SD_DHCP6_OPTION_CLIENTID:
|
||||
@@ -479,7 +481,7 @@ static int dhcp6_lease_parse_message(
|
||||
|
||||
r = dhcp6_lease_set_clientid(lease, optval, optlen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_dhcp6_client_errno(client, r, "Failed to set client ID: %m");
|
||||
|
||||
break;
|
||||
|
||||
@@ -490,17 +492,17 @@ static int dhcp6_lease_parse_message(
|
||||
|
||||
r = dhcp6_lease_set_serverid(lease, optval, optlen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_dhcp6_client_errno(client, r, "Failed to set server ID: %m");
|
||||
|
||||
break;
|
||||
|
||||
case SD_DHCP6_OPTION_PREFERENCE:
|
||||
if (optlen != 1)
|
||||
return -EINVAL;
|
||||
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Received invalid length for preference.");
|
||||
|
||||
r = dhcp6_lease_set_preference(lease, optval[0]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_dhcp6_client_errno(client, r, "Failed to set preference: %m");
|
||||
|
||||
break;
|
||||
|
||||
@@ -509,7 +511,7 @@ static int dhcp6_lease_parse_message(
|
||||
|
||||
r = dhcp6_option_parse_status(optval, optlen, &msg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_dhcp6_client_errno(client, r, "Failed to parse status code: %m");
|
||||
|
||||
if (r > 0)
|
||||
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
|
||||
@@ -529,9 +531,11 @@ static int dhcp6_lease_parse_message(
|
||||
|
||||
r = dhcp6_option_parse_ia(client, client->ia_na.header.id, optcode, optlen, optval, &ia);
|
||||
if (r == -ENOMEM)
|
||||
return r;
|
||||
if (r < 0)
|
||||
return log_oom_debug();
|
||||
if (r < 0) {
|
||||
log_dhcp6_client_errno(client, r, "Failed to parse IA_NA option, ignoring: %m");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lease->ia_na) {
|
||||
log_dhcp6_client(client, "Received duplicate matching IA_NA option, ignoring.");
|
||||
@@ -552,9 +556,11 @@ static int dhcp6_lease_parse_message(
|
||||
|
||||
r = dhcp6_option_parse_ia(client, client->ia_pd.header.id, optcode, optlen, optval, &ia);
|
||||
if (r == -ENOMEM)
|
||||
return r;
|
||||
if (r < 0)
|
||||
return log_oom_debug();
|
||||
if (r < 0) {
|
||||
log_dhcp6_client_errno(client, r, "Failed to parse IA_PD option, ignoring: %m");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lease->ia_pd) {
|
||||
log_dhcp6_client(client, "Received duplicate matching IA_PD option, ignoring.");
|
||||
@@ -566,9 +572,12 @@ static int dhcp6_lease_parse_message(
|
||||
break;
|
||||
}
|
||||
case SD_DHCP6_OPTION_RAPID_COMMIT:
|
||||
if (optlen != 0)
|
||||
log_dhcp6_client(client, "Received rapid commit option with an invalid length (%zu), ignoring.", optlen);
|
||||
|
||||
r = dhcp6_lease_set_rapid_commit(lease);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_dhcp6_client_errno(client, r, "Failed to set rapid commit flag: %m");
|
||||
|
||||
break;
|
||||
|
||||
@@ -609,7 +618,8 @@ static int dhcp6_lease_parse_message(
|
||||
|
||||
case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME:
|
||||
if (optlen != 4)
|
||||
return -EINVAL;
|
||||
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Received information refresh time option with an invalid length (%zu).", optlen);
|
||||
|
||||
irt = unaligned_read_be32((be32_t *) optval) * USEC_PER_SEC;
|
||||
break;
|
||||
|
@@ -51,19 +51,19 @@ static bool event_source_is_offline(sd_event_source *s) {
|
||||
}
|
||||
|
||||
static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] = {
|
||||
[SOURCE_IO] = "io",
|
||||
[SOURCE_TIME_REALTIME] = "realtime",
|
||||
[SOURCE_TIME_BOOTTIME] = "bootime",
|
||||
[SOURCE_TIME_MONOTONIC] = "monotonic",
|
||||
[SOURCE_IO] = "io",
|
||||
[SOURCE_TIME_REALTIME] = "realtime",
|
||||
[SOURCE_TIME_BOOTTIME] = "bootime",
|
||||
[SOURCE_TIME_MONOTONIC] = "monotonic",
|
||||
[SOURCE_TIME_REALTIME_ALARM] = "realtime-alarm",
|
||||
[SOURCE_TIME_BOOTTIME_ALARM] = "boottime-alarm",
|
||||
[SOURCE_SIGNAL] = "signal",
|
||||
[SOURCE_CHILD] = "child",
|
||||
[SOURCE_DEFER] = "defer",
|
||||
[SOURCE_POST] = "post",
|
||||
[SOURCE_EXIT] = "exit",
|
||||
[SOURCE_WATCHDOG] = "watchdog",
|
||||
[SOURCE_INOTIFY] = "inotify",
|
||||
[SOURCE_SIGNAL] = "signal",
|
||||
[SOURCE_CHILD] = "child",
|
||||
[SOURCE_DEFER] = "defer",
|
||||
[SOURCE_POST] = "post",
|
||||
[SOURCE_EXIT] = "exit",
|
||||
[SOURCE_WATCHDOG] = "watchdog",
|
||||
[SOURCE_INOTIFY] = "inotify",
|
||||
};
|
||||
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int);
|
||||
@@ -126,10 +126,10 @@ struct sd_event {
|
||||
Hashmap *inotify_data; /* indexed by priority */
|
||||
|
||||
/* A list of inode structures that still have an fd open, that we need to close before the next loop iteration */
|
||||
LIST_HEAD(struct inode_data, inode_data_to_close);
|
||||
LIST_HEAD(struct inode_data, inode_data_to_close_list);
|
||||
|
||||
/* A list of inotify objects that already have events buffered which aren't processed yet */
|
||||
LIST_HEAD(struct inotify_data, inotify_data_buffered);
|
||||
LIST_HEAD(struct inotify_data, buffered_inotify_data_list);
|
||||
|
||||
pid_t original_pid;
|
||||
|
||||
@@ -422,6 +422,8 @@ fail:
|
||||
}
|
||||
|
||||
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event, sd_event, event_free);
|
||||
#define PROTECT_EVENT(e) \
|
||||
_unused_ _cleanup_(sd_event_unrefp) sd_event *_ref = sd_event_ref(e);
|
||||
|
||||
_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) {
|
||||
if (s)
|
||||
@@ -1696,7 +1698,7 @@ static void event_free_inotify_data(sd_event *e, struct inotify_data *d) {
|
||||
assert(hashmap_isempty(d->wd));
|
||||
|
||||
if (d->buffer_filled > 0)
|
||||
LIST_REMOVE(buffered, e->inotify_data_buffered, d);
|
||||
LIST_REMOVE(buffered, e->buffered_inotify_data_list, d);
|
||||
|
||||
hashmap_free(d->inodes);
|
||||
hashmap_free(d->wd);
|
||||
@@ -1805,10 +1807,10 @@ static void event_free_inode_data(
|
||||
if (!d)
|
||||
return;
|
||||
|
||||
assert(LIST_IS_EMPTY(d->event_sources));
|
||||
assert(!d->event_sources);
|
||||
|
||||
if (d->fd >= 0) {
|
||||
LIST_REMOVE(to_close, e->inode_data_to_close, d);
|
||||
LIST_REMOVE(to_close, e->inode_data_to_close_list, d);
|
||||
safe_close(d->fd);
|
||||
}
|
||||
|
||||
@@ -1868,7 +1870,7 @@ static void event_gc_inode_data(
|
||||
if (!d)
|
||||
return;
|
||||
|
||||
if (!LIST_IS_EMPTY(d->event_sources))
|
||||
if (d->event_sources)
|
||||
return;
|
||||
|
||||
inotify_data = d->inotify_data;
|
||||
@@ -2070,7 +2072,7 @@ static int event_add_inotify_fd_internal(
|
||||
}
|
||||
}
|
||||
|
||||
LIST_PREPEND(to_close, e->inode_data_to_close, inode_data);
|
||||
LIST_PREPEND(to_close, e->inode_data_to_close_list, inode_data);
|
||||
}
|
||||
|
||||
/* Link our event source to the inode data object */
|
||||
@@ -2143,12 +2145,9 @@ static sd_event_source* event_source_free(sd_event_source *s) {
|
||||
* we still retain a valid event source object after
|
||||
* the callback. */
|
||||
|
||||
if (s->dispatching) {
|
||||
if (s->type == SOURCE_IO)
|
||||
source_io_unregister(s);
|
||||
|
||||
if (s->dispatching)
|
||||
source_disconnect(s);
|
||||
} else
|
||||
else
|
||||
source_free(s);
|
||||
|
||||
return NULL;
|
||||
@@ -2357,7 +2356,7 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LIST_PREPEND(to_close, s->event->inode_data_to_close, new_inode_data);
|
||||
LIST_PREPEND(to_close, s->event->inode_data_to_close_list, new_inode_data);
|
||||
}
|
||||
|
||||
/* Move the event source to the new inode data structure */
|
||||
@@ -3423,7 +3422,7 @@ static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t
|
||||
|
||||
assert(n > 0);
|
||||
d->buffer_filled = (size_t) n;
|
||||
LIST_PREPEND(buffered, e->inotify_data_buffered, d);
|
||||
LIST_PREPEND(buffered, e->buffered_inotify_data_list, d);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -3441,7 +3440,7 @@ static void event_inotify_data_drop(sd_event *e, struct inotify_data *d, size_t
|
||||
d->buffer_filled -= sz;
|
||||
|
||||
if (d->buffer_filled == 0)
|
||||
LIST_REMOVE(buffered, e->inotify_data_buffered, d);
|
||||
LIST_REMOVE(buffered, e->buffered_inotify_data_list, d);
|
||||
}
|
||||
|
||||
static int event_inotify_data_process(sd_event *e, struct inotify_data *d) {
|
||||
@@ -3534,7 +3533,7 @@ static int process_inotify(sd_event *e) {
|
||||
|
||||
assert(e);
|
||||
|
||||
LIST_FOREACH(buffered, d, e->inotify_data_buffered) {
|
||||
LIST_FOREACH(buffered, d, e->buffered_inotify_data_list) {
|
||||
r = event_inotify_data_process(e, d);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -3546,8 +3545,8 @@ static int process_inotify(sd_event *e) {
|
||||
}
|
||||
|
||||
static int source_dispatch(sd_event_source *s) {
|
||||
_cleanup_(sd_event_unrefp) sd_event *saved_event = NULL;
|
||||
EventSourceType saved_type;
|
||||
sd_event *saved_event;
|
||||
int r = 0;
|
||||
|
||||
assert(s);
|
||||
@@ -3559,7 +3558,8 @@ static int source_dispatch(sd_event_source *s) {
|
||||
|
||||
/* Similarly, store a reference to the event loop object, so that we can still access it after the
|
||||
* callback might have invalidated/disconnected the event source. */
|
||||
saved_event = sd_event_ref(s->event);
|
||||
saved_event = s->event;
|
||||
PROTECT_EVENT(saved_event);
|
||||
|
||||
/* Check if we hit the ratelimit for this event source, and if so, let's disable it. */
|
||||
assert(!s->ratelimited);
|
||||
@@ -3760,7 +3760,7 @@ static int dispatch_exit(sd_event *e) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
|
||||
PROTECT_EVENT(e);
|
||||
e->iteration++;
|
||||
e->state = SD_EVENT_EXITING;
|
||||
r = source_dispatch(p);
|
||||
@@ -3831,11 +3831,11 @@ static void event_close_inode_data_fds(sd_event *e) {
|
||||
* for the inode). Hence, let's close them when entering the first iteration after they were added, as a
|
||||
* compromise. */
|
||||
|
||||
while ((d = e->inode_data_to_close)) {
|
||||
while ((d = e->inode_data_to_close_list)) {
|
||||
assert(d->fd >= 0);
|
||||
d->fd = safe_close(d->fd);
|
||||
|
||||
LIST_REMOVE(to_close, e->inode_data_to_close, d);
|
||||
LIST_REMOVE(to_close, e->inode_data_to_close_list, d);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3854,7 +3854,7 @@ _public_ int sd_event_prepare(sd_event *e) {
|
||||
assert_return(!e->default_event_ptr || e->tid == gettid(), -EREMOTEIO);
|
||||
|
||||
/* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */
|
||||
_unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
|
||||
PROTECT_EVENT(e);
|
||||
|
||||
if (e->exit_requested)
|
||||
goto pending;
|
||||
@@ -3889,7 +3889,7 @@ _public_ int sd_event_prepare(sd_event *e) {
|
||||
|
||||
event_close_inode_data_fds(e);
|
||||
|
||||
if (event_next_pending(e) || e->need_process_child || !LIST_IS_EMPTY(e->inotify_data_buffered))
|
||||
if (event_next_pending(e) || e->need_process_child || e->buffered_inotify_data_list)
|
||||
goto pending;
|
||||
|
||||
e->state = SD_EVENT_ARMED;
|
||||
@@ -3969,7 +3969,7 @@ static int process_epoll(sd_event *e, usec_t timeout, int64_t threshold, int64_t
|
||||
n_event_max = MALLOC_ELEMENTSOF(e->event_queue);
|
||||
|
||||
/* If we still have inotify data buffered, then query the other fds, but don't wait on it */
|
||||
if (!LIST_IS_EMPTY(e->inotify_data_buffered))
|
||||
if (e->buffered_inotify_data_list)
|
||||
timeout = 0;
|
||||
|
||||
for (;;) {
|
||||
@@ -4184,7 +4184,7 @@ _public_ int sd_event_dispatch(sd_event *e) {
|
||||
|
||||
p = event_next_pending(e);
|
||||
if (p) {
|
||||
_unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
|
||||
PROTECT_EVENT(e);
|
||||
|
||||
e->state = SD_EVENT_RUNNING;
|
||||
r = source_dispatch(p);
|
||||
@@ -4236,7 +4236,7 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
|
||||
}
|
||||
|
||||
/* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */
|
||||
_unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
|
||||
PROTECT_EVENT(e);
|
||||
|
||||
r = sd_event_prepare(e);
|
||||
if (r == 0)
|
||||
@@ -4266,7 +4266,7 @@ _public_ int sd_event_loop(sd_event *e) {
|
||||
assert_return(!event_pid_changed(e), -ECHILD);
|
||||
assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
|
||||
|
||||
_unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
|
||||
PROTECT_EVENT(e);
|
||||
|
||||
while (e->state != SD_EVENT_FINISHED) {
|
||||
r = sd_event_run(e, UINT64_MAX);
|
||||
|
@@ -85,7 +85,7 @@ typedef void (*_sd_destroy_t)(void *userdata);
|
||||
#endif
|
||||
|
||||
#ifndef _SD_ARRAY_STATIC
|
||||
# if __STDC_VERSION__ >= 199901L
|
||||
# if __STDC_VERSION__ >= 199901L && !defined(__cplusplus)
|
||||
# define _SD_ARRAY_STATIC static
|
||||
# else
|
||||
# define _SD_ARRAY_STATIC
|
||||
|
@@ -262,6 +262,7 @@ int sd_dhcp6_client_set_address_request(sd_dhcp6_client *client,
|
||||
int request);
|
||||
int sd_dhcp6_client_add_vendor_option(sd_dhcp6_client *client,
|
||||
sd_dhcp6_option *v);
|
||||
int sd_dhcp6_client_set_rapid_commit(sd_dhcp6_client *client, int enable);
|
||||
|
||||
int sd_dhcp6_client_get_lease(
|
||||
sd_dhcp6_client *client,
|
||||
|
@@ -51,6 +51,8 @@
|
||||
|
||||
#define LOG_TRACE 0
|
||||
|
||||
#define WANT_LINUX_FS_H 0
|
||||
|
||||
#define BUILD_MODE_DEVELOPER (NM_MORE_ASSERTS > 0)
|
||||
|
||||
#define LOG_MESSAGE_VERIFICATION (NM_MORE_ASSERTS > 0)
|
||||
|
@@ -50,16 +50,30 @@ typedef void* (*mfree_func_t)(void *p);
|
||||
|
||||
#define malloc0(n) (calloc(1, (n) ?: 1))
|
||||
|
||||
#define free_and_replace(a, b) \
|
||||
#define free_and_replace_full(a, b, free_func) \
|
||||
({ \
|
||||
typeof(a)* _a = &(a); \
|
||||
typeof(b)* _b = &(b); \
|
||||
free(*_a); \
|
||||
free_func(*_a); \
|
||||
*_a = *_b; \
|
||||
*_b = NULL; \
|
||||
0; \
|
||||
})
|
||||
|
||||
#define free_and_replace(a, b) \
|
||||
free_and_replace_full(a, b, free)
|
||||
|
||||
/* This is similar to free_and_replace_full(), but NULL is not assigned to 'b', and its reference counter is
|
||||
* increased. */
|
||||
#define unref_and_replace_full(a, b, ref_func, unref_func) \
|
||||
({ \
|
||||
typeof(a)* _a = &(a); \
|
||||
typeof(b) _b = ref_func(b); \
|
||||
unref_func(*_a); \
|
||||
*_a = _b; \
|
||||
0; \
|
||||
})
|
||||
|
||||
void* memdup(const void *p, size_t l) _alloc_(2);
|
||||
void* memdup_suffix0(const void *p, size_t l); /* We can't use _alloc_() here, since we return a buffer one byte larger than the specified size */
|
||||
|
||||
|
@@ -35,6 +35,15 @@ char *hw_addr_to_string_full(
|
||||
return buffer;
|
||||
}
|
||||
|
||||
struct hw_addr_data *hw_addr_set(struct hw_addr_data *addr, const uint8_t *bytes, size_t length) {
|
||||
assert(addr);
|
||||
assert(length <= HW_ADDR_MAX_SIZE);
|
||||
|
||||
addr->length = length;
|
||||
memcpy_safe(addr->bytes, bytes, length);
|
||||
return addr;
|
||||
}
|
||||
|
||||
int hw_addr_compare(const struct hw_addr_data *a, const struct hw_addr_data *b) {
|
||||
int r;
|
||||
|
||||
|
@@ -52,6 +52,8 @@ static inline char *hw_addr_to_string(const struct hw_addr_data *addr, char buff
|
||||
|
||||
#define HW_ADDR_NULL ((const struct hw_addr_data){})
|
||||
|
||||
struct hw_addr_data *hw_addr_set(struct hw_addr_data *addr, const uint8_t *bytes, size_t length);
|
||||
|
||||
void hw_addr_hash_func(const struct hw_addr_data *p, struct siphash *state);
|
||||
int hw_addr_compare(const struct hw_addr_data *a, const struct hw_addr_data *b);
|
||||
static inline bool hw_addr_equal(const struct hw_addr_data *a, const struct hw_addr_data *b) {
|
||||
|
@@ -5,7 +5,9 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/btrfs.h>
|
||||
#if WANT_LINUX_FS_H
|
||||
#include <linux/fs.h>
|
||||
#endif
|
||||
#include <linux/magic.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/resource.h>
|
||||
|
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "hash-funcs.h"
|
||||
#include "path-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
void string_hash_func(const char *p, struct siphash *state) {
|
||||
siphash24_compress(p, strlen(p) + 1, state);
|
||||
@@ -17,6 +18,9 @@ DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(string_hash_ops_free,
|
||||
DEFINE_HASH_OPS_FULL(string_hash_ops_free_free,
|
||||
char, string_hash_func, string_compare_func, free,
|
||||
void, free);
|
||||
DEFINE_HASH_OPS_FULL(string_hash_ops_free_strv_free,
|
||||
char, string_hash_func, string_compare_func, free,
|
||||
char*, strv_free);
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
void path_hash_func(const char *q, struct siphash *state) {
|
||||
|
@@ -78,6 +78,7 @@ void string_hash_func(const char *p, struct siphash *state);
|
||||
extern const struct hash_ops string_hash_ops;
|
||||
extern const struct hash_ops string_hash_ops_free;
|
||||
extern const struct hash_ops string_hash_ops_free_free;
|
||||
extern const struct hash_ops string_hash_ops_free_strv_free;
|
||||
|
||||
void path_hash_func(const char *p, struct siphash *state);
|
||||
extern const struct hash_ops path_hash_ops;
|
||||
|
@@ -90,12 +90,7 @@ OrderedHashmap* _ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DE
|
||||
#define ordered_hashmap_new(ops) _ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
|
||||
#define hashmap_free_and_replace(a, b) \
|
||||
({ \
|
||||
hashmap_free(a); \
|
||||
(a) = (b); \
|
||||
(b) = NULL; \
|
||||
0; \
|
||||
})
|
||||
free_and_replace_full(a, b, hashmap_free)
|
||||
|
||||
HashmapBase* _hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value);
|
||||
static inline Hashmap* hashmap_free(Hashmap *h) {
|
||||
|
@@ -51,6 +51,20 @@ bool in4_addr_is_link_local(const struct in_addr *a) {
|
||||
return (be32toh(a->s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
|
||||
}
|
||||
|
||||
bool in4_addr_is_link_local_dynamic(const struct in_addr *a) {
|
||||
assert(a);
|
||||
|
||||
if (!in4_addr_is_link_local(a))
|
||||
return false;
|
||||
|
||||
/* 169.254.0.0/24 and 169.254.255.0/24 must not be used for the dynamic IPv4LL assignment.
|
||||
* See RFC 3927 Section 2.1:
|
||||
* The IPv4 prefix 169.254/16 is registered with the IANA for this purpose. The first 256 and last
|
||||
* 256 addresses in the 169.254/16 prefix are reserved for future use and MUST NOT be selected by a
|
||||
* host using this dynamic configuration mechanism. */
|
||||
return !IN_SET(be32toh(a->s_addr) & 0x0000FF00U, 0x0000U, 0xFF00U);
|
||||
}
|
||||
|
||||
bool in6_addr_is_link_local(const struct in6_addr *a) {
|
||||
assert(a);
|
||||
|
||||
|
@@ -44,6 +44,7 @@ static inline bool in_addr_data_is_set(const struct in_addr_data *a) {
|
||||
int in_addr_is_multicast(int family, const union in_addr_union *u);
|
||||
|
||||
bool in4_addr_is_link_local(const struct in_addr *a);
|
||||
bool in4_addr_is_link_local_dynamic(const struct in_addr *a);
|
||||
bool in6_addr_is_link_local(const struct in6_addr *a);
|
||||
int in_addr_is_link_local(int family, const union in_addr_union *u);
|
||||
bool in6_addr_is_link_local_all_nodes(const struct in6_addr *a);
|
||||
|
@@ -170,9 +170,6 @@
|
||||
i != (p); \
|
||||
i = i->name##_next ? i->name##_next : (head))
|
||||
|
||||
#define LIST_IS_EMPTY(head) \
|
||||
(!(head))
|
||||
|
||||
/* Join two lists tail to head: a->b, c->d to a->b->c->d and de-initialise second list */
|
||||
#define LIST_JOIN(name,a,b) \
|
||||
do { \
|
||||
|
@@ -88,10 +88,6 @@
|
||||
_Pragma("GCC diagnostic push")
|
||||
#endif
|
||||
|
||||
#define DISABLE_WARNING_FLOAT_EQUAL \
|
||||
_Pragma("GCC diagnostic push"); \
|
||||
_Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
|
||||
|
||||
#define DISABLE_WARNING_TYPE_LIMITS \
|
||||
_Pragma("GCC diagnostic push"); \
|
||||
_Pragma("GCC diagnostic ignored \"-Wtype-limits\"")
|
||||
|
@@ -1061,7 +1061,7 @@ int path_extract_filename(const char *path, char **ret) {
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = TAKE_PTR(a);
|
||||
return strlen(c) > (size_t)r ? O_DIRECTORY : 0;
|
||||
return strlen(c) > (size_t) r ? O_DIRECTORY : 0;
|
||||
}
|
||||
|
||||
int path_extract_directory(const char *path, char **ret) {
|
||||
@@ -1115,7 +1115,7 @@ bool filename_is_valid(const char *p) {
|
||||
if (isempty(p))
|
||||
return false;
|
||||
|
||||
if (dot_or_dot_dot(p))
|
||||
if (dot_or_dot_dot(p)) /* Yes, in this context we consider "." and ".." invalid */
|
||||
return false;
|
||||
|
||||
e = strchrnul(p, '/');
|
||||
|
@@ -45,12 +45,16 @@
|
||||
#endif
|
||||
|
||||
static inline bool is_path(const char *p) {
|
||||
assert(p);
|
||||
if (!p) /* A NULL pointer is definitely not a path */
|
||||
return false;
|
||||
|
||||
return strchr(p, '/');
|
||||
}
|
||||
|
||||
static inline bool path_is_absolute(const char *p) {
|
||||
assert(p);
|
||||
if (!p) /* A NULL pointer is definitely not an absolute path */
|
||||
return false;
|
||||
|
||||
return p[0] == '/';
|
||||
}
|
||||
|
||||
@@ -159,10 +163,10 @@ int path_extract_directory(const char *path, char **ret);
|
||||
bool filename_is_valid(const char *p) _pure_;
|
||||
bool path_is_valid_full(const char *p, bool accept_dot_dot) _pure_;
|
||||
static inline bool path_is_valid(const char *p) {
|
||||
return path_is_valid_full(p, true);
|
||||
return path_is_valid_full(p, /* accept_dot_dot= */ true);
|
||||
}
|
||||
static inline bool path_is_safe(const char *p) {
|
||||
return path_is_valid_full(p, false);
|
||||
return path_is_valid_full(p, /* accept_dot_dot= */ false);
|
||||
}
|
||||
bool path_is_normalized(const char *p) _pure_;
|
||||
|
||||
|
@@ -1156,7 +1156,7 @@ void reset_cached_pid(void) {
|
||||
|
||||
pid_t getpid_cached(void) {
|
||||
static bool installed = false;
|
||||
pid_t current_value;
|
||||
pid_t current_value = CACHED_PID_UNSET;
|
||||
|
||||
/* getpid_cached() is much like getpid(), but caches the value in local memory, to avoid having to invoke a
|
||||
* system call each time. This restores glibc behaviour from before 2.24, when getpid() was unconditionally
|
||||
@@ -1167,7 +1167,13 @@ pid_t getpid_cached(void) {
|
||||
* https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=c579f48edba88380635ab98cb612030e3ed8691e
|
||||
*/
|
||||
|
||||
current_value = __sync_val_compare_and_swap(&cached_pid, CACHED_PID_UNSET, CACHED_PID_BUSY);
|
||||
__atomic_compare_exchange_n(
|
||||
&cached_pid,
|
||||
¤t_value,
|
||||
CACHED_PID_BUSY,
|
||||
false,
|
||||
__ATOMIC_SEQ_CST,
|
||||
__ATOMIC_SEQ_CST);
|
||||
|
||||
switch (current_value) {
|
||||
|
||||
@@ -1589,6 +1595,30 @@ bool invoked_as(char *argv[], const char *token) {
|
||||
return strstr(last_path_component(argv[0]), token);
|
||||
}
|
||||
|
||||
bool invoked_by_systemd(void) {
|
||||
int r;
|
||||
|
||||
/* If the process is directly executed by PID1 (e.g. ExecStart= or generator), systemd-importd,
|
||||
* or systemd-homed, then $SYSTEMD_EXEC_PID= is set, and read the command line. */
|
||||
const char *e = getenv("SYSTEMD_EXEC_PID");
|
||||
if (!e)
|
||||
return false;
|
||||
|
||||
if (streq(e, "*"))
|
||||
/* For testing. */
|
||||
return true;
|
||||
|
||||
pid_t p;
|
||||
r = parse_pid(e, &p);
|
||||
if (r < 0) {
|
||||
/* We know that systemd sets the variable correctly. Something else must have set it. */
|
||||
log_debug_errno(r, "Failed to parse \"SYSTEMD_EXEC_PID=%s\", ignoring: %m", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return getpid_cached() == p;
|
||||
}
|
||||
|
||||
_noreturn_ void freeze(void) {
|
||||
log_close();
|
||||
|
||||
|
@@ -192,6 +192,8 @@ int setpriority_closest(int priority);
|
||||
|
||||
bool invoked_as(char *argv[], const char *token);
|
||||
|
||||
bool invoked_by_systemd(void);
|
||||
|
||||
_noreturn_ void freeze(void);
|
||||
|
||||
bool argv_looks_like_help(int argc, char **argv);
|
||||
|
@@ -6,12 +6,7 @@
|
||||
#include "macro.h"
|
||||
|
||||
#define set_free_and_replace(a, b) \
|
||||
({ \
|
||||
set_free(a); \
|
||||
(a) = (b); \
|
||||
(b) = NULL; \
|
||||
0; \
|
||||
})
|
||||
free_and_replace_full(a, b, set_free)
|
||||
|
||||
Set* _set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
#define set_new(ops) _set_new(ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
|
@@ -39,16 +39,17 @@ int is_symlink(const char *path) {
|
||||
}
|
||||
#endif /* NM_IGNORED */
|
||||
|
||||
int is_dir(const char* path, bool follow) {
|
||||
int is_dir_full(int atfd, const char* path, bool follow) {
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(atfd >= 0 || atfd == AT_FDCWD);
|
||||
assert(atfd >= 0 || path);
|
||||
|
||||
if (follow)
|
||||
r = stat(path, &st);
|
||||
if (path)
|
||||
r = fstatat(atfd, path, &st, follow ? 0 : AT_SYMLINK_NOFOLLOW);
|
||||
else
|
||||
r = lstat(path, &st);
|
||||
r = fstat(atfd, &st);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
@@ -56,15 +57,6 @@ int is_dir(const char* path, bool follow) {
|
||||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
int is_dir_fd(int fd) {
|
||||
struct stat st;
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
return !!S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
int is_device_node(const char *path) {
|
||||
struct stat info;
|
||||
|
||||
|
@@ -13,8 +13,13 @@
|
||||
#include "missing_stat.h"
|
||||
|
||||
int is_symlink(const char *path);
|
||||
int is_dir(const char *path, bool follow);
|
||||
int is_dir_fd(int fd);
|
||||
int is_dir_full(int atfd, const char *fname, bool follow);
|
||||
static inline int is_dir(const char *path, bool follow) {
|
||||
return is_dir_full(AT_FDCWD, path, follow);
|
||||
}
|
||||
static inline int is_dir_fd(int fd) {
|
||||
return is_dir_full(fd, NULL, false);
|
||||
}
|
||||
int is_device_node(const char *path);
|
||||
|
||||
int dir_is_empty_at(int dir_fd, const char *path, bool ignore_hidden_or_backup);
|
||||
|
@@ -258,14 +258,7 @@ int strv_extend_n(char ***l, const char *value, size_t n);
|
||||
int fputstrv(FILE *f, char * const *l, const char *separator, bool *space);
|
||||
|
||||
#define strv_free_and_replace(a, b) \
|
||||
({ \
|
||||
char ***_a = &(a); \
|
||||
char ***_b = &(b); \
|
||||
strv_free(*_a); \
|
||||
(*_a) = (*_b); \
|
||||
(*_b) = NULL; \
|
||||
0; \
|
||||
})
|
||||
free_and_replace_full(a, b, strv_free)
|
||||
|
||||
extern const struct hash_ops string_strv_hash_ops;
|
||||
int _string_strv_hashmap_put(Hashmap **h, const char *key, const char *value HASHMAP_DEBUG_PARAMS);
|
||||
|
@@ -595,7 +595,7 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
|
||||
t = b;
|
||||
}
|
||||
|
||||
n = MIN((size_t) k, l);
|
||||
n = MIN((size_t) k, l-1);
|
||||
|
||||
l -= n;
|
||||
p += n;
|
||||
|
@@ -95,6 +95,20 @@
|
||||
_expr_; \
|
||||
})
|
||||
|
||||
#define ASSERT_NONNEG(expr) \
|
||||
({ \
|
||||
typeof(expr) _expr_ = (expr), _zero = 0; \
|
||||
assert(_expr_ >= _zero); \
|
||||
_expr_; \
|
||||
})
|
||||
|
||||
#define ASSERT_SE_NONNEG(expr) \
|
||||
({ \
|
||||
typeof(expr) _expr_ = (expr), _zero = 0; \
|
||||
assert_se(_expr_ >= _zero); \
|
||||
_expr_; \
|
||||
})
|
||||
|
||||
#define assert_cc(expr) static_assert(expr, #expr)
|
||||
|
||||
|
||||
@@ -106,10 +120,10 @@
|
||||
* on this macro will run concurrently to all other code conditionalized
|
||||
* the same way, there's no ordering or completion enforced. */
|
||||
#define ONCE __ONCE(UNIQ_T(_once_, UNIQ))
|
||||
#define __ONCE(o) \
|
||||
({ \
|
||||
static bool (o) = false; \
|
||||
__sync_bool_compare_and_swap(&(o), false, true); \
|
||||
#define __ONCE(o) \
|
||||
({ \
|
||||
static bool (o) = false; \
|
||||
__atomic_exchange_n(&(o), true, __ATOMIC_SEQ_CST); \
|
||||
})
|
||||
|
||||
#undef MAX
|
||||
@@ -186,6 +200,27 @@
|
||||
MIN(_c, z); \
|
||||
})
|
||||
|
||||
/* Returns true if the passed integer is a positive power of two */
|
||||
#define CONST_ISPOWEROF2(x) \
|
||||
((x) > 0 && ((x) & ((x) - 1)) == 0)
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
#define ISPOWEROF2(x) \
|
||||
__builtin_choose_expr( \
|
||||
__builtin_constant_p(x), \
|
||||
CONST_ISPOWEROF2(x), \
|
||||
({ \
|
||||
const typeof(x) _x = (x); \
|
||||
CONST_ISPOWEROF2(_x); \
|
||||
}))
|
||||
#else /* NM_IGNORED */
|
||||
#define ISPOWEROF2(x) \
|
||||
({ \
|
||||
const typeof(x) _x = (x); \
|
||||
CONST_ISPOWEROF2(_x); \
|
||||
})
|
||||
#endif /* NM_IGNORED */
|
||||
|
||||
#define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b))
|
||||
#define __LESS_BY(aq, a, bq, b) \
|
||||
({ \
|
||||
@@ -300,16 +335,7 @@
|
||||
})
|
||||
|
||||
static inline size_t ALIGN_TO(size_t l, size_t ali) {
|
||||
/* Check that alignment is exponent of 2 */
|
||||
#if SIZE_MAX == UINT_MAX
|
||||
assert(__builtin_popcount(ali) == 1);
|
||||
#elif SIZE_MAX == ULONG_MAX
|
||||
assert(__builtin_popcountl(ali) == 1);
|
||||
#elif SIZE_MAX == ULLONG_MAX
|
||||
assert(__builtin_popcountll(ali) == 1);
|
||||
#else
|
||||
#error "Unexpected size_t"
|
||||
#endif
|
||||
assert(ISPOWEROF2(ali));
|
||||
|
||||
if (l > SIZE_MAX - (ali - 1))
|
||||
return SIZE_MAX; /* indicate overflow */
|
||||
@@ -330,7 +356,7 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
|
||||
__builtin_choose_expr( \
|
||||
__builtin_constant_p(l) && \
|
||||
__builtin_constant_p(ali) && \
|
||||
__builtin_popcountll(ali) == 1 && /* is power of 2? */ \
|
||||
CONST_ISPOWEROF2(ali) && \
|
||||
(l <= SIZE_MAX - (ali - 1)), /* overflow? */ \
|
||||
((l) + (ali) - 1) & ~((ali) - 1), \
|
||||
VOID_0)
|
||||
|
Reference in New Issue
Block a user