#include <keyutils.h>'''],
['copy_file_range', '''#include <sys/syscall.h>
#include <unistd.h>'''],
+ ['bpf', '''#include <sys/syscall.h>
+ #include <unistd.h>'''],
['explicit_bzero' , '''#include <string.h>'''],
]
#if 0 /// UNNEEDED by elogind
# libmount = dependency('mount',
-# version : '>= 2.27')
+# version : '>= 2.30')
#
# want_seccomp = get_option('seccomp')
# if want_seccomp != 'false'
# install_rpath : rootlibexecdir,
# install : true,
# install_dir : rootlibexecdir)
-# endif
#
# exe = executable('networkctl',
-# networkctl_sources,
-# include_directories : includes,
-# link_with : [libsystemd_network,
+# networkctl_sources,
+# include_directories : includes,
+# link_with : [libsystemd_network,
# libshared],
-# install_rpath : rootlibexecdir,
-# install : true,
-# install_dir : rootbindir)
-# public_programs += [exe]
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootbindir)
+# public_programs += [exe]
+# endif
#endif // 0
############################################################
int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
_cleanup_fclose_ FILE *f = NULL;
char line[LINE_MAX];
- const char *fs, *controller_str = NULL;
+ const char *fs, *controller_str;
size_t cs = 0;
int unified;
#if 0 /// UNNEEDED by elogind
int cg_kernel_controllers(Set *controllers) {
_cleanup_fclose_ FILE *f = NULL;
+ char buf[LINE_MAX];
int r;
assert(controllers);
}
/* Ignore the header line */
- (void) read_line(f, (size_t) -1, NULL);
+ (void) fgets(buf, sizeof(buf), f);
for (;;) {
char *controller;
"/usr/local/lib/" n "\0" \
"/usr/lib/" n "\0" \
_CONF_PATHS_SPLIT_USR(n)
-
-#define LONG_LINE_MAX (1U*1024U*1024U)
#include "alloc-util.h"
#include "ctype.h"
-#include "def.h"
+#include "env-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
int read_one_line_file(const char *fn, char **line) {
_cleanup_fclose_ FILE *f = NULL;
- int r;
+ char t[LINE_MAX], *c;
assert(fn);
assert(line);
if (!f)
return -errno;
- r = read_line(f, LONG_LINE_MAX, line);
- return r < 0 ? r : 0;
+ if (!fgets(t, sizeof(t), f)) {
+
+ if (ferror(f))
+ return errno > 0 ? -errno : -EIO;
+
+ t[0] = 0;
+ }
+
+ c = strdup(t);
+ if (!c)
+ return -ENOMEM;
+ truncate_nl(c);
+
+ *line = c;
+ return 0;
}
int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
return 0;
}
#endif // 0
-
-static inline void funlockfilep(FILE **f) {
- funlockfile(*f);
-}
-
-int read_line(FILE *f, size_t limit, char **ret) {
- _cleanup_free_ char *buffer = NULL;
- size_t n = 0, allocated = 0, count = 0;
-
- assert(f);
-
- /* Something like a bounded version of getline().
- *
- * Considers EOF, \n and \0 end of line delimiters, and does not include these delimiters in the string
- * returned.
- *
- * Returns the number of bytes read from the files (i.e. including delimiters — this hence usually differs from
- * the number of characters in the returned string). When EOF is hit, 0 is returned.
- *
- * The input parameter limit is the maximum numbers of characters in the returned string, i.e. excluding
- * delimiters. If the limit is hit we fail and return -ENOBUFS.
- *
- * If a line shall be skipped ret may be initialized as NULL. */
-
- if (ret) {
- if (!GREEDY_REALLOC(buffer, allocated, 1))
- return -ENOMEM;
- }
-
- {
- _cleanup_(funlockfilep) FILE *flocked = f;
- flockfile(f);
-
- for (;;) {
- int c;
-
- if (n >= limit)
- return -ENOBUFS;
-
- errno = 0;
- c = fgetc_unlocked(f);
- if (c == EOF) {
- /* if we read an error, and have no data to return, then propagate the error */
- if (ferror_unlocked(f) && n == 0)
- return errno > 0 ? -errno : -EIO;
-
- break;
- }
-
- count++;
-
- if (IN_SET(c, '\n', 0)) /* Reached a delimiter */
- break;
-
- if (ret) {
- if (!GREEDY_REALLOC(buffer, allocated, n + 2))
- return -ENOMEM;
-
- buffer[n] = (char) c;
- }
-
- n++;
- }
- }
-
- if (ret) {
- buffer[n] = 0;
-
- *ret = buffer;
- buffer = NULL;
- }
-
- return (int) count;
-}
int mkdtemp_malloc(const char *template, char **ret);
#endif // 0
-
-int read_line(FILE *f, size_t limit, char **ret);
#include "mkdir.h"
#include "parse-util.h"
#include "path-util.h"
-#include "process-util.h"
#include "stat-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
//#include "time-util.h"
#if 0 /// elogind has a shorter list
# basic_sources_plain = files('''
+# MurmurHash2.c
+# MurmurHash2.h
# af-list.c
# af-list.h
# alloc-util.c
# bitmap.c
# bitmap.h
# blkid-util.h
+# bpf-program.c
+# bpf-program.h
# btrfs-ctree.h
# btrfs-util.c
# btrfs-util.h
# bus-label.h
# calendarspec.c
# calendarspec.h
-# capability-util.c
-# capability-util.h
# cap-list.c
# cap-list.h
+# capability-util.c
+# capability-util.h
# cgroup-util.c
# cgroup-util.h
# chattr-util.c
# extract-word.h
# fd-util.c
# fd-util.h
-# fileio.c
-# fileio.h
# fileio-label.c
# fileio-label.h
+# fileio.c
+# fileio.h
# format-util.h
# fs-util.c
# fs-util.h
# hostname-util.h
# in-addr-util.c
# in-addr-util.h
-# ioprio.h
# io-util.c
# io-util.h
+# ioprio.h
# journal-importer.c
# journal-importer.h
# khash.c
# mempool.c
# mempool.h
# missing_syscall.h
+# mkdir-label.c
# mkdir.c
# mkdir.h
-# mkdir-label.c
# mount-util.c
# mount-util.h
-# MurmurHash2.c
-# MurmurHash2.h
# nss-util.h
# ordered-set.c
# ordered-set.h
# rlimit-util.h
# rm-rf.c
# rm-rf.h
-# securebits.h
# securebits-util.c
# securebits-util.h
+# securebits.h
# selinux-util.c
# selinux-util.h
# set.h
/* Missing glibc definitions to access certain kernel APIs */
#if 0 /// UNNEEDED by elogind
+#include <sys/types.h>
+
#if !HAVE_DECL_PIVOT_ROOT
static inline int pivot_root(const char *new_root, const char *put_old) {
return syscall(SYS_pivot_root, new_root, put_old);
# endif
}
#endif
+
+#if !HAVE_DECL_BPF
+# ifndef __NR_bpf
+# if defined __i386__
+# define __NR_bpf 357
+# elif defined __x86_64__
+# define __NR_bpf 321
+# elif defined __aarch64__
+# define __NR_bpf 280
+# elif defined __sparc__
+# define __NR_bpf 349
+# elif defined __s390__
+# define __NR_bpf 351
+# else
+# warning "__NR_bpf not defined for your architecture"
+# endif
+# endif
+
+union bpf_attr;
+
+static inline int bpf(int cmd, union bpf_attr *attr, size_t size) {
+#ifdef __NR_bpf
+ return (int) syscall(__NR_bpf, cmd, attr, size);
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+#endif
#include "log.h"
#include "macro.h"
#include "parse-util.h"
-#include "path-util.h"
#include "process-util.h"
#include "socket-util.h"
#include "stat-util.h"
}
from_tm:
- if (weekday >= 0 && tm.tm_wday != weekday)
- return -EINVAL;
-
x = mktime_or_timegm(&tm, utc);
if (x < 0)
return -EINVAL;
+ if (weekday >= 0 && tm.tm_wday != weekday)
+ return -EINVAL;
+
ret = (usec_t) x * USEC_PER_SEC + x_usec;
if (ret > USEC_TIMESTAMP_FORMATTABLE_MAX)
return -EINVAL;
} ParseTimestampResult;
int parse_timestamp(const char *t, usec_t *usec) {
- char *last_space, *tz = NULL;
+ char *last_space, *timezone = NULL;
ParseTimestampResult *shared, tmp;
int r;
pid_t pid;
last_space = strrchr(t, ' ');
if (last_space != NULL && timezone_is_valid(last_space + 1))
- tz = last_space + 1;
+ timezone = last_space + 1;
- if (tz == NULL || endswith_no_case(t, " UTC"))
+ if (timezone == NULL || endswith_no_case(t, " UTC"))
return parse_timestamp_impl(t, usec, false);
+ t = strndupa(t, last_space - t);
+
shared = mmap(NULL, sizeof *shared, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
if (shared == MAP_FAILED)
return negative_errno();
}
if (pid == 0) {
- bool with_tz = true;
-
- if (setenv("TZ", tz, 1) != 0) {
+ if (setenv("TZ", timezone, 1) != 0) {
shared->return_value = negative_errno();
_exit(EXIT_FAILURE);
}
tzset();
- /* If there is a timezone that matches the tzname fields, leave the parsing to the implementation.
- * Otherwise just cut it off */
- with_tz = !STR_IN_SET(tz, tzname[0], tzname[1]);
-
- /*cut off the timezone if we dont need it*/
- if (with_tz)
- t = strndupa(t, last_space - t);
-
- shared->return_value = parse_timestamp_impl(t, &shared->usec, with_tz);
+ shared->return_value = parse_timestamp_impl(t, &shared->usec, true);
_exit(EXIT_SUCCESS);
}
#include "macro.h"
#include "missing.h"
#include "parse-util.h"
-#include "process-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
#include "fs-util.h"
#include "parse-util.h"
#include "path-util.h"
-#include "process-util.h"
#include "socket-util.h"
#include "strv.h"
#include "util.h"
#include "fd-util.h"
#include "log.h"
#include "macro.h"
-#include "process-util.h"
#include "signal-util.h"
#include "util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "escape.h"
-#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
#if 1 /// elogind needs an Add-On for sleep configuration
elogind_manager_reset_config(m);
#endif // 1
-
return 0;
}
#if 1 /// elogind needs some extra preparations before connecting...
elogind_manager_startup(m);
#endif // 1
-
/* Connect to console */
r = manager_connect_console(m);
if (r < 0)
#if 1 /// elogind needs an Add-On for sleep configuration
elogind_manager_reset_config(m);
#endif // 1
-
r = manager_startup(m);
if (r < 0) {
log_error_errno(r, "Failed to fully start up daemon: %m");
goto finish;
}
- log_debug("elogind running as pid "PID_FMT, getpid());
+ log_debug("elogind running as pid "PID_FMT, getpid_cached());
sd_notify(false,
"READY=1\n"
#include "alloc-util.h"
#include "conf-files.h"
#include "conf-parser.h"
-#include "def.h"
#include "extract-word.h"
#include "fd-util.h"
-#include "fileio.h"
#include "fs-util.h"
#include "log.h"
#include "macro.h"
fd_warn_permissions(filename, fileno(f));
for (;;) {
- _cleanup_free_ char *buf = NULL;
- char *l, *p, *c = NULL, *e;
+ char buf[LINE_MAX], *l, *p, *c = NULL, *e;
bool escaped = false;
- r = read_line(f, LONG_LINE_MAX, &buf);
- if (r == 0)
- break;
- if (r == -ENOBUFS) {
- if (warn)
- log_error_errno(r, "%s:%u: Line too long", filename, line);
+ if (!fgets(buf, sizeof buf, f)) {
+ if (feof(f))
+ break;
- return r;
- }
- if (r < 0) {
- if (warn)
- log_error_errno(r, "%s:%u: Error while reading configuration file: %m", filename, line);
-
- return r;
+ return log_error_errno(errno, "Failed to read configuration file '%s': %m", filename);
}
l = buf;
- if (allow_bom) {
- char *q;
+ if (allow_bom && startswith(l, UTF8_BYTE_ORDER_MARK))
+ l += strlen(UTF8_BYTE_ORDER_MARK);
+ allow_bom = false;
- q = startswith(buf, UTF8_BYTE_ORDER_MARK);
- if (q) {
- l = q;
- allow_bom = false;
- }
- }
+ truncate_nl(l);
if (continuation) {
- if (strlen(continuation) + strlen(l) > LONG_LINE_MAX) {
- if (warn)
- log_error("%s:%u: Continuation line too long", filename, line);
- return -ENOBUFS;
- }
-
c = strappend(continuation, l);
if (!c) {
if (warn)
if (r < 0) {
if (warn)
- log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line);
+ log_warning_errno(r, "Failed to parse file '%s': %m",
+ filename);
return r;
}
}
assert(rvalue);
assert(data);
+ if (isempty(rvalue)) {
+ n = NULL;
+ goto finalize;
+ }
+
if (!utf8_is_valid(rvalue)) {
log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
return fatal ? -ENOEXEC : 0;
path_kill_slashes(n);
+finalize:
free(*s);
*s = n;
#include <string.h>
-#include "alloc-util.h"
#include "fileio.h"
#include "log.h"
#include "string-util.h"
STRV_FOREACH(state, states) {
int k;
- k = write_string_stream(*f, *state, 0);
+ k = write_string_stream(*f, *state, true);
if (k == 0)
return 0;
log_debug_errno(k, "Failed to write '%s' to /sys/power/state: %m",
# [],
# []],
#
-# [['src/test/test-barrier.c'],
+# [['src/test/test-in-addr-util.c'],
# [],
# []],
#
-# [['src/test/test-in-addr-util.c'],
+# [['src/test/test-barrier.c'],
# [],
# []],
#
#include "cgroup-util.h"
#include "path-util.h"
-#include "process-util.h"
#include "string-util.h"
#include "util.h"
***/
#include "conf-parser.h"
-#include "fd-util.h"
-#include "fileio.h"
#include "log.h"
#include "macro.h"
#include "string-util.h"
#include "util.h"
static void test_config_parse_path_one(const char *rvalue, const char *expected) {
- _cleanup_free_ char *path = NULL;
+ char *path = NULL;
assert_se(config_parse_path("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &path, NULL) >= 0);
assert_se(streq_ptr(expected, path));
+
+ free(path);
}
static void test_config_parse_log_level_one(const char *rvalue, int expected) {
}
static void test_config_parse_strv_one(const char *rvalue, char **expected) {
- _cleanup_strv_free_ char **strv = NULL;
+ char **strv = 0;
assert_se(config_parse_strv("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &strv, NULL) >= 0);
assert_se(strv_equal(expected, strv));
+
+ strv_free(strv);
}
static void test_config_parse_mode_one(const char *rvalue, mode_t expected) {
}
#endif // 0
-#define x10(x) x x x x x x x x x x
-#define x100(x) x10(x10(x))
-#define x1000(x) x10(x100(x))
-
-static const char* const config_file[] = {
- "[Section]\n"
- "setting1=1\n",
-
- "[Section]\n"
- "setting1=1", /* no terminating newline */
-
- "\n\n\n\n[Section]\n\n\n"
- "setting1=1", /* some whitespace, no terminating newline */
-
- "[Section]\n"
- "[Section]\n"
- "setting1=1\n"
- "setting1=2\n"
- "setting1=1\n", /* repeated settings */
-
- "[Section]\n"
- "setting1=1\\\n" /* normal continuation */
- "2\\\n"
- "3\n",
-
- "[Section]\n"
- "setting1=1\\\\\\\n" /* continuation with trailing escape symbols */
- "\\\\2\n", /* note that C requires one level of escaping, so the
- * parser gets "…1 BS BS BS NL BS BS 2 NL", which
- * it translates into "…1 BS BS SP BS BS 2" */
-
- "\n[Section]\n\n"
- "setting1=" /* a line above LINE_MAX length */
- x1000("ABCD")
- "\n",
-
- "[Section]\n"
- "setting1=" /* a line above LINE_MAX length, with continuation */
- x1000("ABCD") "\\\n"
- "foobar",
-
- "[Section]\n"
- "setting1=" /* a line above the allowed limit: 9 + 1050000 + 1 */
- x1000(x1000("x") x10("abcde")) "\n",
-
- "[Section]\n"
- "setting1=" /* many continuation lines, together above the limit */
- x1000(x1000("x") x10("abcde") "\\\n") "xxx",
-};
-
-static void test_config_parse(unsigned i, const char *s) {
- char name[] = "/tmp/test-conf-parser.XXXXXX";
- int fd, r;
- _cleanup_fclose_ FILE *f = NULL;
- _cleanup_free_ char *setting1 = NULL;
-
- const ConfigTableItem items[] = {
- { "Section", "setting1", config_parse_string, 0, &setting1},
- {}
- };
-
- log_info("== %s[%i] ==", __func__, i);
-
- fd = mkostemp_safe(name);
- assert_se(fd >= 0);
- assert_se((size_t) write(fd, s, strlen(s)) == strlen(s));
-
- assert_se(lseek(fd, 0, SEEK_SET) == 0);
- assert_se(f = fdopen(fd, "r"));
-
- /*
- int config_parse(const char *unit,
- const char *filename,
- FILE *f,
- const char *sections,
- ConfigItemLookup lookup,
- const void *table,
- bool relaxed,
- bool allow_include,
- bool warn,
- void *userdata)
- */
-
- r = config_parse(NULL, name, f,
- "Section\0",
- config_item_table_lookup, items,
- false, false, true, NULL);
-
- switch (i) {
- case 0 ... 3:
- assert_se(r == 0);
- assert_se(streq(setting1, "1"));
- break;
-
- case 4:
- assert_se(r == 0);
- assert_se(streq(setting1, "1 2 3"));
- break;
-
- case 5:
- assert_se(r == 0);
- assert_se(streq(setting1, "1\\\\ \\\\2"));
- break;
-
- case 6:
- assert_se(r == 0);
- assert_se(streq(setting1, x1000("ABCD")));
- break;
-
- case 7:
- assert_se(r == 0);
- assert_se(streq(setting1, x1000("ABCD") " foobar"));
- break;
-
- case 8 ... 9:
- assert_se(r == -ENOBUFS);
- assert_se(setting1 == NULL);
- break;
- }
-}
-
int main(int argc, char **argv) {
- unsigned i;
-
log_parse_environment();
log_open();
test_config_parse_iec_uint64();
#endif // 0
- for (i = 0; i < ELEMENTSOF(config_file); i++)
- test_config_parse(i, config_file[i]);
-
return 0;
}
#include "format-util.h"
#include "log.h"
-#include "process-util.h"
#include "util.h"
assert_cc(LOG_REALM_REMOVE_LEVEL(LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, LOG_FTP | LOG_DEBUG))
#include <unistd.h>
#include "macro.h"
-#include "process-util.h"
#include "signal-util.h"
static void test_block_signals(void) {