[systemd-devel] [PATCH 6/7] journal: Open JournalFile by dirfd and filename instead of path
Krzesimir Nowak
krzesimir at endocode.com
Mon Jun 1 08:29:02 PDT 2015
That way we can have access to a file that is not accessible by path,
for example to a file in overlayfs in different mount namespace (which
is the case for rkt pods).
---
src/journal-remote/journal-remote-write.c | 12 +-
src/journal-remote/journal-remote.c | 34 ++--
src/journal/journal-file.c | 108 +++++-----
src/journal/journal-file.h | 10 +-
src/journal/journal-internal.h | 3 +-
src/journal/journal-vacuum.c | 27 +--
src/journal/journal-vacuum.h | 3 +-
src/journal/journal-verify.c | 4 +-
src/journal/journalctl.c | 8 +-
src/journal/journald-server.c | 113 +++++++----
src/journal/sd-journal.c | 324 ++++++++++++++++++++----------
src/journal/test-journal-flush.c | 13 +-
src/journal/test-journal-interleaving.c | 55 +++--
src/journal/test-journal-stream.c | 10 +-
src/journal/test-journal-verify.c | 13 +-
src/journal/test-journal.c | 21 +-
src/shared/util.c | 20 ++
src/shared/util.h | 1 +
18 files changed, 515 insertions(+), 264 deletions(-)
diff --git a/src/journal-remote/journal-remote-write.c b/src/journal-remote/journal-remote-write.c
index 99820fa..0fdeb7f 100644
--- a/src/journal-remote/journal-remote-write.c
+++ b/src/journal-remote/journal-remote-write.c
@@ -59,7 +59,7 @@ static int do_rotate(JournalFile **f, bool compress, bool seal) {
int r = journal_file_rotate(f, compress, seal);
if (r < 0) {
if (*f)
- log_error_errno(r, "Failed to rotate %s: %m", (*f)->path);
+ log_error_errno(r, "Failed to rotate %s/%s: %m", (*f)->directory->path, (*f)->filename);
else
log_error_errno(r, "Failed to create rotated journal: %m");
}
@@ -93,7 +93,7 @@ Writer* writer_free(Writer *w) {
return NULL;
if (w->journal) {
- log_debug("Closing journal file %s.", w->journal->path);
+ log_debug("Closing journal file %s/%s.", w->journal->directory->path, w->journal->filename);
journal_file_close(w->journal);
}
@@ -136,8 +136,8 @@ int writer_write(Writer *w,
assert(iovw->count > 0);
if (journal_file_rotate_suggested(w->journal, 0)) {
- log_info("%s: Journal header limits reached or header out-of-date, rotating",
- w->journal->path);
+ log_info("%s/%s: Journal header limits reached or header out-of-date, rotating",
+ w->journal->directory->path, w->journal->filename);
r = do_rotate(&w->journal, compress, seal);
if (r < 0)
return r;
@@ -151,12 +151,12 @@ int writer_write(Writer *w,
return 1;
}
- log_debug_errno(r, "%s: Write failed, rotating: %m", w->journal->path);
+ log_debug_errno(r, "%s/%s: Write failed, rotating: %m", w->journal->directory->path, w->journal->filename);
r = do_rotate(&w->journal, compress, seal);
if (r < 0)
return r;
else
- log_debug("%s: Successfully rotated journal", w->journal->path);
+ log_debug("%s/%s: Successfully rotated journal", w->journal->directory->path, w->journal->filename);
log_debug("Retrying write.");
r = journal_file_append_entry(w->journal, ts, iovw->iovec, iovw->count,
diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
index 911e2a1..1a4c337 100644
--- a/src/journal-remote/journal-remote.c
+++ b/src/journal-remote/journal-remote.c
@@ -162,14 +162,20 @@ static int spawn_getter(const char *getter, const char *url) {
#define filename_escape(s) xescape((s), "/ ")
static int open_output(Writer *w, const char* host) {
- _cleanup_free_ char *_output = NULL;
- const char *output;
+ _cleanup_free_ char *directory = NULL;
+ _cleanup_free_ char *filename = NULL;
+ JournalDirectory *dir;
int r;
switch (arg_split_mode) {
- case JOURNAL_WRITE_SPLIT_NONE:
+ case JOURNAL_WRITE_SPLIT_NONE: {
+ const char *output;
+
output = arg_output ?: REMOTE_JOURNAL_PATH "/remote.journal";
+ directory = dirname_malloc(output);
+ filename = basename_malloc(output);
break;
+ }
case JOURNAL_WRITE_SPLIT_HOST: {
_cleanup_free_ char *name;
@@ -180,13 +186,10 @@ static int open_output(Writer *w, const char* host) {
if (!name)
return log_oom();
- r = asprintf(&_output, "%s/remote-%s.journal",
- arg_output ?: REMOTE_JOURNAL_PATH,
- name);
+ directory = strdup(arg_output ?: REMOTE_JOURNAL_PATH);
+ r = asprintf(&filename, "remote-%s.journal", name);
if (r < 0)
return log_oom();
-
- output = _output;
break;
}
@@ -194,17 +197,24 @@ static int open_output(Writer *w, const char* host) {
assert_not_reached("what?");
}
- r = journal_file_open_reliably(output,
+ r = journal_directory_open(directory, &dir);
+ if (r < 0) {
+ log_error_errno(r, "Failed to open journal directory %s: %m",
+ directory);
+ return r;
+ }
+ r = journal_file_open_reliably(dir, filename,
O_RDWR|O_CREAT, 0640,
arg_compress, arg_seal,
&w->metrics,
w->mmap,
NULL, &w->journal);
+ dir = journal_directory_unref(dir);
if (r < 0)
- log_error_errno(r, "Failed to open output journal %s: %m",
- output);
+ log_error_errno(r, "Failed to open output journal %s/%s: %m",
+ directory, filename);
else
- log_debug("Opened output file %s", w->journal->path);
+ log_debug("Opened output file %s/%s", w->journal->directory->path, w->journal->filename);
return r;
}
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index be6a552..5acc63c 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -154,8 +154,9 @@ void journal_file_close(JournalFile *f) {
(void) btrfs_defrag_fd(f->fd);
}
+ free(f->filename);
+ journal_directory_unref(f->directory);
safe_close(f->fd);
- free(f->path);
if (f->mmap)
mmap_cache_unref(f->mmap);
@@ -258,12 +259,14 @@ static int journal_file_verify_header(JournalFile *f) {
flags = le32toh(f->header->incompatible_flags);
if (flags & ~HEADER_INCOMPATIBLE_SUPPORTED) {
if (flags & ~HEADER_INCOMPATIBLE_ANY)
- log_debug("Journal file %s has unknown incompatible flags %"PRIx32,
- f->path, flags & ~HEADER_INCOMPATIBLE_ANY);
+ log_debug("Journal file %s/%s has unknown incompatible flags %"PRIx32,
+ f->directory->path, f->filename,
+ flags & ~HEADER_INCOMPATIBLE_ANY);
flags = (flags & HEADER_INCOMPATIBLE_ANY) & ~HEADER_INCOMPATIBLE_SUPPORTED;
if (flags)
- log_debug("Journal file %s uses incompatible flags %"PRIx32
- " disabled at compilation time.", f->path, flags);
+ log_debug("Journal file %s/%s uses incompatible flags %"PRIx32
+ " disabled at compilation time.", f->directory->path,
+ f->filename, flags);
return -EPROTONOSUPPORT;
}
@@ -272,12 +275,14 @@ static int journal_file_verify_header(JournalFile *f) {
flags = le32toh(f->header->compatible_flags);
if (f->writable && (flags & ~HEADER_COMPATIBLE_SUPPORTED)) {
if (flags & ~HEADER_COMPATIBLE_ANY)
- log_debug("Journal file %s has unknown compatible flags %"PRIx32,
- f->path, flags & ~HEADER_COMPATIBLE_ANY);
+ log_debug("Journal file %s/%s has unknown compatible flags %"PRIx32,
+ f->directory->path, f->filename,
+ flags & ~HEADER_COMPATIBLE_ANY);
flags = (flags & HEADER_COMPATIBLE_ANY) & ~HEADER_COMPATIBLE_SUPPORTED;
if (flags)
- log_debug("Journal file %s uses compatible flags %"PRIx32
- " disabled at compilation time.", f->path, flags);
+ log_debug("Journal file %s/%s uses compatible flags %"PRIx32
+ " disabled at compilation time.", f->directory->path,
+ f->filename, flags);
return -EPROTONOSUPPORT;
}
@@ -318,12 +323,14 @@ static int journal_file_verify_header(JournalFile *f) {
state = f->header->state;
if (state == STATE_ONLINE) {
- log_debug("Journal file %s is already online. Assuming unclean closing.", f->path);
+ log_debug("Journal file %s/%s is already online. Assuming unclean closing.",
+ f->directory->path, f->filename);
return -EBUSY;
} else if (state == STATE_ARCHIVED)
return -ESHUTDOWN;
else if (state != STATE_OFFLINE) {
- log_debug("Journal file %s has unknown state %i.", f->path, state);
+ log_debug("Journal file %s/%s has unknown state %i.",
+ f->directory->path, f->filename, state);
return -EBUSY;
}
}
@@ -2128,8 +2135,8 @@ 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/%s: entry array corrupted at entry %"PRIu64,
+ f->directory->path, f->filename, i);
return -EBADMSG;
}
@@ -2453,7 +2460,7 @@ void journal_file_print_header(JournalFile *f) {
assert(f);
- printf("File Path: %s\n"
+ printf("File Path: %s/%s\n"
"File ID: %s\n"
"Machine ID: %s\n"
"Boot ID: %s\n"
@@ -2473,7 +2480,7 @@ void journal_file_print_header(JournalFile *f) {
"Tail Monotonic Timestamp: %s\n"
"Objects: %"PRIu64"\n"
"Entry Objects: %"PRIu64"\n",
- f->path,
+ f->directory->path, f->filename,
sd_id128_to_string(f->header->file_id, a),
sd_id128_to_string(f->header->machine_id, b),
sd_id128_to_string(f->header->boot_id, c),
@@ -2550,15 +2557,16 @@ static int journal_file_warn_btrfs(JournalFile *f) {
return 0;
}
- log_notice("Creating journal file %s on a btrfs file system, and copy-on-write is enabled. "
+ log_notice("Creating journal file %s/%s on a btrfs file system, and copy-on-write is enabled. "
"This is likely to slow down journal access substantially, please consider turning "
- "off the copy-on-write file attribute on the journal directory, using chattr +C.", f->path);
+ "off the copy-on-write file attribute on the journal directory, using chattr +C.", f->directory->path, f->filename);
return 1;
}
int journal_file_open(
- const char *fname,
+ JournalDirectory *dir,
+ const char *filename,
int flags,
mode_t mode,
bool compress,
@@ -2568,20 +2576,21 @@ int journal_file_open(
JournalFile *template,
JournalFile **ret) {
+
bool newly_created = false;
JournalFile *f;
void *h;
int r;
- assert(fname);
+ assert(filename);
assert(ret);
if ((flags & O_ACCMODE) != O_RDONLY &&
(flags & O_ACCMODE) != O_RDWR)
return -EINVAL;
- if (!endswith(fname, ".journal") &&
- !endswith(fname, ".journal~"))
+ if (!endswith(filename, ".journal") &&
+ !endswith(filename, ".journal~"))
return -EINVAL;
f = new0(JournalFile, 1);
@@ -2613,19 +2622,19 @@ int journal_file_open(
}
}
- f->path = strdup(fname);
- if (!f->path) {
+ f->chain_cache = ordered_hashmap_new(&uint64_hash_ops);
+ if (!f->chain_cache) {
r = -ENOMEM;
goto fail;
}
- f->chain_cache = ordered_hashmap_new(&uint64_hash_ops);
- if (!f->chain_cache) {
+ f->filename = strdup(filename);
+ if (!f->filename) {
r = -ENOMEM;
goto fail;
}
-
- f->fd = open(f->path, f->flags|O_CLOEXEC, f->mode);
+ f->directory = journal_directory_ref(dir);
+ f->fd = openat(f->directory->fd, f->filename, f->flags|O_CLOEXEC, f->mode);
if (f->fd < 0) {
r = -errno;
goto fail;
@@ -2770,12 +2779,12 @@ int journal_file_rotate(JournalFile **f, bool compress, bool seal) {
if (!old_file->writable)
return -EINVAL;
- if (!endswith(old_file->path, ".journal"))
+ if (!endswith(old_file->filename, ".journal"))
return -EINVAL;
- l = strlen(old_file->path);
+ l = strlen(old_file->filename);
r = asprintf(&p, "%.*s@" SD_ID128_FORMAT_STR "-%016"PRIx64"-%016"PRIx64".journal",
- (int) l - 8, old_file->path,
+ (int) l - 8, old_file->filename,
SD_ID128_FORMAT_VAL(old_file->header->seqnum_id),
le64toh((*f)->header->head_entry_seqnum),
le64toh((*f)->header->head_entry_realtime));
@@ -2785,7 +2794,8 @@ int journal_file_rotate(JournalFile **f, bool compress, bool seal) {
/* Try to rename the file to the archived version. If the file
* already was deleted, we'll get ENOENT, let's ignore that
* case. */
- r = rename(old_file->path, p);
+ r = renameat(old_file->directory->fd, old_file->filename,
+ old_file->directory->fd, p);
if (r < 0 && errno != ENOENT)
return -errno;
@@ -2796,7 +2806,7 @@ int journal_file_rotate(JournalFile **f, bool compress, bool seal) {
* 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, old_file, &new_file);
+ r = journal_file_open(old_file->directory, old_file->filename, old_file->flags, old_file->mode, compress, seal, NULL, old_file->mmap, old_file, &new_file);
journal_file_close(old_file);
*f = new_file;
@@ -2804,7 +2814,8 @@ int journal_file_rotate(JournalFile **f, bool compress, bool seal) {
}
int journal_file_open_reliably(
- const char *fname,
+ JournalDirectory *dir,
+ const char *filename,
int flags,
mode_t mode,
bool compress,
@@ -2813,12 +2824,11 @@ int journal_file_open_reliably(
MMapCache *mmap_cache,
JournalFile *template,
JournalFile **ret) {
-
int r;
size_t l;
_cleanup_free_ char *p = NULL;
- r = journal_file_open(fname, flags, mode, compress, seal,
+ r = journal_file_open(dir, filename, flags, mode, compress, seal,
metrics, mmap_cache, template, ret);
if (!IN_SET(r,
-EBADMSG, /* corrupted */
@@ -2837,19 +2847,20 @@ int journal_file_open_reliably(
if (!(flags & O_CREAT))
return r;
- if (!endswith(fname, ".journal"))
+ if (!endswith(filename, ".journal"))
return r;
/* The file is corrupted. Rotate it away and try it again (but only once) */
- l = strlen(fname);
+ l = strlen(filename);
if (asprintf(&p, "%.*s@%016"PRIx64 "-%016"PRIx64 ".journal~",
- (int) l - 8, fname,
+ (int) l - 8, filename,
now(CLOCK_REALTIME),
random_u64()) < 0)
return -ENOMEM;
- r = rename(fname, p);
+ r = renameat(dir->fd, filename,
+ dir->fd, p);
if (r < 0)
return -errno;
@@ -2859,10 +2870,10 @@ int journal_file_open_reliably(
(void) chattr_path(p, false, FS_NOCOW_FL);
(void) btrfs_defrag(p);
- log_warning("File %s corrupted or uncleanly shut down, renaming and replacing.", fname);
+ log_warning("File %s/%s corrupted or uncleanly shut down, renaming and replacing.", dir->path, filename);
- return journal_file_open(fname, flags, mode, compress, seal,
- metrics, mmap_cache, template, ret);
+ return journal_file_open(dir, filename, flags, mode, compress,
+ seal, metrics, mmap_cache, template, ret);
}
int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset) {
@@ -3093,7 +3104,8 @@ bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec) {
/* If we gained new header fields we gained new features,
* hence suggest a rotation */
if (le64toh(f->header->header_size) < sizeof(Header)) {
- log_debug("%s uses an outdated header, suggesting rotation.", f->path);
+ log_debug("%s/%s uses an outdated header, suggesting rotation.",
+ f->directory->path, f->filename);
return true;
}
@@ -3105,8 +3117,9 @@ bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec) {
if (JOURNAL_HEADER_CONTAINS(f->header, n_data))
if (le64toh(f->header->n_data) * 4ULL > (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)) * 3ULL) {
- log_debug("Data hash table of %s has a fill level at %.1f (%"PRIu64" of %"PRIu64" items, %llu file size, %"PRIu64" bytes per hash table item), suggesting rotation.",
- f->path,
+ log_debug("Data hash table of %s/%s has a fill level at %.1f (%"PRIu64" of %"PRIu64" items, %llu file size, %"PRIu64" bytes per hash table item), suggesting rotation.",
+ f->directory->path,
+ f->filename,
100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem))),
le64toh(f->header->n_data),
le64toh(f->header->data_hash_table_size) / sizeof(HashItem),
@@ -3117,8 +3130,9 @@ bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec) {
if (JOURNAL_HEADER_CONTAINS(f->header, n_fields))
if (le64toh(f->header->n_fields) * 4ULL > (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)) * 3ULL) {
- log_debug("Field hash table of %s has a fill level at %.1f (%"PRIu64" of %"PRIu64" items), suggesting rotation.",
- f->path,
+ log_debug("Field hash table of %s/%s has a fill level at %.1f (%"PRIu64" of %"PRIu64" items), suggesting rotation.",
+ f->directory->path,
+ f->filename,
100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem))),
le64toh(f->header->n_fields),
le64toh(f->header->field_hash_table_size) / sizeof(HashItem));
diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
index 403c8f7..9a00de6 100644
--- a/src/journal/journal-file.h
+++ b/src/journal/journal-file.h
@@ -34,6 +34,7 @@
#include "macro.h"
#include "mmap-cache.h"
#include "hashmap.h"
+#include "journal-dir.h"
typedef struct JournalMetrics {
uint64_t max_use;
@@ -81,7 +82,8 @@ typedef struct JournalFile {
LocationType location_type;
uint64_t last_n_entries;
- char *path;
+ JournalDirectory *directory;
+ char *filename;
struct stat last_stat;
usec_t last_stat_usec;
@@ -125,7 +127,8 @@ typedef struct JournalFile {
} JournalFile;
int journal_file_open(
- const char *fname,
+ JournalDirectory *dir,
+ const char *filename,
int flags,
mode_t mode,
bool compress,
@@ -139,7 +142,8 @@ int journal_file_set_offline(JournalFile *f);
void journal_file_close(JournalFile *j);
int journal_file_open_reliably(
- const char *fname,
+ JournalDirectory *dir,
+ const char *filename,
int flags,
mode_t mode,
bool compress,
diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h
index b51ecdb..90a0f3f 100644
--- a/src/journal/journal-internal.h
+++ b/src/journal/journal-internal.h
@@ -33,6 +33,7 @@
#include "set.h"
#include "journal-file.h"
#include "sd-journal.h"
+#include "journal-dir.h"
typedef struct Match Match;
typedef struct Location Location;
@@ -78,7 +79,7 @@ struct Location {
};
struct Directory {
- char *path;
+ JournalDirectory *d;
int wd;
bool is_root;
};
diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c
index 81a577e..f1134bb 100644
--- a/src/journal/journal-vacuum.c
+++ b/src/journal/journal-vacuum.c
@@ -67,7 +67,7 @@ static int vacuum_compare(const void *_a, const void *_b) {
}
static void patch_realtime(
- const char *dir,
+ JournalDirectory *dir,
const char *fn,
const struct stat *st,
unsigned long long *realtime) {
@@ -101,14 +101,7 @@ static void patch_realtime(
* unfortunately there's currently no sane API to query
* it. Hence let's implement this manually... */
- /* Unfortunately there is is not fgetxattrat(), so we need to
- * go via path here. :-( */
-
- path = strjoin(dir, "/", fn, NULL);
- if (!path)
- return;
-
- if (path_getcrtime(path, &crtime) >= 0) {
+ if (fd_getcrtime_at(dir->fd, fn, &crtime, 0) >= 0) {
if (crtime < *realtime)
*realtime = crtime;
}
@@ -142,7 +135,7 @@ static int journal_file_empty(int dir_fd, const char *name) {
}
int journal_directory_vacuum(
- const char *directory,
+ JournalDirectory *directory,
uint64_t max_use,
usec_t max_retention_usec,
usec_t *oldest_usec,
@@ -170,9 +163,9 @@ int journal_directory_vacuum(
max_retention_usec = retention_limit = 0;
}
- d = opendir(directory);
- if (!d)
- return -errno;
+ r = journal_directory_opendir(directory, &d);
+ if (r < 0)
+ return r;
for (;;) {
struct dirent *de;
@@ -266,10 +259,10 @@ int journal_directory_vacuum(
uint64_t size = 512UL * (uint64_t) st.st_blocks;
if (unlinkat(dirfd(d), p, 0) >= 0) {
- log_full(verbose ? LOG_INFO : LOG_DEBUG, "Deleted empty archived journal %s/%s (%s).", directory, p, format_bytes(sbytes, sizeof(sbytes), size));
+ log_full(verbose ? LOG_INFO : LOG_DEBUG, "Deleted empty archived journal %s/%s (%s).", directory->path, p, format_bytes(sbytes, sizeof(sbytes), size));
freed += size;
} else if (errno != ENOENT)
- log_warning_errno(errno, "Failed to delete empty archived journal %s/%s: %m", directory, p);
+ log_warning_errno(errno, "Failed to delete empty archived journal %s/%s: %m", directory->path, p);
free(p);
continue;
@@ -303,7 +296,7 @@ int journal_directory_vacuum(
break;
if (unlinkat(dirfd(d), list[i].filename, 0) >= 0) {
- log_full(verbose ? LOG_INFO : LOG_DEBUG, "Deleted archived journal %s/%s (%s).", directory, list[i].filename, format_bytes(sbytes, sizeof(sbytes), list[i].usage));
+ log_full(verbose ? LOG_INFO : LOG_DEBUG, "Deleted archived journal %s/%s (%s).", directory->path, list[i].filename, format_bytes(sbytes, sizeof(sbytes), list[i].usage));
freed += list[i].usage;
if (list[i].usage < sum)
@@ -312,7 +305,7 @@ int journal_directory_vacuum(
sum = 0;
} else if (errno != ENOENT)
- log_warning_errno(errno, "Failed to delete archived journal %s/%s: %m", directory, list[i].filename);
+ log_warning_errno(errno, "Failed to delete archived journal %s/%s: %m", directory->path, list[i].filename);
}
if (oldest_usec && i < n_list && (*oldest_usec == 0 || list[i].realtime < *oldest_usec))
diff --git a/src/journal/journal-vacuum.h b/src/journal/journal-vacuum.h
index c45cc31..cdcdfcd 100644
--- a/src/journal/journal-vacuum.h
+++ b/src/journal/journal-vacuum.h
@@ -21,5 +21,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "journal-dir.h"
-int journal_directory_vacuum(const char *directory, uint64_t max_use, usec_t max_retention_usec, usec_t *oldest_usec, bool vacuum);
+int journal_directory_vacuum(JournalDirectory *directory, uint64_t max_use, usec_t max_retention_usec, usec_t *oldest_usec, bool vacuum);
diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
index ce734d8..347920e 100644
--- a/src/journal/journal-verify.c
+++ b/src/journal/journal-verify.c
@@ -1265,8 +1265,8 @@ fail:
if (show_progress)
flush_progress();
- log_error("File corruption detected at %s:"OFSfmt" (of %llu bytes, %"PRIu64"%%).",
- f->path,
+ log_error("File corruption detected at %s/%s:"OFSfmt" (of %llu bytes, %"PRIu64"%%).",
+ f->directory->path, f->filename,
p,
(unsigned long long) f->last_stat.st_size,
100 * p / f->last_stat.st_size);
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 76ec082..8a2d4a1 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -1576,7 +1576,7 @@ static int verify(sd_journal *j) {
#ifdef HAVE_GCRYPT
if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
- log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
+ log_notice("Journal file %s/%s has sealing enabled but verification key has not been passed using --verify-key=.", f->directory->path, f->filename);
#endif
k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
@@ -1584,11 +1584,11 @@ static int verify(sd_journal *j) {
/* If the key was invalid give up right-away. */
return k;
} else if (k < 0) {
- log_warning("FAIL: %s (%s)", f->path, strerror(-k));
+ log_warning("FAIL: %s/%s (%s)", f->directory->path, f->filename, strerror(-k));
r = k;
} else {
char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
- log_info("PASS: %s", f->path);
+ log_info("PASS: %s/%s", f->directory->path, f->filename);
if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
if (validated > 0) {
@@ -1899,7 +1899,7 @@ int main(int argc, char *argv[]) {
if (d->is_root)
continue;
- q = journal_directory_vacuum(d->path, arg_vacuum_size, arg_vacuum_time, NULL, true);
+ q = journal_directory_vacuum(d->d, arg_vacuum_size, arg_vacuum_time, NULL, true);
if (q < 0) {
log_error_errno(q, "Failed to vacuum: %m");
r = q;
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index 3353024..6ec0b8e 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -200,7 +200,8 @@ void server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
r = fchmod(f->fd, 0640);
if (r < 0)
- log_warning_errno(r, "Failed to fix access mode on %s, ignoring: %m", f->path);
+ log_warning_errno(r, "Failed to fix access mode on %s/%s, ignoring: %m",
+ f->directory->path, f->filename);
#ifdef HAVE_ACL
if (uid <= SYSTEM_UID_MAX)
@@ -208,7 +209,8 @@ void server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
acl = acl_get_fd(f->fd);
if (!acl) {
- log_warning_errno(errno, "Failed to read ACL on %s, ignoring: %m", f->path);
+ log_warning_errno(errno, "Failed to read ACL on %s/%s, ignoring: %m",
+ f->directory->path, f->filename);
return;
}
@@ -218,7 +220,8 @@ void server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
if (acl_create_entry(&acl, &entry) < 0 ||
acl_set_tag_type(entry, ACL_USER) < 0 ||
acl_set_qualifier(entry, &uid) < 0) {
- log_warning_errno(errno, "Failed to patch ACL on %s, ignoring: %m", f->path);
+ log_warning_errno(errno, "Failed to patch ACL on %s/%s, ignoring: %m",
+ f->directory->path, f->filename);
goto finish;
}
}
@@ -228,12 +231,13 @@ void server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
if (acl_get_permset(entry, &permset) < 0 ||
acl_add_perm(permset, ACL_READ) < 0 ||
calc_acl_mask_if_needed(&acl) < 0) {
- log_warning_errno(errno, "Failed to patch ACL on %s, ignoring: %m", f->path);
+ log_warning_errno(errno, "Failed to patch ACL on %s/%s, ignoring: %m",
+ f->directory->path, f->filename);
goto finish;
}
if (acl_set_fd(f->fd, acl) < 0)
- log_warning_errno(errno, "Failed to set ACL on %s, ignoring: %m", f->path);
+ log_warning_errno(errno, "Failed to set ACL on %s/%s, ignoring: %m", f->directory->path, f->filename);
finish:
acl_free(acl);
@@ -241,7 +245,9 @@ finish:
}
static JournalFile* find_journal(Server *s, uid_t uid) {
- _cleanup_free_ char *p = NULL;
+ _cleanup_free_ char *directory = NULL;
+ _cleanup_free_ char *filename = NULL;
+ JournalDirectory *dir;
int r;
JournalFile *f;
sd_id128_t machine;
@@ -267,8 +273,15 @@ static JournalFile* find_journal(Server *s, uid_t uid) {
if (f)
return f;
- if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/user-"UID_FMT".journal",
- SD_ID128_FORMAT_VAL(machine), uid) < 0)
+ if (asprintf(&directory, "/var/log/journal/" SD_ID128_FORMAT_STR,
+ SD_ID128_FORMAT_VAL(machine)) < 0)
+ return s->system_journal;
+
+ if (asprintf(&filename, "user-" UID_FMT ".journal", uid) < 0)
+ return s->system_journal;
+
+ r = journal_directory_open(directory, &dir);
+ if (r < 0)
return s->system_journal;
while (ordered_hashmap_size(s->user_journals) >= USER_JOURNALS_MAX) {
@@ -278,7 +291,8 @@ static JournalFile* find_journal(Server *s, uid_t uid) {
journal_file_close(f);
}
- r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &f);
+ r = journal_file_open_reliably(dir, filename, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &f);
+ dir = journal_directory_unref(dir);
if (r < 0)
return s->system_journal;
@@ -309,7 +323,8 @@ static int do_rotate(
r = journal_file_rotate(f, s->compress, seal);
if (r < 0)
if (*f)
- log_error_errno(r, "Failed to rotate %s: %m", (*f)->path);
+ log_error_errno(r, "Failed to rotate %s/%s: %m",
+ (*f)->directory->path, (*f)->filename);
else
log_error_errno(r, "Failed to create new %s journal: %m", name);
else
@@ -374,13 +389,20 @@ static void do_vacuum(
JournalMetrics *metrics) {
const char *p;
+ JournalDirectory *dir;
int r;
if (!f)
return;
p = strjoina(path, id);
- r = journal_directory_vacuum(p, metrics->max_use, s->max_retention_usec, &s->oldest_file_usec, false);
+ r = journal_directory_open(p, &dir);
+ if (r < 0 && r != -ENOENT) {
+ log_error_errno(r, "Failed to vacuum %s: %m", p);
+ return;
+ }
+ r = journal_directory_vacuum(dir, metrics->max_use, s->max_retention_usec, &s->oldest_file_usec, false);
+ dir = journal_directory_unref(dir);
if (r < 0 && r != -ENOENT)
log_error_errno(r, "Failed to vacuum %s: %m", p);
}
@@ -467,19 +489,19 @@ static bool shall_try_append_again(JournalFile *f, int r) {
-EIDRM Journal file has been deleted */
if (r == -E2BIG || r == -EFBIG || r == -EDQUOT || r == -ENOSPC)
- log_debug("%s: Allocation limit reached, rotating.", f->path);
+ log_debug("%s/%s: Allocation limit reached, rotating.", f->directory->path, f->filename);
else if (r == -EHOSTDOWN)
- log_info("%s: Journal file from other machine, rotating.", f->path);
+ log_info("%s/%s: Journal file from other machine, rotating.", f->directory->path, f->filename);
else if (r == -EBUSY)
- log_info("%s: Unclean shutdown, rotating.", f->path);
+ log_info("%s/%s: Unclean shutdown, rotating.", f->directory->path, f->filename);
else if (r == -EPROTONOSUPPORT)
- log_info("%s: Unsupported feature, rotating.", f->path);
+ log_info("%s/%s: Unsupported feature, rotating.", f->directory->path, f->filename);
else if (r == -EBADMSG || r == -ENODATA || r == ESHUTDOWN)
- log_warning("%s: Journal file corrupted, rotating.", f->path);
+ log_warning("%s/%s: Journal file corrupted, rotating.", f->directory->path, f->filename);
else if (r == -EIO)
- log_warning("%s: IO error, rotating.", f->path);
+ log_warning("%s/%s: IO error, rotating.", f->directory->path, f->filename);
else if (r == -EIDRM)
- log_warning("%s: Journal file has been deleted, rotating.", f->path);
+ log_warning("%s/%s: Journal file has been deleted, rotating.", f->directory->path, f->filename);
else
return false;
@@ -500,7 +522,7 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned
return;
if (journal_file_rotate_suggested(f, s->max_file_usec)) {
- log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path);
+ log_debug("%s/%s: Journal header limits reached or header out-of-date, rotating.", f->directory->path, f->filename);
server_rotate(s);
server_vacuum(s);
vacuumed = true;
@@ -936,6 +958,8 @@ static int system_journal_open(Server *s, bool flush_requested) {
(flush_requested
|| access("/run/systemd/journal/flushed", F_OK) >= 0)) {
+ JournalDirectory *dir;
+
/* If in auto mode: first try to create the machine
* path, but not the prefix.
*
@@ -947,54 +971,75 @@ static int system_journal_open(Server *s, bool flush_requested) {
fn = strjoina("/var/log/journal/", ids);
(void) mkdir(fn, 0755);
+ r = journal_directory_open(fn, &dir);
+ if (r < 0) {
+ log_warning_errno(r, "Failed to open system journal: %m");
+ } else {
- fn = strjoina(fn, "/system.journal");
- r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &s->system_journal);
+ r = journal_file_open_reliably(dir, "system.journal", O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &s->system_journal);
+ dir = journal_directory_unref(dir);
- if (r >= 0)
- server_fix_perms(s, s->system_journal, 0);
- else if (r < 0) {
- if (r != -ENOENT && r != -EROFS)
- log_warning_errno(r, "Failed to open system journal: %m");
+ if (r >= 0)
+ server_fix_perms(s, s->system_journal, 0);
+ else if (r < 0) {
+ if (r != -ENOENT && r != -EROFS)
+ log_warning_errno(r, "Failed to open system journal: %m");
- r = 0;
+ r = 0;
+ }
}
}
if (!s->runtime_journal &&
(s->storage != STORAGE_NONE)) {
- fn = strjoin("/run/log/journal/", ids, "/system.journal", NULL);
+ fn = strjoin("/run/log/journal/", ids, NULL);
if (!fn)
return -ENOMEM;
if (s->system_journal) {
+ JournalDirectory *dir;
+
/* Try to open the runtime journal, but only
* if it already exists, so that we can flush
* it into the system journal */
- r = journal_file_open(fn, O_RDWR, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
- free(fn);
-
+ r = journal_directory_open(fn, &dir);
if (r < 0) {
if (r != -ENOENT)
log_warning_errno(r, "Failed to open runtime journal: %m");
-
r = 0;
+ } else {
+ r = journal_file_open(dir, "system.journal", O_RDWR, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
+ free(fn);
+ dir = journal_directory_unref(dir);
+
+ if (r < 0) {
+ if (r != -ENOENT)
+ log_warning_errno(r, "Failed to open runtime journal: %m");
+
+ r = 0;
+ }
}
} else {
+ JournalDirectory *dir;
+
/* OK, we really need the runtime journal, so create
* it if necessary. */
(void) mkdir("/run/log", 0755);
(void) mkdir("/run/log/journal", 0755);
- (void) mkdir_parents(fn, 0750);
+ (void) mkdir_p(fn, 0750);
- r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
+ r = journal_directory_open(fn, &dir);
+ if (r < 0)
+ return log_error_errno(r, "Failed to open runtime journal: %m");
+ r = journal_file_open_reliably(dir, "system.journal", O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
free(fn);
+ dir = journal_directory_unref(dir);
if (r < 0)
return log_error_errno(r, "Failed to open runtime journal: %m");
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index 9f0f71a..630cc3a 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -798,7 +798,8 @@ static int real_journal_next(sd_journal *j, direction_t direction) {
r = next_beyond_location(j, f, direction);
if (r < 0) {
- log_debug_errno(r, "Can't iterate through %s, ignoring: %m", f->path);
+ log_debug_errno(r, "Can't iterate through %s/%s, ignoring: %m",
+ f->directory->path, f->filename);
remove_file_real(j, f);
continue;
} else if (r == 0) {
@@ -1194,12 +1195,19 @@ static bool file_type_wanted(int flags, const char *filename) {
return false;
}
-static int add_any_file(sd_journal *j, const char *path) {
+static int add_any_file(sd_journal *j, JournalDirectory *d, const char *filename) {
+ _cleanup_free_ char *path = NULL;
JournalFile *f = NULL;
int r;
+ _cleanup_free_ char *fpath = NULL;
assert(j);
- assert(path);
+ assert(d);
+ assert(filename);
+
+ path = strjoin(d->path, "/", filename, NULL);
+ if (!path)
+ return -ENOMEM;
if (ordered_hashmap_get(j->files, path))
return 0;
@@ -1209,19 +1217,23 @@ static int add_any_file(sd_journal *j, const char *path) {
return set_put_error(j, -ETOOMANYREFS);
}
- r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, &f);
+ r = journal_file_open(d, filename, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, &f);
if (r < 0)
return r;
/* journal_file_dump(f); */
- r = ordered_hashmap_put(j->files, f->path, f);
+ fpath = strjoin(f->directory->path, "/", f->filename, NULL);
+ if (!fpath)
+ return -ENOMEM;
+ r = ordered_hashmap_put(j->files, fpath, f);
if (r < 0) {
journal_file_close(f);
return r;
}
+ fpath = NULL;
- log_debug("File %s added.", f->path);
+ log_debug("File %s/%s added.", f->directory->path, f->filename);
check_network(j, f->fd);
@@ -1230,37 +1242,32 @@ static int add_any_file(sd_journal *j, const char *path) {
return 0;
}
-static int add_file(sd_journal *j, const char *prefix, const char *filename) {
- _cleanup_free_ char *path = NULL;
+static int add_file(sd_journal *j, JournalDirectory *d, const char *filename) {
int r;
assert(j);
- assert(prefix);
+ assert(d);
assert(filename);
if (j->no_new_files ||
!file_type_wanted(j->flags, filename))
return 0;
- path = strjoin(prefix, "/", filename, NULL);
- if (!path)
- return -ENOMEM;
-
- r = add_any_file(j, path);
+ r = add_any_file(j, d, filename);
if (r == -ENOENT)
return 0;
return r;
}
-static int remove_file(sd_journal *j, const char *prefix, const char *filename) {
+static int remove_file(sd_journal *j, JournalDirectory *d, const char *filename) {
_cleanup_free_ char *path;
JournalFile *f;
assert(j);
- assert(prefix);
+ assert(d);
assert(filename);
- path = strjoin(prefix, "/", filename, NULL);
+ path = strjoin(d->path, "/", filename, NULL);
if (!path)
return -ENOMEM;
@@ -1273,12 +1280,21 @@ static int remove_file(sd_journal *j, const char *prefix, const char *filename)
}
static void remove_file_real(sd_journal *j, JournalFile *f) {
+ char *fpath;
+ _cleanup_free_ char *path = NULL;
+
assert(j);
assert(f);
- ordered_hashmap_remove(j->files, f->path);
+ path = strjoin(f->directory->path, "/", f->filename, NULL);
+ if (!path) {
+ log_warning("Failed to remove %s/%s.", f->directory->path, f->filename);
+ return;
+ }
+ ordered_hashmap_remove2(j->files, path, (void**)&fpath);
+ free(fpath);
- log_debug("File %s removed.", f->path);
+ log_debug("File %s removed.", path);
if (j->current_file == f) {
j->current_file = NULL;
@@ -1287,7 +1303,7 @@ static void remove_file_real(sd_journal *j, JournalFile *f) {
if (j->unique_file == f) {
/* Jump to the next unique_file or NULL if that one was last */
- j->unique_file = ordered_hashmap_next(j->files, j->unique_file->path);
+ j->unique_file = ordered_hashmap_next(j->files, path);
j->unique_offset = 0;
if (!j->unique_file)
j->unique_file_lost = true;
@@ -1298,7 +1314,39 @@ static void remove_file_real(sd_journal *j, JournalFile *f) {
j->current_invalidate_counter ++;
}
-static int add_directory(sd_journal *j, const char *prefix, const char *dirname) {
+static int new_directory(const char* path, int fd, bool is_root, Directory **ret) {
+ Directory *m;
+ JournalDirectory *d;
+ int r;
+
+ assert(path);
+ assert(ret);
+
+ r = journal_directory_new(path, fd, &d);
+ if (r < 0)
+ return r;
+
+ m = new0(Directory, 1);
+ if (!m) {
+ d = journal_directory_unref(d);
+ return -ENOMEM;
+ }
+
+ m->is_root = is_root;
+ m->d = d;
+ *ret = m;
+
+ return 0;
+}
+
+static void free_directory(Directory *d) {
+ if (d) {
+ journal_directory_unref(d->d);
+ free(d);
+ }
+}
+
+static int add_directory(sd_journal *j, JournalDirectory *directory, const char *dirname) {
_cleanup_free_ char *path = NULL;
int r;
_cleanup_closedir_ DIR *d = NULL;
@@ -1306,54 +1354,59 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
Directory *m;
assert(j);
- assert(prefix);
+ assert(directory);
assert(dirname);
- log_debug("Considering %s/%s.", prefix, dirname);
+ log_debug("Considering %s/%s.", directory->path, dirname);
if ((j->flags & SD_JOURNAL_LOCAL_ONLY) &&
(sd_id128_from_string(dirname, &id) < 0 ||
sd_id128_get_machine(&mid) < 0 ||
- !(sd_id128_equal(id, mid) || path_startswith(prefix, "/run"))))
+ !(sd_id128_equal(id, mid) || path_startswith(directory->path, "/run"))))
return 0;
- path = strjoin(prefix, "/", dirname, NULL);
+ path = strjoin(directory->path, "/", dirname, NULL);
if (!path)
return -ENOMEM;
- d = opendir(path);
- if (!d) {
- log_debug_errno(errno, "Failed to open %s: %m", path);
- if (errno == ENOENT)
- return 0;
- return -errno;
- }
-
m = hashmap_get(j->directories_by_path, path);
if (!m) {
- m = new0(Directory, 1);
- if (!m)
- return -ENOMEM;
+ _cleanup_close_ int fd = -1;
- m->is_root = false;
- m->path = path;
+ fd = openat(directory->fd, dirname, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
+ if (fd < 0)
+ return -errno;
- if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
- free(m);
+ r = new_directory(path, fd, false, &m);
+ if (r < 0)
+ return r;
+
+ if (hashmap_put(j->directories_by_path, m->d->path, m) < 0) {
+ free_directory(m);
return -ENOMEM;
}
- path = NULL; /* avoid freeing in cleanup */
j->current_invalidate_counter ++;
- log_debug("Directory %s added.", m->path);
+ log_debug("Directory %s added.", m->d->path);
} else if (m->is_root)
return 0;
+ r = journal_directory_opendir(m->d, &d);
+ if (r < 0) {
+ log_debug_errno(errno, "Failed to open %s: %m", m->d->path);
+ if (r == -ENOENT)
+ return 0;
+ return r;
+ }
+
+ /* TODO: we can't watch changes happening in overlayfs in
+ other mount namespace, unless we get something like
+ inotify_add_watch_dirfd. */
if (m->wd <= 0 && j->inotify_fd >= 0) {
- m->wd = inotify_add_watch(j->inotify_fd, m->path,
+ m->wd = inotify_add_watch(j->inotify_fd, m->d->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);
@@ -1369,7 +1422,7 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
de = readdir(d);
if (!de && errno != 0) {
r = -errno;
- log_debug_errno(errno, "Failed to read directory %s: %m", m->path);
+ log_debug_errno(errno, "Failed to read directory %s: %m", m->d->path);
return r;
}
if (!de)
@@ -1377,10 +1430,10 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
if (dirent_is_file_with_suffix(de, ".journal") ||
dirent_is_file_with_suffix(de, ".journal~")) {
- r = add_file(j, m->path, de->d_name);
+ r = add_file(j, m->d, de->d_name);
if (r < 0) {
log_debug_errno(r, "Failed to add file %s/%s: %m",
- m->path, de->d_name);
+ m->d->path, de->d_name);
r = set_put_error(j, r);
if (r < 0)
return r;
@@ -1393,54 +1446,43 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
return 0;
}
-static int add_root_directory(sd_journal *j, const char *p) {
+static int add_root_directory_with_fd(sd_journal *j, const char *p, int fd) {
_cleanup_closedir_ DIR *d = NULL;
Directory *m;
int r;
assert(j);
assert(p);
-
- if ((j->flags & SD_JOURNAL_RUNTIME_ONLY) &&
- !path_startswith(p, "/run"))
- return -EINVAL;
-
- if (j->prefix)
- p = strjoina(j->prefix, p);
-
- d = opendir(p);
- if (!d)
- return -errno;
+ assert(fd >= 0);
m = hashmap_get(j->directories_by_path, p);
if (!m) {
- m = new0(Directory, 1);
- if (!m)
- return -ENOMEM;
-
- m->is_root = true;
- m->path = strdup(p);
- if (!m->path) {
- free(m);
- return -ENOMEM;
- }
+ r = new_directory(p, fd, true, &m);
+ if (r < 0)
+ return r;
- if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
- free(m->path);
- free(m);
+ if (hashmap_put(j->directories_by_path, m->d->path, m) < 0) {
+ free_directory(m);
return -ENOMEM;
}
j->current_invalidate_counter ++;
- log_debug("Root directory %s added.", m->path);
+ log_debug("Root directory %s added.", m->d->path);
} else if (!m->is_root)
return 0;
+ r = journal_directory_opendir(m->d, &d);
+ if (r < 0)
+ return r;
+
+ /* TODO: we can't watch changes happening in overlayfs in
+ other mount namespace, unless we get something like
+ inotify_add_watch_dirfd. */
if (m->wd <= 0 && j->inotify_fd >= 0) {
- m->wd = inotify_add_watch(j->inotify_fd, m->path,
+ m->wd = inotify_add_watch(j->inotify_fd, m->d->path,
IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
IN_ONLYDIR);
@@ -1459,7 +1501,7 @@ static int add_root_directory(sd_journal *j, const char *p) {
de = readdir(d);
if (!de && errno != 0) {
r = -errno;
- log_debug_errno(errno, "Failed to read directory %s: %m", m->path);
+ log_debug_errno(errno, "Failed to read directory %s: %m", m->d->path);
return r;
}
if (!de)
@@ -1467,10 +1509,10 @@ static int add_root_directory(sd_journal *j, const char *p) {
if (dirent_is_file_with_suffix(de, ".journal") ||
dirent_is_file_with_suffix(de, ".journal~")) {
- r = add_file(j, m->path, de->d_name);
+ r = add_file(j, m->d, de->d_name);
if (r < 0) {
log_debug_errno(r, "Failed to add file %s/%s: %m",
- m->path, de->d_name);
+ m->d->path, de->d_name);
r = set_put_error(j, r);
if (r < 0)
return r;
@@ -1478,9 +1520,9 @@ static int add_root_directory(sd_journal *j, const char *p) {
} else if ((de->d_type == DT_DIR || de->d_type == DT_LNK || de->d_type == DT_UNKNOWN) &&
sd_id128_from_string(de->d_name, &id) >= 0) {
- r = add_directory(j, m->path, de->d_name);
+ r = add_directory(j, m->d, de->d_name);
if (r < 0)
- log_debug_errno(r, "Failed to add directory %s/%s: %m", m->path, de->d_name);
+ log_debug_errno(r, "Failed to add directory %s/%s: %m", m->d->path, de->d_name);
}
}
@@ -1489,6 +1531,26 @@ static int add_root_directory(sd_journal *j, const char *p) {
return 0;
}
+static int add_root_directory(sd_journal *j, const char *p) {
+ _cleanup_close_ int fd = -1;
+
+ assert(j);
+ assert(p);
+
+ if ((j->flags & SD_JOURNAL_RUNTIME_ONLY) &&
+ !path_startswith(p, "/run"))
+ return -EINVAL;
+
+ if (j->prefix)
+ p = strjoina(j->prefix, p);
+
+ fd = open(p, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
+ if (fd < 0)
+ return -errno;
+
+ return add_root_directory_with_fd(j, p, fd);
+}
+
static int remove_directory(sd_journal *j, Directory *d) {
assert(j);
@@ -1499,15 +1561,14 @@ static int remove_directory(sd_journal *j, Directory *d) {
inotify_rm_watch(j->inotify_fd, d->wd);
}
- hashmap_remove(j->directories_by_path, d->path);
+ hashmap_remove(j->directories_by_path, d->d->path);
if (d->is_root)
- log_debug("Root directory %s removed.", d->path);
+ log_debug("Root directory %s removed.", d->d->path);
else
- log_debug("Directory %s removed.", d->path);
+ log_debug("Directory %s removed.", d->d->path);
- free(d->path);
- free(d);
+ free_directory(d);
return 0;
}
@@ -1539,6 +1600,7 @@ static int add_search_paths(sd_journal *j) {
static int add_current_paths(sd_journal *j) {
Iterator i;
JournalFile *f;
+ const char *p;
assert(j);
assert(j->no_new_files);
@@ -1547,11 +1609,11 @@ static int add_current_paths(sd_journal *j) {
* "root" directories. We don't expect errors here, so we
* treat them as fatal. */
- ORDERED_HASHMAP_FOREACH(f, j->files, i) {
+ ORDERED_HASHMAP_FOREACH_KEY(f, p, j->files, i) {
_cleanup_free_ char *dir;
int r;
- dir = dirname_malloc(f->path);
+ dir = dirname_malloc(p);
if (!dir)
return -ENOMEM;
@@ -1712,6 +1774,8 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla
sd_journal *j;
const char **path;
int r;
+ Hashmap *dirs;
+ Directory *dir;
assert_return(ret, -EINVAL);
assert_return(flags == 0, -EINVAL);
@@ -1719,15 +1783,53 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla
j = journal_new(flags, NULL);
if (!j)
return -ENOMEM;
+ dirs = hashmap_new(&string_hash_ops);
+ if (!dirs) {
+ r = -ENOMEM;
+ goto fail;
+ }
STRV_FOREACH(path, paths) {
- r = add_any_file(j, *path);
+ _cleanup_free_ char *d = NULL;
+ _cleanup_free_ char *b = NULL;
+
+ d = dirname_malloc(*path);
+ b = basename_malloc(*path);
+ if (!d || !b)
+ goto fail;
+
+ dir = hashmap_get(dirs, d);
+ if (!dir) {
+ _cleanup_close_ int dirfd = -1;
+
+ dirfd = open(d, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
+ if (dirfd < 0) {
+ r = -errno;
+ log_error_errno(errno, "Failed to open directory %s: %m", d);
+ goto fail;
+ }
+ r = new_directory(d, dirfd, false, &dir);
+ if (r < 0)
+ goto fail;
+
+ r = hashmap_put(dirs, dir->d->path, dir);
+ if (r < 0) {
+ free_directory(dir);
+ goto fail;
+ }
+ }
+
+ r = add_any_file(j, dir->d, b);
if (r < 0) {
log_error_errno(r, "Failed to open %s: %m", *path);
goto fail;
}
}
+ while ((dir = hashmap_steal_first(dirs)))
+ free_directory(dir);
+ hashmap_free(dirs);
+
j->no_new_files = true;
*ret = j;
@@ -1736,20 +1838,30 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla
fail:
sd_journal_close(j);
+ while ((dir = hashmap_steal_first(dirs)))
+ free_directory(dir);
+ hashmap_free(dirs);
+
return r;
}
_public_ void sd_journal_close(sd_journal *j) {
Directory *d;
- JournalFile *f;
if (!j)
return;
sd_journal_flush_matches(j);
- while ((f = ordered_hashmap_steal_first(j->files)))
+ while (!ordered_hashmap_isempty(j->files)) {
+ char *p;
+ JournalFile *f;
+
+ p = ordered_hashmap_first_key(j->files);
+ f = ordered_hashmap_steal_first(j->files);
+ free(p);
journal_file_close(f);
+ }
ordered_hashmap_free(j->files);
@@ -2129,18 +2241,18 @@ static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
/* Event for a journal file */
if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) {
- r = add_file(j, d->path, e->name);
+ r = add_file(j, d->d, e->name);
if (r < 0) {
log_debug_errno(r, "Failed to add file %s/%s: %m",
- d->path, e->name);
+ d->d->path, e->name);
set_put_error(j, r);
}
} else if (e->mask & (IN_DELETE|IN_MOVED_FROM|IN_UNMOUNT)) {
- r = remove_file(j, d->path, e->name);
+ r = remove_file(j, d->d, e->name);
if (r < 0)
- log_debug_errno(r, "Failed to remove file %s/%s: %m", d->path, e->name);
+ log_debug_errno(r, "Failed to remove file %s/%s: %m", d->d->path, e->name);
}
} else if (!d->is_root && e->len == 0) {
@@ -2150,7 +2262,7 @@ static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
if (e->mask & (IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT)) {
r = remove_directory(j, d);
if (r < 0)
- log_debug_errno(r, "Failed to remove directory %s: %m", d->path);
+ log_debug_errno(r, "Failed to remove directory %s: %m", d->d->path);
}
@@ -2159,9 +2271,9 @@ static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
/* Event for root directory */
if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) {
- r = add_directory(j, d->path, e->name);
+ r = add_directory(j, d->d, e->name);
if (r < 0)
- log_debug_errno(r, "Failed to add directory %s/%s: %m", d->path, e->name);
+ log_debug_errno(r, "Failed to add directory %s/%s: %m", d->d->path, e->name);
}
}
@@ -2447,7 +2559,12 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
/* We reached the end of the list? Then start again, with the next file */
if (j->unique_offset == 0) {
- j->unique_file = ordered_hashmap_next(j->files, j->unique_file->path);
+ char *p = strjoin(j->unique_file->directory->path, "/", j->unique_file->filename, NULL);
+
+ if (!p)
+ return -ENOMEM;
+ j->unique_file = ordered_hashmap_next(j->files, p);
+ free(p);
if (!j->unique_file)
return 0;
@@ -2463,8 +2580,9 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
/* Let's do the type check by hand, since we used 0 context above. */
if (o->object.type != OBJECT_DATA) {
- log_debug("%s:offset " OFSfmt ": object has type %d, expected %d",
- j->unique_file->path, j->unique_offset,
+ log_debug("%s/%s:offset " OFSfmt ": object has type %d, expected %d",
+ j->unique_file->directory->path, j->unique_file->filename,
+ j->unique_offset,
o->object.type, OBJECT_DATA);
return -EBADMSG;
}
@@ -2475,15 +2593,17 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
/* Check if we have at least the field name and "=". */
if (ol <= k) {
- log_debug("%s:offset " OFSfmt ": object has size %zu, expected at least %zu",
- j->unique_file->path, j->unique_offset,
+ log_debug("%s/%s:offset " OFSfmt ": object has size %zu, expected at least %zu",
+ j->unique_file->directory->path, j->unique_file->filename,
+ j->unique_offset,
ol, k + 1);
return -EBADMSG;
}
if (memcmp(odata, j->unique_field, k) || ((const char*) odata)[k] != '=') {
- log_debug("%s:offset " OFSfmt ": object does not start with \"%s=\"",
- j->unique_file->path, j->unique_offset,
+ log_debug("%s/%s:offset " OFSfmt ": object does not start with \"%s=\"",
+ j->unique_file->directory->path, j->unique_file->filename,
+ j->unique_offset,
j->unique_field);
return -EBADMSG;
}
diff --git a/src/journal/test-journal-flush.c b/src/journal/test-journal-flush.c
index 2d4f531..97080fb 100644
--- a/src/journal/test-journal-flush.c
+++ b/src/journal/test-journal-flush.c
@@ -27,17 +27,21 @@
#include "journal-internal.h"
int main(int argc, char *argv[]) {
- _cleanup_free_ char *fn = NULL;
+ const char *fn;
char dn[] = "/var/tmp/test-journal-flush.XXXXXX";
+ JournalDirectory *dir;
JournalFile *new_journal = NULL;
sd_journal *j = NULL;
unsigned n = 0;
int r;
assert_se(mkdtemp(dn));
- fn = strappend(dn, "/test.journal");
+ fn = "test.journal";
- r = journal_file_open(fn, O_CREAT|O_RDWR, 0644, false, false, NULL, NULL, NULL, &new_journal);
+ r = journal_directory_open(dn, &dir);
+ assert_se(r >= 0);
+
+ r = journal_file_open(dir, fn, O_CREAT|O_RDWR, 0644, false, false, NULL, NULL, NULL, &new_journal);
assert_se(r >= 0);
r = sd_journal_open(&j, 0);
@@ -67,7 +71,8 @@ int main(int argc, char *argv[]) {
journal_file_close(new_journal);
- unlink(fn);
+ unlinkat(dir->fd, fn, 0);
+ dir = journal_directory_unref(dir);
assert_se(rmdir(dn) == 0);
return 0;
diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c
index c2fc123..1bb965f 100644
--- a/src/journal/test-journal-interleaving.c
+++ b/src/journal/test-journal-interleaving.c
@@ -49,16 +49,27 @@ noreturn static void log_assert_errno(const char *text, int eno, const char *fil
log_assert_errno(#expr, -_r_, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
} while (false)
-static JournalFile *test_open(const char *name) {
+static JournalFile *test_open(JournalDirectory *dir, const char *filename) {
JournalFile *f;
- assert_ret(journal_file_open(name, O_RDWR|O_CREAT, 0644, true, false, NULL, NULL, NULL, &f));
+ assert_ret(journal_file_open(dir, filename, O_RDWR|O_CREAT, 0644, true, false, NULL, NULL, NULL, &f));
return f;
}
+static JournalDirectory *test_open_dir(const char *dirname) {
+ JournalDirectory *dir;
+
+ assert_ret(journal_directory_open(dirname, &dir));
+ return dir;
+}
+
static void test_close(JournalFile *f) {
journal_file_close (f);
}
+static void test_close_dir(JournalDirectory *dir) {
+ journal_directory_unref(dir);
+}
+
static void append_number(JournalFile *f, int n, uint64_t *seqnum) {
char *p;
dual_timestamp ts;
@@ -115,39 +126,48 @@ static void test_check_numbers_up (sd_journal *j, int count) {
}
-static void setup_sequential(void) {
+static JournalDirectory* setup_sequential(void) {
JournalFile *one, *two;
- one = test_open("one.journal");
- two = test_open("two.journal");
+ JournalDirectory *dir;
+
+ dir = test_open_dir(".");
+ one = test_open(dir, "one.journal");
+ two = test_open(dir, "two.journal");
append_number(one, 1, NULL);
append_number(one, 2, NULL);
append_number(two, 3, NULL);
append_number(two, 4, NULL);
test_close(one);
test_close(two);
+ return dir;
}
-static void setup_interleaved(void) {
+static JournalDirectory* setup_interleaved(void) {
JournalFile *one, *two;
- one = test_open("one.journal");
- two = test_open("two.journal");
+ JournalDirectory *dir;
+
+ dir = test_open_dir(".");
+ one = test_open(dir, "one.journal");
+ two = test_open(dir, "two.journal");
append_number(one, 1, NULL);
append_number(two, 2, NULL);
append_number(one, 3, NULL);
append_number(two, 4, NULL);
test_close(one);
test_close(two);
+ return dir;
}
-static void test_skip(void (*setup)(void)) {
+static void test_skip(JournalDirectory* (*setup)(void)) {
char t[] = "/tmp/journal-skip-XXXXXX";
sd_journal *j;
int r;
+ JournalDirectory *dir;
assert_se(mkdtemp(t));
assert_se(chdir(t) >= 0);
- setup();
+ dir = setup();
/* Seek to head, iterate down.
*/
@@ -188,10 +208,11 @@ static void test_skip(void (*setup)(void)) {
if (arg_keep)
log_info("Not removing %s", t);
else {
- journal_directory_vacuum(".", 3000000, 0, NULL, true);
+ journal_directory_vacuum(dir, 3000000, 0, NULL, true);
assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}
+ test_close_dir(dir);
puts("------------------------------------------------------------");
}
@@ -200,14 +221,15 @@ static void test_sequence_numbers(void) {
char t[] = "/tmp/journal-seq-XXXXXX";
JournalFile *one, *two;
+ JournalDirectory *dir;
uint64_t seqnum = 0;
sd_id128_t seqnum_id;
assert_se(mkdtemp(t));
assert_se(chdir(t) >= 0);
- assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0644,
- true, false, NULL, NULL, NULL, &one) == 0);
+ dir = test_open_dir(".");
+ one = test_open(dir, "one.journal");
append_number(one, 1, &seqnum);
printf("seqnum=%"PRIu64"\n", seqnum);
@@ -223,7 +245,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(dir, "two.journal", O_RDWR|O_CREAT, 0644,
true, false, NULL, NULL, one, &two) == 0);
assert_se(two->header->state == STATE_ONLINE);
@@ -254,7 +276,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(dir, "two.journal", O_RDWR, 0,
true, false, NULL, NULL, NULL, &two) == 0);
assert_se(sd_id128_equal(two->header->seqnum_id, seqnum_id));
@@ -273,10 +295,11 @@ static void test_sequence_numbers(void) {
if (arg_keep)
log_info("Not removing %s", t);
else {
- journal_directory_vacuum(".", 3000000, 0, NULL, true);
+ journal_directory_vacuum(dir, 3000000, 0, NULL, true);
assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}
+ test_close_dir(dir);
}
int main(int argc, char *argv[]) {
diff --git a/src/journal/test-journal-stream.c b/src/journal/test-journal-stream.c
index e1146c6..ba5a0a8 100644
--- a/src/journal/test-journal-stream.c
+++ b/src/journal/test-journal-stream.c
@@ -74,6 +74,7 @@ static void verify_contents(sd_journal *j, unsigned skip) {
int main(int argc, char *argv[]) {
JournalFile *one, *two, *three;
+ JournalDirectory *dir;
char t[] = "/tmp/journal-stream-XXXXXX";
unsigned i;
_cleanup_journal_close_ sd_journal *j = NULL;
@@ -90,9 +91,12 @@ 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, &one) == 0);
- assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &two) == 0);
- assert_se(journal_file_open("three.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &three) == 0);
+ assert_se(journal_directory_open(".", &dir) == 0);
+
+ assert_se(journal_file_open(dir, "one.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &one) == 0);
+ assert_se(journal_file_open(dir, "two.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &two) == 0);
+ assert_se(journal_file_open(dir, "three.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &three) == 0);
+ dir = journal_directory_unref(dir);
for (i = 0; i < N_ENTRIES; i++) {
char *p, *q;
diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c
index d24502d..2160b8d 100644
--- a/src/journal/test-journal-verify.c
+++ b/src/journal/test-journal-verify.c
@@ -52,11 +52,11 @@ static void bit_toggle(const char *fn, uint64_t p) {
safe_close(fd);
}
-static int raw_verify(const char *fn, const char *verification_key) {
+static int raw_verify(JournalDirectory *dir, 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, &f);
+ r = journal_file_open(dir, fn, O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, &f);
if (r < 0)
return r;
@@ -70,6 +70,7 @@ int main(int argc, char *argv[]) {
char t[] = "/tmp/journal-XXXXXX";
unsigned n;
JournalFile *f;
+ JournalDirectory *dir;
const char *verification_key = argv[1];
usec_t from = 0, to = 0, total = 0;
char a[FORMAT_TIMESTAMP_MAX];
@@ -89,7 +90,8 @@ 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, &f) == 0);
+ assert_se(journal_directory_open(".", &dir) == 0);
+ assert_se(journal_file_open(dir, "test.journal", O_RDWR|O_CREAT, 0666, true, !!verification_key, NULL, NULL, NULL, &f) == 0);
for (n = 0; n < N_ENTRIES; n++) {
struct iovec iovec;
@@ -112,7 +114,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, &f) == 0);
+ assert_se(journal_file_open(dir, "test.journal", O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, &f) == 0);
/* journal_file_print_header(f); */
journal_file_dump(f);
@@ -137,7 +139,7 @@ int main(int argc, char *argv[]) {
log_info("[ %"PRIu64"+%"PRIu64"]", p / 8, p % 8);
- if (raw_verify("test.journal", verification_key) >= 0)
+ if (raw_verify(dir, "test.journal", verification_key) >= 0)
log_notice(ANSI_HIGHLIGHT_RED_ON ">>>> %"PRIu64" (bit %"PRIu64") can be toggled without detection." ANSI_HIGHLIGHT_OFF, p / 8, p % 8);
bit_toggle("test.journal", p);
@@ -145,6 +147,7 @@ int main(int argc, char *argv[]) {
}
log_info("Exiting...");
+ dir = journal_directory_unref(dir);
assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c
index caaab25..8e6d7bb 100644
--- a/src/journal/test-journal.c
+++ b/src/journal/test-journal.c
@@ -33,6 +33,7 @@ static bool arg_keep = false;
static void test_non_empty(void) {
dual_timestamp ts;
JournalFile *f;
+ JournalDirectory *dir;
struct iovec iovec;
static const char test[] = "TEST1=1", test2[] = "TEST2=2";
Object *o;
@@ -44,7 +45,8 @@ 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, &f) == 0);
+ assert_se(journal_directory_open(".", &dir) == 0);
+ assert_se(journal_file_open(dir, "test.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, &f) == 0);
dual_timestamp_get(&ts);
@@ -116,16 +118,18 @@ static void test_non_empty(void) {
if (arg_keep)
log_info("Not removing %s", t);
else {
- journal_directory_vacuum(".", 3000000, 0, NULL, true);
+ journal_directory_vacuum(dir, 3000000, 0, NULL, true);
assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}
+ dir = journal_directory_unref(dir);
puts("------------------------------------------------------------");
}
static void test_empty(void) {
JournalFile *f1, *f2, *f3, *f4;
+ JournalDirectory *dir;
char t[] = "/tmp/journal-XXXXXX";
log_set_max_level(LOG_DEBUG);
@@ -133,13 +137,15 @@ 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, &f1) == 0);
+ assert_se(journal_directory_open(".", &dir) == 0);
- assert_se(journal_file_open("test-compress.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &f2) == 0);
+ assert_se(journal_file_open(dir, "test.journal", O_RDWR|O_CREAT, 0666, false, false, NULL, NULL, NULL, &f1) == 0);
- assert_se(journal_file_open("test-seal.journal", O_RDWR|O_CREAT, 0666, false, true, NULL, NULL, NULL, &f3) == 0);
+ assert_se(journal_file_open(dir, "test-compress.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &f2) == 0);
- assert_se(journal_file_open("test-seal-compress.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, &f4) == 0);
+ assert_se(journal_file_open(dir, "test-seal.journal", O_RDWR|O_CREAT, 0666, false, true, NULL, NULL, NULL, &f3) == 0);
+
+ assert_se(journal_file_open(dir, "test-seal-compress.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, &f4) == 0);
journal_file_print_header(f1);
puts("");
@@ -155,7 +161,7 @@ static void test_empty(void) {
if (arg_keep)
log_info("Not removing %s", t);
else {
- journal_directory_vacuum(".", 3000000, 0, NULL, true);
+ journal_directory_vacuum(dir, 3000000, 0, NULL, true);
assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}
@@ -164,6 +170,7 @@ static void test_empty(void) {
journal_file_close(f2);
journal_file_close(f3);
journal_file_close(f4);
+ journal_directory_unref(dir);
}
int main(int argc, char *argv[]) {
diff --git a/src/shared/util.c b/src/shared/util.c
index 395af7c..e27d14e 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -1791,6 +1791,26 @@ int dir_is_empty(const char *path) {
}
}
+char* basename_malloc(const char *path) {
+ char *b, *base, *base2;
+
+ assert(path);
+
+ b = strdup(path);
+ if (!b)
+ return NULL;
+ base = basename(b);
+ assert(base);
+
+ if (base != b) {
+ base2 = strdup(base);
+ free(b);
+ return base2;
+ }
+
+ return base;
+}
+
char* dirname_malloc(const char *path) {
char *d, *dir, *dir2;
diff --git a/src/shared/util.h b/src/shared/util.h
index 1cfb45f..9b5d9af 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -339,6 +339,7 @@ int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll);
bool is_device_path(const char *path);
int dir_is_empty(const char *path);
+char* basename_malloc(const char *path);
char* dirname_malloc(const char *path);
char* lookup_uid(uid_t uid);
--
2.1.0
More information about the systemd-devel
mailing list