chiark / gitweb /
journal: add ability to filter by current user
[elogind.git] / src / journal / sd-journal.c
index 6d0f363faf267eff02e53a48d7ccc79c4799a074..46511df6be0dfc145ed98cd264b263c64a48d66c 100644 (file)
@@ -109,6 +109,9 @@ static void set_location(sd_journal *j, LocationType type, JournalFile *f, Objec
 
         init_location(&j->current_location, type, f, o);
 
+        if (j->current_file)
+                j->current_file->current_offset = 0;
+
         j->current_file = f;
         j->current_field = 0;
 
@@ -194,9 +197,7 @@ static void match_free(Match *m) {
 }
 
 static void match_free_if_empty(Match *m) {
-        assert(m);
-
-        if (m->matches)
+        if (!m || m->matches)
                 return;
 
         match_free(m);
@@ -293,17 +294,10 @@ _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size)
         return 0;
 
 fail:
-        if (add_here)
-                match_free_if_empty(add_here);
-
-        if (j->level2)
-                match_free_if_empty(j->level2);
-
-        if (j->level1)
-                match_free_if_empty(j->level1);
-
-        if (j->level0)
-                match_free_if_empty(j->level0);
+        match_free_if_empty(add_here);
+        match_free_if_empty(j->level2);
+        match_free_if_empty(j->level1);
+        match_free_if_empty(j->level0);
 
         return -ENOMEM;
 }
@@ -412,7 +406,7 @@ _public_ void sd_journal_flush_matches(sd_journal *j) {
 }
 
 static int compare_entry_order(JournalFile *af, Object *_ao,
-                         JournalFile *bf, uint64_t bp) {
+                               JournalFile *bf, uint64_t bp) {
 
         uint64_t a, b;
         Object *ao, *bo;
@@ -495,7 +489,7 @@ static int compare_entry_order(JournalFile *af, Object *_ao,
         return 0;
 }
 
-static int compare_with_location(JournalFile *af, Object *ao, Location *l) {
+_pure_ static int compare_with_location(JournalFile *af, Object *ao, Location *l) {
         uint64_t a;
 
         assert(af);
@@ -1248,15 +1242,51 @@ static void check_network(sd_journal *j, int fd) {
                 return;
 
         j->on_network =
-                (unsigned long) sfs.f_type == CIFS_MAGIC_NUMBER ||
-                (unsigned long) sfs.f_type == CODA_SUPER_MAGIC ||
-                (unsigned long) sfs.f_type == NCP_SUPER_MAGIC ||
-                (unsigned long) sfs.f_type == NFS_SUPER_MAGIC ||
-                (unsigned long) sfs.f_type == SMB_SUPER_MAGIC;
+                F_TYPE_CMP(sfs.f_type, CIFS_MAGIC_NUMBER) ||
+                F_TYPE_CMP(sfs.f_type, CODA_SUPER_MAGIC) ||
+                F_TYPE_CMP(sfs.f_type, NCP_SUPER_MAGIC) ||
+                F_TYPE_CMP(sfs.f_type, NFS_SUPER_MAGIC) ||
+                F_TYPE_CMP(sfs.f_type, SMB_SUPER_MAGIC);
+}
+
+static bool file_has_type_prefix(const char *prefix, const char *filename) {
+        const char *full, *tilded, *atted;
+
+        full = strappend(prefix, ".journal");
+        tilded = strappenda(full, "~");
+        atted = strappenda(prefix, "@");
+
+        return streq(filename, full) ||
+               streq(filename, tilded) ||
+               startswith(filename, atted);
+}
+
+static bool file_type_wanted(int flags, const char *filename) {
+        if (!endswith(filename, ".journal") && !endswith(filename, ".journal~"))
+                return false;
+
+        /* no flags set → every type is OK */
+        if (!(flags & (SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER)))
+                return true;
+
+        if (flags & SD_JOURNAL_SYSTEM && file_has_type_prefix("system", filename))
+                return true;
+
+        if (flags & SD_JOURNAL_CURRENT_USER) {
+                char prefix[5 + DECIMAL_STR_MAX(uid_t) + 1];
+
+                assert_se(snprintf(prefix, sizeof(prefix), "user-%lu", (unsigned long) getuid())
+                          < (int) sizeof(prefix));
+
+                if (file_has_type_prefix(prefix, filename))
+                        return true;
+        }
+
+        return false;
 }
 
 static int add_file(sd_journal *j, const char *prefix, const char *filename) {
-        char _cleanup_free_ *path = NULL;
+        _cleanup_free_ char *path = NULL;
         int r;
         JournalFile *f;
 
@@ -1264,11 +1294,7 @@ static int add_file(sd_journal *j, const char *prefix, const char *filename) {
         assert(prefix);
         assert(filename);
 
-        if ((j->flags & SD_JOURNAL_SYSTEM_ONLY) &&
-            !(streq(filename, "system.journal") ||
-              streq(filename, "system.journal~") ||
-              (startswith(filename, "system@") &&
-               (endswith(filename, ".journal") || endswith(filename, ".journal~")))))
+        if (!file_type_wanted(j->flags, filename))
                 return 0;
 
         path = strjoin(prefix, "/", filename, NULL);
@@ -1299,7 +1325,7 @@ static int add_file(sd_journal *j, const char *prefix, const char *filename) {
                 return r;
         }
 
-        log_debug("File %s got added.", f->path);
+        log_debug("File %s added.", f->path);
 
         check_network(j, f->fd);
 
@@ -1327,7 +1353,7 @@ static int remove_file(sd_journal *j, const char *prefix, const char *filename)
 
         hashmap_remove(j->files, f->path);
 
-        log_debug("File %s got removed.", f->path);
+        log_debug("File %s removed.", f->path);
 
         if (j->current_file == f) {
                 j->current_file = NULL;
@@ -1347,9 +1373,9 @@ static int remove_file(sd_journal *j, const char *prefix, const char *filename)
 }
 
 static int add_directory(sd_journal *j, const char *prefix, const char *dirname) {
-        char _cleanup_free_ *path = NULL;
+        _cleanup_free_ char *path = NULL;
         int r;
-        DIR _cleanup_closedir_ *d = NULL;
+        _cleanup_closedir_ DIR *d = NULL;
         sd_id128_t id, mid;
         Directory *m;
 
@@ -1394,7 +1420,7 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
                 path = NULL; /* avoid freeing in cleanup */
                 j->current_invalidate_counter ++;
 
-                log_debug("Directory %s got added.", m->path);
+                log_debug("Directory %s added.", m->path);
 
         } else if (m->is_root)
                 return 0;
@@ -1437,7 +1463,7 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
 }
 
 static int add_root_directory(sd_journal *j, const char *p) {
-        DIR _cleanup_closedir_ *d = NULL;
+        _cleanup_closedir_ DIR *d = NULL;
         Directory *m;
         int r;
 
@@ -1473,7 +1499,7 @@ static int add_root_directory(sd_journal *j, const char *p) {
 
                 j->current_invalidate_counter ++;
 
-                log_debug("Root directory %s got added.", m->path);
+                log_debug("Root directory %s added.", m->path);
 
         } else if (!m->is_root)
                 return 0;
@@ -1534,9 +1560,9 @@ static int remove_directory(sd_journal *j, Directory *d) {
         hashmap_remove(j->directories_by_path, d->path);
 
         if (d->is_root)
-                log_debug("Root directory %s got removed.", d->path);
+                log_debug("Root directory %s removed.", d->path);
         else
-                log_debug("Directory %s got removed.", d->path);
+                log_debug("Directory %s removed.", d->path);
 
         free(d->path);
         free(d);
@@ -1625,7 +1651,8 @@ _public_ int sd_journal_open(sd_journal **ret, int flags) {
 
         if (flags & ~(SD_JOURNAL_LOCAL_ONLY|
                       SD_JOURNAL_RUNTIME_ONLY|
-                      SD_JOURNAL_SYSTEM_ONLY))
+                      SD_JOURNAL_SYSTEM|
+                      SD_JOURNAL_CURRENT_USER))
                 return -EINVAL;
 
         j = journal_new(flags, NULL);
@@ -2214,6 +2241,8 @@ _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from,
                 return -EINVAL;
         if (!from && !to)
                 return -EINVAL;
+        if (from == to)
+                return -EINVAL;
 
         HASHMAP_FOREACH(f, j->files, i) {
                 usec_t fr, t;
@@ -2253,6 +2282,8 @@ _public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot
                 return -EINVAL;
         if (!from && !to)
                 return -EINVAL;
+        if (from == to)
+                return -EINVAL;
 
         HASHMAP_FOREACH(f, j->files, i) {
                 usec_t fr, t;