Merge pull request #3109 from poettering/journal-by-fd
rework "journalctl -M"
This commit is contained in:
+15
-5
@@ -242,6 +242,7 @@ MANPAGES_ALIAS += \
|
||||
man/SD_JOURNAL_INVALIDATE.3 \
|
||||
man/SD_JOURNAL_LOCAL_ONLY.3 \
|
||||
man/SD_JOURNAL_NOP.3 \
|
||||
man/SD_JOURNAL_OS_ROOT.3 \
|
||||
man/SD_JOURNAL_RUNTIME_ONLY.3 \
|
||||
man/SD_JOURNAL_SUPPRESS_LOCATION.3 \
|
||||
man/SD_JOURNAL_SYSTEM.3 \
|
||||
@@ -388,9 +389,10 @@ MANPAGES_ALIAS += \
|
||||
man/sd_journal_get_timeout.3 \
|
||||
man/sd_journal_has_persistent_files.3 \
|
||||
man/sd_journal_next_skip.3 \
|
||||
man/sd_journal_open_container.3 \
|
||||
man/sd_journal_open_directory.3 \
|
||||
man/sd_journal_open_directory_fd.3 \
|
||||
man/sd_journal_open_files.3 \
|
||||
man/sd_journal_open_files_fd.3 \
|
||||
man/sd_journal_perror.3 \
|
||||
man/sd_journal_previous.3 \
|
||||
man/sd_journal_previous_skip.3 \
|
||||
@@ -571,6 +573,7 @@ man/SD_JOURNAL_FOREACH_UNIQUE.3: man/sd_journal_query_unique.3
|
||||
man/SD_JOURNAL_INVALIDATE.3: man/sd_journal_get_fd.3
|
||||
man/SD_JOURNAL_LOCAL_ONLY.3: man/sd_journal_open.3
|
||||
man/SD_JOURNAL_NOP.3: man/sd_journal_get_fd.3
|
||||
man/SD_JOURNAL_OS_ROOT.3: man/sd_journal_open.3
|
||||
man/SD_JOURNAL_RUNTIME_ONLY.3: man/sd_journal_open.3
|
||||
man/SD_JOURNAL_SUPPRESS_LOCATION.3: man/sd_journal_print.3
|
||||
man/SD_JOURNAL_SYSTEM.3: man/sd_journal_open.3
|
||||
@@ -717,9 +720,10 @@ man/sd_journal_get_monotonic_usec.3: man/sd_journal_get_realtime_usec.3
|
||||
man/sd_journal_get_timeout.3: man/sd_journal_get_fd.3
|
||||
man/sd_journal_has_persistent_files.3: man/sd_journal_has_runtime_files.3
|
||||
man/sd_journal_next_skip.3: man/sd_journal_next.3
|
||||
man/sd_journal_open_container.3: man/sd_journal_open.3
|
||||
man/sd_journal_open_directory.3: man/sd_journal_open.3
|
||||
man/sd_journal_open_directory_fd.3: man/sd_journal_open.3
|
||||
man/sd_journal_open_files.3: man/sd_journal_open.3
|
||||
man/sd_journal_open_files_fd.3: man/sd_journal_open.3
|
||||
man/sd_journal_perror.3: man/sd_journal_print.3
|
||||
man/sd_journal_previous.3: man/sd_journal_next.3
|
||||
man/sd_journal_previous_skip.3: man/sd_journal_next.3
|
||||
@@ -1034,6 +1038,9 @@ man/SD_JOURNAL_LOCAL_ONLY.html: man/sd_journal_open.html
|
||||
man/SD_JOURNAL_NOP.html: man/sd_journal_get_fd.html
|
||||
$(html-alias)
|
||||
|
||||
man/SD_JOURNAL_OS_ROOT.html: man/sd_journal_open.html
|
||||
$(html-alias)
|
||||
|
||||
man/SD_JOURNAL_RUNTIME_ONLY.html: man/sd_journal_open.html
|
||||
$(html-alias)
|
||||
|
||||
@@ -1472,15 +1479,18 @@ man/sd_journal_has_persistent_files.html: man/sd_journal_has_runtime_files.html
|
||||
man/sd_journal_next_skip.html: man/sd_journal_next.html
|
||||
$(html-alias)
|
||||
|
||||
man/sd_journal_open_container.html: man/sd_journal_open.html
|
||||
$(html-alias)
|
||||
|
||||
man/sd_journal_open_directory.html: man/sd_journal_open.html
|
||||
$(html-alias)
|
||||
|
||||
man/sd_journal_open_directory_fd.html: man/sd_journal_open.html
|
||||
$(html-alias)
|
||||
|
||||
man/sd_journal_open_files.html: man/sd_journal_open.html
|
||||
$(html-alias)
|
||||
|
||||
man/sd_journal_open_files_fd.html: man/sd_journal_open.html
|
||||
$(html-alias)
|
||||
|
||||
man/sd_journal_perror.html: man/sd_journal_print.html
|
||||
$(html-alias)
|
||||
|
||||
|
||||
+33
-44
@@ -45,14 +45,16 @@
|
||||
<refnamediv>
|
||||
<refname>sd_journal_open</refname>
|
||||
<refname>sd_journal_open_directory</refname>
|
||||
<refname>sd_journal_open_directory_fd</refname>
|
||||
<refname>sd_journal_open_files</refname>
|
||||
<refname>sd_journal_open_container</refname>
|
||||
<refname>sd_journal_open_files_fd</refname>
|
||||
<refname>sd_journal_close</refname>
|
||||
<refname>sd_journal</refname>
|
||||
<refname>SD_JOURNAL_LOCAL_ONLY</refname>
|
||||
<refname>SD_JOURNAL_RUNTIME_ONLY</refname>
|
||||
<refname>SD_JOURNAL_SYSTEM</refname>
|
||||
<refname>SD_JOURNAL_CURRENT_USER</refname>
|
||||
<refname>SD_JOURNAL_OS_ROOT</refname>
|
||||
<refpurpose>Open the system journal for reading</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
@@ -73,6 +75,13 @@
|
||||
<paramdef>int <parameter>flags</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_journal_open_directory_fd</function></funcdef>
|
||||
<paramdef>sd_journal **<parameter>ret</parameter></paramdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>flags</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_journal_open_files</function></funcdef>
|
||||
<paramdef>sd_journal **<parameter>ret</parameter></paramdef>
|
||||
@@ -81,9 +90,10 @@
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_journal_open_container</function></funcdef>
|
||||
<funcdef>int <function>sd_journal_open_files_fd</function></funcdef>
|
||||
<paramdef>sd_journal **<parameter>ret</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>machine</parameter></paramdef>
|
||||
<paramdef>int <parameter>fds[]</parameter></paramdef>
|
||||
<paramdef>unsigned <parameter>n_fds</parameter></paramdef>
|
||||
<paramdef>int <parameter>flags</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
@@ -117,29 +127,28 @@
|
||||
<constant>SD_JOURNAL_CURRENT_USER</constant> are specified, all
|
||||
journal file types will be opened.</para>
|
||||
|
||||
<para><function>sd_journal_open_directory()</function> is similar
|
||||
to <function>sd_journal_open()</function> but takes an absolute
|
||||
directory path as argument. All journal files in this directory
|
||||
will be opened and interleaved automatically. This call also takes
|
||||
a flags argument, but it must be passed as 0 as no flags are
|
||||
currently understood for this call.</para>
|
||||
<para><function>sd_journal_open_directory()</function> is similar to <function>sd_journal_open()</function> but
|
||||
takes an absolute directory path as argument. All journal files in this directory will be opened and interleaved
|
||||
automatically. This call also takes a flags argument. The only flags parameter accepted by this call is
|
||||
<constant>SD_JOURNAL_OS_ROOT</constant>. If specified, the journal files are searched below the usual
|
||||
<filename>/var/log/journal</filename> and <filename>/run/log/journal</filename> relative to the specified path,
|
||||
instead of directly beneath it.</para>
|
||||
|
||||
<para><function>sd_journal_open_files()</function> is similar to
|
||||
<function>sd_journal_open()</function> but takes a
|
||||
<constant>NULL</constant>-terminated list of file paths to open.
|
||||
All files will be opened and interleaved automatically. This call
|
||||
also takes a flags argument, but it must be passed as 0 as no
|
||||
flags are currently understood for this call. Please note that in
|
||||
the case of a live journal, this function is only useful for
|
||||
debugging, because individual journal files can be rotated at any
|
||||
moment, and the opening of specific files is inherently
|
||||
racy.</para>
|
||||
<para><function>sd_journal_open_directory_fd()</function> is similar to
|
||||
<function>sd_journal_open_directory()</function>, but takes a file descriptor referencing a directory in the file
|
||||
system instead of an absolute file system path.</para>
|
||||
|
||||
<para><function>sd_journal_open_container()</function> is similar
|
||||
to <function>sd_journal_open()</function> but opens the journal
|
||||
files of a running OS container. The specified machine name refers
|
||||
to a container that is registered with
|
||||
<citerefentry><refentrytitle>systemd-machined</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||
<para><function>sd_journal_open_files()</function> is similar to <function>sd_journal_open()</function> but takes a
|
||||
<constant>NULL</constant>-terminated list of file paths to open. All files will be opened and interleaved
|
||||
automatically. This call also takes a flags argument, but it must be passed as 0 as no flags are currently
|
||||
understood for this call. Please note that in the case of a live journal, this function is only useful for
|
||||
debugging, because individual journal files can be rotated at any moment, and the opening of specific files is
|
||||
inherently racy.</para>
|
||||
|
||||
<para><function>sd_journal_open_files_fd()</function> is similar to <function>sd_journal_open_files()</function>
|
||||
but takes an array of open file descriptors that must reference journal files, instead of an array of file system
|
||||
paths. Pass the array of file descriptors as second argument, and the number of array entries in the third. The
|
||||
flags parameter must be passed as 0.</para>
|
||||
|
||||
<para><varname>sd_journal</varname> objects cannot be used in the
|
||||
child after a fork. Functions which take a journal object as an
|
||||
@@ -204,26 +213,6 @@
|
||||
file.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>History</title>
|
||||
|
||||
<para><function>sd_journal_open()</function>,
|
||||
<function>sd_journal_close()</function>,
|
||||
<constant>SD_JOURNAL_LOCAL_ONLY</constant>,
|
||||
<constant>SD_JOURNAL_RUNTIME_ONLY</constant>,
|
||||
<constant>SD_JOURNAL_SYSTEM_ONLY</constant> were added in
|
||||
systemd-38.</para>
|
||||
|
||||
<para><function>sd_journal_open_directory()</function> was added
|
||||
in systemd-187.</para>
|
||||
|
||||
<para><constant>SD_JOURNAL_SYSTEM</constant>,
|
||||
<constant>SD_JOURNAL_CURRENT_USER</constant>, and
|
||||
<function>sd_journal_open_files()</function> were added in
|
||||
systemd-205. <constant>SD_JOURNAL_SYSTEM_ONLY</constant> was
|
||||
deprecated.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
|
||||
|
||||
@@ -217,19 +217,6 @@
|
||||
entry.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>History</title>
|
||||
|
||||
<para><function>sd_uid_get_state()</function>,
|
||||
<function>sd_uid_is_on_seat()</function>,
|
||||
<function>sd_uid_get_sessions()</function>, and
|
||||
<function>sd_uid_get_seats()</function> functions were added in
|
||||
systemd-31.</para>
|
||||
|
||||
<para><function>sd_uid_get_display()</function> was added in
|
||||
systemd-213.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
|
||||
|
||||
@@ -154,18 +154,6 @@
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>History</title>
|
||||
|
||||
<para>The watchdog functionality and the
|
||||
<varname>$WATCHDOG_USEC</varname> variable were added in
|
||||
systemd-41.</para>
|
||||
|
||||
<para><function>sd_watchdog_enabled()</function> function was
|
||||
added in systemd-209. Since that version, the
|
||||
<varname>$WATCHDOG_PID</varname> variable is also set.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para>
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "mkdir.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "time-util.h"
|
||||
@@ -493,3 +494,17 @@ int get_files_in_directory(const char *path, char ***list) {
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
|
||||
char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
|
||||
int r;
|
||||
|
||||
/* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
|
||||
xsprintf(path, "/proc/self/fd/%i", what);
|
||||
|
||||
r = inotify_add_watch(fd, path, mask);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -72,3 +72,5 @@ union inotify_event_buffer {
|
||||
struct inotify_event ev;
|
||||
uint8_t raw[INOTIFY_EVENT_MAX];
|
||||
};
|
||||
|
||||
int inotify_add_watch_fd(int fd, int what, uint32_t mask);
|
||||
|
||||
+35
-15
@@ -37,6 +37,7 @@
|
||||
#include "journal-file.h"
|
||||
#include "lookup3.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "random-util.h"
|
||||
#include "sd-event.h"
|
||||
#include "set.h"
|
||||
@@ -364,7 +365,8 @@ JournalFile* journal_file_close(JournalFile *f) {
|
||||
(void) btrfs_defrag_fd(f->fd);
|
||||
}
|
||||
|
||||
safe_close(f->fd);
|
||||
if (f->close_fd)
|
||||
safe_close(f->fd);
|
||||
free(f->path);
|
||||
|
||||
mmap_cache_unref(f->mmap);
|
||||
@@ -2468,8 +2470,7 @@ int journal_file_next_entry(
|
||||
|
||||
if (p > 0 &&
|
||||
(direction == DIRECTION_DOWN ? ofs <= p : ofs >= p)) {
|
||||
log_debug("%s: entry array corrupted at entry %"PRIu64,
|
||||
f->path, i);
|
||||
log_debug("%s: entry array corrupted at entry %"PRIu64, f->path, i);
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
@@ -2900,6 +2901,7 @@ static int journal_file_warn_btrfs(JournalFile *f) {
|
||||
}
|
||||
|
||||
int journal_file_open(
|
||||
int fd,
|
||||
const char *fname,
|
||||
int flags,
|
||||
mode_t mode,
|
||||
@@ -2916,22 +2918,24 @@ int journal_file_open(
|
||||
void *h;
|
||||
int r;
|
||||
|
||||
assert(fname);
|
||||
assert(ret);
|
||||
assert(fd >= 0 || fname);
|
||||
|
||||
if ((flags & O_ACCMODE) != O_RDONLY &&
|
||||
(flags & O_ACCMODE) != O_RDWR)
|
||||
return -EINVAL;
|
||||
|
||||
if (!endswith(fname, ".journal") &&
|
||||
!endswith(fname, ".journal~"))
|
||||
return -EINVAL;
|
||||
if (fname) {
|
||||
if (!endswith(fname, ".journal") &&
|
||||
!endswith(fname, ".journal~"))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
f = new0(JournalFile, 1);
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
f->fd = -1;
|
||||
f->fd = fd;
|
||||
f->mode = mode;
|
||||
|
||||
f->flags = flags;
|
||||
@@ -2956,7 +2960,10 @@ int journal_file_open(
|
||||
}
|
||||
}
|
||||
|
||||
f->path = strdup(fname);
|
||||
if (fname)
|
||||
f->path = strdup(fname);
|
||||
else /* If we don't know the path, fill in something explanatory and vaguely useful */
|
||||
asprintf(&f->path, "/proc/self/%i", fd);
|
||||
if (!f->path) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
@@ -2968,10 +2975,15 @@ int journal_file_open(
|
||||
goto fail;
|
||||
}
|
||||
|
||||
f->fd = open(f->path, f->flags|O_CLOEXEC, f->mode);
|
||||
if (f->fd < 0) {
|
||||
r = -errno;
|
||||
goto fail;
|
||||
f->fd = open(f->path, f->flags|O_CLOEXEC, f->mode);
|
||||
if (f->fd < 0) {
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* fds we opened here by us should also be closed by us. */
|
||||
f->close_fd = true;
|
||||
}
|
||||
|
||||
r = journal_file_fstat(f);
|
||||
@@ -3092,6 +3104,9 @@ int journal_file_open(
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* The file is opened now successfully, thus we take possesion of any passed in fd. */
|
||||
f->close_fd = true;
|
||||
|
||||
*ret = f;
|
||||
return 0;
|
||||
|
||||
@@ -3118,6 +3133,11 @@ int journal_file_rotate(JournalFile **f, bool compress, bool seal, Set *deferred
|
||||
if (!old_file->writable)
|
||||
return -EINVAL;
|
||||
|
||||
/* Is this a journal file that was passed to us as fd? If so, we synthesized a path name for it, and we refuse
|
||||
* rotation, since we don't know the actual path, and couldn't rename the file hence.*/
|
||||
if (path_startswith(old_file->path, "/proc/self/fd"))
|
||||
return -EINVAL;
|
||||
|
||||
if (!endswith(old_file->path, ".journal"))
|
||||
return -EINVAL;
|
||||
|
||||
@@ -3144,7 +3164,7 @@ int journal_file_rotate(JournalFile **f, bool compress, bool seal, Set *deferred
|
||||
* we archive them */
|
||||
old_file->defrag_on_close = true;
|
||||
|
||||
r = journal_file_open(old_file->path, old_file->flags, old_file->mode, compress, seal, NULL, old_file->mmap, deferred_closes, old_file, &new_file);
|
||||
r = journal_file_open(-1, old_file->path, old_file->flags, old_file->mode, compress, seal, NULL, old_file->mmap, deferred_closes, old_file, &new_file);
|
||||
|
||||
if (deferred_closes &&
|
||||
set_put(deferred_closes, old_file) >= 0)
|
||||
@@ -3172,7 +3192,7 @@ int journal_file_open_reliably(
|
||||
size_t l;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
|
||||
r = journal_file_open(fname, flags, mode, compress, seal, metrics, mmap_cache, deferred_closes, template, ret);
|
||||
r = journal_file_open(-1, fname, flags, mode, compress, seal, metrics, mmap_cache, deferred_closes, template, ret);
|
||||
if (!IN_SET(r,
|
||||
-EBADMSG, /* corrupted */
|
||||
-ENODATA, /* truncated */
|
||||
@@ -3213,7 +3233,7 @@ int journal_file_open_reliably(
|
||||
|
||||
log_warning_errno(r, "File %s corrupted or uncleanly shut down, renaming and replacing.", fname);
|
||||
|
||||
return journal_file_open(fname, flags, mode, compress, seal, metrics, mmap_cache, deferred_closes, template, ret);
|
||||
return journal_file_open(-1, fname, flags, mode, compress, seal, metrics, mmap_cache, deferred_closes, template, ret);
|
||||
}
|
||||
|
||||
int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset) {
|
||||
|
||||
@@ -85,6 +85,7 @@ typedef struct JournalFile {
|
||||
bool compress_lz4:1;
|
||||
bool seal:1;
|
||||
bool defrag_on_close:1;
|
||||
bool close_fd:1;
|
||||
|
||||
bool tail_entry_monotonic_valid:1;
|
||||
|
||||
@@ -142,6 +143,7 @@ typedef struct JournalFile {
|
||||
} JournalFile;
|
||||
|
||||
int journal_file_open(
|
||||
int fd,
|
||||
const char *fname,
|
||||
int flags,
|
||||
mode_t mode,
|
||||
|
||||
@@ -82,6 +82,8 @@ struct Directory {
|
||||
};
|
||||
|
||||
struct sd_journal {
|
||||
int toplevel_fd;
|
||||
|
||||
char *path;
|
||||
char *prefix;
|
||||
|
||||
@@ -117,6 +119,7 @@ struct sd_journal {
|
||||
|
||||
bool on_network:1;
|
||||
bool no_new_files:1;
|
||||
bool no_inotify:1;
|
||||
bool unique_file_lost:1; /* File we were iterating over got
|
||||
removed, and there were no more
|
||||
files, so sd_j_enumerate_unique
|
||||
|
||||
@@ -101,6 +101,7 @@ static const char *arg_after_cursor = NULL;
|
||||
static bool arg_show_cursor = false;
|
||||
static const char *arg_directory = NULL;
|
||||
static char **arg_file = NULL;
|
||||
static bool arg_file_stdin = false;
|
||||
static int arg_priorities = 0xFF;
|
||||
static const char *arg_verify_key = NULL;
|
||||
#ifdef HAVE_GCRYPT
|
||||
@@ -592,9 +593,17 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_FILE:
|
||||
r = glob_extend(&arg_file, optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add paths: %m");
|
||||
if (streq(optarg, "-"))
|
||||
/* An undocumented feature: we can read journal files from STDIN. We don't document
|
||||
* this though, since after all we only support this for mmap-able, seekable files, and
|
||||
* not for example pipes which are probably the primary usecase for reading things from
|
||||
* STDIN. To avoid confusion we hence don't document this feature. */
|
||||
arg_file_stdin = true;
|
||||
else {
|
||||
r = glob_extend(&arg_file, optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add paths: %m");
|
||||
}
|
||||
break;
|
||||
|
||||
case ARG_ROOT:
|
||||
@@ -864,6 +873,18 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!strv_isempty(arg_system_units) && (arg_journal_type == SD_JOURNAL_CURRENT_USER)) {
|
||||
|
||||
/* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
|
||||
* journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
|
||||
* to users, and automatically turn --unit= into --user-unit= if combined with --user. */
|
||||
r = strv_extend_strv(&arg_user_units, arg_system_units, true);
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
arg_system_units = strv_free(arg_system_units);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1869,7 +1890,7 @@ static int access_check(sd_journal *j) {
|
||||
break;
|
||||
|
||||
default:
|
||||
log_warning_errno(err, "An error was encountered while opening journal file %s, ignoring file.", path);
|
||||
log_warning_errno(err, "An error was encountered while opening journal file or directory %s, ignoring file: %m", path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2125,11 +2146,61 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
if (arg_directory)
|
||||
r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
|
||||
else if (arg_file)
|
||||
else if (arg_file_stdin) {
|
||||
int ifd = STDIN_FILENO;
|
||||
r = sd_journal_open_files_fd(&j, &ifd, 1, 0);
|
||||
} else if (arg_file)
|
||||
r = sd_journal_open_files(&j, (const char**) arg_file, 0);
|
||||
else if (arg_machine)
|
||||
r = sd_journal_open_container(&j, arg_machine, 0);
|
||||
else
|
||||
else if (arg_machine) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
int fd;
|
||||
|
||||
if (geteuid() != 0) {
|
||||
/* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of
|
||||
* the container, thus we need root privileges to override them. */
|
||||
log_error("Using the --machine= switch requires root privileges.");
|
||||
r = -EPERM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_bus_open_system(&bus);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to open system bus: %m");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
"org.freedesktop.machine1",
|
||||
"/org/freedesktop/machine1",
|
||||
"org.freedesktop.machine1.Manager",
|
||||
"OpenMachineRootDirectory",
|
||||
&error,
|
||||
&reply,
|
||||
"s", arg_machine);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to open root directory: %s", bus_error_message(&error, r));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_bus_message_read(reply, "h", &fd);
|
||||
if (r < 0) {
|
||||
bus_log_parse_error(r);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
|
||||
if (fd < 0) {
|
||||
r = log_error_errno(errno, "Failed to duplicate file descriptor: %m");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_journal_open_directory_fd(&j, fd, SD_JOURNAL_OS_ROOT);
|
||||
if (r < 0)
|
||||
safe_close(fd);
|
||||
} else
|
||||
r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to open %s: %m", arg_directory ?: arg_file ? "files" : "journal");
|
||||
@@ -2305,6 +2376,10 @@ int main(int argc, char *argv[]) {
|
||||
/* Opening the fd now means the first sd_journal_wait() will actually wait */
|
||||
if (arg_follow) {
|
||||
r = sd_journal_get_fd(j);
|
||||
if (r == -EMEDIUMTYPE) {
|
||||
log_error_errno(r, "The --follow switch is not supported in conjunction with reading from STDIN.");
|
||||
goto finish;
|
||||
}
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to get journal fd: %m");
|
||||
goto finish;
|
||||
|
||||
@@ -253,7 +253,7 @@ static int open_journal(
|
||||
if (reliably)
|
||||
r = journal_file_open_reliably(fname, flags, 0640, s->compress, seal, metrics, s->mmap, s->deferred_closes, NULL, &f);
|
||||
else
|
||||
r = journal_file_open(fname, flags, 0640, s->compress, seal, metrics, s->mmap, s->deferred_closes, NULL, &f);
|
||||
r = journal_file_open(-1, fname, flags, 0640, s->compress, seal, metrics, s->mmap, s->deferred_closes, NULL, &f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
+239
-55
@@ -1233,14 +1233,37 @@ static bool file_type_wanted(int flags, const char *filename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static int add_any_file(sd_journal *j, const char *path) {
|
||||
static bool path_has_prefix(sd_journal *j, const char *path, const char *prefix) {
|
||||
assert(j);
|
||||
assert(path);
|
||||
assert(prefix);
|
||||
|
||||
if (j->toplevel_fd >= 0)
|
||||
return false;
|
||||
|
||||
return path_startswith(path, prefix);
|
||||
}
|
||||
|
||||
static const char *skip_slash(const char *p) {
|
||||
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
while (*p == '/')
|
||||
p++;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static int add_any_file(sd_journal *j, int fd, const char *path) {
|
||||
JournalFile *f = NULL;
|
||||
bool close_fd = false;
|
||||
int r, k;
|
||||
|
||||
assert(j);
|
||||
assert(path);
|
||||
assert(fd >= 0 || path);
|
||||
|
||||
if (ordered_hashmap_get(j->files, path))
|
||||
if (path && ordered_hashmap_get(j->files, path))
|
||||
return 0;
|
||||
|
||||
if (ordered_hashmap_size(j->files) >= JOURNAL_FILES_MAX) {
|
||||
@@ -1249,8 +1272,24 @@ static int add_any_file(sd_journal *j, const char *path) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, NULL, &f);
|
||||
if (fd < 0 && j->toplevel_fd >= 0) {
|
||||
|
||||
/* If there's a top-level fd defined, open the file relative to this now. (Make the path relative,
|
||||
* explicitly, since otherwise openat() ignores the first argument.) */
|
||||
|
||||
fd = openat(j->toplevel_fd, skip_slash(path), O_RDONLY|O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
r = log_debug_errno(errno, "Failed to open journal file %s: %m", path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
close_fd = true;
|
||||
}
|
||||
|
||||
r = journal_file_open(fd, path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, NULL, &f);
|
||||
if (r < 0) {
|
||||
if (close_fd)
|
||||
safe_close(fd);
|
||||
log_debug_errno(r, "Failed to open journal file %s: %m", path);
|
||||
goto fail;
|
||||
}
|
||||
@@ -1259,10 +1298,16 @@ static int add_any_file(sd_journal *j, const char *path) {
|
||||
|
||||
r = ordered_hashmap_put(j->files, f->path, f);
|
||||
if (r < 0) {
|
||||
f->close_fd = close_fd;
|
||||
(void) journal_file_close(f);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!j->has_runtime_files && path_has_prefix(j, f->path, "/run"))
|
||||
j->has_runtime_files = true;
|
||||
else if (!j->has_persistent_files && path_has_prefix(j, f->path, "/var"))
|
||||
j->has_persistent_files = true;
|
||||
|
||||
log_debug("File %s added.", f->path);
|
||||
|
||||
check_network(j, f->fd);
|
||||
@@ -1286,18 +1331,14 @@ static int add_file(sd_journal *j, const char *prefix, const char *filename) {
|
||||
assert(prefix);
|
||||
assert(filename);
|
||||
|
||||
if (j->no_new_files ||
|
||||
!file_type_wanted(j->flags, filename))
|
||||
if (j->no_new_files)
|
||||
return 0;
|
||||
|
||||
if (!file_type_wanted(j->flags, filename))
|
||||
return 0;
|
||||
|
||||
path = strjoina(prefix, "/", filename);
|
||||
|
||||
if (!j->has_runtime_files && path_startswith(path, "/run/log/journal"))
|
||||
j->has_runtime_files = true;
|
||||
else if (!j->has_persistent_files && path_startswith(path, "/var/log/journal"))
|
||||
j->has_persistent_files = true;
|
||||
|
||||
return add_any_file(j, path);
|
||||
return add_any_file(j, -1, path);
|
||||
}
|
||||
|
||||
static void remove_file(sd_journal *j, const char *prefix, const char *filename) {
|
||||
@@ -1373,21 +1414,33 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
|
||||
|
||||
assert(j);
|
||||
assert(prefix);
|
||||
assert(dirname);
|
||||
|
||||
log_debug("Considering %s/%s.", prefix, dirname);
|
||||
/* Adds a journal file directory to watch. If the directory is already tracked this updates the inotify watch
|
||||
* and reenumerates directory contents */
|
||||
|
||||
if ((j->flags & SD_JOURNAL_LOCAL_ONLY) &&
|
||||
!(dirname_is_machine_id(dirname) > 0 || path_startswith(prefix, "/run")))
|
||||
return 0;
|
||||
|
||||
path = strjoin(prefix, "/", dirname, NULL);
|
||||
if (dirname)
|
||||
path = strjoin(prefix, "/", dirname, NULL);
|
||||
else
|
||||
path = strdup(prefix);
|
||||
if (!path) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
d = opendir(path);
|
||||
log_debug("Considering directory %s.", path);
|
||||
|
||||
/* We consider everything local that is in a directory for the local machine ID, or that is stored in /run */
|
||||
if ((j->flags & SD_JOURNAL_LOCAL_ONLY) &&
|
||||
!((dirname && dirname_is_machine_id(dirname) > 0) || path_has_prefix(j, path, "/run")))
|
||||
return 0;
|
||||
|
||||
|
||||
if (j->toplevel_fd < 0)
|
||||
d = opendir(path);
|
||||
else
|
||||
/* Open the specified directory relative to the the toplevel fd. Enforce that the path specified is
|
||||
* relative, by dropping the initial slash */
|
||||
d = xopendirat(j->toplevel_fd, skip_slash(path), 0);
|
||||
if (!d) {
|
||||
r = log_debug_errno(errno, "Failed to open directory %s: %m", path);
|
||||
goto fail;
|
||||
@@ -1419,17 +1472,18 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
|
||||
return 0;
|
||||
|
||||
if (m->wd <= 0 && j->inotify_fd >= 0) {
|
||||
/* Watch this directory, if it not being watched yet. */
|
||||
|
||||
m->wd = inotify_add_watch(j->inotify_fd, m->path,
|
||||
IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
|
||||
IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT|IN_MOVED_FROM|
|
||||
IN_ONLYDIR);
|
||||
m->wd = inotify_add_watch_fd(j->inotify_fd, dirfd(d),
|
||||
IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
|
||||
IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT|IN_MOVED_FROM|
|
||||
IN_ONLYDIR);
|
||||
|
||||
if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0)
|
||||
inotify_rm_watch(j->inotify_fd, m->wd);
|
||||
}
|
||||
|
||||
FOREACH_DIRENT_ALL(de, d, return log_debug_errno(errno, "Failed to read directory %s: %m", m->path)) {
|
||||
FOREACH_DIRENT_ALL(de, d, r = log_debug_errno(errno, "Failed to read directory %s: %m", m->path); goto fail) {
|
||||
|
||||
if (dirent_is_file_with_suffix(de, ".journal") ||
|
||||
dirent_is_file_with_suffix(de, ".journal~"))
|
||||
@@ -1441,7 +1495,7 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
k = journal_put_error(j, r, path ?: dirname);
|
||||
k = journal_put_error(j, r, path ?: prefix);
|
||||
if (k < 0)
|
||||
return k;
|
||||
|
||||
@@ -1449,28 +1503,62 @@ fail:
|
||||
}
|
||||
|
||||
static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
|
||||
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
struct dirent *de;
|
||||
Directory *m;
|
||||
int r, k;
|
||||
|
||||
assert(j);
|
||||
assert(p);
|
||||
|
||||
if ((j->flags & SD_JOURNAL_RUNTIME_ONLY) &&
|
||||
!path_startswith(p, "/run"))
|
||||
return -EINVAL;
|
||||
/* Adds a root directory to our set of directories to use. If the root directory is already in the set, we
|
||||
* update the inotify logic, and renumerate the directory entries. This call may hence be called to initially
|
||||
* populate the set, as well as to update it later. */
|
||||
|
||||
if (j->prefix)
|
||||
p = strjoina(j->prefix, p);
|
||||
if (p) {
|
||||
/* If there's a path specified, use it. */
|
||||
|
||||
d = opendir(p);
|
||||
if (!d) {
|
||||
if (errno == ENOENT && missing_ok)
|
||||
return 0;
|
||||
if ((j->flags & SD_JOURNAL_RUNTIME_ONLY) &&
|
||||
!path_has_prefix(j, p, "/run"))
|
||||
return -EINVAL;
|
||||
|
||||
r = log_debug_errno(errno, "Failed to open root directory %s: %m", p);
|
||||
goto fail;
|
||||
if (j->prefix)
|
||||
p = strjoina(j->prefix, p);
|
||||
|
||||
if (j->toplevel_fd < 0)
|
||||
d = opendir(p);
|
||||
else
|
||||
d = xopendirat(j->toplevel_fd, skip_slash(p), 0);
|
||||
|
||||
if (!d) {
|
||||
if (errno == ENOENT && missing_ok)
|
||||
return 0;
|
||||
|
||||
r = log_debug_errno(errno, "Failed to open root directory %s: %m", p);
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
int dfd;
|
||||
|
||||
/* If there's no path specified, then we use the top-level fd itself. We duplicate the fd here, since
|
||||
* opendir() will take possession of the fd, and close it, which we don't want. */
|
||||
|
||||
p = "."; /* store this as "." in the directories hashmap */
|
||||
|
||||
dfd = fcntl(j->toplevel_fd, F_DUPFD_CLOEXEC, 3);
|
||||
if (dfd < 0) {
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
d = fdopendir(dfd);
|
||||
if (!d) {
|
||||
r = -errno;
|
||||
safe_close(dfd);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rewinddir(d);
|
||||
}
|
||||
|
||||
m = hashmap_get(j->directories_by_path, p);
|
||||
@@ -1482,6 +1570,7 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
|
||||
}
|
||||
|
||||
m->is_root = true;
|
||||
|
||||
m->path = strdup(p);
|
||||
if (!m->path) {
|
||||
free(m);
|
||||
@@ -1505,7 +1594,7 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
|
||||
|
||||
if (m->wd <= 0 && j->inotify_fd >= 0) {
|
||||
|
||||
m->wd = inotify_add_watch(j->inotify_fd, m->path,
|
||||
m->wd = inotify_add_watch_fd(j->inotify_fd, dirfd(d),
|
||||
IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
|
||||
IN_ONLYDIR);
|
||||
|
||||
@@ -1516,7 +1605,7 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
|
||||
if (j->no_new_files)
|
||||
return 0;
|
||||
|
||||
FOREACH_DIRENT_ALL(de, d, return log_debug_errno(errno, "Failed to read directory %s: %m", m->path)) {
|
||||
FOREACH_DIRENT_ALL(de, d, r = log_debug_errno(errno, "Failed to read directory %s: %m", m->path); goto fail) {
|
||||
sd_id128_t id;
|
||||
|
||||
if (dirent_is_file_with_suffix(de, ".journal") ||
|
||||
@@ -1585,8 +1674,7 @@ static int add_current_paths(sd_journal *j) {
|
||||
assert(j);
|
||||
assert(j->no_new_files);
|
||||
|
||||
/* Simply adds all directories for files we have open as
|
||||
* "root" directories. We don't expect errors here, so we
|
||||
/* Simply adds all directories for files we have open as directories. We don't expect errors here, so we
|
||||
* treat them as fatal. */
|
||||
|
||||
ORDERED_HASHMAP_FOREACH(f, j->files, i) {
|
||||
@@ -1597,7 +1685,7 @@ static int add_current_paths(sd_journal *j) {
|
||||
if (!dir)
|
||||
return -ENOMEM;
|
||||
|
||||
r = add_root_directory(j, dir, true);
|
||||
r = add_directory(j, dir, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@@ -1614,13 +1702,7 @@ static int allocate_inotify(sd_journal *j) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (!j->directories_by_wd) {
|
||||
j->directories_by_wd = hashmap_new(NULL);
|
||||
if (!j->directories_by_wd)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return hashmap_ensure_allocated(&j->directories_by_wd, NULL);
|
||||
}
|
||||
|
||||
static sd_journal *journal_new(int flags, const char *path) {
|
||||
@@ -1631,6 +1713,7 @@ static sd_journal *journal_new(int flags, const char *path) {
|
||||
return NULL;
|
||||
|
||||
j->original_pid = getpid();
|
||||
j->toplevel_fd = -1;
|
||||
j->inotify_fd = -1;
|
||||
j->flags = flags;
|
||||
j->data_threshold = DEFAULT_DATA_THRESHOLD;
|
||||
@@ -1684,6 +1767,9 @@ _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, in
|
||||
char *p;
|
||||
int r;
|
||||
|
||||
/* This is pretty much deprecated, people should use machined's OpenMachineRootDirectory() call instead in
|
||||
* combination with sd_journal_open_directory_fd(). */
|
||||
|
||||
assert_return(machine, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM)) == 0, -EINVAL);
|
||||
@@ -1726,13 +1812,16 @@ _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int f
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
assert_return(path, -EINVAL);
|
||||
assert_return(flags == 0, -EINVAL);
|
||||
assert_return((flags & ~SD_JOURNAL_OS_ROOT) == 0, -EINVAL);
|
||||
|
||||
j = journal_new(flags, path);
|
||||
if (!j)
|
||||
return -ENOMEM;
|
||||
|
||||
r = add_root_directory(j, path, false);
|
||||
if (flags & SD_JOURNAL_OS_ROOT)
|
||||
r = add_search_paths(j);
|
||||
else
|
||||
r = add_root_directory(j, path, false);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
@@ -1741,7 +1830,6 @@ _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int f
|
||||
|
||||
fail:
|
||||
sd_journal_close(j);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1758,7 +1846,7 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla
|
||||
return -ENOMEM;
|
||||
|
||||
STRV_FOREACH(path, paths) {
|
||||
r = add_any_file(j, *path);
|
||||
r = add_any_file(j, -1, *path);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
@@ -1770,7 +1858,96 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla
|
||||
|
||||
fail:
|
||||
sd_journal_close(j);
|
||||
return r;
|
||||
}
|
||||
|
||||
_public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
|
||||
sd_journal *j;
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
assert_return(fd >= 0, -EBADF);
|
||||
assert_return((flags & ~SD_JOURNAL_OS_ROOT) == 0, -EINVAL);
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
return -EBADFD;
|
||||
|
||||
j = journal_new(flags, NULL);
|
||||
if (!j)
|
||||
return -ENOMEM;
|
||||
|
||||
j->toplevel_fd = fd;
|
||||
|
||||
if (flags & SD_JOURNAL_OS_ROOT)
|
||||
r = add_search_paths(j);
|
||||
else
|
||||
r = add_root_directory(j, NULL, false);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
*ret = j;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
sd_journal_close(j);
|
||||
return r;
|
||||
}
|
||||
|
||||
_public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fds, int flags) {
|
||||
Iterator iterator;
|
||||
JournalFile *f;
|
||||
sd_journal *j;
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
assert_return(n_fds > 0, -EBADF);
|
||||
assert_return(flags == 0, -EINVAL);
|
||||
|
||||
j = journal_new(flags, NULL);
|
||||
if (!j)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < n_fds; i++) {
|
||||
struct stat st;
|
||||
|
||||
if (fds[i] < 0) {
|
||||
r = -EBADF;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (fstat(fds[i], &st) < 0) {
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
r = -EBADFD;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = add_any_file(j, fds[i], NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
j->no_new_files = true;
|
||||
j->no_inotify = true;
|
||||
|
||||
*ret = j;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
/* If we fail, make sure we don't take possession of the files we managed to make use of successfuly, and they
|
||||
* remain open */
|
||||
ORDERED_HASHMAP_FOREACH(f, j->files, iterator)
|
||||
f->close_fd = false;
|
||||
|
||||
sd_journal_close(j);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -2097,6 +2274,9 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
|
||||
assert_return(j, -EINVAL);
|
||||
assert_return(!journal_pid_changed(j), -ECHILD);
|
||||
|
||||
if (j->no_inotify)
|
||||
return -EMEDIUMTYPE;
|
||||
|
||||
if (j->inotify_fd >= 0)
|
||||
return j->inotify_fd;
|
||||
|
||||
@@ -2104,10 +2284,14 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_debug("Reiterating files to get inotify watches established");
|
||||
|
||||
/* Iterate through all dirs again, to add them to the
|
||||
* inotify */
|
||||
if (j->no_new_files)
|
||||
r = add_current_paths(j);
|
||||
else if (j->toplevel_fd >= 0)
|
||||
r = add_root_directory(j, NULL, false);
|
||||
else if (j->path)
|
||||
r = add_root_directory(j, j->path, true);
|
||||
else
|
||||
|
||||
@@ -38,7 +38,7 @@ int main(int argc, char *argv[]) {
|
||||
assert_se(mkdtemp(dn));
|
||||
fn = strappend(dn, "/test.journal");
|
||||
|
||||
r = journal_file_open(fn, O_CREAT|O_RDWR, 0644, false, false, NULL, NULL, NULL, NULL, &new_journal);
|
||||
r = journal_file_open(-1, fn, O_CREAT|O_RDWR, 0644, false, false, NULL, NULL, NULL, NULL, &new_journal);
|
||||
assert_se(r >= 0);
|
||||
|
||||
r = sd_journal_open(&j, 0);
|
||||
|
||||
@@ -52,7 +52,7 @@ noreturn static void log_assert_errno(const char *text, int eno, const char *fil
|
||||
|
||||
static JournalFile *test_open(const char *name) {
|
||||
JournalFile *f;
|
||||
assert_ret(journal_file_open(name, O_RDWR|O_CREAT, 0644, true, false, NULL, NULL, NULL, NULL, &f));
|
||||
assert_ret(journal_file_open(-1, name, O_RDWR|O_CREAT, 0644, true, false, NULL, NULL, NULL, NULL, &f));
|
||||
return f;
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ static void test_sequence_numbers(void) {
|
||||
assert_se(mkdtemp(t));
|
||||
assert_se(chdir(t) >= 0);
|
||||
|
||||
assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0644,
|
||||
assert_se(journal_file_open(-1, "one.journal", O_RDWR|O_CREAT, 0644,
|
||||
true, false, NULL, NULL, NULL, NULL, &one) == 0);
|
||||
|
||||
append_number(one, 1, &seqnum);
|
||||
@@ -233,7 +233,7 @@ static void test_sequence_numbers(void) {
|
||||
|
||||
memcpy(&seqnum_id, &one->header->seqnum_id, sizeof(sd_id128_t));
|
||||
|
||||
assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0644,
|
||||
assert_se(journal_file_open(-1, "two.journal", O_RDWR|O_CREAT, 0644,
|
||||
true, false, NULL, NULL, NULL, one, &two) == 0);
|
||||
|
||||
assert_se(two->header->state == STATE_ONLINE);
|
||||
@@ -264,7 +264,7 @@ static void test_sequence_numbers(void) {
|
||||
/* restart server */
|
||||
seqnum = 0;
|
||||
|
||||
assert_se(journal_file_open("two.journal", O_RDWR, 0,
|
||||
assert_se(journal_file_open(-1, "two.journal", O_RDWR, 0,
|
||||
true, false, NULL, NULL, NULL, NULL, &two) == 0);
|
||||
|
||||
assert_se(sd_id128_equal(two->header->seqnum_id, seqnum_id));
|
||||
|
||||
@@ -92,9 +92,9 @@ int main(int argc, char *argv[]) {
|
||||
assert_se(mkdtemp(t));
|
||||
assert_se(chdir(t) >= 0);
|
||||
|
||||
assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, NULL, &one) == 0);
|
||||
assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, NULL, &two) == 0);
|
||||
assert_se(journal_file_open("three.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, NULL, &three) == 0);
|
||||
assert_se(journal_file_open(-1, "one.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, NULL, &one) == 0);
|
||||
assert_se(journal_file_open(-1, "two.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, NULL, &two) == 0);
|
||||
assert_se(journal_file_open(-1, "three.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, NULL, &three) == 0);
|
||||
|
||||
for (i = 0; i < N_ENTRIES; i++) {
|
||||
char *p, *q;
|
||||
|
||||
@@ -55,7 +55,7 @@ static int raw_verify(const char *fn, const char *verification_key) {
|
||||
JournalFile *f;
|
||||
int r;
|
||||
|
||||
r = journal_file_open(fn, O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, NULL, &f);
|
||||
r = journal_file_open(-1, fn, O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, NULL, &f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -88,7 +88,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
log_info("Generating...");
|
||||
|
||||
assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, !!verification_key, NULL, NULL, NULL, NULL, &f) == 0);
|
||||
assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, true, !!verification_key, NULL, NULL, NULL, NULL, &f) == 0);
|
||||
|
||||
for (n = 0; n < N_ENTRIES; n++) {
|
||||
struct iovec iovec;
|
||||
@@ -111,7 +111,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
log_info("Verifying...");
|
||||
|
||||
assert_se(journal_file_open("test.journal", O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, NULL, &f) == 0);
|
||||
assert_se(journal_file_open(-1, "test.journal", O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, NULL, &f) == 0);
|
||||
/* journal_file_print_header(f); */
|
||||
journal_file_dump(f);
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ static void test_non_empty(void) {
|
||||
assert_se(mkdtemp(t));
|
||||
assert_se(chdir(t) >= 0);
|
||||
|
||||
assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, NULL, &f) == 0);
|
||||
assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, NULL, &f) == 0);
|
||||
|
||||
dual_timestamp_get(&ts);
|
||||
|
||||
@@ -131,13 +131,13 @@ static void test_empty(void) {
|
||||
assert_se(mkdtemp(t));
|
||||
assert_se(chdir(t) >= 0);
|
||||
|
||||
assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, false, false, NULL, NULL, NULL, NULL, &f1) == 0);
|
||||
assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, false, false, NULL, NULL, NULL, NULL, &f1) == 0);
|
||||
|
||||
assert_se(journal_file_open("test-compress.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, NULL, &f2) == 0);
|
||||
assert_se(journal_file_open(-1, "test-compress.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, NULL, &f2) == 0);
|
||||
|
||||
assert_se(journal_file_open("test-seal.journal", O_RDWR|O_CREAT, 0666, false, true, NULL, NULL, NULL, NULL, &f3) == 0);
|
||||
assert_se(journal_file_open(-1, "test-seal.journal", O_RDWR|O_CREAT, 0666, false, true, NULL, NULL, NULL, NULL, &f3) == 0);
|
||||
|
||||
assert_se(journal_file_open("test-seal-compress.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, NULL, &f4) == 0);
|
||||
assert_se(journal_file_open(-1, "test-seal-compress.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, NULL, &f4) == 0);
|
||||
|
||||
journal_file_print_header(f1);
|
||||
puts("");
|
||||
|
||||
@@ -489,3 +489,9 @@ global:
|
||||
sd_journal_enumerate_fields;
|
||||
sd_journal_restart_fields;
|
||||
} LIBSYSTEMD_227;
|
||||
|
||||
LIBSYSTEMD_230 {
|
||||
global:
|
||||
sd_journal_open_directory_fd;
|
||||
sd_journal_open_files_fd;
|
||||
} LIBSYSTEMD_229;
|
||||
|
||||
@@ -1274,6 +1274,97 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bus_machine_method_open_root_directory(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
_cleanup_close_ int fd = -1;
|
||||
Machine *m = userdata;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
CAP_SYS_ADMIN,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
NULL,
|
||||
false,
|
||||
UID_INVALID,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
|
||||
switch (m->class) {
|
||||
|
||||
case MACHINE_HOST:
|
||||
fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
break;
|
||||
|
||||
case MACHINE_CONTAINER: {
|
||||
_cleanup_close_ int mntns_fd = -1, root_fd = -1;
|
||||
_cleanup_close_pair_ int pair[2] = { -1, -1 };
|
||||
siginfo_t si;
|
||||
pid_t child;
|
||||
|
||||
r = namespace_open(m->leader, NULL, &mntns_fd, NULL, NULL, &root_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
|
||||
return -errno;
|
||||
|
||||
child = fork();
|
||||
if (child < 0)
|
||||
return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
|
||||
|
||||
if (child == 0) {
|
||||
_cleanup_close_ int dfd = -1;
|
||||
|
||||
pair[0] = safe_close(pair[0]);
|
||||
|
||||
r = namespace_enter(-1, mntns_fd, -1, -1, root_fd);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
dfd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
|
||||
if (dfd < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
r = send_one_fd(pair[1], dfd, 0);
|
||||
dfd = safe_close(dfd);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
pair[1] = safe_close(pair[1]);
|
||||
|
||||
r = wait_for_terminate(child, &si);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
|
||||
if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
|
||||
|
||||
fd = receive_one_fd(pair[0], MSG_DONTWAIT);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Opening the root directory is only supported on container machines.");
|
||||
}
|
||||
|
||||
return sd_bus_reply_method_return(message, "h", fd);
|
||||
}
|
||||
|
||||
const sd_bus_vtable machine_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Machine, name), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@@ -1297,6 +1388,7 @@ const sd_bus_vtable machine_vtable[] = {
|
||||
SD_BUS_METHOD("BindMount", "ssbb", NULL, bus_machine_method_bind_mount, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("CopyFrom", "ss", NULL, bus_machine_method_copy, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("CopyTo", "ss", NULL, bus_machine_method_copy, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("OpenRootDirectory", NULL, "h", bus_machine_method_open_root_directory, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bu
|
||||
int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int bus_machine_method_open_root_directory(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
|
||||
int machine_send_signal(Machine *m, bool new_machine);
|
||||
int machine_send_create_reply(Machine *m, sd_bus_error *error);
|
||||
|
||||
@@ -706,6 +706,26 @@ static int method_copy_machine(sd_bus_message *message, void *userdata, sd_bus_e
|
||||
return bus_machine_method_copy(message, machine, error);
|
||||
}
|
||||
|
||||
static int method_open_machine_root_directory(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
Manager *m = userdata;
|
||||
Machine *machine;
|
||||
const char *name;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = sd_bus_message_read(message, "s", &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
machine = hashmap_get(m->machines, name);
|
||||
if (!machine)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
|
||||
|
||||
return bus_machine_method_open_root_directory(message, machine, error);
|
||||
}
|
||||
|
||||
static int method_remove_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
_cleanup_(image_unrefp) Image* i = NULL;
|
||||
const char *name;
|
||||
@@ -1225,6 +1245,7 @@ const sd_bus_vtable manager_vtable[] = {
|
||||
SD_BUS_METHOD("BindMountMachine", "sssbb", NULL, method_bind_mount_machine, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("CopyFromMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("CopyToMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("OpenMachineRootDirectory", "s", "h", method_open_machine_root_directory, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("RemoveImage", "s", NULL, method_remove_image, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("RenameImage", "ss", NULL, method_rename_image, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("CloneImage", "ssb", NULL, method_clone_image, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
|
||||
@@ -67,10 +67,11 @@ typedef struct sd_journal sd_journal;
|
||||
|
||||
/* Open flags */
|
||||
enum {
|
||||
SD_JOURNAL_LOCAL_ONLY = 1,
|
||||
SD_JOURNAL_RUNTIME_ONLY = 2,
|
||||
SD_JOURNAL_SYSTEM = 4,
|
||||
SD_JOURNAL_CURRENT_USER = 8,
|
||||
SD_JOURNAL_LOCAL_ONLY = 1 << 0,
|
||||
SD_JOURNAL_RUNTIME_ONLY = 1 << 1,
|
||||
SD_JOURNAL_SYSTEM = 1 << 2,
|
||||
SD_JOURNAL_CURRENT_USER = 1 << 3,
|
||||
SD_JOURNAL_OS_ROOT = 1 << 4,
|
||||
|
||||
SD_JOURNAL_SYSTEM_ONLY = SD_JOURNAL_SYSTEM /* deprecated name */
|
||||
};
|
||||
@@ -84,8 +85,10 @@ enum {
|
||||
|
||||
int sd_journal_open(sd_journal **ret, int flags);
|
||||
int sd_journal_open_directory(sd_journal **ret, const char *path, int flags);
|
||||
int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags);
|
||||
int sd_journal_open_files(sd_journal **ret, const char **paths, int flags);
|
||||
int sd_journal_open_container(sd_journal **ret, const char *machine, int flags);
|
||||
int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fds, int flags);
|
||||
int sd_journal_open_container(sd_journal **ret, const char *machine, int flags); /* deprecated */
|
||||
void sd_journal_close(sd_journal *j);
|
||||
|
||||
int sd_journal_previous(sd_journal *j);
|
||||
|
||||
Reference in New Issue
Block a user