summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/socket-label.c9
-rw-r--r--src/basic/socket-util.h1
-rw-r--r--src/basic/util.c2
-rw-r--r--src/bootchart/store.c86
-rw-r--r--src/bootchart/svg.c9
-rw-r--r--src/bus-proxyd/proxy.c24
-rw-r--r--src/core/kmod-setup.c2
-rw-r--r--src/core/main.c4
-rw-r--r--src/core/socket.c7
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.c11
-rw-r--r--src/libsystemd/sd-netlink/netlink-internal.h25
-rw-r--r--src/libsystemd/sd-netlink/netlink-message.c174
-rw-r--r--src/login/logind-dbus.c30
-rw-r--r--src/login/logind.c6
-rw-r--r--src/login/logind.h2
-rw-r--r--src/network/networkd-link.c3
-rw-r--r--src/network/networkd-netdev.c13
-rw-r--r--src/nspawn/nspawn.c30
-rw-r--r--src/shared/install.c2
-rw-r--r--src/sysv-generator/sysv-generator.c32
-rw-r--r--src/timedate/timedatectl.c11
l---------src/udev/accelerometer/Makefile1
-rw-r--r--src/udev/accelerometer/accelerometer.c303
-rw-r--r--src/udev/udev-event.c50
-rw-r--r--src/udev/udev-rules.c65
-rw-r--r--src/udev/udev.h3
-rw-r--r--src/udev/udevd.c68
27 files changed, 353 insertions, 620 deletions
diff --git a/src/basic/socket-label.c b/src/basic/socket-label.c
index cbe3ff216e..144e6fd86e 100644
--- a/src/basic/socket-label.c
+++ b/src/basic/socket-label.c
@@ -38,6 +38,7 @@ int socket_address_listen(
int backlog,
SocketAddressBindIPv6Only only,
const char *bind_to_device,
+ bool reuse_port,
bool free_bind,
bool transparent,
mode_t directory_mode,
@@ -83,6 +84,12 @@ int socket_address_listen(
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, bind_to_device, strlen(bind_to_device)+1) < 0)
return -errno;
+ if (reuse_port) {
+ one = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0)
+ log_warning_errno(errno, "SO_REUSEPORT failed: %m");
+ }
+
if (free_bind) {
one = 1;
if (setsockopt(fd, IPPROTO_IP, IP_FREEBIND, &one, sizeof(one)) < 0)
@@ -146,7 +153,7 @@ int make_socket_fd(int log_level, const char* address, int flags) {
}
fd = socket_address_listen(&a, flags, SOMAXCONN, SOCKET_ADDRESS_DEFAULT,
- NULL, false, false, 0755, 0644, NULL);
+ NULL, false, false, false, 0755, 0644, NULL);
if (fd < 0 || log_get_max_level() >= log_level) {
_cleanup_free_ char *p = NULL;
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index 538cf59174..6b0ce7836f 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -80,6 +80,7 @@ int socket_address_listen(
int backlog,
SocketAddressBindIPv6Only only,
const char *bind_to_device,
+ bool reuse_port,
bool free_bind,
bool transparent,
mode_t directory_mode,
diff --git a/src/basic/util.c b/src/basic/util.c
index 727be56f58..906e4abad6 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -3627,7 +3627,7 @@ bool string_is_safe(const char *p) {
if (*t > 0 && *t < ' ')
return false;
- if (strchr("\\\"\'\0x7f", *t))
+ if (strchr("\\\"\'\x7f", *t))
return false;
}
diff --git a/src/bootchart/store.c b/src/bootchart/store.c
index f159cbafe2..caa97b97fc 100644
--- a/src/bootchart/store.c
+++ b/src/bootchart/store.c
@@ -37,6 +37,7 @@
#include "store.h"
#include "bootchart.h"
#include "cgroup-util.h"
+#include "fileio.h"
/*
* Alloc a static 4k buffer for stdio - primarily used to increase
@@ -97,13 +98,14 @@ int log_sample(DIR *proc,
int *cpus) {
static int vmstat = -1;
- static int schedstat = -1;
+ _cleanup_free_ char *buf_schedstat = NULL;
char buf[4096];
char key[256];
char val[256];
char rt[256];
char wt[256];
char *m;
+ int r;
int c;
int p;
int mod;
@@ -115,6 +117,7 @@ int log_sample(DIR *proc,
struct list_sample_data *sampledata;
struct ps_sched_struct *ps_prev = NULL;
int procfd;
+ int taskfd = -1;
sampledata = *ptr;
@@ -155,27 +158,13 @@ vmstat_next:
break;
}
- if (schedstat < 0) {
- /* overall CPU utilization */
- schedstat = openat(procfd, "schedstat", O_RDONLY|O_CLOEXEC);
- if (schedstat < 0)
- return log_error_errno(errno, "Failed to open /proc/schedstat (requires CONFIG_SCHEDSTATS=y in kernel config): %m");
- }
-
- n = pread(schedstat, buf, sizeof(buf) - 1, 0);
- if (n <= 0) {
- schedstat = safe_close(schedstat);
- if (n < 0)
- return -errno;
- return -ENODATA;
- }
+ /* Parse "/proc/schedstat" for overall CPU utilization */
+ r = read_full_file("/proc/schedstat", &buf_schedstat, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Unable to read schedstat: %m");
- buf[n] = '\0';
-
- m = buf;
+ m = buf_schedstat;
while (m) {
- int r;
-
if (sscanf(m, "%s %*s %*s %*s %*s %*s %*s %s %s", key, rt, wt) < 3)
goto schedstat_next;
@@ -237,7 +226,6 @@ schedstat_next:
_cleanup_fclose_ FILE *st = NULL;
char t[32];
struct ps_struct *parent;
- int r;
ps->next_ps = new0(struct ps_struct, 1);
if (!ps->next_ps)
@@ -409,6 +397,62 @@ schedstat_next:
ps->total = (ps->last->runtime - ps->first->runtime)
/ 1000000000.0;
+ /* Take into account CPU runtime/waittime spent in non-main threads of the process
+ * by parsing "/proc/[pid]/task/[tid]/schedstat" for all [tid] != [pid]
+ * See https://github.com/systemd/systemd/issues/139
+ */
+
+ /* Browse directory "/proc/[pid]/task" to know the thread ids of process [pid] */
+ snprintf(filename, sizeof(filename), PID_FMT "/task", pid);
+ taskfd = openat(procfd, filename, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
+ if (taskfd >= 0) {
+ _cleanup_closedir_ DIR *taskdir = NULL;
+
+ taskdir = fdopendir(taskfd);
+ if (!taskdir) {
+ safe_close(taskfd);
+ return -errno;
+ }
+ FOREACH_DIRENT(ent, taskdir, break) {
+ int tid = -1;
+ _cleanup_close_ int tid_schedstat = -1;
+ long long delta_rt;
+ long long delta_wt;
+
+ if ((ent->d_name[0] < '0') || (ent->d_name[0] > '9'))
+ continue;
+
+ /* Skip main thread as it was already accounted */
+ r = safe_atoi(ent->d_name, &tid);
+ if (r < 0 || tid == pid)
+ continue;
+
+ /* Parse "/proc/[pid]/task/[tid]/schedstat" */
+ snprintf(filename, sizeof(filename), PID_FMT "/schedstat", tid);
+ tid_schedstat = openat(taskfd, filename, O_RDONLY|O_CLOEXEC);
+
+ if (tid_schedstat == -1)
+ continue;
+
+ s = pread(tid_schedstat, buf, sizeof(buf) - 1, 0);
+ if (s <= 0)
+ continue;
+ buf[s] = '\0';
+
+ if (!sscanf(buf, "%s %s %*s", rt, wt))
+ continue;
+
+ r = safe_atolli(rt, &delta_rt);
+ if (r < 0)
+ continue;
+ r = safe_atolli(rt, &delta_wt);
+ if (r < 0)
+ continue;
+ ps->sample->runtime += delta_rt;
+ ps->sample->waittime += delta_wt;
+ }
+ }
+
if (!arg_pss)
goto catch_rename;
diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c
index f442200b66..a7ef653d5d 100644
--- a/src/bootchart/svg.c
+++ b/src/bootchart/svg.c
@@ -76,8 +76,6 @@ static void svg_header(FILE *of, struct list_sample_data *head, double graph_sta
assert(head);
- sampledata = head;
- LIST_FIND_TAIL(link, sampledata, head);
sampledata_last = head;
LIST_FOREACH_BEFORE(link, sampledata, head) {
sampledata_last = sampledata;
@@ -174,7 +172,7 @@ static int svg_title(FILE *of, const char *build, int pscount, double log_start,
r = read_one_line_file(filename, &model);
if (r < 0)
- log_warning("Error reading disk model for %s: %m\n", rootbdev);
+ log_info("Error reading disk model for %s: %m\n", rootbdev);
}
/* various utsname parameters */
@@ -210,7 +208,8 @@ static int svg_title(FILE *of, const char *build, int pscount, double log_start,
fprintf(of, "<text class=\"t2\" x=\"20\" y=\"50\">System: %s %s %s %s</text>\n",
uts.sysname, uts.release, uts.version, uts.machine);
fprintf(of, "<text class=\"t2\" x=\"20\" y=\"65\">CPU: %s</text>\n", cpu);
- fprintf(of, "<text class=\"t2\" x=\"20\" y=\"80\">Disk: %s</text>\n", model);
+ if (model)
+ fprintf(of, "<text class=\"t2\" x=\"20\" y=\"80\">Disk: %s</text>\n", model);
fprintf(of, "<text class=\"t2\" x=\"20\" y=\"95\">Boot options: %s</text>\n", cmdline);
fprintf(of, "<text class=\"t2\" x=\"20\" y=\"110\">Build: %s</text>\n", build);
fprintf(of, "<text class=\"t2\" x=\"20\" y=\"125\">Log start time: %.03fs</text>\n", log_start);
@@ -1296,6 +1295,8 @@ int svg_do(FILE *of,
double offset = 7;
int r, c;
+ sampledata = head;
+ LIST_FIND_TAIL(link, sampledata, head);
ps = ps_first;
/* count initcall thread count first */
diff --git a/src/bus-proxyd/proxy.c b/src/bus-proxyd/proxy.c
index 28ab1c97fc..1dc55171e7 100644
--- a/src/bus-proxyd/proxy.c
+++ b/src/bus-proxyd/proxy.c
@@ -494,7 +494,16 @@ static int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m,
}
/* First check if we (the sender) can send to this name */
- if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, destination_names, m->path, m->interface, m->member, true, &n)) {
+ if (sd_bus_message_is_signal(m, NULL, NULL)) {
+ /* If we forward a signal from dbus-1 to kdbus, we have
+ * no idea who the recipient is. Therefore, we cannot
+ * apply any dbus-1 policies that match on receiver
+ * credentials. We know sd-bus always sets
+ * KDBUS_MSG_SIGNAL, so the kernel applies policies to
+ * the message. Therefore, skip policy checks in this
+ * case. */
+ return 0;
+ } else if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, destination_names, m->path, m->interface, m->member, true, &n)) {
if (n) {
/* If we made a receiver decision, then remember which
* name's policy we used, and to which unique ID it
@@ -512,19 +521,8 @@ static int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m,
return r;
}
- if (sd_bus_message_is_signal(m, NULL, NULL)) {
- /* If we forward a signal from dbus-1 to kdbus,
- * we have no idea who the recipient is.
- * Therefore, we cannot apply any dbus-1
- * receiver policies that match on receiver
- * credentials. We know sd-bus always sets
- * KDBUS_MSG_SIGNAL, so the kernel applies
- * receiver policies to the message. Therefore,
- * skip policy checks in this case. */
- return 0;
- } else if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true)) {
+ if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true))
return 0;
- }
}
/* Return an error back to the caller */
diff --git a/src/core/kmod-setup.c b/src/core/kmod-setup.c
index e7a6bdc8c4..fc6d2f4acb 100644
--- a/src/core/kmod-setup.c
+++ b/src/core/kmod-setup.c
@@ -116,7 +116,7 @@ int kmod_setup(void) {
else if (r == KMOD_PROBE_APPLY_BLACKLIST)
log_info("Module '%s' is blacklisted", kmod_module_get_name(mod));
else {
- bool print_warning = kmod_table[i].warn_if_unavailable || (r < 0 && r != -ENOSYS);
+ bool print_warning = kmod_table[i].warn_if_unavailable || (r < 0 && r != -ENOENT);
log_full_errno(print_warning ? LOG_WARNING : LOG_DEBUG, r,
"Failed to insert module '%s': %m", kmod_module_get_name(mod));
diff --git a/src/core/main.c b/src/core/main.c
index 332453a0ea..523f0ce020 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1995,6 +1995,10 @@ finish:
command_line[pos++] = "kmsg";
break;
+ case LOG_TARGET_NULL:
+ command_line[pos++] = "null";
+ break;
+
case LOG_TARGET_CONSOLE:
default:
command_line[pos++] = "console";
diff --git a/src/core/socket.c b/src/core/socket.c
index d3178e642b..693cbc6080 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -922,12 +922,6 @@ static void socket_apply_socket_options(Socket *s, int fd) {
if (setsockopt(fd, SOL_TCP, TCP_CONGESTION, s->tcp_congestion, strlen(s->tcp_congestion)+1) < 0)
log_unit_warning_errno(UNIT(s), errno, "TCP_CONGESTION failed: %m");
- if (s->reuse_port) {
- int b = s->reuse_port;
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &b, sizeof(b)) < 0)
- log_unit_warning_errno(UNIT(s), errno, "SO_REUSEPORT failed: %m");
- }
-
if (s->smack_ip_in) {
r = mac_smack_apply_ip_in_fd(fd, s->smack_ip_in);
if (r < 0)
@@ -1183,6 +1177,7 @@ static int socket_open_fds(Socket *s) {
s->backlog,
s->bind_ipv6_only,
s->bind_to_device,
+ s->reuse_port,
s->free_bind,
s->transparent,
s->directory_mode,
diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c
index f08db2da89..e3fac01f92 100644
--- a/src/libsystemd/sd-bus/bus-kernel.c
+++ b/src/libsystemd/sd-bus/bus-kernel.c
@@ -1385,15 +1385,16 @@ int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) {
r = 0;
}
- } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL)
+ if (r <= 0)
+ close_kdbus_msg(bus, k);
+ } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL) {
r = bus_kernel_translate_message(bus, k);
- else {
+ close_kdbus_msg(bus, k);
+ } else {
log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
r = 0;
- }
-
- if (r <= 0)
close_kdbus_msg(bus, k);
+ }
return r < 0 ? r : 1;
}
diff --git a/src/libsystemd/sd-netlink/netlink-internal.h b/src/libsystemd/sd-netlink/netlink-internal.h
index 7290f4e875..b8a3668bfc 100644
--- a/src/libsystemd/sd-netlink/netlink-internal.h
+++ b/src/libsystemd/sd-netlink/netlink-internal.h
@@ -92,18 +92,25 @@ struct sd_netlink {
sd_event *event;
};
+struct netlink_attribute {
+ size_t offset; /* offset from hdr to attirubte */
+};
+
+struct netlink_container {
+ const struct NLTypeSystem *type_system; /* the type system of the container */
+ size_t offset; /* offset from hdr to the start of the container */
+ struct netlink_attribute *attributes;
+ unsigned short n_attributes; /* number of attributes in container */
+};
+
struct sd_netlink_message {
RefCount n_ref;
sd_netlink *rtnl;
struct nlmsghdr *hdr;
- const struct NLTypeSystem *(container_type_system[RTNL_CONTAINER_DEPTH]); /* the type of the container and all its parents */
- size_t container_offsets[RTNL_CONTAINER_DEPTH]; /* offset from hdr to each container's start */
+ struct netlink_container containers[RTNL_CONTAINER_DEPTH];
unsigned n_containers; /* number of containers */
- size_t next_rta_offset; /* offset from hdr to next rta */
- size_t *rta_offset_tb[RTNL_CONTAINER_DEPTH];
- unsigned short rta_tb_size[RTNL_CONTAINER_DEPTH];
bool sealed:1;
bool broadcast:1;
@@ -122,14 +129,6 @@ int socket_read_message(sd_netlink *nl);
int rtnl_rqueue_make_room(sd_netlink *rtnl);
int rtnl_rqueue_partial_make_room(sd_netlink *rtnl);
-int rtnl_message_read_internal(sd_netlink_message *m, unsigned short type, void **data);
-int rtnl_message_parse(sd_netlink_message *m,
- size_t **rta_offset_tb,
- unsigned short *rta_tb_size,
- int max,
- struct rtattr *rta,
- unsigned int rt_len);
-
/* Make sure callbacks don't destroy the rtnl connection */
#define RTNL_DONT_DESTROY(rtnl) \
_cleanup_netlink_unref_ _unused_ sd_netlink *_dont_destroy_##rtnl = sd_netlink_ref(rtnl)
diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c
index a935b821f6..13573dcea8 100644
--- a/src/libsystemd/sd-netlink/netlink-message.c
+++ b/src/libsystemd/sd-netlink/netlink-message.c
@@ -34,7 +34,7 @@
#include "netlink-internal.h"
#include "netlink-types.h"
-#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
+#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset) : NULL)
#define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
@@ -88,7 +88,7 @@ int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) {
m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
- type_get_type_system(nl_type, &m->container_type_system[0]);
+ type_get_type_system(nl_type, &m->containers[0].type_system);
m->hdr->nlmsg_len = size;
m->hdr->nlmsg_type = type;
@@ -129,7 +129,7 @@ sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) {
free(m->hdr);
for (i = 0; i <= m->n_containers; i++)
- free(m->rta_offset_tb[i]);
+ free(m->containers[i].attributes);
sd_netlink_message_unref(m->next);
@@ -223,7 +223,7 @@ static int message_attribute_has_type(sd_netlink_message *m, size_t *out_size, u
assert(m);
- r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
+ r = type_system_get_type(m->containers[m->n_containers].type_system, &type, attribute_type);
if (r < 0)
return r;
@@ -406,18 +406,18 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type
if (r < 0)
return r;
- r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
+ r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type);
if (r < 0)
return r;
r = type_system_union_protocol_get_type_system(type_system_union,
- &m->container_type_system[m->n_containers + 1],
+ &m->containers[m->n_containers + 1].type_system,
family);
if (r < 0)
return r;
} else {
- r = type_system_get_type_system(m->container_type_system[m->n_containers],
- &m->container_type_system[m->n_containers + 1],
+ r = type_system_get_type_system(m->containers[m->n_containers].type_system,
+ &m->containers[m->n_containers + 1].type_system,
type);
if (r < 0)
return r;
@@ -427,7 +427,7 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type
if (r < 0)
return r;
- m->container_offsets[m->n_containers ++] = r;
+ m->containers[m->n_containers ++].offset = r;
return 0;
}
@@ -439,12 +439,12 @@ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned shor
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
- r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
+ r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type);
if (r < 0)
return r;
r = type_system_union_get_type_system(type_system_union,
- &m->container_type_system[m->n_containers + 1],
+ &m->containers[m->n_containers + 1].type_system,
key);
if (r < 0)
return r;
@@ -454,11 +454,11 @@ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned shor
return r;
/* do we evere need non-null size */
- r = add_rtattr(m, type, NULL, 0);
+ r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0);
if (r < 0)
return r;
- m->container_offsets[m->n_containers ++] = r;
+ m->containers[m->n_containers ++].offset = r;
return 0;
}
@@ -469,26 +469,29 @@ int sd_netlink_message_close_container(sd_netlink_message *m) {
assert_return(!m->sealed, -EPERM);
assert_return(m->n_containers > 0, -EINVAL);
- m->container_type_system[m->n_containers] = NULL;
+ m->containers[m->n_containers].type_system = NULL;
m->n_containers --;
return 0;
}
-int rtnl_message_read_internal(sd_netlink_message *m, unsigned short type, void **data) {
+static int netlink_message_read_internal(sd_netlink_message *m, unsigned short type, void **data) {
+ struct netlink_attribute *attribute;
struct rtattr *rta;
assert_return(m, -EINVAL);
assert_return(m->sealed, -EPERM);
assert_return(data, -EINVAL);
assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
- assert(m->rta_offset_tb[m->n_containers]);
- assert(type < m->rta_tb_size[m->n_containers]);
+ assert(m->containers[m->n_containers].attributes);
+ assert(type < m->containers[m->n_containers].n_attributes);
- if(!m->rta_offset_tb[m->n_containers][type])
+ attribute = &m->containers[m->n_containers].attributes[type];
+
+ if(!attribute->offset)
return -ENODATA;
- rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
+ rta = (struct rtattr*)((uint8_t *) m->hdr + attribute->offset);
*data = RTA_DATA(rta);
@@ -505,7 +508,7 @@ int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, c
if (r < 0)
return r;
- r = rtnl_message_read_internal(m, type, &attr_data);
+ r = netlink_message_read_internal(m, type, &attr_data);
if (r < 0)
return r;
else if (strnlen(attr_data, r) >= (size_t) r)
@@ -527,7 +530,7 @@ int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8
if (r < 0)
return r;
- r = rtnl_message_read_internal(m, type, &attr_data);
+ r = netlink_message_read_internal(m, type, &attr_data);
if (r < 0)
return r;
else if ((size_t) r < sizeof(uint8_t))
@@ -549,7 +552,7 @@ int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint
if (r < 0)
return r;
- r = rtnl_message_read_internal(m, type, &attr_data);
+ r = netlink_message_read_internal(m, type, &attr_data);
if (r < 0)
return r;
else if ((size_t) r < sizeof(uint16_t))
@@ -571,7 +574,7 @@ int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint
if (r < 0)
return r;
- r = rtnl_message_read_internal(m, type, &attr_data);
+ r = netlink_message_read_internal(m, type, &attr_data);
if (r < 0)
return r;
else if ((size_t)r < sizeof(uint32_t))
@@ -593,7 +596,7 @@ int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short typ
if (r < 0)
return r;
- r = rtnl_message_read_internal(m, type, &attr_data);
+ r = netlink_message_read_internal(m, type, &attr_data);
if (r < 0)
return r;
else if ((size_t)r < sizeof(struct ether_addr))
@@ -615,7 +618,7 @@ int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short typ
if (r < 0)
return r;
- r = rtnl_message_read_internal(m, type, &attr_data);
+ r = netlink_message_read_internal(m, type, &attr_data);
if (r < 0)
return r;
else if ((size_t)r < sizeof(struct ifa_cacheinfo))
@@ -637,7 +640,7 @@ int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type,
if (r < 0)
return r;
- r = rtnl_message_read_internal(m, type, &attr_data);
+ r = netlink_message_read_internal(m, type, &attr_data);
if (r < 0)
return r;
else if ((size_t)r < sizeof(struct in_addr))
@@ -659,7 +662,7 @@ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type,
if (r < 0)
return r;
- r = rtnl_message_read_internal(m, type, &attr_data);
+ r = netlink_message_read_internal(m, type, &attr_data);
if (r < 0)
return r;
else if ((size_t)r < sizeof(struct in6_addr))
@@ -671,6 +674,40 @@ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type,
return 0;
}
+static int netlink_container_parse(sd_netlink_message *m,
+ struct netlink_container *container,
+ int count,
+ struct rtattr *rta,
+ unsigned int rt_len) {
+ _cleanup_free_ struct netlink_attribute *attributes = NULL;
+
+ attributes = new0(struct netlink_attribute, count);
+ if(!attributes)
+ return -ENOMEM;
+
+ for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
+ unsigned short type;
+
+ type = RTA_TYPE(rta);
+
+ /* if the kernel is newer than the headers we used
+ when building, we ignore out-of-range attributes */
+ if (type >= count)
+ continue;
+
+ if (attributes[type].offset)
+ log_debug("rtnl: message parse - overwriting repeated attribute");
+
+ attributes[type].offset = (uint8_t *) rta - (uint8_t *) m->hdr;
+ }
+
+ container->attributes = attributes;
+ attributes = NULL;
+ container->n_attributes = count;
+
+ return 0;
+}
+
int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type_id) {
const NLType *nl_type;
const NLTypeSystem *type_system;
@@ -682,7 +719,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
assert_return(m, -EINVAL);
assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
- r = type_system_get_type(m->container_type_system[m->n_containers],
+ r = type_system_get_type(m->containers[m->n_containers].type_system,
&nl_type,
type_id);
if (r < 0)
@@ -691,7 +728,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
type = type_get_type(nl_type);
if (type == NETLINK_TYPE_NESTED) {
- r = type_system_get_type_system(m->container_type_system[m->n_containers],
+ r = type_system_get_type_system(m->containers[m->n_containers].type_system,
&type_system,
type_id);
if (r < 0)
@@ -699,7 +736,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
} else if (type == NETLINK_TYPE_UNION) {
const NLTypeSystemUnion *type_system_union;
- r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
+ r = type_system_get_type_system_union(m->containers[m->n_containers].type_system,
&type_system_union,
type_id);
if (r < 0)
@@ -744,7 +781,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
} else
return -EINVAL;
- r = rtnl_message_read_internal(m, type_id, &container);
+ r = netlink_message_read_internal(m, type_id, &container);
if (r < 0)
return r;
else
@@ -752,18 +789,17 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
m->n_containers ++;
- r = rtnl_message_parse(m,
- &m->rta_offset_tb[m->n_containers],
- &m->rta_tb_size[m->n_containers],
- type_system_get_count(type_system),
- container,
- size);
+ r = netlink_container_parse(m,
+ &m->containers[m->n_containers],
+ type_system_get_count(type_system),
+ container,
+ size);
if (r < 0) {
m->n_containers --;
return r;
}
- m->container_type_system[m->n_containers] = type_system;
+ m->containers[m->n_containers].type_system = type_system;
return 0;
}
@@ -773,9 +809,9 @@ int sd_netlink_message_exit_container(sd_netlink_message *m) {
assert_return(m->sealed, -EINVAL);
assert_return(m->n_containers > 0, -EINVAL);
- free(m->rta_offset_tb[m->n_containers]);
- m->rta_offset_tb[m->n_containers] = NULL;
- m->container_type_system[m->n_containers] = NULL;
+ free(m->containers[m->n_containers].attributes);
+ m->containers[m->n_containers].attributes = NULL;
+ m->containers[m->n_containers].type_system = NULL;
m->n_containers --;
@@ -810,41 +846,6 @@ int sd_netlink_message_get_errno(sd_netlink_message *m) {
return err->error;
}
-int rtnl_message_parse(sd_netlink_message *m,
- size_t **rta_offset_tb,
- unsigned short *rta_tb_size,
- int count,
- struct rtattr *rta,
- unsigned int rt_len) {
- unsigned short type;
- size_t *tb;
-
- tb = new0(size_t, count);
- if(!tb)
- return -ENOMEM;
-
- *rta_tb_size = count;
-
- for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
- type = RTA_TYPE(rta);
-
- /* if the kernel is newer than the headers we used
- when building, we ignore out-of-range attributes
- */
- if (type >= count)
- continue;
-
- if (tb[type])
- log_debug("rtnl: message parse - overwriting repeated attribute");
-
- tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
- }
-
- *rta_offset_tb = tb;
-
- return 0;
-}
-
int sd_netlink_message_rewind(sd_netlink_message *m) {
const NLType *nl_type;
uint16_t type;
@@ -859,15 +860,13 @@ int sd_netlink_message_rewind(sd_netlink_message *m) {
rtnl_message_seal(m);
for (i = 1; i <= m->n_containers; i++) {
- free(m->rta_offset_tb[i]);
- m->rta_offset_tb[i] = NULL;
- m->rta_tb_size[i] = 0;
- m->container_type_system[i] = NULL;
+ free(m->containers[i].attributes);
+ m->containers[i].attributes = NULL;
}
m->n_containers = 0;
- if (m->rta_offset_tb[0]) {
+ if (m->containers[0].attributes) {
/* top-level attributes have already been parsed */
return 0;
}
@@ -886,14 +885,13 @@ int sd_netlink_message_rewind(sd_netlink_message *m) {
type_get_type_system(nl_type, &type_system);
- m->container_type_system[0] = type_system;
+ m->containers[0].type_system = type_system;
- r = rtnl_message_parse(m,
- &m->rta_offset_tb[m->n_containers],
- &m->rta_tb_size[m->n_containers],
- type_system_get_count(type_system),
- (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)),
- NLMSG_PAYLOAD(m->hdr, size));
+ r = netlink_container_parse(m,
+ &m->containers[m->n_containers],
+ type_system_get_count(type_system),
+ (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)),
+ NLMSG_PAYLOAD(m->hdr, size));
if (r < 0)
return r;
}
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 8ebcd3f5ca..659ce18a48 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -690,6 +690,8 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
}
manager_get_session_by_pid(m, leader, &session);
+ if (!session && vtnr > 0)
+ session = (vtnr < m->seat0->position_count) ? m->seat0->positions[vtnr] : NULL;
if (session) {
_cleanup_free_ char *path = NULL;
_cleanup_close_ int fifo_fd = -1;
@@ -1486,18 +1488,13 @@ static int execute_shutdown_or_sleep(
return 0;
}
-static int manager_inhibit_timeout_handler(
- sd_event_source *s,
- uint64_t usec,
- void *userdata) {
+int manager_dispatch_delayed(Manager *manager, bool timeout) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
Inhibitor *offending = NULL;
- Manager *manager = userdata;
int r;
assert(manager);
- assert(manager->inhibit_timeout_source == s);
if (manager->action_what == 0 || manager->action_job)
return 0;
@@ -1505,6 +1502,9 @@ static int manager_inhibit_timeout_handler(
if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
_cleanup_free_ char *comm = NULL, *u = NULL;
+ if (!timeout)
+ return 0;
+
(void) get_process_comm(offending->pid, &comm);
u = uid_to_name(offending->uid);
@@ -1520,9 +1520,25 @@ static int manager_inhibit_timeout_handler(
manager->action_unit = NULL;
manager->action_what = 0;
+ return r;
}
- return 0;
+ return 1;
+}
+
+static int manager_inhibit_timeout_handler(
+ sd_event_source *s,
+ uint64_t usec,
+ void *userdata) {
+
+ Manager *manager = userdata;
+ int r;
+
+ assert(manager);
+ assert(manager->inhibit_timeout_source == s);
+
+ r = manager_dispatch_delayed(manager, true);
+ return (r < 0) ? r : 0;
}
static int delay_shutdown_or_sleep(
diff --git a/src/login/logind.c b/src/login/logind.c
index 01f7cd9ee0..e2fb496289 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -1109,6 +1109,12 @@ static int manager_run(Manager *m) {
manager_gc(m, true);
+ r = manager_dispatch_delayed(m, false);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ continue;
+
r = sd_event_run(m->event, (uint64_t) -1);
if (r < 0)
return r;
diff --git a/src/login/logind.h b/src/login/logind.h
index feb381d0b1..ad437b72cb 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -194,3 +194,5 @@ int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char
int manager_setup_wall_message_timer(Manager *m);
bool logind_wall_tty_filter(const char *tty, void *userdata);
+
+int manager_dispatch_delayed(Manager *manager, bool timeout);
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 16243a5352..dff81a5cf0 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1360,8 +1360,7 @@ static int link_joined(Link *link) {
return link_enter_set_addresses(link);
}
-static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m,
- void *userdata) {
+static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_link_unref_ Link *link = userdata;
int r;
diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index ece9ecc251..6949b403c8 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -92,10 +92,11 @@ static void netdev_cancel_callbacks(NetDev *netdev) {
assert(netdev->manager);
assert(netdev->manager->rtnl);
- callback->callback(netdev->manager->rtnl, m, link);
+ callback->callback(netdev->manager->rtnl, m, callback->link);
}
LIST_REMOVE(callbacks, netdev->callbacks, callback);
+ link_unref(callback->link);
free(callback);
}
}
@@ -177,6 +178,8 @@ int netdev_get(Manager *manager, const char *name, NetDev **ret) {
static int netdev_enter_failed(NetDev *netdev) {
netdev->state = NETDEV_STATE_FAILED;
+ netdev_cancel_callbacks(netdev);
+
return 0;
}
@@ -266,12 +269,20 @@ int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t call
int r;
assert(netdev);
+ assert(netdev->manager);
+ assert(netdev->manager->rtnl);
assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND));
if (netdev->state == NETDEV_STATE_READY) {
r = netdev_enslave_ready(netdev, link, callback);
if (r < 0)
return r;
+ } else if (IN_SET(netdev->state, NETDEV_STATE_LINGER, NETDEV_STATE_FAILED)) {
+ _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+
+ r = rtnl_message_new_synthetic_error(-ENODEV, 0, &m);
+ if (r >= 0)
+ callback(netdev->manager->rtnl, m, link);
} else {
/* the netdev is not yet read, save this request for when it is */
netdev_join_callback *cb;
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 4cf2d14ae2..7fa098bea8 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -1074,18 +1074,18 @@ static int mount_all(const char *dest, bool userns) {
} MountPoint;
static const MountPoint mount_table[] = {
- { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true, true },
- { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, true, true }, /* Bind mount first */
- { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, true, true }, /* Then, make it r/o */
- { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false },
- { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, true, false },
- { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true, false },
- { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false },
- { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false },
- { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_STRICTATIME, true, false },
+ { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true, true },
+ { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, true, true }, /* Bind mount first */
+ { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, true, true }, /* Then, make it r/o */
+ { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false },
+ { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, true, false },
+ { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true, false },
+ { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false },
+ { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false },
+ { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_STRICTATIME, true, false },
#ifdef HAVE_SELINUX
- { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, false, false }, /* Bind mount first */
- { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, false, false }, /* Then, make it r/o */
+ { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, false, false }, /* Bind mount first */
+ { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, false, false }, /* Then, make it r/o */
#endif
};
@@ -4313,10 +4313,6 @@ static int outer_child(
if (r < 0)
return r;
- r = determine_uid_shift(directory);
- if (r < 0)
- return r;
-
/* Turn directory into bind mount */
if (mount(directory, directory, NULL, MS_BIND|MS_REC, NULL) < 0)
return log_error_errno(errno, "Failed to make bind mount: %m");
@@ -4495,6 +4491,10 @@ int main(int argc, char *argv[]) {
if (r < 0)
goto finish;
+ r = determine_uid_shift(arg_directory);
+ if (r < 0)
+ return r;
+
if (geteuid() != 0) {
log_error("Need to be root.");
r = -EPERM;
diff --git a/src/shared/install.c b/src/shared/install.c
index 559fda211d..c37cf1948a 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -2263,7 +2263,7 @@ int unit_file_get_list(
}
}
- return r;
+ return 0;
}
static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c
index 9ae518ac4a..45b119362c 100644
--- a/src/sysv-generator/sysv-generator.c
+++ b/src/sysv-generator/sysv-generator.c
@@ -240,20 +240,21 @@ static bool usage_contains_reload(const char *line) {
}
static char *sysv_translate_name(const char *name) {
- char *r;
+ _cleanup_free_ char *c = NULL;
+ char *res;
- r = new(char, strlen(name) + strlen(".service") + 1);
- if (!r)
+ c = strdup(name);
+ if (!c)
return NULL;
- if (endswith(name, ".sh"))
- /* Drop .sh suffix */
- strcpy(stpcpy(r, name) - 3, ".service");
- else
- /* Normal init script name */
- strcpy(stpcpy(r, name), ".service");
+ res = endswith(c, ".sh");
+ if (res)
+ *res = 0;
- return r;
+ if (unit_name_mangle(c, UNIT_NAME_NOGLOB, &res) < 0)
+ return NULL;
+
+ return res;
}
static int sysv_translate_facility(const char *name, const char *filename, char **_r) {
@@ -340,6 +341,7 @@ static int handle_provides(SysvStub *s, unsigned line, const char *full_text, co
FOREACH_WORD_QUOTED(word, z, text, state_) {
_cleanup_free_ char *n = NULL, *m = NULL;
+ UnitType t;
n = strndup(word, z);
if (!n)
@@ -351,12 +353,13 @@ static int handle_provides(SysvStub *s, unsigned line, const char *full_text, co
if (r == 0)
continue;
- if (unit_name_to_type(m) == UNIT_SERVICE) {
+ t = unit_name_to_type(m);
+ if (t == UNIT_SERVICE) {
log_debug("Adding Provides: alias '%s' for '%s'", m, s->name);
r = add_alias(s->name, m);
if (r < 0)
log_warning_errno(r, "[%s:%u] Failed to add LSB Provides name %s, ignoring: %m", s->path, line, m);
- } else {
+ } else if (t == UNIT_TARGET) {
/* NB: SysV targets which are provided by a
* service are pulled in by the services, as
* an indication that the generic service is
@@ -373,7 +376,10 @@ static int handle_provides(SysvStub *s, unsigned line, const char *full_text, co
if (r < 0)
return log_oom();
}
- }
+ } else if (t == _UNIT_TYPE_INVALID)
+ log_warning("Unit name '%s' is invalid", m);
+ else
+ log_warning("Unknown unit type for unit '%s'", m);
}
if (!isempty(state_))
log_error("[%s:%u] Trailing garbage in Provides, ignoring.", s->path, line);
diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c
index 195d5f3892..25c25952aa 100644
--- a/src/timedate/timedatectl.c
+++ b/src/timedate/timedatectl.c
@@ -154,11 +154,12 @@ static void print_status_info(const StatusInfo *i) {
if (i->rtc_local)
fputs("\n" ANSI_HIGHLIGHT_ON
- "Warning: The system is configured to read the RTC time in the local time zone. This\n"
- " mode can not be fully supported. It will create various problems with time\n"
- " zone changes and daylight saving time adjustments. The RTC time is never updated,\n"
- " it relies on external facilities to maintain it. If at all possible, use\n"
- " RTC in UTC by calling 'timedatectl set-local-rtc 0'" ANSI_HIGHLIGHT_OFF ".\n", stdout);
+ "Warning: The system is configured to read the RTC time in the local time zone.\n"
+ " This mode can not be fully supported. It will create various problems\n"
+ " with time zone changes and daylight saving time adjustments. The RTC\n"
+ " time is never updated, it relies on external facilities to maintain it.\n"
+ " If at all possible, use RTC in UTC by calling\n"
+ " 'timedatectl set-local-rtc 0'" ANSI_HIGHLIGHT_OFF ".\n", stdout);
}
static int show_status(sd_bus *bus, char **args, unsigned n) {
diff --git a/src/udev/accelerometer/Makefile b/src/udev/accelerometer/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/udev/accelerometer/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/udev/accelerometer/accelerometer.c b/src/udev/accelerometer/accelerometer.c
deleted file mode 100644
index 9e2c590c15..0000000000
--- a/src/udev/accelerometer/accelerometer.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * accelerometer - exports device orientation through property
- *
- * When an "change" event is received on an accelerometer,
- * open its device node, and from the value, as well as the previous
- * value of the property, calculate the device's new orientation,
- * and export it as ID_INPUT_ACCELEROMETER_ORIENTATION.
- *
- * Possible values are:
- * undefined
- * * normal
- * * bottom-up
- * * left-up
- * * right-up
- *
- * The property will be persistent across sessions, and the new
- * orientations can be deducted from the previous one (it allows
- * for a threshold for switching between opposite ends of the
- * orientation).
- *
- * Copyright (C) 2011 Red Hat, Inc.
- * Author:
- * Bastien Nocera <hadess@hadess.net>
- *
- * orientation_calc() from the sensorfw package
- * Copyright (C) 2009-2010 Nokia Corporation
- * Authors:
- * Üstün Ergenoglu <ext-ustun.ergenoglu@nokia.com>
- * Timo Rongas <ext-timo.2.rongas@nokia.com>
- * Lihan Guo <lihan.guo@digia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <limits.h>
-#include <linux/input.h>
-
-#include "libudev.h"
-#include "libudev-private.h"
-
-/* we must use this kernel-compatible implementation */
-#define BITS_PER_LONG (sizeof(unsigned long) * 8)
-#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
-#define OFF(x) ((x)%BITS_PER_LONG)
-#define BIT(x) (1UL<<OFF(x))
-#define LONG(x) ((x)/BITS_PER_LONG)
-#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
-
-typedef enum {
- ORIENTATION_UNDEFINED,
- ORIENTATION_NORMAL,
- ORIENTATION_BOTTOM_UP,
- ORIENTATION_LEFT_UP,
- ORIENTATION_RIGHT_UP
-} OrientationUp;
-
-static const char *orientations[] = {
- "undefined",
- "normal",
- "bottom-up",
- "left-up",
- "right-up",
- NULL
-};
-
-#define ORIENTATION_UP_UP ORIENTATION_NORMAL
-
-#define DEFAULT_THRESHOLD 250
-#define RADIANS_TO_DEGREES 180.0/M_PI
-#define SAME_AXIS_LIMIT 5
-
-#define THRESHOLD_LANDSCAPE 25
-#define THRESHOLD_PORTRAIT 20
-
-static const char *
-orientation_to_string (OrientationUp o)
-{
- return orientations[o];
-}
-
-static OrientationUp
-string_to_orientation (const char *orientation)
-{
- int i;
-
- if (orientation == NULL)
- return ORIENTATION_UNDEFINED;
- for (i = 0; orientations[i] != NULL; i++) {
- if (streq (orientation, orientations[i]))
- return i;
- }
- return ORIENTATION_UNDEFINED;
-}
-
-static OrientationUp
-orientation_calc (OrientationUp prev,
- int x, int y, int z)
-{
- int rotation;
- OrientationUp ret = prev;
-
- /* Portrait check */
- rotation = round(atan((double) x / sqrt(y * y + z * z)) * RADIANS_TO_DEGREES);
-
- if (abs(rotation) > THRESHOLD_PORTRAIT) {
- ret = (rotation < 0) ? ORIENTATION_LEFT_UP : ORIENTATION_RIGHT_UP;
-
- /* Some threshold to switching between portrait modes */
- if (prev == ORIENTATION_LEFT_UP || prev == ORIENTATION_RIGHT_UP) {
- if (abs(rotation) < SAME_AXIS_LIMIT) {
- ret = prev;
- }
- }
-
- } else {
- /* Landscape check */
- rotation = round(atan((double) y / sqrt(x * x + z * z)) * RADIANS_TO_DEGREES);
-
- if (abs(rotation) > THRESHOLD_LANDSCAPE) {
- ret = (rotation < 0) ? ORIENTATION_BOTTOM_UP : ORIENTATION_NORMAL;
-
- /* Some threshold to switching between landscape modes */
- if (prev == ORIENTATION_BOTTOM_UP || prev == ORIENTATION_NORMAL) {
- if (abs(rotation) < SAME_AXIS_LIMIT) {
- ret = prev;
- }
- }
- }
- }
-
- return ret;
-}
-
-static OrientationUp
-get_prev_orientation(struct udev_device *dev)
-{
- const char *value;
-
- value = udev_device_get_property_value(dev, "ID_INPUT_ACCELEROMETER_ORIENTATION");
- if (value == NULL)
- return ORIENTATION_UNDEFINED;
- return string_to_orientation(value);
-}
-
-#define READ_AXIS(axis, var) { memzero(&abs_info, sizeof(abs_info)); r = ioctl(fd, EVIOCGABS(axis), &abs_info); if (r < 0) return; var = abs_info.value; }
-
-/* accelerometers */
-static void test_orientation(struct udev *udev,
- struct udev_device *dev,
- const char *devpath)
-{
- OrientationUp old, new;
- _cleanup_close_ int fd = -1;
- struct input_absinfo abs_info;
- int x = 0, y = 0, z = 0;
- int r;
- char text[64];
-
- old = get_prev_orientation(dev);
-
- fd = open(devpath, O_RDONLY|O_CLOEXEC);
- if (fd < 0)
- return;
-
- READ_AXIS(ABS_X, x);
- READ_AXIS(ABS_Y, y);
- READ_AXIS(ABS_Z, z);
-
- new = orientation_calc(old, x, y, z);
- snprintf(text, sizeof(text),
- "ID_INPUT_ACCELEROMETER_ORIENTATION=%s", orientation_to_string(new));
- puts(text);
-}
-
-static void help(void) {
-
- printf("%s [options] <device path>\n\n"
- "Accelerometer device identification.\n\n"
- " -h --help Print this message\n"
- " -d --debug Debug to stderr\n"
- , program_invocation_short_name);
-}
-
-int main (int argc, char** argv)
-{
- struct udev *udev;
- struct udev_device *dev;
-
- static const struct option options[] = {
- { "debug", no_argument, NULL, 'd' },
- { "help", no_argument, NULL, 'h' },
- {}
- };
-
- char devpath[PATH_MAX];
- char *devnode;
- struct udev_enumerate *enumerate;
- struct udev_list_entry *list_entry;
-
- log_parse_environment();
- log_open();
-
- udev = udev_new();
- if (udev == NULL)
- return 1;
-
- /* CLI argument parsing */
- while (1) {
- int option;
-
- option = getopt_long(argc, argv, "dh", options, NULL);
- if (option == -1)
- break;
-
- switch (option) {
- case 'd':
- log_set_target(LOG_TARGET_CONSOLE);
- log_set_max_level(LOG_DEBUG);
- log_open();
- break;
- case 'h':
- help();
- exit(0);
- default:
- exit(1);
- }
- }
-
- if (argv[optind] == NULL) {
- help();
- exit(1);
- }
-
- /* get the device */
- snprintf(devpath, sizeof(devpath), "/sys/%s", argv[optind]);
- dev = udev_device_new_from_syspath(udev, devpath);
- if (dev == NULL) {
- fprintf(stderr, "unable to access '%s'\n", devpath);
- return 1;
- }
-
- /* Get the children devices and find the devnode */
- devnode = NULL;
- enumerate = udev_enumerate_new(udev);
- udev_enumerate_add_match_parent(enumerate, dev);
- udev_enumerate_scan_devices(enumerate);
- udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
- struct udev_device *device;
- const char *node;
-
- device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
- udev_list_entry_get_name(list_entry));
- if (device == NULL)
- continue;
- /* Already found it */
- if (devnode != NULL) {
- udev_device_unref(device);
- continue;
- }
-
- node = udev_device_get_devnode(device);
- if (node == NULL) {
- udev_device_unref(device);
- continue;
- }
- /* Use the event sub-device */
- if (strstr(node, "/event") == NULL) {
- udev_device_unref(device);
- continue;
- }
-
- devnode = strdup(node);
- udev_device_unref(device);
- }
-
- if (devnode == NULL) {
- fprintf(stderr, "unable to get device node for '%s'\n", devpath);
- return 0;
- }
-
- log_debug("opening accelerometer device %s", devnode);
- test_orientation(udev, dev, devnode);
- free(devnode);
- log_close();
- return 0;
-}
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 1092071e26..4761222786 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -721,19 +721,13 @@ int udev_event_spawn(struct udev_event *event,
usec_t timeout_usec,
usec_t timeout_warn_usec,
bool accept_failure,
- const char *cmd, char **envp,
+ const char *cmd,
char *result, size_t ressize) {
int outpipe[2] = {-1, -1};
int errpipe[2] = {-1, -1};
pid_t pid;
- char arg[UTIL_PATH_SIZE];
- char *argv[128];
- char program[UTIL_PATH_SIZE];
int err = 0;
- strscpy(arg, sizeof(arg), cmd);
- udev_build_argv(event->udev, arg, NULL, argv);
-
/* pipes from child to parent */
if (result != NULL || log_get_max_level() >= LOG_INFO) {
if (pipe2(outpipe, O_NONBLOCK) != 0) {
@@ -750,15 +744,14 @@ int udev_event_spawn(struct udev_event *event,
}
}
- /* allow programs in /usr/lib/udev/ to be called without the path */
- if (argv[0][0] != '/') {
- strscpyl(program, sizeof(program), UDEVLIBEXECDIR "/", argv[0], NULL);
- argv[0] = program;
- }
-
pid = fork();
switch(pid) {
case 0:
+ {
+ char arg[UTIL_PATH_SIZE];
+ char *argv[128];
+ char program[UTIL_PATH_SIZE];
+
/* child closes parent's ends of pipes */
if (outpipe[READ_END] >= 0) {
close(outpipe[READ_END]);
@@ -769,12 +762,22 @@ int udev_event_spawn(struct udev_event *event,
errpipe[READ_END] = -1;
}
+ strscpy(arg, sizeof(arg), cmd);
+ udev_build_argv(event->udev, arg, NULL, argv);
+
+ /* allow programs in /usr/lib/udev/ to be called without the path */
+ if (argv[0][0] != '/') {
+ strscpyl(program, sizeof(program), UDEVLIBEXECDIR "/", argv[0], NULL);
+ argv[0] = program;
+ }
+
log_debug("starting '%s'", cmd);
- spawn_exec(event, cmd, argv, envp,
+ spawn_exec(event, cmd, argv, udev_device_get_properties_envp(event->dev),
outpipe[WRITE_END], errpipe[WRITE_END]);
- _exit(2 );
+ _exit(2);
+ }
case -1:
log_error_errno(errno, "fork of '%s' failed: %m", cmd);
err = -1;
@@ -934,26 +937,21 @@ void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_
struct udev_list_entry *list_entry;
udev_list_entry_foreach(list_entry, udev_list_get_entry(&event->run_list)) {
+ char command[UTIL_PATH_SIZE];
const char *cmd = udev_list_entry_get_name(list_entry);
enum udev_builtin_cmd builtin_cmd = udev_list_entry_get_num(list_entry);
- if (builtin_cmd < UDEV_BUILTIN_MAX) {
- char command[UTIL_PATH_SIZE];
+ udev_event_apply_format(event, cmd, command, sizeof(command));
- udev_event_apply_format(event, cmd, command, sizeof(command));
+ if (builtin_cmd < UDEV_BUILTIN_MAX)
udev_builtin_run(event->dev, builtin_cmd, command, false);
- } else {
- char program[UTIL_PATH_SIZE];
- char **envp;
-
+ else {
if (event->exec_delay > 0) {
- log_debug("delay execution of '%s'", program);
+ log_debug("delay execution of '%s'", command);
sleep(event->exec_delay);
}
- udev_event_apply_format(event, cmd, program, sizeof(program));
- envp = udev_device_get_properties_envp(event->dev);
- udev_event_spawn(event, timeout_usec, timeout_warn_usec, false, program, envp, NULL, 0);
+ udev_event_spawn(event, timeout_usec, timeout_warn_usec, false, command, NULL, 0);
}
}
}
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index 8ebc061eb1..d00f90afa6 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -634,14 +634,11 @@ static int import_program_into_properties(struct udev_event *event,
usec_t timeout_usec,
usec_t timeout_warn_usec,
const char *program) {
- struct udev_device *dev = event->dev;
- char **envp;
char result[UTIL_LINE_SIZE];
char *line;
int err;
- envp = udev_device_get_properties_envp(dev);
- err = udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, envp, result, sizeof(result));
+ err = udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, result, sizeof(result));
if (err < 0)
return err;
@@ -654,7 +651,7 @@ static int import_program_into_properties(struct udev_event *event,
pos[0] = '\0';
pos = &pos[1];
}
- import_property_from_string(dev, line);
+ import_property_from_string(event->dev, line);
line = pos;
}
return 0;
@@ -682,41 +679,6 @@ static int import_parent_into_properties(struct udev_device *dev, const char *fi
return 0;
}
-#define WAIT_LOOP_PER_SECOND 50
-static int wait_for_file(struct udev_device *dev, const char *file, int timeout) {
- char filepath[UTIL_PATH_SIZE];
- char devicepath[UTIL_PATH_SIZE];
- struct stat stats;
- int loop = timeout * WAIT_LOOP_PER_SECOND;
-
- /* a relative path is a device attribute */
- devicepath[0] = '\0';
- if (file[0] != '/') {
- strscpyl(devicepath, sizeof(devicepath), udev_device_get_syspath(dev), NULL);
- strscpyl(filepath, sizeof(filepath), devicepath, "/", file, NULL);
- file = filepath;
- }
-
- while (--loop) {
- const struct timespec duration = { 0, 1000 * 1000 * 1000 / WAIT_LOOP_PER_SECOND };
-
- /* lookup file */
- if (stat(file, &stats) == 0) {
- log_debug("file '%s' appeared after %i loops", file, (timeout * WAIT_LOOP_PER_SECOND) - loop-1);
- return 0;
- }
- /* make sure, the device did not disappear in the meantime */
- if (devicepath[0] != '\0' && stat(devicepath, &stats) != 0) {
- log_debug("device disappeared while waiting for '%s'", file);
- return -2;
- }
- log_debug("wait for '%s' for %i mseconds", file, 1000 / WAIT_LOOP_PER_SECOND);
- nanosleep(&duration, NULL);
- }
- log_debug("waiting for '%s' failed", file);
- return -1;
-}
-
static int attr_subst_subdir(char *attr, size_t len) {
bool found = false;
@@ -1397,15 +1359,6 @@ static int add_rule(struct udev_rules *rules, char *line,
continue;
}
- if (streq(key, "WAIT_FOR") || streq(key, "WAIT_FOR_SYSFS")) {
- if (op == OP_REMOVE) {
- log_error("invalid WAIT_FOR/WAIT_FOR_SYSFS operation");
- goto invalid;
- }
- rule_add_key(&rule_tmp, TK_M_WAITFOR, 0, value, NULL);
- continue;
- }
-
if (streq(key, "LABEL")) {
if (op == OP_REMOVE) {
log_error("invalid LABEL operation");
@@ -1999,16 +1952,6 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
if (match_key(rules, cur, udev_device_get_driver(event->dev)) != 0)
goto nomatch;
break;
- case TK_M_WAITFOR: {
- char filename[UTIL_PATH_SIZE];
- int found;
-
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), filename, sizeof(filename));
- found = (wait_for_file(event->dev, filename, 10) == 0);
- if (!found && (cur->key.op != OP_NOMATCH))
- goto nomatch;
- break;
- }
case TK_M_ATTR:
if (match_attr(rules, event->dev, event, cur) != 0)
goto nomatch;
@@ -2119,19 +2062,17 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
}
case TK_M_PROGRAM: {
char program[UTIL_PATH_SIZE];
- char **envp;
char result[UTIL_LINE_SIZE];
free(event->program_result);
event->program_result = NULL;
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), program, sizeof(program));
- envp = udev_device_get_properties_envp(event->dev);
log_debug("PROGRAM '%s' %s:%u",
program,
rules_str(rules, rule->rule.filename_off),
rule->rule.filename_line);
- if (udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, envp, result, sizeof(result)) < 0) {
+ if (udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, result, sizeof(result)) < 0) {
if (cur->key.op != OP_NOMATCH)
goto nomatch;
} else {
diff --git a/src/udev/udev.h b/src/udev/udev.h
index 3dca72e499..d17fc8c1ea 100644
--- a/src/udev/udev.h
+++ b/src/udev/udev.h
@@ -85,8 +85,7 @@ int udev_event_spawn(struct udev_event *event,
usec_t timeout_usec,
usec_t timeout_warn_usec,
bool accept_failure,
- const char *cmd, char **envp,
- char *result, size_t ressize);
+ const char *cmd, char *result, size_t ressize);
void udev_event_execute_rules(struct udev_event *event,
usec_t timeout_usec, usec_t timeout_warn_usec,
struct udev_list *properties_list,
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index cf15ddf641..e27fb1fd9e 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -1608,8 +1608,42 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
return 0;
}
-int main(int argc, char *argv[]) {
+static int run(int fd_ctrl, int fd_uevent, const char *cgroup) {
_cleanup_(manager_freep) Manager *manager = NULL;
+ int r;
+
+ r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup);
+ if (r < 0) {
+ r = log_error_errno(r, "failed to allocate manager object: %m");
+ goto exit;
+ }
+
+ r = udev_rules_apply_static_dev_perms(manager->rules);
+ if (r < 0)
+ log_error_errno(r, "failed to apply permissions on static device nodes: %m");
+
+ (void) sd_notify(false,
+ "READY=1\n"
+ "STATUS=Processing...");
+
+ r = sd_event_loop(manager->event);
+ if (r < 0) {
+ log_error_errno(r, "event loop failed: %m");
+ goto exit;
+ }
+
+ sd_event_get_exit_code(manager->event, &r);
+
+exit:
+ sd_notify(false,
+ "STOPPING=1\n"
+ "STATUS=Shutting down...");
+ if (manager)
+ udev_ctrl_cleanup(manager->ctrl);
+ return r;
+}
+
+int main(int argc, char *argv[]) {
_cleanup_free_ char *cgroup = NULL;
int r, fd_ctrl, fd_uevent;
@@ -1625,8 +1659,10 @@ int main(int argc, char *argv[]) {
if (r < 0)
log_warning_errno(r, "failed to parse kernel command line, ignoring: %m");
- if (arg_debug)
+ if (arg_debug) {
+ log_set_target(LOG_TARGET_CONSOLE);
log_set_max_level(LOG_DEBUG);
+ }
if (getuid() != 0) {
r = log_error_errno(EPERM, "root privileges required");
@@ -1714,35 +1750,9 @@ int main(int argc, char *argv[]) {
write_string_file("/proc/self/oom_score_adj", "-1000");
}
- r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup);
- if (r < 0) {
- r = log_error_errno(r, "failed to allocate manager object: %m");
- goto exit;
- }
-
- r = udev_rules_apply_static_dev_perms(manager->rules);
- if (r < 0)
- log_error_errno(r, "failed to apply permissions on static device nodes: %m");
-
- (void) sd_notify(false,
- "READY=1\n"
- "STATUS=Processing...");
-
- r = sd_event_loop(manager->event);
- if (r < 0) {
- log_error_errno(r, "event loop failed: %m");
- goto exit;
- }
-
- sd_event_get_exit_code(manager->event, &r);
+ r = run(fd_ctrl, fd_uevent, cgroup);
exit:
- sd_notify(false,
- "STOPPING=1\n"
- "STATUS=Shutting down...");
-
- if (manager)
- udev_ctrl_cleanup(manager->ctrl);
mac_selinux_finish();
log_close();
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;