dbus: complete exec coverage
authorLennart Poettering <lennart@poettering.net>
Sun, 4 Jul 2010 14:44:58 +0000 (16:44 +0200)
committerLennart Poettering <lennart@poettering.net>
Sun, 4 Jul 2010 14:44:58 +0000 (16:44 +0200)
12 files changed:
fixme
src/dbus-execute.c
src/dbus-execute.h
src/dbus.c
src/dbus.h
src/execute.c
src/execute.h
src/load-fragment.c
src/missing.h
src/systemctl.c
src/util.c
src/util.h

diff --git a/fixme b/fixme
index 2f0f929..55e47d7 100644 (file)
--- a/fixme
+++ b/fixme
 
 * systemctl daemon-reload is kaputt
 
+* get rid of Subscribe() in systemctl
+
+* Unify NS, USec, NSec, Sec suffixes in properties, use format_timespan
+
+* Turn around negative options
+
 External:
 
 * patch /etc/init.d/functions with:
index 8840396..a41b639 100644 (file)
 
 #include <errno.h>
 #include <dbus/dbus.h>
+#include <sys/prctl.h>
 
 #include "dbus-execute.h"
+#include "missing.h"
+#include "ioprio.h"
 
 DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_input, exec_input, ExecInput);
 DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_output, exec_output, ExecOutput);
+
+int bus_execute_append_oom_adjust(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+        ExecContext *c = data;
+        int32_t n;
+
+        assert(m);
+        assert(i);
+        assert(property);
+        assert(c);
+
+        if (c->oom_adjust_set)
+                n = c->oom_adjust;
+        else {
+                char *t;
+
+                n = 0;
+                if (read_one_line_file("/proc/self/oom_adj", &t) >= 0) {
+                        safe_atoi(t, &n);
+                        free(t);
+                }
+        }
+
+        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
+                return -ENOMEM;
+
+        return 0;
+}
+
+int bus_execute_append_nice(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+        ExecContext *c = data;
+        int32_t n;
+
+        assert(m);
+        assert(i);
+        assert(property);
+        assert(c);
+
+        if (c->nice_set)
+                n = c->nice;
+        else
+                n = getpriority(PRIO_PROCESS, 0);
+
+        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
+                return -ENOMEM;
+
+        return 0;
+}
+
+int bus_execute_append_ioprio(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+        ExecContext *c = data;
+        int32_t n;
+
+        assert(m);
+        assert(i);
+        assert(property);
+        assert(c);
+
+        if (c->ioprio_set)
+                n = c->ioprio;
+        else
+                n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
+
+        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
+                return -ENOMEM;
+
+        return 0;
+}
+
+int bus_execute_append_cpu_sched_policy(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+        ExecContext *c = data;
+        int32_t n;
+
+        assert(m);
+        assert(i);
+        assert(property);
+        assert(c);
+
+        if (c->cpu_sched_set)
+                n = c->cpu_sched_policy;
+        else
+                n = sched_getscheduler(0);
+
+        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
+                return -ENOMEM;
+
+        return 0;
+}
+
+int bus_execute_append_cpu_sched_priority(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+        ExecContext *c = data;
+        int32_t n;
+
+        assert(m);
+        assert(i);
+        assert(property);
+        assert(c);
+
+        if (c->cpu_sched_set)
+                n = c->cpu_sched_priority;
+        else {
+                struct sched_param p;
+                n = 0;
+
+                zero(p);
+                if (sched_getparam(0, &p) >= 0)
+                        n = p.sched_priority;
+        }
+
+        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
+                return -ENOMEM;
+
+        return 0;
+}
+
+int bus_execute_append_affinity(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+        ExecContext *c = data;
+        dbus_bool_t b;
+        DBusMessageIter sub;
+
+        assert(m);
+        assert(i);
+        assert(property);
+        assert(c);
+
+        if (!(dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub)))
+                return -ENOMEM;
+
+        if (c->cpuset)
+                b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
+        else
+                b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, 0);
+
+        if (!b)
+                return -ENOMEM;
+
+        if (!dbus_message_iter_close_container(i, &sub))
+                return -ENOMEM;
+
+        return 0;
+}
+
+int bus_execute_append_timer_slack_ns(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+        ExecContext *c = data;
+        uint64_t u;
+
+        assert(m);
+        assert(i);
+        assert(property);
+        assert(c);
+
+        if (c->timer_slack_ns_set)
+                u = (uint64_t) c->timer_slack_ns_set;
+        else
+                u = (uint64_t) prctl(PR_GET_TIMERSLACK);
+
+        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
+                return -ENOMEM;
+
+        return 0;
+}
+
+int bus_execute_append_capabilities(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+        ExecContext *c = data;
+        char *t = NULL;
+        const char *s;
+        dbus_bool_t b;
+
+        assert(m);
+        assert(i);
+        assert(property);
+        assert(c);
+
+        if (c->capabilities)
+                s = t = cap_to_text(c->capabilities, NULL);
+        else
+                s = "";
+
+        if (!t)
+                return -ENOMEM;
+
+        b = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &s);
+        cap_free(t);
+
+        if (!b)
+                return -ENOMEM;
+
+        return 0;
+}
+
+int bus_execute_append_rlimits(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+        ExecContext *c = data;
+        int r;
+        uint64_t u;
+
+        assert(m);
+        assert(i);
+        assert(property);
+        assert(c);
+
+        assert_se((r = rlimit_from_string(property)) >= 0);
+
+        if (c->rlimit[r])
+                u = (uint64_t) c->rlimit[r]->rlim_max;
+        else {
+                struct rlimit rl;
+
+                zero(rl);
+                getrlimit(r, &rl);
+
+                u = (uint64_t) rl.rlim_max;
+        }
+
+        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
+                return -ENOMEM;
+
+        return 0;
+}
index 1e83cac..f6cca9c 100644 (file)
 #define BUS_EXEC_CONTEXT_INTERFACE                                      \
         "  <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
         "  <property name=\"UMask\" type=\"u\" access=\"read\"/>\n"     \
+        "  <property name=\"LimitCPU\" type=\"t\" access=\"read\"/>\n"  \
+        "  <property name=\"LimitFSIZE\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"LimitDATA\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"LimitSTACK\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"LimitCORE\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"LimitRSS\" type=\"t\" access=\"read\"/>\n"  \
+        "  <property name=\"LimitNOFILE\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"LimitAS\" type=\"t\" access=\"read\"/>\n"   \
+        "  <property name=\"LimitNPROC\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"LimitMEMLOCK\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"LimitLOCKS\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"LimitSIGPENDING\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"LimitMSGQUEUE\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"LimitNICE\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"LimitRTPRIO\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"LimitRTTIME\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"WorkingDirectory\" type=\"s\" access=\"read\"/>\n" \
         "  <property name=\"RootDirectory\" type=\"s\" access=\"read\"/>\n" \
+        "  <property name=\"OOMAdjust\" type=\"i\" access=\"read\"/>\n" \
+        "  <property name=\"Nice\" type=\"i\" access=\"read\"/>\n" \
+        "  <property name=\"IOScheduling\" type=\"i\" access=\"read\"/>\n" \
+        "  <property name=\"CPUSchedulingPolicy\" type=\"i\" access=\"read\"/>\n" \
+        "  <property name=\"CPUSchedulingPriority\" type=\"i\" access=\"read\"/>\n" \
+        "  <property name=\"CPUAffinity\" type=\"ay\" access=\"read\"/>\n" \
+        "  <property name=\"TimerSlackNS\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"CPUSchedulingResetOnFork\" type=\"b\" access=\"read\"/>\n" \
         "  <property name=\"NonBlocking\" type=\"b\" access=\"read\"/>\n" \
         "  <property name=\"StandardInput\" type=\"s\" access=\"read\"/>\n" \
         "  <property name=\"TTYPath\" type=\"s\" access=\"read\"/>\n"   \
         "  <property name=\"SyslogPriority\" type=\"i\" access=\"read\"/>\n" \
         "  <property name=\"SyslogIdentifier\" type=\"s\" access=\"read\"/>\n" \
+        "  <property name=\"SyslogNoPrefix\" type=\"b\" access=\"read\"/>\n" \
+        "  <property name=\"Capabilities\" type=\"s\" access=\"read\"/>\n" \
         "  <property name=\"SecureBits\" type=\"i\" access=\"read\"/>\n" \
         "  <property name=\"CapabilityBoundingSetDrop\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"User\" type=\"s\" access=\"read\"/>\n"      \
         "  <property name=\"Group\" type=\"s\" access=\"read\"/>\n"     \
         "  <property name=\"SupplementaryGroups\" type=\"as\" access=\"read\"/>\n" \
         "  <property name=\"TCPWrapName\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"PAMName\" type=\"s\" access=\"read\"/>\n"
+        "  <property name=\"PAMName\" type=\"s\" access=\"read\"/>\n"   \
+        "  <property name=\"ReadWriteDirectories\" type=\"as\" access=\"read\"/>\n" \
+        "  <property name=\"ReadOnlyDirectories\" type=\"as\" access=\"read\"/>\n" \
+        "  <property name=\"InaccessibleDirectories\" type=\"as\" access=\"read\"/>\n" \
+        "  <property name=\"MountFlags\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"PrivateTmp\" type=\"b\" access=\"read\"/>\n" \
+        "  <property name=\"NoSetSID\" type=\"b\" access=\"read\"/>\n"  \
 
 #define BUS_EXEC_CONTEXT_PROPERTIES(interface, context)                 \
         { interface, "Environment",                   bus_property_append_strv,   "as",    (context).environment                   }, \
         { interface, "UMask",                         bus_property_append_mode,   "u",     &(context).umask                        }, \
-            /* RLimits */                                               \
+        { interface, "LimitCPU",                      bus_execute_append_rlimits, "t",     &(context)                              }, \
+        { interface, "LimitFSIZE",                    bus_execute_append_rlimits, "t",     &(context)                              }, \
+        { interface, "LimitDATA",                     bus_execute_append_rlimits, "t",     &(context)                              }, \
+        { interface, "LimitSTACK",                    bus_execute_append_rlimits, "t",     &(context)                              }, \
+        { interface, "LimitCORE",                     bus_execute_append_rlimits, "t",     &(context)                              }, \
+        { interface, "LimitRSS",                      bus_execute_append_rlimits, "t",     &(context)                              }, \
+        { interface, "LimitNOFILE",                   bus_execute_append_rlimits, "t",     &(context)                              }, \
+        { interface, "LimitAS",                       bus_execute_append_rlimits, "t",     &(context)                              }, \
+        { interface, "LimitNPROC",                    bus_execute_append_rlimits, "t",     &(context)                              }, \
+        { interface, "LimitMEMLOCK",                  bus_execute_append_rlimits, "t",     &(context)                              }, \
+        { interface, "LimitLOCKS",                    bus_execute_append_rlimits, "t",     &(context)                              }, \
+        { interface, "LimitSIGPENDING",               bus_execute_append_rlimits, "t",     &(context)                              }, \
+        { interface, "LimitMSGQUEUE",                 bus_execute_append_rlimits, "t",     &(context)                              }, \
+        { interface, "LimitNICE",                     bus_execute_append_rlimits, "t",     &(context)                              }, \
+        { interface, "LimitRTPRIO",                   bus_execute_append_rlimits, "t",     &(context)                              }, \
+        { interface, "LimitRTTIME",                   bus_execute_append_rlimits, "t",     &(context)                              }, \
         { interface, "WorkingDirectory",              bus_property_append_string, "s",     (context).working_directory             }, \
         { interface, "RootDirectory",                 bus_property_append_string, "s",     (context).root_directory                }, \
-            /* OOM Adjust */                                            \
-            /* Nice */                                                  \
-            /* IOPrio */                                                \
-            /* CPUSchedPolicy */                                        \
-            /* CPUSchedPriority */                                      \
-            /* CPUAffinity */                                           \
-            /* TimerSlackNS */                                          \
+        { interface, "OOMAdjust",                     bus_execute_append_oom_adjust, "i",  &(context)                              }, \
+        { interface, "Nice",                          bus_execute_append_nice,    "i",     &(context)                              }, \
+        { interface, "IOScheduling",                  bus_execute_append_ioprio,  "i",     &(context)                              }, \
+        { interface, "CPUSchedulingPolicy",           bus_execute_append_cpu_sched_policy, "i", &(context)                         }, \
+        { interface, "CPUSchedulingPriority",         bus_execute_append_cpu_sched_priority, "i", &(context)                       }, \
+        { interface, "CPUAffinity",                   bus_execute_append_affinity,"ay",    &(context)                              }, \
+        { interface, "TimerSlackNS",                  bus_execute_append_timer_slack_ns, "t", &(context)                           }, \
         { interface, "CPUSchedulingResetOnFork",      bus_property_append_bool,   "b",     &(context).cpu_sched_reset_on_fork      }, \
         { interface, "NonBlocking",                   bus_property_append_bool,   "b",     &(context).non_blocking                 }, \
         { interface, "StandardInput",                 bus_execute_append_input,   "s",     &(context).std_input                    }, \
         { interface, "TTYPath",                       bus_property_append_string, "s",     (context).tty_path                      }, \
         { interface, "SyslogPriority",                bus_property_append_int,    "i",     &(context).syslog_priority              }, \
         { interface, "SyslogIdentifier",              bus_property_append_string, "s",     (context).syslog_identifier             }, \
-            /* CAPABILITIES */                                          \
+        { interface, "SyslogNoPrefix",                bus_property_append_bool,   "b",     &(context).syslog_no_prefix             }, \
+        { interface, "Capabilities",                  bus_property_append_string, "s",     (context).capabilities                  }, \
         { interface, "SecureBits",                    bus_property_append_int,    "i",     &(context).secure_bits                  }, \
         { interface, "CapabilityBoundingSetDrop",     bus_property_append_uint64, "t",     &(context).capability_bounding_set_drop }, \
         { interface, "User",                          bus_property_append_string, "s",     (context).user                          }, \
         { interface, "Group",                         bus_property_append_string, "s",     (context).group                         }, \
         { interface, "SupplementaryGroups",           bus_property_append_strv,   "as",    (context).supplementary_groups          }, \
         { interface, "TCPWrapName",                   bus_property_append_string, "s",     (context).tcpwrap_name                  }, \
-        { interface, "PAMName",                       bus_property_append_string, "s",     (context).pam_name                      }
+        { interface, "PAMName",                       bus_property_append_string, "s",     (context).pam_name                      }, \
+        { interface, "ReadWriteDirectories",          bus_property_append_strv,   "as",    (context).read_write_dirs               }, \
+        { interface, "ReadOnlyDirectories",           bus_property_append_strv,   "as",    (context).read_only_dirs                }, \
+        { interface, "InaccessibleDirectories",       bus_property_append_strv,   "as",    (context).inaccessible_dirs             }, \
+        { interface, "MountFlags",                    bus_property_append_ul,     "t",     &(context).mount_flags                  }, \
+        { interface, "PrivateTmp",                    bus_property_append_bool,   "b",     &(context).private_tmp                  }, \
+        { interface, "NoSetSID",                      bus_property_append_bool,   "b",     &(context).no_setsid                    }
 
 int bus_execute_append_output(Manager *m, DBusMessageIter *i, const char *property, void *data);
 int bus_execute_append_input(Manager *m, DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_oom_adjust(Manager *m, DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_nice(Manager *m, DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_ioprio(Manager *m, DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_cpu_sched_policy(Manager *m, DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_cpu_sched_priority(Manager *m, DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_affinity(Manager *m, DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_timer_slack_ns(Manager *m, DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_capabilities(Manager *m, DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_rlimits(Manager *m, DBusMessageIter *i, const char *property, void *data);
 
 #endif
index 3a6d79f..405ea46 100644 (file)
@@ -1473,6 +1473,22 @@ int bus_property_append_size(Manager *m, DBusMessageIter *i, const char *propert
         return 0;
 }
 
+int bus_property_append_ul(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+        uint64_t u;
+
+        assert(m);
+        assert(i);
+        assert(property);
+        assert(data);
+
+        u = (uint64_t) *(unsigned long*) data;
+
+        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
+                return -ENOMEM;
+
+        return 0;
+}
+
 int bus_parse_strv(DBusMessage *m, char ***_l) {
         DBusMessageIter iter, sub;
         unsigned n = 0, i = 0;
index 91132fd..ccee74f 100644 (file)
@@ -78,6 +78,7 @@ int bus_property_append_int32(Manager *m, DBusMessageIter *i, const char *proper
 int bus_property_append_uint32(Manager *m, DBusMessageIter *i, const char *property, void *data);
 int bus_property_append_uint64(Manager *m, DBusMessageIter *i, const char *property, void *data);
 int bus_property_append_size(Manager *m, DBusMessageIter *i, const char *property, void *data);
+int bus_property_append_ul(Manager *m, DBusMessageIter *i, const char *property, void *data);
 
 #define bus_property_append_int bus_property_append_int32
 #define bus_property_append_pid bus_property_append_uint32
index 9ded1c7..0bdd600 100644 (file)
@@ -1071,8 +1071,8 @@ int exec_spawn(ExecCommand *command,
                         }
                 }
 
-                if (context->cpu_affinity_set)
-                        if (sched_setaffinity(0, sizeof(context->cpu_affinity), &context->cpu_affinity) < 0) {
+                if (context->cpuset)
+                        if (sched_setaffinity(0, CPU_ALLOC_SIZE(context->cpuset_ncpus), context->cpuset) < 0) {
                                 r = EXIT_CPUAFFINITY;
                                 goto fail;
                         }
@@ -1350,6 +1350,9 @@ void exec_context_done(ExecContext *c) {
 
         strv_free(c->inaccessible_dirs);
         c->inaccessible_dirs = NULL;
+
+        if (c->cpuset)
+                CPU_FREE(c->cpuset);
 }
 
 void exec_command_done(ExecCommand *c) {
@@ -1458,10 +1461,10 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
                         prefix, c->cpu_sched_priority,
                         prefix, yes_no(c->cpu_sched_reset_on_fork));
 
-        if (c->cpu_affinity_set) {
+        if (c->cpuset) {
                 fprintf(f, "%sCPUAffinity:", prefix);
-                for (i = 0; i < CPU_SETSIZE; i++)
-                        if (CPU_ISSET(i, &c->cpu_affinity))
+                for (i = 0; i < c->cpuset_ncpus; i++)
+                        if (CPU_ISSET_S(i, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset))
                                 fprintf(f, " %i", i);
                 fputs("\n", f);
         }
index 841670a..9fb48e6 100644 (file)
@@ -93,7 +93,8 @@ struct ExecContext {
         int cpu_sched_policy;
         int cpu_sched_priority;
 
-        cpu_set_t cpu_affinity;
+        cpu_set_t *cpuset;
+        unsigned cpuset_ncpus;
         unsigned long timer_slack_ns;
 
         ExecInput std_input;
@@ -134,7 +135,6 @@ struct ExecContext {
         bool nice_set:1;
         bool ioprio_set:1;
         bool cpu_sched_set:1;
-        bool cpu_affinity_set:1;
         bool timer_slack_ns_set:1;
 
         /* This is not exposed to the user but available
@@ -142,7 +142,7 @@ struct ExecContext {
          * /bin/mount it is run in the same process group as us so
          * that the autofs logic detects that it belongs to us and we
          * don't enter a trigger loop. */
-        bool no_setsid:1;
+        bool no_setsid;
 };
 
 typedef enum ExitStatus {
index e5c7ba2..a5ea0e4 100644 (file)
@@ -725,19 +725,21 @@ static int config_parse_cpu_affinity(
                 if (!(t = strndup(w, l)))
                         return -ENOMEM;
 
+                if (!(c->cpuset))
+                        if (!(c->cpuset = cpu_set_malloc(&c->cpuset_ncpus)))
+                                return -ENOMEM;
+
                 r = safe_atou(t, &cpu);
                 free(t);
 
-                if (r < 0 || cpu >= CPU_SETSIZE) {
+                if (r < 0 || cpu >= c->cpuset_ncpus) {
                         log_error("[%s:%u] Failed to parse CPU affinity: %s", filename, line, rvalue);
                         return -EBADMSG;
                 }
 
-                CPU_SET(cpu, &c->cpu_affinity);
+                CPU_SET_S(cpu, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset);
         }
 
-        c->cpu_affinity_set = true;
-
         return 0;
 }
 
index 3b4cb9c..602d44a 100644 (file)
@@ -27,6 +27,7 @@
 #include <sys/resource.h>
 #include <sys/syscall.h>
 #include <fcntl.h>
+#include <unistd.h>
 
 #ifndef RLIMIT_RTTIME
 #define RLIMIT_RTTIME 15
index 66d6ef0..392ecf2 100644 (file)
@@ -1111,7 +1111,29 @@ static int print_property(const char *name, DBusMessageIter *iter) {
                         }
 
                         return 0;
+                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_BYTE) {
+                        DBusMessageIter sub;
+
+                        dbus_message_iter_recurse(iter, &sub);
+
+                        if (arg_all ||
+                            dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
+                                printf("%s=", name);
+
+                                while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
+                                        uint8_t u;
 
+                                        assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_BYTE);
+                                        dbus_message_iter_get_basic(&sub, &u);
+                                        printf("%02x", u);
+
+                                        dbus_message_iter_next(&sub);
+                                }
+
+                                puts("");
+                        }
+
+                        return 0;
                 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
                         DBusMessageIter sub, sub2;
 
index b66eb46..ea8bfc1 100644 (file)
@@ -2538,6 +2538,34 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
         return 0;
 }
 
+cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
+        cpu_set_t *r;
+        unsigned n = 1024;
+
+        /* Allocates the cpuset in the right size */
+
+        for (;;) {
+                if (!(r = CPU_ALLOC(n)))
+                        return NULL;
+
+                if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
+                        CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
+
+                        if (ncpus)
+                                *ncpus = n;
+
+                        return r;
+                }
+
+                CPU_FREE(r);
+
+                if (errno != EINVAL)
+                        return NULL;
+
+                n *= 2;
+        }
+}
+
 static const char *const ioprio_class_table[] = {
         [IOPRIO_CLASS_NONE] = "none",
         [IOPRIO_CLASS_RT] = "realtime",
index eda8e5c..50bac6e 100644 (file)
@@ -29,6 +29,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <signal.h>
+#include <sched.h>
 
 #include "macro.h"
 
@@ -284,6 +285,8 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
 
 int rm_rf(const char *path, bool only_dirs, bool delete_root);
 
+cpu_set_t* cpu_set_malloc(unsigned *ncpus);
+
 const char *ioprio_class_to_string(int i);
 int ioprio_class_from_string(const char *s);